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