ext/byebug/byebug.c in byebug-1.8.2 vs ext/byebug/byebug.c in byebug-2.0.0
- old
+ new
@@ -1,78 +1,116 @@
#include <byebug.h>
static VALUE mByebug; /* Ruby Byebug Module object */
-static VALUE cContext;
static VALUE tracing = Qfalse;
static VALUE post_mortem = Qfalse;
static VALUE debug = Qfalse;
-static VALUE context = Qnil;
static VALUE catchpoints = Qnil;
static VALUE breakpoints = Qnil;
+static VALUE tracepoints = Qnil;
-static VALUE tpLine = Qnil;
-static VALUE tpCall = Qnil;
-static VALUE tpCCall = Qnil;
-static VALUE tpReturn = Qnil;
-static VALUE tpCReturn = Qnil;
-static VALUE tpRaise = Qnil;
+/* Implements thread syncronization, we must stop threads when debugging */
+VALUE locker = Qnil;
-static VALUE
-tp_inspect(rb_trace_arg_t *trace_arg) {
- if (trace_arg) {
- VALUE event = rb_tracearg_event(trace_arg);
- if (ID2SYM(rb_intern("line")) == event ||
- ID2SYM(rb_intern("specified_line")) == event)
- {
- VALUE sym = rb_tracearg_method_id(trace_arg);
- if (NIL_P(sym)) sym = rb_str_new_cstr("<main>");
- return rb_sprintf("%"PRIsVALUE"@%"PRIsVALUE":%d in `%"PRIsVALUE"'",
- rb_tracearg_event(trace_arg),
- rb_tracearg_path(trace_arg),
- FIX2INT(rb_tracearg_lineno(trace_arg)),
- sym);
- }
- if (ID2SYM(rb_intern("call")) == event ||
- ID2SYM(rb_intern("c_call")) == event ||
- ID2SYM(rb_intern("return")) == event ||
- ID2SYM(rb_intern("c_return")) == event)
- return rb_sprintf("%"PRIsVALUE" `%"PRIsVALUE"'@%"PRIsVALUE":%d",
- rb_tracearg_event(trace_arg),
- rb_tracearg_method_id(trace_arg),
- rb_tracearg_path(trace_arg),
- FIX2INT(rb_tracearg_lineno(trace_arg)));
- return rb_sprintf("%"PRIsVALUE"@%"PRIsVALUE":%d",
- rb_tracearg_event(trace_arg),
- rb_tracearg_path(trace_arg),
- FIX2INT(rb_tracearg_lineno(trace_arg)));
+/* Threads table */
+VALUE threads = Qnil;
+VALUE cThreadsTable;
+
+#define IS_STARTED (catchpoints != Qnil)
+static void
+check_started()
+{
+ if (!IS_STARTED)
+ {
+ rb_raise(rb_eRuntimeError, "Byebug is not started yet.");
}
- return rb_sprintf("No info");
}
-static VALUE
-Byebug_context(VALUE self)
+static void
+trace_print(rb_trace_arg_t *trace_arg, debug_context_t *dc)
{
- return context;
+ if (trace_arg)
+ {
+ int i = 0;
+ VALUE path = rb_tracearg_path(trace_arg);
+ VALUE line = rb_tracearg_lineno(trace_arg);
+ VALUE event = rb_tracearg_event(trace_arg);
+ VALUE mid = rb_tracearg_method_id(trace_arg);
+ for (i=0; i<dc->stack_size; i++) putc('|', stderr);
+ fprintf(stderr, "[#%d] %s@%s:%d %s\n", dc->thnum,
+ rb_id2name(SYM2ID(event)), RSTRING_PTR(path), NUM2INT(line),
+ NIL_P(mid) ? "" : rb_id2name(SYM2ID(mid)));
+ }
}
static void
cleanup(debug_context_t *dc)
{
+ VALUE thread;
+
dc->stop_reason = CTX_STOP_NONE;
+
+ /* checks for dead threads */
+ check_thread_contexts();
+
+ /* release a lock */
+ locker = Qnil;
+
+ /* let the next thread to run */
+ thread = remove_from_locked();
+ if (thread != Qnil)
+ rb_thread_run(thread);
}
+#define EVENT_SETUP \
+ rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point); \
+ debug_context_t *dc; \
+ VALUE context; \
+ thread_context_lookup(rb_thread_current(), &context); \
+ Data_Get_Struct(context, debug_context_t, dc); \
+ if (debug == Qtrue) trace_print(trace_arg, dc); \
+
+#define EVENT_COMMON if (!trace_common(trace_arg, dc)) { return; }
+
+static int
+trace_common(rb_trace_arg_t *trace_arg, debug_context_t *dc)
+{
+ /* return if thread marked as 'ignored', like byebug's control thread */
+ if (CTX_FL_TEST(dc, CTX_FL_IGNORE))
+ {
+ cleanup(dc);
+ return 0;
+ }
+
+ halt_while_other_thread_is_active(dc);
+
+ /* Get the lock! */
+ locker = rb_thread_current();
+
+ /* Many events per line, but only *one* breakpoint */
+ if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
+ dc->last_file != rb_tracearg_path(trace_arg))
+ {
+ CTX_FL_SET(dc, CTX_FL_ENABLE_BKPT);
+ }
+
+ return 1;
+}
+
static void
save_current_position(debug_context_t *dc, VALUE file, VALUE line)
{
dc->last_file = file;
dc->last_line = line;
CTX_FL_UNSET(dc, CTX_FL_ENABLE_BKPT);
CTX_FL_UNSET(dc, CTX_FL_FORCE_MOVE);
}
+/* Functions that return control to byebug after the different events */
+
static VALUE
call_at(VALUE context_obj, debug_context_t *dc, ID mid, int argc, VALUE a0,
VALUE a1)
{
struct call_with_inspection_data cwi;
@@ -136,56 +174,25 @@
reset_stepping_stop_points(dc);
call_at_line(context_obj, dc, file, line);
}
-#define BYEBUG_STARTED (catchpoints != Qnil)
-#define EVENT_SETUP \
- rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point); \
- debug_context_t *dc; \
- if (!BYEBUG_STARTED) \
- rb_raise(rb_eRuntimeError, "Byebug not started yet!"); \
- Data_Get_Struct(context, debug_context_t, dc); \
- if (debug == Qtrue) \
- printf("%s (stack_size: %d)\n", \
- RSTRING_PTR(tp_inspect(trace_arg)), dc->stack_size); \
+/* TracePoint API event handlers */
-#define EVENT_COMMON() \
- if (trace_common(trace_arg, dc) == 0) { return; }
-
-static int
-trace_common(rb_trace_arg_t *trace_arg, debug_context_t *dc)
-{
- /* ignore a skipped section of code */
- if (CTX_FL_TEST(dc, CTX_FL_SKIPPED))
- {
- cleanup(dc);
- return 0;
- }
-
- /* Many events per line, but only *one* breakpoint */
- if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
- dc->last_file != rb_tracearg_path(trace_arg))
- {
- CTX_FL_SET(dc, CTX_FL_ENABLE_BKPT);
- }
-
- return 1;
-}
-
static void
-process_line_event(VALUE trace_point, void *data)
+line_event(VALUE trace_point, void *data)
{
- EVENT_SETUP;
+ EVENT_SETUP
+
VALUE breakpoint = Qnil;
VALUE file = rb_tracearg_path(trace_arg);
VALUE line = rb_tracearg_lineno(trace_arg);
VALUE binding = rb_tracearg_binding(trace_arg);
int moved = 0;
- EVENT_COMMON();
+ EVENT_COMMON
if (dc->stack_size == 0) dc->stack_size++;
if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
dc->last_file != rb_tracearg_path(trace_arg))
@@ -216,26 +223,45 @@
cleanup(dc);
}
static void
-process_c_return_event(VALUE trace_point, void *data)
+call_event(VALUE trace_point, void *data)
{
- EVENT_SETUP;
- if (dc->stack_size > 0) dc->stack_size--;
- EVENT_COMMON();
+ EVENT_SETUP
+ dc->stack_size++;
+
+ EVENT_COMMON
+
+ VALUE breakpoint = Qnil;
+ VALUE klass = rb_tracearg_defined_class(trace_arg);
+ VALUE mid = SYM2ID(rb_tracearg_method_id(trace_arg));
+ VALUE binding = rb_tracearg_binding(trace_arg);
+ VALUE self = rb_tracearg_self(trace_arg);
+ VALUE file = rb_tracearg_path(trace_arg);
+ VALUE line = rb_tracearg_lineno(trace_arg);
+
+ breakpoint = find_breakpoint_by_method(breakpoints, klass, mid, binding, self);
+ if (breakpoint != Qnil)
+ {
+ call_at_breakpoint(context, dc, breakpoint);
+ call_at_line(context, dc, file, line);
+ }
+
cleanup(dc);
}
static void
-process_return_event(VALUE trace_point, void *data)
+return_event(VALUE trace_point, void *data)
{
- EVENT_SETUP;
+ EVENT_SETUP
+
if (dc->stack_size > 0) dc->stack_size--;
- EVENT_COMMON();
+ EVENT_COMMON
+
if (dc->stack_size + 1 == dc->before_frame)
{
reset_stepping_stop_points(dc);
VALUE file = rb_tracearg_path(trace_arg);
VALUE line = rb_tracearg_lineno(trace_arg);
@@ -250,68 +276,57 @@
cleanup(dc);
}
static void
-process_c_call_event(VALUE trace_point, void *data)
+c_call_event(VALUE trace_point, void *data)
{
- EVENT_SETUP;
+ EVENT_SETUP
+
dc->stack_size++;
- EVENT_COMMON();
+ EVENT_COMMON
+
cleanup(dc);
}
static void
-process_call_event(VALUE trace_point, void *data)
+c_return_event(VALUE trace_point, void *data)
{
- EVENT_SETUP;
- dc->stack_size++;
- EVENT_COMMON();
+ EVENT_SETUP
- VALUE breakpoint = Qnil;
- VALUE klass = rb_tracearg_defined_class(trace_arg);
- VALUE mid = SYM2ID(rb_tracearg_method_id(trace_arg));
- VALUE binding = rb_tracearg_binding(trace_arg);
- VALUE self = rb_tracearg_self(trace_arg);
- VALUE file = rb_tracearg_path(trace_arg);
- VALUE line = rb_tracearg_lineno(trace_arg);
+ if (dc->stack_size > 0) dc->stack_size--;
- breakpoint =
- find_breakpoint_by_method(breakpoints, klass, mid, binding, self);
- if (breakpoint != Qnil)
- {
- call_at_breakpoint(context, dc, breakpoint);
- call_at_line(context, dc, file, line);
- }
+ EVENT_COMMON
cleanup(dc);
}
static void
-process_raise_event(VALUE trace_point, void *data)
+raise_event(VALUE trace_point, void *data)
{
EVENT_SETUP
+
VALUE expn_class, aclass;
VALUE err = rb_errinfo();
VALUE ancestors;
int i;
debug_context_t *new_dc;
- EVENT_COMMON();
+ EVENT_COMMON
VALUE binding = rb_tracearg_binding(trace_arg);
VALUE path = rb_tracearg_path(trace_arg);
VALUE lineno = rb_tracearg_lineno(trace_arg);
if (post_mortem == Qtrue)
{
context = context_dup(dc);
- rb_ivar_set(err, rb_intern("@__debug_file") , path);
- rb_ivar_set(err, rb_intern("@__debug_line") , lineno);
- rb_ivar_set(err, rb_intern("@__debug_binding"), binding);
- rb_ivar_set(err, rb_intern("@__debug_context"), context);
+ rb_ivar_set(err, rb_intern("@__bb_file") , path);
+ rb_ivar_set(err, rb_intern("@__bb_line") , lineno);
+ rb_ivar_set(err, rb_intern("@__bb_binding"), binding);
+ rb_ivar_set(err, rb_intern("@__bb_context"), context);
Data_Get_Struct(context, debug_context_t, new_dc);
rb_debug_inspector_open(context_backtrace_set, (void *)new_dc);
}
@@ -346,138 +361,239 @@
}
cleanup(dc);
}
+
+/* Setup TracePoint functionality */
+
+static void
+register_tracepoints(VALUE self)
+{
+ int i;
+ VALUE traces = tracepoints;
+
+ if (NIL_P(traces))
+ {
+ traces = rb_ary_new();
+
+ int line_msk = RUBY_EVENT_LINE;
+ int call_msk = RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS;
+ int return_msk = RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END;
+ int c_call_msk = RUBY_EVENT_C_CALL;
+ int c_return_msk = RUBY_EVENT_C_RETURN;
+ int raise_msk = RUBY_EVENT_RAISE;
+
+ VALUE tpLine = rb_tracepoint_new(Qnil, line_msk , line_event , 0);
+ VALUE tpCall = rb_tracepoint_new(Qnil, call_msk , call_event , 0);
+ VALUE tpReturn = rb_tracepoint_new(Qnil, return_msk , return_event , 0);
+ VALUE tpCCall = rb_tracepoint_new(Qnil, c_call_msk , c_call_event , 0);
+ VALUE tpCReturn = rb_tracepoint_new(Qnil, c_return_msk, c_return_event, 0);
+ VALUE tpRaise = rb_tracepoint_new(Qnil, raise_msk , raise_event , 0);
+
+ rb_ary_push(traces, tpLine);
+ rb_ary_push(traces, tpCall);
+ rb_ary_push(traces, tpReturn);
+ rb_ary_push(traces, tpCCall);
+ rb_ary_push(traces, tpCReturn);
+ rb_ary_push(traces, tpRaise);
+
+ tracepoints = traces;
+ }
+
+ for (i = 0; i < RARRAY_LEN(traces); i++)
+ rb_tracepoint_enable(rb_ary_entry(traces, i));
+}
+
+static void
+clear_tracepoints(VALUE self)
+{
+ int i;
+
+ for (i = RARRAY_LEN(tracepoints)-1; i >= 0; i--)
+ rb_tracepoint_disable(rb_ary_entry(tracepoints, i));
+}
+
+
+/* Byebug's Public API */
+
+/*
+ * call-seq:
+ * Byebug.contexts -> array
+ *
+ * Returns an array of all contexts.
+ */
static VALUE
-Byebug_setup_tracepoints(VALUE self)
+bb_contexts(VALUE self)
{
- if (catchpoints != Qnil) return Qnil;
+ volatile VALUE list;
+ volatile VALUE new_list;
+ VALUE context;
+ threads_table_t *t_tbl;
+ debug_context_t *dc;
+ int i;
- breakpoints = rb_ary_new();
- catchpoints = rb_hash_new();
- context = context_create();
+ check_started();
- tpLine = rb_tracepoint_new(Qnil,
- RUBY_EVENT_LINE,
- process_line_event, NULL);
+ new_list = rb_ary_new();
+ list = rb_funcall(rb_cThread, rb_intern("list"), 0);
- tpCall = rb_tracepoint_new(Qnil,
- RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_CLASS,
- process_call_event, NULL);
+ for (i = 0; i < RARRAY_LEN(list); i++)
+ {
+ VALUE thread = rb_ary_entry(list, i);
+ thread_context_lookup(thread, &context);
+ rb_ary_push(new_list, context);
+ }
- tpCCall = rb_tracepoint_new(Qnil,
- RUBY_EVENT_C_CALL,
- process_c_call_event, NULL);
+ threads_clear(threads);
+ Data_Get_Struct(threads, threads_table_t, t_tbl);
- tpReturn = rb_tracepoint_new(Qnil,
- RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_END,
- process_return_event, NULL);
+ for (i = 0; i < RARRAY_LEN(new_list); i++)
+ {
+ context = rb_ary_entry(new_list, i);
+ Data_Get_Struct(context, debug_context_t, dc);
+ st_insert(t_tbl->tbl, dc->thread, context);
+ }
- tpCReturn = rb_tracepoint_new(Qnil,
- RUBY_EVENT_C_RETURN,
- process_c_return_event, NULL);
+ return new_list;
+}
- tpRaise = rb_tracepoint_new(Qnil,
- RUBY_EVENT_RAISE,
- process_raise_event, NULL);
+/*
+ * call-seq:
+ * Byebug.thread_context(thread) -> context
+ *
+ * Returns context of the thread passed as an argument.
+ */
+static VALUE
+bb_thread_context(VALUE self, VALUE thread)
+{
+ VALUE context;
- rb_tracepoint_enable(tpLine);
- rb_tracepoint_enable(tpCall);
- rb_tracepoint_enable(tpCCall);
- rb_tracepoint_enable(tpReturn);
- rb_tracepoint_enable(tpCReturn);
- rb_tracepoint_enable(tpRaise);
+ check_started();
- return Qnil;
+ thread_context_lookup(thread, &context);
+
+ return context;
}
+/*
+ * call-seq:
+ * Byebug.current_context -> context
+ *
+ * Returns the current context.
+ * <i>Note:</i> Byebug.current_context.thread == Thread.current
+ */
static VALUE
-Byebug_remove_tracepoints(VALUE self)
+bb_current_context(VALUE self)
{
- rb_tracepoint_disable(tpRaise);
- rb_tracepoint_disable(tpCReturn);
- rb_tracepoint_disable(tpReturn);
- rb_tracepoint_disable(tpCCall);
- rb_tracepoint_disable(tpCall);
- rb_tracepoint_disable(tpLine);
+ VALUE context;
- context = Qnil;
- breakpoints = Qnil;
- catchpoints = Qnil;
+ check_started();
- return Qnil;
+ thread_context_lookup(rb_thread_current(), &context);
+
+ return context;
}
+/*
+ * call-seq:
+ * Byebug.started? -> bool
+ *
+ * Returns +true+ byebug is started.
+ */
static VALUE
-Byebug_started(VALUE self)
+bb_started(VALUE self)
{
- return BYEBUG_STARTED;
+ return IS_STARTED;
}
+/*
+ * call-seq:
+ * Byebug.stop -> bool
+ *
+ * This method disables byebug. It returns +true+ if byebug was already
+ * disabled, otherwise it returns +false+.
+ */
static VALUE
-Byebug_stop(VALUE self)
+bb_stop(VALUE self)
{
- if (BYEBUG_STARTED)
+ if (IS_STARTED)
{
- Byebug_remove_tracepoints(self);
+ clear_tracepoints(self);
+
+ breakpoints = Qnil;
+ catchpoints = Qnil;
+ threads = Qnil;
+
return Qfalse;
}
return Qtrue;
}
+/*
+ * call-seq:
+ * Byebug.start_ -> bool
+ * Byebug.start_ { ... } -> bool
+ *
+ * This method is internal and activates the debugger. Use Byebug.start (from
+ * <tt>lib/byebug.rb</tt>) instead.
+ *
+ * The return value is the value of !Byebug.started? <i>before</i> issuing the
+ * +start+; That is, +true+ is returned, unless byebug was previously started.
+ *
+ * If a block is given, it starts byebug and yields to block. When the block
+ * is finished executing it stops the debugger with Byebug.stop method.
+ */
static VALUE
-Byebug_start(VALUE self)
+bb_start(VALUE self)
{
VALUE result;
- if (BYEBUG_STARTED)
+ if (IS_STARTED)
result = Qfalse;
else
{
- Byebug_setup_tracepoints(self);
+ locker = Qnil;
+ breakpoints = rb_ary_new();
+ catchpoints = rb_hash_new();
+ threads = threads_create();
+
+ register_tracepoints(self);
result = Qtrue;
}
if (rb_block_given_p())
- rb_ensure(rb_yield, self, Byebug_stop, self);
+ rb_ensure(rb_yield, self, bb_stop, self);
return result;
}
+/*
+ * call-seq:
+ * Byebug.debug_load(file, stop = false) -> nil
+ *
+ * Same as Kernel#load but resets current context's frames.
+ * +stop+ parameter forces byebug to stop at the first line of code in +file+
+ */
static VALUE
-set_current_skipped_status(VALUE status)
+bb_load(int argc, VALUE *argv, VALUE self)
{
- VALUE context_obj;
+ VALUE file, stop, context;
debug_context_t *dc;
-
- context_obj = Byebug_context(mByebug);
- Data_Get_Struct(context_obj, debug_context_t, dc);
- if (status)
- CTX_FL_SET(dc, CTX_FL_SKIPPED);
- else
- CTX_FL_UNSET(dc, CTX_FL_SKIPPED);
- return Qnil;
-}
-
-static VALUE
-Byebug_load(int argc, VALUE *argv, VALUE self)
-{
- VALUE file, stop, context_obj;
- debug_context_t *dc;
VALUE status = Qnil;
int state = 0;
if (rb_scan_args(argc, argv, "11", &file, &stop) == 1)
{
stop = Qfalse;
}
- Byebug_start(self);
+ bb_start(self);
- context_obj = Byebug_context(self);
- Data_Get_Struct(context_obj, debug_context_t, dc);
+ context = bb_current_context(self);
+ Data_Get_Struct(context, debug_context_t, dc);
+
if (RTEST(stop)) dc->steps = 1;
/* Reset stack size to ignore byebug's own frames */
dc->stack_size = 0;
@@ -496,77 +612,144 @@
return status;
}
static VALUE
+set_current_skipped_status(VALUE status)
+{
+ VALUE context;
+ debug_context_t *dc;
+
+ context = bb_current_context(mByebug);
+ Data_Get_Struct(context, debug_context_t, dc);
+
+ if (status)
+ CTX_FL_SET(dc, CTX_FL_SKIPPED);
+ else
+ CTX_FL_UNSET(dc, CTX_FL_SKIPPED);
+
+ return Qnil;
+}
+
+static VALUE
debug_at_exit_c(VALUE proc)
{
return rb_funcall(proc, rb_intern("call"), 0);
}
static void
debug_at_exit_i(VALUE proc)
{
- if (BYEBUG_STARTED)
+ if (IS_STARTED)
{
set_current_skipped_status(Qtrue);
rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse);
}
else
debug_at_exit_c(proc);
}
+/*
+ * call-seq:
+ * Byebug.debug_at_exit { block } -> proc
+ *
+ * Register <tt>at_exit</tt> hook which is escaped from byebug.
+ */
static VALUE
-Byebug_at_exit(VALUE self)
+bb_at_exit(VALUE self)
{
VALUE proc;
+
if (!rb_block_given_p()) rb_raise(rb_eArgError, "called without a block");
+
proc = rb_block_proc();
rb_set_end_proc(debug_at_exit_i, proc);
return proc;
}
+/*
+ * call-seq:
+ * Byebug.tracing -> bool
+ *
+ * Returns +true+ if global tracing is enabled.
+ */
static VALUE
-Byebug_tracing(VALUE self)
+bb_tracing(VALUE self)
{
return tracing;
}
+/*
+ * call-seq:
+ * Byebug.tracing = bool
+ *
+ * Sets the global tracing flag.
+ */
static VALUE
-Byebug_set_tracing(VALUE self, VALUE value)
+bb_set_tracing(VALUE self, VALUE value)
{
tracing = RTEST(value) ? Qtrue : Qfalse;
return value;
}
+/*
+ * call-seq:
+ * Byebug.post_mortem? -> bool
+ *
+ * Returns +true+ if post-moterm debugging is enabled.
+ */
static VALUE
-Byebug_post_mortem(VALUE self)
+bb_post_mortem(VALUE self)
{
return post_mortem;
}
+/*
+ * call-seq:
+ * Byebug.post_mortem = bool
+ *
+ * Sets post-moterm flag.
+ */
static VALUE
-Byebug_set_post_mortem(VALUE self, VALUE value)
+bb_set_post_mortem(VALUE self, VALUE value)
{
post_mortem = RTEST(value) ? Qtrue : Qfalse;
return value;
}
+/*
+ * call-seq:
+ * Byebug.breakpoints -> array
+ *
+ * Returns an array of breakpoints.
+ */
static VALUE
-Byebug_breakpoints(VALUE self)
+bb_breakpoints(VALUE self)
{
return breakpoints;
}
+/*
+ * call-seq:
+ * Byebug.catchpoints -> array
+ *
+ * Returns an array of catchpoints.
+ */
static VALUE
-Byebug_catchpoints(VALUE self)
+bb_catchpoints(VALUE self)
{
return catchpoints;
}
+/*
+ * call-seq:
+ * Byebug.add_catchpoint(exception) -> exception
+ *
+ * Adds a new exception to the catchpoints array.
+ */
static VALUE
-Byebug_add_catchpoint(VALUE self, VALUE value)
+bb_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));
@@ -583,36 +766,32 @@
*/
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, "context", Byebug_context, 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);
- rb_define_module_function(mByebug, "debug_at_exit", Byebug_at_exit, 0);
- rb_define_module_function(mByebug, "post_mortem?", Byebug_post_mortem, 0);
- rb_define_module_function(mByebug, "post_mortem=", Byebug_set_post_mortem, 1);
- cContext = Init_context(mByebug);
+ rb_define_module_function(mByebug, "add_catchpoint" , bb_add_catchpoint , 1);
+ rb_define_module_function(mByebug, "breakpoints" , bb_breakpoints , 0);
+ rb_define_module_function(mByebug, "catchpoints" , bb_catchpoints , 0);
+ rb_define_module_function(mByebug, "contexts" , bb_contexts , 0);
+ rb_define_module_function(mByebug, "current_context", bb_current_context, 0);
+ rb_define_module_function(mByebug, "debug_at_exit" , bb_at_exit , 0);
+ rb_define_module_function(mByebug, "debug_load" , bb_load , -1);
+ rb_define_module_function(mByebug, "post_mortem?" , bb_post_mortem , 0);
+ rb_define_module_function(mByebug, "post_mortem=" , bb_set_post_mortem, 1);
+ rb_define_module_function(mByebug, "_start" , bb_start , 0);
+ rb_define_module_function(mByebug, "started?" , bb_started , 0);
+ rb_define_module_function(mByebug, "stop" , bb_stop , 0);
+ rb_define_module_function(mByebug, "thread_context" , bb_thread_context , 1);
+ rb_define_module_function(mByebug, "tracing?" , bb_tracing , 0);
+ rb_define_module_function(mByebug, "tracing=" , bb_set_tracing , 1);
+ cThreadsTable = rb_define_class_under(mByebug, "ThreadsTable", rb_cObject);
+
+ Init_context(mByebug);
Init_breakpoint(mByebug);
- context = Qnil;
- catchpoints = Qnil;
- breakpoints = Qnil;
-
rb_global_variable(&breakpoints);
rb_global_variable(&catchpoints);
- rb_global_variable(&context);
+ rb_global_variable(&tracepoints);
+ rb_global_variable(&threads);
}