1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* variable.c (rb_path2class): should not use rb_eval_string().

* marshal.c (w_extended): should allow marshaling of object which
  is extended by named module.

* class.c (rb_make_metaclass): super may be T_ICLASS, need to skip.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2799 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2002-09-05 09:42:56 +00:00
parent 61ec0281a4
commit 49cd091cf2
5 changed files with 122 additions and 51 deletions

View file

@ -1,8 +1,19 @@
Thu Sep 5 18:32:32 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
* variable.c (rb_path2class): should not use rb_eval_string().
Thu Sep 5 17:18:22 2002 Michal Rokos <michal@ruby-lang.org>
* dln.c: fix memory leak in dln_load (ruby-core:405) and
in load_1 (ruby-core:407)
Thu Sep 5 15:43:54 2002 Yukihiro Matsumoto <matz@ruby-lang.org>
* marshal.c (w_extended): should allow marshaling of object which
is extended by named module.
* class.c (rb_make_metaclass): super may be T_ICLASS, need to skip.
Thu Sep 5 13:09:22 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* eval.c (rb_eval): overriding false constant with class/module

1
ToDo
View file

@ -106,6 +106,7 @@ Standard Libraries
* deprecate Array#indexes, and Array#indices.
* require "1.6" etc. by /usr/lib/ruby/1.6/1.6.rb ;-)
* save both "feature names" and "normalized path" in $"
* allow marshaling of extend'ed object.
Extension Libraries

View file

@ -150,7 +150,7 @@ rb_make_metaclass(obj, super)
if (BUILTIN_TYPE(obj) == T_CLASS) {
RBASIC(klass)->klass = klass;
if (FL_TEST(obj, FL_SINGLETON)) {
RCLASS(klass)->super = RBASIC(RCLASS(obj)->super)->klass;
RCLASS(klass)->super = RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
}
}

122
marshal.c
View file

@ -50,9 +50,10 @@ shortlen(len, ds)
#define TYPE_FALSE 'F'
#define TYPE_FIXNUM 'i'
#define TYPE_EXTENDED 'e'
#define TYPE_UCLASS 'C'
#define TYPE_OBJECT 'o'
#define TYPE_DATA 'd'
#define TYPE_DATA 'd'
#define TYPE_USERDEF 'u'
#define TYPE_USRMARHAL 'U'
#define TYPE_FLOAT 'f'
@ -250,19 +251,38 @@ obj_each(id, value, arg)
}
static void
w_class(obj, arg)
w_extended(klass, arg)
VALUE klass;
struct dump_arg *arg;
{
char *path;
if (FL_TEST(klass, FL_SINGLETON)) {
if (RCLASS(klass)->m_tbl->num_entries ||
(RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries > 1)) {
rb_raise(rb_eTypeError, "singleton can't be dumped");
}
klass = RCLASS(klass)->super;
}
while (BUILTIN_TYPE(klass) == T_ICLASS) {
path = rb_class2name(RBASIC(klass)->klass);
w_byte(TYPE_EXTENDED, arg);
w_unique(path, arg);
klass = RCLASS(klass)->super;
}
}
static void
w_class(type, obj, arg)
int type;
VALUE obj;
struct dump_arg *arg;
{
VALUE klass = CLASS_OF(obj);
char *path;
while (FL_TEST(klass, FL_SINGLETON) || BUILTIN_TYPE(klass) == T_ICLASS) {
if (RCLASS(klass)->m_tbl->num_entries > 0 ||
RCLASS(klass)->iv_tbl->num_entries > 1) {
rb_raise(rb_eTypeError, "singleton can't be dumped");
}
}
VALUE klass = CLASS_OF(obj);
w_extended(klass, arg);
w_byte(type, arg);
path = rb_class2name(klass);
w_unique(path, arg);
}
@ -275,14 +295,7 @@ w_uclass(obj, base_klass, arg)
VALUE klass = CLASS_OF(obj);
char *path;
while (FL_TEST(klass, FL_SINGLETON) || BUILTIN_TYPE(klass) == T_ICLASS) {
if (RCLASS(klass)->m_tbl->num_entries > 0 ||
RCLASS(klass)->iv_tbl->num_entries > 1) {
rb_raise(rb_eTypeError, "singleton can't be dumped");
}
klass = RCLASS(klass)->super;
}
w_extended(klass, arg);
if (klass != base_klass) {
w_byte(TYPE_UCLASS, arg);
w_unique(rb_class2name(CLASS_OF(obj)), arg);
@ -504,17 +517,15 @@ w_object(obj, arg, limit)
break;
case T_OBJECT:
w_byte(TYPE_OBJECT, arg);
w_class(obj, arg);
w_class(TYPE_OBJECT, obj, arg);
w_ivar(ROBJECT(obj)->iv_tbl, &c_arg);
break;
case T_DATA:
w_byte(TYPE_DATA, arg);
{
VALUE v;
w_class(obj, arg);
w_class(TYPE_DATA, obj, arg);
if (!rb_respond_to(obj, s_dump_data)) {
rb_raise(rb_eTypeError,
"class %s needs to have instance method `_dump_data'",
@ -804,6 +815,30 @@ r_ivar(obj, arg)
}
}
static VALUE
path2class(path)
char *path;
{
VALUE v = rb_path2class(path);
if (TYPE(v) != T_CLASS) {
rb_raise(rb_eTypeError, "%s does not refer class", path);
}
return v;
}
static VALUE
path2module(path)
char *path;
{
VALUE v = rb_path2class(path);
if (TYPE(v) != T_MODULE) {
rb_raise(rb_eTypeError, "%s does not refer module", path);
}
return v;
}
static VALUE
r_object0(arg, proc)
struct load_arg *arg;
@ -827,9 +862,18 @@ r_object0(arg, proc)
r_ivar(v, arg);
break;
case TYPE_EXTENDED:
{
VALUE m = path2module(r_unique(arg));
v = r_object0(arg, 0);
rb_extend_object(v, m);
}
break;
case TYPE_UCLASS:
{
VALUE c = rb_path2class(r_unique(arg));
VALUE c = path2class(r_unique(arg));
v = r_object0(arg, 0);
if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
@ -973,7 +1017,7 @@ r_object0(arg, proc)
long len;
ID slot;
klass = rb_path2class(r_unique(arg));
klass = path2class(r_unique(arg));
mem = rb_struct_iv_get(klass, "__member__");
if (mem == Qnil) {
rb_raise(rb_eTypeError, "uninitialized struct");
@ -1002,9 +1046,8 @@ r_object0(arg, proc)
case TYPE_USERDEF:
{
VALUE klass;
VALUE klass = path2class(r_unique(arg));
klass = rb_path2class(r_unique(arg));
if (!rb_respond_to(klass, s_load)) {
rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
rb_class2name(klass));
@ -1016,9 +1059,8 @@ r_object0(arg, proc)
case TYPE_OBJECT:
{
VALUE klass;
VALUE klass = path2class(r_unique(arg));
klass = rb_path2class(r_unique(arg));
v = rb_obj_alloc(klass);
if (TYPE(v) != T_OBJECT) {
rb_raise(rb_eArgError, "dump format error");
@ -1030,9 +1072,7 @@ r_object0(arg, proc)
case TYPE_DATA:
{
VALUE klass;
klass = rb_path2class(r_unique(arg));
VALUE klass = path2class(r_unique(arg));
if (rb_respond_to(klass, s_alloc)) {
static int warn = Qtrue;
if (warn) {
@ -1059,29 +1099,27 @@ r_object0(arg, proc)
case TYPE_MODULE_OLD:
{
volatile VALUE str = r_bytes(arg);
v = r_regist(rb_path2class(RSTRING(str)->ptr), arg);
VALUE str = r_bytes(arg);
v = path2module(RSTRING(str)->ptr);
r_regist(v, arg);
}
break;
case TYPE_CLASS:
{
volatile VALUE str = r_bytes(arg);
v = rb_path2class(RSTRING(str)->ptr);
if (TYPE(v) != T_CLASS) {
rb_raise(rb_eTypeError, "%s is not a class", RSTRING(str)->ptr);
}
VALUE str = r_bytes(arg);
v = path2class(RSTRING(str)->ptr);
r_regist(v, arg);
}
break;
case TYPE_MODULE:
{
volatile VALUE str = r_bytes(arg);
v = rb_path2class(RSTRING(str)->ptr);
if (TYPE(v) != T_MODULE) {
rb_raise(rb_eTypeError, "%s is not a module", RSTRING(str)->ptr);
}
VALUE str = r_bytes(arg);
v = path2module(RSTRING(str)->ptr);
r_regist(v, arg);
}
break;

View file

@ -229,19 +229,40 @@ VALUE
rb_path2class(path)
const char *path;
{
VALUE c;
const char *pbeg, *p;
ID id;
VALUE c = rb_cObject;
if (path[0] == '#') {
rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
}
c = rb_eval_string(path);
switch (TYPE(c)) {
case T_MODULE:
case T_CLASS:
break;
default:
rb_raise(rb_eTypeError, "class path %s does not point class", path);
pbeg = p = path;
while (*p) {
VALUE str;
while (*p && *p != ':') p++;
str = rb_str_new(pbeg, p-pbeg);
id = rb_intern(RSTRING(str)->ptr);
if (p[0] == ':') {
if (p[1] != ':') goto undefined_class;
p += 2;
pbeg = p;
}
if (!rb_const_defined(c, id)) {
undefined_class:
rb_raise(rb_eArgError, "undefined class/module %s", rb_id2name(id));
rb_raise(rb_eArgError, "undefined class/module %s", path);
}
c = rb_const_get_at(c, id);
switch (TYPE(c)) {
case T_MODULE:
case T_CLASS:
break;
default:
rb_raise(rb_eTypeError, "%s does not refer class/module %d", path, TYPE(c));
}
}
return c;
}