diff options
Diffstat (limited to 'src/error.c')
| -rw-r--r-- | src/error.c | 111 |
1 files changed, 25 insertions, 86 deletions
diff --git a/src/error.c b/src/error.c index 2201fc840..062282719 100644 --- a/src/error.c +++ b/src/error.c @@ -47,7 +47,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) mrb_int argc; mrb_value *argv; - if (mrb_get_args(mrb, "|o*", &mesg, &argv, &argc) >= 1) { + if (mrb_get_args(mrb, "|o*!", &mesg, &argv, &argc) >= 1) { mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); } return exc; @@ -62,7 +62,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) * With no argument, or if the argument is the same as the receiver, * return the receiver. Otherwise, create a new * exception object of the same class as the receiver, but with a - * message equal to <code>string.to_str</code>. + * message equal to <code>string</code>. * */ @@ -111,9 +111,7 @@ exc_to_s(mrb_state *mrb, mrb_value exc) * exception.message -> string * * Returns the result of invoking <code>exception.to_s</code>. - * Normally this returns the exception's message or name. By - * supplying a to_str method, exceptions are agreeing to - * be used where Strings are expected. + * Normally this returns the exception's message or name. */ static mrb_value @@ -137,6 +135,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) { mrb_value str, mesg, file, line; mrb_bool append_mesg; + const char *cname; mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file")); @@ -148,57 +147,23 @@ exc_inspect(mrb_state *mrb, mrb_value exc) append_mesg = RSTRING_LEN(mesg) > 0; } + cname = mrb_obj_classname(mrb, exc); + str = mrb_str_new_cstr(mrb, cname); if (mrb_string_p(file) && mrb_fixnum_p(line)) { - char buf[32]; - - str = mrb_str_dup(mrb, file); - snprintf(buf, sizeof(buf), ":%" MRB_PRId ": ", mrb_fixnum(line)); - mrb_str_cat_cstr(mrb, str, buf); if (append_mesg) { - mrb_str_cat_str(mrb, str, mesg); - mrb_str_cat_lit(mrb, str, " ("); + str = mrb_format(mrb, "%S:%S: %S (%S)", file, line, mesg, str); } - mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); - if (append_mesg) { - mrb_str_cat_lit(mrb, str, ")"); + else { + str = mrb_format(mrb, "%S:%S: %S", file, line, str); } } - else { - const char *cname = mrb_obj_classname(mrb, exc); - str = mrb_str_new_cstr(mrb, cname); - if (append_mesg) { - mrb_str_cat_lit(mrb, str, ": "); - mrb_str_cat_str(mrb, str, mesg); - } + else if (append_mesg) { + str = mrb_format(mrb, "%S: %S", str, mesg); } return str; } -void mrb_save_backtrace(mrb_state *mrb); -mrb_value mrb_restore_backtrace(mrb_state *mrb); - -static mrb_value -exc_get_backtrace(mrb_state *mrb, mrb_value exc) -{ - mrb_sym attr_name; - mrb_value backtrace; - - attr_name = mrb_intern_lit(mrb, "backtrace"); - backtrace = mrb_iv_get(mrb, exc, attr_name); - if (mrb_nil_p(backtrace)) { - if (mrb_obj_ptr(exc) == mrb->backtrace.exc && mrb->backtrace.n > 0) { - backtrace = mrb_restore_backtrace(mrb); - mrb->backtrace.n = 0; - mrb->backtrace.exc = 0; - } - else { - backtrace = mrb_exc_backtrace(mrb, exc); - } - mrb_iv_set(mrb, exc, attr_name, backtrace); - } - - return backtrace; -} +void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc); static void set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace) @@ -235,7 +200,6 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) mrb_callinfo *ci = mrb->c->ci; mrb_code *pc = ci->pc; - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value((mrb_int)(ci - mrb->c->cibase))); while (ci >= mrb->c->cibase) { mrb_code *err = ci->err; @@ -256,41 +220,18 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) } } -static mrb_bool -have_backtrace(mrb_state *mrb, struct RObject *exc) -{ - return !mrb_nil_p(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "backtrace"))); -} - void mrb_exc_set(mrb_state *mrb, mrb_value exc) { - if (!mrb->gc.out_of_memory && mrb->backtrace.n > 0) { - mrb_value target_exc = mrb_nil_value(); - int ai; - - ai = mrb_gc_arena_save(mrb); - if ((mrb->exc && !have_backtrace(mrb, mrb->exc))) { - target_exc = mrb_obj_value(mrb->exc); - } - else if (!mrb_nil_p(exc) && mrb->backtrace.exc) { - target_exc = mrb_obj_value(mrb->backtrace.exc); - mrb_gc_protect(mrb, target_exc); - } - if (!mrb_nil_p(target_exc)) { - mrb_value backtrace; - backtrace = mrb_restore_backtrace(mrb); - set_backtrace(mrb, target_exc, backtrace); - } - mrb_gc_arena_restore(mrb, ai); - } - - mrb->backtrace.n = 0; if (mrb_nil_p(exc)) { mrb->exc = 0; } else { mrb->exc = mrb_obj_ptr(exc); + if (!mrb->gc.out_of_memory) { + exc_debug_info(mrb, mrb->exc); + mrb_keep_backtrace(mrb, exc); + } } } @@ -301,10 +242,6 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc) mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); } mrb_exc_set(mrb, exc); - if (!mrb->gc.out_of_memory) { - exc_debug_info(mrb, mrb->exc); - mrb_save_backtrace(mrb); - } if (!mrb->jmp) { mrb_p(mrb, exc); abort(); @@ -535,7 +472,7 @@ mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, void mrb_init_exception(mrb_state *mrb) { - struct RClass *exception, *runtime_error, *script_error, *stack_error; + struct RClass *exception, *script_error, *stack_error, *nomem_error; mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION); @@ -545,17 +482,19 @@ mrb_init_exception(mrb_state *mrb) mrb_define_method(mrb, exception, "to_s", 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", exc_get_backtrace, MRB_ARGS_NONE()); + mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1)); mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ - runtime_error = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ - mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, runtime_error, "Out of memory")); -#ifdef MRB_GC_FIXED_ARENA - mrb->arena_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, runtime_error, "arena overflow error")); -#endif + mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ stack_error = mrb_define_class(mrb, "SystemStackError", exception); mrb->stack_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, stack_error, "stack level too deep")); + + nomem_error = mrb_define_class(mrb, "NoMemoryError", exception); + mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "Out of memory")); +#ifdef MRB_GC_FIXED_ARENA + mrb->arena_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "arena overflow error")); +#endif } |
