Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / third-party / mruby / src / variable.c
1 /*
2 ** variable.c - mruby variables
3 **
4 ** See Copyright Notice in mruby.h
5 */
6
7 #include <mruby.h>
8 #include <mruby/array.h>
9 #include <mruby/class.h>
10 #include <mruby/proc.h>
11 #include <mruby/string.h>
12 #include <mruby/variable.h>
13
14 #ifndef MRB_IV_SEGMENT_SIZE
15 #define MRB_IV_SEGMENT_SIZE 4
16 #endif
17
18 typedef struct segment {
19   mrb_sym key[MRB_IV_SEGMENT_SIZE];
20   mrb_value val[MRB_IV_SEGMENT_SIZE];
21   struct segment *next;
22 } segment;
23
24 /* Instance variable table structure */
25 typedef struct iv_tbl {
26   segment *rootseg;
27   size_t size;
28   size_t last_len;
29 } iv_tbl;
30
31 /* Creates the instance variable table. */
32 static iv_tbl*
33 iv_new(mrb_state *mrb)
34 {
35   iv_tbl *t;
36
37   t = (iv_tbl*)mrb_malloc(mrb, sizeof(iv_tbl));
38   t->size = 0;
39   t->rootseg =  NULL;
40   t->last_len = 0;
41
42   return t;
43 }
44
45 /* Set the value for the symbol in the instance variable table. */
46 static void
47 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
48 {
49   segment *seg;
50   segment *prev = NULL;
51   segment *matched_seg = NULL;
52   size_t matched_idx = 0;
53   size_t i;
54
55   if (t == NULL) return;
56   seg = t->rootseg;
57   while (seg) {
58     for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
59       mrb_sym key = seg->key[i];
60       /* Found room in last segment after last_len */
61       if (!seg->next && i >= t->last_len) {
62         seg->key[i] = sym;
63         seg->val[i] = val;
64         t->last_len = i+1;
65         t->size++;
66         return;
67       }
68       if (!matched_seg && key == 0) {
69         matched_seg = seg;
70         matched_idx = i;
71       }
72       else if (key == sym) {
73         seg->val[i] = val;
74         return;
75       }
76     }
77     prev = seg;
78     seg = seg->next;
79   }
80
81   /* Not found */
82   t->size++;
83   if (matched_seg) {
84     matched_seg->key[matched_idx] = sym;
85     matched_seg->val[matched_idx] = val;
86     return;
87   }
88
89   seg = (segment*)mrb_malloc(mrb, sizeof(segment));
90   if (!seg) return;
91   seg->next = NULL;
92   seg->key[0] = sym;
93   seg->val[0] = val;
94   t->last_len = 1;
95   if (prev) {
96     prev->next = seg;
97   }
98   else {
99     t->rootseg = seg;
100   }
101 }
102
103 /* Get a value for a symbol from the instance variable table. */
104 static mrb_bool
105 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
106 {
107   segment *seg;
108   size_t i;
109
110   if (t == NULL) return FALSE;
111   seg = t->rootseg;
112   while (seg) {
113     for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
114       mrb_sym key = seg->key[i];
115
116       if (!seg->next && i >= t->last_len) {
117         return FALSE;
118       }
119       if (key == sym) {
120         if (vp) *vp = seg->val[i];
121         return TRUE;
122       }
123     }
124     seg = seg->next;
125   }
126   return FALSE;
127 }
128
129 /* Deletes the value for the symbol from the instance variable table. */
130 static mrb_bool
131 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
132 {
133   segment *seg;
134   size_t i;
135
136   if (t == NULL) return FALSE;
137   seg = t->rootseg;
138   while (seg) {
139     for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
140       mrb_sym key = seg->key[i];
141
142       if (!seg->next && i >= t->last_len) {
143         return FALSE;
144       }
145       if (key == sym) {
146         t->size--;
147         seg->key[i] = 0;
148         if (vp) *vp = seg->val[i];
149         return TRUE;
150       }
151     }
152     seg = seg->next;
153   }
154   return FALSE;
155 }
156
157 /* Iterates over the instance variable table. */
158 static void
159 iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p)
160 {
161   segment *seg;
162   size_t i;
163
164   if (t == NULL) return;
165   seg = t->rootseg;
166   while (seg) {
167     for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
168       mrb_sym key = seg->key[i];
169
170       /* no value in last segment after last_len */
171       if (!seg->next && i >= t->last_len) {
172         return;
173       }
174       if (key != 0) {
175         if ((*func)(mrb, key, seg->val[i], p) != 0) {
176           return;
177         }
178       }
179     }
180     seg = seg->next;
181   }
182   return;
183 }
184
185 /* Get the size of the instance variable table. */
186 static size_t
187 iv_size(mrb_state *mrb, iv_tbl *t)
188 {
189   segment *seg;
190   size_t size = 0;
191
192   if (t == NULL) return 0;
193   if (t->size > 0) return t->size;
194   seg = t->rootseg;
195   while (seg) {
196     if (seg->next == NULL) {
197       size += t->last_len;
198       return size;
199     }
200     seg = seg->next;
201     size += MRB_IV_SEGMENT_SIZE;
202   }
203   /* empty iv_tbl */
204   return 0;
205 }
206
207 /* Copy the instance variable table. */
208 static iv_tbl*
209 iv_copy(mrb_state *mrb, iv_tbl *t)
210 {
211   segment *seg;
212   iv_tbl *t2;
213
214   size_t i;
215
216   seg = t->rootseg;
217   t2 = iv_new(mrb);
218
219   while (seg != NULL) {
220     for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) {
221       mrb_sym key = seg->key[i];
222       mrb_value val = seg->val[i];
223
224       if ((seg->next == NULL) && (i >= t->last_len)) {
225         return t2;
226       }
227       iv_put(mrb, t2, key, val);
228     }
229     seg = seg->next;
230   }
231   return t2;
232 }
233
234 /* Free memory of the instance variable table. */
235 static void
236 iv_free(mrb_state *mrb, iv_tbl *t)
237 {
238   segment *seg;
239
240   seg = t->rootseg;
241   while (seg) {
242     segment *p = seg;
243     seg = seg->next;
244     mrb_free(mrb, p);
245   }
246   mrb_free(mrb, t);
247 }
248
249 static int
250 iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
251 {
252   mrb_gc_mark_value(mrb, v);
253   return 0;
254 }
255
256 static void
257 mark_tbl(mrb_state *mrb, iv_tbl *t)
258 {
259   iv_foreach(mrb, t, iv_mark_i, 0);
260 }
261
262 void
263 mrb_gc_mark_gv(mrb_state *mrb)
264 {
265   mark_tbl(mrb, mrb->globals);
266 }
267
268 void
269 mrb_gc_free_gv(mrb_state *mrb)
270 {
271   if (mrb->globals)
272     iv_free(mrb, mrb->globals);
273 }
274
275 void
276 mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj)
277 {
278   mark_tbl(mrb, obj->iv);
279 }
280
281 size_t
282 mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj)
283 {
284   return iv_size(mrb, obj->iv);
285 }
286
287 void
288 mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj)
289 {
290   if (obj->iv) {
291     iv_free(mrb, obj->iv);
292   }
293 }
294
295 mrb_value
296 mrb_vm_special_get(mrb_state *mrb, mrb_sym i)
297 {
298   return mrb_fixnum_value(0);
299 }
300
301 void
302 mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
303 {
304 }
305
306 static mrb_bool
307 obj_iv_p(mrb_value obj)
308 {
309   switch (mrb_type(obj)) {
310     case MRB_TT_OBJECT:
311     case MRB_TT_CLASS:
312     case MRB_TT_MODULE:
313     case MRB_TT_SCLASS:
314     case MRB_TT_HASH:
315     case MRB_TT_DATA:
316     case MRB_TT_EXCEPTION:
317       return TRUE;
318     default:
319       return FALSE;
320   }
321 }
322
323 MRB_API mrb_value
324 mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
325 {
326   mrb_value v;
327
328   if (obj->iv && iv_get(mrb, obj->iv, sym, &v))
329     return v;
330   return mrb_nil_value();
331 }
332
333 MRB_API mrb_value
334 mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
335 {
336   if (obj_iv_p(obj)) {
337     return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
338   }
339   return mrb_nil_value();
340 }
341
342 static inline void assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
343
344 MRB_API void
345 mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
346 {
347   iv_tbl *t;
348
349   if (MRB_FROZEN_P(obj)) {
350     mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
351   }
352   assign_class_name(mrb, obj, sym, v);
353   if (!obj->iv) {
354     obj->iv = iv_new(mrb);
355   }
356   t = obj->iv;
357   iv_put(mrb, t, sym, v);
358   mrb_write_barrier(mrb, (struct RBasic*)obj);
359 }
360
361 /* Iterates over the instance variable table. */
362 MRB_API void
363 mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p)
364 {
365   if (!obj_iv_p(obj)) return;
366   iv_foreach(mrb, mrb_obj_ptr(obj)->iv, func, p);
367 }
368
369 static inline mrb_bool
370 namespace_p(enum mrb_vtype tt)
371 {
372   return tt == MRB_TT_CLASS || tt == MRB_TT_MODULE ? TRUE : FALSE;
373 }
374
375 static inline void
376 assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
377 {
378   if (namespace_p(obj->tt) && namespace_p(mrb_type(v))) {
379     struct RObject *c = mrb_obj_ptr(v);
380     if (obj != c && ISUPPER(mrb_sym2name(mrb, sym)[0])) {
381       mrb_sym id_classname = mrb_intern_lit(mrb, "__classname__");
382       mrb_value o = mrb_obj_iv_get(mrb, c, id_classname);
383
384       if (mrb_nil_p(o)) {
385         mrb_sym id_outer = mrb_intern_lit(mrb, "__outer__");
386         o = mrb_obj_iv_get(mrb, c, id_outer);
387
388         if (mrb_nil_p(o)) {
389           if ((struct RClass *)obj == mrb->object_class) {
390             mrb_obj_iv_set(mrb, c, id_classname, mrb_symbol_value(sym));
391           }
392           else {
393             mrb_obj_iv_set(mrb, c, id_outer, mrb_obj_value(obj));
394           }
395         }
396       }
397     }
398   }
399 }
400
401 MRB_API void
402 mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
403 {
404   if (obj_iv_p(obj)) {
405     mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
406   }
407   else {
408     mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable");
409   }
410 }
411
412 MRB_API mrb_bool
413 mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
414 {
415   iv_tbl *t;
416
417   t = obj->iv;
418   if (t) {
419     return iv_get(mrb, t, sym, NULL);
420   }
421   return FALSE;
422 }
423
424 MRB_API mrb_bool
425 mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
426 {
427   if (!obj_iv_p(obj)) return FALSE;
428   return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
429 }
430
431 MRB_API mrb_bool
432 mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym iv_name)
433 {
434   const char *s;
435   mrb_int len;
436
437   s = mrb_sym2name_len(mrb, iv_name, &len);
438   if (len < 2) return FALSE;
439   if (s[0] != '@') return FALSE;
440   if (ISDIGIT(s[1])) return FALSE;
441   return mrb_ident_p(s+1, len-1);
442 }
443
444 MRB_API void
445 mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym iv_name)
446 {
447   if (!mrb_iv_name_sym_p(mrb, iv_name)) {
448     mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name));
449   }
450 }
451
452 MRB_API void
453 mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
454 {
455   struct RObject *d = mrb_obj_ptr(dest);
456   struct RObject *s = mrb_obj_ptr(src);
457
458   if (d->iv) {
459     iv_free(mrb, d->iv);
460     d->iv = 0;
461   }
462   if (s->iv) {
463     mrb_write_barrier(mrb, (struct RBasic*)d);
464     d->iv = iv_copy(mrb, s->iv);
465   }
466 }
467
468 static int
469 inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
470 {
471   mrb_value str = *(mrb_value*)p;
472   const char *s;
473   mrb_int len;
474   mrb_value ins;
475   char *sp = RSTRING_PTR(str);
476
477   /* need not to show internal data */
478   if (sp[0] == '-') { /* first element */
479     sp[0] = '#';
480     mrb_str_cat_lit(mrb, str, " ");
481   }
482   else {
483     mrb_str_cat_lit(mrb, str, ", ");
484   }
485   s = mrb_sym2name_len(mrb, sym, &len);
486   mrb_str_cat(mrb, str, s, len);
487   mrb_str_cat_lit(mrb, str, "=");
488   if (mrb_type(v) == MRB_TT_OBJECT) {
489     ins = mrb_any_to_s(mrb, v);
490   }
491   else {
492     ins = mrb_inspect(mrb, v);
493   }
494   mrb_str_cat_str(mrb, str, ins);
495   return 0;
496 }
497
498 mrb_value
499 mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
500 {
501   iv_tbl *t = obj->iv;
502   size_t len = iv_size(mrb, t);
503
504   if (len > 0) {
505     const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
506     mrb_value str = mrb_str_new_capa(mrb, 30);
507
508     mrb_str_cat_lit(mrb, str, "-<");
509     mrb_str_cat_cstr(mrb, str, cn);
510     mrb_str_cat_lit(mrb, str, ":");
511     mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
512
513     iv_foreach(mrb, t, inspect_i, &str);
514     mrb_str_cat_lit(mrb, str, ">");
515     return str;
516   }
517   return mrb_any_to_s(mrb, mrb_obj_value(obj));
518 }
519
520 MRB_API mrb_value
521 mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
522 {
523   if (obj_iv_p(obj)) {
524     iv_tbl *t = mrb_obj_ptr(obj)->iv;
525     mrb_value val;
526
527     if (iv_del(mrb, t, sym, &val)) {
528       return val;
529     }
530   }
531   return mrb_undef_value();
532 }
533
534 static int
535 iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
536 {
537   mrb_value ary;
538   const char* s;
539   mrb_int len;
540
541   ary = *(mrb_value*)p;
542   s = mrb_sym2name_len(mrb, sym, &len);
543   if (len > 1 && s[0] == '@' && s[1] != '@') {
544     mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
545   }
546   return 0;
547 }
548
549 /* 15.3.1.3.23 */
550 /*
551  *  call-seq:
552  *     obj.instance_variables    -> array
553  *
554  *  Returns an array of instance variable names for the receiver. Note
555  *  that simply defining an accessor does not create the corresponding
556  *  instance variable.
557  *
558  *     class Fred
559  *       attr_accessor :a1
560  *       def initialize
561  *         @iv = 3
562  *       end
563  *     end
564  *     Fred.new.instance_variables   #=> [:@iv]
565  */
566 mrb_value
567 mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
568 {
569   mrb_value ary;
570
571   ary = mrb_ary_new(mrb);
572   if (obj_iv_p(self)) {
573     iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
574   }
575   return ary;
576 }
577
578 static int
579 cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
580 {
581   mrb_value ary;
582   const char* s;
583   mrb_int len;
584
585   ary = *(mrb_value*)p;
586   s = mrb_sym2name_len(mrb, sym, &len);
587   if (len > 2 && s[0] == '@' && s[1] == '@') {
588     mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
589   }
590   return 0;
591 }
592
593 /* 15.2.2.4.19 */
594 /*
595  *  call-seq:
596  *     mod.class_variables   -> array
597  *
598  *  Returns an array of the names of class variables in <i>mod</i>.
599  *
600  *     class One
601  *       @@var1 = 1
602  *     end
603  *     class Two < One
604  *       @@var2 = 2
605  *     end
606  *     One.class_variables   #=> [:@@var1]
607  *     Two.class_variables   #=> [:@@var2]
608  */
609 mrb_value
610 mrb_mod_class_variables(mrb_state *mrb, mrb_value mod)
611 {
612   mrb_value ary;
613   struct RClass *c;
614
615   ary = mrb_ary_new(mrb);
616   c = mrb_class_ptr(mod);
617   while (c) {
618     iv_foreach(mrb, c->iv, cv_i, &ary);
619     c = c->super;
620   }
621   return ary;
622 }
623
624 mrb_value
625 mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym)
626 {
627   struct RClass * cls = c;
628   mrb_value v;
629   int given = FALSE;
630
631   while (c) {
632     if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
633       given = TRUE;
634     }
635     c = c->super;
636   }
637   if (given) return v;
638   if (cls && cls->tt == MRB_TT_SCLASS) {
639     mrb_value klass;
640
641     klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
642                            mrb_intern_lit(mrb, "__attached__"));
643     c = mrb_class_ptr(klass);
644     if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) {
645       given = FALSE;
646       while (c) {
647         if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
648           given = TRUE;
649         }
650         c = c->super;
651       }
652       if (given) return v;
653     }
654   }
655   mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
656                  mrb_sym2str(mrb, sym), mrb_obj_value(cls));
657   /* not reached */
658   return mrb_nil_value();
659 }
660
661 MRB_API mrb_value
662 mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
663 {
664   return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym);
665 }
666
667 MRB_API void
668 mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
669 {
670   struct RClass * cls = c;
671
672   while (c) {
673     iv_tbl *t = c->iv;
674
675     if (iv_get(mrb, t, sym, NULL)) {
676       iv_put(mrb, t, sym, v);
677       mrb_write_barrier(mrb, (struct RBasic*)c);
678       return;
679     }
680     c = c->super;
681   }
682
683   if (cls && cls->tt == MRB_TT_SCLASS) {
684     mrb_value klass;
685
686     klass = mrb_obj_iv_get(mrb, (struct RObject*)cls,
687                            mrb_intern_lit(mrb, "__attached__"));
688     switch (mrb_type(klass)) {
689     case MRB_TT_CLASS:
690     case MRB_TT_MODULE:
691     case MRB_TT_SCLASS:
692       c = mrb_class_ptr(klass);
693       break;
694     default:
695       c = cls;
696       break;
697     }
698   }
699   else{
700     c = cls;
701   }
702
703   if (!c->iv) {
704     c->iv = iv_new(mrb);
705   }
706
707   iv_put(mrb, c->iv, sym, v);
708   mrb_write_barrier(mrb, (struct RBasic*)c);
709 }
710
711 MRB_API void
712 mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
713 {
714   mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
715 }
716
717 mrb_bool
718 mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
719 {
720   while (c) {
721     iv_tbl *t = c->iv;
722     if (iv_get(mrb, t, sym, NULL)) return TRUE;
723     c = c->super;
724   }
725
726   return FALSE;
727 }
728
729 MRB_API mrb_bool
730 mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
731 {
732   return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
733 }
734
735 mrb_value
736 mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
737 {
738   struct RClass *c;
739
740   c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
741   return mrb_mod_cv_get(mrb, c, sym);
742 }
743
744 void
745 mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
746 {
747   struct RClass *c;
748
749   c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
750   mrb_mod_cv_set(mrb, c, sym, v);
751 }
752
753 static void
754 mod_const_check(mrb_state *mrb, mrb_value mod)
755 {
756   switch (mrb_type(mod)) {
757   case MRB_TT_CLASS:
758   case MRB_TT_MODULE:
759   case MRB_TT_SCLASS:
760     break;
761   default:
762     mrb_raise(mrb, E_TYPE_ERROR, "constant look-up for non class/module");
763     break;
764   }
765 }
766
767 static mrb_value
768 const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
769 {
770   struct RClass *c = base;
771   mrb_value v;
772   mrb_bool retry = FALSE;
773   mrb_value name;
774
775 L_RETRY:
776   while (c) {
777     if (c->iv) {
778       if (iv_get(mrb, c->iv, sym, &v))
779         return v;
780     }
781     c = c->super;
782   }
783   if (!retry && base->tt == MRB_TT_MODULE) {
784     c = mrb->object_class;
785     retry = TRUE;
786     goto L_RETRY;
787   }
788   name = mrb_symbol_value(sym);
789   return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name);
790 }
791
792 MRB_API mrb_value
793 mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
794 {
795   mod_const_check(mrb, mod);
796   return const_get(mrb, mrb_class_ptr(mod), sym);
797 }
798
799 mrb_value
800 mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
801 {
802   struct RClass *c;
803   struct RClass *c2;
804   mrb_value v;
805   struct RProc *proc;
806
807   c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
808   if (iv_get(mrb, c->iv, sym, &v)) {
809     return v;
810   }
811   c2 = c;
812   while (c2 && c2->tt == MRB_TT_SCLASS) {
813     mrb_value klass;
814
815     if (!iv_get(mrb, c2->iv, mrb_intern_lit(mrb, "__attached__"), &klass)) {
816       c2 = NULL;
817       break;
818     }
819     c2 = mrb_class_ptr(klass);
820   }
821   if (c2 && (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE)) c = c2;
822   mrb_assert(!MRB_PROC_CFUNC_P(mrb->c->ci->proc));
823   proc = mrb->c->ci->proc;
824   while (proc) {
825     c2 = MRB_PROC_TARGET_CLASS(proc);
826     if (c2 && iv_get(mrb, c2->iv, sym, &v)) {
827       return v;
828     }
829     proc = proc->upper;
830   }
831   return const_get(mrb, c, sym);
832 }
833
834 MRB_API void
835 mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
836 {
837   mod_const_check(mrb, mod);
838   if (mrb_type(v) == MRB_TT_CLASS || mrb_type(v) == MRB_TT_MODULE) {
839     mrb_class_name_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(v), sym);
840   }
841   mrb_iv_set(mrb, mod, sym, v);
842 }
843
844 void
845 mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
846 {
847   struct RClass *c;
848
849   c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
850   mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
851 }
852
853 MRB_API void
854 mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym)
855 {
856   mod_const_check(mrb, mod);
857   mrb_iv_remove(mrb, mod, sym);
858 }
859
860 MRB_API void
861 mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
862 {
863   mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v);
864 }
865
866 MRB_API void
867 mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
868 {
869   mrb_define_const(mrb, mrb->object_class, name, val);
870 }
871
872 static int
873 const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
874 {
875   mrb_value ary;
876   const char* s;
877   mrb_int len;
878
879   ary = *(mrb_value*)p;
880   s = mrb_sym2name_len(mrb, sym, &len);
881   if (len >= 1 && ISUPPER(s[0])) {
882     mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
883   }
884   return 0;
885 }
886
887 /* 15.2.2.4.24 */
888 /*
889  *  call-seq:
890  *     mod.constants    -> array
891  *
892  *  Returns an array of all names of contants defined in the receiver.
893  */
894 mrb_value
895 mrb_mod_constants(mrb_state *mrb, mrb_value mod)
896 {
897   mrb_value ary;
898   mrb_bool inherit = TRUE;
899   struct RClass *c = mrb_class_ptr(mod);
900
901   mrb_get_args(mrb, "|b", &inherit);
902   ary = mrb_ary_new(mrb);
903   while (c) {
904     iv_foreach(mrb, c->iv, const_i, &ary);
905     if (!inherit) break;
906     c = c->super;
907     if (c == mrb->object_class) break;
908   }
909   return ary;
910 }
911
912 MRB_API mrb_value
913 mrb_gv_get(mrb_state *mrb, mrb_sym sym)
914 {
915   mrb_value v;
916
917   if (iv_get(mrb, mrb->globals, sym, &v))
918     return v;
919   return mrb_nil_value();
920 }
921
922 MRB_API void
923 mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
924 {
925   iv_tbl *t;
926
927   if (!mrb->globals) {
928     mrb->globals = iv_new(mrb);
929   }
930   t = mrb->globals;
931   iv_put(mrb, t, sym, v);
932 }
933
934 MRB_API void
935 mrb_gv_remove(mrb_state *mrb, mrb_sym sym)
936 {
937   iv_del(mrb, mrb->globals, sym, NULL);
938 }
939
940 static int
941 gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
942 {
943   mrb_value ary;
944
945   ary = *(mrb_value*)p;
946   mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
947   return 0;
948 }
949
950 /* 15.3.1.2.4  */
951 /* 15.3.1.3.14 */
952 /*
953  *  call-seq:
954  *     global_variables    -> array
955  *
956  *  Returns an array of the names of global variables.
957  *
958  *     global_variables.grep /std/   #=> [:$stdin, :$stdout, :$stderr]
959  */
960 mrb_value
961 mrb_f_global_variables(mrb_state *mrb, mrb_value self)
962 {
963   iv_tbl *t = mrb->globals;
964   mrb_value ary = mrb_ary_new(mrb);
965   size_t i;
966   char buf[3];
967
968   iv_foreach(mrb, t, gv_i, &ary);
969   buf[0] = '$';
970   buf[2] = 0;
971   for (i = 1; i <= 9; ++i) {
972     buf[1] = (char)(i + '0');
973     mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2)));
974   }
975   return ary;
976 }
977
978 static mrb_bool
979 mrb_const_defined_0(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
980 {
981   struct RClass *klass = mrb_class_ptr(mod);
982   struct RClass *tmp;
983   mrb_bool mod_retry = FALSE;
984
985   tmp = klass;
986 retry:
987   while (tmp) {
988     if (iv_get(mrb, tmp->iv, id, NULL)) {
989       return TRUE;
990     }
991     if (!recurse && (klass != mrb->object_class)) break;
992     tmp = tmp->super;
993   }
994   if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) {
995     mod_retry = TRUE;
996     tmp = mrb->object_class;
997     goto retry;
998   }
999   return FALSE;
1000 }
1001
1002 MRB_API mrb_bool
1003 mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id)
1004 {
1005   return mrb_const_defined_0(mrb, mod, id, TRUE, TRUE);
1006 }
1007
1008 MRB_API mrb_bool
1009 mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id)
1010 {
1011   return mrb_const_defined_0(mrb, mod, id, TRUE, FALSE);
1012 }
1013
1014 MRB_API mrb_value
1015 mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
1016 {
1017   return mrb_iv_get(mrb, obj, id);
1018 }
1019
1020 struct csym_arg {
1021   struct RClass *c;
1022   mrb_sym sym;
1023 };
1024
1025 static int
1026 csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
1027 {
1028   struct csym_arg *a = (struct csym_arg*)p;
1029   struct RClass *c = a->c;
1030
1031   if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
1032     a->sym = sym;
1033     return 1;     /* stop iteration */
1034   }
1035   return 0;
1036 }
1037
1038 static mrb_sym
1039 find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c)
1040 {
1041   struct csym_arg arg;
1042
1043   if (!outer) return 0;
1044   if (outer == c) return 0;
1045   arg.c = c;
1046   arg.sym = 0;
1047   iv_foreach(mrb, outer->iv, csym_i, &arg);
1048   return arg.sym;
1049 }
1050
1051 static struct RClass*
1052 outer_class(mrb_state *mrb, struct RClass *c)
1053 {
1054   mrb_value ov;
1055
1056   ov = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
1057   if (mrb_nil_p(ov)) return NULL;
1058   switch (mrb_type(ov)) {
1059   case MRB_TT_CLASS:
1060   case MRB_TT_MODULE:
1061     return mrb_class_ptr(ov);
1062   default:
1063     break;
1064   }
1065   return NULL;
1066 }
1067
1068 static mrb_bool
1069 detect_outer_loop(mrb_state *mrb, struct RClass *c)
1070 {
1071   struct RClass *t = c;         /* tortoise */
1072   struct RClass *h = c;         /* hare */
1073
1074   for (;;) {
1075     if (h == NULL) return FALSE;
1076     h = outer_class(mrb, h);
1077     if (h == NULL) return FALSE;
1078     h = outer_class(mrb, h);
1079     t = outer_class(mrb, t);
1080     if (t == h) return TRUE;
1081   }
1082 }
1083
1084 mrb_value
1085 mrb_class_find_path(mrb_state *mrb, struct RClass *c)
1086 {
1087   struct RClass *outer;
1088   mrb_value path;
1089   mrb_sym name;
1090   const char *str;
1091   mrb_int len;
1092
1093   if (detect_outer_loop(mrb, c)) return mrb_nil_value();
1094   outer = outer_class(mrb, c);
1095   if (outer == NULL) return mrb_nil_value();
1096   name = find_class_sym(mrb, outer, c);
1097   if (name == 0) return mrb_nil_value();
1098   str = mrb_class_name(mrb, outer);
1099   path = mrb_str_new_capa(mrb, 40);
1100   mrb_str_cat_cstr(mrb, path, str);
1101   mrb_str_cat_cstr(mrb, path, "::");
1102
1103   str = mrb_sym2name_len(mrb, name, &len);
1104   mrb_str_cat(mrb, path, str, len);
1105   if (RSTRING_PTR(path)[0] != '#') {
1106     iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL);
1107     iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
1108     mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
1109   }
1110   return path;
1111 }
1112
1113 #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
1114
1115 mrb_bool
1116 mrb_ident_p(const char *s, mrb_int len)
1117 {
1118   for (mrb_int i = 0; i < len; i++) {
1119     if (!identchar(s[i])) return FALSE;
1120   }
1121   return TRUE;
1122 }