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 rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
00237 {
00238 NODE *new_node;
00239 while (node) {
00240 if (node->nd_clss == old_klass) {
00241 new_node = NEW_CREF(new_klass);
00242 RB_OBJ_WRITE(new_node, &new_node->nd_next, node->nd_next);
00243 *new_cref_ptr = new_node;
00244 return;
00245 }
00246 new_node = NEW_CREF(node->nd_clss);
00247 node = node->nd_next;
00248 *new_cref_ptr = new_node;
00249 new_cref_ptr = &new_node->nd_next;
00250 }
00251 *new_cref_ptr = NULL;
00252 }
00253
00254 static void
00255 clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
00256 {
00257 VALUE newiseqval;
00258 if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
00259 rb_iseq_t *iseq;
00260 NODE *new_cref;
00261 newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass);
00262 GetISeqPtr(newiseqval, iseq);
00263 rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass, &new_cref);
00264 RB_OBJ_WRITE(iseq->self, &iseq->cref_stack, new_cref);
00265 rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
00266 RB_GC_GUARD(newiseqval);
00267 }
00268 else {
00269 rb_method_entry_set(klass, mid, me, me->flag);
00270 }
00271 }
00272
00273 static int
00274 clone_method_i(st_data_t key, st_data_t value, st_data_t data)
00275 {
00276 clone_method((VALUE)data, (ID)key, (const rb_method_entry_t *)value);
00277 return ST_CONTINUE;
00278 }
00279
00280 struct clone_const_arg {
00281 VALUE klass;
00282 st_table *tbl;
00283 };
00284
00285 static int
00286 clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg)
00287 {
00288 rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
00289 MEMCPY(nce, ce, rb_const_entry_t, 1);
00290 RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
00291 RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
00292
00293 st_insert(arg->tbl, key, (st_data_t)nce);
00294 return ST_CONTINUE;
00295 }
00296
00297 static int
00298 clone_const_i(st_data_t key, st_data_t value, st_data_t data)
00299 {
00300 return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data);
00301 }
00302
00303 static void
00304 class_init_copy_check(VALUE clone, VALUE orig)
00305 {
00306 if (orig == rb_cBasicObject) {
00307 rb_raise(rb_eTypeError, "can't copy the root class");
00308 }
00309 if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
00310 rb_raise(rb_eTypeError, "already initialized class");
00311 }
00312 if (FL_TEST(orig, FL_SINGLETON)) {
00313 rb_raise(rb_eTypeError, "can't copy singleton class");
00314 }
00315 }
00316
00317
00318 VALUE
00319 rb_mod_init_copy(VALUE clone, VALUE orig)
00320 {
00321 if (RB_TYPE_P(clone, T_CLASS)) {
00322 class_init_copy_check(clone, orig);
00323 }
00324 if (!OBJ_INIT_COPY(clone, orig)) return clone;
00325 if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
00326 RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
00327 rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
00328 }
00329 RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
00330 RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
00331 if (RCLASS_IV_TBL(clone)) {
00332 st_free_table(RCLASS_IV_TBL(clone));
00333 RCLASS_IV_TBL(clone) = 0;
00334 }
00335 if (RCLASS_CONST_TBL(clone)) {
00336 rb_free_const_table(RCLASS_CONST_TBL(clone));
00337 RCLASS_CONST_TBL(clone) = 0;
00338 }
00339 if (RCLASS_M_TBL_WRAPPER(clone)) {
00340 rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
00341 RCLASS_M_TBL_WRAPPER(clone) = 0;
00342 }
00343 if (RCLASS_IV_TBL(orig)) {
00344 st_data_t id;
00345
00346 RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
00347 CONST_ID(id, "__tmp_classpath__");
00348 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00349 CONST_ID(id, "__classpath__");
00350 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00351 CONST_ID(id, "__classid__");
00352 st_delete(RCLASS_IV_TBL(clone), &id, 0);
00353 }
00354 if (RCLASS_CONST_TBL(orig)) {
00355 struct clone_const_arg arg;
00356
00357 RCLASS_CONST_TBL(clone) = st_init_numtable();
00358 arg.klass = clone;
00359 arg.tbl = RCLASS_CONST_TBL(clone);
00360 st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
00361 }
00362 if (RCLASS_M_TBL(orig)) {
00363 RCLASS_M_TBL_INIT(clone);
00364 st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone);
00365 }
00366
00367 return clone;
00368 }
00369
00370 VALUE
00371 rb_singleton_class_clone(VALUE obj)
00372 {
00373 return rb_singleton_class_clone_and_attach(obj, Qundef);
00374 }
00375
00376 VALUE
00377 rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
00378 {
00379 VALUE klass = RBASIC(obj)->klass;
00380
00381 if (!FL_TEST(klass, FL_SINGLETON))
00382 return klass;
00383 else {
00384
00385 VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
00386
00387 if (BUILTIN_TYPE(obj) == T_CLASS) {
00388 RBASIC_SET_CLASS(clone, clone);
00389 }
00390 else {
00391 RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
00392 }
00393
00394 RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
00395 RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
00396 if (RCLASS_IV_TBL(klass)) {
00397 RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass));
00398 }
00399 if (RCLASS_CONST_TBL(klass)) {
00400 struct clone_const_arg arg;
00401 RCLASS_CONST_TBL(clone) = st_init_numtable();
00402 arg.klass = clone;
00403 arg.tbl = RCLASS_CONST_TBL(clone);
00404 st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
00405 }
00406 if (attach != Qundef) {
00407 rb_singleton_class_attached(clone, attach);
00408 }
00409 RCLASS_M_TBL_INIT(clone);
00410 st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone);
00411 rb_singleton_class_attached(RBASIC(clone)->klass, clone);
00412 FL_SET(clone, FL_SINGLETON);
00413
00414 return clone;
00415 }
00416 }
00417
00422 void
00423 rb_singleton_class_attached(VALUE klass, VALUE obj)
00424 {
00425 if (FL_TEST(klass, FL_SINGLETON)) {
00426 if (!RCLASS_IV_TBL(klass)) {
00427 RCLASS_IV_TBL(klass) = st_init_numtable();
00428 }
00429 rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), id_attached, obj);
00430 }
00431 }
00432
00433
00434
00435 #define METACLASS_OF(k) RBASIC(k)->klass
00436 #define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
00437
00443 #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k))
00444
00450 #define HAVE_METACLASS_P(k) \
00451 (FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \
00452 rb_ivar_get(METACLASS_OF(k), id_attached) == (k))
00453
00461 #define ENSURE_EIGENCLASS(klass) \
00462 (HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass))
00463
00464
00474 static inline VALUE
00475 make_metaclass(VALUE klass)
00476 {
00477 VALUE super;
00478 VALUE metaclass = rb_class_boot(Qundef);
00479
00480 FL_SET(metaclass, FL_SINGLETON);
00481 rb_singleton_class_attached(metaclass, klass);
00482
00483 if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
00484 SET_METACLASS_OF(klass, metaclass);
00485 SET_METACLASS_OF(metaclass, metaclass);
00486 }
00487 else {
00488 VALUE tmp = METACLASS_OF(klass);
00489 SET_METACLASS_OF(klass, metaclass);
00490 SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
00491 }
00492
00493 super = RCLASS_SUPER(klass);
00494 while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
00495 RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
00496
00497 OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
00498
00499 return metaclass;
00500 }
00501
00508 static inline VALUE
00509 make_singleton_class(VALUE obj)
00510 {
00511 VALUE orig_class = RBASIC(obj)->klass;
00512 VALUE klass = rb_class_boot(orig_class);
00513
00514 FL_SET(klass, FL_SINGLETON);
00515 RBASIC_SET_CLASS(obj, klass);
00516 rb_singleton_class_attached(klass, obj);
00517
00518 SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
00519 return klass;
00520 }
00521
00522
00523 static VALUE
00524 boot_defclass(const char *name, VALUE super)
00525 {
00526 VALUE obj = rb_class_boot(super);
00527 ID id = rb_intern(name);
00528
00529 rb_name_class(obj, id);
00530 rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
00531 return obj;
00532 }
00533
00534 void
00535 Init_class_hierarchy(void)
00536 {
00537 rb_cBasicObject = boot_defclass("BasicObject", 0);
00538 rb_cObject = boot_defclass("Object", rb_cBasicObject);
00539 rb_cModule = boot_defclass("Module", rb_cObject);
00540 rb_cClass = boot_defclass("Class", rb_cModule);
00541
00542 rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
00543 RBASIC_SET_CLASS(rb_cClass, rb_cClass);
00544 RBASIC_SET_CLASS(rb_cModule, rb_cClass);
00545 RBASIC_SET_CLASS(rb_cObject, rb_cClass);
00546 RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
00547 }
00548
00549
00560 VALUE
00561 rb_make_metaclass(VALUE obj, VALUE unused)
00562 {
00563 if (BUILTIN_TYPE(obj) == T_CLASS) {
00564 return make_metaclass(obj);
00565 }
00566 else {
00567 return make_singleton_class(obj);
00568 }
00569 }
00570
00571
00582 VALUE
00583 rb_define_class_id(ID id, VALUE super)
00584 {
00585 VALUE klass;
00586
00587 if (!super) super = rb_cObject;
00588 klass = rb_class_new(super);
00589 rb_make_metaclass(klass, RBASIC(super)->klass);
00590
00591 return klass;
00592 }
00593
00594
00603 VALUE
00604 rb_class_inherited(VALUE super, VALUE klass)
00605 {
00606 ID inherited;
00607 if (!super) super = rb_cObject;
00608 CONST_ID(inherited, "inherited");
00609 return rb_funcall(super, inherited, 1, klass);
00610 }
00611
00612
00613
00629 VALUE
00630 rb_define_class(const char *name, VALUE super)
00631 {
00632 VALUE klass;
00633 ID id;
00634
00635 id = rb_intern(name);
00636 if (rb_const_defined(rb_cObject, id)) {
00637 klass = rb_const_get(rb_cObject, id);
00638 if (!RB_TYPE_P(klass, T_CLASS)) {
00639 rb_raise(rb_eTypeError, "%s is not a class", name);
00640 }
00641 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00642 rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
00643 }
00644 return klass;
00645 }
00646 if (!super) {
00647 rb_warn("no super class for `%s', Object assumed", name);
00648 }
00649 klass = rb_define_class_id(id, super);
00650 rb_vm_add_root_module(id, klass);
00651 rb_name_class(klass, id);
00652 rb_const_set(rb_cObject, id, klass);
00653 rb_class_inherited(super, klass);
00654
00655 return klass;
00656 }
00657
00658
00675 VALUE
00676 rb_define_class_under(VALUE outer, const char *name, VALUE super)
00677 {
00678 return rb_define_class_id_under(outer, rb_intern(name), super);
00679 }
00680
00681
00698 VALUE
00699 rb_define_class_id_under(VALUE outer, ID id, VALUE super)
00700 {
00701 VALUE klass;
00702
00703 if (rb_const_defined_at(outer, id)) {
00704 klass = rb_const_get_at(outer, id);
00705 if (!RB_TYPE_P(klass, T_CLASS)) {
00706 rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
00707 }
00708 if (rb_class_real(RCLASS_SUPER(klass)) != super) {
00709 rb_name_error(id, "%s is already defined", rb_id2name(id));
00710 }
00711 return klass;
00712 }
00713 if (!super) {
00714 rb_warn("no super class for `%s::%s', Object assumed",
00715 rb_class2name(outer), rb_id2name(id));
00716 }
00717 klass = rb_define_class_id(id, super);
00718 rb_set_class_path_string(klass, outer, rb_id2str(id));
00719 rb_const_set(outer, id, klass);
00720 rb_class_inherited(super, klass);
00721 rb_gc_register_mark_object(klass);
00722
00723 return klass;
00724 }
00725
00726 VALUE
00727 rb_module_new(void)
00728 {
00729 VALUE mdl = class_alloc(T_MODULE, rb_cModule);
00730 RCLASS_M_TBL_INIT(mdl);
00731 return (VALUE)mdl;
00732 }
00733
00734 VALUE
00735 rb_define_module_id(ID id)
00736 {
00737 VALUE mdl;
00738
00739 mdl = rb_module_new();
00740 rb_name_class(mdl, id);
00741
00742 return mdl;
00743 }
00744
00745 VALUE
00746 rb_define_module(const char *name)
00747 {
00748 VALUE module;
00749 ID id;
00750
00751 id = rb_intern(name);
00752 if (rb_const_defined(rb_cObject, id)) {
00753 module = rb_const_get(rb_cObject, id);
00754 if (RB_TYPE_P(module, T_MODULE))
00755 return module;
00756 rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
00757 }
00758 module = rb_define_module_id(id);
00759 rb_vm_add_root_module(id, module);
00760 rb_const_set(rb_cObject, id, module);
00761
00762 return module;
00763 }
00764
00765 VALUE
00766 rb_define_module_under(VALUE outer, const char *name)
00767 {
00768 return rb_define_module_id_under(outer, rb_intern(name));
00769 }
00770
00771 VALUE
00772 rb_define_module_id_under(VALUE outer, ID id)
00773 {
00774 VALUE module;
00775
00776 if (rb_const_defined_at(outer, id)) {
00777 module = rb_const_get_at(outer, id);
00778 if (RB_TYPE_P(module, T_MODULE))
00779 return module;
00780 rb_raise(rb_eTypeError, "%s::%s is not a module",
00781 rb_class2name(outer), rb_obj_classname(module));
00782 }
00783 module = rb_define_module_id(id);
00784 rb_const_set(outer, id, module);
00785 rb_set_class_path_string(module, outer, rb_id2str(id));
00786 rb_gc_register_mark_object(module);
00787
00788 return module;
00789 }
00790
00791 VALUE
00792 rb_include_class_new(VALUE module, VALUE super)
00793 {
00794 VALUE klass = class_alloc(T_ICLASS, rb_cClass);
00795
00796 if (BUILTIN_TYPE(module) == T_ICLASS) {
00797 module = RBASIC(module)->klass;
00798 }
00799 if (!RCLASS_IV_TBL(module)) {
00800 RCLASS_IV_TBL(module) = st_init_numtable();
00801 }
00802 if (!RCLASS_CONST_TBL(module)) {
00803 RCLASS_CONST_TBL(module) = st_init_numtable();
00804 }
00805 RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
00806 RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
00807
00808 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(klass)) =
00809 RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(RCLASS_ORIGIN(module)));
00810
00811 RCLASS_SET_SUPER(klass, super);
00812 if (RB_TYPE_P(module, T_ICLASS)) {
00813 RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
00814 }
00815 else {
00816 RBASIC_SET_CLASS(klass, module);
00817 }
00818 OBJ_INFECT(klass, module);
00819 OBJ_INFECT(klass, super);
00820
00821 return (VALUE)klass;
00822 }
00823
00824 static int include_modules_at(const VALUE klass, VALUE c, VALUE module);
00825
00826 void
00827 rb_include_module(VALUE klass, VALUE module)
00828 {
00829 int changed = 0;
00830
00831 rb_frozen_class_p(klass);
00832
00833 if (!RB_TYPE_P(module, T_MODULE)) {
00834 Check_Type(module, T_MODULE);
00835 }
00836
00837 OBJ_INFECT(klass, module);
00838
00839 changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module);
00840 if (changed < 0)
00841 rb_raise(rb_eArgError, "cyclic include detected");
00842 }
00843
00844 static int
00845 add_refined_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
00846 {
00847 rb_add_refined_method_entry((VALUE) data, (ID) key);
00848 return ST_CONTINUE;
00849 }
00850
00851 static int
00852 include_modules_at(const VALUE klass, VALUE c, VALUE module)
00853 {
00854 VALUE p, iclass;
00855 int method_changed = 0, constant_changed = 0;
00856 const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
00857
00858 while (module) {
00859 int superclass_seen = FALSE;
00860
00861 if (RCLASS_ORIGIN(module) != module)
00862 goto skip;
00863 if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
00864 return -1;
00865
00866 for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
00867 switch (BUILTIN_TYPE(p)) {
00868 case T_ICLASS:
00869 if (RCLASS_M_TBL_WRAPPER(p) == RCLASS_M_TBL_WRAPPER(module)) {
00870 if (!superclass_seen) {
00871 c = p;
00872 }
00873 goto skip;
00874 }
00875 break;
00876 case T_CLASS:
00877 superclass_seen = TRUE;
00878 break;
00879 }
00880 }
00881 iclass = rb_include_class_new(module, RCLASS_SUPER(c));
00882 c = RCLASS_SET_SUPER(c, iclass);
00883
00884 if (BUILTIN_TYPE(module) == T_ICLASS) {
00885 rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass);
00886 } else {
00887 rb_module_add_to_subclasses_list(module, iclass);
00888 }
00889
00890 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
00891 VALUE refined_class =
00892 rb_refinement_module_get_refined_class(klass);
00893
00894 st_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i,
00895 (st_data_t) refined_class);
00896 FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
00897 }
00898 if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
00899 method_changed = 1;
00900 if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
00901 constant_changed = 1;
00902 skip:
00903 module = RCLASS_SUPER(module);
00904 }
00905
00906 if (method_changed) rb_clear_method_cache_by_class(klass);
00907 if (constant_changed) rb_clear_constant_cache();
00908
00909 return method_changed;
00910 }
00911
00912 static int
00913 move_refined_method(st_data_t key, st_data_t value, st_data_t data)
00914 {
00915 rb_method_entry_t *me = (rb_method_entry_t *) value;
00916 st_table *tbl = (st_table *) data;
00917
00918 if (me->def->type == VM_METHOD_TYPE_REFINED) {
00919 if (me->def->body.orig_me) {
00920 rb_method_entry_t *orig_me = me->def->body.orig_me, *new_me;
00921 me->def->body.orig_me = NULL;
00922 new_me = ALLOC(rb_method_entry_t);
00923 *new_me = *me;
00924 st_add_direct(tbl, key, (st_data_t) new_me);
00925 *me = *orig_me;
00926 xfree(orig_me);
00927 return ST_CONTINUE;
00928 }
00929 else {
00930 st_add_direct(tbl, key, (st_data_t) me);
00931 return ST_DELETE;
00932 }
00933 }
00934 else {
00935 return ST_CONTINUE;
00936 }
00937 }
00938
00939 void
00940 rb_prepend_module(VALUE klass, VALUE module)
00941 {
00942 void rb_vm_check_redefinition_by_prepend(VALUE klass);
00943 VALUE origin;
00944 int changed = 0;
00945
00946 rb_frozen_class_p(klass);
00947
00948 Check_Type(module, T_MODULE);
00949
00950 OBJ_INFECT(klass, module);
00951
00952 origin = RCLASS_ORIGIN(klass);
00953 if (origin == klass) {
00954 origin = class_alloc(T_ICLASS, klass);
00955 OBJ_WB_UNPROTECT(origin);
00956 RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
00957 RCLASS_SET_SUPER(klass, origin);
00958 RCLASS_ORIGIN(klass) = origin;
00959 RCLASS_M_TBL_WRAPPER(origin) = RCLASS_M_TBL_WRAPPER(klass);
00960 RCLASS_M_TBL_INIT(klass);
00961 st_foreach(RCLASS_M_TBL(origin), move_refined_method,
00962 (st_data_t) RCLASS_M_TBL(klass));
00963 }
00964 changed = include_modules_at(klass, klass, module);
00965 if (changed < 0)
00966 rb_raise(rb_eArgError, "cyclic prepend detected");
00967 if (changed) {
00968 rb_vm_check_redefinition_by_prepend(klass);
00969 }
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 VALUE
00990 rb_mod_included_modules(VALUE mod)
00991 {
00992 VALUE ary = rb_ary_new();
00993 VALUE p;
00994 VALUE origin = RCLASS_ORIGIN(mod);
00995
00996 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
00997 if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
00998 VALUE m = RBASIC(p)->klass;
00999 if (RB_TYPE_P(m, T_MODULE))
01000 rb_ary_push(ary, m);
01001 }
01002 }
01003 return ary;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025 VALUE
01026 rb_mod_include_p(VALUE mod, VALUE mod2)
01027 {
01028 VALUE p;
01029
01030 Check_Type(mod2, T_MODULE);
01031 for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
01032 if (BUILTIN_TYPE(p) == T_ICLASS) {
01033 if (RBASIC(p)->klass == mod2) return Qtrue;
01034 }
01035 }
01036 return Qfalse;
01037 }
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 VALUE
01056 rb_mod_ancestors(VALUE mod)
01057 {
01058 VALUE p, ary = rb_ary_new();
01059
01060 for (p = mod; p; p = RCLASS_SUPER(p)) {
01061 if (BUILTIN_TYPE(p) == T_ICLASS) {
01062 rb_ary_push(ary, RBASIC(p)->klass);
01063 }
01064 else if (p == RCLASS_ORIGIN(p)) {
01065 rb_ary_push(ary, p);
01066 }
01067 }
01068 return ary;
01069 }
01070
01071 #define VISI(x) ((x)&NOEX_MASK)
01072 #define VISI_CHECK(x,f) (VISI(x) == (f))
01073
01074 static int
01075 ins_methods_push(ID name, long type, VALUE ary, long visi)
01076 {
01077 if (type == -1) return ST_CONTINUE;
01078
01079 switch (visi) {
01080 case NOEX_PRIVATE:
01081 case NOEX_PROTECTED:
01082 case NOEX_PUBLIC:
01083 visi = (type == visi);
01084 break;
01085 default:
01086 visi = (type != NOEX_PRIVATE);
01087 break;
01088 }
01089 if (visi) {
01090 rb_ary_push(ary, ID2SYM(name));
01091 }
01092 return ST_CONTINUE;
01093 }
01094
01095 static int
01096 ins_methods_i(st_data_t name, st_data_t type, st_data_t ary)
01097 {
01098 return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1);
01099 }
01100
01101 static int
01102 ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary)
01103 {
01104 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED);
01105 }
01106
01107 static int
01108 ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary)
01109 {
01110 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE);
01111 }
01112
01113 static int
01114 ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
01115 {
01116 return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
01117 }
01118
01119 static int
01120 method_entry_i(st_data_t key, st_data_t value, st_data_t data)
01121 {
01122 const rb_method_entry_t *me = (const rb_method_entry_t *)value;
01123 st_table *list = (st_table *)data;
01124 long type;
01125
01126 if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
01127 me = rb_resolve_refined_method(Qnil, me, NULL);
01128 if (!me) return ST_CONTINUE;
01129 }
01130 if (!st_lookup(list, key, 0)) {
01131 if (UNDEFINED_METHOD_ENTRY_P(me)) {
01132 type = -1;
01133 }
01134 else {
01135 type = VISI(me->flag);
01136 }
01137 st_add_direct(list, key, type);
01138 }
01139 return ST_CONTINUE;
01140 }
01141
01142 static VALUE
01143 class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
01144 {
01145 VALUE ary;
01146 int recur, prepended = 0;
01147 st_table *list;
01148
01149 if (argc == 0) {
01150 recur = TRUE;
01151 }
01152 else {
01153 VALUE r;
01154 rb_scan_args(argc, argv, "01", &r);
01155 recur = RTEST(r);
01156 }
01157
01158 if (!recur && RCLASS_ORIGIN(mod) != mod) {
01159 mod = RCLASS_ORIGIN(mod);
01160 prepended = 1;
01161 }
01162
01163 list = st_init_numtable();
01164 for (; mod; mod = RCLASS_SUPER(mod)) {
01165 if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
01166 if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
01167 if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
01168 if (!recur) break;
01169 }
01170 ary = rb_ary_new();
01171 st_foreach(list, func, ary);
01172 st_free_table(list);
01173
01174 return ary;
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 VALUE
01205 rb_class_instance_methods(int argc, VALUE *argv, VALUE mod)
01206 {
01207 return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);
01208 }
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 VALUE
01220 rb_class_protected_instance_methods(int argc, VALUE *argv, VALUE mod)
01221 {
01222 return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 VALUE
01243 rb_class_private_instance_methods(int argc, VALUE *argv, VALUE mod)
01244 {
01245 return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257 VALUE
01258 rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
01259 {
01260 return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 VALUE
01294 rb_obj_methods(int argc, VALUE *argv, VALUE obj)
01295 {
01296 retry:
01297 if (argc == 0) {
01298 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_i);
01299 }
01300 else {
01301 VALUE recur;
01302
01303 rb_scan_args(argc, argv, "1", &recur);
01304 if (RTEST(recur)) {
01305 argc = 0;
01306 goto retry;
01307 }
01308 return rb_obj_singleton_methods(argc, argv, obj);
01309 }
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 VALUE
01322 rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj)
01323 {
01324 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_prot_i);
01325 }
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336 VALUE
01337 rb_obj_private_methods(int argc, VALUE *argv, VALUE obj)
01338 {
01339 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_priv_i);
01340 }
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351 VALUE
01352 rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
01353 {
01354 return class_instance_method_list(argc, argv, CLASS_OF(obj), 1, ins_methods_pub_i);
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
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 VALUE
01391 rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
01392 {
01393 VALUE recur, ary, klass, origin;
01394 st_table *list, *mtbl;
01395
01396 if (argc == 0) {
01397 recur = Qtrue;
01398 }
01399 else {
01400 rb_scan_args(argc, argv, "01", &recur);
01401 }
01402 klass = CLASS_OF(obj);
01403 origin = RCLASS_ORIGIN(klass);
01404 list = st_init_numtable();
01405 if (klass && FL_TEST(klass, FL_SINGLETON)) {
01406 if ((mtbl = RCLASS_M_TBL(origin)) != 0)
01407 st_foreach(mtbl, method_entry_i, (st_data_t)list);
01408 klass = RCLASS_SUPER(klass);
01409 }
01410 if (RTEST(recur)) {
01411 while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
01412 if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
01413 st_foreach(mtbl, method_entry_i, (st_data_t)list);
01414 klass = RCLASS_SUPER(klass);
01415 }
01416 }
01417 ary = rb_ary_new();
01418 st_foreach(list, ins_methods_i, ary);
01419 st_free_table(list);
01420
01421 return ary;
01422 }
01423
01481 void
01482 rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc)
01483 {
01484 rb_add_method_cfunc(klass, mid, func, argc, NOEX_PUBLIC);
01485 }
01486
01487 void
01488 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01489 {
01490 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
01491 }
01492
01493 void
01494 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01495 {
01496 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
01497 }
01498
01499 void
01500 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
01501 {
01502 rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PRIVATE);
01503 }
01504
01505 void
01506 rb_undef_method(VALUE klass, const char *name)
01507 {
01508 rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF);
01509 }
01510
01519 #define SPECIAL_SINGLETON(x,c) do {\
01520 if (obj == (x)) {\
01521 return (c);\
01522 }\
01523 } while (0)
01524
01525 static inline VALUE
01526 special_singleton_class_of(VALUE obj)
01527 {
01528 SPECIAL_SINGLETON(Qnil, rb_cNilClass);
01529 SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
01530 SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
01531 return Qnil;
01532 }
01533
01534 VALUE
01535 rb_special_singleton_class(VALUE obj)
01536 {
01537 return special_singleton_class_of(obj);
01538 }
01539
01549 static VALUE
01550 singleton_class_of(VALUE obj)
01551 {
01552 VALUE klass;
01553
01554 if (FIXNUM_P(obj) || FLONUM_P(obj) || SYMBOL_P(obj)) {
01555 rb_raise(rb_eTypeError, "can't define singleton");
01556 }
01557 if (SPECIAL_CONST_P(obj)) {
01558 klass = special_singleton_class_of(obj);
01559 if (NIL_P(klass))
01560 rb_bug("unknown immediate %p", (void *)obj);
01561 return klass;
01562 }
01563 else {
01564 enum ruby_value_type type = BUILTIN_TYPE(obj);
01565 if (type == T_FLOAT || type == T_BIGNUM) {
01566 rb_raise(rb_eTypeError, "can't define singleton");
01567 }
01568 }
01569
01570 if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
01571 rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) {
01572 klass = RBASIC(obj)->klass;
01573 }
01574 else {
01575 klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
01576 }
01577
01578 if (OBJ_TAINTED(obj)) {
01579 OBJ_TAINT(klass);
01580 }
01581 else {
01582 FL_UNSET(klass, FL_TAINT);
01583 }
01584 if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
01585
01586 return klass;
01587 }
01588
01596 VALUE
01597 rb_singleton_class_get(VALUE obj)
01598 {
01599 VALUE klass;
01600
01601 if (SPECIAL_CONST_P(obj)) {
01602 return rb_special_singleton_class(obj);
01603 }
01604 klass = RBASIC(obj)->klass;
01605 if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
01606 if (rb_ivar_get(klass, id_attached) != obj) return Qnil;
01607 return klass;
01608 }
01609
01627 VALUE
01628 rb_singleton_class(VALUE obj)
01629 {
01630 VALUE klass = singleton_class_of(obj);
01631
01632
01633 if (RB_TYPE_P(obj, T_CLASS)) (void)ENSURE_EIGENCLASS(klass);
01634
01635 return klass;
01636 }
01637
01654 void
01655 rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
01656 {
01657 rb_define_method(singleton_class_of(obj), name, func, argc);
01658 }
01659
01660
01661
01669 void
01670 rb_define_module_function(VALUE module, const char *name, VALUE (*func)(ANYARGS), int argc)
01671 {
01672 rb_define_private_method(module, name, func, argc);
01673 rb_define_singleton_method(module, name, func, argc);
01674 }
01675
01676
01683 void
01684 rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc)
01685 {
01686 rb_define_module_function(rb_mKernel, name, func, argc);
01687 }
01688
01689
01696 void
01697 rb_define_alias(VALUE klass, const char *name1, const char *name2)
01698 {
01699 rb_alias(klass, rb_intern(name1), rb_intern(name2));
01700 }
01701
01709 void
01710 rb_define_attr(VALUE klass, const char *name, int read, int write)
01711 {
01712 rb_attr(klass, rb_intern(name), read, write, FALSE);
01713 }
01714
01715 int
01716 rb_obj_basic_to_s_p(VALUE obj)
01717 {
01718 const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), rb_intern("to_s"), 0);
01719 if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
01720 me->def->body.cfunc.func == rb_any_to_s)
01721 return 1;
01722 return 0;
01723 }
01724
01725 #include <stdarg.h>
01726
01727 int
01728 rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
01729 {
01730 int i;
01731 const char *p = fmt;
01732 VALUE *var;
01733 va_list vargs;
01734 int f_var = 0, f_hash = 0, f_block = 0;
01735 int n_lead = 0, n_opt = 0, n_trail = 0, n_mand;
01736 int argi = 0;
01737 VALUE hash = Qnil;
01738
01739 if (ISDIGIT(*p)) {
01740 n_lead = *p - '0';
01741 p++;
01742 if (ISDIGIT(*p)) {
01743 n_opt = *p - '0';
01744 p++;
01745 if (ISDIGIT(*p)) {
01746 n_trail = *p - '0';
01747 p++;
01748 goto block_arg;
01749 }
01750 }
01751 }
01752 if (*p == '*') {
01753 f_var = 1;
01754 p++;
01755 if (ISDIGIT(*p)) {
01756 n_trail = *p - '0';
01757 p++;
01758 }
01759 }
01760 block_arg:
01761 if (*p == ':') {
01762 f_hash = 1;
01763 p++;
01764 }
01765 if (*p == '&') {
01766 f_block = 1;
01767 p++;
01768 }
01769 if (*p != '\0') {
01770 rb_fatal("bad scan arg format: %s", fmt);
01771 }
01772 n_mand = n_lead + n_trail;
01773
01774 if (argc < n_mand)
01775 goto argc_error;
01776
01777 va_start(vargs, fmt);
01778
01779
01780 if (f_hash && n_mand < argc) {
01781 VALUE last = argv[argc - 1];
01782
01783 if (NIL_P(last)) {
01784
01785
01786
01787 if (!f_var && n_mand + n_opt < argc)
01788 argc--;
01789 }
01790 else {
01791 hash = rb_check_hash_type(last);
01792 if (!NIL_P(hash)) {
01793 VALUE opts = rb_extract_keywords(&hash);
01794 if (!hash) argc--;
01795 hash = opts ? opts : Qnil;
01796 }
01797 }
01798 }
01799
01800 for (i = n_lead; i-- > 0; ) {
01801 var = va_arg(vargs, VALUE *);
01802 if (var) *var = argv[argi];
01803 argi++;
01804 }
01805
01806 for (i = n_opt; i-- > 0; ) {
01807 var = va_arg(vargs, VALUE *);
01808 if (argi < argc - n_trail) {
01809 if (var) *var = argv[argi];
01810 argi++;
01811 }
01812 else {
01813 if (var) *var = Qnil;
01814 }
01815 }
01816
01817 if (f_var) {
01818 int n_var = argc - argi - n_trail;
01819
01820 var = va_arg(vargs, VALUE *);
01821 if (0 < n_var) {
01822 if (var) *var = rb_ary_new4(n_var, &argv[argi]);
01823 argi += n_var;
01824 }
01825 else {
01826 if (var) *var = rb_ary_new();
01827 }
01828 }
01829
01830 for (i = n_trail; i-- > 0; ) {
01831 var = va_arg(vargs, VALUE *);
01832 if (var) *var = argv[argi];
01833 argi++;
01834 }
01835
01836 if (f_hash) {
01837 var = va_arg(vargs, VALUE *);
01838 if (var) *var = hash;
01839 }
01840
01841 if (f_block) {
01842 var = va_arg(vargs, VALUE *);
01843 if (rb_block_given_p()) {
01844 *var = rb_block_proc();
01845 }
01846 else {
01847 *var = Qnil;
01848 }
01849 }
01850 va_end(vargs);
01851
01852 if (argi < argc) {
01853 argc_error:
01854 rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
01855 }
01856
01857 return argc;
01858 }
01859
01860 NORETURN(static void keyword_error(const char *error, VALUE keys));
01861 static void
01862 keyword_error(const char *error, VALUE keys)
01863 {
01864 const char *msg = "";
01865 if (RARRAY_LEN(keys) == 1) {
01866 keys = RARRAY_AREF(keys, 0);
01867 }
01868 else {
01869 keys = rb_ary_join(keys, rb_usascii_str_new2(", "));
01870 msg = "s";
01871 }
01872 rb_raise(rb_eArgError, "%s keyword%s: %"PRIsVALUE, error, msg, keys);
01873 }
01874
01875 NORETURN(static void unknown_keyword_error(VALUE hash, const ID *table, int keywords));
01876 static void
01877 unknown_keyword_error(VALUE hash, const ID *table, int keywords)
01878 {
01879 st_table *tbl = rb_hash_tbl_raw(hash);
01880 VALUE keys;
01881 int i;
01882 for (i = 0; i < keywords; i++) {
01883 st_data_t key = ID2SYM(table[i]);
01884 st_delete(tbl, &key, NULL);
01885 }
01886 keys = rb_funcall(hash, rb_intern("keys"), 0, 0);
01887 if (!RB_TYPE_P(keys, T_ARRAY)) rb_raise(rb_eArgError, "unknown keyword");
01888 keyword_error("unknown", keys);
01889 }
01890
01891 static int
01892 separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
01893 {
01894 VALUE *kwdhash = (VALUE *)arg;
01895
01896 if (!SYMBOL_P(key)) kwdhash++;
01897 if (!*kwdhash) *kwdhash = rb_hash_new();
01898 rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
01899 return ST_CONTINUE;
01900 }
01901
01902 VALUE
01903 rb_extract_keywords(VALUE *orighash)
01904 {
01905 VALUE parthash[2] = {0, 0};
01906 VALUE hash = *orighash;
01907
01908 if (RHASH_EMPTY_P(hash)) {
01909 *orighash = 0;
01910 return hash;
01911 }
01912 st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&parthash);
01913 *orighash = parthash[1];
01914 return parthash[0];
01915 }
01916
01917 int
01918 rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
01919 {
01920 int i = 0, j;
01921 int rest = 0;
01922 VALUE missing = Qnil;
01923 st_data_t key;
01924
01925 #define extract_kwarg(keyword, val) \
01926 (key = (st_data_t)(keyword), values ? \
01927 st_delete(rb_hash_tbl_raw(keyword_hash), &key, (val)) : \
01928 st_lookup(rb_hash_tbl_raw(keyword_hash), key, (val)))
01929
01930 if (optional < 0) {
01931 rest = 1;
01932 optional = -1-optional;
01933 }
01934 if (values) {
01935 for (j = 0; j < required + optional; j++) {
01936 values[j] = Qundef;
01937 }
01938 }
01939 if (required) {
01940 for (; i < required; i++) {
01941 VALUE keyword = ID2SYM(table[i]);
01942 if (keyword_hash) {
01943 st_data_t val;
01944 if (extract_kwarg(keyword, &val)) {
01945 if (values) values[i] = (VALUE)val;
01946 continue;
01947 }
01948 }
01949 if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
01950 rb_ary_push(missing, keyword);
01951 }
01952 if (!NIL_P(missing)) {
01953 keyword_error("missing", missing);
01954 }
01955 }
01956 j = i;
01957 if (optional && keyword_hash) {
01958 for (i = 0; i < optional; i++) {
01959 st_data_t val;
01960 if (extract_kwarg(ID2SYM(table[required+i]), &val)) {
01961 if (values) values[required+i] = (VALUE)val;
01962 j++;
01963 }
01964 }
01965 }
01966 if (!rest && keyword_hash) {
01967 if (RHASH_SIZE(keyword_hash) > (unsigned int)j) {
01968 unknown_keyword_error(keyword_hash, table, required+optional);
01969 }
01970 }
01971 return j;
01972 #undef extract_kwarg
01973 }
01974