summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-15 23:45:26 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-15 23:45:26 +0000
commit8eb537a88abf2f37b0728e628f8b7ac2d0d75252 (patch)
tree9bb38799448b07618368d6e9b4f07a4d00b2c65f /eval.c
parentabbffef10ccd7bb0b2022bcc73afc51c86bc49c4 (diff)
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4962 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c118
1 files changed, 68 insertions, 50 deletions
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