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 "vm_core.h"
00030 #include <ctype.h>
00031
00032 extern st_table *rb_class_tbl;
00033 static ID id_attached;
00034
00047 static VALUE
00048 class_alloc(VALUE flags, VALUE klass)
00049 {
00050 rb_classext_t *ext = ALLOC(rb_classext_t);
00051 NEWOBJ(obj, struct RClass);
00052 OBJSETUP(obj, klass, flags);
00053 obj->ptr = ext;
00054 RCLASS_IV_TBL(obj) = 0;
00055 RCLASS_M_TBL(obj) = 0;
00056 RCLASS_SUPER(obj) = 0;
00057 RCLASS_IV_INDEX_TBL(obj) = 0;
00058 return (VALUE)obj;
00059 }
00060
00061
00071 VALUE
00072 rb_class_boot(VALUE super)
00073 {
00074 VALUE klass = class_alloc(T_CLASS, rb_cClass);
00075
00076 RCLASS_SUPER(klass) = super;
00077 RCLASS_M_TBL(klass) = st_init_numtable();
00078
00079 OBJ_INFECT(klass, super);
00080 return (VALUE)klass;
00081 }
00082
00083
00090 void
00091 rb_check_inheritable(VALUE super)
00092 {
00093 if (TYPE(super) != T_CLASS) {
00094 rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
00095 rb_obj_classname(super));
00096 }
00097 if (RBASIC(super)->flags & FL_SINGLETON) {
00098 rb_raise(rb_eTypeError, "can't make subclass of singleton class");
00099 }
00100 if (super == rb_cClass) {
00101 rb_raise(rb_eTypeError, "can't make subclass of Class");
00102 }
00103 }
00104
00105
00112 VALUE
00113 rb_class_new(VALUE super)
00114 {
00115 Check_Type(super, T_CLASS);
00116 rb_check_inheritable(super);
00117 return rb_class_boot(super);
00118 }
00119
00120 struct clone_method_data {
00121 st_table *tbl;
00122 VALUE klass;
00123 };
00124
00125 VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
00126
00127 static int
00128 clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data)
00129 {
00130 if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
00131 VALUE newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass);
00132 rb_iseq_t *iseq;
00133 GetISeqPtr(newiseqval, iseq);
00134 rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
00135 }
00136 else {
00137 rb_method_entry_set(data->klass, mid, me, me->flag);
00138 }
00139 return ST_CONTINUE;
00140 }
00141
00142
00143 VALUE
00144 rb_mod_init_copy(VALUE clone, VALUE orig)
00145 {
00146 rb_obj_init_copy(clone, orig);
00147 if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
00148 RBASIC(clone)->klass = rb_singleton_class_clone(orig);
00149 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00150 }
00151 RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
00152 if (RCLASS_IV_TBL(orig)) {
00153 ID id;
00154
00155 if (RCLASS_IV_TBL(clone)) {
00156 st_free_table(RCLASS_IV_TBL(clone));
00157 }
00158 RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig));
00159 CONST_ID(id, "__classpath__");
00160 st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0);
00161 CONST_ID(id, "__classid__");
00162 st_delete(RCLASS_IV_TBL(clone), (st_data_t*)&id, 0);
00163 }
00164 if (RCLASS_M_TBL(orig)) {
00165 struct clone_method_data data;
00166
00167 if (RCLASS_M_TBL(clone)) {
00168 extern void rb_free_m_table(st_table *tbl);
00169 rb_free_m_table(RCLASS_M_TBL(clone));
00170 }
00171 data.tbl = RCLASS_M_TBL(clone) = st_init_numtable();
00172 data.klass = clone;
00173 st_foreach(RCLASS_M_TBL(orig), clone_method,
00174 (st_data_t)&data);
00175 }
00176
00177 return clone;
00178 }
00179
00180
00181 VALUE
00182 rb_class_init_copy(VALUE clone, VALUE orig)
00183 {
00184 if (orig == rb_cBasicObject) {
00185 rb_raise(rb_eTypeError, "can't copy the root class");
00186 }
00187 if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
00188 rb_raise(rb_eTypeError, "already initialized class");
00189 }
00190 if (FL_TEST(orig, FL_SINGLETON)) {
00191 rb_raise(rb_eTypeError, "can't copy singleton class");
00192 }
00193 return rb_mod_init_copy(clone, orig);
00194 }
00195
00196 VALUE
00197 rb_singleton_class_clone(VALUE obj)
00198 {
00199 VALUE klass = RBASIC(obj)->klass;
00200
00201 if (!FL_TEST(klass, FL_SINGLETON))
00202 return klass;
00203 else {
00204 struct clone_method_data data;
00205
00206 VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
00207
00208 if (BUILTIN_TYPE(obj) == T_CLASS) {
00209 RBASIC(clone)->klass = (VALUE)clone;
00210 }
00211 else {
00212 RBASIC(clone)->klass = rb_singleton_class_clone(klass);
00213 }
00214
00215 RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
00216 if (RCLASS_IV_TBL(klass)) {
00217 RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
00218 }
00219 RCLASS_M_TBL(clone) = st_init_numtable();
00220 data.tbl = RCLASS_M_TBL(clone);
00221 data.klass = (VALUE)clone;
00222 st_foreach(RCLASS_M_TBL(klass), clone_method,
00223 (st_data_t)&data);
00224 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00225 FL_SET(clone, FL_SINGLETON);
00226 return (VALUE)clone;
00227 }
00228 }
00229
00234 void
00235 rb_singleton_class_attached(VALUE klass, VALUE obj)
00236 {
00237 if (FL_TEST(klass, FL_SINGLETON)) {
00238 if (!RCLASS_IV_TBL(klass)) {
00239 RCLASS_IV_TBL(klass) = st_init_numtable();
00240 }
00241 st_insert(RCLASS_IV_TBL(klass), id_attached, obj);
00242 }
00243 }
00244
00245
00246
00247 #define METACLASS_OF(k) RBASIC(k)->klass
00248
00254 #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == k)
00255
00256
00264 #define ENSURE_EIGENCLASS(klass) \
00265 (rb_ivar_get(METACLASS_OF(klass), id_attached) == klass ? METACLASS_OF(klass) : make_metaclass(klass))
00266
00267
00277 static inline VALUE
00278 make_metaclass(VALUE klass)
00279 {
00280 VALUE super;
00281 VALUE metaclass = rb_class_boot(Qundef);
00282
00283 FL_SET(metaclass, FL_SINGLETON);
00284 rb_singleton_class_attached(metaclass, klass);
00285
00286 if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
00287 METACLASS_OF(klass) = METACLASS_OF(metaclass) = metaclass;
00288 }
00289 else {
00290 VALUE tmp = METACLASS_OF(klass);
00291 METACLASS_OF(klass) = metaclass;
00292 METACLASS_OF(metaclass) = ENSURE_EIGENCLASS(tmp);
00293 }
00294
00295 super = RCLASS_SUPER(klass);
00296 while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
00297 RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass;
00298
00299 OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
00300
00301 return metaclass;
00302 }
00303
00310 static inline VALUE
00311 make_singleton_class(VALUE obj)
00312 {
00313 VALUE orig_class = RBASIC(obj)->klass;
00314 VALUE klass = rb_class_boot(orig_class);
00315
00316 FL_SET(klass, FL_SINGLETON);
00317 RBASIC(obj)->klass = klass;
00318 rb_singleton_class_attached(klass, obj);
00319
00320 METACLASS_OF(klass) = METACLASS_OF(rb_class_real(orig_class));
00321 return klass;
00322 }
00323
00324
00325 static VALUE
00326 boot_defclass(const char *name, VALUE super)
00327 {
00328 extern st_table *rb_class_tbl;
00329 VALUE obj = rb_class_boot(super);
00330 ID id = rb_intern(name);
00331
00332 rb_name_class(obj, id);
00333 st_add_direct(rb_class_tbl, id, obj);
00334 rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
00335 return obj;
00336 }
00337
00338 void
00339 Init_class_hierarchy(void)
00340 {
00341 id_attached = rb_intern("__attached__");
00342
00343 rb_cBasicObject = boot_defclass("BasicObject", 0);
00344 rb_cObject = boot_defclass("Object", rb_cBasicObject);
00345 rb_cModule = boot_defclass("Module", rb_cObject);
00346 rb_cClass = boot_defclass("Class", rb_cModule);
00347
00348 RBASIC(rb_cClass)->klass
00349 = RBASIC(rb_cModule)->klass
00350 = RBASIC(rb_cObject)->klass
00351 = RBASIC(rb_cBasicObject)->klass
00352 = rb_cClass;
00353 }
00354
00355
00366 VALUE
00367 rb_make_metaclass(VALUE obj, VALUE unused)
00368 {
00369 if (BUILTIN_TYPE(obj) == T_CLASS) {
00370 return make_metaclass(obj);
00371 }
00372 else {
00373 return make_singleton_class(obj);
00374 }
00375 }
00376
00377
00388 VALUE
00389 rb_define_class_id(ID id, VALUE super)
00390 {
00391 VALUE klass;
00392
00393 if (!super) super = rb_cObject;
00394 klass = rb_class_new(super);
00395 rb_make_metaclass(klass, RBASIC(super)->klass);
00396
00397 return klass;
00398 }
00399
00400
00409 VALUE
00410 rb_class_inherited(VALUE super, VALUE klass)
00411 {
00412 ID inherited;
00413 if (!super) super = rb_cObject;
00414 CONST_ID(inherited, "inherited");
00415 return rb_funcall(super, inherited, 1, klass);
00416 }
00417
00418
00419
00435 VALUE
00436 rb_define_class(const char *name, VALUE super)
00437 {
00438 VALUE klass;
00439 ID id;
00440
00441 id = rb_intern(name);
00442 if (rb_const_defined(rb_cObject, id)) {
00443 klass = rb_const_get(rb_cObject, id);
00444 if (TYPE(klass) != T_CLASS) {
00445 rb_raise(rb_eTypeError, "%s is not a class", name);
00446 }
00447 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00448 rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
00449 }
00450 return klass;
00451 }
00452 if (!super) {
00453 rb_warn("no super class for `%s', Object assumed", name);
00454 }
00455 klass = rb_define_class_id(id, super);
00456 st_add_direct(rb_class_tbl, id, klass);
00457 rb_name_class(klass, id);
00458 rb_const_set(rb_cObject, id, klass);
00459 rb_class_inherited(super, klass);
00460
00461 return klass;
00462 }
00463
00464
00481 VALUE
00482 rb_define_class_under(VALUE outer, const char *name, VALUE super)
00483 {
00484 return rb_define_class_id_under(outer, rb_intern(name), super);
00485 }
00486
00487
00504 VALUE
00505 rb_define_class_id_under(VALUE outer, ID id, VALUE super)
00506 {
00507 VALUE klass;
00508
00509 if (rb_const_defined_at(outer, id)) {
00510 klass = rb_const_get_at(outer, id);
00511 if (TYPE(klass) != T_CLASS) {
00512 rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
00513 }
00514 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00515 rb_name_error(id, "%s is already defined", rb_id2name(id));
00516 }
00517 return klass;
00518 }
00519 if (!super) {
00520 rb_warn("no super class for `%s::%s', Object assumed",
00521 rb_class2name(outer), rb_id2name(id));
00522 }
00523 klass = rb_define_class_id(id, super);
00524 rb_set_class_path_string(klass, outer, rb_id2str(id));
00525 rb_const_set(outer, id, klass);
00526 rb_class_inherited(super, klass);
00527 rb_gc_register_mark_object(klass);
00528
00529 return klass;
00530 }
00531
00532 VALUE
00533 rb_module_new(void)
00534 {
00535 VALUE mdl = class_alloc(T_MODULE, rb_cModule);
00536
00537 RCLASS_M_TBL(mdl) = st_init_numtable();
00538
00539 return (VALUE)mdl;
00540 }
00541
00542 VALUE
00543 rb_define_module_id(ID id)
00544 {
00545 VALUE mdl;
00546
00547 mdl = rb_module_new();
00548 rb_name_class(mdl, id);
00549
00550 return mdl;
00551 }
00552
00553 VALUE
00554 rb_define_module(const char *name)
00555 {
00556 VALUE module;
00557 ID id;
00558
00559 id = rb_intern(name);
00560 if (rb_const_defined(rb_cObject, id)) {
00561 module = rb_const_get(rb_cObject, id);
00562 if (TYPE(module) == T_MODULE)
00563 return module;
00564 rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
00565 }
00566 module = rb_define_module_id(id);
00567 st_add_direct(rb_class_tbl, id, module);
00568 rb_const_set(rb_cObject, id, module);
00569
00570 return module;
00571 }
00572
00573 VALUE
00574 rb_define_module_under(VALUE outer, const char *name)
00575 {
00576 return rb_define_module_id_under(outer, rb_intern(name));
00577 }
00578
00579 VALUE
00580 rb_define_module_id_under(VALUE outer, ID id)
00581 {
00582 VALUE module;
00583
00584 if (rb_const_defined_at(outer, id)) {
00585 module = rb_const_get_at(outer, id);
00586 if (TYPE(module) == T_MODULE)
00587 return module;
00588 rb_raise(rb_eTypeError, "%s::%s is not a module",
00589 rb_class2name(outer), rb_obj_classname(module));
00590 }
00591 module = rb_define_module_id(id);
00592 rb_const_set(outer, id, module);
00593 rb_set_class_path_string(module, outer, rb_id2str(id));
00594 rb_gc_register_mark_object(module);
00595
00596 return module;
00597 }
00598
00599 static VALUE
00600 include_class_new(VALUE module, VALUE super)
00601 {
00602 VALUE klass = class_alloc(T_ICLASS, rb_cClass);
00603
00604 if (BUILTIN_TYPE(module) == T_ICLASS) {
00605 module = RBASIC(module)->klass;
00606 }
00607 if (!RCLASS_IV_TBL(module)) {
00608 RCLASS_IV_TBL(module) = st_init_numtable();
00609 }
00610 RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
00611 RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
00612 RCLASS_SUPER(klass) = super;
00613 if (TYPE(module) == T_ICLASS) {
00614 RBASIC(klass)->klass = RBASIC(module)->klass;
00615 }
00616 else {
00617 RBASIC(klass)->klass = module;
00618 }
00619 OBJ_INFECT(klass, module);
00620 OBJ_INFECT(klass, super);
00621
00622 return (VALUE)klass;
00623 }
00624
00625 void
00626 rb_include_module(VALUE klass, VALUE module)
00627 {
00628 VALUE p, c;
00629 int changed = 0;
00630
00631 rb_frozen_class_p(klass);
00632 if (!OBJ_UNTRUSTED(klass)) {
00633 rb_secure(4);
00634 }
00635
00636 if (TYPE(module) != T_MODULE) {
00637 Check_Type(module, T_MODULE);
00638 }
00639
00640 OBJ_INFECT(klass, module);
00641 c = klass;
00642 while (module) {
00643 int superclass_seen = FALSE;
00644
00645 if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
00646 rb_raise(rb_eArgError, "cyclic include detected");
00647
00648 for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
00649 switch (BUILTIN_TYPE(p)) {
00650 case T_ICLASS:
00651 if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
00652 if (!superclass_seen) {
00653 c = p;
00654 }
00655 goto skip;
00656 }
00657 break;
00658 case T_CLASS:
00659 superclass_seen = TRUE;
00660 break;
00661 }
00662 }
00663 c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
00664 changed = 1;
00665 skip:
00666 module = RCLASS_SUPER(module);
00667 }
00668 if (changed) rb_clear_cache();
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 VALUE
00689 rb_mod_included_modules(VALUE mod)
00690 {
00691 VALUE ary = rb_ary_new();
00692 VALUE p;
00693
00694 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00695 if (BUILTIN_TYPE(p) == T_ICLASS) {
00696 rb_ary_push(ary, RBASIC(p)->klass);
00697 }
00698 }
00699 return ary;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721 VALUE
00722 rb_mod_include_p(VALUE mod, VALUE mod2)
00723 {
00724 VALUE p;
00725
00726 Check_Type(mod2, T_MODULE);
00727 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00728 if (BUILTIN_TYPE(p) == T_ICLASS) {
00729 if (RBASIC(p)->klass == mod2) return Qtrue;
00730 }
00731 }
00732 return Qfalse;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 VALUE
00752 rb_mod_ancestors(VALUE mod)
00753 {
00754 VALUE p, ary = rb_ary_new();
00755
00756 for (p = mod; p; p = RCLASS_SUPER(p)) {
00757 if (FL_TEST(p, FL_SINGLETON))
00758 continue;
00759 if (BUILTIN_TYPE(p) == T_ICLASS) {
00760 rb_ary_push(ary, RBASIC(p)->klass);
00761 }
00762 else {
00763 rb_ary_push(ary, p);
00764 }
00765 }
00766 return ary;
00767 }
00768
00769 #define VISI(x) ((x)&NOEX_MASK)
00770 #define VISI_CHECK(x,f) (VISI(x) == (f))
00771
00772 static int
00773 ins_methods_push(ID name, long type, VALUE ary, long visi)
00774 {
00775 if (type == -1) return ST_CONTINUE;
00776
00777 switch (visi) {
00778 case NOEX_PRIVATE:
00779 case NOEX_PROTECTED:
00780 case NOEX_PUBLIC:
00781 visi = (type == visi);
00782 break;
00783 default:
00784 visi = (type != NOEX_PRIVATE);
00785 break;
00786 }
00787 if (visi) {
00788 rb_ary_push(ary, ID2SYM(name));
00789 }
00790 return ST_CONTINUE;
00791 }
00792
00793 static int
00794 ins_methods_i(ID name, long type, VALUE ary)
00795 {
00796 return ins_methods_push(name, type, ary, -1);
00797 }
00798
00799 static int
00800 ins_methods_prot_i(ID name, long type, VALUE ary)
00801 {
00802 return ins_methods_push(name, type, ary, NOEX_PROTECTED);
00803 }
00804
00805 static int
00806 ins_methods_priv_i(ID name, long type, VALUE ary)
00807 {
00808 return ins_methods_push(name, type, ary, NOEX_PRIVATE);
00809 }
00810
00811 static int
00812 ins_methods_pub_i(ID name, long type, VALUE ary)
00813 {
00814 return ins_methods_push(name, type, ary, NOEX_PUBLIC);
00815 }
00816
00817 static int
00818 method_entry(ID key, const rb_method_entry_t *me, st_table *list)
00819 {
00820 long type;
00821
00822 if (key == ID_ALLOCATOR) {
00823 return ST_CONTINUE;
00824 }
00825
00826 if (!st_lookup(list, key, 0)) {
00827 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00828 type = -1;
00829 }
00830 else {
00831 type = VISI(me->flag);
00832 }
00833 st_add_direct(list, key, type);
00834 }
00835 return ST_CONTINUE;
00836 }
00837
00838 static VALUE
00839 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (ID, long, VALUE))
00840 {
00841 VALUE ary;
00842 int recur;
00843 st_table *list;
00844
00845 if (argc == 0) {
00846 recur = TRUE;
00847 }
00848 else {
00849 VALUE r;
00850 rb_scan_args(argc, argv, "01", &r);
00851 recur = RTEST(r);
00852 }
00853
00854 list = st_init_numtable();
00855 for (; mod; mod = RCLASS_SUPER(mod)) {
00856 st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
00857 if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
00858 if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
00859 if (!recur) break;
00860 }
00861 ary = rb_ary_new();
00862 st_foreach(list, func, ary);
00863 st_free_table(list);
00864
00865 return ary;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 VALUE
00896 rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
00897 {
00898 return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
00899 }
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 VALUE
00911 rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
00912 {
00913 return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 VALUE
00934 rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
00935 {
00936 return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 VALUE
00949 rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
00950 {
00951 return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 VALUE
00974 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
00975 {
00976 retry:
00977 if (argc == 0) {
00978 VALUE args[1];
00979
00980 args[0] = Qtrue;
00981 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
00982 }
00983 else {
00984 VALUE recur;
00985
00986 rb_scan_args(argc, argv, "1", &recur);
00987 if (RTEST(recur)) {
00988 argc = 0;
00989 goto retry;
00990 }
00991 return rb_obj_singleton_methods(argc, argv, obj);
00992 }
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 VALUE
01005 rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
01006 {
01007 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 VALUE
01020 rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
01021 {
01022 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 VALUE
01035 rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
01036 {
01037 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 VALUE
01074 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
01075 {
01076 VALUE recur, ary, klass;
01077 st_table *list;
01078
01079 if (argc == 0) {
01080 recur = Qtrue;
01081 }
01082 else {
01083 rb_scan_args(argc, argv, "01", &recur);
01084 }
01085 klass = CLASS_OF(obj);
01086 list = st_init_numtable();
01087 if (klass && FL_TEST(klass, FL_SINGLETON)) {
01088 st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
01089 klass = RCLASS_SUPER(klass);
01090 }
01091 if (RTEST(recur)) {
01092 while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
01093 st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
01094 klass = RCLASS_SUPER(klass);
01095 }
01096 }
01097 ary = rb_ary_new();
01098 st_foreach(list, ins_methods_i, ary);
01099 st_free_table(list);
01100
01101 return ary;
01102 }
01103
01161 void
01162 rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
01163 {
01164 rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
01165 }
01166
01167 void
01168 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01169 {
01170 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
01171 }
01172
01173 void
01174 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01175 {
01176 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
01177 }
01178
01179 void
01180 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01181 {
01182 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
01183 }
01184
01185 void
01186 rb_undef_method(VALUE klass, const char *name)
01187 {
01188 rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
01189 }
01190
01199 #define SPECIAL_SINGLETON(x,c) do {\
01200 if (obj == (x)) {\
01201 return c;\
01202 }\
01203 } while (0)
01204
01205
01215 static VALUE
01216 singleton_class_of(VALUE obj)
01217 {
01218 VALUE klass;
01219
01220 if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
01221 rb_raise(rb_eTypeError, "can't define singleton");
01222 }
01223 if (rb_special_const_p(obj)) {
01224 SPECIAL_SINGLETON(Qnil, rb_cNilClass);
01225 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
01226 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
01227 rb_bug("unknown immediate %ld", obj);
01228 }
01229
01230 if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
01231 rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) {
01232 klass = RBASIC(obj)->klass;
01233 }
01234 else {
01235 klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
01236 }
01237
01238 if (OBJ_TAINTED(obj)) {
01239 OBJ_TAINT(klass);
01240 }
01241 else {
01242 FL_UNSET(klass, FL_TAINT);
01243 }
01244 if (OBJ_UNTRUSTED(obj)) {
01245 OBJ_UNTRUST(klass);
01246 }
01247 else {
01248 FL_UNSET(klass, FL_UNTRUSTED);
01249 }
01250 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
01251
01252 return klass;
01253 }
01254
01255
01273 VALUE
01274 rb_singleton_class(VALUE obj)
01275 {
01276 VALUE klass = singleton_class_of(obj);
01277
01278
01279 if (TYPE(obj) == T_CLASS) ENSURE_EIGENCLASS(klass);
01280
01281 return klass;
01282 }
01283
01300 void
01301 rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
01302 {
01303 rb_define_method(singleton_class_of(obj), name, func, argc);
01304 }
01305
01306
01307
01315 void
01316 rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
01317 {
01318 rb_define_private_method(module, name, func, argc);
01319 rb_define_singleton_method(module, name, func, argc);
01320 }
01321
01322
01329 void
01330 rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
01331 {
01332 rb_define_module_function(rb_mKernel, name, func, argc);
01333 }
01334
01335
01342 void
01343 rb_define_alias(VALUE klass, const char *name1, const char *name2)
01344 {
01345 rb_alias(klass, rb_intern(name1), rb_intern(name2));
01346 }
01347
01355 void
01356 rb_define_attr(VALUE klass, const char *name, int read, int write)
01357 {
01358 rb_attr(klass, rb_intern(name), read, write, FALSE);
01359 }
01360
01361 int
01362 rb_obj_basic_to_s_p(VALUE obj)
01363 {
01364 const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
01365 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
01366 me->def->body.cfunc.func == rb_any_to_s)
01367 return 1;
01368 return 0;
01369 }
01370
01371 #include <stdarg.h>
01372
01373 int
01374 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
01375 {
01376 int i;
01377 const char *p = fmt;
01378 VALUE *var;
01379 va_list vargs;
01380 int f_var = 0, f_block = 0;
01381 int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
01382 int argi = 0;
01383
01384 if (ISDIGIT(*p)) {
01385 n_lead = *p - '0';
01386 p++;
01387 if (ISDIGIT(*p)) {
01388 n_opt = *p - '0';
01389 p++;
01390 if (ISDIGIT(*p)) {
01391 n_trail = *p - '0';
01392 p++;
01393 goto block_arg;
01394 }
01395 }
01396 }
01397 if (*p == '*') {
01398 f_var = 1;
01399 p++;
01400 if (ISDIGIT(*p)) {
01401 n_trail = *p - '0';
01402 p++;
01403 }
01404 }
01405 block_arg:
01406 if (*p == '&') {
01407 f_block = 1;
01408 p++;
01409 }
01410 if (*p != '\0') {
01411 rb_fatal("bad scan arg format: %s", fmt);
01412 }
01413 n_mand = n_lead + n_trail;
01414
01415 if (argc < n_mand)
01416 goto argc_error;
01417
01418 va_start(vargs, fmt);
01419
01420
01421 for (i = n_lead; i-- > 0; ) {
01422 var = va_arg(vargs, VALUE *);
01423 if (var) *var = argv[argi];
01424 argi++;
01425 }
01426
01427 for (i = n_opt; i-- > 0; ) {
01428 var = va_arg(vargs, VALUE *);
01429 if (argi < argc - n_trail) {
01430 if (var) *var = argv[argi];
01431 argi++;
01432 }
01433 else {
01434 if (var) *var = Qnil;
01435 }
01436 }
01437
01438 if (f_var) {
01439 int n_var = argc - argi - n_trail;
01440
01441 var = va_arg(vargs, VALUE *);
01442 if (0 < n_var) {
01443 if (var) *var = rb_ary_new4(n_var, &argv[argi]);
01444 argi += n_var;
01445 }
01446 else {
01447 if (var) *var = rb_ary_new();
01448 }
01449 }
01450
01451 for (i = n_trail; i-- > 0; ) {
01452 var = va_arg(vargs, VALUE *);
01453 if (var) *var = argv[argi];
01454 argi++;
01455 }
01456
01457 if (f_block) {
01458 var = va_arg(vargs, VALUE *);
01459 if (rb_block_given_p()) {
01460 *var = rb_block_proc();
01461 }
01462 else {
01463 *var = Qnil;
01464 }
01465 }
01466 va_end(vargs);
01467
01468 if (argi < argc)
01469 goto argc_error;
01470
01471 return argc;
01472
01473 argc_error:
01474 if (0 < n_opt)
01475 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
01476 argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
01477 else
01478 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
01479 argc, n_mand, f_var ? "+" : "");
01480 }
01481