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);
|
rb_threadptr_error_print(th, th->errinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
|
print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg)
|
||||||
{
|
{
|
||||||
volatile VALUE errat = Qundef;
|
const char *einfo = "";
|
||||||
volatile int raised_flag = th->raised_flag;
|
long elen = 0;
|
||||||
volatile VALUE eclass = Qundef, e = Qundef;
|
|
||||||
const char *volatile einfo;
|
|
||||||
volatile long elen;
|
|
||||||
VALUE mesg;
|
VALUE mesg;
|
||||||
|
|
||||||
if (NIL_P(errinfo))
|
if (emesg != Qundef) {
|
||||||
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 (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
|
if (NIL_P(errat) || RARRAY_LEN(errat) == 0 ||
|
||||||
NIL_P(mesg = RARRAY_AREF(errat, 0))) {
|
NIL_P(mesg = RARRAY_AREF(errat, 0))) {
|
||||||
error_pos();
|
error_pos();
|
||||||
|
@ -108,18 +89,12 @@ rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
|
||||||
warn_print(": ");
|
warn_print(": ");
|
||||||
}
|
}
|
||||||
|
|
||||||
eclass = CLASS_OF(errinfo);
|
if (!NIL_P(emesg)) {
|
||||||
if (eclass != Qundef &&
|
einfo = RSTRING_PTR(emesg);
|
||||||
(e = rb_check_funcall(errinfo, rb_intern("message"), 0, 0)) != Qundef &&
|
elen = RSTRING_LEN(emesg);
|
||||||
(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) {
|
if (eclass == rb_eRuntimeError && elen == 0) {
|
||||||
warn_print("unhandled exception\n");
|
warn_print("unhandled exception\n");
|
||||||
}
|
}
|
||||||
|
@ -141,19 +116,23 @@ rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo)
|
||||||
len = tail - einfo;
|
len = tail - einfo;
|
||||||
tail++; /* skip newline */
|
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) {
|
if (epath) {
|
||||||
warn_print(" (");
|
warn_print(" (");
|
||||||
warn_print_str(epath);
|
warn_print_str(epath);
|
||||||
warn_print(")\n");
|
warn_print(")\n");
|
||||||
}
|
}
|
||||||
if (tail) {
|
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);
|
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)) {
|
if (!NIL_P(errat)) {
|
||||||
long i;
|
long i;
|
||||||
long len = RARRAY_LEN(errat);
|
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
|
#define TRACE_TAIL 5
|
||||||
|
|
||||||
for (i = 1; i < len; i++) {
|
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)) {
|
if (RB_TYPE_P(line, T_STRING)) {
|
||||||
warn_print_str(rb_sprintf("\tfrom %"PRIsVALUE"\n", line));
|
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:
|
error:
|
||||||
TH_POP_TAG();
|
TH_POP_TAG();
|
||||||
th->errinfo = errinfo;
|
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);
|
void rb_stdio_set_default_encoding(void);
|
||||||
VALUE rb_io_flush_raw(VALUE, int);
|
VALUE rb_io_flush_raw(VALUE, int);
|
||||||
size_t rb_io_memsize(const rb_io_t *);
|
size_t rb_io_memsize(const rb_io_t *);
|
||||||
|
int rb_stderr_tty_p(void);
|
||||||
|
|
||||||
/* load.c */
|
/* load.c */
|
||||||
VALUE rb_get_load_path(void);
|
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
|
static void
|
||||||
must_respond_to(ID mid, VALUE val, ID id)
|
must_respond_to(ID mid, VALUE val, ID id)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue