00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00026 #include "ruby/ruby.h"
00027 #include "ruby/st.h"
00028 #include "method.h"
00029 #include "constant.h"
00030 #include "vm_core.h"
00031 #include "internal.h"
00032 #include <ctype.h>
00033
00034 extern st_table *rb_class_tbl;
00035 static ID id_attached;
00036
00049 static VALUE
00050 class_alloc(VALUE flags, VALUE klass)
00051 {
00052 rb_classext_t *ext = ALLOC(rb_classext_t);
00053 NEWOBJ(obj, struct RClass);
00054 OBJSETUP(obj, klass, flags);
00055 obj->ptr = ext;
00056 RCLASS_IV_TBL(obj) = 0;
00057 RCLASS_CONST_TBL(obj) = 0;
00058 RCLASS_M_TBL(obj) = 0;
00059 RCLASS_SUPER(obj) = 0;
00060 RCLASS_IV_INDEX_TBL(obj) = 0;
00061 return (VALUE)obj;
00062 }
00063
00064
00074 VALUE
00075 rb_class_boot(VALUE super)
00076 {
00077 VALUE klass = class_alloc(T_CLASS, rb_cClass);
00078
00079 RCLASS_SUPER(klass) = super;
00080 RCLASS_M_TBL(klass) = st_init_numtable();
00081
00082 OBJ_INFECT(klass, super);
00083 return (VALUE)klass;
00084 }
00085
00086
00093 void
00094 rb_check_inheritable(VALUE super)
00095 {
00096 if (TYPE(super) != T_CLASS) {
00097 rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
00098 rb_obj_classname(super));
00099 }
00100 if (RBASIC(super)->flags & FL_SINGLETON) {
00101 rb_raise(rb_eTypeError, "can't make subclass of singleton class");
00102 }
00103 if (super == rb_cClass) {
00104 rb_raise(rb_eTypeError, "can't make subclass of Class");
00105 }
00106 }
00107
00108
00115 VALUE
00116 rb_class_new(VALUE super)
00117 {
00118 Check_Type(super, T_CLASS);
00119 rb_check_inheritable(super);
00120 return rb_class_boot(super);
00121 }
00122
00123 struct clone_method_data {
00124 st_table *tbl;
00125 VALUE klass;
00126 };
00127
00128 VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
00129
00130 static int
00131 clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data)
00132 {
00133 VALUE newiseqval;
00134 if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
00135 rb_iseq_t *iseq;
00136 newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass);
00137 GetISeqPtr(newiseqval, iseq);
00138 rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
00139 RB_GC_GUARD(newiseqval);
00140 }
00141 else {
00142 rb_method_entry_set(data->klass, mid, me, me->flag);
00143 }
00144 return ST_CONTINUE;
00145 }
00146
00147 static int
00148 clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl)
00149 {
00150 rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
00151 *nce = *ce;
00152 st_insert(tbl, key, (st_data_t)nce);
00153 return ST_CONTINUE;
00154 }
00155
00156 static int
00157 clone_const_i(st_data_t key, st_data_t value, st_data_t data)
00158 {
00159 return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data);
00160 }
00161
00162 static void
00163 class_init_copy_check(VALUE clone, VALUE orig)
00164 {
00165 if (orig == rb_cBasicObject) {
00166 rb_raise(rb_eTypeError, "can't copy the root class");
00167 }
00168 if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
00169 rb_raise(rb_eTypeError, "already initialized class");
00170 }
00171 if (FL_TEST(orig, FL_SINGLETON)) {
00172 rb_raise(rb_eTypeError, "can't copy singleton class");
00173 }
00174 }
00175
00176
00177 VALUE
00178 rb_mod_init_copy(VALUE clone, VALUE orig)
00179 {
00180 if (RB_TYPE_P(clone, T_CLASS)) {
00181 class_init_copy_check(clone, orig);
00182 }
00183 if (clone == orig) return clone;
00184 rb_obj_init_copy(clone, orig);
00185 if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
00186 RBASIC(clone)->klass = rb_singleton_class_clone(orig);
00187 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00188 }
00189 RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
00190 if (RCLASS_IV_TBL(orig)) {
00191 st_data_t id;
00192
00193 if (RCLASS_IV_TBL(clone)) {
00194 st_free_table(RCLASS_IV_TBL(clone));
00195 }
00196 RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig));
00197 CONST_ID(id, "__classpath__");
00198 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00199 CONST_ID(id, "__classid__");
00200 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00201 }
00202 if (RCLASS_CONST_TBL(orig)) {
00203 if (RCLASS_CONST_TBL(clone)) {
00204 rb_free_const_table(RCLASS_CONST_TBL(clone));
00205 }
00206 RCLASS_CONST_TBL(clone) = st_init_numtable();
00207 st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
00208 }
00209 if (RCLASS_M_TBL(orig)) {
00210 struct clone_method_data data;
00211
00212 if (RCLASS_M_TBL(clone)) {
00213 rb_free_m_table(RCLASS_M_TBL(clone));
00214 }
00215 data.tbl = RCLASS_M_TBL(clone) = st_init_numtable();
00216 data.klass = clone;
00217 st_foreach(RCLASS_M_TBL(orig), clone_method,
00218 (st_data_t)&data);
00219 }
00220
00221 return clone;
00222 }
00223
00224 VALUE
00225 rb_singleton_class_clone(VALUE obj)
00226 {
00227 VALUE klass = RBASIC(obj)->klass;
00228
00229 if (!FL_TEST(klass, FL_SINGLETON))
00230 return klass;
00231 else {
00232 struct clone_method_data data;
00233
00234 VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0);
00235
00236 if (BUILTIN_TYPE(obj) == T_CLASS) {
00237 RBASIC(clone)->klass = (VALUE)clone;
00238 }
00239 else {
00240 RBASIC(clone)->klass = rb_singleton_class_clone(klass);
00241 }
00242
00243 RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
00244 if (RCLASS_IV_TBL(klass)) {
00245 RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
00246 }
00247 if (RCLASS_CONST_TBL(klass)) {
00248 RCLASS_CONST_TBL(clone) = st_init_numtable();
00249 st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
00250 }
00251 RCLASS_M_TBL(clone) = st_init_numtable();
00252 data.tbl = RCLASS_M_TBL(clone);
00253 data.klass = (VALUE)clone;
00254 st_foreach(RCLASS_M_TBL(klass), clone_method,
00255 (st_data_t)&data);
00256 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00257 FL_SET(clone, FL_SINGLETON);
00258 return (VALUE)clone;
00259 }
00260 }
00261
00266 void
00267 rb_singleton_class_attached(VALUE klass, VALUE obj)
00268 {
00269 if (FL_TEST(klass, FL_SINGLETON)) {
00270 if (!RCLASS_IV_TBL(klass)) {
00271 RCLASS_IV_TBL(klass) = st_init_numtable();
00272 }
00273 st_insert(RCLASS_IV_TBL(klass), id_attached, obj);
00274 }
00275 }
00276
00277
00278
00279 #define METACLASS_OF(k) RBASIC(k)->klass
00280
00286 #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k))
00287
00288
00296 #define ENSURE_EIGENCLASS(klass) \
00297 (rb_ivar_get(METACLASS_OF(klass), id_attached) == (klass) ? METACLASS_OF(klass) : make_metaclass(klass))
00298
00299
00309 static inline VALUE
00310 make_metaclass(VALUE klass)
00311 {
00312 VALUE super;
00313 VALUE metaclass = rb_class_boot(Qundef);
00314
00315 FL_SET(metaclass, FL_SINGLETON);
00316 rb_singleton_class_attached(metaclass, klass);
00317
00318 if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
00319 METACLASS_OF(klass) = METACLASS_OF(metaclass) = metaclass;
00320 }
00321 else {
00322 VALUE tmp = METACLASS_OF(klass);
00323 METACLASS_OF(klass) = metaclass;
00324 METACLASS_OF(metaclass) = ENSURE_EIGENCLASS(tmp);
00325 }
00326
00327 super = RCLASS_SUPER(klass);
00328 while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
00329 RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass;
00330
00331 OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
00332
00333 return metaclass;
00334 }
00335
00342 static inline VALUE
00343 make_singleton_class(VALUE obj)
00344 {
00345 VALUE orig_class = RBASIC(obj)->klass;
00346 VALUE klass = rb_class_boot(orig_class);
00347
00348 FL_SET(klass, FL_SINGLETON);
00349 RBASIC(obj)->klass = klass;
00350 rb_singleton_class_attached(klass, obj);
00351
00352 METACLASS_OF(klass) = METACLASS_OF(rb_class_real(orig_class));
00353 return klass;
00354 }
00355
00356
00357 static VALUE
00358 boot_defclass(const char *name, VALUE super)
00359 {
00360 extern st_table *rb_class_tbl;
00361 VALUE obj = rb_class_boot(super);
00362 ID id = rb_intern(name);
00363
00364 rb_name_class(obj, id);
00365 st_add_direct(rb_class_tbl, id, obj);
00366 rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
00367 return obj;
00368 }
00369
00370 void
00371 Init_class_hierarchy(void)
00372 {
00373 id_attached = rb_intern("__attached__");
00374
00375 rb_cBasicObject = boot_defclass("BasicObject", 0);
00376 rb_cObject = boot_defclass("Object", rb_cBasicObject);
00377 rb_cModule = boot_defclass("Module", rb_cObject);
00378 rb_cClass = boot_defclass("Class", rb_cModule);
00379
00380 rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
00381 RBASIC(rb_cClass)->klass
00382 = RBASIC(rb_cModule)->klass
00383 = RBASIC(rb_cObject)->klass
00384 = RBASIC(rb_cBasicObject)->klass
00385 = rb_cClass;
00386 }
00387
00388
00399 VALUE
00400 rb_make_metaclass(VALUE obj, VALUE unused)
00401 {
00402 if (BUILTIN_TYPE(obj) == T_CLASS) {
00403 return make_metaclass(obj);
00404 }
00405 else {
00406 return make_singleton_class(obj);
00407 }
00408 }
00409
00410
00421 VALUE
00422 rb_define_class_id(ID id, VALUE super)
00423 {
00424 VALUE klass;
00425
00426 if (!super) super = rb_cObject;
00427 klass = rb_class_new(super);
00428 rb_make_metaclass(klass, RBASIC(super)->klass);
00429
00430 return klass;
00431 }
00432
00433
00442 VALUE
00443 rb_class_inherited(VALUE super, VALUE klass)
00444 {
00445 ID inherited;
00446 if (!super) super = rb_cObject;
00447 CONST_ID(inherited, "inherited");
00448 return rb_funcall(super, inherited, 1, klass);
00449 }
00450
00451
00452
00468 VALUE
00469 rb_define_class(const char *name, VALUE super)
00470 {
00471 VALUE klass;
00472 ID id;
00473
00474 id = rb_intern(name);
00475 if (rb_const_defined(rb_cObject, id)) {
00476 klass = rb_const_get(rb_cObject, id);
00477 if (TYPE(klass) != T_CLASS) {
00478 rb_raise(rb_eTypeError, "%s is not a class", name);
00479 }
00480 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00481 rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
00482 }
00483 return klass;
00484 }
00485 if (!super) {
00486 rb_warn("no super class for `%s', Object assumed", name);
00487 }
00488 klass = rb_define_class_id(id, super);
00489 st_add_direct(rb_class_tbl, id, klass);
00490 rb_name_class(klass, id);
00491 rb_const_set(rb_cObject, id, klass);
00492 rb_class_inherited(super, klass);
00493
00494 return klass;
00495 }
00496
00497
00514 VALUE
00515 rb_define_class_under(VALUE outer, const char *name, VALUE super)
00516 {
00517 return rb_define_class_id_under(outer, rb_intern(name), super);
00518 }
00519
00520
00537 VALUE
00538 rb_define_class_id_under(VALUE outer, ID id, VALUE super)
00539 {
00540 VALUE klass;
00541
00542 if (rb_const_defined_at(outer, id)) {
00543 klass = rb_const_get_at(outer, id);
00544 if (TYPE(klass) != T_CLASS) {
00545 rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
00546 }
00547 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00548 rb_name_error(id, "%s is already defined", rb_id2name(id));
00549 }
00550 return klass;
00551 }
00552 if (!super) {
00553 rb_warn("no super class for `%s::%s', Object assumed",
00554 rb_class2name(outer), rb_id2name(id));
00555 }
00556 klass = rb_define_class_id(id, super);
00557 rb_set_class_path_string(klass, outer, rb_id2str(id));
00558 rb_const_set(outer, id, klass);
00559 rb_class_inherited(super, klass);
00560 rb_gc_register_mark_object(klass);
00561
00562 return klass;
00563 }
00564
00565 VALUE
00566 rb_module_new(void)
00567 {
00568 VALUE mdl = class_alloc(T_MODULE, rb_cModule);
00569
00570 RCLASS_M_TBL(mdl) = st_init_numtable();
00571
00572 return (VALUE)mdl;
00573 }
00574
00575 VALUE
00576 rb_define_module_id(ID id)
00577 {
00578 VALUE mdl;
00579
00580 mdl = rb_module_new();
00581 rb_name_class(mdl, id);
00582
00583 return mdl;
00584 }
00585
00586 VALUE
00587 rb_define_module(const char *name)
00588 {
00589 VALUE module;
00590 ID id;
00591
00592 id = rb_intern(name);
00593 if (rb_const_defined(rb_cObject, id)) {
00594 module = rb_const_get(rb_cObject, id);
00595 if (TYPE(module) == T_MODULE)
00596 return module;
00597 rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
00598 }
00599 module = rb_define_module_id(id);
00600 st_add_direct(rb_class_tbl, id, module);
00601 rb_const_set(rb_cObject, id, module);
00602
00603 return module;
00604 }
00605
00606 VALUE
00607 rb_define_module_under(VALUE outer, const char *name)
00608 {
00609 return rb_define_module_id_under(outer, rb_intern(name));
00610 }
00611
00612 VALUE
00613 rb_define_module_id_under(VALUE outer, ID id)
00614 {
00615 VALUE module;
00616
00617 if (rb_const_defined_at(outer, id)) {
00618 module = rb_const_get_at(outer, id);
00619 if (TYPE(module) == T_MODULE)
00620 return module;
00621 rb_raise(rb_eTypeError, "%s::%s is not a module",
00622 rb_class2name(outer), rb_obj_classname(module));
00623 }
00624 module = rb_define_module_id(id);
00625 rb_const_set(outer, id, module);
00626 rb_set_class_path_string(module, outer, rb_id2str(id));
00627 rb_gc_register_mark_object(module);
00628
00629 return module;
00630 }
00631
00632 static VALUE
00633 include_class_new(VALUE module, VALUE super)
00634 {
00635 VALUE klass = class_alloc(T_ICLASS, rb_cClass);
00636
00637 if (BUILTIN_TYPE(module) == T_ICLASS) {
00638 module = RBASIC(module)->klass;
00639 }
00640 if (!RCLASS_IV_TBL(module)) {
00641 RCLASS_IV_TBL(module) = st_init_numtable();
00642 }
00643 if (!RCLASS_CONST_TBL(module)) {
00644 RCLASS_CONST_TBL(module) = st_init_numtable();
00645 }
00646 RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
00647 RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
00648 RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
00649 RCLASS_SUPER(klass) = super;
00650 if (TYPE(module) == T_ICLASS) {
00651 RBASIC(klass)->klass = RBASIC(module)->klass;
00652 }
00653 else {
00654 RBASIC(klass)->klass = module;
00655 }
00656 OBJ_INFECT(klass, module);
00657 OBJ_INFECT(klass, super);
00658
00659 return (VALUE)klass;
00660 }
00661
00662 void
00663 rb_include_module(VALUE klass, VALUE module)
00664 {
00665 VALUE p, c;
00666 int changed = 0;
00667
00668 rb_frozen_class_p(klass);
00669 if (!OBJ_UNTRUSTED(klass)) {
00670 rb_secure(4);
00671 }
00672
00673 if (TYPE(module) != T_MODULE) {
00674 Check_Type(module, T_MODULE);
00675 }
00676
00677 OBJ_INFECT(klass, module);
00678 c = klass;
00679 while (module) {
00680 int superclass_seen = FALSE;
00681
00682 if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
00683 rb_raise(rb_eArgError, "cyclic include detected");
00684
00685 for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
00686 switch (BUILTIN_TYPE(p)) {
00687 case T_ICLASS:
00688 if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
00689 if (!superclass_seen) {
00690 c = p;
00691 }
00692 goto skip;
00693 }
00694 break;
00695 case T_CLASS:
00696 superclass_seen = TRUE;
00697 break;
00698 }
00699 }
00700 c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
00701 if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
00702 changed = 1;
00703 if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
00704 changed = 1;
00705 skip:
00706 module = RCLASS_SUPER(module);
00707 }
00708 if (changed) rb_clear_cache();
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 VALUE
00729 rb_mod_included_modules(VALUE mod)
00730 {
00731 VALUE ary = rb_ary_new();
00732 VALUE p;
00733
00734 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00735 if (BUILTIN_TYPE(p) == T_ICLASS) {
00736 rb_ary_push(ary, RBASIC(p)->klass);
00737 }
00738 }
00739 return ary;
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 VALUE
00762 rb_mod_include_p(VALUE mod, VALUE mod2)
00763 {
00764 VALUE p;
00765
00766 Check_Type(mod2, T_MODULE);
00767 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00768 if (BUILTIN_TYPE(p) == T_ICLASS) {
00769 if (RBASIC(p)->klass == mod2) return Qtrue;
00770 }
00771 }
00772 return Qfalse;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 VALUE
00792 rb_mod_ancestors(VALUE mod)
00793 {
00794 VALUE p, ary = rb_ary_new();
00795
00796 for (p = mod; p; p = RCLASS_SUPER(p)) {
00797 if (FL_TEST(p, FL_SINGLETON))
00798 continue;
00799 if (BUILTIN_TYPE(p) == T_ICLASS) {
00800 rb_ary_push(ary, RBASIC(p)->klass);
00801 }
00802 else {
00803 rb_ary_push(ary, p);
00804 }
00805 }
00806 return ary;
00807 }
00808
00809 #define VISI(x) ((x)&NOEX_MASK)
00810 #define VISI_CHECK(x,f) (VISI(x) == (f))
00811
00812 static int
00813 ins_methods_push(ID name, long type, VALUE ary, long visi)
00814 {
00815 if (type == -1) return ST_CONTINUE;
00816
00817 switch (visi) {
00818 case NOEX_PRIVATE:
00819 case NOEX_PROTECTED:
00820 case NOEX_PUBLIC:
00821 visi = (type == visi);
00822 break;
00823 default:
00824 visi = (type != NOEX_PRIVATE);
00825 break;
00826 }
00827 if (visi) {
00828 rb_ary_push(ary, ID2SYM(name));
00829 }
00830 return ST_CONTINUE;
00831 }
00832
00833 static int
00834 ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
00835 {
00836 return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1);
00837 }
00838
00839 static int
00840 ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
00841 {
00842 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED);
00843 }
00844
00845 static int
00846 ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
00847 {
00848 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE);
00849 }
00850
00851 static int
00852 ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
00853 {
00854 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
00855 }
00856
00857 static int
00858 method_entry_i(st_data_t key, st_data_t value, st_data_t data)
00859 {
00860 const rb_method_entry_t *me = (const rb_method_entry_t *)value;
00861 st_table *list = (st_table *)data;
00862 long type;
00863
00864 if ((ID)key == ID_ALLOCATOR) {
00865 return ST_CONTINUE;
00866 }
00867
00868 if (!st_lookup(list, key, 0)) {
00869 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00870 type = -1;
00871 }
00872 else {
00873 type = VISI(me->flag);
00874 }
00875 st_add_direct(list, key, type);
00876 }
00877 return ST_CONTINUE;
00878 }
00879
00880 static VALUE
00881 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
00882 {
00883 VALUE ary;
00884 int recur;
00885 st_table *list;
00886
00887 if (argc == 0) {
00888 recur = TRUE;
00889 }
00890 else {
00891 VALUE r;
00892 rb_scan_args(argc, argv, "01", &r);
00893 recur = RTEST(r);
00894 }
00895
00896 list = st_init_numtable();
00897 for (; mod; mod = RCLASS_SUPER(mod)) {
00898 st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
00899 if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
00900 if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
00901 if (!recur) break;
00902 }
00903 ary = rb_ary_new();
00904 st_foreach(list, func, ary);
00905 st_free_table(list);
00906
00907 return ary;
00908 }
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 VALUE
00938 rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
00939 {
00940 return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 VALUE
00953 rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
00954 {
00955 return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 VALUE
00976 rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
00977 {
00978 return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 VALUE
00991 rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
00992 {
00993 return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015 VALUE
01016 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
01017 {
01018 retry:
01019 if (argc == 0) {
01020 VALUE args[1];
01021
01022 args[0] = Qtrue;
01023 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
01024 }
01025 else {
01026 VALUE recur;
01027
01028 rb_scan_args(argc, argv, "1", &recur);
01029 if (RTEST(recur)) {
01030 argc = 0;
01031 goto retry;
01032 }
01033 return rb_obj_singleton_methods(argc, argv, obj);
01034 }
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 VALUE
01047 rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
01048 {
01049 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 VALUE
01062 rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
01063 {
01064 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 VALUE
01077 rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
01078 {
01079 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
01080 }
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 VALUE
01116 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
01117 {
01118 VALUE recur, ary, klass;
01119 st_table *list;
01120
01121 if (argc == 0) {
01122 recur = Qtrue;
01123 }
01124 else {
01125 rb_scan_args(argc, argv, "01", &recur);
01126 }
01127 klass = CLASS_OF(obj);
01128 list = st_init_numtable();
01129 if (klass && FL_TEST(klass, FL_SINGLETON)) {
01130 st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
01131 klass = RCLASS_SUPER(klass);
01132 }
01133 if (RTEST(recur)) {
01134 while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
01135 st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
01136 klass = RCLASS_SUPER(klass);
01137 }
01138 }
01139 ary = rb_ary_new();
01140 st_foreach(list, ins_methods_i, ary);
01141 st_free_table(list);
01142
01143 return ary;
01144 }
01145
01203 void
01204 rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
01205 {
01206 rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
01207 }
01208
01209 void
01210 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01211 {
01212 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
01213 }
01214
01215 void
01216 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01217 {
01218 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
01219 }
01220
01221 void
01222 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01223 {
01224 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
01225 }
01226
01227 void
01228 rb_undef_method(VALUE klass, const char *name)
01229 {
01230 rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
01231 }
01232
01241 #define SPECIAL_SINGLETON(x,c) do {\
01242 if (obj == (x)) {\
01243 return (c);\
01244 }\
01245 } while (0)
01246
01247
01257 static VALUE
01258 singleton_class_of(VALUE obj)
01259 {
01260 VALUE klass;
01261
01262 if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
01263 rb_raise(rb_eTypeError, "can't define singleton");
01264 }
01265 if (rb_special_const_p(obj)) {
01266 SPECIAL_SINGLETON(Qnil, rb_cNilClass);
01267 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
01268 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
01269 rb_bug("unknown immediate %p", (void *)obj);
01270 }
01271
01272 if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
01273 rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) {
01274 klass = RBASIC(obj)->klass;
01275 }
01276 else {
01277 klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
01278 }
01279
01280 if (OBJ_TAINTED(obj)) {
01281 OBJ_TAINT(klass);
01282 }
01283 else {
01284 FL_UNSET(klass, FL_TAINT);
01285 }
01286 if (OBJ_UNTRUSTED(obj)) {
01287 OBJ_UNTRUST(klass);
01288 }
01289 else {
01290 FL_UNSET(klass, FL_UNTRUSTED);
01291 }
01292 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
01293
01294 return klass;
01295 }
01296
01297
01315 VALUE
01316 rb_singleton_class(VALUE obj)
01317 {
01318 VALUE klass = singleton_class_of(obj);
01319
01320
01321 if (TYPE(obj) == T_CLASS) (void)ENSURE_EIGENCLASS(klass);
01322
01323 return klass;
01324 }
01325
01342 void
01343 rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
01344 {
01345 rb_define_method(singleton_class_of(obj), name, func, argc);
01346 }
01347
01348
01349
01357 void
01358 rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
01359 {
01360 rb_define_private_method(module, name, func, argc);
01361 rb_define_singleton_method(module, name, func, argc);
01362 }
01363
01364
01371 void
01372 rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
01373 {
01374 rb_define_module_function(rb_mKernel, name, func, argc);
01375 }
01376
01377
01384 void
01385 rb_define_alias(VALUE klass, const char *name1, const char *name2)
01386 {
01387 rb_alias(klass, rb_intern(name1), rb_intern(name2));
01388 }
01389
01397 void
01398 rb_define_attr(VALUE klass, const char *name, int read, int write)
01399 {
01400 rb_attr(klass, rb_intern(name), read, write, FALSE);
01401 }
01402
01403 int
01404 rb_obj_basic_to_s_p(VALUE obj)
01405 {
01406 const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
01407 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
01408 me->def->body.cfunc.func == rb_any_to_s)
01409 return 1;
01410 return 0;
01411 }
01412
01413 #include <stdarg.h>
01414
01415 int
01416 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
01417 {
01418 int i;
01419 const char *p = fmt;
01420 VALUE *var;
01421 va_list vargs;
01422 int f_var = 0, f_hash = 0, f_block = 0;
01423 int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
01424 int argi = 0;
01425 VALUE hash = Qnil;
01426
01427 if (ISDIGIT(*p)) {
01428 n_lead = *p - '0';
01429 p++;
01430 if (ISDIGIT(*p)) {
01431 n_opt = *p - '0';
01432 p++;
01433 if (ISDIGIT(*p)) {
01434 n_trail = *p - '0';
01435 p++;
01436 goto block_arg;
01437 }
01438 }
01439 }
01440 if (*p == '*') {
01441 f_var = 1;
01442 p++;
01443 if (ISDIGIT(*p)) {
01444 n_trail = *p - '0';
01445 p++;
01446 }
01447 }
01448 block_arg:
01449 if (*p == ':') {
01450 f_hash = 1;
01451 p++;
01452 }
01453 if (*p == '&') {
01454 f_block = 1;
01455 p++;
01456 }
01457 if (*p != '\0') {
01458 rb_fatal("bad scan arg format: %s", fmt);
01459 }
01460 n_mand = n_lead + n_trail;
01461
01462 if (argc < n_mand)
01463 goto argc_error;
01464
01465 va_start(vargs, fmt);
01466
01467
01468 if (f_hash && n_mand < argc) {
01469 VALUE last = argv[argc - 1];
01470
01471 if (NIL_P(last)) {
01472
01473
01474
01475 if (!f_var && n_mand + n_opt < argc)
01476 argc--;
01477 }
01478 else {
01479 hash = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
01480 if (!NIL_P(hash))
01481 argc--;
01482 }
01483 }
01484
01485 for (i = n_lead; i-- > 0; ) {
01486 var = va_arg(vargs, VALUE *);
01487 if (var) *var = argv[argi];
01488 argi++;
01489 }
01490
01491 for (i = n_opt; i-- > 0; ) {
01492 var = va_arg(vargs, VALUE *);
01493 if (argi < argc - n_trail) {
01494 if (var) *var = argv[argi];
01495 argi++;
01496 }
01497 else {
01498 if (var) *var = Qnil;
01499 }
01500 }
01501
01502 if (f_var) {
01503 int n_var = argc - argi - n_trail;
01504
01505 var = va_arg(vargs, VALUE *);
01506 if (0 < n_var) {
01507 if (var) *var = rb_ary_new4(n_var, &argv[argi]);
01508 argi += n_var;
01509 }
01510 else {
01511 if (var) *var = rb_ary_new();
01512 }
01513 }
01514
01515 for (i = n_trail; i-- > 0; ) {
01516 var = va_arg(vargs, VALUE *);
01517 if (var) *var = argv[argi];
01518 argi++;
01519 }
01520
01521 if (f_hash) {
01522 var = va_arg(vargs, VALUE *);
01523 if (var) *var = hash;
01524 }
01525
01526 if (f_block) {
01527 var = va_arg(vargs, VALUE *);
01528 if (rb_block_given_p()) {
01529 *var = rb_block_proc();
01530 }
01531 else {
01532 *var = Qnil;
01533 }
01534 }
01535 va_end(vargs);
01536
01537 if (argi < argc)
01538 goto argc_error;
01539
01540 return argc;
01541
01542 argc_error:
01543 if (0 < n_opt)
01544 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
01545 argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
01546 else
01547 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
01548 argc, n_mand, f_var ? "+" : "");
01549 }
01550