byebug 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.travis.yml +0 -5
- data/CHANGELOG.md +6 -0
- data/Gemfile +1 -1
- data/LICENSE +23 -20
- data/byebug.gemspec +5 -5
- data/ext/byebug/breakpoint.c +102 -134
- data/ext/byebug/byebug.c +110 -64
- data/ext/byebug/byebug.h +2 -3
- data/ext/byebug/context.c +72 -39
- data/lib/byebug.rb +34 -38
- data/lib/byebug/command.rb +19 -24
- data/lib/byebug/commands/breakpoints.rb +11 -12
- data/lib/byebug/commands/catchpoint.rb +1 -1
- data/lib/byebug/commands/control.rb +2 -4
- data/lib/byebug/commands/finish.rb +1 -1
- data/lib/byebug/commands/frame.rb +15 -17
- data/lib/byebug/commands/info.rb +29 -28
- data/lib/byebug/commands/irb.rb +23 -21
- data/lib/byebug/commands/method.rb +4 -4
- data/lib/byebug/commands/reload.rb +8 -6
- data/lib/byebug/commands/set.rb +27 -23
- data/lib/byebug/commands/show.rb +6 -4
- data/lib/byebug/commands/stepping.rb +2 -2
- data/lib/byebug/commands/threads.rb +10 -10
- data/lib/byebug/commands/trace.rb +13 -14
- data/lib/byebug/commands/variables.rb +14 -12
- data/lib/byebug/context.rb +2 -15
- data/lib/byebug/interface.rb +5 -0
- data/lib/byebug/processor.rb +59 -64
- data/lib/byebug/version.rb +2 -1
- data/old_doc/Makefile +20 -0
- data/{man/rdebug.1 → old_doc/byebug.1} +5 -5
- data/old_doc/byebug.html +6178 -0
- data/old_doc/byebug.texi +3775 -0
- data/{doc → old_doc}/hanoi.rb +0 -0
- data/{doc → old_doc}/primes.rb +0 -0
- data/{doc → old_doc}/test-tri2.rb +0 -0
- data/{doc → old_doc}/tri3.rb +0 -0
- data/{doc → old_doc}/triangle.rb +0 -0
- data/test/breakpoints_test.rb +96 -60
- data/test/conditions_test.rb +15 -12
- data/test/examples/info.rb +5 -5
- data/test/examples/stepping.rb +1 -1
- data/test/frame_test.rb +40 -39
- data/test/info_test.rb +105 -96
- data/test/irb_test.rb +66 -61
- data/test/jump_test.rb +18 -9
- data/test/list_test.rb +114 -107
- data/test/restart_test.rb +51 -58
- data/test/save_test.rb +8 -7
- data/test/set_test.rb +8 -11
- data/test/show_test.rb +3 -5
- data/test/stepping_test.rb +43 -53
- data/test/support/context.rb +1 -0
- data/test/support/processor.rb +10 -4
- data/test/support/test_dsl.rb +46 -18
- data/test/support/test_interface.rb +8 -5
- data/test/test_helper.rb +2 -2
- data/test/trace_test.rb +123 -124
- metadata +39 -17
- data/AUTHORS +0 -10
- data/doc/rdebug-emacs.texi +0 -1030
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
-
Copyright (
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
1
|
+
Copyright (C) 2013 David Rodríguez <deivid.rodriguez@gmail.com>
|
2
|
+
All rights reserved.
|
3
|
+
*
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
*
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
15
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
16
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
17
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
18
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
19
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
20
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
21
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
22
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
23
|
+
SUCH DAMAGE.
|
data/byebug.gemspec
CHANGED
@@ -5,7 +5,7 @@ require File.dirname(__FILE__) + "/lib/byebug/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{byebug}
|
7
7
|
s.version = Byebug::VERSION
|
8
|
-
s.authors = ["David Rodríguez"]
|
8
|
+
s.authors = ["David Rodríguez", "Kent Sibilev", "Mark Moseley"]
|
9
9
|
s.email = "deivid.rodriguez@mail.com"
|
10
10
|
s.homepage = "http://github.com/deivid-rodriguez/byebug"
|
11
11
|
s.summary = %q{Ruby 2.0 fast debugger - base + cli}
|
@@ -13,17 +13,17 @@ Gem::Specification.new do |s|
|
|
13
13
|
Ruby 2.0 TracePoint C API. The C extension was forked from debase whereas
|
14
14
|
the rest of the gem was forked from debugger. The core component provides
|
15
15
|
support that front-ends can build on. It provides breakpoint handling,
|
16
|
-
bindings for stack frames among other things.
|
17
|
-
}
|
16
|
+
bindings for stack frames among other things.}
|
18
17
|
s.required_rubygems_version = ">= 1.3.6"
|
19
18
|
s.extra_rdoc_files = [ "README.md" ]
|
20
19
|
s.files = `git ls-files`.split("\n")
|
21
20
|
s.extensions << "ext/byebug/extconf.rb"
|
22
21
|
s.executables = ["byebug"]
|
23
|
-
s.add_dependency "columnize", "
|
22
|
+
s.add_dependency "columnize", "~> 0.3.6"
|
24
23
|
s.add_dependency "debugger-linecache", '~> 1.2.0'
|
25
24
|
s.add_development_dependency 'rake', '~> 10.0.3'
|
26
25
|
s.add_development_dependency 'rake-compiler', '~> 0.8.3'
|
27
26
|
s.add_development_dependency 'mocha', '~> 0.13.3'
|
28
|
-
s.
|
27
|
+
s.add_development_dependency 'minitest', '~> 4.7.0'
|
28
|
+
s.license = "BSD"
|
29
29
|
end
|
data/ext/byebug/breakpoint.c
CHANGED
@@ -21,34 +21,6 @@ eval_expression(VALUE args)
|
|
21
21
|
return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args));
|
22
22
|
}
|
23
23
|
|
24
|
-
extern VALUE
|
25
|
-
catchpoint_hit_count(VALUE catchpoints, VALUE exception, VALUE *exception_name)
|
26
|
-
{
|
27
|
-
VALUE ancestors;
|
28
|
-
VALUE expn_class;
|
29
|
-
VALUE aclass;
|
30
|
-
VALUE mod_name;
|
31
|
-
VALUE hit_count;
|
32
|
-
int i;
|
33
|
-
|
34
|
-
if (catchpoints == Qnil /*|| st_get_num_entries(RHASH_TBL(rdebug_catchpoints)) == 0)*/)
|
35
|
-
return Qnil;
|
36
|
-
expn_class = rb_obj_class(exception);
|
37
|
-
ancestors = rb_mod_ancestors(expn_class);
|
38
|
-
for(i = 0; i < RARRAY_LEN(ancestors); i++)
|
39
|
-
{
|
40
|
-
aclass = rb_ary_entry(ancestors, i);
|
41
|
-
mod_name = rb_mod_name(aclass);
|
42
|
-
hit_count = rb_hash_aref(catchpoints, mod_name);
|
43
|
-
if(hit_count != Qnil)
|
44
|
-
{
|
45
|
-
*exception_name = mod_name;
|
46
|
-
return hit_count;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
return Qnil;
|
50
|
-
}
|
51
|
-
|
52
24
|
static VALUE
|
53
25
|
Breakpoint_hit_count(VALUE self)
|
54
26
|
{
|
@@ -81,41 +53,41 @@ Breakpoint_set_hit_value(VALUE self, VALUE value)
|
|
81
53
|
static VALUE
|
82
54
|
Breakpoint_hit_condition(VALUE self)
|
83
55
|
{
|
84
|
-
|
56
|
+
breakpoint_t *breakpoint;
|
85
57
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
58
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
59
|
+
switch(breakpoint->hit_condition)
|
60
|
+
{
|
61
|
+
case HIT_COND_GE:
|
62
|
+
return ID2SYM(rb_intern("greater_or_equal"));
|
63
|
+
case HIT_COND_EQ:
|
64
|
+
return ID2SYM(rb_intern("equal"));
|
65
|
+
case HIT_COND_MOD:
|
66
|
+
return ID2SYM(rb_intern("modulo"));
|
67
|
+
case HIT_COND_NONE:
|
68
|
+
default:
|
69
|
+
return Qnil;
|
70
|
+
}
|
99
71
|
}
|
100
72
|
|
101
73
|
static VALUE
|
102
74
|
Breakpoint_set_hit_condition(VALUE self, VALUE value)
|
103
75
|
{
|
104
|
-
|
105
|
-
|
76
|
+
breakpoint_t *breakpoint;
|
77
|
+
ID id_value;
|
106
78
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
79
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
80
|
+
id_value = rb_to_id(value);
|
81
|
+
|
82
|
+
if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
|
83
|
+
breakpoint->hit_condition = HIT_COND_GE;
|
84
|
+
else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
|
85
|
+
breakpoint->hit_condition = HIT_COND_EQ;
|
86
|
+
else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
|
87
|
+
breakpoint->hit_condition = HIT_COND_MOD;
|
88
|
+
else
|
89
|
+
rb_raise(rb_eArgError, "Invalid condition parameter");
|
90
|
+
return value;
|
119
91
|
}
|
120
92
|
|
121
93
|
static void
|
@@ -153,6 +125,7 @@ Breakpoint_initialize(VALUE self, VALUE source, VALUE pos, VALUE expr)
|
|
153
125
|
breakpoint->expr = NIL_P(expr) ? expr : StringValue(expr);
|
154
126
|
breakpoint->hit_count = 0;
|
155
127
|
breakpoint->hit_value = 0;
|
128
|
+
breakpoint->hit_condition = HIT_COND_NONE;
|
156
129
|
|
157
130
|
return Qnil;
|
158
131
|
}
|
@@ -302,47 +275,45 @@ filename_cmp(VALUE source, char *file)
|
|
302
275
|
#endif
|
303
276
|
}
|
304
277
|
|
305
|
-
/* XXX: Activate */
|
306
|
-
/*
|
307
278
|
static int
|
308
|
-
|
279
|
+
check_breakpoint_by_hit_condition(VALUE breakpoint_object)
|
309
280
|
{
|
310
|
-
|
281
|
+
breakpoint_t *breakpoint;
|
311
282
|
|
312
|
-
|
313
|
-
|
283
|
+
if (breakpoint_object == Qnil)
|
284
|
+
return 0;
|
285
|
+
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
314
286
|
|
315
|
-
|
316
|
-
breakpoint->hit_count++;
|
287
|
+
breakpoint->hit_count++;
|
317
288
|
|
318
|
-
|
319
|
-
|
320
|
-
|
289
|
+
if (Qtrue != breakpoint->enabled)
|
290
|
+
return 0;
|
291
|
+
|
292
|
+
switch (breakpoint->hit_condition)
|
293
|
+
{
|
294
|
+
case HIT_COND_NONE:
|
295
|
+
return 1;
|
296
|
+
case HIT_COND_GE:
|
321
297
|
{
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
{
|
326
|
-
if (breakpoint->hit_count >= breakpoint->hit_value)
|
327
|
-
return 1;
|
328
|
-
break;
|
329
|
-
}
|
330
|
-
case HIT_COND_EQ:
|
331
|
-
{
|
332
|
-
if (breakpoint->hit_count == breakpoint->hit_value)
|
333
|
-
return 1;
|
334
|
-
break;
|
335
|
-
}
|
336
|
-
case HIT_COND_MOD:
|
337
|
-
{
|
338
|
-
if (breakpoint->hit_count % breakpoint->hit_value == 0)
|
339
|
-
return 1;
|
340
|
-
break;
|
341
|
-
}
|
298
|
+
if (breakpoint->hit_count >= breakpoint->hit_value)
|
299
|
+
return 1;
|
300
|
+
break;
|
342
301
|
}
|
343
|
-
|
302
|
+
case HIT_COND_EQ:
|
303
|
+
{
|
304
|
+
if (breakpoint->hit_count == breakpoint->hit_value)
|
305
|
+
return 1;
|
306
|
+
break;
|
307
|
+
}
|
308
|
+
case HIT_COND_MOD:
|
309
|
+
{
|
310
|
+
if (breakpoint->hit_count % breakpoint->hit_value == 0)
|
311
|
+
return 1;
|
312
|
+
break;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
return 0;
|
344
316
|
}
|
345
|
-
*/
|
346
317
|
|
347
318
|
static int
|
348
319
|
check_breakpoint_by_pos(VALUE breakpoint_object, char *file, int line)
|
@@ -352,6 +323,7 @@ check_breakpoint_by_pos(VALUE breakpoint_object, char *file, int line)
|
|
352
323
|
if(breakpoint_object == Qnil)
|
353
324
|
return 0;
|
354
325
|
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
326
|
+
|
355
327
|
if (Qtrue != breakpoint->enabled)
|
356
328
|
return 0;
|
357
329
|
if(breakpoint->type != BP_POS_TYPE)
|
@@ -367,48 +339,43 @@ static int
|
|
367
339
|
check_breakpoint_by_method(VALUE breakpoint_object, VALUE klass, ID mid,
|
368
340
|
VALUE self)
|
369
341
|
{
|
370
|
-
|
342
|
+
breakpoint_t *breakpoint;
|
371
343
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
if (classname_cmp(breakpoint->source, klass))
|
382
|
-
return 1;
|
383
|
-
if ((rb_type(self) == T_CLASS) &&
|
384
|
-
classname_cmp(breakpoint->source, self))
|
385
|
-
return 1;
|
344
|
+
if (breakpoint_object == Qnil)
|
345
|
+
return 0;
|
346
|
+
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
347
|
+
|
348
|
+
if (!Qtrue == breakpoint->enabled)
|
349
|
+
return 0;
|
350
|
+
if (breakpoint->type != BP_METHOD_TYPE)
|
351
|
+
return 0;
|
352
|
+
if (breakpoint->pos.mid != mid)
|
386
353
|
return 0;
|
354
|
+
if (classname_cmp(breakpoint->source, klass))
|
355
|
+
return 1;
|
356
|
+
if ((rb_type(self) == T_CLASS) && classname_cmp(breakpoint->source, self))
|
357
|
+
return 1;
|
358
|
+
return 0;
|
387
359
|
}
|
388
360
|
|
389
361
|
static int
|
390
362
|
check_breakpoint_by_expr(VALUE breakpoint_object, VALUE binding)
|
391
363
|
{
|
392
|
-
|
393
|
-
|
364
|
+
breakpoint_t *breakpoint;
|
365
|
+
VALUE args, expr_result;
|
394
366
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
if (Qtrue != breakpoint->enabled)
|
399
|
-
return 0;
|
400
|
-
if (NIL_P(breakpoint->expr))
|
401
|
-
return 1;
|
402
|
-
args = rb_ary_new3(2, breakpoint->expr, binding);
|
403
|
-
expr_result = rb_protect(eval_expression, args, 0);
|
404
|
-
return RTEST(expr_result);
|
405
|
-
}
|
367
|
+
if (breakpoint_object == Qnil)
|
368
|
+
return 0;
|
369
|
+
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
406
370
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
371
|
+
if (Qtrue != breakpoint->enabled)
|
372
|
+
return 0;
|
373
|
+
if (NIL_P(breakpoint->expr))
|
374
|
+
return 1;
|
375
|
+
args = rb_ary_new3(2, breakpoint->expr, binding);
|
376
|
+
expr_result = rb_protect(eval_expression, args, 0);
|
377
|
+
return RTEST(expr_result);
|
378
|
+
}
|
412
379
|
|
413
380
|
extern VALUE
|
414
381
|
find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
|
@@ -425,7 +392,8 @@ find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
|
|
425
392
|
{
|
426
393
|
breakpoint_object = rb_ary_entry(breakpoints, i);
|
427
394
|
if ( check_breakpoint_by_pos(breakpoint_object, file, line) &&
|
428
|
-
check_breakpoint_by_expr(breakpoint_object, binding)
|
395
|
+
check_breakpoint_by_expr(breakpoint_object, binding) &&
|
396
|
+
check_breakpoint_by_hit_condition(breakpoint_object) )
|
429
397
|
{
|
430
398
|
return breakpoint_object;
|
431
399
|
}
|
@@ -437,17 +405,18 @@ extern VALUE
|
|
437
405
|
find_breakpoint_by_method(VALUE breakpoints, VALUE klass, ID mid, VALUE binding,
|
438
406
|
VALUE self)
|
439
407
|
{
|
440
|
-
|
441
|
-
|
408
|
+
VALUE breakpoint_object;
|
409
|
+
int i;
|
442
410
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
411
|
+
for(i = 0; i < RARRAY_LEN(breakpoints); i++)
|
412
|
+
{
|
413
|
+
breakpoint_object = rb_ary_entry(breakpoints, i);
|
414
|
+
if ( check_breakpoint_by_method(breakpoint_object, klass, mid, self) &&
|
415
|
+
check_breakpoint_by_expr(breakpoint_object, binding) &&
|
416
|
+
check_breakpoint_by_hit_condition(breakpoint_object) )
|
417
|
+
return breakpoint_object;
|
418
|
+
}
|
419
|
+
return Qnil;
|
451
420
|
}
|
452
421
|
|
453
422
|
extern void
|
@@ -455,7 +424,6 @@ Init_breakpoint(VALUE mByebug)
|
|
455
424
|
{
|
456
425
|
breakpoint_max = 0;
|
457
426
|
cBreakpoint = rb_define_class_under(mByebug, "Breakpoint", rb_cObject);
|
458
|
-
/* rb_define_singleton_method(cBreakpoint, "find", Breakpoint_find, 4); */
|
459
427
|
rb_define_singleton_method(cBreakpoint, "remove", Breakpoint_remove, 2);
|
460
428
|
rb_define_method(cBreakpoint, "initialize", Breakpoint_initialize, 3);
|
461
429
|
rb_define_method(cBreakpoint, "id", Breakpoint_id, 0);
|
data/ext/byebug/byebug.c
CHANGED
@@ -4,8 +4,10 @@ static VALUE mByebug; /* Ruby Byebug Module object */
|
|
4
4
|
static VALUE cContext;
|
5
5
|
static VALUE cDebugThread;
|
6
6
|
|
7
|
-
static VALUE
|
8
|
-
static VALUE
|
7
|
+
static VALUE tracing = Qfalse;
|
8
|
+
static VALUE debug = Qfalse;
|
9
|
+
static VALUE locker = Qnil;
|
10
|
+
|
9
11
|
static VALUE contexts;
|
10
12
|
static VALUE catchpoints;
|
11
13
|
static VALUE breakpoints;
|
@@ -16,10 +18,6 @@ static VALUE tpReturn;
|
|
16
18
|
static VALUE tpRaise;
|
17
19
|
|
18
20
|
static VALUE idAlive;
|
19
|
-
static VALUE idAtBreakpoint;
|
20
|
-
static VALUE idAtCatchpoint;
|
21
|
-
static VALUE idAtLine;
|
22
|
-
static VALUE idAtTracing;
|
23
21
|
|
24
22
|
static void
|
25
23
|
print_debug_info(char *event, VALUE path, VALUE lineno, VALUE method_id,
|
@@ -87,9 +85,7 @@ check_start_processing(debug_context_t *context, VALUE thread)
|
|
87
85
|
|
88
86
|
while(1)
|
89
87
|
{
|
90
|
-
/* halt execution of the current thread if
|
91
|
-
is activated in another
|
92
|
-
*/
|
88
|
+
/* halt execution of the current thread if byebug is activated in another */
|
93
89
|
while(locker != Qnil && locker != thread)
|
94
90
|
{
|
95
91
|
add_to_locked(thread);
|
@@ -140,11 +136,11 @@ static void
|
|
140
136
|
call_at_line(debug_context_t *context, char *file, int line,
|
141
137
|
VALUE context_object, VALUE path, VALUE lineno)
|
142
138
|
{
|
143
|
-
CTX_FL_UNSET(context,
|
139
|
+
CTX_FL_UNSET(context, CTX_FL_ENABLE_BKPT);
|
144
140
|
CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
|
145
141
|
context->last_file = file;
|
146
142
|
context->last_line = line;
|
147
|
-
rb_funcall(context_object,
|
143
|
+
rb_funcall(context_object, rb_intern("at_line"), 2, path, lineno);
|
148
144
|
}
|
149
145
|
|
150
146
|
static void
|
@@ -154,56 +150,62 @@ process_line_event(VALUE trace_point, void *data)
|
|
154
150
|
VALUE context_object;
|
155
151
|
VALUE breakpoint;
|
156
152
|
debug_context_t *context;
|
157
|
-
int moved;
|
153
|
+
int moved = 0;
|
158
154
|
|
159
155
|
context_object = Byebug_current_context(mByebug);
|
160
156
|
Data_Get_Struct(context_object, debug_context_t, context);
|
161
157
|
if (!check_start_processing(context, rb_thread_current())) return;
|
162
158
|
|
163
|
-
load_frame_info(
|
164
|
-
|
159
|
+
load_frame_info(
|
160
|
+
trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
|
165
161
|
if (debug == Qtrue)
|
166
|
-
print_debug_info(
|
167
|
-
|
162
|
+
print_debug_info(
|
163
|
+
"line", path, lineno, method_id, defined_class, context->stack_size);
|
168
164
|
|
169
165
|
update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
|
170
166
|
defined_class, binding, self);
|
171
167
|
|
172
|
-
|
173
|
-
|
168
|
+
if (context->last_line != FIX2INT(lineno) || context->last_file == NULL ||
|
169
|
+
strcmp(context->last_file, RSTRING_PTR(path)))
|
170
|
+
{
|
171
|
+
CTX_FL_SET(context, CTX_FL_ENABLE_BKPT);
|
172
|
+
moved = 1;
|
173
|
+
}
|
174
174
|
|
175
|
-
if (
|
176
|
-
rb_funcall(context_object,
|
175
|
+
if (RTEST(tracing))
|
176
|
+
rb_funcall(context_object, rb_intern("at_tracing"), 2, path, lineno);
|
177
177
|
|
178
178
|
if (context->dest_frame == -1 || context->stack_size == context->dest_frame)
|
179
179
|
{
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
if (moved || (CTX_FL_TEST(context, CTX_FL_STEPPED) && !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)))
|
185
|
-
{
|
186
|
-
context->stop_line--;
|
187
|
-
CTX_FL_UNSET(context, CTX_FL_STEPPED);
|
188
|
-
}
|
180
|
+
if (moved || !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)) {
|
181
|
+
context->stop_next = context->stop_next <= 0 ? -1 : context->stop_next-1;
|
182
|
+
context->stop_line = context->stop_line <= 0 ? -1 : context->stop_line-1;
|
183
|
+
}
|
189
184
|
}
|
190
185
|
else if (context->stack_size < context->dest_frame)
|
191
186
|
{
|
192
187
|
context->stop_next = 0;
|
193
188
|
}
|
194
189
|
|
195
|
-
|
196
|
-
if (context->stop_next == 0 || context->stop_line == 0 ||
|
197
|
-
breakpoint != Qnil)
|
190
|
+
if (context->stop_next == 0 || context->stop_line == 0)
|
198
191
|
{
|
199
192
|
context->stop_reason = CTX_STOP_STEP;
|
193
|
+
reset_stepping_stop_points(context);
|
194
|
+
call_at_line(
|
195
|
+
context, RSTRING_PTR(path), FIX2INT(lineno), context_object, path, lineno);
|
196
|
+
}
|
197
|
+
else if (CTX_FL_TEST(context, CTX_FL_ENABLE_BKPT))
|
198
|
+
{
|
199
|
+
breakpoint = find_breakpoint_by_pos(breakpoints, path, lineno, binding);
|
200
200
|
if (breakpoint != Qnil) {
|
201
|
-
|
201
|
+
context->stop_reason = CTX_STOP_BREAKPOINT;
|
202
|
+
reset_stepping_stop_points(context);
|
203
|
+
rb_funcall(context_object, rb_intern("at_breakpoint"), 1, breakpoint);
|
204
|
+
call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
|
205
|
+
path, lineno);
|
202
206
|
}
|
203
|
-
reset_stepping_stop_points(context);
|
204
|
-
call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
|
205
|
-
path, lineno);
|
206
207
|
}
|
208
|
+
|
207
209
|
cleanup(context);
|
208
210
|
}
|
209
211
|
|
@@ -218,7 +220,7 @@ process_return_event(VALUE trace_point, void *data)
|
|
218
220
|
Data_Get_Struct(context_object, debug_context_t, context);
|
219
221
|
if (!check_start_processing(context, rb_thread_current())) return;
|
220
222
|
|
221
|
-
if(context->stack_size == context->stop_frame)
|
223
|
+
if (context->stack_size == context->stop_frame)
|
222
224
|
{
|
223
225
|
context->stop_next = 1;
|
224
226
|
context->stop_frame = 0;
|
@@ -230,9 +232,9 @@ process_return_event(VALUE trace_point, void *data)
|
|
230
232
|
print_debug_info("return", path, lineno, method_id, defined_class,
|
231
233
|
context->stack_size);
|
232
234
|
|
233
|
-
//
|
234
|
-
|
235
|
+
//rb_funcall(context_object, idAtReturn, 2, path, lineno);
|
235
236
|
pop_frame(context_object);
|
237
|
+
|
236
238
|
cleanup(context);
|
237
239
|
}
|
238
240
|
|
@@ -262,7 +264,7 @@ process_call_event(VALUE trace_point, void *data)
|
|
262
264
|
binding, self);
|
263
265
|
if (breakpoint != Qnil) {
|
264
266
|
context->stop_reason = CTX_STOP_BREAKPOINT;
|
265
|
-
rb_funcall(context_object,
|
267
|
+
rb_funcall(context_object, rb_intern("at_breakpoint"), 1, breakpoint);
|
266
268
|
call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
|
267
269
|
path, lineno);
|
268
270
|
}
|
@@ -275,10 +277,11 @@ process_raise_event(VALUE trace_point, void *data)
|
|
275
277
|
{
|
276
278
|
VALUE path, lineno, method_id, defined_class, binding, self;
|
277
279
|
VALUE context_object;
|
278
|
-
VALUE
|
279
|
-
VALUE
|
280
|
+
VALUE expn_class, aclass;
|
281
|
+
VALUE err = rb_errinfo();
|
282
|
+
VALUE ancestors;
|
280
283
|
debug_context_t *context;
|
281
|
-
int
|
284
|
+
int i;
|
282
285
|
|
283
286
|
context_object = Byebug_current_context(mByebug);
|
284
287
|
Data_Get_Struct(context_object, debug_context_t, context);
|
@@ -289,28 +292,47 @@ process_raise_event(VALUE trace_point, void *data)
|
|
289
292
|
update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
|
290
293
|
defined_class, binding, self);
|
291
294
|
|
292
|
-
if (
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
295
|
+
if (debug == Qtrue)
|
296
|
+
print_debug_info("call", path, lineno, method_id, defined_class,
|
297
|
+
context->stack_size);
|
298
|
+
expn_class = rb_obj_class(err);
|
299
|
+
|
300
|
+
if (catchpoints == Qnil ||
|
301
|
+
context->stack_size == 0 ||
|
302
|
+
CTX_FL_TEST(context, CTX_FL_CATCHING) ||
|
303
|
+
RHASH_TBL(catchpoints)->num_entries == 0) {
|
304
|
+
cleanup(context);
|
305
|
+
return;
|
306
|
+
}
|
307
|
+
|
308
|
+
ancestors = rb_mod_ancestors(expn_class);
|
309
|
+
for (i = 0; i < RARRAY_LEN(ancestors); i++) {
|
310
|
+
VALUE mod_name;
|
311
|
+
VALUE hit_count;
|
312
|
+
|
313
|
+
aclass = rb_ary_entry(ancestors, i);
|
314
|
+
mod_name = rb_mod_name(aclass);
|
315
|
+
hit_count = rb_hash_aref(catchpoints, mod_name);
|
316
|
+
|
317
|
+
if (hit_count != Qnil) {
|
318
|
+
/* increment exception */
|
319
|
+
rb_hash_aset(catchpoints, mod_name, INT2FIX(FIX2INT(hit_count) + 1));
|
320
|
+
context->stop_reason = CTX_STOP_CATCHPOINT;
|
321
|
+
rb_funcall(context_object, rb_intern("at_catchpoint"), 1, rb_errinfo());
|
322
|
+
call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
|
323
|
+
path, lineno);
|
324
|
+
break;
|
325
|
+
}
|
304
326
|
}
|
305
327
|
|
306
328
|
cleanup(context);
|
307
329
|
}
|
308
330
|
|
309
|
-
|
310
331
|
static VALUE
|
311
332
|
Byebug_setup_tracepoints(VALUE self)
|
312
333
|
{
|
313
334
|
if (catchpoints != Qnil) return Qnil;
|
335
|
+
|
314
336
|
contexts = rb_hash_new();
|
315
337
|
breakpoints = rb_ary_new();
|
316
338
|
catchpoints = rb_hash_new();
|
@@ -436,7 +458,18 @@ Byebug_load(int argc, VALUE *argv, VALUE self)
|
|
436
458
|
return Qnil;
|
437
459
|
}
|
438
460
|
|
461
|
+
static VALUE
|
462
|
+
Byebug_tracing(VALUE self)
|
463
|
+
{
|
464
|
+
return tracing;
|
465
|
+
}
|
439
466
|
|
467
|
+
static VALUE
|
468
|
+
Byebug_set_tracing(VALUE self, VALUE value)
|
469
|
+
{
|
470
|
+
tracing = RTEST(value) ? Qtrue : Qfalse;
|
471
|
+
return value;
|
472
|
+
}
|
440
473
|
|
441
474
|
static VALUE
|
442
475
|
Byebug_contexts(VALUE self)
|
@@ -467,34 +500,47 @@ Byebug_catchpoints(VALUE self)
|
|
467
500
|
return catchpoints;
|
468
501
|
}
|
469
502
|
|
503
|
+
static VALUE
|
504
|
+
Byebug_add_catchpoint(VALUE self, VALUE value)
|
505
|
+
{
|
506
|
+
if (TYPE(value) != T_STRING)
|
507
|
+
rb_raise(rb_eTypeError, "value of a catchpoint must be String");
|
508
|
+
|
509
|
+
rb_hash_aset(catchpoints, rb_str_dup(value), INT2FIX(0));
|
510
|
+
return value;
|
511
|
+
}
|
512
|
+
|
470
513
|
/*
|
471
514
|
* Document-class: Byebug
|
472
515
|
*
|
473
516
|
* == Summary
|
474
517
|
*
|
475
|
-
* This is a singleton class allows controlling
|
518
|
+
* This is a singleton class allows controlling byebug. Use it to start/stop
|
476
519
|
* byebug, set/remove breakpoints, etc.
|
477
520
|
*/
|
478
521
|
void
|
479
522
|
Init_byebug()
|
480
523
|
{
|
481
524
|
mByebug = rb_define_module("Byebug");
|
482
|
-
rb_define_module_function(mByebug, "setup_tracepoints",
|
483
|
-
|
484
|
-
rb_define_module_function(mByebug, "
|
525
|
+
rb_define_module_function(mByebug, "setup_tracepoints",
|
526
|
+
Byebug_setup_tracepoints, 0);
|
527
|
+
rb_define_module_function(mByebug, "remove_tracepoints",
|
528
|
+
Byebug_remove_tracepoints, 0);
|
529
|
+
rb_define_module_function(mByebug, "current_context",
|
530
|
+
Byebug_current_context, 0);
|
485
531
|
rb_define_module_function(mByebug, "contexts", Byebug_contexts, 0);
|
486
532
|
rb_define_module_function(mByebug, "breakpoints", Byebug_breakpoints, 0);
|
533
|
+
rb_define_module_function(mByebug, "add_catchpoint",
|
534
|
+
Byebug_add_catchpoint, 1);
|
487
535
|
rb_define_module_function(mByebug, "catchpoints", Byebug_catchpoints, 0);
|
488
536
|
rb_define_module_function(mByebug, "_start", Byebug_start, 0);
|
489
537
|
rb_define_module_function(mByebug, "stop", Byebug_stop, 0);
|
490
538
|
rb_define_module_function(mByebug, "started?", Byebug_started, 0);
|
539
|
+
rb_define_module_function(mByebug, "tracing", Byebug_tracing, 0);
|
540
|
+
rb_define_module_function(mByebug, "tracing=", Byebug_set_tracing, 1);
|
491
541
|
rb_define_module_function(mByebug, "debug_load", Byebug_load, -1);
|
492
542
|
|
493
543
|
idAlive = rb_intern("alive?");
|
494
|
-
idAtBreakpoint = rb_intern("at_breakpoint");
|
495
|
-
idAtCatchpoint = rb_intern("at_catchpoint");
|
496
|
-
idAtTracing = rb_intern("at_tracing");
|
497
|
-
idAtLine = rb_intern("at_line");
|
498
544
|
|
499
545
|
cContext = Init_context(mByebug);
|
500
546
|
|