From 22b898fe831e7f9c6f6d549d97e69d3509dc857e Mon Sep 17 00:00:00 2001 From: usa Date: Wed, 25 Feb 2004 00:38:35 +0000 Subject: * error.c (NameError::Message): new class for lazy evaluation of message to ensure replaced before marshalling. merge from HEAD. (ruby-bugs-ja:PR#588) * eval.c (rb_method_missing): use NameError::Message. merge from HEAD. (ruby-bugs-ja:PR#588) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@5827 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 ++++++ error.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ eval.c | 76 ++++----------------------------------------- 3 files changed, 120 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e0490809e..65330b72df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Feb 25 09:35:22 2004 NAKAMURA Usaku + + * error.c (NameError::Message): new class for lazy evaluation of + message to ensure replaced before marshalling. merge from HEAD. + (ruby-bugs-ja:PR#588) + + * eval.c (rb_method_missing): use NameError::Message. merge from + HEAD. (ruby-bugs-ja:PR#588) + Tue Feb 24 18:59:37 Hirokazu Yamamoto * dir.c (glob_helper): '**/' should not match leading period diff --git a/error.c b/error.c index 3a7a5bfdfc..c6fb7b446c 100644 --- a/error.c +++ b/error.c @@ -293,6 +293,7 @@ VALUE rb_eNoMethodError; VALUE rb_eSecurityError; VALUE rb_eNotImpError; VALUE rb_eNoMemError; +static VALUE rb_cNameErrorMesg; VALUE rb_eScriptError; VALUE rb_eSyntaxError; @@ -627,6 +628,28 @@ name_err_name(self) return rb_attr_get(self, rb_intern("name")); } +/* + * call-seq: + * name_error.to_s => string + * + * Produce a nicely-formated string representing the +NameError+. + */ + +static VALUE +name_err_to_s(exc) + VALUE exc; +{ + VALUE mesg = rb_attr_get(exc, rb_intern("mesg")), str = mesg; + + if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc)); + StringValue(str); + if (str != mesg) { + rb_iv_set(exc, "mesg", mesg = str); + } + if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg); + return mesg; +} + /* * call-seq: * NoMethodError.new(msg, name [, args]) => no_method_error @@ -649,6 +672,82 @@ nometh_err_initialize(argc, argv, self) return self; } +/* :nodoc: */ +static void +name_err_mesg_mark(ptr) + VALUE *ptr; +{ + rb_gc_mark_locations(ptr, ptr+3); +} + +/* :nodoc: */ +static VALUE +name_err_mesg_new(obj, mesg, recv, method) + VALUE obj, mesg, recv, method; +{ + VALUE *ptr = ALLOC_N(VALUE, 3); + + ptr[0] = mesg; + ptr[1] = recv; + ptr[2] = method; + return Data_Wrap_Struct(rb_cNameErrorMesg, name_err_mesg_mark, -1, ptr); +} + +/* :nodoc: */ +static VALUE +name_err_mesg_to_str(obj) + VALUE obj; +{ + VALUE *ptr, mesg; + Data_Get_Struct(obj, VALUE, ptr); + + mesg = ptr[0]; + if (NIL_P(mesg)) return Qnil; + else { + char *desc = 0; + VALUE d = 0, args[3]; + + obj = ptr[1]; + switch (TYPE(obj)) { + case T_NIL: + desc = "nil"; + break; + case T_TRUE: + desc = "true"; + break; + case T_FALSE: + desc = "false"; + break; + default: + d = rb_protect(rb_inspect, obj, 0); + if (NIL_P(d) || RSTRING(d)->len > 65) { + d = rb_any_to_s(obj); + } + desc = RSTRING(d)->ptr; + break; + } + if (desc && desc[0] != '#') { + d = rb_str_new2(desc); + rb_str_cat2(d, ":"); + rb_str_cat2(d, rb_obj_classname(obj)); + } + args[0] = mesg; + args[1] = ptr[2]; + args[2] = d; + mesg = rb_f_sprintf(3, args); + } + if (OBJ_TAINTED(obj)) OBJ_TAINT(mesg); + return mesg; +} + +/* :nodoc: */ +static VALUE +name_err_mesg_load(klass, str) + VALUE klass, str; +{ + return str; +} + /* * call-seq: * no_method_error.args => obj @@ -884,6 +983,12 @@ Init_Exception() rb_eNameError = rb_define_class("NameError", rb_eStandardError); rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1); rb_define_method(rb_eNameError, "name", name_err_name, 0); + rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0); + rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData); + rb_define_singleton_method(rb_cNameErrorMesg, "!", name_err_mesg_new, 3); + rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0); + rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1); + rb_define_singleton_method(rb_cNameErrorMesg, "_load", name_err_mesg_load, 1); rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError); rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1); rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0); diff --git a/eval.c b/eval.c index 8565bde72d..f0f69b56c8 100644 --- a/eval.c +++ b/eval.c @@ -5162,65 +5162,6 @@ static int last_call_status; #define CSTAT_VCALL 4 #define CSTAT_SUPER 8 -/* - * call-seq: - * name_error.to_s => string - * - * Produce a nicely-formated string representing the +NameError+. - */ - -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; -} - /* * call-seq: * obj.method_missing(symbol [, *args] ) => result @@ -5271,36 +5212,34 @@ rb_method_missing(argc, argv, obj) id = SYM2ID(argv[0]); if (last_call_status & CSTAT_PRIV) { - format = "private method `%s' called for %%s%%s%%s"; + format = "private method `%s' called for %s"; } else if (last_call_status & CSTAT_PROT) { - format = "protected method `%s' called for %%s%%s%%s"; + format = "protected method `%s' called for %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"; 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"; } ruby_current_node = cnode; { - char buf[BUFSIZ]; int n = 0; VALUE args[3]; - snprintf(buf, BUFSIZ, format, rb_id2name(id)); - args[n++] = rb_str_new2(buf); + args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!', + 3, rb_str_new2(format), obj, argv[0]); 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); } @@ -7667,9 +7606,6 @@ 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 -- cgit v1.2.3