byebug 0.0.1 → 1.0.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.
- 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
|
|