From 6f484e4930be69c58462dd11c97663e6c8488b8e Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 3 Sep 2002 05:20:14 +0000 Subject: [PATCH] * variable.c (rb_copy_generic_ivar): remove old generic instance variable table if it existes. * class.c (rb_make_metaclass): metaclass of a metaclass is a metaclass itself. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2784 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 41 ++++++++++++++++ array.c | 38 ++++++--------- class.c | 56 +++++++++------------ compar.c | 40 +++++++++------ error.c | 7 +++ ext/digest/digest.c | 103 +++++++++++++++------------------------ ext/digest/md5/md5init.c | 7 +-- ext/extmk.rb.in | 2 +- ext/stringio/stringio.c | 20 ++++---- file.c | 18 ++++--- hash.c | 28 +---------- intern.h | 1 - io.c | 2 + object.c | 52 ++++++++++++-------- range.c | 6 ++- re.c | 37 ++++++++++---- ruby.h | 2 +- string.c | 4 +- struct.c | 16 +++--- time.c | 20 ++++---- variable.c | 10 +++- version.h | 4 +- 22 files changed, 276 insertions(+), 238 deletions(-) diff --git a/ChangeLog b/ChangeLog index fe0e4167cd..2574b013dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,10 +14,20 @@ Mon Sep 2 21:21:46 2002 Minero Aoki * intern.h (ruby_parser_stack_on_heap): added. +Mon Sep 2 18:45:07 2002 Yukihiro Matsumoto + + * variable.c (rb_copy_generic_ivar): remove old generic instance + variable table if it existes. + Sun Sep 1 15:54:33 2002 WATANABE Hirofumi * config.guess: fixed for Linux/PPC. +Sat Aug 31 09:38:12 2002 Yukihiro Matsumoto + + * class.c (rb_make_metaclass): metaclass of a metaclass is a + metaclass itself. + Fri Aug 30 22:45:16 2002 Akinori MUSHA * lib/set.rb: Added. @@ -45,6 +55,37 @@ Fri Aug 30 19:40:28 2002 Nobuyoshi Nakada * ext/tcltklib/tcltklib.c (ip_toUTF8, ip_fromUTF8): ditto. +Fri Aug 30 01:32:17 2002 Yukihiro Matsumoto + + * class.c (rb_singleton_class): superclass of a metaclass + should be a metaclass of superclass. + + * range.c (range_eq): two instances must belong to a same class to + be equal. + + * range.c (range_eql): ditto. + + * io.c (rb_io_taint_check): frozen check added. + + * file.c (rb_stat_become): frozen check added. + + * object.c (rb_obj_become): ditto. + + * re.c (rb_reg_become): ditto. + + * struct.c (rb_struct_become): ditto. + + * time.c (time_become): ditto. + + * array.c (rb_ary_become): should call rb_ary_modify(). + + * hash.c (rb_hash_become): should call rb_hash_modify(). + + * compar.c (cmp_equal): should not use NUM2LONG(), since <=> may + return bignum. + + * compar.c (cmp_gt, cmp_ge, cmp_lt, cmp_le, cmp_between): ditto. + Thu Aug 29 23:34:42 2002 KONISHI Hiromasa * bcc32/MakeFile.sub (sitearch): add. diff --git a/array.c b/array.c index f247db9794..ee59769a5c 100644 --- a/array.c +++ b/array.c @@ -795,22 +795,6 @@ rb_ary_empty_p(ary) return Qfalse; } -static VALUE -rb_ary_become(copy, orig) - VALUE copy, orig; -{ - orig = to_ary(orig); - ary_make_shared(orig); - if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) - free(RARRAY(copy)->ptr); - RARRAY(copy)->ptr = RARRAY(orig)->ptr; - RARRAY(copy)->len = RARRAY(orig)->len; - RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; - FL_SET(copy, ELTS_SHARED); - - return copy; -} - VALUE rb_ary_dup(ary) VALUE ary; @@ -1316,13 +1300,21 @@ rb_ary_delete_if(ary) } static VALUE -rb_ary_replace(ary, ary2) - VALUE ary, ary2; +rb_ary_replace(copy, orig) + VALUE copy, orig; { - if (ary == ary2) return ary; - ary2 = to_ary(ary2); - rb_ary_update(ary, 0, RARRAY(ary)->len, ary2); - return ary; + rb_ary_modify(copy); + orig = to_ary(orig); + if (copy == orig) return copy; + ary_make_shared(orig); + if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) + free(RARRAY(copy)->ptr); + RARRAY(copy)->ptr = RARRAY(orig)->ptr; + RARRAY(copy)->len = RARRAY(orig)->len; + RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; + FL_SET(copy, ELTS_SHARED); + + return copy; } VALUE @@ -1857,7 +1849,7 @@ Init_Array() rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1); rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1); rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1); - rb_define_method(rb_cArray, "become", rb_ary_become, 1); + rb_define_method(rb_cArray, "become", rb_ary_replace, 1); rb_define_method(rb_cArray, "join", rb_ary_join_m, -1); rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0); rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0); diff --git a/class.c b/class.c index a35d85f0ed..1930a2da67 100644 --- a/class.c +++ b/class.c @@ -94,25 +94,24 @@ rb_mod_dup(mod) } VALUE -rb_singleton_class_new(super) - VALUE super; +rb_singleton_class_clone(obj) + VALUE obj; { - VALUE klass = rb_class_boot(super); + VALUE klass = RBASIC(obj)->klass; - FL_SET(klass, FL_SINGLETON); - return klass; -} - -VALUE -rb_singleton_class_clone(klass) - VALUE klass; -{ if (!FL_TEST(klass, FL_SINGLETON)) return klass; else { /* copy singleton(unnamed) class */ NEWOBJ(clone, struct RClass); - CLONESETUP(clone, klass); + OBJSETUP(clone, 0, RBASIC(klass)->flags); + + if (BUILTIN_TYPE(obj) == T_CLASS) { + RBASIC(clone)->klass = (VALUE)clone; + } + else { + RBASIC(clone)->klass = rb_singleton_class_clone(klass); + } clone->super = RCLASS(klass)->super; clone->iv_tbl = 0; @@ -122,6 +121,7 @@ rb_singleton_class_clone(klass) } clone->m_tbl = st_init_numtable(); st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl); + rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); FL_SET(clone, FL_SINGLETON); return (VALUE)clone; } @@ -140,12 +140,17 @@ rb_singleton_class_attached(klass, obj) } VALUE -rb_make_metaclass(obj, klass) - VALUE obj, klass; +rb_make_metaclass(obj, super) + VALUE obj, super; { - klass = rb_singleton_class_new(klass); + VALUE klass = rb_class_boot(super); + FL_SET(klass, FL_SINGLETON); RBASIC(obj)->klass = klass; rb_singleton_class_attached(klass, obj); + if (BUILTIN_TYPE(obj) == T_CLASS) { + RBASIC(klass)->klass = klass; + } + return klass; } @@ -667,28 +672,12 @@ rb_undef_method(klass, name) rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF); } -#if 0 - -#define SPECIAL_SINGLETON(x,c) do { - if (obj == (x)) {\ - if (!FL_TEST(c, FL_SINGLETON)) {\ - c = rb_singleton_class_new(c);\ - rb_singleton_class_attached(c,obj);\ - }\ - return c;\ - }\ -} while (0) - -#else - #define SPECIAL_SINGLETON(x,c) do {\ if (obj == (x)) {\ return c;\ }\ } while (0) -#endif - VALUE rb_singleton_class(obj) VALUE obj; @@ -707,13 +696,12 @@ rb_singleton_class(obj) DEFER_INTS; if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && - ((BUILTIN_TYPE(obj) != T_CLASS && BUILTIN_TYPE(obj) != T_MODULE) || - rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj)) { + (BUILTIN_TYPE(obj) == T_CLASS || /* metaclass (or metaclass of metaclass) */ + rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj)) { klass = RBASIC(obj)->klass; } else { klass = rb_make_metaclass(obj, RBASIC(obj)->klass); - RBASIC(klass)->klass = CLASS_OF(RCLASS(klass)->super); } if (OBJ_TAINTED(obj)) { OBJ_TAINT(klass); diff --git a/compar.c b/compar.c index ebdd47a8d7..3647f9b376 100644 --- a/compar.c +++ b/compar.c @@ -23,7 +23,10 @@ cmp_equal(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) == 0) return Qtrue; + if (c == INT2FIX(0)) return Qtrue; + if (TYPE(c) == T_BIGNUM) { + if (rb_big_norm(c) == INT2FIX(0)) return Qtrue; + } return Qfalse; } @@ -34,7 +37,11 @@ cmp_gt(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) > 0) return Qtrue; + if (FIXNUM_P(c) && FIX2INT(c) > 0) return Qtrue; + if (TYPE(c) == T_BIGNUM) { + if (rb_big_norm(x) == INT2FIX(0)) return Qfalse; + if (RBIGNUM(c)->sign) return Qtrue; + } return Qfalse; } @@ -45,7 +52,11 @@ cmp_ge(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) >= 0) return Qtrue; + if (FIXNUM_P(c) && FIX2INT(c) >= 0) return Qtrue; + if (TYPE(c) == T_BIGNUM) { + if (rb_big_norm(x) == INT2FIX(0)) return Qtrue; + if (RBIGNUM(c)->sign) return Qtrue; + } return Qfalse; } @@ -55,8 +66,11 @@ cmp_lt(x, y) { VALUE c = rb_funcall(x, cmp, 1, y); - if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) < 0) return Qtrue; + if (FIXNUM_P(c) && FIX2INT(c) < 0) return Qtrue; + if (TYPE(c) == T_BIGNUM) { + if (rb_big_norm(x) == INT2FIX(0)) return Qfalse; + if (!RBIGNUM(c)->sign) return Qtrue; + } return Qfalse; } @@ -67,7 +81,11 @@ cmp_le(x, y) VALUE c = rb_funcall(x, cmp, 1, y); if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) <= 0) return Qtrue; + if (FIXNUM_P(c) && FIX2INT(c) <= 0) return Qtrue; + if (TYPE(c) == T_BIGNUM) { + if (rb_big_norm(x) == INT2FIX(0)) return Qtrue; + if (!RBIGNUM(c)->sign) return Qtrue; + } return Qfalse; } @@ -75,14 +93,8 @@ static VALUE cmp_between(x, min, max) VALUE x, min, max; { - VALUE c = rb_funcall(x, cmp, 1, min); - - if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) < 0) return Qfalse; - - c = rb_funcall(x, cmp, 1, max); - if (NIL_P(c)) return Qfalse; - if (NUM2LONG(c) > 0) return Qfalse; + if (cmp_lt(x, min)) return Qfalse; + if (cmp_gt(x, max)) return Qfalse; return Qtrue; } diff --git a/error.c b/error.c index 6a4641fc53..ed2d5220b7 100644 --- a/error.c +++ b/error.c @@ -813,6 +813,13 @@ rb_error_frozen(what) rb_raise(rb_eTypeError, "can't modify frozen %s", what); } +void +rb_check_frozen(obj) + VALUE obj; +{ + if (OBJ_FROZEN(obj)) rb_error_frozen(rb_class2name(CLASS_OF(obj))); +} + static void init_syserr() { diff --git a/ext/digest/digest.c b/ext/digest/digest.c index 3d47685aac..f4f5729f32 100644 --- a/ext/digest/digest.c +++ b/ext/digest/digest.c @@ -41,16 +41,17 @@ static ID id_metadata; */ static algo_t * -get_digest_base_metadata(class) - VALUE class; +get_digest_base_metadata(klass) + VALUE klass; { VALUE obj; algo_t *algo; - if (rb_cvar_defined(class, id_metadata) == Qfalse) + if (rb_cvar_defined(klass, id_metadata) == Qfalse) { rb_notimplement(); + } - obj = rb_cvar_get(class, id_metadata); + obj = rb_cvar_get(klass, id_metadata); Data_Get_Struct(obj, algo_t, algo); @@ -58,54 +59,42 @@ get_digest_base_metadata(class) } static VALUE -rb_digest_base_s_new(argc, argv, class) - int argc; - VALUE* argv; - VALUE class; +rb_digest_base_alloc(klass) + VALUE klass; { algo_t *algo; VALUE obj; void *pctx; - if (class == cDigest_Base) + if (klass == cDigest_Base) { rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); + } - algo = get_digest_base_metadata(class); + algo = get_digest_base_metadata(klass); pctx = xmalloc(algo->ctx_size); algo->init_func(pctx); - obj = Data_Wrap_Struct(class, 0, free, pctx); - - rb_obj_call_init(obj, argc, argv); + obj = Data_Wrap_Struct(klass, 0, free, pctx); return obj; } static VALUE -rb_digest_base_s_digest(class, str) - VALUE class; +rb_digest_base_s_digest(klass, str) + VALUE klass; VALUE str; { algo_t *algo; void *pctx; size_t len; unsigned char *digest; - VALUE obj; + VALUE obj = rb_digest_base_alloc(klass); - if (class == cDigest_Base) - rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); + algo = get_digest_base_metadata(klass); + Data_Get_Struct(obj, void, pctx); -#ifdef StringValue StringValue(str); -#else - Check_Type(str, T_STRING); -#endif - - algo = get_digest_base_metadata(class); - - pctx = xmalloc(algo->ctx_size); - algo->init_func(pctx); algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len); len = algo->digest_len; @@ -122,26 +111,18 @@ rb_digest_base_s_digest(class, str) } static VALUE -rb_digest_base_s_hexdigest(class, str) - VALUE class; +rb_digest_base_s_hexdigest(klass, str) + VALUE klass; VALUE str; { algo_t *algo; void *pctx; size_t len; unsigned char *hexdigest; - VALUE obj; + VALUE obj = rb_digest_base_alloc(klass); - if (class == cDigest_Base) - rb_raise(rb_eNotImpError, "Digest::Base is an abstract class"); - -#ifdef StringValue StringValue(str); -#else - Check_Type(str, T_STRING); -#endif - - algo = get_digest_base_metadata(class); + algo = get_digest_base_metadata(klass); pctx = xmalloc(algo->ctx_size); algo->init_func(pctx); @@ -161,21 +142,25 @@ rb_digest_base_s_hexdigest(class, str) } static VALUE -rb_digest_base_clone(self) - VALUE self; +rb_digest_base_become(copy, obj) + VALUE copy, obj; { algo_t *algo; void *pctx1, *pctx2; - VALUE class; + VALUE klass; - class = CLASS_OF(self); - algo = get_digest_base_metadata(class); - Data_Get_Struct(self, void, pctx1); - - pctx2 = xmalloc(algo->ctx_size); + printf("Digest::Base::bacome\n"); + if (copy = obj) return copy; + rb_check_frozen(copy); + algo = get_digest_base_metadata(CLASS_OF(klass)); + if (algo != get_digest_base_metadata(CLASS_OF(obj))) { + rb_raise(rb_eTypeError, "wrong argument class"); + } + Data_Get_Struct(copy, void, pctx1); + Data_Get_Struct(copy, void, pctx2); memcpy(pctx2, pctx1, algo->ctx_size); - return Data_Wrap_Struct(class, 0, free, pctx2); + return copy; } static VALUE @@ -185,12 +170,7 @@ rb_digest_base_update(self, str) algo_t *algo; void *pctx; -#ifdef StringValue StringValue(str); -#else - Check_Type(str, T_STRING); -#endif - algo = get_digest_base_metadata(CLASS_OF(self)); Data_Get_Struct(self, void, pctx); @@ -281,13 +261,13 @@ rb_digest_base_equal(self, other) VALUE self, other; { algo_t *algo; - VALUE class; + VALUE klass; VALUE str1, str2; - class = CLASS_OF(self); - algo = get_digest_base_metadata(class); + klass = CLASS_OF(self); + algo = get_digest_base_metadata(klass); - if (CLASS_OF(other) == class) { + if (CLASS_OF(other) == klass) { void *pctx1, *pctx2; Data_Get_Struct(self, void, pctx1); @@ -296,11 +276,7 @@ rb_digest_base_equal(self, other) return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse; } -#ifdef StringValue StringValue(other); -#else - Check_Type(other, T_STRING); -#endif str2 = other; if (RSTRING(str2)->len == algo->digest_len) @@ -326,12 +302,13 @@ Init_digest() cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject); - rb_define_singleton_method(cDigest_Base, "new", rb_digest_base_s_new, -1); + printf("Init_digest\n"); + rb_define_singleton_method(cDigest_Base, "allocate", rb_digest_base_alloc, 0); rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1); rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1); rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1); - rb_define_method(cDigest_Base, "clone", rb_digest_base_clone, 0); + rb_define_method(cDigest_Base, "become", rb_digest_base_become, 1); rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1); rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1); rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0); diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c index 90ab707433..69b15c5b39 100644 --- a/ext/digest/md5/md5init.c +++ b/ext/digest/md5/md5init.c @@ -18,7 +18,6 @@ void Init_md5() { VALUE mDigest, cDigest_Base, cDigest_MD5; - ID id_metadata; rb_require("digest.so"); @@ -27,8 +26,6 @@ Init_md5() cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); - id_metadata = rb_intern("metadata"); - - rb_cvar_set(cDigest_MD5, id_metadata, - Data_Wrap_Struct(rb_cObject, 0, 0, &md5), Qtrue); + rb_cvar_declare(cDigest_MD5, rb_intern("metadata"), + Data_Wrap_Struct(rb_cObject, 0, 0, &md5)); } diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index cebb115214..b2d0b02937 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -822,7 +822,7 @@ if $extlist.size > 0 if File.exist?(f) $extinit += format("\ \tInit_%s();\n\ -\trb_provide(\"%s\");\n\ +\trb_provide(\"%s.so\");\n\ ", i, t) $extobjs += "ext/" $extobjs += f diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index a6ba07307e..4f682b3a20 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -148,7 +148,7 @@ static VALUE strio_closed _((VALUE)); static VALUE strio_closed_read _((VALUE)); static VALUE strio_closed_write _((VALUE)); static VALUE strio_eof _((VALUE)); -static VALUE strio_clone _((VALUE)); +static VALUE strio_become _((VALUE, VALUE)); static VALUE strio_get_lineno _((VALUE)); static VALUE strio_set_lineno _((VALUE, VALUE)); static VALUE strio_get_pos _((VALUE)); @@ -405,14 +405,17 @@ strio_eof(self) } static VALUE -strio_clone(self) - VALUE self; +strio_become(copy, orig) + VALUE copy, orig; { - struct StringIO *ptr = StringIO(self); - VALUE clone = rb_call_super(0, 0); - DATA_PTR(clone) = ptr; + struct StringIO *ptr = StringIO(orig); + + if (DATA_PTR(copy)) { + strio_free(DATA_PTR(ptr)); + } + DATA_PTR(copy) = ptr; ++ptr->count; - return self; + return copy; } static VALUE @@ -883,8 +886,7 @@ Init_stringio() rb_define_singleton_method(StringIO, "open", strio_s_open, -1); rb_define_method(StringIO, "initialize", strio_initialize, -1); rb_enable_super(StringIO, "initialize"); - rb_define_method(StringIO, "clone", strio_clone, 0); - rb_enable_super(StringIO, "clone"); + rb_define_method(StringIO, "become", strio_become, 1); rb_define_method(StringIO, "reopen", strio_reopen, -1); rb_define_method(StringIO, "string", strio_get_string, 0); diff --git a/file.c b/file.c index 3e53f70982..148ef04925 100644 --- a/file.c +++ b/file.c @@ -2024,26 +2024,28 @@ rb_stat_init(obj, fname) } static VALUE -rb_stat_become(obj, orig) - VALUE obj, orig; +rb_stat_become(copy, orig) + VALUE copy, orig; { struct stat *nst; + if (copy == orig) return orig; + rb_check_frozen(copy); /* need better argument type check */ - if (!rb_obj_is_instance_of(orig, rb_obj_class(obj))) { + if (!rb_obj_is_instance_of(orig, rb_obj_class(copy))) { rb_raise(rb_eTypeError, "wrong argument class"); } - if (DATA_PTR(obj)) { - free(DATA_PTR(obj)); - DATA_PTR(obj) = 0; + if (DATA_PTR(copy)) { + free(DATA_PTR(copy)); + DATA_PTR(copy) = 0; } if (DATA_PTR(orig)) { nst = ALLOC(struct stat); *nst = *(struct stat*)DATA_PTR(orig); - DATA_PTR(obj) = nst; + DATA_PTR(copy) = nst; } - return obj; + return copy; } static VALUE diff --git a/hash.c b/hash.c index 60dc89ff0b..3c0aeab2b8 100644 --- a/hash.c +++ b/hash.c @@ -254,30 +254,6 @@ to_hash(hash) return rb_convert_type(hash, T_HASH, "Hash", "to_hash"); } -static VALUE -rb_hash_become(copy, orig) - VALUE copy, orig; -{ - orig = to_hash(orig); - if (RHASH(copy)->tbl) st_free_table(RHASH(copy)->tbl); - RHASH(copy)->tbl = (st_table*)st_copy(RHASH(orig)->tbl); - RHASH(copy)->ifnone = RHASH(orig)->ifnone; - if (FL_TEST(orig, HASH_PROC_DEFAULT)) { - FL_SET(copy, HASH_PROC_DEFAULT); - } - else { - FL_UNSET(copy, HASH_PROC_DEFAULT); - } - if (FL_TEST(orig, HASH_DELETED)) { - FL_SET(copy, HASH_DELETED); - } - else { - FL_UNSET(copy, HASH_DELETED); - } - - return copy; -} - static int rb_hash_rehash_i(key, value, tbl) VALUE key, value; @@ -596,7 +572,7 @@ replace_i(key, val, hash) } static VALUE -rb_hash_replace(hash, hash2) +rb_hash_become(hash, hash2) VALUE hash, hash2; { hash2 = to_hash(hash2); @@ -1654,7 +1630,7 @@ Init_Hash() rb_define_method(rb_cHash,"clear", rb_hash_clear, 0); rb_define_method(rb_cHash,"invert", rb_hash_invert, 0); rb_define_method(rb_cHash,"update", rb_hash_update, 1); - rb_define_method(rb_cHash,"replace", rb_hash_replace, 1); + rb_define_method(rb_cHash,"replace", rb_hash_become, 1); rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1); rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1); diff --git a/intern.h b/intern.h index afc902d267..61234db154 100644 --- a/intern.h +++ b/intern.h @@ -95,7 +95,6 @@ VALUE rb_class_boot _((VALUE)); VALUE rb_class_new _((VALUE)); VALUE rb_mod_clone _((VALUE)); VALUE rb_mod_dup _((VALUE)); -VALUE rb_singleton_class_new _((VALUE)); VALUE rb_singleton_class_clone _((VALUE)); void rb_singleton_class_attached _((VALUE,VALUE)); VALUE rb_make_metaclass _((VALUE, VALUE)); diff --git a/io.c b/io.c index 7de74befde..28cb8a51c7 100644 --- a/io.c +++ b/io.c @@ -177,6 +177,7 @@ rb_io_taint_check(io) { if (!OBJ_TAINTED(io) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO"); + rb_check_frozen(io); return io; } @@ -2270,6 +2271,7 @@ rb_io_become(clone, io) char *mode; io = rb_io_get_io(io); + if (clone == io) return clone; GetOpenFile(io, orig); MakeOpenFile(clone, fptr); diff --git a/object.c b/object.c index cbc37944f3..d26efe1837 100644 --- a/object.c +++ b/object.c @@ -90,23 +90,43 @@ rb_obj_class(obj) return rb_class_real(CLASS_OF(obj)); } +static void +copy_object(dest, obj) + VALUE dest, obj; +{ + RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR|FL_TAINT); + RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT); + if (FL_TEST(obj, FL_EXIVAR)) { + rb_copy_generic_ivar(dest, obj); + } + switch (TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + if (ROBJECT(dest)->iv_tbl) { + st_free_table(ROBJECT(dest)->iv_tbl); + ROBJECT(dest)->iv_tbl = 0; + } + if (ROBJECT(obj)->iv_tbl) { + ROBJECT(dest)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); + } + } +} + VALUE rb_obj_clone(obj) VALUE obj; { VALUE clone; - int frozen; if (rb_special_const_p(obj)) { rb_raise(rb_eTypeError, "can't clone %s", rb_class2name(CLASS_OF(obj))); } - clone = rb_obj_alloc(rb_class_real(RBASIC(obj)->klass)); - CLONESETUP(clone, obj); - frozen = OBJ_FROZEN(obj); - FL_UNSET(clone, FL_FREEZE); /* temporarily remove frozen flag */ + clone = rb_obj_alloc(rb_obj_class(obj)); + RBASIC(clone)->klass = rb_singleton_class_clone(obj); + copy_object(clone, obj); rb_funcall(clone, become, 1, obj); - if (frozen) OBJ_FREEZE(clone); /* restore frozen status */ - OBJ_INFECT(clone, obj); + RBASIC(clone)->flags = RBASIC(obj)->flags; return clone; } @@ -120,10 +140,9 @@ rb_obj_dup(obj) if (rb_special_const_p(obj)) { rb_raise(rb_eTypeError, "can't dup %s", rb_class2name(CLASS_OF(obj))); } - dup = rb_obj_alloc(rb_class_real(RBASIC(obj)->klass)); - DUPSETUP(dup, obj); + dup = rb_obj_alloc(rb_obj_class(obj)); + copy_object(dup, obj); rb_funcall(dup, become, 1, obj); - OBJ_INFECT(dup, obj); return dup; } @@ -132,18 +151,11 @@ VALUE rb_obj_become(obj, orig) VALUE obj, orig; { - long type; - - if ((type = TYPE(obj)) != TYPE(orig) || - rb_obj_class(obj) != rb_obj_class(orig)) { + if (obj == orig) return obj; + rb_check_frozen(obj); + if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) { rb_raise(rb_eTypeError, "become should take same class object"); } - if (type == T_OBJECT) { - if (ROBJECT(obj)->iv_tbl) st_free_table(ROBJECT(obj)->iv_tbl); - if (ROBJECT(orig)->iv_tbl) { - ROBJECT(obj)->iv_tbl = st_copy(ROBJECT(orig)->iv_tbl); - } - } return obj; } diff --git a/range.c b/range.c index b7d921f404..932442af39 100644 --- a/range.c +++ b/range.c @@ -95,7 +95,8 @@ range_eq(range, obj) VALUE range, obj; { if (range == obj) return Qtrue; - if (!rb_obj_is_kind_of(obj, rb_obj_class(range))) return Qfalse; + if (!rb_obj_is_instance_of(obj, rb_obj_class(range))) + return Qfalse; if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) return Qfalse; @@ -153,7 +154,8 @@ range_eql(range, obj) VALUE range, obj; { if (range == obj) return Qtrue; - if (!rb_obj_is_kind_of(obj, rb_obj_class(obj))) return Qfalse; + if (!rb_obj_is_instance_of(obj, rb_obj_class(range))) + return Qfalse; if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) return Qfalse; diff --git a/re.c b/re.c index 3f76b5e5b6..019e4de09f 100644 --- a/re.c +++ b/re.c @@ -526,6 +526,23 @@ match_alloc(klass) return (VALUE)match; } +static VALUE +match_clone(match) + VALUE match; +{ + NEWOBJ(clone, struct RMatch); + CLONESETUP(clone, match); + + clone->str = RMATCH(match)->str; + clone->regs = 0; + + clone->regs = ALLOC(struct re_registers); + clone->regs->allocated = 0; + re_copy_registers(clone->regs, RMATCH(match)->regs); + + return (VALUE)clone; +} + static VALUE match_become(obj, orig) VALUE obj, orig; @@ -1158,9 +1175,7 @@ rb_reg_initialize_m(argc, argv, self) } } - if (OBJ_FROZEN(self)) { - rb_error_frozen("Regexp"); - } + rb_check_frozen(self); src = argv[0]; if (TYPE(src) == T_REGEXP) { rb_reg_check(src); @@ -1311,20 +1326,22 @@ rb_reg_options(re) } static VALUE -rb_reg_become(clone, re) +rb_reg_become(copy, re) VALUE re; { + if (copy == re) return copy; + rb_check_frozen(copy); /* need better argument type check */ - if (!rb_obj_is_instance_of(re, rb_obj_class(clone))) { + if (!rb_obj_is_instance_of(re, rb_obj_class(copy))) { rb_raise(rb_eTypeError, "wrong argument type"); } - RREGEXP(clone)->ptr = 0; - RREGEXP(clone)->len = 0; - RREGEXP(clone)->str = 0; + RREGEXP(copy)->ptr = 0; + RREGEXP(copy)->len = 0; + RREGEXP(copy)->str = 0; rb_reg_check(re); - rb_reg_initialize(clone, RREGEXP(re)->str, RREGEXP(re)->len, + rb_reg_initialize(copy, RREGEXP(re)->str, RREGEXP(re)->len, rb_reg_options(re)); - return clone; + return copy; } VALUE diff --git a/ruby.h b/ruby.h index 7829b85476..8b5dc179fe 100644 --- a/ruby.h +++ b/ruby.h @@ -278,7 +278,7 @@ VALUE rb_newobj _((void)); if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\ } while (0) #define CLONESETUP(clone,obj) do {\ - OBJSETUP(clone,rb_singleton_class_clone(RBASIC(obj)->klass),RBASIC(obj)->flags);\ + OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\ rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\ if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\ } while (0) diff --git a/string.c b/string.c index b036cb5db7..6bd42f00d1 100644 --- a/string.c +++ b/string.c @@ -213,7 +213,7 @@ rb_str_to_str(str) } static void -rb_str_become(str, str2) +rb_str_shared_replace(str, str2) VALUE str, str2; { if (str == str2) return; @@ -1071,7 +1071,7 @@ rb_str_succ_bang(str) VALUE str; { rb_str_modify(str); - rb_str_become(str, rb_str_succ(str)); + rb_str_shared_replace(str, rb_str_succ(str)); return str; } diff --git a/struct.c b/struct.c index 4378196982..324ecc52a1 100644 --- a/struct.c +++ b/struct.c @@ -421,17 +421,19 @@ rb_struct_to_a(s) } static VALUE -rb_struct_become(clone, s) - VALUE clone, s; +rb_struct_become(copy, s) + VALUE copy, s; { - if (!rb_obj_is_instance_of(s, rb_obj_class(clone))) { + if (copy == s) return copy; + rb_check_frozen(copy); + if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) { rb_raise(rb_eTypeError, "wrong argument class"); } - RSTRUCT(clone)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len); - RSTRUCT(clone)->len = RSTRUCT(s)->len; - MEMCPY(RSTRUCT(clone)->ptr, RSTRUCT(s)->ptr, VALUE, RSTRUCT(clone)->len); + RSTRUCT(copy)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len); + RSTRUCT(copy)->len = RSTRUCT(s)->len; + MEMCPY(RSTRUCT(copy)->ptr, RSTRUCT(s)->ptr, VALUE, RSTRUCT(copy)->len); - return clone; + return copy; } static VALUE diff --git a/time.c b/time.c index 223f5de8ae..0d7216acaa 100644 --- a/time.c +++ b/time.c @@ -793,12 +793,23 @@ time_hash(time) return LONG2FIX(hash); } +static void +time_modify(time) + VALUE time; +{ + rb_check_frozen(time); + if (!OBJ_TAINTED(time) && rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't modify Time"); +} + static VALUE time_become(copy, time) VALUE copy, time; { struct time_object *tobj, *tcopy; + if (copy == time) return copy; + time_modify(copy); if (TYPE(time) != T_DATA || RDATA(time)->dfree != time_free) { rb_raise(rb_eTypeError, "wrong argument type"); } @@ -818,15 +829,6 @@ time_dup(time) return dup; } -static void -time_modify(time) - VALUE time; -{ - if (OBJ_FROZEN(time)) rb_error_frozen("Time"); - if (!OBJ_TAINTED(time) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't modify Time"); -} - static VALUE time_localtime(time) VALUE time; diff --git a/variable.c b/variable.c index 0b2c8ebe07..c37548fb91 100644 --- a/variable.c +++ b/variable.c @@ -924,7 +924,15 @@ rb_copy_generic_ivar(clone, obj) if (!generic_iv_tbl) return; if (st_lookup(generic_iv_tbl, obj, &tbl)) { - st_add_direct(generic_iv_tbl, clone, st_copy(tbl)); + st_table *old; + + if (st_lookup(generic_iv_tbl, clone, &old)) { + st_free_table(old); + st_insert(generic_iv_tbl, clone, st_copy(tbl)); + } + else { + st_add_direct(generic_iv_tbl, clone, st_copy(tbl)); + } } } diff --git a/version.h b/version.h index c4adb51517..c32cdd284e 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.3" -#define RUBY_RELEASE_DATE "2002-09-02" +#define RUBY_RELEASE_DATE "2002-09-03" #define RUBY_VERSION_CODE 173 -#define RUBY_RELEASE_CODE 20020902 +#define RUBY_RELEASE_CODE 20020903