summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authortake_cheeze <[email protected]>2013-08-26 22:51:53 +0900
committertake_cheeze <[email protected]>2013-09-02 00:48:06 +0900
commitd12b6ab2187528828977ba1ea8b6f6fc9f6e42f2 (patch)
tree9d3bbe7d7c8d7beede1ce6841c56e35b7a9fe781
parentd19d9bb047a8b63c79442d5713be9205cf74c60c (diff)
downloadmruby-d12b6ab2187528828977ba1ea8b6f6fc9f6e42f2.tar.gz
mruby-d12b6ab2187528828977ba1ea8b6f6fc9f6e42f2.zip
add verbose_backtrace
-rw-r--r--include/mruby.h1
-rw-r--r--src/backtrace.c34
-rw-r--r--src/class.c5
-rw-r--r--src/error.c2
-rw-r--r--test/t/exception.rb10
5 files changed, 44 insertions, 8 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 88546dd6d..0541bc709 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -323,6 +323,7 @@ void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
void mrb_warn(mrb_state *mrb, const char *fmt, ...);
void mrb_bug(mrb_state *mrb, const char *fmt, ...);
void mrb_print_backtrace(mrb_state *mrb);
+void mrb_print_verbose_backtrace(mrb_state *mrb);
void mrb_print_error(mrb_state *mrb);
/* macros to get typical exception objects
diff --git a/src/backtrace.c b/src/backtrace.c
index 6092aaf86..cee2c9389 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -55,7 +55,7 @@ get_backtrace_i(mrb_state *mrb, void *stream, int level, const char *format, ...
}
static void
-mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream)
+mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream, mrb_bool verbose)
{
mrb_callinfo *ci;
mrb_int ciidx;
@@ -72,10 +72,10 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
filename = "(unknown)";
line = -1;
- if (MRB_PROC_CFUNC_P(ci->proc)) {
+ if (!verbose && MRB_PROC_CFUNC_P(ci->proc)) {
continue;
}
- else {
+ if(!MRB_PROC_CFUNC_P(ci->proc)) {
mrb_irep *irep = ci->proc->body.irep;
if (irep->filename != NULL)
filename = irep->filename;
@@ -93,13 +93,16 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
}
}
}
- if (line == -1) continue;
+ if (!verbose && line == -1) continue;
if (ci->target_class == ci->proc->target_class)
sep = ".";
else
sep = "#";
method = mrb_sym2name(mrb, ci->mid);
+ if (verbose && !method && ci->proc->env) {
+ method = mrb_sym2name(mrb, ci->proc->env->mid);
+ }
if (method) {
const char *cn = mrb_class_name(mrb, ci->proc->target_class);
@@ -126,7 +129,15 @@ void
mrb_print_backtrace(mrb_state *mrb)
{
#ifdef ENABLE_STDIO
- mrb_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr);
+ mrb_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr, 0);
+#endif
+}
+
+void
+mrb_print_verbose_backtrace(mrb_state *mrb)
+{
+#ifdef ENABLE_STDIO
+ mrb_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr, 1);
#endif
}
@@ -136,7 +147,18 @@ mrb_get_backtrace(mrb_state *mrb, mrb_value self)
mrb_value ary;
ary = mrb_ary_new(mrb);
- mrb_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary));
+ mrb_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary), 0);
+
+ return ary;
+}
+
+mrb_value
+mrb_get_verbose_backtrace(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ mrb_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary), 1);
return ary;
}
diff --git a/src/class.c b/src/class.c
index 1870b94ba..e04aa5ce8 100644
--- a/src/class.c
+++ b/src/class.c
@@ -55,7 +55,7 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
mrb_obj_iv_set(mrb, (struct RObject*)c,
mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name));
}
-
+
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
static void
@@ -311,6 +311,7 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f
int ai = mrb_gc_arena_save(mrb);
p = mrb_proc_new_cfunc(mrb, func);
+ p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
mrb_gc_arena_restore(mrb, ai);
}
@@ -1065,7 +1066,7 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv)
{
mrb_value super;
struct RClass *new_class;
-
+
if (mrb_get_args(mrb, "|o", &super) == 0) {
super = mrb_obj_value(mrb->object_class);
}
diff --git a/src/error.c b/src/error.c
index 03f587a38..f7d41c2e2 100644
--- a/src/error.c
+++ b/src/error.c
@@ -436,6 +436,7 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
}
mrb_value mrb_get_backtrace(mrb_state*, mrb_value);
+mrb_value mrb_get_verbose_backtrace(mrb_state*, mrb_value);
void
mrb_init_exception(mrb_state *mrb)
@@ -451,6 +452,7 @@ mrb_init_exception(mrb_state *mrb)
mrb_define_method(mrb, e, "message", exc_message, MRB_ARGS_NONE());
mrb_define_method(mrb, e, "inspect", exc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, e, "backtrace", mrb_get_backtrace, MRB_ARGS_NONE());
+ mrb_define_method(mrb, e, "verbose_backtrace", mrb_get_verbose_backtrace, MRB_ARGS_NONE());
mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
diff --git a/test/t/exception.rb b/test/t/exception.rb
index 4239cba8b..ef5b284a5 100644
--- a/test/t/exception.rb
+++ b/test/t/exception.rb
@@ -345,3 +345,13 @@ assert('Exception#backtrace') do
true
end
+
+assert('Exception#verbose_backtrace') do
+ begin
+ raise "get backtrace"
+ rescue => e
+ e.verbose_backtrace
+ end
+
+ true
+end