1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57685 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-02-22 08:50:25 +00:00
parent dbd4c4a7b3
commit 5318154fe1
3 changed files with 72 additions and 45 deletions

View file

@ -72,54 +72,29 @@ error_print(rb_thread_t *th)
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 *volatile th, volatile VALUE errinfo)
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 *volatile th, volatile VALUE errinfo)
#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 *volatile th, volatile VALUE errinfo)
}
}
}
}
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;

View file

@ -1193,6 +1193,7 @@ ssize_t rb_io_bufread(VALUE io, void *buf, size_t size);
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);

8
io.c
View file

@ -7400,6 +7400,14 @@ rb_write_error_str(VALUE mesg)
}
}
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)
{