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