summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorKOBAYASHI Shuji <[email protected]>2019-12-17 23:16:20 +0900
committerKOBAYASHI Shuji <[email protected]>2019-12-17 23:16:20 +0900
commit29ecc3840a6df57deba9b22d917aee37f66ffc4f (patch)
tree751036caa78c352800bc25ec42cc2baf65c31ffb /src
parent8bc9a79e65bb4ee9f1791daf2726d33ac43d727d (diff)
downloadmruby-29ecc3840a6df57deba9b22d917aee37f66ffc4f.tar.gz
mruby-29ecc3840a6df57deba9b22d917aee37f66ffc4f.zip
Refine output of `mrb_print_error()`
The following improvements are made according to Ruby's behavior: - Match location number to index. - Remove duplicate most recent call output. - Fix that first call is not output when array (unpacked) backtrace. ### Example ```ruby def a; raise "error!" end def b; a end begin b rescue => e e.backtrace if ARGV[0] == "unpack" # unpack backtrace raise e end ``` #### Before this patch: ``` $ bin/mruby example.rb unpack trace (most recent call last): [0] example.rb:2:in b [1] example.rb:1:in a example.rb:1: error! (RuntimeError) ``` #### After this patch: ``` $ bin/mruby example.rb unpack trace (most recent call last): [2] example.rb:4 [1] example.rb:2:in b example.rb:1:in a: error! (RuntimeError) ```
Diffstat (limited to 'src')
-rw-r--r--src/backtrace.c71
-rw-r--r--src/error.c6
-rw-r--r--src/print.c1
3 files changed, 31 insertions, 47 deletions
diff --git a/src/backtrace.c b/src/backtrace.c
index 4ae2bc89d..a25a5adad 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -25,6 +25,10 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
+mrb_value mrb_exc_to_s(mrb_state *mrb, mrb_value exc);
+mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass);
+mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
+
static void
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtrace_func func, void *data)
{
@@ -74,50 +78,35 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, const mrb_code *pc0, each_backtr
#ifndef MRB_DISABLE_STDIO
static void
-print_backtrace(mrb_state *mrb, mrb_value backtrace)
+print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
{
int i;
- mrb_int n;
+ mrb_int n = RARRAY_LEN(backtrace);
+ mrb_value *loc, mesg, cname;
FILE *stream = stderr;
- n = RARRAY_LEN(backtrace) - 1;
- if (n == 0) return;
-
- fprintf(stream, "trace (most recent call last):\n");
- for (i=0; i<n; i++) {
- mrb_value entry = RARRAY_PTR(backtrace)[n-i-1];
-
- if (mrb_string_p(entry)) {
- fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry));
+ if (n != 0) {
+ fprintf(stream, "trace (most recent call last):\n");
+ for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) {
+ if (mrb_string_p(*loc)) {
+ fprintf(stream, "\t[%d] %.*s\n",
+ i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
+ }
}
}
-}
-static void
-print_packed_backtrace(mrb_state *mrb, mrb_value packed)
-{
- FILE *stream = stderr;
- const struct backtrace_location *bt;
- int n, i;
- int ai = mrb_gc_arena_save(mrb);
-
- bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type);
- if (bt == NULL) return;
- n = (int)RDATA(packed)->flags;
- if (n == 0) return;
-
- fprintf(stream, "trace (most recent call last):\n");
- for (i = 0; i<n; i++) {
- const struct backtrace_location *entry = &bt[n-i-1];
- fprintf(stream, "\t[%d] %s:%d", i, entry->filename, (int)entry->lineno);
- if (entry->method_id != 0) {
- const char *method_name;
-
- method_name = mrb_sym_name(mrb, entry->method_id);
- fprintf(stream, ":in %s", method_name);
- mrb_gc_arena_restore(mrb, ai);
- }
- fprintf(stream, "\n");
+ if (n != 0) {
+ fprintf(stream, "%.*s: ", (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
+ }
+ mesg = mrb_exc_to_s(mrb, mrb_obj_value(exc));
+ cname = mrb_mod_to_s(mrb, mrb_obj_value(exc->c));
+ if (RSTRING_LEN(mesg) == 0) {
+ fprintf(stream, "%.*s \n", (int)RSTRING_LEN(cname), RSTRING_PTR(cname));
+ }
+ else {
+ fprintf(stream, "%.*s (%.*s)\n",
+ (int)RSTRING_LEN(mesg), RSTRING_PTR(mesg),
+ (int)RSTRING_LEN(cname), RSTRING_PTR(cname));
}
}
@@ -137,12 +126,8 @@ mrb_print_backtrace(mrb_state *mrb)
backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace"));
if (mrb_nil_p(backtrace)) return;
- if (mrb_array_p(backtrace)) {
- print_backtrace(mrb, backtrace);
- }
- else {
- print_packed_backtrace(mrb, backtrace);
- }
+ if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace);
+ print_backtrace(mrb, mrb->exc, backtrace);
}
#else
diff --git a/src/error.c b/src/error.c
index 43b09ec66..d2a32f506 100644
--- a/src/error.c
+++ b/src/error.c
@@ -88,8 +88,8 @@ exc_exception(mrb_state *mrb, mrb_value self)
* no message is set).
*/
-static mrb_value
-exc_to_s(mrb_state *mrb, mrb_value exc)
+mrb_value
+mrb_exc_to_s(mrb_state *mrb, mrb_value exc)
{
mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
struct RObject *p;
@@ -596,7 +596,7 @@ mrb_init_exception(mrb_state *mrb)
mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_OPT(1));
mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_OPT(1));
mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_OPT(1));
- mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "to_s", mrb_exc_to_s, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
diff --git a/src/print.c b/src/print.c
index 03b5eadfa..7d2d16086 100644
--- a/src/print.c
+++ b/src/print.c
@@ -31,7 +31,6 @@ MRB_API void
mrb_print_error(mrb_state *mrb)
{
mrb_print_backtrace(mrb);
- printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr);
}
MRB_API void