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
|
|
|
}
|
|
|
|
|
2004-11-15 23:55:14 -05:00
|
|
|
void
|
|
|
|
rb_check_inheritable(super)
|
|
|
|
VALUE super;
|
|
|
|
{
|
|
|
|
if (TYPE(super) != T_CLASS) {
|
|
|
|
rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
|
|
|
|
rb_obj_classname(super));
|
|
|
|
}
|
|
|
|
if (RBASIC(super)->flags & FL_SINGLETON) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of singleton class");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-18 01:56:05 -04:00
|
|
|
VALUE
|
|
|
|
rb_class_new(super)
|
|
|
|
VALUE super;
|
|
|
|
{
|
|
|
|
Check_Type(super, T_CLASS);
|
2004-11-15 23:55:14 -05:00
|
|
|
rb_check_inheritable(super);
|
2001-07-18 01:56:05 -04:00
|
|
|
if (super == rb_cClass) {
|
|
|
|
rb_raise(rb_eTypeError, "can't make subclass of 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;
|
|
|
|
}
|
|
|
|
|
2004-01-18 09:16:47 -05:00
|
|
|
/* :nodoc: */
|
2001-05-02 00:22:21 -04:00
|
|
|
VALUE
|
2003-08-06 17:50:06 -04:00
|
|
|
rb_mod_init_copy(clone, orig)
|
|
|
|
VALUE clone, orig;
|
2001-05-02 00:22:21 -04:00
|
|
|
{
|
2003-08-06 17:50:06 -04:00
|
|
|
rb_obj_init_copy(clone, orig);
|
2003-12-22 07:15:34 -05:00
|
|
|
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
|
|
|
|
RBASIC(clone)->klass = rb_singleton_class_clone(orig);
|
|
|
|
}
|
2003-08-06 17:50:06 -04:00
|
|
|
RCLASS(clone)->super = RCLASS(orig)->super;
|
|
|
|
if (RCLASS(orig)->iv_tbl) {
|
2001-10-22 02:48:18 -04:00
|
|
|
ID id;
|
|
|
|
|
2003-08-06 17:50:06 -04:00
|
|
|
RCLASS(clone)->iv_tbl = st_copy(RCLASS(orig)->iv_tbl);
|
2001-10-22 02:48:18 -04:00
|
|
|
id = rb_intern("__classpath__");
|
2003-07-25 01:36:55 -04:00
|
|
|
st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
|
2001-10-22 02:48:18 -04:00
|
|
|
id = rb_intern("__classid__");
|
2003-07-25 01:36:55 -04:00
|
|
|
st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
2003-08-06 17:50:06 -04:00
|
|
|
if (RCLASS(orig)->m_tbl) {
|
2001-10-03 03:19:19 -04:00
|
|
|
RCLASS(clone)->m_tbl = st_init_numtable();
|
2003-08-06 17:50:06 -04:00
|
|
|
st_foreach(RCLASS(orig)->m_tbl, clone_method,
|
* 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_data_t)RCLASS(clone)->m_tbl);
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
|
2003-08-06 17:50:06 -04:00
|
|
|
return clone;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
|
2004-01-18 09:16:47 -05:00
|
|
|
/* :nodoc: */
|
2001-05-02 00:22:21 -04:00
|
|
|
VALUE
|
2003-08-06 17:50:06 -04:00
|
|
|
rb_class_init_copy(clone, orig)
|
|
|
|
VALUE clone, orig;
|
2001-05-02 00:22:21 -04:00
|
|
|
{
|
2003-08-06 17:50:06 -04:00
|
|
|
if (RCLASS(clone)->super != 0) {
|
|
|
|
rb_raise(rb_eTypeError, "already initialized class");
|
|
|
|
}
|
2005-05-16 09:28:59 -04:00
|
|
|
if (FL_TEST(orig, FL_SINGLETON)) {
|
|
|
|
rb_raise(rb_eTypeError, "can't copy singleton class");
|
|
|
|
}
|
2003-08-06 17:50:06 -04:00
|
|
|
return rb_mod_init_copy(clone, orig);
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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-25 03:03:05 -04:00
|
|
|
if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
return RBASIC(obj)->klass = rb_cClass;
|
2002-09-25 03:03:05 -04:00
|
|
|
}
|
|
|
|
else {
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
VALUE metasuper;
|
|
|
|
VALUE klass = rb_class_boot(super);
|
2002-09-27 22:41:05 -04:00
|
|
|
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
FL_SET(klass, FL_SINGLETON);
|
|
|
|
RBASIC(obj)->klass = klass;
|
|
|
|
rb_singleton_class_attached(klass, obj);
|
|
|
|
|
|
|
|
metasuper = RBASIC(rb_class_real(super))->klass;
|
2002-09-27 22:41:05 -04:00
|
|
|
/* 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
|
|
|
}
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
return klass;
|
2002-09-03 01:20:14 -04:00
|
|
|
}
|
2002-01-10 15:18:39 -05:00
|
|
|
}
|
|
|
|
|
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);
|
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);
|
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);
|
2004-01-19 04:19:31 -05:00
|
|
|
rb_name_class(klass, id);
|
2003-06-30 21:36:25 -04:00
|
|
|
rb_const_set(rb_cObject, 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)) {
|
2003-06-20 03:11:44 -04:00
|
|
|
klass = rb_const_get_at(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);
|
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);
|
2003-06-30 21:36:25 -04:00
|
|
|
rb_const_set(rb_cObject, id, module);
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
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)) {
|
2003-06-20 03:11:44 -04:00
|
|
|
module = rb_const_get_at(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
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.included_modules -> array
|
|
|
|
*
|
|
|
|
* Returns the list of modules included in <i>mod</i>.
|
|
|
|
*
|
|
|
|
* module Mixin
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* module Outer
|
|
|
|
* include Mixin
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* Mixin.included_modules #=> []
|
|
|
|
* Outer.included_modules #=> [Mixin]
|
|
|
|
*/
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.include?(module) => true or false
|
|
|
|
*
|
|
|
|
* Returns <code>true</code> if <i>module</i> is included in
|
|
|
|
* <i>mod</i> or one of <i>mod</i>'s ancestors.
|
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* include A
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* end
|
|
|
|
* B.include?(A) #=> true
|
|
|
|
* C.include?(A) #=> true
|
|
|
|
* A.include?(A) #=> false
|
|
|
|
*/
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.ancestors -> array
|
|
|
|
*
|
|
|
|
* Returns a list of modules included in <i>mod</i> (including
|
|
|
|
* <i>mod</i> itself).
|
|
|
|
*
|
|
|
|
* module Mod
|
|
|
|
* include Math
|
|
|
|
* include Comparable
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* Mod.ancestors #=> [Mod, Comparable, Math]
|
|
|
|
* Math.ancestors #=> [Math]
|
|
|
|
*/
|
|
|
|
|
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;
|
|
|
|
{
|
2003-08-06 17:50:06 -04:00
|
|
|
VALUE p, ary = rb_ary_new();
|
1998-01-16 07:19:22 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-05-02 04:24:43 -04:00
|
|
|
#define VISI(x) ((x)&NOEX_MASK)
|
|
|
|
#define VISI_CHECK(x,f) (VISI(x) == (f))
|
2002-10-30 03:04:32 -05:00
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
static int
|
2003-05-02 04:24:43 -04:00
|
|
|
ins_methods_push(name, type, ary, visi)
|
|
|
|
ID name;
|
|
|
|
long type;
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE ary;
|
2003-05-02 04:24:43 -04:00
|
|
|
long visi;
|
|
|
|
{
|
|
|
|
if (type == -1) return ST_CONTINUE;
|
|
|
|
switch (visi) {
|
|
|
|
case NOEX_PRIVATE:
|
|
|
|
case NOEX_PROTECTED:
|
|
|
|
case NOEX_PUBLIC:
|
|
|
|
visi = (type == visi);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
visi = (type != NOEX_PRIVATE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (visi) {
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(name)));
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-05-02 04:24:43 -04:00
|
|
|
ins_methods_i(name, type, ary)
|
|
|
|
ID name;
|
|
|
|
long type;
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE ary;
|
|
|
|
{
|
2003-05-02 04:24:43 -04:00
|
|
|
return ins_methods_push(name, type, ary, -1); /* everything but private */
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2003-05-02 04:24:43 -04:00
|
|
|
static int
|
|
|
|
ins_methods_prot_i(name, type, ary)
|
|
|
|
ID name;
|
|
|
|
long type;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
|
|
|
return ins_methods_push(name, type, ary, NOEX_PROTECTED);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-05-02 04:24:43 -04:00
|
|
|
ins_methods_priv_i(name, type, ary)
|
|
|
|
ID name;
|
|
|
|
long type;
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE ary;
|
|
|
|
{
|
2003-05-02 04:24:43 -04:00
|
|
|
return ins_methods_push(name, type, ary, NOEX_PRIVATE);
|
|
|
|
}
|
2002-10-30 03:04:32 -05:00
|
|
|
|
2003-05-02 04:24:43 -04:00
|
|
|
static int
|
|
|
|
ins_methods_pub_i(name, type, ary)
|
|
|
|
ID name;
|
|
|
|
long type;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
|
|
|
return ins_methods_push(name, type, ary, NOEX_PUBLIC);
|
2002-10-30 03:04:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2003-05-02 04:24:43 -04:00
|
|
|
method_entry(key, body, list)
|
2002-10-30 03:04:32 -05:00
|
|
|
ID key;
|
|
|
|
NODE *body;
|
2003-05-02 04:24:43 -04:00
|
|
|
st_table *list;
|
2002-10-30 03:04:32 -05:00
|
|
|
{
|
2003-05-02 04:24:43 -04:00
|
|
|
long type;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2003-05-02 04:24:43 -04:00
|
|
|
if (key == ID_ALLOCATOR) return ST_CONTINUE;
|
|
|
|
if (!st_lookup(list, key, 0)) {
|
|
|
|
if (!body->nd_body) type = -1; /* none */
|
|
|
|
else type = VISI(body->nd_noex);
|
|
|
|
st_add_direct(list, key, type);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2003-06-25 03:12:10 -04:00
|
|
|
static VALUE
|
|
|
|
class_instance_method_list(argc, argv, mod, func)
|
1998-01-16 07:19:22 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
2003-06-26 08:34:51 -04:00
|
|
|
int (*func) _((ID, long, VALUE));
|
1998-01-16 07:19:22 -05:00
|
|
|
{
|
2003-06-26 08:34:51 -04:00
|
|
|
VALUE ary;
|
|
|
|
int recur;
|
|
|
|
st_table *list;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2003-05-02 12:11:48 -04:00
|
|
|
if (argc == 0) {
|
|
|
|
recur = Qtrue;
|
|
|
|
}
|
2003-06-26 08:34:51 -04:00
|
|
|
else {
|
|
|
|
VALUE r;
|
|
|
|
rb_scan_args(argc, argv, "01", &r);
|
|
|
|
recur = RTEST(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
list = st_init_numtable();
|
|
|
|
for (; mod; mod = RCLASS(mod)->super) {
|
|
|
|
st_foreach(RCLASS(mod)->m_tbl, method_entry, (st_data_t)list);
|
2003-08-04 04:31:24 -04:00
|
|
|
if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
|
|
|
|
if (FL_TEST(mod, FL_SINGLETON)) continue;
|
2003-06-26 08:34:51 -04:00
|
|
|
if (!recur) break;
|
|
|
|
}
|
|
|
|
ary = rb_ary_new();
|
|
|
|
st_foreach(list, func, ary);
|
|
|
|
st_free_table(list);
|
|
|
|
|
|
|
|
return ary;
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2004-07-15 07:46:00 -04:00
|
|
|
* mod.instance_methods(include_super=true) => array
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* Returns an array containing the names of public instance methods in
|
|
|
|
* the receiver. For a module, these are the public methods; for a
|
|
|
|
* class, they are the instance (not singleton) methods. With no
|
|
|
|
* argument, or with an argument that is <code>false</code>, the
|
|
|
|
* instance methods in <i>mod</i> are returned, otherwise the methods
|
|
|
|
* in <i>mod</i> and <i>mod</i>'s superclasses are returned.
|
|
|
|
*
|
|
|
|
* module A
|
|
|
|
* def method1() end
|
|
|
|
* end
|
|
|
|
* class B
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* class C < B
|
|
|
|
* def method3() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* A.instance_methods #=> ["method1"]
|
2004-06-16 10:21:34 -04:00
|
|
|
* B.instance_methods(false) #=> ["method2"]
|
|
|
|
* C.instance_methods(false) #=> ["method3"]
|
2003-12-28 01:33:07 -05:00
|
|
|
* C.instance_methods(true).length #=> 43
|
|
|
|
*/
|
|
|
|
|
1998-01-16 07:19:22 -05:00
|
|
|
VALUE
|
2003-06-25 03:12:10 -04:00
|
|
|
rb_class_instance_methods(argc, argv, mod)
|
1999-01-19 23:59:39 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
2003-06-25 03:12:10 -04:00
|
|
|
return class_instance_method_list(argc, argv, mod, ins_methods_i);
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2004-07-15 07:46:00 -04:00
|
|
|
* mod.protected_instance_methods(include_super=true) => array
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* Returns a list of the protected instance methods defined in
|
|
|
|
* <i>mod</i>. If the optional parameter is not <code>false</code>, the
|
|
|
|
* methods of any ancestors are included.
|
|
|
|
*/
|
|
|
|
|
2003-06-25 03:12:10 -04:00
|
|
|
VALUE
|
|
|
|
rb_class_protected_instance_methods(argc, argv, mod)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
|
|
|
return class_instance_method_list(argc, argv, mod, ins_methods_prot_i);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2004-07-15 07:46:00 -04:00
|
|
|
* mod.private_instance_methods(include_super=true) => array
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* Returns a list of the private instance methods defined in
|
|
|
|
* <i>mod</i>. If the optional parameter is not <code>false</code>, the
|
|
|
|
* methods of any ancestors are included.
|
|
|
|
*
|
|
|
|
* module Mod
|
|
|
|
* def method1() end
|
|
|
|
* private :method1
|
|
|
|
* def method2() end
|
|
|
|
* end
|
|
|
|
* Mod.instance_methods #=> ["method2"]
|
|
|
|
* Mod.private_instance_methods #=> ["method1"]
|
|
|
|
*/
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE
|
|
|
|
rb_class_private_instance_methods(argc, argv, mod)
|
1998-01-16 07:19:22 -05:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
2003-06-25 03:12:10 -04:00
|
|
|
return class_instance_method_list(argc, argv, mod, ins_methods_priv_i);
|
1998-01-16 07:19:22 -05:00
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2004-07-15 07:46:00 -04:00
|
|
|
* mod.public_instance_methods(include_super=true) => array
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* Returns a list of the public instance methods defined in <i>mod</i>.
|
|
|
|
* If the optional parameter is not <code>false</code>, the methods of
|
|
|
|
* any ancestors are included.
|
|
|
|
*/
|
|
|
|
|
2002-10-30 03:04:32 -05:00
|
|
|
VALUE
|
|
|
|
rb_class_public_instance_methods(argc, argv, mod)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE mod;
|
|
|
|
{
|
2003-06-25 03:12:10 -04:00
|
|
|
return class_instance_method_list(argc, argv, mod, ins_methods_pub_i);
|
2002-10-30 03:04:32 -05:00
|
|
|
}
|
|
|
|
|
2003-12-28 01:33:07 -05:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2004-07-15 07:46:00 -04:00
|
|
|
* obj.singleton_methods(all=true) => array
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* Returns an array of the names of singleton methods for <i>obj</i>.
|
|
|
|
* If the optional <i>all</i> parameter is true, the list will include
|
|
|
|
* methods in modules included in <i>obj</i>.
|
|
|
|
*
|
|
|
|
* module Other
|
|
|
|
* def three() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* class Single
|
|
|
|
* def Single.four() end
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* a = Single.new
|
|
|
|
*
|
|
|
|
* def a.one()
|
2004-05-11 22:51:54 -04:00
|
|
|
* end
|
2003-12-28 01:33:07 -05:00
|
|
|
*
|
|
|
|
* class << a
|
|
|
|
* include Other
|
|
|
|
* def two()
|
2004-05-11 22:51:54 -04:00
|
|
|
* end
|
2003-12-28 01:33:07 -05:00
|
|
|
* end
|
|
|
|
*
|
|
|
|
* Single.singleton_methods #=> ["four"]
|
2004-06-16 10:21:34 -04:00
|
|
|
* a.singleton_methods(false) #=> ["two", "one"]
|
|
|
|
* a.singleton_methods #=> ["two", "one", "three"]
|
2003-12-28 01:33:07 -05:00
|
|
|
*/
|
|
|
|
|
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;
|
|
|
|
{
|
2003-05-06 02:51:31 -04:00
|
|
|
VALUE recur, ary, klass;
|
2003-05-02 04:24:43 -04:00
|
|
|
st_table *list;
|
1998-01-16 07:19:22 -05:00
|
|
|
|
2003-05-06 02:51:31 -04:00
|
|
|
rb_scan_args(argc, argv, "01", &recur);
|
2003-05-02 12:11:48 -04:00
|
|
|
if (argc == 0) {
|
2003-05-04 12:03:24 -04:00
|
|
|
recur = Qtrue;
|
2003-05-02 12:11:48 -04:00
|
|
|
}
|
1998-01-16 07:19:22 -05:00
|
|
|
klass = CLASS_OF(obj);
|
2003-05-02 04:24:43 -04:00
|
|
|
list = st_init_numtable();
|
2003-08-01 16:16:53 -04:00
|
|
|
if (klass && FL_TEST(klass, FL_SINGLETON)) {
|
2003-05-02 04:24:43 -04:00
|
|
|
st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
|
1998-01-16 07:19:22 -05:00
|
|
|
klass = RCLASS(klass)->super;
|
|
|
|
}
|
2003-05-06 02:51:31 -04:00
|
|
|
if (RTEST(recur)) {
|
2003-08-01 16:16:53 -04:00
|
|
|
while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
|
2003-05-02 04:24:43 -04:00
|
|
|
st_foreach(RCLASS(klass)->m_tbl, method_entry, (st_data_t)list);
|
2001-05-30 05:12:34 -04:00
|
|
|
klass = RCLASS(klass)->super;
|
|
|
|
}
|
|
|
|
}
|
2003-05-02 04:24:43 -04:00
|
|
|
ary = rb_ary_new();
|
|
|
|
st_foreach(list, ins_methods_i, ary);
|
|
|
|
st_free_table(list);
|
1998-01-16 07:19:22 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
{
|
2003-07-16 03:11:30 -04:00
|
|
|
rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
|
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;
|
|
|
|
{
|
2004-06-16 10:21:34 -04:00
|
|
|
rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
|
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
|
|
|
{
|
2003-07-16 03:11:30 -04:00
|
|
|
rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED);
|
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;
|
|
|
|
{
|
2003-07-16 03:11:30 -04:00
|
|
|
rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
2003-06-16 03:14:50 -04:00
|
|
|
*var = rb_block_proc();
|
2000-02-18 01:59:36 -05:00
|
|
|
}
|
|
|
|
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) {
|
2004-03-29 02:54:38 -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;
|
|
|
|
}
|