diff options
author | sorah <sorah@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-12 11:47:16 +0000 |
---|---|---|
committer | sorah <sorah@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-12 11:47:16 +0000 |
commit | 0d7718896cfb629ad823b9ca5004465ef2063ab8 (patch) | |
tree | 764655a01a2038af09ef45f4ae5fbeb0ff31ce42 /eval_error.c | |
parent | 838f23ae34a634f3bbe39d27b861abc8dd853762 (diff) |
error.c(exc_full_message): Exception#full_message
Add a method to retrieve a String expression of an exception,
formatted in the same way that Ruby prints an uncaught exception out.
[Feature #14141]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61154 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval_error.c')
-rw-r--r-- | eval_error.c | 127 |
1 files changed, 74 insertions, 53 deletions
diff --git a/eval_error.c b/eval_error.c index 4c79bf044e..f602737dd2 100644 --- a/eval_error.c +++ b/eval_error.c @@ -4,25 +4,38 @@ */ #ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P +#define write_warn(str, x) RB_GNUC_EXTENSION_BLOCK( \ + NIL_P(str) ? \ + warn_print(x) : ( \ + (__builtin_constant_p(x)) ? \ + rb_str_concat((str), rb_str_new((x), (long)strlen(x))) : \ + rb_str_concat((str), rb_str_new2(x)) \ + ) \ + ) #define warn_print(x) RB_GNUC_EXTENSION_BLOCK( \ (__builtin_constant_p(x)) ? \ rb_write_error2((x), (long)strlen(x)) : \ rb_write_error(x) \ ) #else +#define write_warn(str, x) NIL_P(str) ? rb_write_error((x)) : rb_str_concat((str), rb_str_new2(x)) #define warn_print(x) rb_write_error(x) #endif + +#define write_warn2(str,x,l) NIL_P(str) ? warn_print2(x,l) : rb_str_concat((str), rb_str_new((x),(l))) #define warn_print2(x,l) rb_write_error2((x),(l)) + +#define write_warn_str(str,x) NIL_P(str) ? rb_write_error_str(x) : rb_str_concat((str), (x)) #define warn_print_str(x) rb_write_error_str(x) static VALUE error_pos_str(void); static void -error_pos(void) +error_pos(const VALUE str) { - VALUE str = error_pos_str(); - if (!NIL_P(str)) { - warn_print_str(str); + VALUE pos = error_pos_str(); + if (!NIL_P(pos)) { + write_warn_str(str, pos); } } @@ -73,7 +86,7 @@ error_print(rb_execution_context_t *ec) } static void -print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, int colored) +print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VALUE str, int colored) { static const char underline[] = "\033[4;1m"; static const char bold[] = "\033[1m"; @@ -85,14 +98,14 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, int colo if (emesg != Qundef) { if (NIL_P(errat) || RARRAY_LEN(errat) == 0 || NIL_P(mesg = RARRAY_AREF(errat, 0))) { - error_pos(); + error_pos(str); } else { - warn_print_str(mesg); - warn_print(": "); + write_warn_str(str, mesg); + write_warn(str, ": "); } - if (colored) warn_print(bold); + if (colored) write_warn(str, bold); if (!NIL_P(emesg)) { einfo = RSTRING_PTR(emesg); @@ -101,17 +114,17 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, int colo } if (eclass == rb_eRuntimeError && elen == 0) { - if (colored) warn_print(underline); - warn_print("unhandled exception\n"); + if (colored) write_warn(str, underline); + write_warn(str, "unhandled exception\n"); } else { VALUE epath; epath = rb_class_name(eclass); if (elen == 0) { - if (colored) warn_print(underline); - warn_print_str(epath); - warn_print("\n"); + if (colored) write_warn(str, underline); + write_warn_str(str, epath); + write_warn(str, "\n"); } else { const char *tail = 0; @@ -123,26 +136,26 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, int colo len = tail - einfo; tail++; /* skip newline */ } - warn_print_str(tail ? rb_str_subseq(emesg, 0, len) : emesg); + write_warn_str(str, tail ? rb_str_subseq(emesg, 0, len) : emesg); if (epath) { - warn_print(" ("); - if (colored) warn_print(underline); - warn_print_str(epath); - if (colored) warn_print(reset); - if (colored) warn_print(bold); - warn_print(")\n"); + write_warn(str, " ("); + if (colored) write_warn(str, underline); + write_warn_str(str, epath); + if (colored) write_warn(str, reset); + if (colored) write_warn(str, bold); + write_warn(str, ")\n"); } if (tail) { - warn_print_str(rb_str_subseq(emesg, tail - einfo, elen - len - 1)); + write_warn_str(str, rb_str_subseq(emesg, tail - einfo, elen - len - 1)); } - if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1); + if (tail ? einfo[elen-1] != '\n' : !epath) write_warn2(str, "\n", 1); } } - if (colored) warn_print(reset); + if (colored) write_warn(str, reset); } static void -print_backtrace(const VALUE eclass, const VALUE errat, int reverse) +print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reverse) { if (!NIL_P(errat)) { long i; @@ -161,12 +174,12 @@ print_backtrace(const VALUE eclass, const VALUE errat, int reverse) for (i = 1; i < len; i++) { VALUE line = RARRAY_AREF(errat, reverse ? len - i : i); if (RB_TYPE_P(line, T_STRING)) { - VALUE str = rb_str_new_cstr("\t"); - if (reverse) rb_str_catf(str, "%*ld: ", width, len - i); - warn_print_str(rb_str_catf(str, "from %"PRIsVALUE"\n", line)); + VALUE bt = rb_str_new_cstr("\t"); + if (reverse) rb_str_catf(bt, "%*ld: ", width, len - i); + write_warn_str(str, rb_str_catf(bt, "from %"PRIsVALUE"\n", line)); } if (skip && i == TRACE_HEAD && len > TRACE_MAX) { - warn_print_str(rb_sprintf("\t ... %ld levels...\n", + write_warn_str(str, rb_sprintf("\t ... %ld levels...\n", len - TRACE_HEAD - TRACE_TAIL)); i = len - TRACE_TAIL; } @@ -175,26 +188,16 @@ print_backtrace(const VALUE eclass, const VALUE errat, int reverse) } void -rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) +rb_ec_error_write(volatile VALUE errinfo, volatile VALUE errat, volatile VALUE str) { - volatile VALUE errat = Qundef; - volatile int raised_flag = ec->raised_flag; volatile VALUE eclass = Qundef, emesg = Qundef; if (NIL_P(errinfo)) return; - rb_ec_raised_clear(ec); - EC_PUSH_TAG(ec); - if (EC_EXEC_TAG() == TAG_NONE) { - errat = rb_get_backtrace(errinfo); - } - else if (errat == Qundef) { + if (errat == Qundef) { errat = Qnil; } - else if (eclass == Qundef || emesg != Qundef) { - goto error; - } if ((eclass = CLASS_OF(errinfo)) != Qundef) { VALUE e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0); if (e != Qundef) { @@ -203,15 +206,33 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) } } if (rb_stderr_tty_p()) { - warn_print("\033[1mTraceback \033[m(most recent call last):\n"); - print_backtrace(eclass, errat, TRUE); - print_errinfo(eclass, errat, emesg, TRUE); + write_warn(str, "\033[1mTraceback \033[m(most recent call last):\n"); + print_backtrace(eclass, errat, str, TRUE); + print_errinfo(eclass, errat, emesg, str, TRUE); } else { - print_errinfo(eclass, errat, emesg, FALSE); - print_backtrace(eclass, errat, FALSE); + print_errinfo(eclass, errat, emesg, str, FALSE); + print_backtrace(eclass, errat, str, FALSE); } - error: +} + +void +rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo) +{ + volatile int raised_flag = ec->raised_flag; + volatile VALUE errat; + + if (NIL_P(errinfo)) + return; + rb_ec_raised_clear(ec); + + EC_PUSH_TAG(ec); + if (EC_EXEC_TAG() == TAG_NONE) { + errat = rb_get_backtrace(errinfo); + } + + rb_ec_error_write(errinfo, errat, Qnil); + EC_POP_TAG(); ec->errinfo = errinfo; rb_ec_raised_set(ec, raised_flag); @@ -290,28 +311,28 @@ error_handle(int ex) break; case TAG_RETURN: - error_pos(); + error_pos(Qnil); warn_print("unexpected return\n"); break; case TAG_NEXT: - error_pos(); + error_pos(Qnil); warn_print("unexpected next\n"); break; case TAG_BREAK: - error_pos(); + error_pos(Qnil); warn_print("unexpected break\n"); break; case TAG_REDO: - error_pos(); + error_pos(Qnil); warn_print("unexpected redo\n"); break; case TAG_RETRY: - error_pos(); + error_pos(Qnil); warn_print("retry outside of rescue clause\n"); break; case TAG_THROW: /* TODO: fix me */ - error_pos(); + error_pos(Qnil); warn_print("unexpected throw\n"); break; case TAG_RAISE: { |