summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--ToDo5
-rw-r--r--array.c3
-rw-r--r--configure.in2
-rw-r--r--eval.c12
-rw-r--r--file.c8
-rw-r--r--gc.c2
-rw-r--r--hash.c6
-rw-r--r--lib/finalize.rb253
-rw-r--r--marshal.c25
-rw-r--r--re.c2
-rw-r--r--ruby.h3
-rw-r--r--string.c28
-rw-r--r--struct.c4
14 files changed, 203 insertions, 164 deletions
diff --git a/ChangeLog b/ChangeLog
index a90f169..d7acebe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,13 @@ Thu Aug 29 00:55:55 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* marshal.c (r_object): yield loaded objects, not intermediates.
(ruby-bugs-ja:PR#296)
+Thu Aug 29 00:06:54 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_become): should not free ptr if it's shared.
+
+ * eval.c (rb_alias): prohibit making an alias named "allocate" if
+ klass is a metaclass.
+
Wed Aug 28 23:59:15 2002 Michal Rokos <michal@ruby-lang.org>
* signal.c: remove #ifdef SIGINT for struct signals.
@@ -17,6 +24,11 @@ Wed Aug 28 23:34:32 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* io.c (appendline): data was lost when raw mode.
+Wed Aug 28 22:57:34 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_string_value_ptr): StringValuePtr() should never
+ return NULL pointer.
+
Wed Aug 28 19:12:46 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* ext/stringio/stringio.c (strio_initialize): RSTRING(mode)->ptr
@@ -34,7 +46,7 @@ Wed Aug 28 17:45:03 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
Wed Aug 28 16:36:40 2002 WATANABE Hirofumi <eban@ruby-lang.org>
- * configure.in (ar): don't check twice for ar.
+ * configure.in (ar): don't check ar twice.
Wed Aug 28 15:00:29 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
diff --git a/ToDo b/ToDo
index 3b03b41..fa7f32d 100644
--- a/ToDo
+++ b/ToDo
@@ -32,10 +32,11 @@ Language Spec.
* .. or something like defadvice in Emacs.
* property - for methods, or for objects in general.
* "in" modifier, to annotate, or to encourage assertion.
-* selector namespace - something like generic-flet in CLOS, to help RubyBehevior
+* selector namespace - something like generic-flet in CLOS, to help RubyBehavior
* private instance variable (as in Python?) @_foo in class Foo => @_Foo_foo
* warn/error "bare word" method, like "foo", you should type "foo()"
* clarify evaluation order of operator argument (=~, .., ...)
+* :symbol => value hash in the form of {symbol: value, ...} ??
Hacking Interpreter
@@ -115,7 +116,7 @@ Extension Libraries
Ruby Libraries
-* add uri.rb
+- add uri.rb
* urllib.rb, nttplib.rb, etc.
* format like perl's
diff --git a/array.c b/array.c
index f88e1b1..f247db9 100644
--- a/array.c
+++ b/array.c
@@ -801,7 +801,8 @@ rb_ary_become(copy, orig)
{
orig = to_ary(orig);
ary_make_shared(orig);
- if (RARRAY(copy)->ptr) free(RARRAY(copy)->ptr);
+ 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;
diff --git a/configure.in b/configure.in
index 4553aaa..357eb74 100644
--- a/configure.in
+++ b/configure.in
@@ -1018,7 +1018,7 @@ case "$target_os" in
CFLAGS="$CFLAGS -pipe -no-precomp"
;;
darwin*)
- CFLAGS="$CFLAGS -pipe -no-precomp"
+ CFLAGS="$CFLAGS -pipe"
;;
os2_emx)
CFLAGS="$CFLAGS -DOS2"
diff --git a/eval.c b/eval.c
index 425ee5a..25ce389 100644
--- a/eval.c
+++ b/eval.c
@@ -1700,6 +1700,7 @@ rb_alias(klass, name, def)
{
VALUE origin;
NODE *orig, *body;
+ VALUE singleton = 0;
rb_frozen_class_p(klass);
if (name == def) return;
@@ -1715,6 +1716,12 @@ rb_alias(klass, name, def)
if (!orig || !orig->nd_body) {
print_undef(klass, def);
}
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ singleton = rb_iv_get(klass, "__attached__");
+ if (name == alloc && TYPE(singleton) == T_CLASS) {
+ rb_raise(rb_eNameError, "cannot make alias named `allocate'");
+ }
+ }
body = orig->nd_body;
orig->nd_cnt++;
if (nd_type(body) == NODE_FBODY) { /* was alias */
@@ -1726,9 +1733,8 @@ rb_alias(klass, name, def)
rb_clear_cache_by_id(name);
st_insert(RCLASS(klass)->m_tbl, name,
NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
- if (FL_TEST(klass, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(klass, "__attached__"),
- singleton_added, 1, ID2SYM(name));
+ if (singleton) {
+ rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
}
else {
rb_funcall(klass, added, 1, ID2SYM(name));
diff --git a/file.c b/file.c
index 719bb27..fe13a9e 100644
--- a/file.c
+++ b/file.c
@@ -2027,8 +2027,12 @@ rb_stat_become(obj, orig)
struct stat *nst;
/* need better argument type check */
- if (!rb_obj_is_kind_of(orig, rb_obj_class(obj))) {
- rb_raise(rb_eTypeError, "wrong argument type");
+ if (!rb_obj_is_instance_of(orig, rb_obj_class(obj))) {
+ rb_raise(rb_eTypeError, "wrong argument class");
+ }
+ if (DATA_PTR(obj)) {
+ free(DATA_PTR(obj));
+ DATA_PTR(obj) = 0;
}
if (DATA_PTR(orig)) {
nst = ALLOC(struct stat);
diff --git a/gc.c b/gc.c
index 678240a..1503d42 100644
--- a/gc.c
+++ b/gc.c
@@ -1356,7 +1356,7 @@ static VALUE
call_final(os, obj)
VALUE os, obj;
{
- rb_warn("ObjectSpace::call_final is deprecated; use define_finalizer");
+ rb_warn("ObjectSpace::call_finalizer is deprecated; use define_finalizer");
need_call_final = 1;
FL_SET(obj, FL_FINALIZE);
return obj;
diff --git a/hash.c b/hash.c
index e7fa574..60dc89f 100644
--- a/hash.c
+++ b/hash.c
@@ -265,9 +265,15 @@ rb_hash_become(copy, orig)
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;
}
diff --git a/lib/finalize.rb b/lib/finalize.rb
index 598569f..7d86d94 100644
--- a/lib/finalize.rb
+++ b/lib/finalize.rb
@@ -43,159 +43,144 @@
module Finalizer
RCS_ID='-$Id: finalize.rb,v 1.4 1998/02/27 05:34:33 keiju Exp keiju $-'
-
- # @dependency: {id => [[dependant, method, *opt], ...], ...}
-
- # add dependency R_method(obj, dependant)
- def add_dependency(obj, dependant, method = :finalize, *opt)
- ObjectSpace.call_finalizer(obj)
- method = method.intern unless method.kind_of?(Integer)
- assoc = [dependant, method].concat(opt)
- if dep = @dependency[obj.id]
- dep.push assoc
- else
- @dependency[obj.id] = [assoc]
+
+ class <<self
+ # @dependency: {id => [[dependant, method, *opt], ...], ...}
+
+ # add dependency R_method(obj, dependant)
+ def add_dependency(obj, dependant, method = :finalize, *opt)
+ ObjectSpace.call_finalizer(obj)
+ method = method.intern unless method.kind_of?(Integer)
+ assoc = [dependant, method].concat(opt)
+ if dep = @dependency[obj.id]
+ dep.push assoc
+ else
+ @dependency[obj.id] = [assoc]
+ end
end
- end
- alias add add_dependency
-
- # delete dependency R_method(obj, dependant)
- def delete_dependency(id, dependant, method = :finalize)
- id = id.id unless id.kind_of?(Integer)
- method = method.intern unless method.kind_of?(Integer)
- for assoc in @dependency[id]
- assoc.delete_if do
- |d, m, *o|
- d == dependant && m == method
+ alias add add_dependency
+
+ # delete dependency R_method(obj, dependant)
+ def delete_dependency(id, dependant, method = :finalize)
+ id = id.id unless id.kind_of?(Integer)
+ method = method.intern unless method.kind_of?(Integer)
+ for assoc in @dependency[id]
+ assoc.delete_if do
+ |d, m, *o|
+ d == dependant && m == method
+ end
+ @dependency.delete(id) if assoc.empty?
end
- @dependency.delete(id) if assoc.empty?
end
- end
- alias delete delete_dependency
-
- # delete dependency R_*(obj, dependant)
- def delete_all_dependency(id, dependant)
- id = id.id unless id.kind_of?(Integer)
- method = method.intern unless method.kind_of?(Integer)
- for assoc in @dependency[id]
- assoc.delete_if do
- |d, m, *o|
- d == dependant
+ alias delete delete_dependency
+
+ # delete dependency R_*(obj, dependant)
+ def delete_all_dependency(id, dependant)
+ id = id.id unless id.kind_of?(Integer)
+ method = method.intern unless method.kind_of?(Integer)
+ for assoc in @dependency[id]
+ assoc.delete_if do
+ |d, m, *o|
+ d == dependant
+ end
+ @dependency.delete(id) if assoc.empty?
end
- @dependency.delete(id) if assoc.empty?
end
- end
-
- # delete dependency R_method(*, dependant)
- def delete_by_dependant(dependant, method = :finalize)
- method = method.intern unless method.kind_of?(Integer)
- for id in @dependency.keys
- delete(id, dependant, method)
+
+ # delete dependency R_method(*, dependant)
+ def delete_by_dependant(dependant, method = :finalize)
+ method = method.intern unless method.kind_of?(Integer)
+ for id in @dependency.keys
+ delete(id, dependant, method)
+ end
end
- end
-
- # delete dependency R_*(*, dependant)
- def delete_all_by_dependant(dependant)
- for id in @dependency.keys
- delete_all_dependency(id, dependant)
+
+ # delete dependency R_*(*, dependant)
+ def delete_all_by_dependant(dependant)
+ for id in @dependency.keys
+ delete_all_dependency(id, dependant)
+ end
end
- end
-
- # finalize the depandant connected by dependency R_method(obj, dependtant)
- def finalize_dependency(id, dependant, method = :finalize)
- id = id.id unless id.kind_of?(Integer)
- method = method.intern unless method.kind_of?(Integer)
- for assocs in @dependency[id]
- assocs.delete_if do
- |d, m, *o|
- d.send(m, id, *o) if ret = d == dependant && m == method
- ret
+
+ # finalize the depandant connected by dependency R_method(obj, dependtant)
+ def finalize_dependency(id, dependant, method = :finalize)
+ id = id.id unless id.kind_of?(Integer)
+ method = method.intern unless method.kind_of?(Integer)
+ for assocs in @dependency[id]
+ assocs.delete_if do
+ |d, m, *o|
+ d.send(m, id, *o) if ret = d == dependant && m == method
+ ret
+ end
+ @dependency.delete(id) if assoc.empty?
end
- @dependency.delete(id) if assoc.empty?
end
- end
- alias finalize finalize_dependency
-
- # finalize all dependants connected by dependency R_*(obj, dependtant)
- def finalize_all_dependency(id, dependant)
- id = id.id unless id.kind_of?(Integer)
- method = method.intern unless method.kind_of?(Integer)
- for assoc in @dependency[id]
- assoc.delete_if do
- |d, m, *o|
- d.send(m, id, *o) if ret = d == dependant
+ alias finalize finalize_dependency
+
+ # finalize all dependants connected by dependency R_*(obj, dependtant)
+ def finalize_all_dependency(id, dependant)
+ id = id.id unless id.kind_of?(Integer)
+ method = method.intern unless method.kind_of?(Integer)
+ for assoc in @dependency[id]
+ assoc.delete_if do
+ |d, m, *o|
+ d.send(m, id, *o) if ret = d == dependant
+ end
+ @dependency.delete(id) if assoc.empty?
end
- @dependency.delete(id) if assoc.empty?
end
- end
-
- # finalize the dependant connected by dependency R_method(*, dependtant)
- def finalize_by_dependant(dependant, method = :finalize)
- method = method.intern unless method.kind_of?(Integer)
- for id in @dependency.keys
- finalize(id, dependant, method)
+
+ # finalize the dependant connected by dependency R_method(*, dependtant)
+ def finalize_by_dependant(dependant, method = :finalize)
+ method = method.intern unless method.kind_of?(Integer)
+ for id in @dependency.keys
+ finalize(id, dependant, method)
+ end
end
- end
-
- # finalize all dependants connected by dependency R_*(*, dependtant)
- def finalize_all_by_dependant(dependant)
- for id in @dependency.keys
- finalize_all_dependency(id, dependant)
+
+ # finalize all dependants connected by dependency R_*(*, dependtant)
+ def finalize_all_by_dependant(dependant)
+ for id in @dependency.keys
+ finalize_all_dependency(id, dependant)
+ end
end
- end
-
- # finalize all dependants registered to the Finalizer.
- def finalize_all
- for id, assocs in @dependency
- for dependant, method, *opt in assocs
- dependant.send(method, id, *opt)
+
+ # finalize all dependants registered to the Finalizer.
+ def finalize_all
+ for id, assocs in @dependency
+ for dependant, method, *opt in assocs
+ dependant.send(method, id, *opt)
+ end
+ assocs.clear
end
- assocs.clear
end
- end
-
- # method to call finalize_* safely.
- def safe
- old_status = Thread.critical
- Thread.critical = true
- ObjectSpace.remove_finalizer(@proc)
- yield
- ObjectSpace.add_finalizer(@proc)
- Thread.critical = old_status
- end
-
- # registering function to ObjectSpace#add_finalizer
- def final_of(id)
- if assocs = @dependency.delete(id)
- for dependant, method, *opt in assocs
- dependant.send(method, id, *opt)
+
+ # method to call finalize_* safely.
+ def safe
+ old_status = Thread.critical
+ Thread.critical = true
+ ObjectSpace.remove_finalizer(@proc)
+ begin
+ yield
+ ensure
+ ObjectSpace.add_finalizer(@proc)
+ Thread.critical = old_status
+ end
+ end
+
+ private
+
+ # registering function to ObjectSpace#add_finalizer
+ def final_of(id)
+ if assocs = @dependency.delete(id)
+ for dependant, method, *opt in assocs
+ dependant.send(method, id, *opt)
+ end
end
end
+
end
-
@dependency = Hash.new
@proc = proc{|id| final_of(id)}
ObjectSpace.add_finalizer(@proc)
-
- module_function :add
- module_function :add_dependency
-
- module_function :delete
- module_function :delete_dependency
- module_function :delete_all_dependency
- module_function :delete_by_dependant
- module_function :delete_all_by_dependant
-
- module_function :finalize
- module_function :finalize_dependency
- module_function :finalize_all_dependency
- module_function :finalize_by_dependant
- module_function :finalize_all_by_dependant
- module_function :finalize_all
-
- module_function :safe
-
- module_function :final_of
- private_class_method :final_of
-
end
diff --git a/marshal.c b/marshal.c
index 3b4761e..78d801b 100644
--- a/marshal.c
+++ b/marshal.c
@@ -466,11 +466,15 @@ w_object(obj, arg, limit)
case T_HASH:
w_uclass(obj, rb_cHash, arg);
- if (!NIL_P(RHASH(obj)->ifnone)) {
- w_byte(TYPE_HASH_DEF, arg);
+ if (NIL_P(RHASH(obj)->ifnone)) {
+ w_byte(TYPE_HASH, arg);
+ }
+ else if (FL_TEST(obj, FL_USER2)) {
+ /* FL_USER2 means HASH_PROC_DEFAULT (see hash.c) */
+ rb_raise(rb_eArgError, "cannot dump hash with default proc");
}
else {
- w_byte(TYPE_HASH, arg);
+ w_byte(TYPE_HASH_DEF, arg);
}
w_long(RHASH(obj)->tbl->num_entries, arg);
st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
@@ -1047,12 +1051,17 @@ r_object0(arg, proc)
VALUE klass;
klass = rb_path2class(r_unique(arg));
- if (!rb_respond_to(klass, s_alloc)) {
- rb_raise(rb_eTypeError,
- "class %s needs to have class method `_alloc'",
- rb_class2name(klass));
+ if (rb_respond_to(klass, s_alloc)) {
+ static int warn = Qtrue;
+ if (warn) {
+ rb_warn("define `allocate' instead of `_alloc'");
+ warn = Qfalse;
+ }
+ v = rb_funcall(klass, s_alloc, 0);
}
- v = rb_funcall(klass, s_alloc, 0);
+ else {
+ v = rb_obj_alloc(klass);
+ }
if (TYPE(v) != T_DATA) {
rb_raise(rb_eArgError, "dump format error");
}
diff --git a/re.c b/re.c
index 60f8140..0b0c899 100644
--- a/re.c
+++ b/re.c
@@ -1333,7 +1333,7 @@ rb_reg_become(clone, re)
VALUE re;
{
/* need better argument type check */
- if (!rb_obj_is_kind_of(re, rb_obj_class(clone))) {
+ if (!rb_obj_is_instance_of(re, rb_obj_class(clone))) {
rb_raise(rb_eTypeError, "wrong argument type");
}
RREGEXP(clone)->ptr = 0;
diff --git a/ruby.h b/ruby.h
index 3b74185..7829b85 100644
--- a/ruby.h
+++ b/ruby.h
@@ -211,6 +211,7 @@ void rb_check_type _((VALUE,int));
VALUE rb_str_to_str _((VALUE));
VALUE rb_string_value _((volatile VALUE*));
+char *rb_string_value_ptr _((volatile VALUE*));
#define StringValue(v) if (TYPE(v) != T_STRING) rb_string_value(&(v))
void rb_check_safe_str _((VALUE));
@@ -218,7 +219,7 @@ void rb_check_safe_str _((VALUE));
StringValue(v);\
rb_check_safe_str(v);\
} while (0)
-#define StringValuePtr(v) RSTRING((TYPE(v) == T_STRING) ? (v) : rb_string_value(&(v)))->ptr
+#define StringValuePtr(v) rb_string_value_ptr(&(v))
/* obsolete macro - use SafeStringValue(v) */
#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
diff --git a/string.c b/string.c
index 2ef8de5..b036cb5 100644
--- a/string.c
+++ b/string.c
@@ -440,6 +440,21 @@ rb_string_value(ptr)
return *ptr = rb_str_to_str(*ptr);
}
+char *
+rb_string_value_ptr(ptr)
+ volatile VALUE *ptr;
+{
+ VALUE s = *ptr;
+ if (TYPE(s) != T_STRING) {
+ s = rb_str_to_str(s);
+ *ptr = s;
+ }
+ if (!RSTRING(s)->ptr) {
+ str_make_independent(s);
+ }
+ return RSTRING(s)->ptr;
+}
+
VALUE
rb_str_substr(str, beg, len)
VALUE str;
@@ -1609,18 +1624,17 @@ rb_str_replace(str, str2)
}
RSTRING(str)->len = RSTRING(str2)->len;
RSTRING(str)->ptr = RSTRING(str2)->ptr;
- if (FL_TEST(str2, ELTS_SHARED|STR_ASSOC)) {
- FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
- RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
- }
- else {
- RSTRING(str)->aux.capa = RSTRING(str2)->aux.capa;
- }
+ FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
+ RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
}
else {
rb_str_modify(str);
rb_str_resize(str, RSTRING(str2)->len);
memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ if (FL_TEST(str2, STR_ASSOC)) {
+ FL_SET(str, RBASIC(str2)->flags & (ELTS_SHARED|STR_ASSOC));
+ RSTRING(str)->aux.shared = RSTRING(str2)->aux.shared;
+ }
}
OBJ_INFECT(str, str2);
diff --git a/struct.c b/struct.c
index 1a378c8..4378196 100644
--- a/struct.c
+++ b/struct.c
@@ -424,8 +424,8 @@ static VALUE
rb_struct_become(clone, s)
VALUE clone, s;
{
- if (!rb_obj_is_kind_of(s, rb_obj_class(clone))) {
- rb_raise(rb_eTypeError, "wrong argument type");
+ if (!rb_obj_is_instance_of(s, rb_obj_class(clone))) {
+ rb_raise(rb_eTypeError, "wrong argument class");
}
RSTRUCT(clone)->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len);
RSTRUCT(clone)->len = RSTRUCT(s)->len;