summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--error.c3
-rw-r--r--eval.c118
3 files changed, 79 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 32d53da55c..415e99ca5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Sun Nov 16 04:41:33 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (eval): do not re-raise exception to avoid unnecessary
+ exception copying, instead modify exception and internal
+ information to adjust eval().
+
+ * eval.c (backtrace): can return the current frame information
+ only if lev < -1.
+
Sat Nov 15 22:16:42 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* /ext/openssl/ossl_x509ext.c (ossl_x509extfactory_create_ext):
diff --git a/error.c b/error.c
index 2baf3b1ba7..b5b14decae 100644
--- a/error.c
+++ b/error.c
@@ -479,8 +479,9 @@ name_err_initialize(argc, argv, self)
VALUE *argv;
VALUE self;
{
- VALUE name = (argc > 1) ? argv[--argc] : Qnil;
+ VALUE name;
+ name = (argc > 1) ? argv[--argc] : Qnil;
exc_initialize(argc, argv, self);
rb_iv_set(self, "name", name);
return self;
diff --git a/eval.c b/eval.c
index 64fa28bd98..4d3fd66b7f 100644
--- a/eval.c
+++ b/eval.c
@@ -1328,7 +1328,6 @@ void rb_exec_end_proc _((void));
static void
ruby_finalize_0()
{
- ruby_errinfo = 0;
PUSH_TAG(PROT_NONE);
if (EXEC_TAG() == 0) {
rb_trap_exit();
@@ -4720,6 +4719,58 @@ static int last_call_status;
#define CSTAT_SUPER 8
static VALUE
+name_err_to_s(exc)
+ VALUE exc;
+{
+ VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
+ ID id_recv = rb_intern("recv");
+
+ if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc));
+ if (rb_ivar_defined(exc, id_recv)) {
+ char buf[BUFSIZ];
+ char *desc = "";
+ volatile VALUE d = 0;
+ int noclass;
+ VALUE obj = rb_ivar_get(exc, id_recv);
+ int state;
+
+ switch (TYPE(obj)) {
+ case T_NIL:
+ desc = "nil";
+ break;
+ case T_TRUE:
+ desc = "true";
+ break;
+ case T_FALSE:
+ desc = "false";
+ break;
+ default:
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ d = rb_inspect(obj);
+ }
+ POP_TAG();
+ if (!d || RSTRING(d)->len > 65) {
+ d = rb_any_to_s(obj);
+ }
+ break;
+ }
+ if (d) {
+ desc = RSTRING(d)->ptr;
+ }
+ noclass = (!desc || desc[0]=='#');
+ snprintf(buf, BUFSIZ, RSTRING(mesg)->ptr, desc,
+ noclass ? "" : ":",
+ noclass ? "" : rb_obj_classname(obj));
+ mesg = rb_str_new2(buf);
+ rb_iv_set(exc, "mesg", mesg);
+ st_delete(ROBJECT(exc)->iv_tbl, (st_data_t*)&id_recv, 0);
+ }
+ if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
+ return mesg;
+}
+
+static VALUE
rb_method_missing(argc, argv, obj)
int argc;
VALUE *argv;
@@ -4727,11 +4778,8 @@ rb_method_missing(argc, argv, obj)
{
ID id;
VALUE exc = rb_eNoMethodError;
- volatile VALUE d = 0;
char *format = 0;
- char *desc = "";
NODE *cnode = ruby_current_node;
- int state;
if (argc == 0 || !SYMBOL_P(argv[0])) {
rb_raise(rb_eArgError, "no id given");
@@ -4741,64 +4789,37 @@ rb_method_missing(argc, argv, obj)
id = SYM2ID(argv[0]);
- switch (TYPE(obj)) {
- case T_NIL:
- desc = "nil";
- break;
- case T_TRUE:
- desc = "true";
- break;
- case T_FALSE:
- desc = "false";
- break;
- default:
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- d = rb_inspect(obj);
- }
- POP_TAG();
- if (!d || RSTRING(d)->len > 65) {
- d = rb_any_to_s(obj);
- }
- break;
- }
- if (d) {
- desc = RSTRING(d)->ptr;
- }
-
if (last_call_status & CSTAT_PRIV) {
- format = "private method `%s' called for %s%s%s";
+ format = "private method `%s' called for %%s%%s%%s";
}
else if (last_call_status & CSTAT_PROT) {
- format = "protected method `%s' called for %s%s%s";
+ format = "protected method `%s' called for %%s%%s%%s";
}
else if (last_call_status & CSTAT_VCALL) {
- format = "undefined local variable or method `%s' for %s%s%s";
+ format = "undefined local variable or method `%s' for %%s%%s%%s";
exc = rb_eNameError;
}
else if (last_call_status & CSTAT_SUPER) {
format = "super: no superclass method `%s'";
}
if (!format) {
- format = "undefined method `%s' for %s%s%s";
+ format = "undefined method `%s' for %%s%%s%%s";
}
ruby_current_node = cnode;
{
char buf[BUFSIZ];
- int noclass = (!desc || desc[0]=='#');
int n = 0;
VALUE args[3];
- snprintf(buf, BUFSIZ, format, rb_id2name(id),
- desc, noclass ? "" : ":",
- noclass ? "" : rb_obj_classname(obj));
+ snprintf(buf, BUFSIZ, format, rb_id2name(id));
args[n++] = rb_str_new2(buf);
args[n++] = argv[0];
if (exc == rb_eNoMethodError) {
args[n++] = rb_ary_new4(argc-1, argv+1);
}
exc = rb_class_new_instance(n, args, exc);
+ rb_iv_set(exc, "recv", obj);
ruby_frame = ruby_frame->prev; /* pop frame for "method_missing" */
rb_exc_raise(exc);
}
@@ -5357,6 +5378,7 @@ backtrace(lev)
snprintf(buf, BUFSIZ, "%s:%d", ruby_sourcefile, ruby_sourceline);
}
rb_ary_push(ary, rb_str_new2(buf));
+ if (lev < -1) return ary;
}
else {
while (lev-- > 0) {
@@ -5557,20 +5579,13 @@ eval(self, src, scope, file, line)
ruby_set_current_source();
if (state) {
if (state == TAG_RAISE) {
- VALUE err, errat, mesg;
-
- mesg = rb_obj_as_string(ruby_errinfo);
if (strcmp(file, "(eval)") == 0) {
- if (ruby_sourceline > 1) {
- errat = get_backtrace(ruby_errinfo);
- err = rb_str_dup(RARRAY(errat)->ptr[0]);
- rb_str_cat2(err, ": ");
- rb_str_append(err, mesg);
- }
- else {
- err = mesg;
- }
- rb_exc_raise(rb_funcall(ruby_errinfo, rb_intern("exception"), 1, err));
+ VALUE mesg, errat;
+
+ errat = get_backtrace(ruby_errinfo);
+ mesg = rb_obj_as_string(ruby_errinfo);
+ rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]);
+ RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0];
}
rb_exc_raise(ruby_errinfo);
}
@@ -6757,6 +6772,9 @@ Init_load()
ruby_dln_librefs = rb_ary_new();
rb_global_variable(&ruby_dln_librefs);
+
+ /* not really a right place */
+ rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
}
static void