[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]