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 (FL_TEST(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
00528 return klass;
00529 }
00530
00531 VALUE
00532 rb_module_new(void)
00533 {
00534 VALUE mdl = class_alloc(T_MODULE, rb_cModule);
00535
00536 RCLASS_M_TBL(mdl) = st_init_numtable();
00537
00538 return (VALUE)mdl;
00539 }
00540
00541 VALUE
00542 rb_define_module_id(ID id)
00543 {
00544 VALUE mdl;
00545
00546 mdl = rb_module_new();
00547 rb_name_class(mdl, id);
00548
00549 return mdl;
00550 }
00551
00552 VALUE
00553 rb_define_module(const char *name)
00554 {
00555 VALUE module;
00556 ID id;
00557
00558 id = rb_intern(name);
00559 if (rb_const_defined(rb_cObject, id)) {
00560 module = rb_const_get(rb_cObject, id);
00561 if (TYPE(module) == T_MODULE)
00562 return module;
00563 rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
00564 }
00565 module = rb_define_module_id(id);
00566 st_add_direct(rb_class_tbl, id, module);
00567 rb_const_set(rb_cObject, id, module);
00568
00569 return module;
00570 }
00571
00572 VALUE
00573 rb_define_module_under(VALUE outer, const char *name)
00574 {
00575 return rb_define_module_id_under(outer, rb_intern(name));
00576 }
00577
00578 VALUE
00579 rb_define_module_id_under(VALUE outer, ID id)
00580 {
00581 VALUE module;
00582
00583 if (rb_const_defined_at(outer, id)) {
00584 module = rb_const_get_at(outer, id);
00585 if (TYPE(module) == T_MODULE)
00586 return module;
00587 rb_raise(rb_eTypeError, "%s::%s is not a module",
00588 rb_class2name(outer), rb_obj_classname(module));
00589 }
00590 module = rb_define_module_id(id);
00591 rb_const_set(outer, id, module);
00592 rb_set_class_path_string(module, outer, rb_id2str(id));
00593
00594 return module;
00595 }
00596
00597 static VALUE
00598 include_class_new(VALUE module, VALUE super)
00599 {
00600 VALUE klass = class_alloc(T_ICLASS, rb_cClass);
00601
00602 if (BUILTIN_TYPE(module) == T_ICLASS) {
00603 module = RBASIC(module)->klass;
00604 }
00605 if (!RCLASS_IV_TBL(module)) {
00606 RCLASS_IV_TBL(module) = st_init_numtable();
00607 }
00608 RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
00609 RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
00610 RCLASS_SUPER(klass) = super;
00611 if (TYPE(module) == T_ICLASS) {
00612 RBASIC(klass)->klass = RBASIC(module)->klass;
00613 }
00614 else {
00615 RBASIC(klass)->klass = module;
00616 }
00617 OBJ_INFECT(klass, module);
00618 OBJ_INFECT(klass, super);
00619
00620 return (VALUE)klass;
00621 }
00622
00623 void
00624 rb_include_module(VALUE klass, VALUE module)
00625 {
00626 VALUE p, c;
00627 int changed = 0;
00628
00629 rb_frozen_class_p(klass);
00630 if (!OBJ_UNTRUSTED(klass)) {
00631 rb_secure(4);
00632 }
00633
00634 if (TYPE(module) != T_MODULE) {
00635 Check_Type(module, T_MODULE);
00636 }
00637
00638 OBJ_INFECT(klass, module);
00639 c = klass;
00640 while (module) {
00641 int superclass_seen = FALSE;
00642
00643 if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
00644 rb_raise(rb_eArgError, "cyclic include detected");
00645
00646 for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
00647 switch (BUILTIN_TYPE(p)) {
00648 case T_ICLASS:
00649 if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
00650 if (!superclass_seen) {
00651 c = p;
00652 }
00653 goto skip;
00654 }
00655 break;
00656 case T_CLASS:
00657 superclass_seen = TRUE;
00658 break;
00659 }
00660 }
00661 c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
00662 changed = 1;
00663 skip:
00664 module = RCLASS_SUPER(module);
00665 }
00666 if (changed) rb_clear_cache();
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 VALUE
00687 rb_mod_included_modules(VALUE mod)
00688 {
00689 VALUE ary = rb_ary_new();
00690 VALUE p;
00691
00692 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00693 if (BUILTIN_TYPE(p) == T_ICLASS) {
00694 rb_ary_push(ary, RBASIC(p)->klass);
00695 }
00696 }
00697 return ary;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 VALUE
00720 rb_mod_include_p(VALUE mod, VALUE mod2)
00721 {
00722 VALUE p;
00723
00724 Check_Type(mod2, T_MODULE);
00725 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00726 if (BUILTIN_TYPE(p) == T_ICLASS) {
00727 if (RBASIC(p)->klass == mod2) return Qtrue;
00728 }
00729 }
00730 return Qfalse;
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 VALUE
00750 rb_mod_ancestors(VALUE mod)
00751 {
00752 VALUE p, ary = rb_ary_new();
00753
00754 for (p = mod; p; p = RCLASS_SUPER(p)) {
00755 if (FL_TEST(p, FL_SINGLETON))
00756 continue;
00757 if (BUILTIN_TYPE(p) == T_ICLASS) {
00758 rb_ary_push(ary, RBASIC(p)->klass);
00759 }
00760 else {
00761 rb_ary_push(ary, p);
00762 }
00763 }
00764 return ary;
00765 }
00766
00767 #define VISI(x) ((x)&NOEX_MASK)
00768 #define VISI_CHECK(x,f) (VISI(x) == (f))
00769
00770 static int
00771 ins_methods_push(ID name, long type, VALUE ary, long visi)
00772 {
00773 if (type == -1) return ST_CONTINUE;
00774
00775 switch (visi) {
00776 case NOEX_PRIVATE:
00777 case NOEX_PROTECTED:
00778 case NOEX_PUBLIC:
00779 visi = (type == visi);
00780 break;
00781 default:
00782 visi = (type != NOEX_PRIVATE);
00783 break;
00784 }
00785 if (visi) {
00786 rb_ary_push(ary, ID2SYM(name));
00787 }
00788 return ST_CONTINUE;
00789 }
00790
00791 static int
00792 ins_methods_i(ID name, long type, VALUE ary)
00793 {
00794 return ins_methods_push(name, type, ary, -1);
00795 }
00796
00797 static int
00798 ins_methods_prot_i(ID name, long type, VALUE ary)
00799 {
00800 return ins_methods_push(name, type, ary, NOEX_PROTECTED);
00801 }
00802
00803 static int
00804 ins_methods_priv_i(ID name, long type, VALUE ary)
00805 {
00806 return ins_methods_push(name, type, ary, NOEX_PRIVATE);
00807 }
00808
00809 static int
00810 ins_methods_pub_i(ID name, long type, VALUE ary)
00811 {
00812 return ins_methods_push(name, type, ary, NOEX_PUBLIC);
00813 }
00814
00815 static int
00816 method_entry(ID key, const rb_method_entry_t *me, st_table *list)
00817 {
00818 long type;
00819
00820 if (key == ID_ALLOCATOR) {
00821 return ST_CONTINUE;
00822 }
00823
00824 if (!st_lookup(list, key, 0)) {
00825 if (UNDEFINED_METHOD_ENTRY_P(me)) {
00826 type = -1;
00827 }
00828 else {
00829 type = VISI(me->flag);
00830 }
00831 st_add_direct(list, key, type);
00832 }
00833 return ST_CONTINUE;
00834 }
00835
00836 static VALUE
00837 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (ID, long, VALUE))
00838 {
00839 VALUE ary;
00840 int recur;
00841 st_table *list;
00842
00843 if (argc == 0) {
00844 recur = TRUE;
00845 }
00846 else {
00847 VALUE r;
00848 rb_scan_args(argc, argv, "01", &r);
00849 recur = RTEST(r);
00850 }
00851
00852 list = st_init_numtable();
00853 for (; mod; mod = RCLASS_SUPER(mod)) {
00854 st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
00855 if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
00856 if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
00857 if (!recur) break;
00858 }
00859 ary = rb_ary_new();
00860 st_foreach(list, func, ary);
00861 st_free_table(list);
00862
00863 return ary;
00864 }
00865
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 VALUE
00894 rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
00895 {
00896 return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 VALUE
00909 rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
00910 {
00911 return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 VALUE
00932 rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
00933 {
00934 return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 VALUE
00947 rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
00948 {
00949 return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 VALUE
00972 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
00973 {
00974 retry:
00975 if (argc == 0) {
00976 VALUE args[1];
00977
00978 args[0] = Qtrue;
00979 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
00980 }
00981 else {
00982 VALUE recur;
00983
00984 rb_scan_args(argc, argv, "1", &recur);
00985 if (RTEST(recur)) {
00986 argc = 0;
00987 goto retry;
00988 }
00989 return rb_obj_singleton_methods(argc, argv, obj);
00990 }
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 VALUE
01003 rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
01004 {
01005 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 VALUE
01018 rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
01019 {
01020 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 VALUE
01033 rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
01034 {
01035 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
01036 }
01037
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 VALUE
01072 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
01073 {
01074 VALUE recur, ary, klass;
01075 st_table *list;
01076
01077 if (argc == 0) {
01078 recur = Qtrue;
01079 }
01080 else {
01081 rb_scan_args(argc, argv, "01", &recur);
01082 }
01083 klass = CLASS_OF(obj);
01084 list = st_init_numtable();
01085 if (klass && FL_TEST(klass, FL_SINGLETON)) {
01086 st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
01087 klass = RCLASS_SUPER(klass);
01088 }
01089 if (RTEST(recur)) {
01090 while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
01091 st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
01092 klass = RCLASS_SUPER(klass);
01093 }
01094 }
01095 ary = rb_ary_new();
01096 st_foreach(list, ins_methods_i, ary);
01097 st_free_table(list);
01098
01099 return ary;
01100 }
01101
01159 void
01160 rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
01161 {
01162 rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
01163 }
01164
01165 void
01166 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01167 {
01168 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
01169 }
01170
01171 void
01172 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01173 {
01174 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
01175 }
01176
01177 void
01178 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01179 {
01180 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
01181 }
01182
01183 void
01184 rb_undef_method(VALUE klass, const char *name)
01185 {
01186 rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
01187 }
01188
01197 #define SPECIAL_SINGLETON(x,c) do {\
01198 if (obj == (x)) {\
01199 return c;\
01200 }\
01201 } while (0)
01202
01203
01213 static VALUE
01214 singleton_class_of(VALUE obj)
01215 {
01216 VALUE klass;
01217
01218 if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
01219 rb_raise(rb_eTypeError, "can't define singleton");
01220 }
01221 if (rb_special_const_p(obj)) {
01222 SPECIAL_SINGLETON(Qnil, rb_cNilClass);
01223 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
01224 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
01225 rb_bug("unknown immediate %ld", obj);
01226 }
01227
01228 if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
01229 rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) {
01230 klass = RBASIC(obj)->klass;
01231 }
01232 else {
01233 klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
01234 }
01235
01236 if (OBJ_TAINTED(obj)) {
01237 OBJ_TAINT(klass);
01238 }
01239 else {
01240 FL_UNSET(klass, FL_TAINT);
01241 }
01242 if (OBJ_UNTRUSTED(obj)) {
01243 OBJ_UNTRUST(klass);
01244 }
01245 else {
01246 FL_UNSET(klass, FL_UNTRUSTED);
01247 }
01248 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
01249
01250 return klass;
01251 }
01252
01253
01271 VALUE
01272 rb_singleton_class(VALUE obj)
01273 {
01274 VALUE klass = singleton_class_of(obj);
01275
01276
01277 if (TYPE(obj) == T_CLASS) ENSURE_EIGENCLASS(klass);
01278
01279 return klass;
01280 }
01281
01298 void
01299 rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
01300 {
01301 rb_define_method(singleton_class_of(obj), name, func, argc);
01302 }
01303
01304
01305
01313 void
01314 rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
01315 {
01316 rb_define_private_method(module, name, func, argc);
01317 rb_define_singleton_method(module, name, func, argc);
01318 }
01319
01320
01327 void
01328 rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
01329 {
01330 rb_define_module_function(rb_mKernel, name, func, argc);
01331 }
01332
01333
01340 void
01341 rb_define_alias(VALUE klass, const char *name1, const char *name2)
01342 {
01343 rb_alias(klass, rb_intern(name1), rb_intern(name2));
01344 }
01345
01353 void
01354 rb_define_attr(VALUE klass, const char *name, int read, int write)
01355 {
01356 rb_attr(klass, rb_intern(name), read, write, FALSE);
01357 }
01358
01359 int
01360 rb_obj_basic_to_s_p(VALUE obj)
01361 {
01362 const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"));
01363 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
01364 me->def->body.cfunc.func == rb_any_to_s)
01365 return 1;
01366 return 0;
01367 }
01368
01369 #include <stdarg.h>
01370
01371 int
01372 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
01373 {
01374 int i;
01375 const char *p = fmt;
01376 VALUE *var;
01377 va_list vargs;
01378 int f_var = 0, f_block = 0;
01379 int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
01380 int argi = 0;
01381
01382 if (ISDIGIT(*p)) {
01383 n_lead = *p - '0';
01384 p++;
01385 if (ISDIGIT(*p)) {
01386 n_opt = *p - '0';
01387 p++;
01388 if (ISDIGIT(*p)) {
01389 n_trail = *p - '0';
01390 p++;
01391 goto block_arg;
01392 }
01393 }
01394 }
01395 if (*p == '*') {
01396 f_var = 1;
01397 p++;
01398 if (ISDIGIT(*p)) {
01399 n_trail = *p - '0';
01400 p++;
01401 }
01402 }
01403 block_arg:
01404 if (*p == '&') {
01405 f_block = 1;
01406 p++;
01407 }
01408 if (*p != '\0') {
01409 rb_fatal("bad scan arg format: %s", fmt);
01410 }
01411 n_mand = n_lead + n_trail;
01412
01413 if (argc < n_mand)
01414 goto argc_error;
01415
01416 va_start(vargs, fmt);
01417
01418
01419 for (i = n_lead; i-- > 0; ) {
01420 var = va_arg(vargs, VALUE *);
01421 if (var) *var = argv[argi];
01422 argi++;
01423 }
01424
01425 for (i = n_opt; i-- > 0; ) {
01426 var = va_arg(vargs, VALUE *);
01427 if (argi < argc - n_trail) {
01428 if (var) *var = argv[argi];
01429 argi++;
01430 }
01431 else {
01432 if (var) *var = Qnil;
01433 }
01434 }
01435
01436 if (f_var) {
01437 int n_var = argc - argi - n_trail;
01438
01439 var = va_arg(vargs, VALUE *);
01440 if (0 < n_var) {
01441 if (var) *var = rb_ary_new4(n_var, &argv[argi]);
01442 argi += n_var;
01443 }
01444 else {
01445 if (var) *var = rb_ary_new();
01446 }
01447 }
01448
01449 for (i = n_trail; i-- > 0; ) {
01450 var = va_arg(vargs, VALUE *);
01451 if (var) *var = argv[argi];
01452 argi++;
01453 }
01454
01455 if (f_block) {
01456 var = va_arg(vargs, VALUE *);
01457 if (rb_block_given_p()) {
01458 *var = rb_block_proc();
01459 }
01460 else {
01461 *var = Qnil;
01462 }
01463 }
01464 va_end(vargs);
01465
01466 if (argi < argc)
01467 goto argc_error;
01468
01469 return argc;
01470
01471 argc_error:
01472 if (0 < n_opt)
01473 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d..%d%s)",
01474 argc, n_mand, n_mand + n_opt, f_var ? "+" : "");
01475 else
01476 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d%s)",
01477 argc, n_mand, f_var ? "+" : "");
01478 }
01479