Ruby  1.9.3p551(2014-11-13revision48407)
vm_method.c
Go to the documentation of this file.
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 
10 
14 
15 struct cache_entry { /* method hash table. */
16  VALUE filled_version; /* filled state version */
17  ID mid; /* method's id */
18  VALUE klass; /* receiver's class */
20 };
21 
22 static struct cache_entry cache[CACHE_SIZE];
23 #define ruby_running (GET_VM()->running)
24 /* int ruby_running = 0; */
25 
26 static void
28 {
29  struct cache_entry *ent, *end;
30 
31  ent = cache;
32  end = ent + CACHE_SIZE;
33  while (ent < end) {
34  ent->filled_version = 0;
35  ent++;
36  }
37 }
38 
39 void
41 {
43 }
44 
45 static void
47 {
49 }
50 
51 static void
53 {
55 }
56 
57 void
59 {
61 }
62 
63 VALUE
65 {
67 }
68 
69 static void
71 {
73 }
74 
75 void
77 {
78  if (func != rb_f_notimplement) {
80  opt.func = func;
81  opt.argc = argc;
82  rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex);
83  }
84  else {
85  rb_define_notimplement_method_id(klass, mid, noex);
86  }
87 }
88 
89 void
91 {
93  ume->me = me;
94  ume->next = GET_VM()->unlinked_method_entry_list;
95  GET_VM()->unlinked_method_entry_list = ume;
96 }
97 
98 void
100 {
101  rb_vm_t *vm = pvm;
103 
104  while (ume) {
105  if (ume->me->mark) {
106  rb_mark_method_entry(ume->me);
107  }
108  ume = ume->next;
109  }
110 }
111 
112 void
114 {
115  rb_vm_t *vm = pvm;
116  struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume;
117 
118  while (ume) {
119  if (ume->me->mark) {
120  ume->me->mark = 0;
121  prev_ume = ume;
122  ume = ume->next;
123  }
124  else {
125  rb_free_method_entry(ume->me);
126 
127  if (prev_ume == 0) {
128  vm->unlinked_method_entry_list = ume->next;
129  }
130  else {
131  prev_ume->next = ume->next;
132  }
133 
134  curr_ume = ume;
135  ume = ume->next;
136  xfree(curr_ume);
137  }
138  }
139 }
140 
141 void
143 {
144  rb_method_definition_t *def = me->def;
145 
146  if (def) {
147  if (def->alias_count == 0) {
148  xfree(def);
149  }
150  else if (def->alias_count > 0) {
151  def->alias_count--;
152  }
153  me->def = 0;
154  }
155  xfree(me);
156 }
157 
159 
160 static rb_method_entry_t *
163 {
165  st_table *mtbl;
166  st_data_t data;
167 
168  if (NIL_P(klass)) {
169  klass = rb_cObject;
170  }
171  if (rb_safe_level() >= 4 &&
172  (klass == rb_cObject || !OBJ_UNTRUSTED(klass))) {
173  rb_raise(rb_eSecurityError, "Insecure: can't define method");
174  }
175  if (!FL_TEST(klass, FL_SINGLETON) &&
177  type != VM_METHOD_TYPE_ZSUPER &&
178  (mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
179  noex = NOEX_PRIVATE | noex;
180  }
181  else if (FL_TEST(klass, FL_SINGLETON) &&
182  type == VM_METHOD_TYPE_CFUNC &&
183  mid == rb_intern("allocate")) {
184  rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()",
186  mid = ID_ALLOCATOR;
187  }
188 
189  rb_check_frozen(klass);
190  mtbl = RCLASS_M_TBL(klass);
191 
192  /* check re-definition */
193  if (st_lookup(mtbl, mid, &data)) {
194  rb_method_entry_t *old_me = (rb_method_entry_t *)data;
195  rb_method_definition_t *old_def = old_me->def;
196 
197  if (rb_method_definition_eq(old_def, def)) return old_me;
199 
200  if (RTEST(ruby_verbose) &&
201  type != VM_METHOD_TYPE_UNDEF &&
202  old_def->alias_count == 0 &&
203  old_def->type != VM_METHOD_TYPE_UNDEF &&
204  old_def->type != VM_METHOD_TYPE_ZSUPER) {
205  rb_iseq_t *iseq = 0;
206 
207  rb_warning("method redefined; discarding old %s", rb_id2name(mid));
208  switch (old_def->type) {
209  case VM_METHOD_TYPE_ISEQ:
210  iseq = old_def->body.iseq;
211  break;
213  iseq = rb_proc_get_iseq(old_def->body.proc, 0);
214  break;
215  default:
216  break;
217  }
218  if (iseq && !NIL_P(iseq->filename)) {
219  int line = iseq->insn_info_table ? rb_iseq_first_lineno(iseq) : 0;
221  "previous definition of %s was here",
222  rb_id2name(old_def->original_id));
223  }
224  }
225 
226  rb_unlink_method_entry(old_me);
227  }
228 
229  me = ALLOC(rb_method_entry_t);
230 
232 
233  me->flag = NOEX_WITH_SAFE(noex);
234  me->mark = 0;
235  me->called_id = mid;
236  me->klass = klass;
237  me->def = def;
238  if (def) def->alias_count++;
239 
240  /* check mid */
241  if (klass == rb_cObject && mid == idInitialize) {
242  rb_warn("redefining Object#initialize may cause infinite loop");
243  }
244  /* check mid */
245  if (mid == object_id || mid == id__send__) {
246  if (type == VM_METHOD_TYPE_ISEQ) {
247  rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
248  }
249  }
250 
251  st_insert(mtbl, mid, (st_data_t) me);
252 
253  return me;
254 }
255 
256 #define CALL_METHOD_HOOK(klass, hook, mid) do { \
257  const VALUE arg = ID2SYM(mid); \
258  VALUE recv_class = (klass); \
259  ID hook_id = (hook); \
260  if (FL_TEST((klass), FL_SINGLETON)) { \
261  recv_class = rb_ivar_get((klass), attached); \
262  hook_id = singleton_##hook; \
263  } \
264  rb_funcall2(recv_class, hook_id, 1, &arg); \
265  } while (0)
266 
267 static void
268 method_added(VALUE klass, ID mid)
269 {
270  if (mid != ID_ALLOCATOR && ruby_running) {
271  CALL_METHOD_HOOK(klass, added, mid);
272  }
273 }
274 
277 {
278  rb_thread_t *th;
279  rb_control_frame_t *cfp;
280  int line;
281  rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex);
283  me->def = def;
284  def->type = type;
285  def->original_id = mid;
286  def->alias_count = 0;
287  switch (type) {
288  case VM_METHOD_TYPE_ISEQ:
289  def->body.iseq = (rb_iseq_t *)opts;
290  break;
292  def->body.cfunc = *(rb_method_cfunc_t *)opts;
293  break;
295  case VM_METHOD_TYPE_IVAR:
296  def->body.attr.id = (ID)opts;
297  def->body.attr.location = Qfalse;
298  th = GET_THREAD();
299  cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
300  if (cfp && (line = rb_vm_get_sourceline(cfp))) {
301  VALUE location = rb_ary_new3(2, cfp->iseq->filename, INT2FIX(line));
302  def->body.attr.location = rb_ary_freeze(location);
303  }
304  break;
306  def->body.proc = (VALUE)opts;
307  break;
310  def->body.cfunc.argc = -1;
311  break;
313  def->body.optimize_type = (enum method_optimized_type)opts;
314  break;
317  break;
318  default:
319  rb_bug("rb_add_method: unsupported method type (%d)\n", type);
320  }
321  if (type != VM_METHOD_TYPE_UNDEF) {
322  method_added(klass, mid);
323  }
324  return me;
325 }
326 
329 {
331  rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex);
332  method_added(klass, mid);
333  return newme;
334 }
335 
336 void
338 {
339  Check_Type(klass, T_CLASS);
341  func, 0, NOEX_PRIVATE);
342 }
343 
344 void
346 {
347  Check_Type(klass, T_CLASS);
349 }
350 
353 {
355  Check_Type(klass, T_CLASS);
356  me = rb_method_entry(CLASS_OF(klass), ID_ALLOCATOR);
357 
358  if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC) {
359  return (rb_alloc_func_t)me->def->body.cfunc.func;
360  }
361  else {
362  return 0;
363  }
364 }
365 
366 static rb_method_entry_t*
368 {
369  st_data_t body;
370  if (!klass) {
371  return 0;
372  }
373 
374  while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
375  klass = RCLASS_SUPER(klass);
376  if (!klass) {
377  return 0;
378  }
379  }
380 
381  return (rb_method_entry_t *)body;
382 }
383 
384 /*
385  * search method entry without the method cache.
386  *
387  * if you need method entry with method cache (normal case), use
388  * rb_method_entry() simply.
389  */
392 {
393  rb_method_entry_t *me = search_method(klass, id);
394 
395  if (ruby_running) {
396  struct cache_entry *ent;
397  ent = cache + EXPR1(klass, id);
399  ent->klass = klass;
400 
401  if (UNDEFINED_METHOD_ENTRY_P(me)) {
402  ent->mid = id;
403  ent->me = 0;
404  me = 0;
405  }
406  else {
407  ent->mid = id;
408  ent->me = me;
409  }
410  }
411 
412  return me;
413 }
414 
417 {
418  struct cache_entry *ent;
419 
420  ent = cache + EXPR1(klass, id);
421  if (ent->filled_version == GET_VM_STATE_VERSION() &&
422  ent->mid == id && ent->klass == klass) {
423  return ent->me;
424  }
425 
426  return rb_method_entry_get_without_cache(klass, id);
427 }
428 
429 static void
430 remove_method(VALUE klass, ID mid)
431 {
432  st_data_t key, data;
433  rb_method_entry_t *me = 0;
434 
435  if (klass == rb_cObject) {
436  rb_secure(4);
437  }
438  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
439  rb_raise(rb_eSecurityError, "Insecure: can't remove method");
440  }
441  rb_check_frozen(klass);
442  if (mid == object_id || mid == id__send__ || mid == idInitialize) {
443  rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
444  }
445 
446  if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
447  !(me = (rb_method_entry_t *)data) ||
448  (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
449  rb_name_error(mid, "method `%s' not defined in %s",
450  rb_id2name(mid), rb_class2name(klass));
451  }
452  key = (st_data_t)mid;
453  st_delete(RCLASS_M_TBL(klass), &key, &data);
454 
456  rb_clear_cache_for_undef(klass, mid);
458 
459  CALL_METHOD_HOOK(klass, removed, mid);
460 }
461 
462 void
464 {
465  remove_method(klass, mid);
466 }
467 
468 void
469 rb_remove_method(VALUE klass, const char *name)
470 {
471  remove_method(klass, rb_intern(name));
472 }
473 
474 /*
475  * call-seq:
476  * remove_method(symbol) -> self
477  *
478  * Removes the method identified by _symbol_ from the current
479  * class. For an example, see <code>Module.undef_method</code>.
480  */
481 
482 static VALUE
484 {
485  int i;
486 
487  for (i = 0; i < argc; i++) {
488  remove_method(mod, rb_to_id(argv[i]));
489  }
490  return mod;
491 }
492 
493 #undef rb_disable_super
494 #undef rb_enable_super
495 
496 void
497 rb_disable_super(VALUE klass, const char *name)
498 {
499  /* obsolete - no use */
500 }
501 
502 void
503 rb_enable_super(VALUE klass, const char *name)
504 {
505  rb_warning("rb_enable_super() is obsolete");
506 }
507 
508 static void
510 {
512 
513  if (klass == rb_cObject) {
514  rb_secure(4);
515  }
516 
517  me = search_method(klass, name);
518  if (!me && TYPE(klass) == T_MODULE) {
519  me = search_method(rb_cObject, name);
520  }
521 
522  if (UNDEFINED_METHOD_ENTRY_P(me)) {
523  rb_print_undef(klass, name, 0);
524  }
525 
526  if (me->flag != noex) {
528 
529  if (klass == me->klass) {
530  me->flag = noex;
531  }
532  else {
533  rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex);
534  }
535  }
536 }
537 
538 int
539 rb_method_boundp(VALUE klass, ID id, int ex)
540 {
541  rb_method_entry_t *me = rb_method_entry(klass, id);
542 
543  if (me != 0) {
544  if ((ex & ~NOEX_RESPONDS) && (me->flag & NOEX_PRIVATE)) {
545  return FALSE;
546  }
547  if (!me->def) return 0;
548  if (me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
549  if (ex & NOEX_RESPONDS) return 2;
550  return 0;
551  }
552  return 1;
553  }
554  return 0;
555 }
556 
557 void
558 rb_attr(VALUE klass, ID id, int read, int write, int ex)
559 {
560  const char *name;
561  ID attriv;
562  VALUE aname;
563  rb_method_flag_t noex;
564 
565  if (!ex) {
566  noex = NOEX_PUBLIC;
567  }
568  else {
569  if (SCOPE_TEST(NOEX_PRIVATE)) {
570  noex = NOEX_PRIVATE;
572  "attribute accessor as module_function" :
573  "private attribute?");
574  }
575  else if (SCOPE_TEST(NOEX_PROTECTED)) {
576  noex = NOEX_PROTECTED;
577  }
578  else {
579  noex = NOEX_PUBLIC;
580  }
581  }
582 
583  if (!rb_is_local_id(id) && !rb_is_const_id(id)) {
584  rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id));
585  }
586  name = rb_id2name(id);
587  if (!name) {
588  rb_raise(rb_eArgError, "argument needs to be symbol or string");
589  }
590  aname = rb_sprintf("@%s", name);
591  rb_enc_copy(aname, rb_id2str(id));
592  attriv = rb_intern_str(aname);
593  if (read) {
594  rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex);
595  }
596  if (write) {
597  rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex);
598  }
599 }
600 
601 void
602 rb_undef(VALUE klass, ID id)
603 {
605 
606  if (NIL_P(klass)) {
607  rb_raise(rb_eTypeError, "no class to undef method");
608  }
609  if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
610  rb_secure(4);
611  }
612  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
613  rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id));
614  }
615  rb_frozen_class_p(klass);
616  if (id == object_id || id == id__send__ || id == idInitialize) {
617  rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
618  }
619 
620  me = search_method(klass, id);
621 
622  if (UNDEFINED_METHOD_ENTRY_P(me)) {
623  const char *s0 = " class";
624  VALUE c = klass;
625 
626  if (FL_TEST(c, FL_SINGLETON)) {
627  VALUE obj = rb_ivar_get(klass, attached);
628 
629  switch (TYPE(obj)) {
630  case T_MODULE:
631  case T_CLASS:
632  c = obj;
633  s0 = "";
634  }
635  }
636  else if (TYPE(c) == T_MODULE) {
637  s0 = " module";
638  }
639  rb_name_error(id, "undefined method `%s' for%s `%s'",
640  rb_id2name(id), s0, rb_class2name(c));
641  }
642 
644 
645  CALL_METHOD_HOOK(klass, undefined, id);
646 }
647 
648 /*
649  * call-seq:
650  * undef_method(symbol) -> self
651  *
652  * Prevents the current class from responding to calls to the named
653  * method. Contrast this with <code>remove_method</code>, which deletes
654  * the method from the particular class; Ruby will still search
655  * superclasses and mixed-in modules for a possible receiver.
656  *
657  * class Parent
658  * def hello
659  * puts "In parent"
660  * end
661  * end
662  * class Child < Parent
663  * def hello
664  * puts "In child"
665  * end
666  * end
667  *
668  *
669  * c = Child.new
670  * c.hello
671  *
672  *
673  * class Child
674  * remove_method :hello # remove from child, still in parent
675  * end
676  * c.hello
677  *
678  *
679  * class Child
680  * undef_method :hello # prevent any calls to 'hello'
681  * end
682  * c.hello
683  *
684  * <em>produces:</em>
685  *
686  * In child
687  * In parent
688  * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
689  */
690 
691 static VALUE
693 {
694  int i;
695  for (i = 0; i < argc; i++) {
696  rb_undef(mod, rb_to_id(argv[i]));
697  }
698  return mod;
699 }
700 
701 /*
702  * call-seq:
703  * mod.method_defined?(symbol) -> true or false
704  *
705  * Returns +true+ if the named method is defined by
706  * _mod_ (or its included modules and, if _mod_ is a class,
707  * its ancestors). Public and protected methods are matched.
708  *
709  * module A
710  * def method1() end
711  * end
712  * class B
713  * def method2() end
714  * end
715  * class C < B
716  * include A
717  * def method3() end
718  * end
719  *
720  * A.method_defined? :method1 #=> true
721  * C.method_defined? "method1" #=> true
722  * C.method_defined? "method2" #=> true
723  * C.method_defined? "method3" #=> true
724  * C.method_defined? "method4" #=> false
725  */
726 
727 static VALUE
729 {
730  if (!rb_method_boundp(mod, rb_to_id(mid), 1)) {
731  return Qfalse;
732  }
733  return Qtrue;
734 
735 }
736 
737 #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f))
738 
739 static VALUE
741 {
742  const rb_method_entry_t *me;
743  me = rb_method_entry(mod, mid);
744  if (me) {
745  if (VISI_CHECK(me->flag, noex))
746  return Qtrue;
747  }
748  return Qfalse;
749 }
750 
751 /*
752  * call-seq:
753  * mod.public_method_defined?(symbol) -> true or false
754  *
755  * Returns +true+ if the named public method is defined by
756  * _mod_ (or its included modules and, if _mod_ is a class,
757  * its ancestors).
758  *
759  * module A
760  * def method1() end
761  * end
762  * class B
763  * protected
764  * def method2() end
765  * end
766  * class C < B
767  * include A
768  * def method3() end
769  * end
770  *
771  * A.method_defined? :method1 #=> true
772  * C.public_method_defined? "method1" #=> true
773  * C.public_method_defined? "method2" #=> false
774  * C.method_defined? "method2" #=> true
775  */
776 
777 static VALUE
779 {
780  return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC);
781 }
782 
783 /*
784  * call-seq:
785  * mod.private_method_defined?(symbol) -> true or false
786  *
787  * Returns +true+ if the named private method is defined by
788  * _ mod_ (or its included modules and, if _mod_ is a class,
789  * its ancestors).
790  *
791  * module A
792  * def method1() end
793  * end
794  * class B
795  * private
796  * def method2() end
797  * end
798  * class C < B
799  * include A
800  * def method3() end
801  * end
802  *
803  * A.method_defined? :method1 #=> true
804  * C.private_method_defined? "method1" #=> false
805  * C.private_method_defined? "method2" #=> true
806  * C.method_defined? "method2" #=> false
807  */
808 
809 static VALUE
811 {
812  return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE);
813 }
814 
815 /*
816  * call-seq:
817  * mod.protected_method_defined?(symbol) -> true or false
818  *
819  * Returns +true+ if the named protected method is defined
820  * by _mod_ (or its included modules and, if _mod_ is a
821  * class, its ancestors).
822  *
823  * module A
824  * def method1() end
825  * end
826  * class B
827  * protected
828  * def method2() end
829  * end
830  * class C < B
831  * include A
832  * def method3() end
833  * end
834  *
835  * A.method_defined? :method1 #=> true
836  * C.protected_method_defined? "method1" #=> false
837  * C.protected_method_defined? "method2" #=> true
838  * C.method_defined? "method2" #=> true
839  */
840 
841 static VALUE
843 {
844  return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED);
845 }
846 
847 int
849 {
850  return rb_method_definition_eq(m1->def, m2->def);
851 }
852 
853 static int
855 {
856  if (d1 == d2) return 1;
857  if (!d1 || !d2) return 0;
858  if (d1->type != d2->type) {
859  return 0;
860  }
861  switch (d1->type) {
862  case VM_METHOD_TYPE_ISEQ:
863  return d1->body.iseq == d2->body.iseq;
865  return
866  d1->body.cfunc.func == d2->body.cfunc.func &&
867  d1->body.cfunc.argc == d2->body.cfunc.argc;
869  case VM_METHOD_TYPE_IVAR:
870  return d1->body.attr.id == d2->body.attr.id;
872  return RTEST(rb_equal(d1->body.proc, d2->body.proc));
874  return d1->original_id == d2->original_id;
878  return 1;
880  return d1->body.optimize_type == d2->body.optimize_type;
881  default:
882  rb_bug("rb_method_entry_eq: unsupported method type (%d)\n", d1->type);
883  return 0;
884  }
885 }
886 
887 void
888 rb_alias(VALUE klass, ID name, ID def)
889 {
890  VALUE target_klass = klass;
891  rb_method_entry_t *orig_me;
893 
894  if (NIL_P(klass)) {
895  rb_raise(rb_eTypeError, "no class to make alias");
896  }
897 
898  rb_frozen_class_p(klass);
899  if (klass == rb_cObject) {
900  rb_secure(4);
901  }
902 
903  again:
904  orig_me = search_method(klass, def);
905 
906  if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
907  if ((TYPE(klass) != T_MODULE) ||
908  (orig_me = search_method(rb_cObject, def), UNDEFINED_METHOD_ENTRY_P(orig_me))) {
909  rb_print_undef(klass, def, 0);
910  }
911  }
912  if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
913  klass = RCLASS_SUPER(klass);
914  def = orig_me->def->original_id;
915  flag = orig_me->flag;
916  goto again;
917  }
918 
919  if (flag == NOEX_UNDEF) flag = orig_me->flag;
920  rb_method_entry_set(target_klass, name, orig_me, flag);
921 }
922 
923 /*
924  * call-seq:
925  * alias_method(new_name, old_name) -> self
926  *
927  * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
928  * be used to retain access to methods that are overridden.
929  *
930  * module Mod
931  * alias_method :orig_exit, :exit
932  * def exit(code=0)
933  * puts "Exiting with code #{code}"
934  * orig_exit(code)
935  * end
936  * end
937  * include Mod
938  * exit(99)
939  *
940  * <em>produces:</em>
941  *
942  * Exiting with code 99
943  */
944 
945 static VALUE
947 {
948  rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
949  return mod;
950 }
951 
952 static void
954 {
955  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(self)) {
957  "Insecure: can't change method visibility");
958  }
959 }
960 
961 static void
963 {
964  int i;
965  secure_visibility(self);
966 
967  if (argc == 0) {
968  rb_warning("%s with no argument is just ignored", rb_id2name(rb_frame_callee()));
969  }
970 
971  for (i = 0; i < argc; i++) {
972  rb_export_method(self, rb_to_id(argv[i]), ex);
973  }
975 }
976 
977 /*
978  * call-seq:
979  * public -> self
980  * public(symbol, ...) -> self
981  *
982  * With no arguments, sets the default visibility for subsequently
983  * defined methods to public. With arguments, sets the named methods to
984  * have public visibility.
985  */
986 
987 static VALUE
989 {
990  secure_visibility(module);
991  if (argc == 0) {
993  }
994  else {
995  set_method_visibility(module, argc, argv, NOEX_PUBLIC);
996  }
997  return module;
998 }
999 
1000 /*
1001  * call-seq:
1002  * protected -> self
1003  * protected(symbol, ...) -> self
1004  *
1005  * With no arguments, sets the default visibility for subsequently
1006  * defined methods to protected. With arguments, sets the named methods
1007  * to have protected visibility.
1008  */
1009 
1010 static VALUE
1012 {
1013  secure_visibility(module);
1014  if (argc == 0) {
1016  }
1017  else {
1018  set_method_visibility(module, argc, argv, NOEX_PROTECTED);
1019  }
1020  return module;
1021 }
1022 
1023 /*
1024  * call-seq:
1025  * private -> self
1026  * private(symbol, ...) -> self
1027  *
1028  * With no arguments, sets the default visibility for subsequently
1029  * defined methods to private. With arguments, sets the named methods
1030  * to have private visibility.
1031  *
1032  * module Mod
1033  * def a() end
1034  * def b() end
1035  * private
1036  * def c() end
1037  * private :a
1038  * end
1039  * Mod.private_instance_methods #=> [:a, :c]
1040  */
1041 
1042 static VALUE
1044 {
1045  secure_visibility(module);
1046  if (argc == 0) {
1048  }
1049  else {
1050  set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1051  }
1052  return module;
1053 }
1054 
1055 /*
1056  * call-seq:
1057  * mod.public_class_method(symbol, ...) -> mod
1058  *
1059  * Makes a list of existing class methods public.
1060  */
1061 
1062 static VALUE
1064 {
1065  set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PUBLIC);
1066  return obj;
1067 }
1068 
1069 /*
1070  * call-seq:
1071  * mod.private_class_method(symbol, ...) -> mod
1072  *
1073  * Makes existing class methods private. Often used to hide the default
1074  * constructor <code>new</code>.
1075  *
1076  * class SimpleSingleton # Not thread safe
1077  * private_class_method :new
1078  * def SimpleSingleton.create(*args, &block)
1079  * @me = new(*args, &block) if ! @me
1080  * @me
1081  * end
1082  * end
1083  */
1084 
1085 static VALUE
1087 {
1088  set_method_visibility(CLASS_OF(obj), argc, argv, NOEX_PRIVATE);
1089  return obj;
1090 }
1091 
1092 /*
1093  * call-seq:
1094  * public
1095  * public(symbol, ...)
1096  *
1097  * With no arguments, sets the default visibility for subsequently
1098  * defined methods to public. With arguments, sets the named methods to
1099  * have public visibility.
1100  */
1101 
1102 static VALUE
1104 {
1105  return rb_mod_public(argc, argv, rb_cObject);
1106 }
1107 
1108 static VALUE
1110 {
1111  return rb_mod_private(argc, argv, rb_cObject);
1112 }
1113 
1114 /*
1115  * call-seq:
1116  * module_function(symbol, ...) -> self
1117  *
1118  * Creates module functions for the named methods. These functions may
1119  * be called with the module as a receiver, and also become available
1120  * as instance methods to classes that mix in the module. Module
1121  * functions are copies of the original, and so may be changed
1122  * independently. The instance-method versions are made private. If
1123  * used with no arguments, subsequently defined methods become module
1124  * functions.
1125  *
1126  * module Mod
1127  * def one
1128  * "This is one"
1129  * end
1130  * module_function :one
1131  * end
1132  * class Cls
1133  * include Mod
1134  * def call_one
1135  * one
1136  * end
1137  * end
1138  * Mod.one #=> "This is one"
1139  * c = Cls.new
1140  * c.call_one #=> "This is one"
1141  * module Mod
1142  * def one
1143  * "This is the new one"
1144  * end
1145  * end
1146  * Mod.one #=> "This is one"
1147  * c.call_one #=> "This is the new one"
1148  */
1149 
1150 static VALUE
1152 {
1153  int i;
1154  ID id;
1155  const rb_method_entry_t *me;
1156 
1157  if (TYPE(module) != T_MODULE) {
1158  rb_raise(rb_eTypeError, "module_function must be called for modules");
1159  }
1160 
1161  secure_visibility(module);
1162  if (argc == 0) {
1164  return module;
1165  }
1166 
1167  set_method_visibility(module, argc, argv, NOEX_PRIVATE);
1168 
1169  for (i = 0; i < argc; i++) {
1170  VALUE m = module;
1171 
1172  id = rb_to_id(argv[i]);
1173  for (;;) {
1174  me = search_method(m, id);
1175  if (me == 0) {
1176  me = search_method(rb_cObject, id);
1177  }
1178  if (UNDEFINED_METHOD_ENTRY_P(me)) {
1179  rb_print_undef(module, id, 0);
1180  }
1181  if (me->def->type != VM_METHOD_TYPE_ZSUPER) {
1182  break; /* normal case: need not to follow 'super' link */
1183  }
1184  m = RCLASS_SUPER(m);
1185  if (!m)
1186  break;
1187  }
1189  }
1190  return module;
1191 }
1192 
1193 int
1195 {
1196  const rb_method_entry_t *me = rb_method_entry(klass, id);
1197  if (me && (me->flag & NOEX_BASIC))
1198  return 1;
1199  return 0;
1200 }
1201 
1202 static inline int
1203 basic_obj_respond_to(VALUE obj, ID id, int pub)
1204 {
1205  VALUE klass = CLASS_OF(obj);
1206 
1207  switch (rb_method_boundp(klass, id, pub|NOEX_RESPONDS)) {
1208  case 2:
1209  return FALSE;
1210  case 0:
1211  return RTEST(rb_funcall(obj, respond_to_missing, 2, ID2SYM(id), pub ? Qfalse : Qtrue));
1212  default:
1213  return TRUE;
1214  }
1215 }
1216 
1217 int
1218 rb_obj_respond_to(VALUE obj, ID id, int priv)
1219 {
1220  VALUE klass = CLASS_OF(obj);
1221 
1223  return basic_obj_respond_to(obj, id, !RTEST(priv));
1224  }
1225  else {
1226  return RTEST(rb_funcall(obj, idRespond_to, priv ? 2 : 1, ID2SYM(id), Qtrue));
1227  }
1228 }
1229 
1230 int
1232 {
1233  return rb_obj_respond_to(obj, id, FALSE);
1234 }
1235 
1236 
1237 /*
1238  * call-seq:
1239  * obj.respond_to?(symbol, include_private=false) -> true or false
1240  *
1241  * Returns +true+ if _obj_ responds to the given
1242  * method. Private methods are included in the search only if the
1243  * optional second parameter evaluates to +true+.
1244  *
1245  * If the method is not implemented,
1246  * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
1247  * false is returned.
1248  *
1249  * If the method is not defined, <code>respond_to_missing?</code>
1250  * method is called and the result is returned.
1251  */
1252 
1253 static VALUE
1255 {
1256  VALUE mid, priv;
1257  ID id;
1258 
1259  rb_scan_args(argc, argv, "11", &mid, &priv);
1260  id = rb_to_id(mid);
1261  if (basic_obj_respond_to(obj, id, !RTEST(priv)))
1262  return Qtrue;
1263  return Qfalse;
1264 }
1265 
1266 /*
1267  * call-seq:
1268  * obj.respond_to_missing?(symbol, include_private) -> true or false
1269  *
1270  * Hook method to return whether the _obj_ can respond to _id_ method
1271  * or not.
1272  *
1273  * See #respond_to?.
1274  */
1275 static VALUE
1277 {
1278  return Qfalse;
1279 }
1280 
1281 void
1283 {
1284 #undef rb_intern
1285 #define rb_intern(str) rb_intern_const(str)
1286 
1287  rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
1288  rb_define_method(rb_mKernel, "respond_to_missing?", obj_respond_to_missing, 2);
1289 
1296  rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
1297 
1298  rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
1299  rb_define_method(rb_cModule, "public_method_defined?", rb_mod_public_method_defined, 1);
1300  rb_define_method(rb_cModule, "private_method_defined?", rb_mod_private_method_defined, 1);
1301  rb_define_method(rb_cModule, "protected_method_defined?", rb_mod_protected_method_defined, 1);
1302  rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
1303  rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
1304 
1307 
1308  object_id = rb_intern("object_id");
1309  added = rb_intern("method_added");
1310  singleton_added = rb_intern("singleton_method_added");
1311  removed = rb_intern("method_removed");
1312  singleton_removed = rb_intern("singleton_method_removed");
1313  undefined = rb_intern("method_undefined");
1314  singleton_undefined = rb_intern("singleton_method_undefined");
1315  attached = rb_intern("__attached__");
1316  respond_to_missing = rb_intern("respond_to_missing?");
1317 }
1318 
1319