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:
parent
dbd4c4a7b3
commit
5318154fe1
3 changed files with 72 additions and 45 deletions
92
eval_error.c
92
eval_error.c
|
@ -72,33 +72,14 @@ 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);
|
||||
|
||||
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 (emesg != Qundef) {
|
||||
if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
|
||||
NIL_P(mesg = RARRAY_AREF(errat, 0))) {
|
||||
error_pos();
|
||||
|
@ -108,18 +89,12 @@ rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
|
|||
warn_print(": ");
|
||||
}
|
||||
|
||||
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);
|
||||
if (!NIL_P(emesg)) {
|
||||
einfo = RSTRING_PTR(emesg);
|
||||
elen = RSTRING_LEN(emesg);
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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
8
io.c
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue