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