00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00026 #include "ruby/ruby.h"
00027 #include "ruby/st.h"
00028 #include "method.h"
00029 #include "constant.h"
00030 #include "vm_core.h"
00031 #include "internal.h"
00032 #include <ctype.h>
00033
00034 int rb_vm_add_root_module(ID id, VALUE module);
00035
00036
00037 #define id_attached id__attached__
00038
00039 void
00040 rb_class_subclass_add(VALUE super, VALUE klass)
00041 {
00042 rb_subclass_entry_t *entry, *head;
00043
00044 if (super && super != Qundef) {
00045 entry = xmalloc(sizeof(*entry));
00046 entry->klass = klass;
00047 entry->next = NULL;
00048
00049 head = RCLASS_EXT(super)->subclasses;
00050 if (head) {
00051 entry->next = head;
00052 RCLASS_EXT(head->klass)->parent_subclasses = &entry->next;
00053 }
00054
00055 RCLASS_EXT(super)->subclasses = entry;
00056 RCLASS_EXT(klass)->parent_subclasses = &RCLASS_EXT(super)->subclasses;
00057 }
00058 }
00059
00060 static void
00061 rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
00062 {
00063 rb_subclass_entry_t *entry, *head;
00064
00065 entry = xmalloc(sizeof(*entry));
00066 entry->klass = iclass;
00067 entry->next = NULL;
00068
00069 head = RCLASS_EXT(module)->subclasses;
00070 if (head) {
00071 entry->next = head;
00072 RCLASS_EXT(head->klass)->module_subclasses = &entry->next;
00073 }
00074
00075 RCLASS_EXT(module)->subclasses = entry;
00076 RCLASS_EXT(iclass)->module_subclasses = &RCLASS_EXT(module)->subclasses;
00077 }
00078
00079 void
00080 rb_class_remove_from_super_subclasses(VALUE klass)
00081 {
00082 rb_subclass_entry_t *entry;
00083
00084 if (RCLASS_EXT(klass)->parent_subclasses) {
00085 entry = *RCLASS_EXT(klass)->parent_subclasses;
00086
00087 *RCLASS_EXT(klass)->parent_subclasses = entry->next;
00088 if (entry->next) {
00089 RCLASS_EXT(entry->next->klass)->parent_subclasses = RCLASS_EXT(klass)->parent_subclasses;
00090 }
00091 xfree(entry);
00092 }
00093
00094 RCLASS_EXT(klass)->parent_subclasses = NULL;
00095 }
00096
00097 void
00098 rb_class_remove_from_module_subclasses(VALUE klass)
00099 {
00100 rb_subclass_entry_t *entry;
00101
00102 if (RCLASS_EXT(klass)->module_subclasses) {
00103 entry = *RCLASS_EXT(klass)->module_subclasses;
00104 *RCLASS_EXT(klass)->module_subclasses = entry->next;
00105
00106 if (entry->next) {
00107 RCLASS_EXT(entry->next->klass)->module_subclasses = RCLASS_EXT(klass)->module_subclasses;
00108 }
00109
00110 xfree(entry);
00111 }
00112
00113 RCLASS_EXT(klass)->module_subclasses = NULL;
00114 }
00115
00116 void
00117 rb_class_foreach_subclass(VALUE klass, void(*f)(VALUE))
00118 {
00119 rb_subclass_entry_t *cur = RCLASS_EXT(klass)->subclasses;
00120
00121
00122
00123 while (cur) {
00124 VALUE curklass = cur->klass;
00125 cur = cur->next;
00126 f(curklass);
00127 }
00128 }
00129
00130 void
00131 rb_class_detach_subclasses(VALUE klass)
00132 {
00133 rb_class_foreach_subclass(klass, rb_class_remove_from_super_subclasses);
00134 }
00135
00136 void
00137 rb_class_detach_module_subclasses(VALUE klass)
00138 {
00139 rb_class_foreach_subclass(klass, rb_class_remove_from_module_subclasses);
00140 }
00141
00154 static VALUE
00155 class_alloc(VALUE flags, VALUE klass)
00156 {
00157 NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0));
00158 obj->ptr = ALLOC(rb_classext_t);
00159 RCLASS_IV_TBL(obj) = 0;
00160 RCLASS_CONST_TBL(obj) = 0;
00161 RCLASS_M_TBL_WRAPPER(obj) = 0;
00162 RCLASS_SET_SUPER((VALUE)obj, 0);
00163 RCLASS_ORIGIN(obj) = (VALUE)obj;
00164 RCLASS_IV_INDEX_TBL(obj) = 0;
00165
00166 RCLASS_EXT(obj)->subclasses = NULL;
00167 RCLASS_EXT(obj)->parent_subclasses = NULL;
00168 RCLASS_EXT(obj)->module_subclasses = NULL;
00169 RCLASS_SERIAL(obj) = rb_next_class_serial();
00170
00171 RCLASS_REFINED_CLASS(obj) = Qnil;
00172 RCLASS_EXT(obj)->allocator = 0;
00173 return (VALUE)obj;
00174 }
00175
00176
00186 VALUE
00187 rb_class_boot(VALUE super)
00188 {
00189 VALUE klass = class_alloc(T_CLASS, rb_cClass);
00190
00191 RCLASS_SET_SUPER(klass, super);
00192 RCLASS_M_TBL_INIT(klass);
00193
00194 OBJ_INFECT(klass, super);
00195 return (VALUE)klass;
00196 }
00197
00198
00205 void
00206 rb_check_inheritable(VALUE super)
00207 {
00208 if (!RB_TYPE_P(super, T_CLASS)) {
00209 rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
00210 rb_obj_classname(super));
00211 }
00212 if (RBASIC(super)->flags & FL_SINGLETON) {
00213 rb_raise(rb_eTypeError, "can't make subclass of singleton class");
00214 }
00215 if (super == rb_cClass) {
00216 rb_raise(rb_eTypeError, "can't make subclass of Class");
00217 }
00218 }
00219
00220
00227 VALUE
00228 rb_class_new(VALUE super)
00229 {
00230 Check_Type(super, T_CLASS);
00231 rb_check_inheritable(super);
00232 return rb_class_boot(super);
00233 }
00234
00235 static void
00236 clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
00237 {
00238 VALUE newiseqval;
00239 if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
00240 rb_iseq_t *iseq;
00241 NODE *new_cref;
00242 newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass);
00243 GetISeqPtr(newiseqval, iseq);
00244 rb_vm_rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass, &new_cref);
00245 RB_OBJ_WRITE(iseq->self, &iseq->cref_stack, new_cref);
00246 rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
00247 RB_GC_GUARD(newiseqval);
00248 }
00249 else {
00250 rb_method_entry_set(klass, mid, me, me->flag);
00251 }
00252 }
00253
00254 static int
00255 clone_method_i(st_data_t key, st_data_t value, st_data_t data)
00256 {
00257 clone_method((VALUE)data, (ID)key, (const rb_method_entry_t *)value);
00258 return ST_CONTINUE;
00259 }
00260
00261 struct clone_const_arg {
00262 VALUE klass;
00263 st_table *tbl;
00264 };
00265
00266 static int
00267 clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg)
00268 {
00269 rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
00270 MEMCPY(nce, ce, rb_const_entry_t, 1);
00271 RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
00272 RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
00273
00274 st_insert(arg->tbl, key, (st_data_t)nce);
00275 return ST_CONTINUE;
00276 }
00277
00278 static int
00279 clone_const_i(st_data_t key, st_data_t value, st_data_t data)
00280 {
00281 return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data);
00282 }
00283
00284 static void
00285 class_init_copy_check(VALUE clone, VALUE orig)
00286 {
00287 if (orig == rb_cBasicObject) {
00288 rb_raise(rb_eTypeError, "can't copy the root class");
00289 }
00290 if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
00291 rb_raise(rb_eTypeError, "already initialized class");
00292 }
00293 if (FL_TEST(orig, FL_SINGLETON)) {
00294 rb_raise(rb_eTypeError, "can't copy singleton class");
00295 }
00296 }
00297
00298
00299 VALUE
00300 rb_mod_init_copy(VALUE clone, VALUE orig)
00301 {
00302 if (RB_TYPE_P(clone, T_CLASS)) {
00303 class_init_copy_check(clone, orig);
00304 }
00305 if (!OBJ_INIT_COPY(clone, orig)) return clone;
00306 if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
00307 RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
00308 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00309 }
00310 RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
00311 RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
00312 if (RCLASS_IV_TBL(clone)) {
00313 st_free_table(RCLASS_IV_TBL(clone));
00314 RCLASS_IV_TBL(clone) = 0;
00315 }
00316 if (RCLASS_CONST_TBL(clone)) {
00317 rb_free_const_table(RCLASS_CONST_TBL(clone));
00318 RCLASS_CONST_TBL(clone) = 0;
00319 }
00320 if (RCLASS_M_TBL_WRAPPER(clone)) {
00321 rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
00322 RCLASS_M_TBL_WRAPPER(clone) = 0;
00323 }
00324 if (RCLASS_IV_TBL(orig)) {
00325 st_data_t id;
00326
00327 RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
00328 CONST_ID(id, "__tmp_classpath__");
00329 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00330 CONST_ID(id, "__classpath__");
00331 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00332 CONST_ID(id, "__classid__");
00333 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00334 }
00335 if (RCLASS_CONST_TBL(orig)) {
00336 struct clone_const_arg arg;
00337
00338 RCLASS_CONST_TBL(clone) = st_init_numtable();
00339 arg.klass = clone;
00340 arg.tbl = RCLASS_CONST_TBL(clone);
00341 st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
00342 }
00343 if (RCLASS_M_TBL(orig)) {
00344 RCLASS_M_TBL_INIT(clone);
00345 st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone);
00346 }
00347
00348 return clone;
00349 }
00350
00351 VALUE
00352 rb_singleton_class_clone(VALUE obj)
00353 {
00354 return rb_singleton_class_clone_and_attach(obj, Qundef);
00355 }
00356
00357 VALUE
00358 rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
00359 {
00360 VALUE klass = RBASIC(obj)->klass;
00361
00362 if (!FL_TEST(klass, FL_SINGLETON))
00363 return klass;
00364 else {
00365
00366 VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
00367
00368 if (BUILTIN_TYPE(obj) == T_CLASS) {
00369 RBASIC_SET_CLASS(clone, clone);
00370 }
00371 else {
00372 RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
00373 }
00374
00375 RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
00376 RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
00377 if (RCLASS_IV_TBL(klass)) {
00378 RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass));
00379 }
00380 if (RCLASS_CONST_TBL(klass)) {
00381 struct clone_const_arg arg;
00382 RCLASS_CONST_TBL(clone) = st_init_numtable();
00383 arg.klass = clone;
00384 arg.tbl = RCLASS_CONST_TBL(clone);
00385 st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
00386 }
00387 if (attach != Qundef) {
00388 rb_singleton_class_attached(clone, attach);
00389 }
00390 RCLASS_M_TBL_INIT(clone);
00391 st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone);
00392 rb_singleton_class_attached(RBASIC(clone)->klass, clone);
00393 FL_SET(clone, FL_SINGLETON);
00394
00395 return clone;
00396 }
00397 }
00398
00403 void
00404 rb_singleton_class_attached(VALUE klass, VALUE obj)
00405 {
00406 if (FL_TEST(klass, FL_SINGLETON)) {
00407 if (!RCLASS_IV_TBL(klass)) {
00408 RCLASS_IV_TBL(klass) = st_init_numtable();
00409 }
00410 rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), id_attached, obj);
00411 }
00412 }
00413
00414
00415
00416 #define METACLASS_OF(k) RBASIC(k)->klass
00417 #define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
00418
00424 #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k))
00425
00431 #define HAVE_METACLASS_P(k) \
00432 (FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \
00433 rb_ivar_get(METACLASS_OF(k), id_attached) == (k))
00434
00442 #define ENSURE_EIGENCLASS(klass) \
00443 (HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass))
00444
00445
00455 static inline VALUE
00456 make_metaclass(VALUE klass)
00457 {
00458 VALUE super;
00459 VALUE metaclass = rb_class_boot(Qundef);
00460
00461 FL_SET(metaclass, FL_SINGLETON);
00462 rb_singleton_class_attached(metaclass, klass);
00463
00464 if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
00465 SET_METACLASS_OF(klass, metaclass);
00466 SET_METACLASS_OF(metaclass, metaclass);
00467 }
00468 else {
00469 VALUE tmp = METACLASS_OF(klass);
00470 SET_METACLASS_OF(klass, metaclass);
00471 SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
00472 }
00473
00474 super = RCLASS_SUPER(klass);
00475 while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
00476 RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
00477
00478 OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
00479
00480 return metaclass;
00481 }
00482
00489 static inline VALUE
00490 make_singleton_class(VALUE obj)
00491 {
00492 VALUE orig_class = RBASIC(obj)->klass;
00493 VALUE klass = rb_class_boot(orig_class);
00494
00495 FL_SET(klass, FL_SINGLETON);
00496 RBASIC_SET_CLASS(obj, klass);
00497 rb_singleton_class_attached(klass, obj);
00498
00499 SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
00500 return klass;
00501 }
00502
00503
00504 static VALUE
00505 boot_defclass(const char *name, VALUE super)
00506 {
00507 VALUE obj = rb_class_boot(super);
00508 ID id = rb_intern(name);
00509
00510 rb_name_class(obj, id);
00511 rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
00512 return obj;
00513 }
00514
00515 void
00516 Init_class_hierarchy(void)
00517 {
00518 rb_cBasicObject = boot_defclass("BasicObject", 0);
00519 rb_cObject = boot_defclass("Object", rb_cBasicObject);
00520 rb_cModule = boot_defclass("Module", rb_cObject);
00521 rb_cClass = boot_defclass("Class", rb_cModule);
00522
00523 rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
00524 RBASIC_SET_CLASS(rb_cClass, rb_cClass);
00525 RBASIC_SET_CLASS(rb_cModule, rb_cClass);
00526 RBASIC_SET_CLASS(rb_cObject, rb_cClass);
00527 RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
00528 }
00529
00530
00541 VALUE
00542 rb_make_metaclass(VALUE obj, VALUE unused)
00543 {
00544 if (BUILTIN_TYPE(obj) == T_CLASS) {
00545 return make_metaclass(obj);
00546 }
00547 else {
00548 return make_singleton_class(obj);
00549 }
00550 }
00551
00552
00563 VALUE
00564 rb_define_class_id(ID id, VALUE super)
00565 {
00566 VALUE klass;
00567
00568 if (!super) super = rb_cObject;
00569 klass = rb_class_new(super);
00570 rb_make_metaclass(klass, RBASIC(super)->klass);
00571
00572 return klass;
00573 }
00574
00575
00584 VALUE
00585 rb_class_inherited(VALUE super, VALUE klass)
00586 {
00587 ID inherited;
00588 if (!super) super = rb_cObject;
00589 CONST_ID(inherited, "inherited");
00590 return rb_funcall(super, inherited, 1, klass);
00591 }
00592
00593
00594
00610 VALUE
00611 rb_define_class(const char *name, VALUE super)
00612 {
00613 VALUE klass;
00614 ID id;
00615
00616 id = rb_intern(name);
00617 if (rb_const_defined(rb_cObject, id)) {
00618 klass = rb_const_get(rb_cObject, id);
00619 if (!RB_TYPE_P(klass, T_CLASS)) {
00620 rb_raise(rb_eTypeError, "%s is not a class", name);
00621 }
00622 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00623 rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
00624 }
00625 return klass;
00626 }
00627 if (!super) {
00628 rb_warn("no super class for `%s', Object assumed", name);
00629 }
00630 klass = rb_define_class_id(id, super);
00631 rb_vm_add_root_module(id, klass);
00632 rb_name_class(klass, id);
00633 rb_const_set(rb_cObject, id, klass);
00634 rb_class_inherited(super, klass);
00635
00636 return klass;
00637 }
00638
00639
00656 VALUE
00657 rb_define_class_under(VALUE outer, const char *name, VALUE super)
00658 {
00659 return rb_define_class_id_under(outer, rb_intern(name), super);
00660 }
00661
00662
00679 VALUE
00680 rb_define_class_id_under(VALUE outer, ID id, VALUE super)
00681 {
00682 VALUE klass;
00683
00684 if (rb_const_defined_at(outer, id)) {
00685 klass = rb_const_get_at(outer, id);
00686 if (!RB_TYPE_P(klass, T_CLASS)) {
00687 rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
00688 }
00689 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00690 rb_name_error(id, "%s is already defined", rb_id2name(id));
00691 }
00692 return klass;
00693 }
00694 if (!super) {
00695 rb_warn("no super class for `%s::%s', Object assumed",
00696 rb_class2name(outer), rb_id2name(id));
00697 }
00698 klass = rb_define_class_id(id, super);
00699 rb_set_class_path_string(klass, outer, rb_id2str(id));
00700 rb_const_set(outer, id, klass);
00701 rb_class_inherited(super, klass);
00702 rb_gc_register_mark_object(klass);
00703
00704 return klass;
00705 }
00706
00707 VALUE
00708 rb_module_new(void)
00709 {
00710 VALUE mdl = class_alloc(T_MODULE, rb_cModule);
00711 RCLASS_M_TBL_INIT(mdl);
00712 return (VALUE)mdl;
00713 }
00714
00715 VALUE
00716 rb_define_module_id(ID id)
00717 {
00718 VALUE mdl;
00719
00720 mdl = rb_module_new();
00721 rb_name_class(mdl, id);
00722
00723 return mdl;
00724 }
00725
00726 VALUE
00727 rb_define_module(const char *name)
00728 {
00729 VALUE module;
00730 ID id;
00731
00732 id = rb_intern(name);
00733 if (rb_const_defined(rb_cObject, id)) {
00734 module = rb_const_get(rb_cObject, id);
00735 if (RB_TYPE_P(module, T_MODULE))
00736 return module;
00737 rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
00738 }
00739 module = rb_define_module_id(id);
00740 rb_vm_add_root_module(id, module);
00741 rb_const_set(rb_cObject, id, module);
00742
00743 return module;
00744 }
00745
00746 VALUE
00747 rb_define_module_under(VALUE outer, const char *name)
00748 {
00749 return rb_define_module_id_under(outer, rb_intern(name));
00750 }
00751
00752 VALUE
00753 rb_define_module_id_under(VALUE outer, ID id)
00754 {
00755 VALUE module;
00756
00757 if (rb_const_defined_at(outer, id)) {
00758 module = rb_const_get_at(outer, id);
00759 if (RB_TYPE_P(module, T_MODULE))
00760 return module;
00761 rb_raise(rb_eTypeError, "%s::%s is not a module",
00762 rb_class2name(outer), rb_obj_classname(module));
00763 }
00764 module = rb_define_module_id(id);
00765 rb_const_set(outer, id, module);
00766 rb_set_class_path_string(module, outer, rb_id2str(id));
00767 rb_gc_register_mark_object(module);
00768
00769 return module;
00770 }
00771
00772 VALUE
00773 rb_include_class_new(VALUE module, VALUE super)
00774 {
00775 VALUE klass = class_alloc(T_ICLASS, rb_cClass);
00776
00777 if (BUILTIN_TYPE(module) == T_ICLASS) {
00778 module = RBASIC(module)->klass;
00779 }
00780 if (!RCLASS_IV_TBL(module)) {
00781 RCLASS_IV_TBL(module) = st_init_numtable();
00782 }
00783 if (!RCLASS_CONST_TBL(module)) {
00784 RCLASS_CONST_TBL(module) = st_init_numtable();
00785 }
00786 RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
00787 RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
00788
00789 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(klass)) =
00790 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(RCLASS_ORIGIN(module)));
00791
00792 RCLASS_SET_SUPER(klass, super);
00793 if (RB_TYPE_P(module, T_ICLASS)) {
00794 RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
00795 }
00796 else {
00797 RBASIC_SET_CLASS(klass, module);
00798 }
00799 OBJ_INFECT(klass, module);
00800 OBJ_INFECT(klass, super);
00801
00802 return (VALUE)klass;
00803 }
00804
00805 static int include_modules_at(const VALUE klass, VALUE c, VALUE module);
00806
00807 void
00808 rb_include_module(VALUE klass, VALUE module)
00809 {
00810 int changed = 0;
00811
00812 rb_frozen_class_p(klass);
00813
00814 if (!RB_TYPE_P(module, T_MODULE)) {
00815 Check_Type(module, T_MODULE);
00816 }
00817
00818 OBJ_INFECT(klass, module);
00819
00820 changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module);
00821 if (changed < 0)
00822 rb_raise(rb_eArgError, "cyclic include detected");
00823 }
00824
00825 static int
00826 add_refined_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
00827 {
00828 rb_add_refined_method_entry((VALUE) data, (ID) key);
00829 return ST_CONTINUE;
00830 }
00831
00832 static int
00833 include_modules_at(const VALUE klass, VALUE c, VALUE module)
00834 {
00835 VALUE p, iclass;
00836 int method_changed = 0, constant_changed = 0;
00837 const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
00838
00839 while (module) {
00840 int superclass_seen = FALSE;
00841
00842 if (RCLASS_ORIGIN(module) != module)
00843 goto skip;
00844 if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
00845 return -1;
00846
00847 for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
00848 switch (BUILTIN_TYPE(p)) {
00849 case T_ICLASS:
00850 if (RCLASS_M_TBL_WRAPPER(p) == RCLASS_M_TBL_WRAPPER(module)) {
00851 if (!superclass_seen) {
00852 c = p;
00853 }
00854 goto skip;
00855 }
00856 break;
00857 case T_CLASS:
00858 superclass_seen = TRUE;
00859 break;
00860 }
00861 }
00862 iclass = rb_include_class_new(module, RCLASS_SUPER(c));
00863 c = RCLASS_SET_SUPER(c, iclass);
00864
00865 if (BUILTIN_TYPE(module) == T_ICLASS) {
00866 rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass);
00867 } else {
00868 rb_module_add_to_subclasses_list(module, iclass);
00869 }
00870
00871 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
00872 VALUE refined_class =
00873 rb_refinement_module_get_refined_class(klass);
00874
00875 st_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i,
00876 (st_data_t) refined_class);
00877 FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
00878 }
00879 if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
00880 method_changed = 1;
00881 if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
00882 constant_changed = 1;
00883 skip:
00884 module = RCLASS_SUPER(module);
00885 }
00886
00887 if (method_changed) rb_clear_method_cache_by_class(klass);
00888 if (constant_changed) rb_clear_constant_cache();
00889
00890 return method_changed;
00891 }
00892
00893 static int
00894 move_refined_method(st_data_t key, st_data_t value, st_data_t data)
00895 {
00896 rb_method_entry_t *me = (rb_method_entry_t *) value;
00897 st_table *tbl = (st_table *) data;
00898
00899 if (me->def->type == VM_METHOD_TYPE_REFINED) {
00900 if (me->def->body.orig_me) {
00901 rb_method_entry_t *orig_me = me->def->body.orig_me, *new_me;
00902 me->def->body.orig_me = NULL;
00903 new_me = ALLOC(rb_method_entry_t);
00904 *new_me = *me;
00905 st_add_direct(tbl, key, (st_data_t) new_me);
00906 *me = *orig_me;
00907 xfree(orig_me);
00908 return ST_CONTINUE;
00909 }
00910 else {
00911 st_add_direct(tbl, key, (st_data_t) me);
00912 return ST_DELETE;
00913 }
00914 }
00915 else {
00916 return ST_CONTINUE;
00917 }
00918 }
00919
00920 void
00921 rb_prepend_module(VALUE klass, VALUE module)
00922 {
00923 void rb_vm_check_redefinition_by_prepend(VALUE klass);
00924 VALUE origin;
00925 int changed = 0;
00926
00927 rb_frozen_class_p(klass);
00928
00929 Check_Type(module, T_MODULE);
00930
00931 OBJ_INFECT(klass, module);
00932
00933 origin = RCLASS_ORIGIN(klass);
00934 if (origin == klass) {
00935 origin = class_alloc(T_ICLASS, klass);
00936 OBJ_WB_UNPROTECT(origin);
00937 RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
00938 RCLASS_SET_SUPER(klass, origin);
00939 RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin);
00940 RCLASS_M_TBL_WRAPPER(origin) = RCLASS_M_TBL_WRAPPER(klass);
00941 RCLASS_M_TBL_INIT(klass);
00942 st_foreach(RCLASS_M_TBL(origin), move_refined_method,
00943 (st_data_t) RCLASS_M_TBL(klass));
00944 }
00945 changed = include_modules_at(klass, klass, module);
00946 if (changed < 0)
00947 rb_raise(rb_eArgError, "cyclic prepend detected");
00948 if (changed) {
00949 rb_vm_check_redefinition_by_prepend(klass);
00950 }
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 VALUE
00971 rb_mod_included_modules(VALUE mod)
00972 {
00973 VALUE ary = rb_ary_new();
00974 VALUE p;
00975 VALUE origin = RCLASS_ORIGIN(mod);
00976
00977 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00978 if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
00979 VALUE m = RBASIC(p)->klass;
00980 if (RB_TYPE_P(m, T_MODULE))
00981 rb_ary_push(ary, m);
00982 }
00983 }
00984 return ary;
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 VALUE
01007 rb_mod_include_p(VALUE mod, VALUE mod2)
01008 {
01009 VALUE p;
01010
01011 Check_Type(mod2, T_MODULE);
01012 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
01013 if (BUILTIN_TYPE(p) == T_ICLASS) {
01014 if (RBASIC(p)->klass == mod2) return Qtrue;
01015 }
01016 }
01017 return Qfalse;
01018 }
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036 VALUE
01037 rb_mod_ancestors(VALUE mod)
01038 {
01039 VALUE p, ary = rb_ary_new();
01040
01041 for (p = mod; p; p = RCLASS_SUPER(p)) {
01042 if (BUILTIN_TYPE(p) == T_ICLASS) {
01043 rb_ary_push(ary, RBASIC(p)->klass);
01044 }
01045 else if (p == RCLASS_ORIGIN(p)) {
01046 rb_ary_push(ary, p);
01047 }
01048 }
01049 return ary;
01050 }
01051
01052 #define VISI(x) ((x)&NOEX_MASK)
01053 #define VISI_CHECK(x,f) (VISI(x) == (f))
01054
01055 static int
01056 ins_methods_push(ID name, long type, VALUE ary, long visi)
01057 {
01058 if (type == -1) return ST_CONTINUE;
01059
01060 switch (visi) {
01061 case NOEX_PRIVATE:
01062 case NOEX_PROTECTED:
01063 case NOEX_PUBLIC:
01064 visi = (type == visi);
01065 break;
01066 default:
01067 visi = (type != NOEX_PRIVATE);
01068 break;
01069 }
01070 if (visi) {
01071 rb_ary_push(ary, ID2SYM(name));
01072 }
01073 return ST_CONTINUE;
01074 }
01075
01076 static int
01077 ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
01078 {
01079 return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1);
01080 }
01081
01082 static int
01083 ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
01084 {
01085 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED);
01086 }
01087
01088 static int
01089 ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
01090 {
01091 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE);
01092 }
01093
01094 static int
01095 ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
01096 {
01097 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
01098 }
01099
01100 struct method_entry_arg {
01101 st_table *list;
01102 int recur;
01103 };
01104
01105 static int
01106 method_entry_i(st_data_t key, st_data_t value, st_data_t data)
01107 {
01108 const rb_method_entry_t *me = (const rb_method_entry_t *)value;
01109 struct method_entry_arg *arg = (struct method_entry_arg *)data;
01110 long type;
01111
01112 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
01113 VALUE klass = me->klass;
01114 me = rb_resolve_refined_method(Qnil, me, NULL);
01115 if (!me) return ST_CONTINUE;
01116 if (!arg->recur && me->klass != klass) return ST_CONTINUE;
01117 }
01118 if (!st_lookup(arg->list, key, 0)) {
01119 if (UNDEFINED_METHOD_ENTRY_P(me)) {
01120 type = -1;
01121 }
01122 else {
01123 type = VISI(me->flag);
01124 }
01125 st_add_direct(arg->list, key, type);
01126 }
01127 return ST_CONTINUE;
01128 }
01129
01130 static VALUE
01131 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
01132 {
01133 VALUE ary;
01134 int recur, prepended = 0;
01135 struct method_entry_arg me_arg;
01136
01137 if (argc == 0) {
01138 recur = TRUE;
01139 }
01140 else {
01141 VALUE r;
01142 rb_scan_args(argc, argv, "01", &r);
01143 recur = RTEST(r);
01144 }
01145
01146 if (!recur && RCLASS_ORIGIN(mod) != mod) {
01147 mod = RCLASS_ORIGIN(mod);
01148 prepended = 1;
01149 }
01150
01151 me_arg.list = st_init_numtable();
01152 me_arg.recur = recur;
01153 for (; mod; mod = RCLASS_SUPER(mod)) {
01154 if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&me_arg);
01155 if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
01156 if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
01157 if (!recur) break;
01158 }
01159 ary = rb_ary_new();
01160 st_foreach(me_arg.list, func, ary);
01161 st_free_table(me_arg.list);
01162
01163 return ary;
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 VALUE
01194 rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
01195 {
01196 return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 VALUE
01209 rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
01210 {
01211 return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 VALUE
01232 rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
01233 {
01234 return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
01235 }
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246 VALUE
01247 rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
01248 {
01249 return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 VALUE
01283 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
01284 {
01285 retry:
01286 if (argc == 0) {
01287 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
01288 }
01289 else {
01290 VALUE recur;
01291
01292 rb_scan_args(argc, argv, "1", &recur);
01293 if (RTEST(recur)) {
01294 argc = 0;
01295 goto retry;
01296 }
01297 return rb_obj_singleton_methods(argc, argv, obj);
01298 }
01299 }
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 VALUE
01311 rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
01312 {
01313 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
01314 }
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325 VALUE
01326 rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
01327 {
01328 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340 VALUE
01341 rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
01342 {
01343 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379 VALUE
01380 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
01381 {
01382 VALUE recur, ary, klass, origin;
01383 struct method_entry_arg me_arg;
01384 st_table *mtbl;
01385
01386 if (argc == 0) {
01387 recur = Qtrue;
01388 }
01389 else {
01390 rb_scan_args(argc, argv, "01", &recur);
01391 }
01392 klass = CLASS_OF(obj);
01393 origin = RCLASS_ORIGIN(klass);
01394 me_arg.list = st_init_numtable();
01395 me_arg.recur = recur;
01396 if (klass && FL_TEST(klass, FL_SINGLETON)) {
01397 if ((mtbl = RCLASS_M_TBL(origin)) != 0)
01398 st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
01399 klass = RCLASS_SUPER(klass);
01400 }
01401 if (RTEST(recur)) {
01402 while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
01403 if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
01404 st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
01405 klass = RCLASS_SUPER(klass);
01406 }
01407 }
01408 ary = rb_ary_new();
01409 st_foreach(me_arg.list, ins_methods_i, ary);
01410 st_free_table(me_arg.list);
01411
01412 return ary;
01413 }
01414
01472 void
01473 rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
01474 {
01475 rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
01476 }
01477
01478 void
01479 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01480 {
01481 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
01482 }
01483
01484 void
01485 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01486 {
01487 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
01488 }
01489
01490 void
01491 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01492 {
01493 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
01494 }
01495
01496 void
01497 rb_undef_method(VALUE klass, const char *name)
01498 {
01499 rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
01500 }
01501
01510 #define SPECIAL_SINGLETON(x,c) do {\
01511 if (obj == (x)) {\
01512 return (c);\
01513 }\
01514 } while (0)
01515
01516 static inline VALUE
01517 special_singleton_class_of(VALUE obj)
01518 {
01519 SPECIAL_SINGLETON(Qnil, rb_cNilClass);
01520 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
01521 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
01522 return Qnil;
01523 }
01524
01525 VALUE
01526 rb_special_singleton_class(VALUE obj)
01527 {
01528 return special_singleton_class_of(obj);
01529 }
01530
01540 static VALUE
01541 singleton_class_of(VALUE obj)
01542 {
01543 VALUE klass;
01544
01545 if (FIXNUM_P(obj) || FLONUM_P(obj) || SYMBOL_P(obj)) {
01546 rb_raise(rb_eTypeError, "can't define singleton");
01547 }
01548 if (SPECIAL_CONST_P(obj)) {
01549 klass = special_singleton_class_of(obj);
01550 if (NIL_P(klass))
01551 rb_bug("unknown immediate %p", (void *)obj);
01552 return klass;
01553 }
01554 else {
01555 enum ruby_value_type type = BUILTIN_TYPE(obj);
01556 if (type == T_FLOAT || type == T_BIGNUM) {
01557 rb_raise(rb_eTypeError, "can't define singleton");
01558 }
01559 }
01560
01561 if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
01562 rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) {
01563 klass = RBASIC(obj)->klass;
01564 }
01565 else {
01566 klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
01567 }
01568
01569 if (OBJ_TAINTED(obj)) {
01570 OBJ_TAINT(klass);
01571 }
01572 else {
01573 FL_UNSET(klass, FL_TAINT);
01574 }
01575 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
01576
01577 return klass;
01578 }
01579
01587 VALUE
01588 rb_singleton_class_get(VALUE obj)
01589 {
01590 VALUE klass;
01591
01592 if (SPECIAL_CONST_P(obj)) {
01593 return rb_special_singleton_class(obj);
01594 }
01595 klass = RBASIC(obj)->klass;
01596 if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
01597 if (rb_ivar_get(klass, id_attached) != obj) return Qnil;
01598 return klass;
01599 }
01600
01618 VALUE
01619 rb_singleton_class(VALUE obj)
01620 {
01621 VALUE klass = singleton_class_of(obj);
01622
01623
01624 if (RB_TYPE_P(obj, T_CLASS)) (void)ENSURE_EIGENCLASS(klass);
01625
01626 return klass;
01627 }
01628
01645 void
01646 rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
01647 {
01648 rb_define_method(singleton_class_of(obj), name, func, argc);
01649 }
01650
01651
01652
01660 void
01661 rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
01662 {
01663 rb_define_private_method(module, name, func, argc);
01664 rb_define_singleton_method(module, name, func, argc);
01665 }
01666
01667
01674 void
01675 rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
01676 {
01677 rb_define_module_function(rb_mKernel, name, func, argc);
01678 }
01679
01680
01687 void
01688 rb_define_alias(VALUE klass, const char *name1, const char *name2)
01689 {
01690 rb_alias(klass, rb_intern(name1), rb_intern(name2));
01691 }
01692
01700 void
01701 rb_define_attr(VALUE klass, const char *name, int read, int write)
01702 {
01703 rb_attr(klass, rb_intern(name), read, write, FALSE);
01704 }
01705
01706 int
01707 rb_obj_basic_to_s_p(VALUE obj)
01708 {
01709 const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"), 0);
01710 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
01711 me->def->body.cfunc.func == rb_any_to_s)
01712 return 1;
01713 return 0;
01714 }
01715
01716 #include <stdarg.h>
01717
01718 int
01719 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
01720 {
01721 int i;
01722 const char *p = fmt;
01723 VALUE *var;
01724 va_list vargs;
01725 int f_var = 0, f_hash = 0, f_block = 0;
01726 int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
01727 int argi = 0;
01728 VALUE hash = Qnil;
01729
01730 if (ISDIGIT(*p)) {
01731 n_lead = *p - '0';
01732 p++;
01733 if (ISDIGIT(*p)) {
01734 n_opt = *p - '0';
01735 p++;
01736 if (ISDIGIT(*p)) {
01737 n_trail = *p - '0';
01738 p++;
01739 goto block_arg;
01740 }
01741 }
01742 }
01743 if (*p == '*') {
01744 f_var = 1;
01745 p++;
01746 if (ISDIGIT(*p)) {
01747 n_trail = *p - '0';
01748 p++;
01749 }
01750 }
01751 block_arg:
01752 if (*p == ':') {
01753 f_hash = 1;
01754 p++;
01755 }
01756 if (*p == '&') {
01757 f_block = 1;
01758 p++;
01759 }
01760 if (*p != '\0') {
01761 rb_fatal("bad scan arg format: %s", fmt);
01762 }
01763 n_mand = n_lead + n_trail;
01764
01765 if (argc < n_mand)
01766 goto argc_error;
01767
01768 va_start(vargs, fmt);
01769
01770
01771 if (f_hash && n_mand < argc) {
01772 VALUE last = argv[argc - 1];
01773
01774 if (NIL_P(last)) {
01775
01776
01777
01778 if (!f_var && n_mand + n_opt < argc)
01779 argc--;
01780 }
01781 else {
01782 hash = rb_check_hash_type(last);
01783 if (!NIL_P(hash)) {
01784 VALUE opts = rb_extract_keywords(&hash);
01785 if (!hash) argc--;
01786 hash = opts ? opts : Qnil;
01787 }
01788 }
01789 }
01790
01791 for (i = n_lead; i-- > 0; ) {
01792 var = va_arg(vargs, VALUE *);
01793 if (var) *var = argv[argi];
01794 argi++;
01795 }
01796
01797 for (i = n_opt; i-- > 0; ) {
01798 var = va_arg(vargs, VALUE *);
01799 if (argi < argc - n_trail) {
01800 if (var) *var = argv[argi];
01801 argi++;
01802 }
01803 else {
01804 if (var) *var = Qnil;
01805 }
01806 }
01807
01808 if (f_var) {
01809 int n_var = argc - argi - n_trail;
01810
01811 var = va_arg(vargs, VALUE *);
01812 if (0 < n_var) {
01813 if (var) *var = rb_ary_new4(n_var, &argv[argi]);
01814 argi += n_var;
01815 }
01816 else {
01817 if (var) *var = rb_ary_new();
01818 }
01819 }
01820
01821 for (i = n_trail; i-- > 0; ) {
01822 var = va_arg(vargs, VALUE *);
01823 if (var) *var = argv[argi];
01824 argi++;
01825 }
01826
01827 if (f_hash) {
01828 var = va_arg(vargs, VALUE *);
01829 if (var) *var = hash;
01830 }
01831
01832 if (f_block) {
01833 var = va_arg(vargs, VALUE *);
01834 if (rb_block_given_p()) {
01835 *var = rb_block_proc();
01836 }
01837 else {
01838 *var = Qnil;
01839 }
01840 }
01841 va_end(vargs);
01842
01843 if (argi < argc) {
01844 argc_error:
01845 rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
01846 }
01847
01848 return argc;
01849 }
01850
01851 NORETURN(static void keyword_error(const char *error, VALUE keys));
01852 static void
01853 keyword_error(const char *error, VALUE keys)
01854 {
01855 const char *msg = "";
01856 if (RARRAY_LEN(keys) == 1) {
01857 keys = RARRAY_AREF(keys, 0);
01858 }
01859 else {
01860 keys = rb_ary_join(keys, rb_usascii_str_new2(", "));
01861 msg = "s";
01862 }
01863 rb_raise(rb_eArgError, "%s keyword%s: %"PRIsVALUE, error, msg, keys);
01864 }
01865
01866 NORETURN(static void unknown_keyword_error(VALUE hash, const ID *table, int keywords));
01867 static void
01868 unknown_keyword_error(VALUE hash, const ID *table, int keywords)
01869 {
01870 st_table *tbl = rb_hash_tbl_raw(hash);
01871 VALUE keys;
01872 int i;
01873 for (i = 0; i < keywords; i++) {
01874 st_data_t key = ID2SYM(table[i]);
01875 st_delete(tbl, &key, NULL);
01876 }
01877 keys = rb_funcall(hash, rb_intern("keys"), 0, 0);
01878 if (!RB_TYPE_P(keys, T_ARRAY)) rb_raise(rb_eArgError, "unknown keyword");
01879 keyword_error("unknown", keys);
01880 }
01881
01882 static int
01883 separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
01884 {
01885 VALUE *kwdhash = (VALUE *)arg;
01886
01887 if (!SYMBOL_P(key)) kwdhash++;
01888 if (!*kwdhash) *kwdhash = rb_hash_new();
01889 rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
01890 return ST_CONTINUE;
01891 }
01892
01893 VALUE
01894 rb_extract_keywords(VALUE *orighash)
01895 {
01896 VALUE parthash[2] = {0, 0};
01897 VALUE hash = *orighash;
01898
01899 if (RHASH_EMPTY_P(hash)) {
01900 *orighash = 0;
01901 return hash;
01902 }
01903 st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&parthash);
01904 *orighash = parthash[1];
01905 return parthash[0];
01906 }
01907
01908 int
01909 rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
01910 {
01911 int i = 0, j;
01912 int rest = 0;
01913 VALUE missing = Qnil;
01914 st_data_t key;
01915
01916 #define extract_kwarg(keyword, val) \
01917 (key = (st_data_t)(keyword), values ? \
01918 st_delete(rb_hash_tbl_raw(keyword_hash), &key, (val)) : \
01919 st_lookup(rb_hash_tbl_raw(keyword_hash), key, (val)))
01920
01921 if (optional < 0) {
01922 rest = 1;
01923 optional = -1-optional;
01924 }
01925 if (values) {
01926 for (j = 0; j < required + optional; j++) {
01927 values[j] = Qundef;
01928 }
01929 }
01930 if (required) {
01931 for (; i < required; i++) {
01932 VALUE keyword = ID2SYM(table[i]);
01933 if (keyword_hash) {
01934 st_data_t val;
01935 if (extract_kwarg(keyword, &val)) {
01936 if (values) values[i] = (VALUE)val;
01937 continue;
01938 }
01939 }
01940 if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
01941 rb_ary_push(missing, keyword);
01942 }
01943 if (!NIL_P(missing)) {
01944 keyword_error("missing", missing);
01945 }
01946 }
01947 j = i;
01948 if (optional && keyword_hash) {
01949 for (i = 0; i < optional; i++) {
01950 st_data_t val;
01951 if (extract_kwarg(ID2SYM(table[required+i]), &val)) {
01952 if (values) values[required+i] = (VALUE)val;
01953 j++;
01954 }
01955 }
01956 }
01957 if (!rest && keyword_hash) {
01958 if (RHASH_SIZE(keyword_hash) > (unsigned int)j) {
01959 unknown_keyword_error(keyword_hash, table, required+optional);
01960 }
01961 }
01962 return j;
01963 #undef extract_kwarg
01964 }
01965