ext/byebug/byebug.c in byebug-0.0.1 vs ext/byebug/byebug.c in byebug-1.0.0
- old
+ new
@@ -2,26 +2,24 @@
static VALUE mByebug; /* Ruby Byebug Module object */
static VALUE cContext;
static VALUE cDebugThread;
-static VALUE debug = Qfalse;
-static VALUE locker = Qnil;
+static VALUE tracing = Qfalse;
+static VALUE debug = Qfalse;
+static VALUE locker = Qnil;
+
static VALUE contexts;
static VALUE catchpoints;
static VALUE breakpoints;
static VALUE tpLine;
static VALUE tpCall;
static VALUE tpReturn;
static VALUE tpRaise;
static VALUE idAlive;
-static VALUE idAtBreakpoint;
-static VALUE idAtCatchpoint;
-static VALUE idAtLine;
-static VALUE idAtTracing;
static void
print_debug_info(char *event, VALUE path, VALUE lineno, VALUE method_id,
VALUE defined_class, int stack_size)
{
@@ -85,13 +83,11 @@
*/
if(CTX_FL_TEST(context, CTX_FL_IGNORE)) return 0;
while(1)
{
- /* halt execution of the current thread if the byebug
- is activated in another
- */
+ /* halt execution of the current thread if byebug is activated in another */
while(locker != Qnil && locker != thread)
{
add_to_locked(thread);
rb_thread_stop();
}
@@ -138,74 +134,80 @@
static void
call_at_line(debug_context_t *context, char *file, int line,
VALUE context_object, VALUE path, VALUE lineno)
{
- CTX_FL_UNSET(context, CTX_FL_STEPPED);
+ CTX_FL_UNSET(context, CTX_FL_ENABLE_BKPT);
CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
context->last_file = file;
context->last_line = line;
- rb_funcall(context_object, idAtLine, 2, path, lineno);
+ rb_funcall(context_object, rb_intern("at_line"), 2, path, lineno);
}
static void
process_line_event(VALUE trace_point, void *data)
{
VALUE path, lineno, method_id, defined_class, binding, self;
VALUE context_object;
VALUE breakpoint;
debug_context_t *context;
- int moved;
+ int moved = 0;
context_object = Byebug_current_context(mByebug);
Data_Get_Struct(context_object, debug_context_t, context);
if (!check_start_processing(context, rb_thread_current())) return;
- load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
- &binding, &self);
+ load_frame_info(
+ trace_point, &path, &lineno, &method_id, &defined_class, &binding, &self);
if (debug == Qtrue)
- print_debug_info("line", path, lineno, method_id, defined_class,
- context->stack_size);
+ print_debug_info(
+ "line", path, lineno, method_id, defined_class, context->stack_size);
update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
defined_class, binding, self);
- moved = context->last_line != FIX2INT(lineno) || context->last_file == NULL ||
- strcmp(context->last_file, RSTRING_PTR(path)) != 0;
+ if (context->last_line != FIX2INT(lineno) || context->last_file == NULL ||
+ strcmp(context->last_file, RSTRING_PTR(path)))
+ {
+ CTX_FL_SET(context, CTX_FL_ENABLE_BKPT);
+ moved = 1;
+ }
- if (CTX_FL_TEST(context, CTX_FL_TRACING))
- rb_funcall(context_object, idAtTracing, 2, path, lineno);
+ if (RTEST(tracing))
+ rb_funcall(context_object, rb_intern("at_tracing"), 2, path, lineno);
if (context->dest_frame == -1 || context->stack_size == context->dest_frame)
{
- if (moved || !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE))
- context->stop_next--;
- if (context->stop_next < 0)
- context->stop_next = -1;
- if (moved || (CTX_FL_TEST(context, CTX_FL_STEPPED) && !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)))
- {
- context->stop_line--;
- CTX_FL_UNSET(context, CTX_FL_STEPPED);
- }
+ if (moved || !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)) {
+ context->stop_next = context->stop_next <= 0 ? -1 : context->stop_next-1;
+ context->stop_line = context->stop_line <= 0 ? -1 : context->stop_line-1;
+ }
}
else if (context->stack_size < context->dest_frame)
{
context->stop_next = 0;
}
- breakpoint = find_breakpoint_by_pos(breakpoints, path, lineno, binding);
- if (context->stop_next == 0 || context->stop_line == 0 ||
- breakpoint != Qnil)
+ if (context->stop_next == 0 || context->stop_line == 0)
{
context->stop_reason = CTX_STOP_STEP;
+ reset_stepping_stop_points(context);
+ call_at_line(
+ context, RSTRING_PTR(path), FIX2INT(lineno), context_object, path, lineno);
+ }
+ else if (CTX_FL_TEST(context, CTX_FL_ENABLE_BKPT))
+ {
+ breakpoint = find_breakpoint_by_pos(breakpoints, path, lineno, binding);
if (breakpoint != Qnil) {
- rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
+ context->stop_reason = CTX_STOP_BREAKPOINT;
+ reset_stepping_stop_points(context);
+ rb_funcall(context_object, rb_intern("at_breakpoint"), 1, breakpoint);
+ call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
+ path, lineno);
}
- reset_stepping_stop_points(context);
- call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
- path, lineno);
}
+
cleanup(context);
}
static void
process_return_event(VALUE trace_point, void *data)
@@ -216,11 +218,11 @@
context_object = Byebug_current_context(mByebug);
Data_Get_Struct(context_object, debug_context_t, context);
if (!check_start_processing(context, rb_thread_current())) return;
- if(context->stack_size == context->stop_frame)
+ if (context->stack_size == context->stop_frame)
{
context->stop_next = 1;
context->stop_frame = 0;
}
@@ -228,13 +230,13 @@
&binding, &self);
if (debug == Qtrue)
print_debug_info("return", path, lineno, method_id, defined_class,
context->stack_size);
- // rb_funcall(context_object, idAtReturn, 2, path, lineno);
-
+ //rb_funcall(context_object, idAtReturn, 2, path, lineno);
pop_frame(context_object);
+
cleanup(context);
}
static void
process_call_event(VALUE trace_point, void *data)
@@ -260,11 +262,11 @@
breakpoint = find_breakpoint_by_method(breakpoints, defined_class,
SYM2ID(method_id),
binding, self);
if (breakpoint != Qnil) {
context->stop_reason = CTX_STOP_BREAKPOINT;
- rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
+ rb_funcall(context_object, rb_intern("at_breakpoint"), 1, breakpoint);
call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
path, lineno);
}
cleanup(context);
@@ -273,46 +275,66 @@
static void
process_raise_event(VALUE trace_point, void *data)
{
VALUE path, lineno, method_id, defined_class, binding, self;
VALUE context_object;
- VALUE hit_count;
- VALUE exception_name;
+ VALUE expn_class, aclass;
+ VALUE err = rb_errinfo();
+ VALUE ancestors;
debug_context_t *context;
- int c_hit_count;
+ int i;
context_object = Byebug_current_context(mByebug);
Data_Get_Struct(context_object, debug_context_t, context);
if (!check_start_processing(context, rb_thread_current())) return;
load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
&binding, &self);
update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
defined_class, binding, self);
- if (catchpoint_hit_count(catchpoints, rb_errinfo(), &exception_name) != Qnil) {
- /* On 64-bit systems with gcc and -O2 there seems to be
- an optimization bug in running INT2FIX(FIX2INT...)..)
- So we do this in two steps.
- */
- c_hit_count = FIX2INT(rb_hash_aref(catchpoints, exception_name)) + 1;
- hit_count = INT2FIX(c_hit_count);
- rb_hash_aset(catchpoints, exception_name, hit_count);
- context->stop_reason = CTX_STOP_CATCHPOINT;
- rb_funcall(context_object, idAtCatchpoint, 1, rb_errinfo());
- call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
- path, lineno);
+ if (debug == Qtrue)
+ print_debug_info("call", path, lineno, method_id, defined_class,
+ context->stack_size);
+ expn_class = rb_obj_class(err);
+
+ if (catchpoints == Qnil ||
+ context->stack_size == 0 ||
+ CTX_FL_TEST(context, CTX_FL_CATCHING) ||
+ RHASH_TBL(catchpoints)->num_entries == 0) {
+ cleanup(context);
+ return;
}
+ ancestors = rb_mod_ancestors(expn_class);
+ for (i = 0; i < RARRAY_LEN(ancestors); i++) {
+ VALUE mod_name;
+ VALUE hit_count;
+
+ aclass = rb_ary_entry(ancestors, i);
+ mod_name = rb_mod_name(aclass);
+ hit_count = rb_hash_aref(catchpoints, mod_name);
+
+ if (hit_count != Qnil) {
+ /* increment exception */
+ rb_hash_aset(catchpoints, mod_name, INT2FIX(FIX2INT(hit_count) + 1));
+ context->stop_reason = CTX_STOP_CATCHPOINT;
+ rb_funcall(context_object, rb_intern("at_catchpoint"), 1, rb_errinfo());
+ call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
+ path, lineno);
+ break;
+ }
+ }
+
cleanup(context);
}
-
static VALUE
Byebug_setup_tracepoints(VALUE self)
{
if (catchpoints != Qnil) return Qnil;
+
contexts = rb_hash_new();
breakpoints = rb_ary_new();
catchpoints = rb_hash_new();
tpLine = rb_tracepoint_new(Qnil,
@@ -434,11 +456,22 @@
rb_exec_end_proc();
return Qnil;
}
+static VALUE
+Byebug_tracing(VALUE self)
+{
+ return tracing;
+}
+static VALUE
+Byebug_set_tracing(VALUE self, VALUE value)
+{
+ tracing = RTEST(value) ? Qtrue : Qfalse;
+ return value;
+}
static VALUE
Byebug_contexts(VALUE self)
{
VALUE ary;
@@ -465,37 +498,50 @@
if (catchpoints == Qnil)
rb_raise(rb_eRuntimeError, "Byebug.start is not called yet.");
return catchpoints;
}
+static VALUE
+Byebug_add_catchpoint(VALUE self, VALUE value)
+{
+ if (TYPE(value) != T_STRING)
+ rb_raise(rb_eTypeError, "value of a catchpoint must be String");
+
+ rb_hash_aset(catchpoints, rb_str_dup(value), INT2FIX(0));
+ return value;
+}
+
/*
* Document-class: Byebug
*
* == Summary
*
- * This is a singleton class allows controlling the byebug. Use it to start/stop
+ * This is a singleton class allows controlling byebug. Use it to start/stop
* byebug, set/remove breakpoints, etc.
*/
void
Init_byebug()
{
mByebug = rb_define_module("Byebug");
- rb_define_module_function(mByebug, "setup_tracepoints", Byebug_setup_tracepoints, 0);
- rb_define_module_function(mByebug, "remove_tracepoints", Byebug_remove_tracepoints, 0);
- rb_define_module_function(mByebug, "current_context", Byebug_current_context, 0);
+ rb_define_module_function(mByebug, "setup_tracepoints",
+ Byebug_setup_tracepoints, 0);
+ rb_define_module_function(mByebug, "remove_tracepoints",
+ Byebug_remove_tracepoints, 0);
+ rb_define_module_function(mByebug, "current_context",
+ Byebug_current_context, 0);
rb_define_module_function(mByebug, "contexts", Byebug_contexts, 0);
rb_define_module_function(mByebug, "breakpoints", Byebug_breakpoints, 0);
+ rb_define_module_function(mByebug, "add_catchpoint",
+ Byebug_add_catchpoint, 1);
rb_define_module_function(mByebug, "catchpoints", Byebug_catchpoints, 0);
rb_define_module_function(mByebug, "_start", Byebug_start, 0);
rb_define_module_function(mByebug, "stop", Byebug_stop, 0);
rb_define_module_function(mByebug, "started?", Byebug_started, 0);
+ rb_define_module_function(mByebug, "tracing", Byebug_tracing, 0);
+ rb_define_module_function(mByebug, "tracing=", Byebug_set_tracing, 1);
rb_define_module_function(mByebug, "debug_load", Byebug_load, -1);
idAlive = rb_intern("alive?");
- idAtBreakpoint = rb_intern("at_breakpoint");
- idAtCatchpoint = rb_intern("at_catchpoint");
- idAtTracing = rb_intern("at_tracing");
- idAtLine = rb_intern("at_line");
cContext = Init_context(mByebug);
Init_breakpoint(mByebug);