summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-03 05:20:14 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-09-03 05:20:14 +0000
commit6f484e4930be69c58462dd11c97663e6c8488b8e (patch)
tree324b1dbdf4149be943eb3cbff26ad7f377e53dc0
parent20254d4e133331e69e6aa7514e1e72ad7d14d496 (diff)
* 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
-rw-r--r--ChangeLog41
-rw-r--r--array.c38
-rw-r--r--class.c56
-rw-r--r--compar.c40
-rw-r--r--error.c7
-rw-r--r--ext/digest/digest.c105
-rw-r--r--ext/digest/md5/md5init.c7
-rw-r--r--ext/extmk.rb.in2
-rw-r--r--ext/stringio/stringio.c20
-rw-r--r--file.c18
-rw-r--r--hash.c28
-rw-r--r--intern.h1
-rw-r--r--io.c2
-rw-r--r--object.c52
-rw-r--r--range.c6
-rw-r--r--re.c37
-rw-r--r--ruby.h2
-rw-r--r--string.c4
-rw-r--r--struct.c16
-rw-r--r--time.c20
-rw-r--r--variable.c10
-rw-r--r--version.h4
22 files changed, 277 insertions, 239 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 <aamine@loveruby.net>
* intern.h (ruby_parser_stack_on_heap): added.
+Mon Sep 2 18:45:07 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_copy_generic_ivar): remove old generic instance
+ variable table if it existes.
+
Sun Sep 1 15:54:33 2002 WATANABE Hirofumi <eban@ruby-lang.org>
* config.guess: fixed for Linux/PPC.
+Sat Aug 31 09:38:12 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_make_metaclass): metaclass of a metaclass is a
+ metaclass itself.
+
Fri Aug 30 22:45:16 2002 Akinori MUSHA <knu@iDaemons.org>
* lib/set.rb: Added.
@@ -45,6 +55,37 @@ Fri Aug 30 19:40:28 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* ext/tcltklib/tcltklib.c (ip_toUTF8, ip_fromUTF8): ditto.
+Fri Aug 30 01:32:17 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <konishih@fd6.so-net.ne.jp>
* 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);
-
- FL_SET(klass, FL_SINGLETON);
- return klass;
-}
+ VALUE klass = RBASIC(obj)->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;
-
- if (class == cDigest_Base)
- rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ VALUE obj = rb_digest_base_alloc(klass);
-#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;
-
- class = CLASS_OF(self);
- algo = get_digest_base_metadata(class);
- Data_Get_Struct(self, void, pctx1);
-
- pctx2 = xmalloc(algo->ctx_size);
+ VALUE klass;
+
+ 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
@@ -527,6 +527,23 @@ match_alloc(klass)
}
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