1/* 2 * This file is included by vm.c 3 */ 4 5#define CACHE_SIZE 0x800 6#define CACHE_MASK 0x7ff 7#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) 8 9#define NOEX_NOREDEF 0 10#ifndef NOEX_NOREDEF 11#define NOEX_NOREDEF NOEX_RESPONDS 12#endif 13 14static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass); 15 16static ID object_id; 17static ID removed, singleton_removed, undefined, singleton_undefined; 18static ID added, singleton_added, attached; 19 20struct cache_entry { /* method hash table. */ 21 VALUE filled_version; /* filled state version */ 22 ID mid; /* method's id */ 23 VALUE klass; /* receiver's class */ 24 rb_method_entry_t *me; 25 VALUE defined_class; 26}; 27 28static struct cache_entry cache[CACHE_SIZE]; 29#define ruby_running (GET_VM()->running) 30/* int ruby_running = 0; */ 31 32static void 33vm_clear_global_method_cache(void) 34{ 35 struct cache_entry *ent, *end; 36 37 ent = cache; 38 end = ent + CACHE_SIZE; 39 while (ent < end) { 40 ent->filled_version = 0; 41 ent++; 42 } 43} 44 45void 46rb_clear_cache(void) 47{ 48 rb_vm_change_state(); 49} 50 51static void 52rb_clear_cache_for_undef(VALUE klass, ID id) 53{ 54 rb_vm_change_state(); 55} 56 57static void 58rb_clear_cache_by_id(ID id) 59{ 60 rb_vm_change_state(); 61} 62 63void 64rb_clear_cache_by_class(VALUE klass) 65{ 66 rb_vm_change_state(); 67} 68 69VALUE 70rb_f_notimplement(int argc, VALUE *argv, VALUE obj) 71{ 72 rb_notimplement(); 73 74 UNREACHABLE; 75} 76 77static void 78rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex) 79{ 80 rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex); 81} 82 83void 84rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex) 85{ 86 if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc); 87 if (func != rb_f_notimplement) { 88 rb_method_cfunc_t opt; 89 opt.func = func; 90 opt.argc = argc; 91 rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex); 92 } 93 else { 94 rb_define_notimplement_method_id(klass, mid, noex); 95 } 96} 97 98void 99rb_unlink_method_entry(rb_method_entry_t *me) 100{ 101 struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry); 102 ume->me = me; 103 ume->next = GET_VM()->unlinked_method_entry_list; 104 GET_VM()->unlinked_method_entry_list = ume; 105} 106 107void 108rb_gc_mark_unlinked_live_method_entries(void *pvm) 109{ 110 rb_vm_t *vm = pvm; 111 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list; 112 113 while (ume) { 114 if (ume->me->mark) { 115 rb_mark_method_entry(ume->me); 116 } 117 ume = ume->next; 118 } 119} 120 121void 122rb_sweep_method_entry(void *pvm) 123{ 124 rb_vm_t *vm = pvm; 125 struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume; 126 127 while (ume) { 128 if (ume->me->mark) { 129 ume->me->mark = 0; 130 prev_ume = ume; 131 ume = ume->next; 132 } 133 else { 134 rb_free_method_entry(ume->me); 135 136 if (prev_ume == 0) { 137 vm->unlinked_method_entry_list = ume->next; 138 } 139 else { 140 prev_ume->next = ume->next; 141 } 142 143 curr_ume = ume; 144 ume = ume->next; 145 xfree(curr_ume); 146 } 147 } 148} 149 150static void 151release_method_definition(rb_method_definition_t *def) 152{ 153 if (def == 0) 154 return; 155 if (def->alias_count == 0) { 156 if (def->type == VM_METHOD_TYPE_REFINED && 157 def->body.orig_me) { 158 release_method_definition(def->body.orig_me->def); 159 xfree(def->body.orig_me); 160 } 161 xfree(def); 162 } 163 else if (def->alias_count > 0) { 164 def->alias_count--; 165 } 166} 167 168void 169rb_free_method_entry(rb_method_entry_t *me) 170{ 171 release_method_definition(me->def); 172 xfree(me); 173} 174 175static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); 176 177static inline rb_method_entry_t * 178lookup_method_table(VALUE klass, ID id) 179{ 180 st_data_t body; 181 st_table *m_tbl = RCLASS_M_TBL(klass); 182 if (st_lookup(m_tbl, id, &body)) { 183 return (rb_method_entry_t *) body; 184 } 185 else { 186 return 0; 187 } 188} 189 190static void 191make_method_entry_refined(rb_method_entry_t *me) 192{ 193 rb_method_definition_t *new_def; 194 195 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) 196 return; 197 198 new_def = ALLOC(rb_method_definition_t); 199 new_def->type = VM_METHOD_TYPE_REFINED; 200 new_def->original_id = me->called_id; 201 new_def->alias_count = 0; 202 new_def->body.orig_me = ALLOC(rb_method_entry_t); 203 *new_def->body.orig_me = *me; 204 rb_vm_check_redefinition_opt_method(me, me->klass); 205 if (me->def) me->def->alias_count++; 206 me->flag = NOEX_WITH_SAFE(NOEX_PUBLIC); 207 me->def = new_def; 208} 209 210void 211rb_add_refined_method_entry(VALUE refined_class, ID mid) 212{ 213 rb_method_entry_t *me = lookup_method_table(refined_class, mid); 214 215 if (me) { 216 make_method_entry_refined(me); 217 } 218 else { 219 rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, 220 NOEX_PUBLIC); 221 } 222} 223 224static rb_method_entry_t * 225rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, 226 rb_method_definition_t *def, rb_method_flag_t noex, 227 VALUE defined_class) 228{ 229 rb_method_entry_t *me; 230#if NOEX_NOREDEF 231 VALUE rklass; 232#endif 233 st_table *mtbl; 234 st_data_t data; 235 int make_refined = 0; 236 237 if (NIL_P(klass)) { 238 klass = rb_cObject; 239 } 240 if (rb_safe_level() >= 4 && 241 (klass == rb_cObject || !OBJ_UNTRUSTED(klass))) { 242 rb_raise(rb_eSecurityError, "Insecure: can't define method"); 243 } 244 if (!FL_TEST(klass, FL_SINGLETON) && 245 type != VM_METHOD_TYPE_NOTIMPLEMENTED && 246 type != VM_METHOD_TYPE_ZSUPER && 247 (mid == idInitialize || mid == idInitialize_copy || 248 mid == idInitialize_clone || mid == idInitialize_dup || 249 mid == idRespond_to_missing)) { 250 noex = NOEX_PRIVATE | noex; 251 } 252 253 rb_check_frozen(klass); 254#if NOEX_NOREDEF 255 rklass = klass; 256#endif 257 if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { 258 VALUE refined_class = 259 rb_refinement_module_get_refined_class(klass); 260 261 rb_add_refined_method_entry(refined_class, mid); 262 } 263 if (type == VM_METHOD_TYPE_REFINED) { 264 rb_method_entry_t *old_me = 265 lookup_method_table(RCLASS_ORIGIN(klass), mid); 266 if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass); 267 } 268 else { 269 klass = RCLASS_ORIGIN(klass); 270 } 271 mtbl = RCLASS_M_TBL(klass); 272 273 /* check re-definition */ 274 if (st_lookup(mtbl, mid, &data)) { 275 rb_method_entry_t *old_me = (rb_method_entry_t *)data; 276 rb_method_definition_t *old_def = old_me->def; 277 278 if (rb_method_definition_eq(old_def, def)) return old_me; 279#if NOEX_NOREDEF 280 if (old_me->flag & NOEX_NOREDEF) { 281 rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE, 282 rb_class_name(rklass), rb_id2str(mid)); 283 } 284#endif 285 rb_vm_check_redefinition_opt_method(old_me, klass); 286 if (old_def->type == VM_METHOD_TYPE_REFINED) 287 make_refined = 1; 288 289 if (RTEST(ruby_verbose) && 290 type != VM_METHOD_TYPE_UNDEF && 291 old_def->alias_count == 0 && 292 old_def->type != VM_METHOD_TYPE_UNDEF && 293 old_def->type != VM_METHOD_TYPE_ZSUPER) { 294 rb_iseq_t *iseq = 0; 295 296 rb_warning("method redefined; discarding old %s", rb_id2name(mid)); 297 switch (old_def->type) { 298 case VM_METHOD_TYPE_ISEQ: 299 iseq = old_def->body.iseq; 300 break; 301 case VM_METHOD_TYPE_BMETHOD: 302 iseq = rb_proc_get_iseq(old_def->body.proc, 0); 303 break; 304 default: 305 break; 306 } 307 if (iseq && !NIL_P(iseq->location.path)) { 308 int line = iseq->line_info_table ? rb_iseq_first_lineno(iseq) : 0; 309 rb_compile_warning(RSTRING_PTR(iseq->location.path), line, 310 "previous definition of %s was here", 311 rb_id2name(old_def->original_id)); 312 } 313 } 314 315 rb_unlink_method_entry(old_me); 316 } 317 318 me = ALLOC(rb_method_entry_t); 319 320 rb_clear_cache_by_id(mid); 321 322 me->flag = NOEX_WITH_SAFE(noex); 323 me->mark = 0; 324 me->called_id = mid; 325 me->klass = defined_class; 326 me->def = def; 327 if (def) def->alias_count++; 328 329 /* check mid */ 330 if (klass == rb_cObject && mid == idInitialize) { 331 rb_warn("redefining Object#initialize may cause infinite loop"); 332 } 333 /* check mid */ 334 if (mid == object_id || mid == id__send__) { 335 if (type == VM_METHOD_TYPE_ISEQ) { 336 rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid)); 337 } 338 } 339 340 if (make_refined) { 341 make_method_entry_refined(me); 342 } 343 344 st_insert(mtbl, mid, (st_data_t) me); 345 346 return me; 347} 348 349#define CALL_METHOD_HOOK(klass, hook, mid) do { \ 350 const VALUE arg = ID2SYM(mid); \ 351 VALUE recv_class = (klass); \ 352 ID hook_id = (hook); \ 353 if (FL_TEST((klass), FL_SINGLETON)) { \ 354 recv_class = rb_ivar_get((klass), attached); \ 355 hook_id = singleton_##hook; \ 356 } \ 357 rb_funcall2(recv_class, hook_id, 1, &arg); \ 358 } while (0) 359 360static void 361method_added(VALUE klass, ID mid) 362{ 363 if (ruby_running) { 364 CALL_METHOD_HOOK(klass, added, mid); 365 } 366} 367 368static VALUE 369(*call_cfunc_invoker_func(int argc))(VALUE (*func)(ANYARGS), VALUE recv, int argc, const VALUE *) 370{ 371 switch (argc) { 372 case -2: return &call_cfunc_m2; 373 case -1: return &call_cfunc_m1; 374 case 0: return &call_cfunc_0; 375 case 1: return &call_cfunc_1; 376 case 2: return &call_cfunc_2; 377 case 3: return &call_cfunc_3; 378 case 4: return &call_cfunc_4; 379 case 5: return &call_cfunc_5; 380 case 6: return &call_cfunc_6; 381 case 7: return &call_cfunc_7; 382 case 8: return &call_cfunc_8; 383 case 9: return &call_cfunc_9; 384 case 10: return &call_cfunc_10; 385 case 11: return &call_cfunc_11; 386 case 12: return &call_cfunc_12; 387 case 13: return &call_cfunc_13; 388 case 14: return &call_cfunc_14; 389 case 15: return &call_cfunc_15; 390 default: 391 rb_bug("call_cfunc_func: unsupported length: %d", argc); 392 } 393} 394 395static void 396setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc) 397{ 398 cfunc->func = func; 399 cfunc->argc = argc; 400 cfunc->invoker = call_cfunc_invoker_func(argc); 401} 402 403rb_method_entry_t * 404rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) 405{ 406 rb_thread_t *th; 407 rb_control_frame_t *cfp; 408 int line; 409 rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass); 410 rb_method_definition_t *def = ALLOC(rb_method_definition_t); 411 if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) { 412 me->def->body.orig_me->def = def; 413 } 414 else { 415 me->def = def; 416 } 417 def->type = type; 418 def->original_id = mid; 419 def->alias_count = 0; 420 switch (type) { 421 case VM_METHOD_TYPE_ISEQ: 422 def->body.iseq = (rb_iseq_t *)opts; 423 break; 424 case VM_METHOD_TYPE_CFUNC: 425 { 426 rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts; 427 setup_method_cfunc_struct(&def->body.cfunc, cfunc->func, cfunc->argc); 428 } 429 break; 430 case VM_METHOD_TYPE_ATTRSET: 431 case VM_METHOD_TYPE_IVAR: 432 def->body.attr.id = (ID)opts; 433 def->body.attr.location = Qfalse; 434 th = GET_THREAD(); 435 cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); 436 if (cfp && (line = rb_vm_get_sourceline(cfp))) { 437 VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line)); 438 def->body.attr.location = rb_ary_freeze(location); 439 } 440 break; 441 case VM_METHOD_TYPE_BMETHOD: 442 def->body.proc = (VALUE)opts; 443 break; 444 case VM_METHOD_TYPE_NOTIMPLEMENTED: 445 setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1); 446 break; 447 case VM_METHOD_TYPE_OPTIMIZED: 448 def->body.optimize_type = (enum method_optimized_type)opts; 449 break; 450 case VM_METHOD_TYPE_ZSUPER: 451 case VM_METHOD_TYPE_UNDEF: 452 break; 453 case VM_METHOD_TYPE_REFINED: 454 def->body.orig_me = (rb_method_entry_t *) opts; 455 break; 456 default: 457 rb_bug("rb_add_method: unsupported method type (%d)\n", type); 458 } 459 if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) { 460 method_added(klass, mid); 461 } 462 return me; 463} 464 465static rb_method_entry_t * 466method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, 467 rb_method_flag_t noex, VALUE defined_class) 468{ 469 rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF; 470 rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex, 471 defined_class); 472 method_added(klass, mid); 473 return newme; 474} 475 476rb_method_entry_t * 477rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me, rb_method_flag_t noex) 478{ 479 return method_entry_set(klass, mid, me, noex, klass); 480} 481 482#define UNDEF_ALLOC_FUNC ((rb_alloc_func_t)-1) 483 484void 485rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) 486{ 487 Check_Type(klass, T_CLASS); 488 RCLASS_EXT(klass)->allocator = func; 489} 490 491void 492rb_undef_alloc_func(VALUE klass) 493{ 494 rb_define_alloc_func(klass, UNDEF_ALLOC_FUNC); 495} 496 497rb_alloc_func_t 498rb_get_alloc_func(VALUE klass) 499{ 500 Check_Type(klass, T_CLASS); 501 502 for (; klass; klass = RCLASS_SUPER(klass)) { 503 rb_alloc_func_t allocator = RCLASS_EXT(klass)->allocator; 504 if (allocator == UNDEF_ALLOC_FUNC) break; 505 if (allocator) return allocator; 506 } 507 return 0; 508} 509 510static inline rb_method_entry_t* 511search_method(VALUE klass, ID id, VALUE *defined_class_ptr) 512{ 513 rb_method_entry_t *me; 514 515 for (me = 0; klass; klass = RCLASS_SUPER(klass)) { 516 if ((me = lookup_method_table(klass, id)) != 0) break; 517 } 518 519 if (defined_class_ptr) 520 *defined_class_ptr = klass; 521 return me; 522} 523 524/* 525 * search method entry without the method cache. 526 * 527 * if you need method entry with method cache (normal case), use 528 * rb_method_entry() simply. 529 */ 530rb_method_entry_t * 531rb_method_entry_get_without_cache(VALUE klass, ID id, 532 VALUE *defined_class_ptr) 533{ 534 VALUE defined_class; 535 rb_method_entry_t *me = search_method(klass, id, &defined_class); 536 537 if (me && me->klass) { 538 switch (BUILTIN_TYPE(me->klass)) { 539 case T_CLASS: 540 if (RBASIC(klass)->flags & FL_SINGLETON) break; 541 /* fall through */ 542 case T_ICLASS: 543 defined_class = me->klass; 544 } 545 } 546 547 if (ruby_running) { 548 struct cache_entry *ent; 549 ent = cache + EXPR1(klass, id); 550 ent->filled_version = GET_VM_STATE_VERSION(); 551 ent->klass = klass; 552 ent->defined_class = defined_class; 553 554 if (UNDEFINED_METHOD_ENTRY_P(me)) { 555 ent->mid = id; 556 ent->me = 0; 557 me = 0; 558 } 559 else { 560 ent->mid = id; 561 ent->me = me; 562 } 563 } 564 565 if (defined_class_ptr) 566 *defined_class_ptr = defined_class; 567 return me; 568} 569 570rb_method_entry_t * 571rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr) 572{ 573#if OPT_GLOBAL_METHOD_CACHE 574 struct cache_entry *ent; 575 576 ent = cache + EXPR1(klass, id); 577 if (ent->filled_version == GET_VM_STATE_VERSION() && 578 ent->mid == id && ent->klass == klass) { 579 if (defined_class_ptr) 580 *defined_class_ptr = ent->defined_class; 581 return ent->me; 582 } 583#endif 584 585 return rb_method_entry_get_without_cache(klass, id, defined_class_ptr); 586} 587 588static rb_method_entry_t * 589get_original_method_entry(VALUE refinements, 590 const rb_method_entry_t *me, 591 VALUE *defined_class_ptr) 592{ 593 if (me->def->body.orig_me) { 594 return me->def->body.orig_me; 595 } 596 else { 597 rb_method_entry_t *tmp_me; 598 tmp_me = rb_method_entry(RCLASS_SUPER(me->klass), me->called_id, 599 defined_class_ptr); 600 return rb_resolve_refined_method(refinements, tmp_me, 601 defined_class_ptr); 602 } 603} 604 605rb_method_entry_t * 606rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, 607 VALUE *defined_class_ptr) 608{ 609 if (me && me->def->type == VM_METHOD_TYPE_REFINED) { 610 VALUE refinement; 611 rb_method_entry_t *tmp_me; 612 613 refinement = find_refinement(refinements, me->klass); 614 if (NIL_P(refinement)) { 615 return get_original_method_entry(refinements, me, 616 defined_class_ptr); 617 } 618 tmp_me = rb_method_entry(refinement, me->called_id, 619 defined_class_ptr); 620 if (tmp_me && tmp_me->def->type != VM_METHOD_TYPE_REFINED) { 621 return tmp_me; 622 } 623 else { 624 return get_original_method_entry(refinements, me, 625 defined_class_ptr); 626 } 627 } 628 else { 629 return (rb_method_entry_t *)me; 630 } 631} 632 633rb_method_entry_t * 634rb_method_entry_with_refinements(VALUE klass, ID id, 635 VALUE *defined_class_ptr) 636{ 637 VALUE defined_class; 638 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class); 639 640 if (me && me->def->type == VM_METHOD_TYPE_REFINED) { 641 NODE *cref = rb_vm_cref(); 642 VALUE refinements = cref ? cref->nd_refinements : Qnil; 643 644 me = rb_resolve_refined_method(refinements, me, &defined_class); 645 } 646 if (defined_class_ptr) 647 *defined_class_ptr = defined_class; 648 return me; 649} 650 651rb_method_entry_t * 652rb_method_entry_without_refinements(VALUE klass, ID id, 653 VALUE *defined_class_ptr) 654{ 655 VALUE defined_class; 656 rb_method_entry_t *me = rb_method_entry(klass, id, &defined_class); 657 658 if (me && me->def->type == VM_METHOD_TYPE_REFINED) { 659 me = rb_resolve_refined_method(Qnil, me, &defined_class); 660 } 661 if (defined_class_ptr) 662 *defined_class_ptr = defined_class; 663 if (UNDEFINED_METHOD_ENTRY_P(me)) { 664 return 0; 665 } 666 else { 667 return me; 668 } 669} 670 671static void 672remove_method(VALUE klass, ID mid) 673{ 674 st_data_t key, data; 675 rb_method_entry_t *me = 0; 676 VALUE self = klass; 677 678 klass = RCLASS_ORIGIN(klass); 679 if (klass == rb_cObject) { 680 rb_secure(4); 681 } 682 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 683 rb_raise(rb_eSecurityError, "Insecure: can't remove method"); 684 } 685 rb_check_frozen(klass); 686 if (mid == object_id || mid == id__send__ || mid == idInitialize) { 687 rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); 688 } 689 690 if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || 691 !(me = (rb_method_entry_t *)data) || 692 (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { 693 rb_name_error(mid, "method `%s' not defined in %s", 694 rb_id2name(mid), rb_class2name(klass)); 695 } 696 key = (st_data_t)mid; 697 st_delete(RCLASS_M_TBL(klass), &key, &data); 698 699 rb_vm_check_redefinition_opt_method(me, klass); 700 rb_clear_cache_for_undef(klass, mid); 701 rb_unlink_method_entry(me); 702 703 CALL_METHOD_HOOK(self, removed, mid); 704} 705 706void 707rb_remove_method_id(VALUE klass, ID mid) 708{ 709 remove_method(klass, mid); 710} 711 712void 713rb_remove_method(VALUE klass, const char *name) 714{ 715 remove_method(klass, rb_intern(name)); 716} 717 718/* 719 * call-seq: 720 * remove_method(symbol) -> self 721 * 722 * Removes the method identified by _symbol_ from the current 723 * class. For an example, see <code>Module.undef_method</code>. 724 */ 725 726static VALUE 727rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) 728{ 729 int i; 730 731 for (i = 0; i < argc; i++) { 732 VALUE v = argv[i]; 733 ID id = rb_check_id(&v); 734 if (!id) { 735 rb_name_error_str(v, "method `%s' not defined in %s", 736 RSTRING_PTR(v), rb_class2name(mod)); 737 } 738 remove_method(mod, id); 739 } 740 return mod; 741} 742 743#undef rb_disable_super 744#undef rb_enable_super 745 746void 747rb_disable_super(VALUE klass, const char *name) 748{ 749 /* obsolete - no use */ 750} 751 752void 753rb_enable_super(VALUE klass, const char *name) 754{ 755 rb_warning("rb_enable_super() is obsolete"); 756} 757 758static void 759rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) 760{ 761 rb_method_entry_t *me; 762 VALUE defined_class; 763 764 if (klass == rb_cObject) { 765 rb_secure(4); 766 } 767 768 me = search_method(klass, name, &defined_class); 769 if (!me && RB_TYPE_P(klass, T_MODULE)) { 770 me = search_method(rb_cObject, name, &defined_class); 771 } 772 773 if (UNDEFINED_METHOD_ENTRY_P(me)) { 774 rb_print_undef(klass, name, 0); 775 } 776 777 if (me->flag != noex) { 778 rb_vm_check_redefinition_opt_method(me, klass); 779 780 if (klass == defined_class || 781 RCLASS_ORIGIN(klass) == defined_class) { 782 me->flag = noex; 783 if (me->def->type == VM_METHOD_TYPE_REFINED) { 784 me->def->body.orig_me->flag = noex; 785 } 786 } 787 else { 788 rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); 789 } 790 } 791} 792 793int 794rb_method_boundp(VALUE klass, ID id, int ex) 795{ 796 rb_method_entry_t *me = 797 rb_method_entry_without_refinements(klass, id, 0); 798 799 if (me != 0) { 800 if ((ex & ~NOEX_RESPONDS) && 801 ((me->flag & NOEX_PRIVATE) || 802 ((ex & NOEX_RESPONDS) && (me->flag & NOEX_PROTECTED)))) { 803 return 0; 804 } 805 if (!me->def) return 0; 806 if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) { 807 if (ex & NOEX_RESPONDS) return 2; 808 return 0; 809 } 810 return 1; 811 } 812 return 0; 813} 814 815void 816rb_attr(VALUE klass, ID id, int read, int write, int ex) 817{ 818 const char *name; 819 ID attriv; 820 VALUE aname; 821 rb_method_flag_t noex; 822 823 if (!ex) { 824 noex = NOEX_PUBLIC; 825 } 826 else { 827 if (SCOPE_TEST(NOEX_PRIVATE)) { 828 noex = NOEX_PRIVATE; 829 rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? 830 "attribute accessor as module_function" : 831 "private attribute?"); 832 } 833 else if (SCOPE_TEST(NOEX_PROTECTED)) { 834 noex = NOEX_PROTECTED; 835 } 836 else { 837 noex = NOEX_PUBLIC; 838 } 839 } 840 841 if (!rb_is_local_id(id) && !rb_is_const_id(id)) { 842 rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); 843 } 844 name = rb_id2name(id); 845 if (!name) { 846 rb_raise(rb_eArgError, "argument needs to be symbol or string"); 847 } 848 aname = rb_sprintf("@%s", name); 849 rb_enc_copy(aname, rb_id2str(id)); 850 attriv = rb_intern_str(aname); 851 if (read) { 852 rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex); 853 } 854 if (write) { 855 rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex); 856 } 857} 858 859void 860rb_undef(VALUE klass, ID id) 861{ 862 rb_method_entry_t *me; 863 864 if (NIL_P(klass)) { 865 rb_raise(rb_eTypeError, "no class to undef method"); 866 } 867 if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { 868 rb_secure(4); 869 } 870 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { 871 rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); 872 } 873 rb_frozen_class_p(klass); 874 if (id == object_id || id == id__send__ || id == idInitialize) { 875 rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); 876 } 877 878 me = search_method(klass, id, 0); 879 880 if (UNDEFINED_METHOD_ENTRY_P(me) || 881 (me->def->type == VM_METHOD_TYPE_REFINED && 882 UNDEFINED_METHOD_ENTRY_P(me->def->body.orig_me))) { 883 const char *s0 = " class"; 884 VALUE c = klass; 885 886 if (FL_TEST(c, FL_SINGLETON)) { 887 VALUE obj = rb_ivar_get(klass, attached); 888 889 if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) { 890 c = obj; 891 s0 = ""; 892 } 893 } 894 else if (RB_TYPE_P(c, T_MODULE)) { 895 s0 = " module"; 896 } 897 rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'", 898 QUOTE_ID(id), s0, rb_class_name(c)); 899 } 900 901 rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); 902 903 CALL_METHOD_HOOK(klass, undefined, id); 904} 905 906/* 907 * call-seq: 908 * undef_method(symbol) -> self 909 * 910 * Prevents the current class from responding to calls to the named 911 * method. Contrast this with <code>remove_method</code>, which deletes 912 * the method from the particular class; Ruby will still search 913 * superclasses and mixed-in modules for a possible receiver. 914 * 915 * class Parent 916 * def hello 917 * puts "In parent" 918 * end 919 * end 920 * class Child < Parent 921 * def hello 922 * puts "In child" 923 * end 924 * end 925 * 926 * 927 * c = Child.new 928 * c.hello 929 * 930 * 931 * class Child 932 * remove_method :hello # remove from child, still in parent 933 * end 934 * c.hello 935 * 936 * 937 * class Child 938 * undef_method :hello # prevent any calls to 'hello' 939 * end 940 * c.hello 941 * 942 * <em>produces:</em> 943 * 944 * In child 945 * In parent 946 * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError) 947 */ 948 949static VALUE 950rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) 951{ 952 int i; 953 for (i = 0; i < argc; i++) { 954 VALUE v = argv[i]; 955 ID id = rb_check_id(&v); 956 if (!id) { 957 rb_method_name_error(mod, v); 958 } 959 rb_undef(mod, id); 960 } 961 return mod; 962} 963 964/* 965 * call-seq: 966 * mod.method_defined?(symbol) -> true or false 967 * 968 * Returns +true+ if the named method is defined by 969 * _mod_ (or its included modules and, if _mod_ is a class, 970 * its ancestors). Public and protected methods are matched. 971 * 972 * module A 973 * def method1() end 974 * end 975 * class B 976 * def method2() end 977 * end 978 * class C < B 979 * include A 980 * def method3() end 981 * end 982 * 983 * A.method_defined? :method1 #=> true 984 * C.method_defined? "method1" #=> true 985 * C.method_defined? "method2" #=> true 986 * C.method_defined? "method3" #=> true 987 * C.method_defined? "method4" #=> false 988 */ 989 990static VALUE 991rb_mod_method_defined(VALUE mod, VALUE mid) 992{ 993 ID id = rb_check_id(&mid); 994 if (!id || !rb_method_boundp(mod, id, 1)) { 995 return Qfalse; 996 } 997 return Qtrue; 998 999} 1000 1001#define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f)) 1002 1003static VALUE 1004check_definition(VALUE mod, VALUE mid, rb_method_flag_t noex) 1005{ 1006 const rb_method_entry_t *me; 1007 ID id = rb_check_id(&mid); 1008 if (!id) return Qfalse; 1009 me = rb_method_entry(mod, id, 0); 1010 if (me) { 1011 if (VISI_CHECK(me->flag, noex)) 1012 return Qtrue; 1013 } 1014 return Qfalse; 1015} 1016 1017/* 1018 * call-seq: 1019 * mod.public_method_defined?(symbol) -> true or false 1020 * 1021 * Returns +true+ if the named public method is defined by 1022 * _mod_ (or its included modules and, if _mod_ is a class, 1023 * its ancestors). 1024 * 1025 * module A 1026 * def method1() end 1027 * end 1028 * class B 1029 * protected 1030 * def method2() end 1031 * end 1032 * class C < B 1033 * include A 1034 * def method3() end 1035 * end 1036 * 1037 * A.method_defined? :method1 #=> true 1038 * C.public_method_defined? "method1" #=> true 1039 * C.public_method_defined? "method2" #=> false 1040 * C.method_defined? "method2" #=> true 1041 */ 1042 1043static VALUE 1044rb_mod_public_method_defined(VALUE mod, VALUE mid) 1045{ 1046 return check_definition(mod, mid, NOEX_PUBLIC); 1047} 1048 1049/* 1050 * call-seq: 1051 * mod.private_method_defined?(symbol) -> true or false 1052 * 1053 * Returns +true+ if the named private method is defined by 1054 * _ mod_ (or its included modules and, if _mod_ is a class, 1055 * its ancestors). 1056 * 1057 * module A 1058 * def method1() end 1059 * end 1060 * class B 1061 * private 1062 * def method2() end 1063 * end 1064 * class C < B 1065 * include A 1066 * def method3() end 1067 * end 1068 * 1069 * A.method_defined? :method1 #=> true 1070 * C.private_method_defined? "method1" #=> false 1071 * C.private_method_defined? "method2" #=> true 1072 * C.method_defined? "method2" #=> false 1073 */ 1074 1075static VALUE 1076rb_mod_private_method_defined(VALUE mod, VALUE mid) 1077{ 1078 return check_definition(mod, mid, NOEX_PRIVATE); 1079} 1080 1081/* 1082 * call-seq: 1083 * mod.protected_method_defined?(symbol) -> true or false 1084 * 1085 * Returns +true+ if the named protected method is defined 1086 * by _mod_ (or its included modules and, if _mod_ is a 1087 * class, its ancestors). 1088 * 1089 * module A 1090 * def method1() end 1091 * end 1092 * class B 1093 * protected 1094 * def method2() end 1095 * end 1096 * class C < B 1097 * include A 1098 * def method3() end 1099 * end 1100 * 1101 * A.method_defined? :method1 #=> true 1102 * C.protected_method_defined? "method1" #=> false 1103 * C.protected_method_defined? "method2" #=> true 1104 * C.method_defined? "method2" #=> true 1105 */ 1106 1107static VALUE 1108rb_mod_protected_method_defined(VALUE mod, VALUE mid) 1109{ 1110 return check_definition(mod, mid, NOEX_PROTECTED); 1111} 1112 1113int 1114rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) 1115{ 1116 return rb_method_definition_eq(m1->def, m2->def); 1117} 1118 1119static int 1120rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2) 1121{ 1122 if (d1 && d1->type == VM_METHOD_TYPE_REFINED && d1->body.orig_me) 1123 d1 = d1->body.orig_me->def; 1124 if (d2 && d2->type == VM_METHOD_TYPE_REFINED && d2->body.orig_me) 1125 d2 = d2->body.orig_me->def; 1126 if (d1 == d2) return 1; 1127 if (!d1 || !d2) return 0; 1128 if (d1->type != d2->type) { 1129 return 0; 1130 } 1131 switch (d1->type) { 1132 case VM_METHOD_TYPE_ISEQ: 1133 return d1->body.iseq == d2->body.iseq; 1134 case VM_METHOD_TYPE_CFUNC: 1135 return 1136 d1->body.cfunc.func == d2->body.cfunc.func && 1137 d1->body.cfunc.argc == d2->body.cfunc.argc; 1138 case VM_METHOD_TYPE_ATTRSET: 1139 case VM_METHOD_TYPE_IVAR: 1140 return d1->body.attr.id == d2->body.attr.id; 1141 case VM_METHOD_TYPE_BMETHOD: 1142 return RTEST(rb_equal(d1->body.proc, d2->body.proc)); 1143 case VM_METHOD_TYPE_MISSING: 1144 return d1->original_id == d2->original_id; 1145 case VM_METHOD_TYPE_ZSUPER: 1146 case VM_METHOD_TYPE_NOTIMPLEMENTED: 1147 case VM_METHOD_TYPE_UNDEF: 1148 return 1; 1149 case VM_METHOD_TYPE_OPTIMIZED: 1150 return d1->body.optimize_type == d2->body.optimize_type; 1151 default: 1152 rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type); 1153 return 0; 1154 } 1155} 1156 1157static st_index_t 1158rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def) 1159{ 1160 again: 1161 hash = rb_hash_uint(hash, def->type); 1162 switch (def->type) { 1163 case VM_METHOD_TYPE_ISEQ: 1164 return rb_hash_uint(hash, (st_index_t)def->body.iseq); 1165 case VM_METHOD_TYPE_CFUNC: 1166 hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func); 1167 return rb_hash_uint(hash, def->body.cfunc.argc); 1168 case VM_METHOD_TYPE_ATTRSET: 1169 case VM_METHOD_TYPE_IVAR: 1170 return rb_hash_uint(hash, def->body.attr.id); 1171 case VM_METHOD_TYPE_BMETHOD: 1172 return rb_hash_proc(hash, def->body.proc); 1173 case VM_METHOD_TYPE_MISSING: 1174 return rb_hash_uint(hash, def->original_id); 1175 case VM_METHOD_TYPE_ZSUPER: 1176 case VM_METHOD_TYPE_NOTIMPLEMENTED: 1177 case VM_METHOD_TYPE_UNDEF: 1178 return hash; 1179 case VM_METHOD_TYPE_OPTIMIZED: 1180 return rb_hash_uint(hash, def->body.optimize_type); 1181 case VM_METHOD_TYPE_REFINED: 1182 if (def->body.orig_me) { 1183 def = def->body.orig_me->def; 1184 goto again; 1185 } 1186 else { 1187 return hash; 1188 } 1189 default: 1190 rb_bug("rb_hash_method_definition: unsupported method type (%d)\n", def->type); 1191 } 1192 return hash; 1193} 1194 1195st_index_t 1196rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me) 1197{ 1198 return rb_hash_method_definition(hash, me->def); 1199} 1200 1201void 1202rb_alias(VALUE klass, ID name, ID def) 1203{ 1204 VALUE target_klass = klass; 1205 VALUE defined_class; 1206 rb_method_entry_t *orig_me; 1207 rb_method_flag_t flag = NOEX_UNDEF; 1208 1209 if (NIL_P(klass)) { 1210 rb_raise(rb_eTypeError, "no class to make alias"); 1211 } 1212 1213 rb_frozen_class_p(klass); 1214 if (klass == rb_cObject) { 1215 rb_secure(4); 1216 } 1217 1218 again: 1219 orig_me = search_method(klass, def, &defined_class); 1220 1221 if (UNDEFINED_METHOD_ENTRY_P(orig_me)) { 1222 if ((!RB_TYPE_P(klass, T_MODULE)) || 1223 (orig_me = search_method(rb_cObject, def, 0), 1224 UNDEFINED_METHOD_ENTRY_P(orig_me))) { 1225 rb_print_undef(klass, def, 0); 1226 } 1227 } 1228 if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) { 1229 klass = RCLASS_SUPER(klass); 1230 def = orig_me->def->original_id; 1231 flag = orig_me->flag; 1232 goto again; 1233 } 1234 if (RB_TYPE_P(defined_class, T_ICLASS)) { 1235 VALUE real_class = RBASIC(defined_class)->klass; 1236 if (real_class && RCLASS_ORIGIN(real_class) == defined_class) 1237 defined_class = real_class; 1238 } 1239 1240 if (flag == NOEX_UNDEF) flag = orig_me->flag; 1241 method_entry_set(target_klass, name, orig_me, flag, defined_class); 1242} 1243 1244/* 1245 * call-seq: 1246 * alias_method(new_name, old_name) -> self 1247 * 1248 * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can 1249 * be used to retain access to methods that are overridden. 1250 * 1251 * module Mod 1252 * alias_method :orig_exit, :exit 1253 * def exit(code=0) 1254 * puts "Exiting with code #{code}" 1255 * orig_exit(code) 1256 * end 1257 * end 1258 * include Mod 1259 * exit(99) 1260 * 1261 * <em>produces:</em> 1262 * 1263 * Exiting with code 99 1264 */ 1265 1266static VALUE 1267rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) 1268{ 1269 ID oldid = rb_check_id(&oldname); 1270 if (!oldid) { 1271 rb_print_undef_str(mod, oldname); 1272 } 1273 rb_alias(mod, rb_to_id(newname), oldid); 1274 return mod; 1275} 1276 1277static void 1278secure_visibility(VALUE self) 1279{ 1280 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) { 1281 rb_raise(rb_eSecurityError, 1282 "Insecure: can't change method visibility"); 1283 } 1284} 1285 1286static void 1287set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex) 1288{ 1289 int i; 1290 secure_visibility(self); 1291 1292 if (argc == 0) { 1293 rb_warning("%s with no argument is just ignored", rb_id2name(rb_frame_callee())); 1294 } 1295 1296 for (i = 0; i < argc; i++) { 1297 VALUE v = argv[i]; 1298 ID id = rb_check_id(&v); 1299 if (!id) { 1300 rb_print_undef_str(self, v); 1301 } 1302 rb_export_method(self, id, ex); 1303 } 1304 rb_clear_cache_by_class(self); 1305} 1306 1307/* 1308 * call-seq: 1309 * public -> self 1310 * public(symbol, ...) -> self 1311 * 1312 * With no arguments, sets the default visibility for subsequently 1313 * defined methods to public. With arguments, sets the named methods to 1314 * have public visibility. 1315 */ 1316 1317static VALUE 1318rb_mod_public(int argc, VALUE *argv, VALUE module) 1319{ 1320 secure_visibility(module); 1321 if (argc == 0) { 1322 SCOPE_SET(NOEX_PUBLIC); 1323 } 1324 else { 1325 set_method_visibility(module, argc, argv, NOEX_PUBLIC); 1326 } 1327 return module; 1328} 1329 1330/* 1331 * call-seq: 1332 * protected -> self 1333 * protected(symbol, ...) -> self 1334 * 1335 * With no arguments, sets the default visibility for subsequently 1336 * defined methods to protected. With arguments, sets the named methods 1337 * to have protected visibility. 1338 */ 1339 1340static VALUE 1341rb_mod_protected(int argc, VALUE *argv, VALUE module) 1342{ 1343 secure_visibility(module); 1344 if (argc == 0) { 1345 SCOPE_SET(NOEX_PROTECTED); 1346 } 1347 else { 1348 set_method_visibility(module, argc, argv, NOEX_PROTECTED); 1349 } 1350 return module; 1351} 1352 1353/* 1354 * call-seq: 1355 * private -> self 1356 * private(symbol, ...) -> self 1357 * 1358 * With no arguments, sets the default visibility for subsequently 1359 * defined methods to private. With arguments, sets the named methods 1360 * to have private visibility. 1361 * 1362 * module Mod 1363 * def a() end 1364 * def b() end 1365 * private 1366 * def c() end 1367 * private :a 1368 * end 1369 * Mod.private_instance_methods #=> [:a, :c] 1370 */ 1371 1372static VALUE 1373rb_mod_private(int argc, VALUE *argv, VALUE module) 1374{ 1375 secure_visibility(module); 1376 if (argc == 0) { 1377 SCOPE_SET(NOEX_PRIVATE); 1378 } 1379 else { 1380 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 1381 } 1382 return module; 1383} 1384 1385/* 1386 * call-seq: 1387 * mod.public_class_method(symbol, ...) -> mod 1388 * 1389 * Makes a list of existing class methods public. 1390 */ 1391 1392static VALUE 1393rb_mod_public_method(int argc, VALUE *argv, VALUE obj) 1394{ 1395 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PUBLIC); 1396 return obj; 1397} 1398 1399/* 1400 * call-seq: 1401 * mod.private_class_method(symbol, ...) -> mod 1402 * 1403 * Makes existing class methods private. Often used to hide the default 1404 * constructor <code>new</code>. 1405 * 1406 * class SimpleSingleton # Not thread safe 1407 * private_class_method :new 1408 * def SimpleSingleton.create(*args, &block) 1409 * @me = new(*args, &block) if ! @me 1410 * @me 1411 * end 1412 * end 1413 */ 1414 1415static VALUE 1416rb_mod_private_method(int argc, VALUE *argv, VALUE obj) 1417{ 1418 set_method_visibility(rb_singleton_class(obj), argc, argv, NOEX_PRIVATE); 1419 return obj; 1420} 1421 1422/* 1423 * call-seq: 1424 * public 1425 * public(symbol, ...) 1426 * 1427 * With no arguments, sets the default visibility for subsequently 1428 * defined methods to public. With arguments, sets the named methods to 1429 * have public visibility. 1430 */ 1431 1432static VALUE 1433top_public(int argc, VALUE *argv) 1434{ 1435 return rb_mod_public(argc, argv, rb_cObject); 1436} 1437 1438static VALUE 1439top_private(int argc, VALUE *argv) 1440{ 1441 return rb_mod_private(argc, argv, rb_cObject); 1442} 1443 1444/* 1445 * call-seq: 1446 * module_function(symbol, ...) -> self 1447 * 1448 * Creates module functions for the named methods. These functions may 1449 * be called with the module as a receiver, and also become available 1450 * as instance methods to classes that mix in the module. Module 1451 * functions are copies of the original, and so may be changed 1452 * independently. The instance-method versions are made private. If 1453 * used with no arguments, subsequently defined methods become module 1454 * functions. 1455 * 1456 * module Mod 1457 * def one 1458 * "This is one" 1459 * end 1460 * module_function :one 1461 * end 1462 * class Cls 1463 * include Mod 1464 * def call_one 1465 * one 1466 * end 1467 * end 1468 * Mod.one #=> "This is one" 1469 * c = Cls.new 1470 * c.call_one #=> "This is one" 1471 * module Mod 1472 * def one 1473 * "This is the new one" 1474 * end 1475 * end 1476 * Mod.one #=> "This is one" 1477 * c.call_one #=> "This is the new one" 1478 */ 1479 1480static VALUE 1481rb_mod_modfunc(int argc, VALUE *argv, VALUE module) 1482{ 1483 int i; 1484 ID id; 1485 const rb_method_entry_t *me; 1486 1487 if (!RB_TYPE_P(module, T_MODULE)) { 1488 rb_raise(rb_eTypeError, "module_function must be called for modules"); 1489 } 1490 1491 secure_visibility(module); 1492 if (argc == 0) { 1493 SCOPE_SET(NOEX_MODFUNC); 1494 return module; 1495 } 1496 1497 set_method_visibility(module, argc, argv, NOEX_PRIVATE); 1498 1499 for (i = 0; i < argc; i++) { 1500 VALUE m = module; 1501 1502 id = rb_to_id(argv[i]); 1503 for (;;) { 1504 me = search_method(m, id, 0); 1505 if (me == 0) { 1506 me = search_method(rb_cObject, id, 0); 1507 } 1508 if (UNDEFINED_METHOD_ENTRY_P(me)) { 1509 rb_print_undef(module, id, 0); 1510 } 1511 if (me->def->type != VM_METHOD_TYPE_ZSUPER) { 1512 break; /* normal case: need not to follow 'super' link */ 1513 } 1514 m = RCLASS_SUPER(m); 1515 if (!m) 1516 break; 1517 } 1518 rb_method_entry_set(rb_singleton_class(module), id, me, NOEX_PUBLIC); 1519 } 1520 return module; 1521} 1522 1523int 1524rb_method_basic_definition_p(VALUE klass, ID id) 1525{ 1526 const rb_method_entry_t *me = rb_method_entry(klass, id, 0); 1527 if (me && (me->flag & NOEX_BASIC)) 1528 return 1; 1529 return 0; 1530} 1531 1532static inline int 1533basic_obj_respond_to(VALUE obj, ID id, int pub) 1534{ 1535 VALUE klass = CLASS_OF(obj); 1536 VALUE args[2]; 1537 1538 switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) { 1539 case 2: 1540 return FALSE; 1541 case 0: 1542 args[0] = ID2SYM(id); 1543 args[1] = pub ? Qfalse : Qtrue; 1544 return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args)); 1545 default: 1546 return TRUE; 1547 } 1548} 1549 1550int 1551rb_obj_respond_to(VALUE obj, ID id, int priv) 1552{ 1553 VALUE klass = CLASS_OF(obj); 1554 1555 if (rb_method_basic_definition_p(klass, idRespond_to)) { 1556 return basic_obj_respond_to(obj, id, !RTEST(priv)); 1557 } 1558 else { 1559 int argc = 1; 1560 VALUE args[2]; 1561 args[0] = ID2SYM(id); 1562 args[1] = Qtrue; 1563 if (priv) { 1564 if (rb_obj_method_arity(obj, idRespond_to) != 1) { 1565 argc = 2; 1566 } 1567 else if (!NIL_P(ruby_verbose)) { 1568 VALUE klass = CLASS_OF(obj); 1569 VALUE location = rb_mod_method_location(klass, idRespond_to); 1570 rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is" 1571 " old fashion which takes only one parameter", 1572 (FL_TEST(klass, FL_SINGLETON) ? obj : klass), 1573 (FL_TEST(klass, FL_SINGLETON) ? '.' : '#'), 1574 QUOTE_ID(id)); 1575 if (!NIL_P(location)) { 1576 VALUE path = RARRAY_PTR(location)[0]; 1577 VALUE line = RARRAY_PTR(location)[1]; 1578 if (!NIL_P(path)) { 1579 rb_compile_warn(RSTRING_PTR(path), NUM2INT(line), 1580 "respond_to? is defined here"); 1581 } 1582 } 1583 } 1584 } 1585 return RTEST(rb_funcall2(obj, idRespond_to, argc, args)); 1586 } 1587} 1588 1589int 1590rb_respond_to(VALUE obj, ID id) 1591{ 1592 return rb_obj_respond_to(obj, id, FALSE); 1593} 1594 1595 1596/* 1597 * call-seq: 1598 * obj.respond_to?(symbol, include_all=false) -> true or false 1599 * 1600 * Returns +true+ if _obj_ responds to the given method. Private and 1601 * protected methods are included in the search only if the optional 1602 * second parameter evaluates to +true+. 1603 * 1604 * If the method is not implemented, 1605 * as Process.fork on Windows, File.lchmod on GNU/Linux, etc., 1606 * false is returned. 1607 * 1608 * If the method is not defined, <code>respond_to_missing?</code> 1609 * method is called and the result is returned. 1610 */ 1611 1612static VALUE 1613obj_respond_to(int argc, VALUE *argv, VALUE obj) 1614{ 1615 VALUE mid, priv; 1616 ID id; 1617 1618 rb_scan_args(argc, argv, "11", &mid, &priv); 1619 if (!(id = rb_check_id(&mid))) { 1620 if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) { 1621 VALUE args[2]; 1622 args[0] = ID2SYM(rb_to_id(mid)); 1623 args[1] = priv; 1624 return rb_funcall2(obj, idRespond_to_missing, 2, args); 1625 } 1626 return Qfalse; 1627 } 1628 if (basic_obj_respond_to(obj, id, !RTEST(priv))) 1629 return Qtrue; 1630 return Qfalse; 1631} 1632 1633/* 1634 * call-seq: 1635 * obj.respond_to_missing?(symbol, include_all) -> true or false 1636 * 1637 * DO NOT USE THIS DIRECTLY. 1638 * 1639 * Hook method to return whether the _obj_ can respond to _id_ method 1640 * or not. 1641 * 1642 * See #respond_to?. 1643 */ 1644static VALUE 1645obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv) 1646{ 1647 return Qfalse; 1648} 1649 1650void 1651Init_eval_method(void) 1652{ 1653#undef rb_intern 1654#define rb_intern(str) rb_intern_const(str) 1655 1656 rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1); 1657 rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2); 1658 1659 rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1); 1660 rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1); 1661 rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); 1662 rb_define_private_method(rb_cModule, "public", rb_mod_public, -1); 1663 rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1); 1664 rb_define_private_method(rb_cModule, "private", rb_mod_private, -1); 1665 rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1); 1666 1667 rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1); 1668 rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1); 1669 rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1); 1670 rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1); 1671 rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1); 1672 rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1); 1673 1674 rb_define_private_method(rb_singleton_class(rb_vm_top_self()), 1675 "public", top_public, -1); 1676 rb_define_private_method(rb_singleton_class(rb_vm_top_self()), 1677 "private", top_private, -1); 1678 1679 object_id = rb_intern("object_id"); 1680 added = rb_intern("method_added"); 1681 singleton_added = rb_intern("singleton_method_added"); 1682 removed = rb_intern("method_removed"); 1683 singleton_removed = rb_intern("singleton_method_removed"); 1684 undefined = rb_intern("method_undefined"); 1685 singleton_undefined = rb_intern("singleton_method_undefined"); 1686 attached = rb_intern("__attached__"); 1687 1688 { 1689#define REPLICATE_METHOD(klass, id, noex) \ 1690 rb_method_entry_set((klass), (id), \ 1691 rb_method_entry((klass), (id), 0), \ 1692 (rb_method_flag_t)(noex | NOEX_BASIC | NOEX_NOREDEF)) 1693 REPLICATE_METHOD(rb_eException, idMethodMissing, NOEX_PRIVATE); 1694 REPLICATE_METHOD(rb_eException, idRespond_to, NOEX_PUBLIC); 1695 REPLICATE_METHOD(rb_eException, idRespond_to_missing, NOEX_PUBLIC); 1696 } 1697} 1698