2000-05-01 05:42:38 -04:00
|
|
|
/**********************************************************************
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
class.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
$Date$
|
|
|
|
created at: Tue Aug 10 15:05:44 JST 1993
|
|
|
|
|
2003-01-16 02:34:03 -05:00
|
|
|
Copyright (C) 1993-2003 Yukihiro Matsumoto
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-05-01 05:42:38 -04:00
|
|
|
**********************************************************************/
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
#include "ruby.h"
|
2000-07-27 05:49:34 -04:00
|
|
|
#include "rubysig.h"
|
1998-01-16 07:13:05 -05:00
|
|
|
#include "node.h"
|
|
|
|
#include "st.h"
|
1999-01-19 23:59:39 -05:00
|
|
|
#include <ctype.h>
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
extern st_table *rb_class_tbl;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
VALUE
|
2001-07-18 01:56:05 -04:00
|
|
|
rb_class_boot(super)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE super;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
NEWOBJ(klass, struct RClass);
|
1999-01-19 23:59:39 -05:00
|
|
|
OBJSETUP(klass, rb_cClass, T_CLASS);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
klass->super = super;
|
|
|
|
klass->iv_tbl = 0;
|
|
|
|
klass->m_tbl = 0; /* safe GC */
|
1999-01-19 23:59:39 -05:00
|
|
|
klass->m_tbl = st_init_numtable();
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-08-14 04:13:31 -04:00
|
|
|
OBJ_INFECT(klass, super);
|
1998-01-16 07:19:22 -05:00
|
|
|
return (VALUE)klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2001-07-18 01:56:05 -04:00
|
|
|
VALUE
|
|
|
|
rb_class_new(super)
|
|
|
|
VALUE super;
|
|
|
|
{
|
|
|
|
Check_Type(super, T_CLASS);
|
|
|
|
if (super == rb_cClass) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of Class");
|
|
|
|
}
|
|
|
|
if (FL_TEST(super, FL_SINGLETON)) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of virtual class");
|
|
|
|
}
|
|
|
|
return rb_class_boot(super);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
static int
|
|
|
|
clone_method(mid, body, tbl)
|
|
|
|
ID mid;
|
|
|
|
NODE *body;
|
|
|
|
st_table *tbl;
|
|
|
|
{
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex));
|
1998-01-16 07:13:05 -05:00
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2001-05-02 00:22:21 -04:00
|
|
|
VALUE
|
|
|
|
rb_mod_clone(module)
|
|
|
|
VALUE module;
|
|
|
|
{
|
2002-03-08 02:03:09 -05:00
|
|
|
NEWOBJ(clone, struct RClass);
|
|
|
|
CLONESETUP(clone, module);
|
2001-05-02 00:22:21 -04:00
|
|
|
|
2001-10-03 03:19:19 -04:00
|
|
|
RCLASS(clone)->super = RCLASS(module)->super;
|
2001-05-02 00:22:21 -04:00
|
|
|
if (RCLASS(module)->iv_tbl) {
|
2001-10-22 02:48:18 -04:00
|
|
|
ID id;
|
|
|
|
|
2001-10-03 03:19:19 -04:00
|
|
|
RCLASS(clone)->iv_tbl = st_copy(RCLASS(module)->iv_tbl);
|
2001-10-22 02:48:18 -04:00
|
|
|
id = rb_intern("__classpath__");
|
|
|
|
st_delete(RCLASS(clone)->iv_tbl, &id, 0);
|
|
|
|
id = rb_intern("__classid__");
|
|
|
|
st_delete(RCLASS(clone)->iv_tbl, &id, 0);
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
if (RCLASS(module)->m_tbl) {
|
2001-10-03 03:19:19 -04:00
|
|
|
RCLASS(clone)->m_tbl = st_init_numtable();
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_foreach(RCLASS(module)->m_tbl, clone_method,
|
|
|
|
(st_data_t)RCLASS(clone)->m_tbl);
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
|
2002-03-08 02:03:09 -05:00
|
|
|
return (VALUE)clone;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_mod_dup(mod)
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
VALUE dup = rb_mod_clone(mod);
|
2001-12-10 02:18:16 -05:00
|
|
|
|
2002-08-27 04:31:08 -04:00
|
|
|
RBASIC(dup)->flags = RBASIC(mod)->flags & (T_MASK|FL_TAINT|FL_SINGLETON);
|
2001-05-02 00:22:21 -04:00
|
|
|
return dup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
2002-09-03 01:20:14 -04:00
|
|
|
rb_singleton_class_clone(obj)
|
|
|
|
VALUE obj;
|
2001-05-02 00:22:21 -04:00
|
|
|
{
|
2002-09-03 01:20:14 -04:00
|
|
|
VALUE klass = RBASIC(obj)->klass;
|
2001-05-02 00:22:21 -04:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
if (!FL_TEST(klass, FL_SINGLETON))
|
|
|
|
return klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
else {
|
|
|
|
/* copy singleton(unnamed) class */
|
|
|
|
NEWOBJ(clone, struct RClass);
|
2002-09-03 01:20:14 -04:00
|
|
|
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);
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
clone->super = RCLASS(klass)->super;
|
1998-01-16 07:13:05 -05:00
|
|
|
clone->iv_tbl = 0;
|
|
|
|
clone->m_tbl = 0;
|
2001-03-28 03:43:25 -05:00
|
|
|
if (RCLASS(klass)->iv_tbl) {
|
|
|
|
clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
clone->m_tbl = st_init_numtable();
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 10:55:43 -05:00
|
|
|
st_foreach(RCLASS(klass)->m_tbl, clone_method,
|
|
|
|
(st_data_t)clone->m_tbl);
|
2002-09-03 01:20:14 -04:00
|
|
|
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
|
1998-01-16 07:13:05 -05:00
|
|
|
FL_SET(clone, FL_SINGLETON);
|
|
|
|
return (VALUE)clone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_singleton_class_attached(klass, obj)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass, obj;
|
|
|
|
{
|
2001-05-02 00:22:21 -04:00
|
|
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
|
|
|
if (!RCLASS(klass)->iv_tbl) {
|
|
|
|
RCLASS(klass)->iv_tbl = st_init_numtable();
|
|
|
|
}
|
|
|
|
st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
2002-01-10 15:18:39 -05:00
|
|
|
VALUE
|
2002-09-03 01:20:14 -04:00
|
|
|
rb_make_metaclass(obj, super)
|
|
|
|
VALUE obj, super;
|
2002-01-10 15:18:39 -05:00
|
|
|
{
|
2002-09-03 01:20:14 -04:00
|
|
|
VALUE klass = rb_class_boot(super);
|
|
|
|
FL_SET(klass, FL_SINGLETON);
|
2002-01-10 15:18:39 -05:00
|
|
|
RBASIC(obj)->klass = klass;
|
|
|
|
rb_singleton_class_attached(klass, obj);
|
2002-09-25 03:03:05 -04:00
|
|
|
if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
|
2002-09-03 01:20:14 -04:00
|
|
|
RBASIC(klass)->klass = klass;
|
2002-09-25 03:03:05 -04:00
|
|
|
RCLASS(klass)->super = RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
|
|
|
|
}
|
|
|
|
else {
|
2002-09-27 22:41:05 -04:00
|
|
|
VALUE metasuper = RBASIC(rb_class_real(super))->klass;
|
|
|
|
|
|
|
|
/* metaclass of a superclass may be NULL at boot time */
|
|
|
|
if (metasuper) {
|
2002-10-01 04:14:03 -04:00
|
|
|
RBASIC(klass)->klass = metasuper;
|
2002-09-27 22:41:05 -04:00
|
|
|
}
|
2002-09-03 01:20:14 -04:00
|
|
|
}
|
|
|
|
|
2002-01-10 15:18:39 -05:00
|
|
|
return klass;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE
|
|
|
|
rb_define_class_id(id, super)
|
|
|
|
ID id;
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE super;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!super) super = rb_cObject;
|
|
|
|
klass = rb_class_new(super);
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_name_class(klass, id);
|
2002-01-10 15:18:39 -05:00
|
|
|
rb_make_metaclass(klass, RBASIC(super)->klass);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
return klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2002-01-10 15:18:39 -05:00
|
|
|
VALUE
|
|
|
|
rb_class_inherited(super, klass)
|
|
|
|
VALUE super, klass;
|
|
|
|
{
|
2002-01-15 21:20:25 -05:00
|
|
|
if (!super) super = rb_cObject;
|
2002-01-10 15:18:39 -05:00
|
|
|
return rb_funcall(super, rb_intern("inherited"), 1, klass);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE
|
|
|
|
rb_define_class(name, super)
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE super;
|
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2002-03-19 04:03:11 -05:00
|
|
|
if (rb_autoload_defined(id)) {
|
|
|
|
rb_autoload_load(id);
|
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (rb_const_defined(rb_cObject, id)) {
|
|
|
|
klass = rb_const_get(rb_cObject, id);
|
2001-12-18 03:47:06 -05:00
|
|
|
if (TYPE(klass) != T_CLASS) {
|
|
|
|
rb_raise(rb_eTypeError, "%s is not a class", name);
|
|
|
|
}
|
|
|
|
if (rb_class_real(RCLASS(klass)->super) != super) {
|
|
|
|
rb_name_error(id, "%s is already defined", name);
|
|
|
|
}
|
|
|
|
return klass;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
2002-02-17 09:44:14 -05:00
|
|
|
if (!super) {
|
|
|
|
rb_warn("no super class for `%s', Object assumed", name);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
klass = rb_define_class_id(id, super);
|
|
|
|
st_add_direct(rb_class_tbl, id, klass);
|
2003-01-07 02:36:40 -05:00
|
|
|
rb_class_inherited(super, klass);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
return klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_class_under(outer, name, super)
|
|
|
|
VALUE outer;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE super;
|
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2001-05-02 00:22:21 -04:00
|
|
|
if (rb_const_defined_at(outer, id)) {
|
|
|
|
klass = rb_const_get(outer, id);
|
2001-12-18 03:47:06 -05:00
|
|
|
if (TYPE(klass) != T_CLASS) {
|
|
|
|
rb_raise(rb_eTypeError, "%s is not a class", name);
|
|
|
|
}
|
|
|
|
if (rb_class_real(RCLASS(klass)->super) != super) {
|
|
|
|
rb_name_error(id, "%s is already defined", name);
|
|
|
|
}
|
|
|
|
return klass;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
2002-02-17 09:44:14 -05:00
|
|
|
if (!super) {
|
|
|
|
rb_warn("no super class for `%s::%s', Object assumed",
|
|
|
|
rb_class2name(outer), name);
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
klass = rb_define_class_id(id, super);
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_set_class_path(klass, outer, name);
|
2002-01-10 15:18:39 -05:00
|
|
|
rb_const_set(outer, id, klass);
|
2003-01-07 02:36:40 -05:00
|
|
|
rb_class_inherited(super, klass);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
return klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_module_new()
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
NEWOBJ(mdl, struct RClass);
|
1999-01-19 23:59:39 -05:00
|
|
|
OBJSETUP(mdl, rb_cModule, T_MODULE);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
mdl->super = 0;
|
|
|
|
mdl->iv_tbl = 0;
|
|
|
|
mdl->m_tbl = 0;
|
1999-01-19 23:59:39 -05:00
|
|
|
mdl->m_tbl = st_init_numtable();
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return (VALUE)mdl;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_define_module_id(id)
|
|
|
|
ID id;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE mdl;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
mdl = rb_module_new();
|
1998-01-16 07:13:05 -05:00
|
|
|
rb_name_class(mdl, id);
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
return mdl;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_define_module(name)
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
VALUE module;
|
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2002-03-19 04:03:11 -05:00
|
|
|
if (rb_autoload_defined(id)) {
|
|
|
|
rb_autoload_load(id);
|
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (rb_const_defined(rb_cObject, id)) {
|
|
|
|
module = rb_const_get(rb_cObject, id);
|
|
|
|
if (TYPE(module) == T_MODULE)
|
|
|
|
return module;
|
2003-01-30 23:00:17 -05:00
|
|
|
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
module = rb_define_module_id(id);
|
|
|
|
st_add_direct(rb_class_tbl, id, module);
|
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_module_under(outer, name)
|
|
|
|
VALUE outer;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
|
|
|
VALUE module;
|
|
|
|
ID id;
|
|
|
|
|
|
|
|
id = rb_intern(name);
|
2002-01-07 00:27:01 -05:00
|
|
|
if (rb_const_defined_at(outer, id)) {
|
|
|
|
module = rb_const_get(outer, id);
|
2001-05-02 00:22:21 -04:00
|
|
|
if (TYPE(module) == T_MODULE)
|
|
|
|
return module;
|
|
|
|
rb_raise(rb_eTypeError, "%s::%s is not a module",
|
2003-01-30 23:00:17 -05:00
|
|
|
rb_class2name(outer), rb_obj_classname(module));
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
module = rb_define_module_id(id);
|
1999-12-14 01:50:43 -05:00
|
|
|
rb_const_set(outer, id, module);
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_set_class_path(module, outer, name);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static VALUE
|
1998-01-16 07:13:05 -05:00
|
|
|
include_class_new(module, super)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE module, super;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
NEWOBJ(klass, struct RClass);
|
1999-01-19 23:59:39 -05:00
|
|
|
OBJSETUP(klass, rb_cClass, T_ICLASS);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-07-11 04:22:18 -04:00
|
|
|
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
|
|
|
module = RBASIC(module)->klass;
|
|
|
|
}
|
1999-08-13 01:45:20 -04:00
|
|
|
if (!RCLASS(module)->iv_tbl) {
|
|
|
|
RCLASS(module)->iv_tbl = st_init_numtable();
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
klass->iv_tbl = RCLASS(module)->iv_tbl;
|
1999-08-13 01:45:20 -04:00
|
|
|
klass->m_tbl = RCLASS(module)->m_tbl;
|
1998-01-16 07:19:22 -05:00
|
|
|
klass->super = super;
|
1998-01-16 07:13:05 -05:00
|
|
|
if (TYPE(module) == T_ICLASS) {
|
1999-01-19 23:59:39 -05:00
|
|
|
RBASIC(klass)->klass = RBASIC(module)->klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
RBASIC(klass)->klass = module;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2001-08-14 04:13:31 -04:00
|
|
|
OBJ_INFECT(klass, module);
|
|
|
|
OBJ_INFECT(klass, super);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
return (VALUE)klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_include_module(klass, module)
|
|
|
|
VALUE klass, module;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2001-09-08 10:17:53 -04:00
|
|
|
VALUE p, c;
|
2001-03-28 03:43:25 -05:00
|
|
|
int changed = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2001-05-02 00:22:21 -04:00
|
|
|
rb_frozen_class_p(klass);
|
|
|
|
if (!OBJ_TAINTED(klass)) {
|
|
|
|
rb_secure(4);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
if (NIL_P(module)) return;
|
1999-01-19 23:59:39 -05:00
|
|
|
if (klass == module) return;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2002-12-19 04:20:20 -05:00
|
|
|
if (TYPE(module) != T_MODULE) {
|
1998-01-16 07:13:05 -05:00
|
|
|
Check_Type(module, T_MODULE);
|
|
|
|
}
|
|
|
|
|
2001-08-14 04:13:31 -04:00
|
|
|
OBJ_INFECT(klass, module);
|
2001-09-08 10:17:53 -04:00
|
|
|
c = klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
while (module) {
|
2002-07-11 04:22:18 -04:00
|
|
|
int superclass_seen = Qfalse;
|
|
|
|
|
2002-01-25 03:22:11 -05:00
|
|
|
if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
|
|
|
|
rb_raise(rb_eArgError, "cyclic include detected");
|
1998-01-16 07:13:05 -05:00
|
|
|
/* ignore if the module included already in superclasses */
|
1998-01-16 07:19:22 -05:00
|
|
|
for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
|
2002-07-11 04:22:18 -04:00
|
|
|
switch (BUILTIN_TYPE(p)) {
|
|
|
|
case T_ICLASS:
|
2002-02-19 02:47:07 -05:00
|
|
|
if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
|
2002-07-11 04:22:18 -04:00
|
|
|
if (!superclass_seen) {
|
|
|
|
c = p; /* move insertion point */
|
|
|
|
}
|
2002-01-25 03:22:11 -05:00
|
|
|
goto skip;
|
2002-02-19 02:47:07 -05:00
|
|
|
}
|
2002-07-11 04:22:18 -04:00
|
|
|
break;
|
|
|
|
case T_CLASS:
|
|
|
|
superclass_seen = Qtrue;
|
|
|
|
break;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2002-07-11 04:22:18 -04:00
|
|
|
c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
|
2001-03-28 03:43:25 -05:00
|
|
|
changed = 1;
|
2001-09-08 10:17:53 -04:00
|
|
|
skip:
|
|
|
|
module = RCLASS(module)->super;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2001-03-28 03:43:25 -05:00
|
|
|
if (changed) rb_clear_cache();
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_mod_included_modules(mod)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE mod;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE ary = rb_ary_new();
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE p;
|
|
|
|
|
|
|
|
for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
|
|
|
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, RBASIC(p)->klass);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2001-07-24 05:07:33 -04:00
|
|
|
VALUE
|
|
|
|
rb_mod_include_p(mod, mod2)
|
|
|
|
VALUE mod;
|
|
|
|
VALUE mod2;
|
|
|
|
{
|
|
|
|
VALUE p;
|
|
|
|
|
|
|
|
Check_Type(mod2, T_MODULE);
|
|
|
|
for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
|
|
|
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
|
|
|
if (RBASIC(p)->klass == mod2) return Qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_mod_ancestors(mod)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE mod;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE ary = rb_ary_new();
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE p;
|
|
|
|
|
|
|
|
for (p = mod; p; p = RCLASS(p)->super) {
|
1999-01-19 23:59:39 -05:00
|
|
|
if (FL_TEST(p, FL_SINGLETON))
|
|
|
|
continue;
|
1998-01-16 07:19:22 -05:00
|
|
|
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, RBASIC(p)->klass);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, p);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2002-10-30 03:04:32 -05:00
|
|
|
#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static int
|
|
|
|
ins_methods_i(key, body, ary)
|
|
|
|
ID key;
|
|
|
|
NODE *body;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
2002-12-24 03:02:00 -05:00
|
|
|
if (key == ID_ALLOCATOR) return ST_CONTINUE;
|
2002-10-30 03:04:32 -05:00
|
|
|
if (!body->nd_body) {
|
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
}
|
|
|
|
else if (!VISI_CHECK(body->nd_noex, NOEX_PRIVATE)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE name = rb_str_new2(rb_id2name(key));
|
1998-01-16 07:19:22 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!rb_ary_includes(ary, name)) {
|
|
|
|
rb_ary_push(ary, name);
|
|
|
|
}
|
|
|
|
}
|
2002-10-30 03:04:32 -05:00
|
|
|
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ins_methods_prot_i(key, body, ary)
|
|
|
|
ID key;
|
|
|
|
NODE *body;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
2002-12-24 03:02:00 -05:00
|
|
|
if (key == ID_ALLOCATOR) return ST_CONTINUE;
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!body->nd_body) {
|
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
}
|
2002-10-30 03:04:32 -05:00
|
|
|
else if (VISI_CHECK(body->nd_noex, NOEX_PROTECTED)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE name = rb_str_new2(rb_id2name(key));
|
|
|
|
|
|
|
|
if (!rb_ary_includes(ary, name)) {
|
|
|
|
rb_ary_push(ary, name);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ins_methods_priv_i(key, body, ary)
|
|
|
|
ID key;
|
|
|
|
NODE *body;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
2002-12-24 03:02:00 -05:00
|
|
|
if (key == ID_ALLOCATOR) return ST_CONTINUE;
|
1998-01-16 07:19:22 -05:00
|
|
|
if (!body->nd_body) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
2002-10-30 03:04:32 -05:00
|
|
|
else if (VISI_CHECK(body->nd_noex, NOEX_PRIVATE)) {
|
|
|
|
VALUE name = rb_str_new2(rb_id2name(key));
|
|
|
|
|
|
|
|
if (!rb_ary_includes(ary, name)) {
|
|
|
|
rb_ary_push(ary, name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
|
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ins_methods_pub_i(key, body, ary)
|
|
|
|
ID key;
|
|
|
|
NODE *body;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
2002-12-24 03:02:00 -05:00
|
|
|
if (key == ID_ALLOCATOR) return ST_CONTINUE;
|
2002-10-30 03:04:32 -05:00
|
|
|
if (!body->nd_body) {
|
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
}
|
|
|
|
else if (VISI_CHECK(body->nd_noex, NOEX_PUBLIC)) {
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE name = rb_str_new2(rb_id2name(key));
|
1998-01-16 07:19:22 -05:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (!rb_ary_includes(ary, name)) {
|
|
|
|
rb_ary_push(ary, name);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_ary_push(ary, Qnil);
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
method_list(mod, option, func)
|
|
|
|
VALUE mod;
|
|
|
|
int option;
|
|
|
|
int (*func)();
|
|
|
|
{
|
|
|
|
VALUE ary;
|
|
|
|
VALUE klass;
|
|
|
|
VALUE *p, *q, *pend;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
ary = rb_ary_new();
|
1998-01-16 07:19:22 -05:00
|
|
|
for (klass = mod; klass; klass = RCLASS(klass)->super) {
|
|
|
|
st_foreach(RCLASS(klass)->m_tbl, func, ary);
|
|
|
|
if (!option) break;
|
|
|
|
}
|
|
|
|
p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len;
|
|
|
|
while (p < pend) {
|
|
|
|
if (*p == Qnil) {
|
|
|
|
p+=2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*q++ = *p++;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
RARRAY(ary)->len = q - RARRAY(ary)->ptr;
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_class_instance_methods(argc, argv, mod)
|
1998-01-16 07:19:22 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
VALUE option;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "01", &option);
|
|
|
|
return method_list(mod, RTEST(option), ins_methods_i);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_class_protected_instance_methods(argc, argv, mod)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
VALUE option;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "01", &option);
|
|
|
|
return method_list(mod, RTEST(option), ins_methods_prot_i);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_class_private_instance_methods(argc, argv, mod)
|
1998-01-16 07:19:22 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
VALUE option;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "01", &option);
|
|
|
|
return method_list(mod, RTEST(option), ins_methods_priv_i);
|
|
|
|
}
|
|
|
|
|
2002-10-30 03:04:32 -05:00
|
|
|
VALUE
|
|
|
|
rb_class_public_instance_methods(argc, argv, mod)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
VALUE option;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "01", &option);
|
|
|
|
return method_list(mod, RTEST(option), ins_methods_pub_i);
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE
|
2001-05-30 05:12:34 -04:00
|
|
|
rb_obj_singleton_methods(argc, argv, obj)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE obj;
|
|
|
|
{
|
2001-05-30 05:12:34 -04:00
|
|
|
VALUE all;
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE ary;
|
|
|
|
VALUE klass;
|
|
|
|
VALUE *p, *q, *pend;
|
|
|
|
|
2001-05-30 05:12:34 -04:00
|
|
|
rb_scan_args(argc, argv, "01", &all);
|
1999-01-19 23:59:39 -05:00
|
|
|
ary = rb_ary_new();
|
1998-01-16 07:19:22 -05:00
|
|
|
klass = CLASS_OF(obj);
|
|
|
|
while (klass && FL_TEST(klass, FL_SINGLETON)) {
|
|
|
|
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
|
|
|
|
klass = RCLASS(klass)->super;
|
|
|
|
}
|
2001-05-30 05:12:34 -04:00
|
|
|
if (RTEST(all)) {
|
|
|
|
while (klass && TYPE(klass) == T_ICLASS) {
|
|
|
|
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
|
|
|
|
klass = RCLASS(klass)->super;
|
|
|
|
}
|
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len;
|
|
|
|
while (p < pend) {
|
|
|
|
if (*p == Qnil) {
|
|
|
|
p+=2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*q++ = *p++;
|
|
|
|
}
|
|
|
|
RARRAY(ary)->len = q - RARRAY(ary)->ptr;
|
|
|
|
|
|
|
|
return ary;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_define_method_id(klass, name, func, argc)
|
|
|
|
VALUE klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
ID name;
|
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC|NOEX_CFUNC);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_define_method(klass, name, func, argc)
|
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
ID id = rb_intern(name);
|
2002-11-07 14:18:16 -05:00
|
|
|
int ex = NOEX_PUBLIC;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2002-11-07 14:18:16 -05:00
|
|
|
|
|
|
|
if (BUILTIN_TYPE(klass) == T_CLASS) {
|
|
|
|
ex |= NOEX_CFUNC;
|
|
|
|
}
|
|
|
|
rb_add_method(klass, id, NEW_CFUNC(func, argc), ex);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_protected_method(klass, name, func, argc)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
|
|
|
|
NOEX_PROTECTED|NOEX_CFUNC);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_define_private_method(klass, name, func, argc)
|
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc),
|
|
|
|
NOEX_PRIVATE|NOEX_CFUNC);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_undef_method(klass, name)
|
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
2002-04-25 09:57:01 -04:00
|
|
|
#define SPECIAL_SINGLETON(x,c) do {\
|
|
|
|
if (obj == (x)) {\
|
|
|
|
return c;\
|
|
|
|
}\
|
|
|
|
} while (0)
|
2002-03-08 02:03:09 -05:00
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE
|
|
|
|
rb_singleton_class(obj)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE obj;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-12-14 01:50:43 -05:00
|
|
|
VALUE klass;
|
2000-03-07 03:37:59 -05:00
|
|
|
|
2000-05-01 05:42:38 -04:00
|
|
|
if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
|
1999-08-13 01:45:20 -04:00
|
|
|
rb_raise(rb_eTypeError, "can't define singleton");
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-05-01 05:42:38 -04:00
|
|
|
if (rb_special_const_p(obj)) {
|
|
|
|
SPECIAL_SINGLETON(Qnil, rb_cNilClass);
|
|
|
|
SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
|
|
|
|
SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
|
2002-05-28 14:11:07 -04:00
|
|
|
rb_bug("unknown immediate %ld", obj);
|
2000-05-01 05:42:38 -04:00
|
|
|
}
|
|
|
|
|
2000-07-27 05:49:34 -04:00
|
|
|
DEFER_INTS;
|
2002-03-08 02:03:09 -05:00
|
|
|
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
|
2002-09-25 03:03:05 -04:00
|
|
|
rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
|
1999-12-14 01:50:43 -05:00
|
|
|
klass = RBASIC(obj)->klass;
|
|
|
|
}
|
|
|
|
else {
|
2002-01-10 15:18:39 -05:00
|
|
|
klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
|
1999-12-14 01:50:43 -05:00
|
|
|
}
|
|
|
|
if (OBJ_TAINTED(obj)) {
|
|
|
|
OBJ_TAINT(klass);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
1999-12-14 01:50:43 -05:00
|
|
|
else {
|
|
|
|
FL_UNSET(klass, FL_TAINT);
|
|
|
|
}
|
2000-06-22 04:29:58 -04:00
|
|
|
if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
|
2000-07-27 05:49:34 -04:00
|
|
|
ALLOW_INTS;
|
1999-12-14 01:50:43 -05:00
|
|
|
|
|
|
|
return klass;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_singleton_method(obj, name, func, argc)
|
|
|
|
VALUE obj;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
|
|
|
rb_define_method(rb_singleton_class(obj), name, func, argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_module_function(module, name, func, argc)
|
|
|
|
VALUE module;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
|
|
|
rb_define_private_method(module, name, func, argc);
|
|
|
|
rb_define_singleton_method(module, name, func, argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_global_function(name, func, argc)
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_module_function(rb_mKernel, name, func, argc);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_define_alias(klass, name1, name2)
|
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name1, *name2;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1998-01-16 07:19:22 -05:00
|
|
|
rb_alias(klass, rb_intern(name1), rb_intern(name2));
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_attr(klass, name, read, write)
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE klass;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *name;
|
1998-01-16 07:19:22 -05:00
|
|
|
int read, write;
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_attr(klass, rb_intern(name), read, write, Qfalse);
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
|
|
|
#include <stdarg.h>
|
|
|
|
#define va_init_list(a,b) va_start(a,b)
|
|
|
|
#else
|
1998-01-16 07:13:05 -05:00
|
|
|
#include <varargs.h>
|
1999-01-19 23:59:39 -05:00
|
|
|
#define va_init_list(a,b) va_start(a)
|
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
int
|
1999-01-19 23:59:39 -05:00
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
2002-04-18 04:46:18 -04:00
|
|
|
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
|
1999-01-19 23:59:39 -05:00
|
|
|
#else
|
1998-01-16 07:13:05 -05:00
|
|
|
rb_scan_args(argc, argv, fmt, va_alist)
|
|
|
|
int argc;
|
2002-04-18 04:46:18 -04:00
|
|
|
const VALUE *argv;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *fmt;
|
1998-01-16 07:13:05 -05:00
|
|
|
va_dcl
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
2000-02-18 01:59:36 -05:00
|
|
|
int n, i = 0;
|
1999-08-13 01:45:20 -04:00
|
|
|
const char *p = fmt;
|
1998-01-16 07:13:05 -05:00
|
|
|
VALUE *var;
|
|
|
|
va_list vargs;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
va_init_list(vargs, fmt);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-02-24 22:51:23 -05:00
|
|
|
if (*p == '*') goto rest_arg;
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ISDIGIT(*p)) {
|
1998-01-16 07:13:05 -05:00
|
|
|
n = *p - '0';
|
|
|
|
if (n > argc)
|
2001-11-19 00:03:03 -05:00
|
|
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, n);
|
1998-01-16 07:13:05 -05:00
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
var = va_arg(vargs, VALUE*);
|
1999-08-13 01:45:20 -04:00
|
|
|
if (var) *var = argv[i];
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
if (ISDIGIT(*p)) {
|
1998-01-16 07:13:05 -05:00
|
|
|
n = i + *p - '0';
|
|
|
|
for (; i<n; i++) {
|
|
|
|
var = va_arg(vargs, VALUE*);
|
|
|
|
if (argc > i) {
|
1999-08-13 01:45:20 -04:00
|
|
|
if (var) *var = argv[i];
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-08-13 01:45:20 -04:00
|
|
|
if (var) *var = Qnil;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*p == '*') {
|
2000-02-24 22:51:23 -05:00
|
|
|
rest_arg:
|
1998-01-16 07:13:05 -05:00
|
|
|
var = va_arg(vargs, VALUE*);
|
|
|
|
if (argc > i) {
|
1999-08-13 01:45:20 -04:00
|
|
|
if (var) *var = rb_ary_new4(argc-i, argv+i);
|
2000-02-18 01:59:36 -05:00
|
|
|
i = argc;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
|
|
|
else {
|
1999-08-13 01:45:20 -04:00
|
|
|
if (var) *var = rb_ary_new();
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-02-18 01:59:36 -05:00
|
|
|
p++;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-02-18 01:59:36 -05:00
|
|
|
|
|
|
|
if (*p == '&') {
|
|
|
|
var = va_arg(vargs, VALUE*);
|
2000-05-24 00:34:26 -04:00
|
|
|
if (rb_block_given_p()) {
|
2000-02-18 01:59:36 -05:00
|
|
|
*var = rb_f_lambda();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*var = Qnil;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-02-18 01:59:36 -05:00
|
|
|
p++;
|
1998-01-16 07:13:05 -05:00
|
|
|
}
|
2000-02-18 01:59:36 -05:00
|
|
|
va_end(vargs);
|
|
|
|
|
|
|
|
if (*p != '\0') {
|
1998-01-16 07:13:05 -05:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2000-02-18 01:59:36 -05:00
|
|
|
if (argc > i) {
|
2001-11-19 00:03:03 -05:00
|
|
|
rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)", argc, i);
|
2000-02-18 01:59:36 -05:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
return argc;
|
|
|
|
|
|
|
|
error:
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_fatal("bad scan arg format: %s", fmt);
|
1998-01-16 07:13:05 -05:00
|
|
|
return 0;
|
|
|
|
}
|