From 292b3ecbb4a5cde9abd7ec6ed430acb30856dd78 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 17 Jan 2004 14:58:57 +0000 Subject: [PATCH] * error.c (NameError::Message): new class for lazy evaluation of message to ensure replaced before marshalling. [ruby-dev:22604] * eval.c (rb_method_missing): use NameError::Message. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5481 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++++ error.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ eval.c | 75 +++------------------------------------- 3 files changed, 113 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0bd35191d3..7537879ada 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sat Jan 17 23:58:51 2004 Nobuyoshi Nakada + + * error.c (NameError::Message): new class for lazy evaluation of + message to ensure replaced before marshalling. [ruby-dev:22604] + + * eval.c (rb_method_missing): use NameError::Message. + Sat Jan 17 21:49:50 2004 NAKAMURA Usaku * lib/time.rb (test_rfc2822, test_rfc3339, test_encode_xmlschema): diff --git a/error.c b/error.c index 3a7a5bfdfc..f2424272d5 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,78 @@ nometh_err_initialize(argc, argv, self) return self; } +static void +name_err_mesg_mark(ptr) + VALUE *ptr; +{ + rb_gc_mark_locations(ptr, ptr+3); +} + +static VALUE +name_err_mesg_init(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); +} + +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; +} + +static VALUE +name_err_mesg_load(klass, str) + VALUE klass, str; +{ + return str; +} + /* * call-seq: * no_method_error.args => obj @@ -884,6 +979,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_define_singleton_method(rb_eNameError, "message", name_err_mesg_init, 3); + rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "Message", rb_cData); + 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 0ad7402877..85ed4592a4 100644 --- a/eval.c +++ b/eval.c @@ -5159,65 +5159,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 @@ -5268,36 +5209,33 @@ 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(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); } @@ -7661,9 +7599,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