=begin
Hi,
At Mon, 8 Dec 2008 18:23:04 +0900,
Roger Pack wrote in [ruby-core:20416]:
This patch adds output to unrescued exceptions' output to the command line:
Rereading from scripts would have problems:
- they can be removed or changed
- -e and stdin are N/A
- slow.
Instead, isn't it enough only when debugging?
$ ./ruby -rtracer -e 'def foo;raise;end' -e foo
-e:1:in foo': unhandled exception foo from -e:2:in
'
Index: error.c
--- error.c (revision 20580)
+++ error.c (working copy)
@@ -510,16 +510,31 @@ rb_check_backtrace(VALUE bt)
long i;
static const char err[] = "backtrace must be Array of String";
- int t = TYPE(bt);
-
- if (t == T_STRING) return rb_ary_new3(1, bt);
- if (t != T_ARRAY) {
- if (IMMEDIATE_P(bt)) {
-
rb_raise(rb_eTypeError, err);
- }
- switch (BUILTIN_TYPE(bt)) {
- case T_STRING:
-
return rb_ary_new3(1, bt);
- case T_ARRAY:
-
break;
- case T_STRUCT:
-
if (CLASS_OF(bt) == rb_cBacktrace)
-
return rb_ary_new3(1, bt);
- default:
rb_raise(rb_eTypeError, err);
}
for (i=0;i<RARRAY_LEN(bt);i++) {
-
VALUE a = RARRAY_PTR(bt)[i];
-
if (!IMMEDIATE_P(a)) {
-
switch (BUILTIN_TYPE(a)) {
-
case T_STRING: continue;
-
case T_STRUCT:
-
if (CLASS_OF(a) == rb_cBacktrace) continue;
-
}
}
-
rb_raise(rb_eTypeError, err);
}
}
Index: eval_error.c
===================================================================
--- eval_error.c (revision 20580)
+++ eval_error.c (working copy)
@@ -64,4 +64,25 @@ set_backtrace(VALUE info, VALUE bt)
}
+static void
+print_debug_line(VALUE *debug_lines, VALUE at)
+{
- extern VALUE rb_cBacktrace;
- VALUE hash = *debug_lines, lines, line, *p;
-
- if (TYPE(at) != T_STRUCT || CLASS_OF(at) != rb_cBacktrace) return;
- if (!hash) {
- if (!rb_const_defined_at(rb_cObject, rb_intern("SCRIPT_LINES__"))) return;
- hash = rb_const_get_at(rb_cObject, rb_intern("SCRIPT_LINES__"));
- if (TYPE(hash) != T_HASH) return;
- *debug_lines = hash;
- }
- p = RSTRUCT_PTR(at);
- lines = rb_hash_lookup(hash, p[0]);
- if (NIL_P(lines)) return;
- line = rb_ary_entry(lines, NUM2INT(p[1]));
- if (NIL_P(line)) return;
- warn_printf("\t\t %s", RSTRING_PTR(line));
+}
-
static void
error_print(void)
@@ -72,4 +93,5 @@ error_print(void)
const char *einfo;
long elen;
-
VALUE debug_lines = 0;
if (NIL_P(errinfo))
@@ -99,4 +121,5 @@ error_print(void)
VALUE mesg = RARRAY_PTR(errat)[0];
-
mesg = rb_check_string_type(mesg);
if (NIL_P(mesg))
error_pos();
@@ -121,4 +144,7 @@ error_print(void)
if (eclass == rb_eRuntimeError && elen == 0) {
warn_print(": unhandled exception\n");
-
if (!NIL_P(errat)) {
-
print_debug_line(&debug_lines, RARRAY_PTR(errat)[0]);
-
}
}
else {
@@ -166,6 +192,9 @@ error_print(void)
for (i = 1; i < len; i++) {
-
VALUE a = ptr[i], s;
-
s = rb_check_string_type(a);
-
if (!NIL_P(s)) {
-
warn_printf("\tfrom %s\n", RSTRING_PTR(s));
-
print_debug_line(&debug_lines, a);
}
if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
Index: vm.c¶
--- vm.c (revision 20580)
+++ vm.c (working copy)
@@ -33,4 +33,5 @@ VALUE rb_cThread;
VALUE rb_cEnv;
VALUE rb_mRubyVMFrozenCore;
+VALUE rb_cBacktrace;
VALUE ruby_vm_global_state_version = 1;
@@ -629,4 +630,22 @@ rb_lastline_set(VALUE val)
/* backtrace */
+static VALUE
+backtrace_to_str(VALUE self)
+{
- VALUE *p = RSTRUCT_PTR(self);
- VALUE file = p[0], line = p[1], name = p[2];
- VALUE str = p[3];
- if (NIL_P(str)) {
- str = rb_sprintf("%s:%d:in `%s'",
-
NIL_P(file) ? "" : StringValueCStr(file),
-
NUM2INT(line), StringValueCStr(name));
- if (!OBJ_FROZEN(self) &&
-
(OBJ_UNTRUSTED(self) || rb_safe_level() < 4)) {
-
p[3] = str;
- }
- }
- return str;
+}
-
int
vm_get_sourceline(const rb_control_frame_t *cfp)
@@ -654,10 +673,10 @@ static VALUE
vm_backtrace_each(rb_thread_t *th,
const rb_control_frame_t *limit_cfp, const rb_control_frame_t *cfp,
{
-
str = 0;
if (cfp->iseq != 0) {
if (cfp->pc != 0) {
@@ -665,15 +684,17 @@ vm_backtrace_each(rb_thread_t *th,
line_no = vm_get_sourceline(cfp);
-
file = RSTRING_PTR(iseq->filename);
-
str = rb_sprintf("%s:%d:in `%s'",
-
file, line_no, RSTRING_PTR(iseq->name));
-
rb_ary_push(ary, str);
-
b[0] = Qnil;
-
b[1] = INT2FIX(0);
-
b[2] = rb_id2str(cfp->method_id);
-
bt = rb_class_new_instance(sizeof(b) / sizeof(*b), b, rb_cBacktrace);
-
rb_ary_push(ary, bt);
}
cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
@@ -704,6 +725,5 @@ vm_backtrace(rb_thread_t *th, int lev)
}
- ary = vm_backtrace_each(th, RUBY_VM_NEXT_CONTROL_FRAME(cfp),
-
top_of_cfp, "", 0, ary);
-
ary = vm_backtrace_each(th, RUBY_VM_NEXT_CONTROL_FRAME(cfp), top_of_cfp, ary);
return ary;
}
@@ -1847,4 +1867,9 @@ Init_VM(void)
rb_define_const(rb_cRubyVM, "INSTRUCTION_NAMES", ruby_insns_name_array());
-
rb_cBacktrace = rb_struct_define((char*)0, "file", "line", "name", "str", (char*)0);
-
rb_define_const(rb_cRubyVM, "Backtrace", rb_cBacktrace);
-
rb_define_method(rb_cBacktrace, "to_str", backtrace_to_str, 0);
-
rb_define_method(rb_cBacktrace, "inspect", backtrace_to_str, 0);
-
/* debug functions ::VM::SDR(), ::VM::NSDR() */
#if VMDEBUG
--
Nobu Nakada
=end