ruby-changes:45612
From: nobu <ko1@a...>
Date: Wed, 22 Feb 2017 17:50:32 +0900 (JST)
Subject: [ruby-changes:45612] nobu:r57685 (trunk): eval_error.c: backstrace in reverse order
nobu 2017-02-22 17:50:25 +0900 (Wed, 22 Feb 2017) New Revision: 57685 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57685 Log: eval_error.c: backstrace in reverse order * eval_error.c (rb_threadptr_error_print): print backtrace and error message in reverse order if STDERR is unchanged and a tty. [Feature #8661] Modified files: trunk/eval_error.c trunk/internal.h trunk/io.c Index: eval_error.c =================================================================== --- eval_error.c (revision 57684) +++ eval_error.c (revision 57685) @@ -72,54 +72,29 @@ error_print(rb_thread_t *th) https://github.com/ruby/ruby/blob/trunk/eval_error.c#L72 rb_threadptr_error_print(th, th->errinfo); } -void -rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo) +static void +print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg) { - volatile VALUE errat = Qundef; - volatile int raised_flag = th->raised_flag; - volatile VALUE eclass = Qundef, e = Qundef; - const char *volatile einfo; - volatile long elen; + const char *einfo = ""; + long elen = 0; VALUE mesg; - if (NIL_P(errinfo)) - return; - rb_thread_raised_clear(th); + if (emesg != Qundef) { + if (NIL_P(errat) || RARRAY_LEN(errat) == 0 || + NIL_P(mesg = RARRAY_AREF(errat, 0))) { + error_pos(); + } + else { + warn_print_str(mesg); + warn_print(": "); + } - TH_PUSH_TAG(th); - if (TH_EXEC_TAG() == 0) { - errat = rb_get_backtrace(errinfo); - } - else if (errat == Qundef) { - errat = Qnil; - } - else if (eclass == Qundef || e != Qundef) { - goto error; - } - else { - goto no_message; - } - if (NIL_P(errat) || RARRAY_LEN(errat) == 0 || - NIL_P(mesg = RARRAY_AREF(errat, 0))) { - error_pos(); - } - else { - warn_print_str(mesg); - warn_print(": "); + if (!NIL_P(emesg)) { + einfo = RSTRING_PTR(emesg); + elen = RSTRING_LEN(emesg); + } } - eclass = CLASS_OF(errinfo); - if (eclass != Qundef && - (e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0)) != Qundef && - (RB_TYPE_P(e, T_STRING) || !NIL_P(e = rb_check_string_type(e)))) { - einfo = RSTRING_PTR(e); - elen = RSTRING_LEN(e); - } - else { - no_message: - einfo = ""; - elen = 0; - } if (eclass == rb_eRuntimeError && elen == 0) { warn_print("unhandled exception\n"); } @@ -141,19 +116,23 @@ rb_threadptr_error_print(rb_thread_t *vo https://github.com/ruby/ruby/blob/trunk/eval_error.c#L116 len = tail - einfo; tail++; /* skip newline */ } - warn_print_str(tail ? rb_str_subseq(e, 0, len) : e); + warn_print_str(tail ? rb_str_subseq(emesg, 0, len) : emesg); if (epath) { warn_print(" ("); warn_print_str(epath); warn_print(")\n"); } if (tail) { - warn_print_str(rb_str_subseq(e, tail - einfo, elen - len - 1)); + warn_print_str(rb_str_subseq(emesg, tail - einfo, elen - len - 1)); } if (tail ? einfo[elen-1] != '\n' : !epath) warn_print2("\n", 1); } } +} +static void +print_backtrace(const VALUE eclass, const VALUE errat, int reverse) +{ if (!NIL_P(errat)) { long i; long len = RARRAY_LEN(errat); @@ -164,7 +143,7 @@ rb_threadptr_error_print(rb_thread_t *vo https://github.com/ruby/ruby/blob/trunk/eval_error.c#L143 #define TRACE_TAIL 5 for (i = 1; i < len; i++) { - VALUE line = RARRAY_AREF(errat, i); + VALUE line = RARRAY_AREF(errat, reverse ? len - i : i); if (RB_TYPE_P(line, T_STRING)) { warn_print_str(rb_sprintf("\tfrom %"PRIsVALUE"\n", line)); } @@ -175,6 +154,45 @@ rb_threadptr_error_print(rb_thread_t *vo https://github.com/ruby/ruby/blob/trunk/eval_error.c#L154 } } } +} + +void +rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo) +{ + volatile VALUE errat = Qundef; + volatile int raised_flag = th->raised_flag; + volatile VALUE eclass = Qundef, emesg = Qundef; + + if (NIL_P(errinfo)) + return; + rb_thread_raised_clear(th); + + TH_PUSH_TAG(th); + if (TH_EXEC_TAG() == 0) { + errat = rb_get_backtrace(errinfo); + } + else 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) { + if (!RB_TYPE_P(e, T_STRING)) e = rb_check_string_type(e); + emesg = e; + } + } + if (rb_stderr_tty_p()) { + if (0) warn_print("Traceback (most recent call last):\n"); + print_backtrace(eclass, errat, TRUE); + print_errinfo(eclass, errat, emesg); + } + else { + print_errinfo(eclass, errat, emesg); + print_backtrace(eclass, errat, FALSE); + } error: TH_POP_TAG(); th->errinfo = errinfo; Index: io.c =================================================================== --- io.c (revision 57684) +++ io.c (revision 57685) @@ -7400,6 +7400,14 @@ rb_write_error_str(VALUE mesg) https://github.com/ruby/ruby/blob/trunk/io.c#L7400 } } +int +rb_stderr_tty_p(void) +{ + if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) + return isatty(fileno(stderr)); + return 0; +} + static void must_respond_to(ID mid, VALUE val, ID id) { Index: internal.h =================================================================== --- internal.h (revision 57684) +++ internal.h (revision 57685) @@ -1193,6 +1193,7 @@ ssize_t rb_io_bufread(VALUE io, void *bu https://github.com/ruby/ruby/blob/trunk/internal.h#L1193 void rb_stdio_set_default_encoding(void); VALUE rb_io_flush_raw(VALUE, int); size_t rb_io_memsize(const rb_io_t *); +int rb_stderr_tty_p(void); /* load.c */ VALUE rb_get_load_path(void); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/