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:
parent
61ec0281a4
commit
49cd091cf2
5 changed files with 122 additions and 51 deletions
11
ChangeLog
11
ChangeLog
|
@ -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
1
ToDo
|
@ -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
|
||||
|
||||
|
|
2
class.c
2
class.c
|
@ -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
122
marshal.c
|
@ -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;
|
||||
|
|
37
variable.c
37
variable.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue