variable.c
DEFINITIONS
This source file includes following functions.
- Init_var_tables
- fc_path
- fc_i
- find_class_path
- classname
- rb_mod_name
- rb_class_path
- rb_set_class_path
- rb_path2class
- rb_name_class
- rb_autoload_id
- rb_autoload
- rb_f_autoload
- rb_class2name
- rb_global_entry
- undef_getter
- undef_setter
- undef_marker
- val_getter
- val_setter
- val_marker
- var_getter
- var_setter
- var_marker
- readonly_setter
- mark_global_entry
- rb_gc_mark_global_tbl
- global_id
- rb_define_hooked_variable
- rb_define_variable
- rb_define_readonly_variable
- rb_define_virtual_variable
- rb_trace_eval
- rb_f_trace_var
- remove_trace
- rb_f_untrace_var
- rb_gvar_get
- trace_ev
- trace_en
- rb_gvar_set
- rb_gv_set
- rb_gv_get
- rb_gvar_defined
- gvar_i
- rb_f_global_variables
- rb_alias_variable
- rb_generic_ivar_table
- generic_ivar_get
- generic_ivar_set
- generic_ivar_defined
- generic_ivar_remove
- rb_mark_generic_ivar
- givar_mark_i
- givar_i
- rb_mark_generic_ivar_tbl
- rb_free_generic_ivar
- rb_copy_generic_ivar
- rb_ivar_get
- rb_ivar_set
- rb_ivar_defined
- ivar_i
- rb_obj_instance_variables
- rb_obj_remove_instance_variable
- top_const_get
- rb_const_get_at
- rb_autoload_load
- rb_const_get
- rb_mod_remove_const
- sv_i
- autoload_i
- rb_mod_const_at
- rb_mod_const_of
- list_i
- rb_const_list
- rb_mod_constants
- rb_const_defined_at
- rb_autoload_defined
- rb_const_defined
- mod_av_set
- rb_const_set
- rb_const_assign
- rb_define_const
- rb_define_global_const
- original_module
- cvar_override_check
- rb_cvar_set
- rb_cvar_get
- rb_cvar_defined
- rb_cv_set
- rb_cv_get
- rb_define_class_variable
- cv_i
- rb_mod_class_variables
- rb_mod_remove_cvar
- rb_iv_get
- rb_iv_set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include "ruby.h"
16 #include "env.h"
17 #include "node.h"
18 #include "st.h"
19 #include "util.h"
20
21 static st_table *rb_global_tbl;
22 st_table *rb_class_tbl;
23
24 void
25 Init_var_tables()
26 {
27 rb_global_tbl = st_init_numtable();
28 rb_class_tbl = st_init_numtable();
29 }
30
31 struct fc_result {
32 ID name;
33 VALUE klass;
34 VALUE path;
35 VALUE track;
36 struct fc_result *prev;
37 };
38
39 static VALUE
40 fc_path(fc, name)
41 struct fc_result *fc;
42 ID name;
43 {
44 VALUE path, tmp;
45
46 path = rb_str_new2(rb_id2name(name));
47 while (fc) {
48 if (fc->track == rb_cObject) break;
49 if (ROBJECT(fc->track)->iv_tbl &&
50 st_lookup(ROBJECT(fc->track)->iv_tbl, rb_intern("__classpath__"), &tmp)) {
51 tmp = rb_str_dup(tmp);
52 rb_str_cat2(tmp, "::");
53 rb_str_append(tmp, path);
54
55 return tmp;
56 }
57 tmp = rb_str_new2(rb_id2name(fc->name));
58 rb_str_cat2(tmp, "::");
59 rb_str_append(tmp, path);
60 path = tmp;
61 fc = fc->prev;
62 }
63 return path;
64 }
65
66 static int
67 fc_i(key, value, res)
68 ID key;
69 VALUE value;
70 struct fc_result *res;
71 {
72 if (!rb_is_const_id(key)) return ST_CONTINUE;
73
74 if (value == res->klass) {
75 res->path = fc_path(res, key);
76 return ST_STOP;
77 }
78 switch (TYPE(value)) {
79 case T_MODULE:
80 case T_CLASS:
81 if (!RCLASS(value)->iv_tbl) return ST_CONTINUE;
82 else {
83 struct fc_result arg;
84 struct fc_result *list;
85
86 list = res;
87 while (list) {
88 if (list->track == value) return ST_CONTINUE;
89 list = list->prev;
90 }
91
92 arg.name = key;
93 arg.path = 0;
94 arg.klass = res->klass;
95 arg.track = value;
96 arg.prev = res;
97 st_foreach(RCLASS(value)->iv_tbl, fc_i, &arg);
98 if (arg.path) {
99 res->path = arg.path;
100 return ST_STOP;
101 }
102 }
103 break;
104
105 default:
106 break;
107
108 }
109 return ST_CONTINUE;
110 }
111
112 static VALUE
113 find_class_path(klass)
114 VALUE klass;
115 {
116 struct fc_result arg;
117
118 arg.name = 0;
119 arg.path = 0;
120 arg.klass = klass;
121 arg.track = rb_cObject;
122 arg.prev = 0;
123 if (RCLASS(rb_cObject)->iv_tbl) {
124 st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg);
125 }
126 if (arg.path == 0) {
127 st_foreach(rb_class_tbl, fc_i, &arg);
128 }
129 if (arg.path) {
130 if (!ROBJECT(klass)->iv_tbl) {
131 ROBJECT(klass)->iv_tbl = st_init_numtable();
132 }
133 st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path);
134 return arg.path;
135 }
136 return Qnil;
137 }
138
139 static VALUE
140 classname(klass)
141 VALUE klass;
142 {
143 VALUE path = Qnil;
144 ID classpath = rb_intern("__classpath__");
145
146 if (TYPE(klass) == T_ICLASS) {
147 klass = RBASIC(klass)->klass;
148 }
149 klass = rb_class_real(klass);
150 if (!klass) klass = rb_cObject;
151 if (ROBJECT(klass)->iv_tbl &&
152 !st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
153 ID classid = rb_intern("__classid__");
154
155 if (st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
156 path = rb_str_new2(rb_id2name(SYM2ID(path)));
157 st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
158 st_delete(RCLASS(klass)->iv_tbl, &classid, 0);
159 }
160 }
161 if (NIL_P(path)) {
162 path = find_class_path(klass);
163 if (NIL_P(path)) {
164 return 0;
165 }
166 return path;
167 }
168 if (TYPE(path) != T_STRING)
169 rb_bug("class path is not set properly");
170 return path;
171 }
172
173 VALUE
174 rb_mod_name(mod)
175 VALUE mod;
176 {
177 VALUE path = classname(mod);
178
179 if (path) return rb_str_dup(path);
180 return rb_str_new(0,0);
181 }
182
183 VALUE
184 rb_class_path(klass)
185 VALUE klass;
186 {
187 VALUE path = classname(klass);
188
189 if (path) return path;
190 else {
191 VALUE str;
192 char *s = "Class";
193
194 if (TYPE(klass) == T_MODULE) {
195 if (rb_obj_class(klass) == rb_cModule) {
196 s = "Module";
197 }
198 else {
199 s = rb_class2name(RBASIC(klass)->klass);
200 }
201 }
202 str = rb_str_new(0, 2 + strlen(s) + 3 + 2 * SIZEOF_LONG + 1);
203 sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", s, klass);
204 RSTRING(str)->len = strlen(RSTRING(str)->ptr);
205
206 return str;
207 }
208 }
209
210 void
211 rb_set_class_path(klass, under, name)
212 VALUE klass, under;
213 const char *name;
214 {
215 VALUE str;
216
217 if (under == rb_cObject) {
218 str = rb_str_new2(name);
219 }
220 else {
221 str = rb_str_dup(rb_class_path(under));
222 rb_str_cat2(str, "::");
223 rb_str_cat2(str, name);
224 }
225 rb_iv_set(klass, "__classpath__", str);
226 }
227
228 VALUE
229 rb_path2class(path)
230 const char *path;
231 {
232 const char *pbeg, *p;
233 ID id;
234 VALUE c = rb_cObject;
235
236 if (path[0] == '#') {
237 rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
238 }
239 pbeg = p = path;
240 while (*p) {
241 VALUE str;
242
243 while (*p && *p != ':') p++;
244 str = rb_str_new(pbeg, p-pbeg);
245 id = rb_intern(RSTRING(str)->ptr);
246 if (p[0] == ':') {
247 if (p[1] != ':') goto undefined_class;
248 p += 2;
249 pbeg = p;
250 }
251 if (!rb_const_defined(c, id)) {
252 undefined_class:
253 rb_raise(rb_eArgError, "undefined class/module %s", rb_id2name(id));
254 rb_raise(rb_eArgError, "undefined class/module %s", path);
255 }
256 c = rb_const_get_at(c, id);
257 switch (TYPE(c)) {
258 case T_MODULE:
259 case T_CLASS:
260 break;
261 default:
262 rb_raise(rb_eTypeError, "%s does not refer class/module %d", path, TYPE(c));
263 }
264 }
265
266 return c;
267 }
268
269 void
270 rb_name_class(klass, id)
271 VALUE klass;
272 ID id;
273 {
274 rb_iv_set(klass, "__classid__", ID2SYM(id));
275 }
276
277 static st_table *autoload_tbl = 0;
278
279 static void
280 rb_autoload_id(id, filename)
281 ID id;
282 const char *filename;
283 {
284 rb_secure(4);
285 if (!rb_is_const_id(id)) {
286 rb_name_error(id, "autoload must be constant name");
287 }
288
289 if (!autoload_tbl) {
290 autoload_tbl = st_init_numtable();
291 }
292 st_insert(autoload_tbl, id, strdup(filename));
293 }
294
295 void
296 rb_autoload(klass, filename)
297 const char *klass, *filename;
298 {
299 rb_autoload_id(rb_intern(klass), filename);
300 }
301
302 VALUE
303 rb_f_autoload(obj, klass, file)
304 VALUE obj, klass, file;
305 {
306 rb_autoload_id(rb_to_id(klass), StringValuePtr(file));
307 return Qnil;
308 }
309
310 char *
311 rb_class2name(klass)
312 VALUE klass;
313 {
314 return RSTRING(rb_class_path(klass))->ptr;
315 }
316
317 struct trace_var {
318 int removed;
319 void (*func)();
320 VALUE data;
321 struct trace_var *next;
322 };
323
324 struct global_variable {
325 int counter;
326 void *data;
327 VALUE (*getter)();
328 void (*setter)();
329 void (*marker)();
330 int block_trace;
331 struct trace_var *trace;
332 };
333
334 struct global_entry {
335 struct global_variable *var;
336 ID id;
337 };
338
339 static VALUE undef_getter();
340 static void undef_setter();
341 static void undef_marker();
342
343 static VALUE val_getter();
344 static void val_setter();
345 static void val_marker();
346
347 static VALUE var_getter();
348 static void var_setter();
349 static void var_marker();
350
351 struct global_entry*
352 rb_global_entry(id)
353 ID id;
354 {
355 struct global_entry *entry;
356
357 if (!st_lookup(rb_global_tbl, id, &entry)) {
358 struct global_variable *var;
359 entry = ALLOC(struct global_entry);
360 st_add_direct(rb_global_tbl, id, entry);
361 var = ALLOC(struct global_variable);
362 entry->id = id;
363 entry->var = var;
364 var->counter = 1;
365 var->data = 0;
366 var->getter = undef_getter;
367 var->setter = undef_setter;
368 var->marker = undef_marker;
369
370 var->block_trace = 0;
371 var->trace = 0;
372 }
373 return entry;
374 }
375
376 static VALUE
377 undef_getter(id)
378 ID id;
379 {
380 rb_warning("global variable `%s' not initialized", rb_id2name(id));
381
382 return Qnil;
383 }
384
385 static void
386 undef_setter(val, id, data, var)
387 VALUE val;
388 ID id;
389 void *data;
390 struct global_variable *var;
391 {
392 var->getter = val_getter;
393 var->setter = val_setter;
394 var->marker = val_marker;
395
396 var->data = (void*)val;
397 }
398
399 static void
400 undef_marker()
401 {
402 }
403
404 static VALUE
405 val_getter(id, val)
406 ID id;
407 VALUE val;
408 {
409 return val;
410 }
411
412 static void
413 val_setter(val, id, data, var)
414 VALUE val;
415 ID id;
416 void *data;
417 struct global_variable *var;
418 {
419 var->data = (void*)val;
420 }
421
422 static void
423 val_marker(data)
424 VALUE data;
425 {
426 if (data) rb_gc_mark_maybe(data);
427 }
428
429 static VALUE
430 var_getter(id, var)
431 ID id;
432 VALUE *var;
433 {
434 if (!var) return Qnil;
435 return *var;
436 }
437
438 static void
439 var_setter(val, id, var)
440 VALUE val;
441 ID id;
442 VALUE *var;
443 {
444 *var = val;
445 }
446
447 static void
448 var_marker(var)
449 VALUE *var;
450 {
451 if (var) rb_gc_mark_maybe(*var);
452 }
453
454 static void
455 readonly_setter(val, id, var)
456 VALUE val;
457 ID id;
458 void *var;
459 {
460 rb_name_error(id, "can't set variable %s", rb_id2name(id));
461 }
462
463 static int
464 mark_global_entry(key, entry)
465 ID key;
466 struct global_entry *entry;
467 {
468 struct trace_var *trace;
469 struct global_variable *var = entry->var;
470
471 (*var->marker)(var->data);
472 trace = var->trace;
473 while (trace) {
474 if (trace->data) rb_gc_mark_maybe(trace->data);
475 trace = trace->next;
476 }
477 return ST_CONTINUE;
478 }
479
480 void
481 rb_gc_mark_global_tbl()
482 {
483 st_foreach(rb_global_tbl, mark_global_entry, 0);
484 }
485
486 static ID
487 global_id(name)
488 const char *name;
489 {
490 ID id;
491
492 if (name[0] == '$') id = rb_intern(name);
493 else {
494 char *buf = ALLOCA_N(char, strlen(name)+2);
495 buf[0] = '$';
496 strcpy(buf+1, name);
497 id = rb_intern(buf);
498 }
499 return id;
500 }
501
502 void
503 rb_define_hooked_variable(name, var, getter, setter)
504 const char *name;
505 VALUE *var;
506 VALUE (*getter)();
507 void (*setter)();
508 {
509 struct global_variable *gvar;
510 ID id = global_id(name);
511
512 gvar = rb_global_entry(id)->var;
513 gvar->data = (void*)var;
514 gvar->getter = getter?getter:var_getter;
515 gvar->setter = setter?setter:var_setter;
516 gvar->marker = var_marker;
517 }
518
519 void
520 rb_define_variable(name, var)
521 const char *name;
522 VALUE *var;
523 {
524 rb_define_hooked_variable(name, var, 0, 0);
525 }
526
527 void
528 rb_define_readonly_variable(name, var)
529 const char *name;
530 VALUE *var;
531 {
532 rb_define_hooked_variable(name, var, 0, readonly_setter);
533 }
534
535 void
536 rb_define_virtual_variable(name, getter, setter)
537 const char *name;
538 VALUE (*getter)();
539 void (*setter)();
540 {
541 if (!getter) getter = val_getter;
542 if (!setter) setter = readonly_setter;
543 rb_define_hooked_variable(name, 0, getter, setter);
544 }
545
546 static void
547 rb_trace_eval(cmd, val)
548 VALUE cmd, val;
549 {
550 rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
551 }
552
553 VALUE
554 rb_f_trace_var(argc, argv)
555 int argc;
556 VALUE *argv;
557 {
558 VALUE var, cmd;
559 struct global_entry *entry;
560 struct trace_var *trace;
561
562 rb_secure(4);
563 if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
564 cmd = rb_f_lambda();
565 }
566 if (NIL_P(cmd)) {
567 return rb_f_untrace_var(argc, argv);
568 }
569 entry = rb_global_entry(rb_to_id(var));
570 if (OBJ_TAINTED(cmd)) {
571 rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
572 }
573 trace = ALLOC(struct trace_var);
574 trace->next = entry->var->trace;
575 trace->func = rb_trace_eval;
576 trace->data = cmd;
577 trace->removed = 0;
578 entry->var->trace = trace;
579
580 return Qnil;
581 }
582
583 static void
584 remove_trace(var)
585 struct global_variable *var;
586 {
587 struct trace_var *trace = var->trace;
588 struct trace_var t;
589 struct trace_var *next;
590
591 t.next = trace;
592 trace = &t;
593 while (trace->next) {
594 next = trace->next;
595 if (next->removed) {
596 trace->next = next->next;
597 free(next);
598 }
599 else {
600 trace = next;
601 }
602 }
603 var->trace = t.next;
604 }
605
606 VALUE
607 rb_f_untrace_var(argc, argv)
608 int argc;
609 VALUE *argv;
610 {
611 VALUE var, cmd;
612 ID id;
613 struct global_entry *entry;
614 struct trace_var *trace;
615
616 rb_scan_args(argc, argv, "11", &var, &cmd);
617 id = rb_to_id(var);
618 if (!st_lookup(rb_global_tbl, id, &entry)) {
619 rb_name_error(id, "undefined global variable %s", rb_id2name(id));
620 }
621
622 trace = entry->var->trace;
623 if (NIL_P(cmd)) {
624 VALUE ary = rb_ary_new();
625
626 while (trace) {
627 struct trace_var *next = trace->next;
628 rb_ary_push(ary, (VALUE)trace->data);
629 trace->removed = 1;
630 trace = next;
631 }
632
633 if (!entry->var->block_trace) remove_trace(entry->var);
634 return ary;
635 }
636 else {
637 while (trace) {
638 if (trace->data == cmd) {
639 trace->removed = 1;
640 if (!entry->var->block_trace) remove_trace(entry->var);
641 return rb_ary_new3(1, cmd);
642 }
643 trace = trace->next;
644 }
645 }
646 return Qnil;
647 }
648
649 VALUE
650 rb_gvar_get(entry)
651 struct global_entry *entry;
652 {
653 struct global_variable *var = entry->var;
654 return (*var->getter)(entry->id, var->data, var);
655 }
656
657 struct trace_data {
658 struct trace_var *trace;
659 VALUE val;
660 };
661
662 static VALUE
663 trace_ev(data)
664 struct trace_data *data;
665 {
666 struct trace_var *trace = data->trace;
667
668 while (trace) {
669 (*trace->func)(trace->data, data->val);
670 trace = trace->next;
671 }
672 return Qnil;
673 }
674
675 static VALUE
676 trace_en(var)
677 struct global_variable *var;
678 {
679 var->block_trace = 0;
680 remove_trace(var);
681 return Qnil;
682 }
683
684 VALUE
685 rb_gvar_set(entry, val)
686 struct global_entry *entry;
687 VALUE val;
688 {
689 struct trace_data trace;
690 struct global_variable *var = entry->var;
691
692 if (rb_safe_level() >= 4)
693 rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
694 (*var->setter)(val, entry->id, var->data, var);
695
696 if (var->trace && !var->block_trace) {
697 var->block_trace = 1;
698 trace.trace = var->trace;
699 trace.val = val;
700 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
701 }
702 return val;
703 }
704
705 VALUE
706 rb_gv_set(name, val)
707 const char *name;
708 VALUE val;
709 {
710 struct global_entry *entry;
711
712 entry = rb_global_entry(global_id(name));
713 return rb_gvar_set(entry, val);
714 }
715
716 VALUE
717 rb_gv_get(name)
718 const char *name;
719 {
720 struct global_entry *entry;
721
722 entry = rb_global_entry(global_id(name));
723 return rb_gvar_get(entry);
724 }
725
726 VALUE
727 rb_gvar_defined(entry)
728 struct global_entry *entry;
729 {
730 if (entry->var->getter == undef_getter) return Qfalse;
731 return Qtrue;
732 }
733
734 static int
735 gvar_i(key, entry, ary)
736 ID key;
737 struct global_entry *entry;
738 VALUE ary;
739 {
740 rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
741 return ST_CONTINUE;
742 }
743
744 VALUE
745 rb_f_global_variables()
746 {
747 VALUE ary = rb_ary_new();
748 char buf[4];
749 char *s = "&`'+123456789";
750
751 st_foreach(rb_global_tbl, gvar_i, ary);
752 if (!NIL_P(rb_backref_get())) {
753 while (*s) {
754 sprintf(buf, "$%c", *s++);
755 rb_ary_push(ary, rb_str_new2(buf));
756 }
757 }
758 return ary;
759 }
760
761 void
762 rb_alias_variable(name1, name2)
763 ID name1;
764 ID name2;
765 {
766 struct global_entry *entry1, *entry2;
767
768 if (rb_safe_level() >= 4)
769 rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
770
771 entry2 = rb_global_entry(name2);
772 if (!st_lookup(rb_global_tbl, name1, &entry1)) {
773 entry1 = ALLOC(struct global_entry);
774 st_add_direct(rb_global_tbl, name1, entry1);
775 entry1->id = name1;
776 }
777 else if (entry1->var != entry2->var) {
778 struct global_variable *var = entry1->var;
779 if (var->block_trace) {
780 rb_raise(rb_eRuntimeError, "can't alias in tracer");
781 }
782 var->counter--;
783 if (var->counter == 0) {
784 struct trace_var *trace = var->trace;
785 while (trace) {
786 struct trace_var *next = trace->next;
787 free(trace);
788 trace = next;
789 }
790 free(var);
791 }
792 }
793 else {
794 return;
795 }
796 entry2->var->counter++;
797 entry1->var = entry2->var;
798 }
799
800 static int special_generic_ivar = 0;
801 static st_table *generic_iv_tbl;
802
803 st_table*
804 rb_generic_ivar_table(obj)
805 VALUE obj;
806 {
807 st_table *tbl;
808
809 if (!generic_iv_tbl) return 0;
810 if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
811 return tbl;
812 }
813
814 static VALUE
815 generic_ivar_get(obj, id)
816 VALUE obj;
817 ID id;
818 {
819 st_table *tbl;
820 VALUE val;
821
822 if (!generic_iv_tbl) return Qnil;
823 if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil;
824 if (st_lookup(tbl, id, &val)) {
825 return val;
826 }
827 return Qnil;
828 }
829
830 static void
831 generic_ivar_set(obj, id, val)
832 VALUE obj;
833 ID id;
834 VALUE val;
835 {
836 st_table *tbl;
837
838 if (rb_special_const_p(obj)) {
839 special_generic_ivar = 1;
840 }
841 if (!generic_iv_tbl) {
842 generic_iv_tbl = st_init_numtable();
843 }
844
845 if (!st_lookup(generic_iv_tbl, obj, &tbl)) {
846 FL_SET(obj, FL_EXIVAR);
847 tbl = st_init_numtable();
848 st_add_direct(generic_iv_tbl, obj, tbl);
849 st_add_direct(tbl, id, val);
850 return;
851 }
852 st_insert(tbl, id, val);
853 }
854
855 static VALUE
856 generic_ivar_defined(obj, id)
857 VALUE obj;
858 ID id;
859 {
860 st_table *tbl;
861 VALUE val;
862
863 if (!generic_iv_tbl) return Qfalse;
864 if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qfalse;
865 if (st_lookup(tbl, id, &val)) {
866 return Qtrue;
867 }
868 return Qfalse;
869 }
870
871 static int
872 generic_ivar_remove(obj, id, valp)
873 VALUE obj;
874 ID id;
875 VALUE *valp;
876 {
877 st_table *tbl;
878 int status;
879
880 if (!generic_iv_tbl) return 0;
881 if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
882 status = st_delete(tbl, &id, valp);
883 if (tbl->num_entries == 0) {
884 st_delete(generic_iv_tbl, &obj, &tbl);
885 st_free_table(tbl);
886 }
887 return status;
888 }
889
890 void
891 rb_mark_generic_ivar(obj)
892 VALUE obj;
893 {
894 st_table *tbl;
895
896 if (!generic_iv_tbl) return;
897 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
898 rb_mark_tbl(tbl);
899 }
900 }
901
902 static int
903 givar_mark_i(key, value)
904 ID key;
905 VALUE value;
906 {
907 rb_gc_mark(value);
908 return ST_CONTINUE;
909 }
910
911 static int
912 givar_i(obj, tbl)
913 VALUE obj;
914 st_table *tbl;
915 {
916 if (rb_special_const_p(obj)) {
917 st_foreach(tbl, givar_mark_i, 0);
918 }
919 return ST_CONTINUE;
920 }
921
922 void
923 rb_mark_generic_ivar_tbl()
924 {
925 if (!generic_iv_tbl) return;
926 if (special_generic_ivar == 0) return;
927 st_foreach(generic_iv_tbl, givar_i, 0);
928 }
929
930 void
931 rb_free_generic_ivar(obj)
932 VALUE obj;
933 {
934 st_table *tbl;
935
936 if (st_delete(generic_iv_tbl, &obj, &tbl))
937 st_free_table(tbl);
938 }
939
940 void
941 rb_copy_generic_ivar(clone, obj)
942 VALUE clone, obj;
943 {
944 st_table *tbl;
945
946 if (!generic_iv_tbl) return;
947 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
948 st_table *old;
949
950 if (st_lookup(generic_iv_tbl, clone, &old)) {
951 st_free_table(old);
952 st_insert(generic_iv_tbl, clone, st_copy(tbl));
953 }
954 else {
955 st_add_direct(generic_iv_tbl, clone, st_copy(tbl));
956 }
957 }
958 }
959
960 VALUE
961 rb_ivar_get(obj, id)
962 VALUE obj;
963 ID id;
964 {
965 VALUE val;
966
967 switch (TYPE(obj)) {
968 case T_OBJECT:
969 case T_CLASS:
970 case T_MODULE:
971 if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
972 return val;
973 break;
974 default:
975 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
976 return generic_ivar_get(obj, id);
977 break;
978 }
979 rb_warning("instance variable %s not initialized", rb_id2name(id));
980
981 return Qnil;
982 }
983
984 VALUE
985 rb_ivar_set(obj, id, val)
986 VALUE obj;
987 ID id;
988 VALUE val;
989 {
990 if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
991 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
992 if (OBJ_FROZEN(obj)) rb_error_frozen("object");
993 switch (TYPE(obj)) {
994 case T_OBJECT:
995 case T_CLASS:
996 case T_MODULE:
997 if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
998 st_insert(ROBJECT(obj)->iv_tbl, id, val);
999 break;
1000 default:
1001 generic_ivar_set(obj, id, val);
1002 break;
1003 }
1004 return val;
1005 }
1006
1007 VALUE
1008 rb_ivar_defined(obj, id)
1009 VALUE obj;
1010 ID id;
1011 {
1012 switch (TYPE(obj)) {
1013 case T_OBJECT:
1014 case T_CLASS:
1015 case T_MODULE:
1016 if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
1017 return Qtrue;
1018 break;
1019 default:
1020 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
1021 return generic_ivar_defined(obj, id);
1022 break;
1023 }
1024 return Qfalse;
1025 }
1026
1027 static int
1028 ivar_i(key, entry, ary)
1029 ID key;
1030 struct global_entry *entry;
1031 VALUE ary;
1032 {
1033 if (rb_is_instance_id(key)) {
1034 rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
1035 }
1036 return ST_CONTINUE;
1037 }
1038
1039 VALUE
1040 rb_obj_instance_variables(obj)
1041 VALUE obj;
1042 {
1043 VALUE ary;
1044
1045 ary = rb_ary_new();
1046 switch (TYPE(obj)) {
1047 case T_OBJECT:
1048 case T_CLASS:
1049 case T_MODULE:
1050 if (ROBJECT(obj)->iv_tbl) {
1051 st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary);
1052 }
1053 break;
1054 default:
1055 if (!generic_iv_tbl) break;
1056 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1057 st_table *tbl;
1058
1059 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
1060 st_foreach(tbl, ivar_i, ary);
1061 }
1062 }
1063 break;
1064 }
1065 return ary;
1066 }
1067
1068 VALUE
1069 rb_obj_remove_instance_variable(obj, name)
1070 VALUE obj, name;
1071 {
1072 VALUE val = Qnil;
1073 ID id = rb_to_id(name);
1074
1075 if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
1076 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
1077 if (OBJ_FROZEN(obj)) rb_error_frozen("object");
1078 if (!rb_is_instance_id(id)) {
1079 rb_name_error(id, "`%s' is not an instance variable", rb_id2name(id));
1080 }
1081
1082 switch (TYPE(obj)) {
1083 case T_OBJECT:
1084 case T_CLASS:
1085 case T_MODULE:
1086 if (ROBJECT(obj)->iv_tbl && st_delete(ROBJECT(obj)->iv_tbl, &id, &val)) {
1087 return val;
1088 }
1089 break;
1090 default:
1091 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1092 if (generic_ivar_remove(obj, id, &val)) {
1093 return val;
1094 }
1095 }
1096 break;
1097 }
1098 rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
1099 return Qnil;
1100 }
1101
1102 static int
1103 top_const_get(id, klassp)
1104 ID id;
1105 VALUE *klassp;
1106 {
1107
1108 if (st_lookup(rb_class_tbl, id, klassp)) return Qtrue;
1109
1110
1111 if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
1112 rb_autoload_load(id);
1113 *klassp = rb_const_get(rb_cObject, id);
1114 return Qtrue;
1115 }
1116 return Qfalse;
1117 }
1118
1119 VALUE
1120 rb_const_get_at(klass, id)
1121 VALUE klass;
1122 ID id;
1123 {
1124 VALUE value;
1125
1126 if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
1127 return value;
1128 }
1129 if (klass == rb_cObject && top_const_get(id, &value)) {
1130 return value;
1131 }
1132 rb_name_error(id, "uninitialized constant %s::%s",
1133 RSTRING(rb_class_path(klass))->ptr,
1134 rb_id2name(id));
1135 return Qnil;
1136 }
1137
1138 void
1139 rb_autoload_load(id)
1140 ID id;
1141 {
1142 char *modname;
1143 VALUE module;
1144
1145 st_delete(autoload_tbl, &id, &modname);
1146 if (rb_provided(modname)) {
1147 free(modname);
1148 return;
1149 }
1150 module = rb_str_new2(modname);
1151 free(modname);
1152 FL_UNSET(module, FL_TAINT);
1153 rb_f_require(Qnil, module);
1154 }
1155
1156 VALUE
1157 rb_const_get(klass, id)
1158 VALUE klass;
1159 ID id;
1160 {
1161 VALUE value, tmp;
1162 int mod_retry = 0;
1163
1164 tmp = klass;
1165 retry:
1166 while (tmp) {
1167 if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
1168 return value;
1169 }
1170 if (tmp == rb_cObject && top_const_get(id, &value)) return value;
1171 tmp = RCLASS(tmp)->super;
1172 }
1173 if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
1174 mod_retry = 1;
1175 tmp = rb_cObject;
1176 goto retry;
1177 }
1178
1179
1180 if (klass && klass != rb_cObject) {
1181 rb_name_error(id, "uninitialized constant %s at %s",
1182 rb_id2name(id),
1183 RSTRING(rb_class_path(klass))->ptr);
1184 }
1185 else {
1186 rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
1187 }
1188 return Qnil;
1189 }
1190
1191 VALUE
1192 rb_mod_remove_const(mod, name)
1193 VALUE mod, name;
1194 {
1195 ID id = rb_to_id(name);
1196 VALUE val;
1197
1198 if (!rb_is_const_id(id)) {
1199 rb_name_error(id, "`%s' is not constant", rb_id2name(id));
1200 }
1201 if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
1202 rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
1203 if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1204
1205 if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
1206 return val;
1207 }
1208 if (rb_const_defined_at(mod, id)) {
1209 rb_name_error(id, "cannot remove %s::%s",
1210 rb_class2name(mod), rb_id2name(id));
1211 }
1212 rb_name_error(id, "constant %s::%s not defined",
1213 rb_class2name(mod), rb_id2name(id));
1214 return Qnil;
1215 }
1216
1217 static int
1218 sv_i(key, value, tbl)
1219 ID key;
1220 VALUE value;
1221 st_table *tbl;
1222 {
1223 if (rb_is_const_id(key)) {
1224 if (!st_lookup(tbl, key, 0)) {
1225 st_insert(tbl, key, key);
1226 }
1227 }
1228 return ST_CONTINUE;
1229 }
1230
1231 static int
1232 autoload_i(key, name, tbl)
1233 ID key;
1234 const char *name;
1235 st_table *tbl;
1236 {
1237 if (!st_lookup(tbl, key, 0)) {
1238 st_insert(tbl, key, key);
1239 }
1240 return ST_CONTINUE;
1241 }
1242
1243 void*
1244 rb_mod_const_at(mod, data)
1245 VALUE mod;
1246 void *data;
1247 {
1248 st_table *tbl = data;
1249 if (!tbl) {
1250 tbl = st_init_numtable();
1251 }
1252 if (RCLASS(mod)->iv_tbl) {
1253 st_foreach(RCLASS(mod)->iv_tbl, sv_i, tbl);
1254 }
1255 if ((VALUE)mod == rb_cObject) {
1256 st_foreach(rb_class_tbl, sv_i, tbl);
1257 if (autoload_tbl) {
1258 st_foreach(autoload_tbl, autoload_i, tbl);
1259 }
1260 }
1261 return tbl;
1262 }
1263
1264 void*
1265 rb_mod_const_of(mod, data)
1266 VALUE mod;
1267 void *data;
1268 {
1269 for (;;) {
1270 data = rb_mod_const_at(mod, data);
1271 mod = RCLASS(mod)->super;
1272 if (!mod) break;
1273 }
1274 return data;
1275 }
1276
1277 static int
1278 list_i(key, value, ary)
1279 ID key, value;
1280 VALUE ary;
1281 {
1282 rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
1283 return ST_CONTINUE;
1284 }
1285
1286 VALUE
1287 rb_const_list(data)
1288 void *data;
1289 {
1290 st_table *tbl = data;
1291 VALUE ary;
1292
1293 if (!tbl) return rb_ary_new2(0);
1294 ary = rb_ary_new2(tbl->num_entries);
1295 st_foreach(tbl, list_i, ary);
1296 st_free_table(tbl);
1297
1298 return ary;
1299 }
1300
1301 VALUE
1302 rb_mod_constants(mod)
1303 VALUE mod;
1304 {
1305 return rb_const_list(rb_mod_const_of(mod, 0));
1306 }
1307
1308 int
1309 rb_const_defined_at(klass, id)
1310 VALUE klass;
1311 ID id;
1312 {
1313 if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
1314 return Qtrue;
1315 }
1316 if (klass == rb_cObject) {
1317 return rb_const_defined(klass, id);
1318 }
1319 return Qfalse;
1320 }
1321
1322 int
1323 rb_autoload_defined(id)
1324 ID id;
1325 {
1326 if (autoload_tbl && st_lookup(autoload_tbl, id, 0))
1327 return Qtrue;
1328 return Qfalse;
1329 }
1330
1331 int
1332 rb_const_defined(klass, id)
1333 VALUE klass;
1334 ID id;
1335 {
1336 VALUE tmp = klass;
1337
1338 while (tmp) {
1339 if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1340 return Qtrue;
1341 }
1342 tmp = RCLASS(tmp)->super;
1343 }
1344 if (BUILTIN_TYPE(klass) == T_MODULE) {
1345 return rb_const_defined(rb_cObject, id);
1346 }
1347 if (st_lookup(rb_class_tbl, id, 0))
1348 return Qtrue;
1349 return rb_autoload_defined(id);
1350 }
1351
1352 static void
1353 mod_av_set(klass, id, val, isconst)
1354 VALUE klass;
1355 ID id;
1356 VALUE val;
1357 int isconst;
1358 {
1359 char *dest = isconst ? "constant" : "class variable";
1360
1361 if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
1362 rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
1363 if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
1364 if (!RCLASS(klass)->iv_tbl) {
1365 RCLASS(klass)->iv_tbl = st_init_numtable();
1366 }
1367 else if (isconst) {
1368 if (st_lookup(RCLASS(klass)->iv_tbl, id, 0) ||
1369 (klass == rb_cObject && st_lookup(rb_class_tbl, id, 0))) {
1370 rb_warn("already initialized %s %s", dest, rb_id2name(id));
1371 }
1372 }
1373
1374 st_insert(RCLASS(klass)->iv_tbl, id, val);
1375 }
1376
1377 void
1378 rb_const_set(klass, id, val)
1379 VALUE klass;
1380 ID id;
1381 VALUE val;
1382 {
1383 mod_av_set(klass, id, val, Qtrue);
1384 }
1385
1386 void
1387 rb_const_assign(klass, id, val)
1388 VALUE klass;
1389 ID id;
1390 VALUE val;
1391 {
1392 VALUE tmp = klass;
1393
1394 while (tmp) {
1395 if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1396 st_insert(RCLASS(tmp)->iv_tbl, id, val);
1397 return;
1398 }
1399 tmp = RCLASS(tmp)->super;
1400 }
1401
1402 if (st_lookup(rb_class_tbl, id, 0)) {
1403 st_delete(rb_class_tbl, &id, 0);
1404 st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
1405 return;
1406 }
1407
1408
1409 if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
1410 char *modname;
1411
1412 st_delete(autoload_tbl, &id, &modname);
1413 free(modname);
1414 st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
1415 return;
1416 }
1417
1418
1419 if (klass && klass != rb_cObject)
1420 rb_name_error(id, "uninitialized constant %s::%s",
1421 RSTRING(rb_class_path(klass))->ptr,
1422 rb_id2name(id));
1423 else {
1424 rb_name_error(id, "uninitialized constant %s",rb_id2name(id));
1425 }
1426 }
1427
1428 void
1429 rb_define_const(klass, name, val)
1430 VALUE klass;
1431 const char *name;
1432 VALUE val;
1433 {
1434 ID id = rb_intern(name);
1435
1436 if (klass == rb_cObject) {
1437 rb_secure(4);
1438 }
1439 rb_const_set(klass, id, val);
1440 }
1441
1442 void
1443 rb_define_global_const(name, val)
1444 const char *name;
1445 VALUE val;
1446 {
1447 rb_define_const(rb_cObject, name, val);
1448 }
1449
1450 static VALUE
1451 original_module(c)
1452 VALUE c;
1453 {
1454 if (TYPE(c) == T_ICLASS)
1455 return RBASIC(c)->klass;
1456 return c;
1457 }
1458
1459 static void
1460 cvar_override_check(id, a)
1461 VALUE a;
1462 {
1463 VALUE base = original_module(a);
1464
1465 a = RCLASS(a)->super;
1466 while (a) {
1467 if (RCLASS(a)->iv_tbl) {
1468 if (st_lookup(RCLASS(a)->iv_tbl,id,0)) {
1469 rb_warning("class variable %s of %s is overridden by %s",
1470 rb_id2name(id), rb_class2name(original_module(a)),
1471 rb_class2name(base));
1472 }
1473 }
1474 a = RCLASS(a)->super;
1475 }
1476 }
1477
1478 void
1479 rb_cvar_set(klass, id, val, warn)
1480 VALUE klass;
1481 ID id;
1482 VALUE val;
1483 int warn;
1484 {
1485 VALUE tmp;
1486
1487 tmp = klass;
1488 while (tmp) {
1489 if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1490 if (OBJ_FROZEN(tmp)) rb_error_frozen("class/module");
1491 if (!OBJ_TAINTED(tmp) && rb_safe_level() >= 4)
1492 rb_raise(rb_eSecurityError, "Insecure: can't modify class variable");
1493 if (warn && RTEST(ruby_verbose) && klass != tmp) {
1494 rb_warning("already initialized class variable %s", rb_id2name(id));
1495 }
1496 st_insert(RCLASS(tmp)->iv_tbl,id,val);
1497 if (RTEST(ruby_verbose)) {
1498 cvar_override_check(id, tmp);
1499 }
1500 return;
1501 }
1502 tmp = RCLASS(tmp)->super;
1503 }
1504
1505 mod_av_set(klass, id, val, Qfalse);
1506 }
1507
1508 VALUE
1509 rb_cvar_get(klass, id)
1510 VALUE klass;
1511 ID id;
1512 {
1513 VALUE value;
1514 VALUE tmp;
1515
1516 tmp = klass;
1517 while (tmp) {
1518 if (RCLASS(tmp)->iv_tbl) {
1519 if (st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
1520 if (RTEST(ruby_verbose)) {
1521 cvar_override_check(id, tmp);
1522 }
1523 return value;
1524 }
1525 }
1526 tmp = RCLASS(tmp)->super;
1527 }
1528
1529 rb_name_error(id,"uninitialized class variable %s in %s",
1530 rb_id2name(id), rb_class2name(klass));
1531 return Qnil;
1532 }
1533
1534 VALUE
1535 rb_cvar_defined(klass, id)
1536 VALUE klass;
1537 ID id;
1538 {
1539 VALUE tmp;
1540
1541 tmp = klass;
1542 while (tmp) {
1543 if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
1544 return Qtrue;
1545 }
1546 tmp = RCLASS(tmp)->super;
1547 }
1548
1549 return Qfalse;
1550 }
1551
1552 void
1553 rb_cv_set(klass, name, val)
1554 VALUE klass;
1555 const char *name;
1556 VALUE val;
1557 {
1558 ID id = rb_intern(name);
1559 if (!rb_is_class_id(id)) {
1560 rb_name_error(id, "wrong class variable name %s", name);
1561 }
1562 rb_cvar_set(klass, id, val, Qfalse);
1563 }
1564
1565 VALUE
1566 rb_cv_get(klass, name)
1567 VALUE klass;
1568 const char *name;
1569 {
1570 ID id = rb_intern(name);
1571 if (!rb_is_class_id(id)) {
1572 rb_name_error(id, "wrong class variable name %s", name);
1573 }
1574 return rb_cvar_get(klass, id);
1575 }
1576
1577 void
1578 rb_define_class_variable(klass, name, val)
1579 VALUE klass;
1580 const char *name;
1581 VALUE val;
1582 {
1583 ID id = rb_intern(name);
1584
1585 if (!rb_is_class_id(id)) {
1586 rb_name_error(id, "wrong class variable name %s", name);
1587 }
1588 rb_cvar_set(klass, id, val, Qtrue);
1589 }
1590
1591 static int
1592 cv_i(key, value, ary)
1593 ID key;
1594 VALUE value;
1595 VALUE ary;
1596 {
1597 if (rb_is_class_id(key)) {
1598 VALUE kval = rb_str_new2(rb_id2name(key));
1599 if (!rb_ary_includes(ary, kval)) {
1600 rb_ary_push(ary, kval);
1601 }
1602 }
1603 return ST_CONTINUE;
1604 }
1605
1606 VALUE
1607 rb_mod_class_variables(obj)
1608 VALUE obj;
1609 {
1610 VALUE ary = rb_ary_new();
1611
1612 for (;;) {
1613 if (RCLASS(obj)->iv_tbl) {
1614 st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary);
1615 }
1616 obj = RCLASS(obj)->super;
1617 if (!obj) break;
1618 }
1619 return ary;
1620 }
1621
1622 VALUE
1623 rb_mod_remove_cvar(mod, name)
1624 VALUE mod, name;
1625 {
1626 ID id = rb_to_id(name);
1627 VALUE val;
1628
1629 if (!rb_is_class_id(id)) {
1630 rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
1631 }
1632 if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
1633 rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
1634 if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1635
1636 if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
1637 return val;
1638 }
1639 if (rb_cvar_defined(mod, id)) {
1640 rb_name_error(id, "cannot remove %s for %s",
1641 rb_id2name(id), rb_class2name(mod));
1642 }
1643 rb_name_error(id, "class variable %s not defined for %s",
1644 rb_id2name(id), rb_class2name(mod));
1645 return Qnil;
1646 }
1647
1648 VALUE
1649 rb_iv_get(obj, name)
1650 VALUE obj;
1651 const char *name;
1652 {
1653 ID id = rb_intern(name);
1654
1655 return rb_ivar_get(obj, id);
1656 }
1657
1658 VALUE
1659 rb_iv_set(obj, name, val)
1660 VALUE obj;
1661 const char *name;
1662 VALUE val;
1663 {
1664 ID id = rb_intern(name);
1665
1666 return rb_ivar_set(obj, id, val);
1667 }