* include/ruby/io.h (rb_io_t): new fields: writeconv,
[ruby-svn.git] / variable.c
blob48de287408697857b9194fe1d86bef1a31377e96
1 /**********************************************************************
3 variable.c -
5 $Author$
6 created at: Tue Apr 19 23:55:15 JST 1994
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/ruby.h"
15 #include "ruby/node.h"
16 #include "ruby/st.h"
17 #include "ruby/util.h"
19 void rb_vm_change_state(void);
20 st_table *rb_global_tbl;
21 st_table *rb_class_tbl;
22 static ID autoload, classpath, tmp_classpath;
24 void
25 Init_var_tables(void)
27 rb_global_tbl = st_init_numtable();
28 rb_class_tbl = st_init_numtable();
29 CONST_ID(autoload, "__autoload__");
30 CONST_ID(classpath, "__classpath__");
31 CONST_ID(tmp_classpath, "__tmp_classpath__");
34 struct fc_result {
35 ID name;
36 VALUE klass;
37 VALUE path;
38 VALUE track;
39 struct fc_result *prev;
42 static VALUE
43 fc_path(struct fc_result *fc, ID name)
45 VALUE path, tmp;
47 path = rb_str_dup(rb_id2str(name));
48 while (fc) {
49 if (fc->track == rb_cObject) break;
50 if (RCLASS_IV_TBL(fc->track) &&
51 st_lookup(RCLASS_IV_TBL(fc->track), classpath, &tmp)) {
52 tmp = rb_str_dup(tmp);
53 rb_str_cat2(tmp, "::");
54 rb_str_append(tmp, path);
55 path = tmp;
56 break;
58 tmp = rb_str_dup(rb_id2str(fc->name));
59 rb_str_cat2(tmp, "::");
60 rb_str_append(tmp, path);
61 path = tmp;
62 fc = fc->prev;
64 OBJ_FREEZE(path);
65 return path;
68 static int
69 fc_i(ID key, VALUE value, struct fc_result *res)
71 if (!rb_is_const_id(key)) return ST_CONTINUE;
73 if (value == res->klass) {
74 res->path = fc_path(res, key);
75 return ST_STOP;
77 switch (TYPE(value)) {
78 case T_MODULE:
79 case T_CLASS:
80 if (!RCLASS_IV_TBL(value)) return ST_CONTINUE;
81 else {
82 struct fc_result arg;
83 struct fc_result *list;
85 list = res;
86 while (list) {
87 if (list->track == value) return ST_CONTINUE;
88 list = list->prev;
91 arg.name = key;
92 arg.path = 0;
93 arg.klass = res->klass;
94 arg.track = value;
95 arg.prev = res;
96 st_foreach(RCLASS_IV_TBL(value), fc_i, (st_data_t)&arg);
97 if (arg.path) {
98 res->path = arg.path;
99 return ST_STOP;
102 break;
104 default:
105 break;
107 return ST_CONTINUE;
110 static VALUE
111 find_class_path(VALUE klass)
113 struct fc_result arg;
115 arg.name = 0;
116 arg.path = 0;
117 arg.klass = klass;
118 arg.track = rb_cObject;
119 arg.prev = 0;
120 if (RCLASS_IV_TBL(rb_cObject)) {
121 st_foreach_safe(RCLASS_IV_TBL(rb_cObject), fc_i, (st_data_t)&arg);
123 if (arg.path == 0) {
124 st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
126 if (arg.path) {
127 if (!RCLASS_IV_TBL(klass)) {
128 RCLASS_IV_TBL(klass) = st_init_numtable();
130 st_insert(RCLASS_IV_TBL(klass), classpath, arg.path);
131 st_delete(RCLASS_IV_TBL(klass), &tmp_classpath, 0);
132 return arg.path;
134 return Qnil;
137 static VALUE
138 classname(VALUE klass)
140 VALUE path = Qnil;
142 if (!klass) klass = rb_cObject;
143 if (RCLASS_IV_TBL(klass)) {
144 if (!st_lookup(RCLASS_IV_TBL(klass), classpath, &path)) {
145 ID classid;
147 CONST_ID(classid, "__classid__");
149 if (!st_lookup(RCLASS_IV_TBL(klass), classid, &path)) {
150 return find_class_path(klass);
152 path = rb_str_dup(rb_id2str(SYM2ID(path)));
153 OBJ_FREEZE(path);
154 st_insert(RCLASS_IV_TBL(klass), classpath, path);
155 st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&classid, 0);
157 if (TYPE(path) != T_STRING) {
158 rb_bug("class path is not set properly");
160 return path;
162 return find_class_path(klass);
166 * call-seq:
167 * mod.name => string
169 * Returns the name of the module <i>mod</i>. Returns nil for anonymous modules.
172 VALUE
173 rb_mod_name(VALUE mod)
175 VALUE path = classname(mod);
177 if (!NIL_P(path)) return rb_str_dup(path);
178 return path;
181 VALUE
182 rb_class_path(VALUE klass)
184 VALUE path = classname(klass);
186 if (!NIL_P(path)) return path;
187 if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
188 tmp_classpath, &path)) {
189 return path;
191 else {
192 const char *s = "Class";
194 if (TYPE(klass) == T_MODULE) {
195 if (rb_obj_class(klass) == rb_cModule) {
196 s = "Module";
198 else {
199 s = rb_class2name(RBASIC(klass)->klass);
202 path = rb_sprintf("#<%s:%p>", s, (void*)klass);
203 OBJ_FREEZE(path);
204 rb_ivar_set(klass, tmp_classpath, path);
206 return path;
210 void
211 rb_set_class_path(VALUE klass, VALUE under, const char *name)
213 VALUE str;
215 if (under == rb_cObject) {
216 str = rb_str_new2(name);
218 else {
219 str = rb_str_dup(rb_class_path(under));
220 rb_str_cat2(str, "::");
221 rb_str_cat2(str, name);
223 OBJ_FREEZE(str);
224 rb_ivar_set(klass, classpath, str);
227 VALUE
228 rb_path2class(const char *path)
230 const char *pbeg, *p;
231 ID id;
232 VALUE c = rb_cObject;
234 if (path[0] == '#') {
235 rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
237 pbeg = p = path;
238 while (*p) {
239 while (*p && *p != ':') p++;
240 id = rb_intern2(pbeg, p-pbeg);
241 if (p[0] == ':') {
242 if (p[1] != ':') goto undefined_class;
243 p += 2;
244 pbeg = p;
246 if (!rb_const_defined(c, id)) {
247 undefined_class:
248 rb_raise(rb_eArgError, "undefined class/module %.*s", (int)(p-path), path);
250 c = rb_const_get_at(c, id);
251 switch (TYPE(c)) {
252 case T_MODULE:
253 case T_CLASS:
254 break;
255 default:
256 rb_raise(rb_eTypeError, "%s does not refer class/module", path);
260 return c;
263 void
264 rb_name_class(VALUE klass, ID id)
266 rb_iv_set(klass, "__classid__", ID2SYM(id));
269 VALUE
270 rb_class_name(VALUE klass)
272 return rb_class_path(rb_class_real(klass));
275 const char *
276 rb_class2name(VALUE klass)
278 return RSTRING_PTR(rb_class_name(klass));
281 const char *
282 rb_obj_classname(VALUE obj)
284 return rb_class2name(CLASS_OF(obj));
287 struct trace_var {
288 int removed;
289 void (*func)();
290 VALUE data;
291 struct trace_var *next;
294 struct global_variable {
295 int counter;
296 void *data;
297 VALUE (*getter)();
298 void (*setter)();
299 void (*marker)();
300 int block_trace;
301 struct trace_var *trace;
304 struct global_entry {
305 struct global_variable *var;
306 ID id;
309 static VALUE undef_getter(ID id);
310 static void undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
311 static void undef_marker(void);
313 static VALUE val_getter(ID id, VALUE val);
314 static void val_setter(VALUE val, ID id, void *data, struct global_variable *var);
315 static void val_marker(VALUE data);
317 static VALUE var_getter(ID id, VALUE *var);
318 static void var_setter(VALUE val, ID id, VALUE *var);
319 static void var_marker(VALUE *var);
321 struct global_entry*
322 rb_global_entry(ID id)
324 struct global_entry *entry;
325 st_data_t data;
327 if (!st_lookup(rb_global_tbl, id, &data)) {
328 struct global_variable *var;
329 entry = ALLOC(struct global_entry);
330 var = ALLOC(struct global_variable);
331 entry->id = id;
332 entry->var = var;
333 var->counter = 1;
334 var->data = 0;
335 var->getter = undef_getter;
336 var->setter = undef_setter;
337 var->marker = undef_marker;
339 var->block_trace = 0;
340 var->trace = 0;
341 st_add_direct(rb_global_tbl, id, (st_data_t)entry);
343 else {
344 entry = (struct global_entry *)data;
346 return entry;
349 static VALUE
350 undef_getter(ID id)
352 rb_warning("global variable `%s' not initialized", rb_id2name(id));
354 return Qnil;
357 static void
358 undef_setter(VALUE val, ID id, void *data, struct global_variable *var)
360 var->getter = val_getter;
361 var->setter = val_setter;
362 var->marker = val_marker;
364 var->data = (void*)val;
367 static void
368 undef_marker(void)
372 static VALUE
373 val_getter(ID id, VALUE val)
375 return val;
378 static void
379 val_setter(VALUE val, ID id, void *data, struct global_variable *var)
381 var->data = (void*)val;
384 static void
385 val_marker(VALUE data)
387 if (data) rb_gc_mark_maybe(data);
390 static VALUE
391 var_getter(ID id, VALUE *var)
393 if (!var) return Qnil;
394 return *var;
397 static void
398 var_setter(VALUE val, ID id, VALUE *var)
400 *var = val;
403 static void
404 var_marker(VALUE *var)
406 if (var) rb_gc_mark_maybe(*var);
409 static void
410 readonly_setter(VALUE val, ID id, void *var)
412 rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
415 static int
416 mark_global_entry(ID key, struct global_entry *entry)
418 struct trace_var *trace;
419 struct global_variable *var = entry->var;
421 (*var->marker)(var->data);
422 trace = var->trace;
423 while (trace) {
424 if (trace->data) rb_gc_mark_maybe(trace->data);
425 trace = trace->next;
427 return ST_CONTINUE;
430 void
431 rb_gc_mark_global_tbl(void)
433 if (rb_global_tbl)
434 st_foreach_safe(rb_global_tbl, mark_global_entry, 0);
437 static ID
438 global_id(const char *name)
440 ID id;
442 if (name[0] == '$') id = rb_intern(name);
443 else {
444 char *buf = ALLOCA_N(char, strlen(name)+2);
445 buf[0] = '$';
446 strcpy(buf+1, name);
447 id = rb_intern(buf);
449 return id;
452 void
453 rb_define_hooked_variable(
454 const char *name,
455 VALUE *var,
456 VALUE (*getter)(ANYARGS),
457 void (*setter)(ANYARGS))
459 struct global_variable *gvar;
460 ID id;
461 VALUE tmp;
463 if (var)
464 tmp = *var;
466 id = global_id(name);
467 gvar = rb_global_entry(id)->var;
468 gvar->data = (void*)var;
469 gvar->getter = getter?getter:var_getter;
470 gvar->setter = setter?setter:var_setter;
471 gvar->marker = var_marker;
473 RB_GC_GUARD(tmp);
476 void
477 rb_define_variable(const char *name, VALUE *var)
479 rb_define_hooked_variable(name, var, 0, 0);
482 void
483 rb_define_readonly_variable(const char *name, VALUE *var)
485 rb_define_hooked_variable(name, var, 0, readonly_setter);
488 void
489 rb_define_virtual_variable(
490 const char *name,
491 VALUE (*getter)(ANYARGS),
492 void (*setter)(ANYARGS))
494 if (!getter) getter = val_getter;
495 if (!setter) setter = readonly_setter;
496 rb_define_hooked_variable(name, 0, getter, setter);
499 static void
500 rb_trace_eval(VALUE cmd, VALUE val)
502 rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
506 * call-seq:
507 * trace_var(symbol, cmd ) => nil
508 * trace_var(symbol) {|val| block } => nil
510 * Controls tracing of assignments to global variables. The parameter
511 * +symbol_ identifies the variable (as either a string name or a
512 * symbol identifier). _cmd_ (which may be a string or a
513 * +Proc+ object) or block is executed whenever the variable
514 * is assigned. The block or +Proc+ object receives the
515 * variable's new value as a parameter. Also see
516 * <code>Kernel::untrace_var</code>.
518 * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
519 * $_ = "hello"
520 * $_ = ' there'
522 * <em>produces:</em>
524 * $_ is now 'hello'
525 * $_ is now ' there'
528 VALUE
529 rb_f_trace_var(int argc, VALUE *argv)
531 VALUE var, cmd;
532 struct global_entry *entry;
533 struct trace_var *trace;
535 rb_secure(4);
536 if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
537 cmd = rb_block_proc();
539 if (NIL_P(cmd)) {
540 return rb_f_untrace_var(argc, argv);
542 entry = rb_global_entry(rb_to_id(var));
543 if (OBJ_TAINTED(cmd)) {
544 rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
546 trace = ALLOC(struct trace_var);
547 trace->next = entry->var->trace;
548 trace->func = rb_trace_eval;
549 trace->data = cmd;
550 trace->removed = 0;
551 entry->var->trace = trace;
553 return Qnil;
556 static void
557 remove_trace(struct global_variable *var)
559 struct trace_var *trace = var->trace;
560 struct trace_var t;
561 struct trace_var *next;
563 t.next = trace;
564 trace = &t;
565 while (trace->next) {
566 next = trace->next;
567 if (next->removed) {
568 trace->next = next->next;
569 xfree(next);
571 else {
572 trace = next;
575 var->trace = t.next;
579 * call-seq:
580 * untrace_var(symbol [, cmd] ) => array or nil
582 * Removes tracing for the specified command on the given global
583 * variable and returns +nil+. If no command is specified,
584 * removes all tracing for that variable and returns an array
585 * containing the commands actually removed.
588 VALUE
589 rb_f_untrace_var(int argc, VALUE *argv)
591 VALUE var, cmd;
592 ID id;
593 struct global_entry *entry;
594 struct trace_var *trace;
595 st_data_t data;
597 rb_secure(4);
598 rb_scan_args(argc, argv, "11", &var, &cmd);
599 id = rb_to_id(var);
600 if (!st_lookup(rb_global_tbl, id, &data)) {
601 rb_name_error(id, "undefined global variable %s", rb_id2name(id));
604 trace = (entry = (struct global_entry *)data)->var->trace;
605 if (NIL_P(cmd)) {
606 VALUE ary = rb_ary_new();
608 while (trace) {
609 struct trace_var *next = trace->next;
610 rb_ary_push(ary, (VALUE)trace->data);
611 trace->removed = 1;
612 trace = next;
615 if (!entry->var->block_trace) remove_trace(entry->var);
616 return ary;
618 else {
619 while (trace) {
620 if (trace->data == cmd) {
621 trace->removed = 1;
622 if (!entry->var->block_trace) remove_trace(entry->var);
623 return rb_ary_new3(1, cmd);
625 trace = trace->next;
628 return Qnil;
631 VALUE
632 rb_gvar_get(struct global_entry *entry)
634 struct global_variable *var = entry->var;
635 return (*var->getter)(entry->id, var->data, var);
638 struct trace_data {
639 struct trace_var *trace;
640 VALUE val;
643 static VALUE
644 trace_ev(struct trace_data *data)
646 struct trace_var *trace = data->trace;
648 while (trace) {
649 (*trace->func)(trace->data, data->val);
650 trace = trace->next;
652 return Qnil; /* not reached */
655 static VALUE
656 trace_en(struct global_variable *var)
658 var->block_trace = 0;
659 remove_trace(var);
660 return Qnil; /* not reached */
663 VALUE
664 rb_gvar_set(struct global_entry *entry, VALUE val)
666 struct trace_data trace;
667 struct global_variable *var = entry->var;
669 if (rb_safe_level() >= 4)
670 rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
671 (*var->setter)(val, entry->id, var->data, var);
673 if (var->trace && !var->block_trace) {
674 var->block_trace = 1;
675 trace.trace = var->trace;
676 trace.val = val;
677 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
679 return val;
682 VALUE
683 rb_gv_set(const char *name, VALUE val)
685 struct global_entry *entry;
687 entry = rb_global_entry(global_id(name));
688 return rb_gvar_set(entry, val);
691 VALUE
692 rb_gv_get(const char *name)
694 struct global_entry *entry;
696 entry = rb_global_entry(global_id(name));
697 return rb_gvar_get(entry);
700 VALUE
701 rb_gvar_defined(struct global_entry *entry)
703 if (entry->var->getter == undef_getter) return Qfalse;
704 return Qtrue;
707 static int
708 gvar_i(ID key, struct global_entry *entry, VALUE ary)
710 rb_ary_push(ary, ID2SYM(key));
711 return ST_CONTINUE;
715 * call-seq:
716 * global_variables => array
718 * Returns an array of the names of global variables.
720 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
723 VALUE
724 rb_f_global_variables(void)
726 VALUE ary = rb_ary_new();
727 char buf[4];
728 const char *s = "123456789";
730 st_foreach_safe(rb_global_tbl, gvar_i, ary);
731 while (*s) {
732 sprintf(buf, "$%c", *s++);
733 rb_ary_push(ary, ID2SYM(rb_intern(buf)));
735 return ary;
738 void
739 rb_alias_variable(ID name1, ID name2)
741 struct global_entry *entry1, *entry2;
742 st_data_t data1;
744 if (rb_safe_level() >= 4)
745 rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
747 entry2 = rb_global_entry(name2);
748 if (!st_lookup(rb_global_tbl, name1, &data1)) {
749 entry1 = ALLOC(struct global_entry);
750 entry1->id = name1;
751 st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
753 else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) {
754 struct global_variable *var = entry1->var;
755 if (var->block_trace) {
756 rb_raise(rb_eRuntimeError, "can't alias in tracer");
758 var->counter--;
759 if (var->counter == 0) {
760 struct trace_var *trace = var->trace;
761 while (trace) {
762 struct trace_var *next = trace->next;
763 xfree(trace);
764 trace = next;
766 xfree(var);
769 else {
770 return;
772 entry2->var->counter++;
773 entry1->var = entry2->var;
776 static int special_generic_ivar = 0;
777 static st_table *generic_iv_tbl;
779 st_table*
780 rb_generic_ivar_table(VALUE obj)
782 st_data_t tbl;
784 if (!FL_TEST(obj, FL_EXIVAR)) return 0;
785 if (!generic_iv_tbl) return 0;
786 if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
787 return (st_table *)tbl;
790 static VALUE
791 generic_ivar_get(VALUE obj, ID id, int warn)
793 st_data_t tbl;
794 VALUE val;
796 if (generic_iv_tbl) {
797 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
798 if (st_lookup((st_table *)tbl, id, &val)) {
799 return val;
803 if (warn) {
804 rb_warning("instance variable %s not initialized", rb_id2name(id));
806 return Qnil;
809 static void
810 generic_ivar_set(VALUE obj, ID id, VALUE val)
812 st_table *tbl;
813 st_data_t data;
815 if (rb_special_const_p(obj)) {
816 if (rb_obj_frozen_p(obj)) rb_error_frozen("object");
817 special_generic_ivar = 1;
819 if (!generic_iv_tbl) {
820 generic_iv_tbl = st_init_numtable();
822 if (!st_lookup(generic_iv_tbl, obj, &data)) {
823 FL_SET(obj, FL_EXIVAR);
824 tbl = st_init_numtable();
825 st_add_direct(generic_iv_tbl, obj, (st_data_t)tbl);
826 st_add_direct(tbl, id, val);
827 return;
829 st_insert((st_table *)data, id, val);
832 static VALUE
833 generic_ivar_defined(VALUE obj, ID id)
835 st_table *tbl;
836 st_data_t data;
837 VALUE val;
839 if (!generic_iv_tbl) return Qfalse;
840 if (!st_lookup(generic_iv_tbl, obj, &data)) return Qfalse;
841 tbl = (st_table *)data;
842 if (st_lookup(tbl, id, &val)) {
843 return Qtrue;
845 return Qfalse;
848 static int
849 generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
851 st_table *tbl;
852 st_data_t data;
853 int status;
855 if (!generic_iv_tbl) return 0;
856 if (!st_lookup(generic_iv_tbl, obj, &data)) return 0;
857 tbl = (st_table *)data;
858 status = st_delete(tbl, &id, valp);
859 if (tbl->num_entries == 0) {
860 st_delete(generic_iv_tbl, &obj, &data);
861 st_free_table((st_table *)data);
863 return status;
866 void
867 rb_mark_generic_ivar(VALUE obj)
869 st_data_t tbl;
871 if (!generic_iv_tbl) return;
872 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
873 rb_mark_tbl((st_table *)tbl);
877 static int
878 givar_mark_i(ID key, VALUE value)
880 rb_gc_mark(value);
881 return ST_CONTINUE;
884 static int
885 givar_i(VALUE obj, st_table *tbl)
887 if (rb_special_const_p(obj)) {
888 st_foreach_safe(tbl, givar_mark_i, 0);
890 return ST_CONTINUE;
893 void
894 rb_mark_generic_ivar_tbl(void)
896 if (!generic_iv_tbl) return;
897 if (special_generic_ivar == 0) return;
898 st_foreach_safe(generic_iv_tbl, givar_i, 0);
901 void
902 rb_free_generic_ivar(VALUE obj)
904 st_data_t tbl;
906 if (!generic_iv_tbl) return;
907 if (st_delete(generic_iv_tbl, &obj, &tbl))
908 st_free_table((st_table *)tbl);
911 void
912 rb_copy_generic_ivar(VALUE clone, VALUE obj)
914 st_data_t data;
916 if (!generic_iv_tbl) return;
917 if (!FL_TEST(obj, FL_EXIVAR)) {
918 clear:
919 if (FL_TEST(clone, FL_EXIVAR)) {
920 rb_free_generic_ivar(clone);
921 FL_UNSET(clone, FL_EXIVAR);
923 return;
925 if (st_lookup(generic_iv_tbl, obj, &data)) {
926 st_table *tbl = (st_table *)data;
928 if (tbl->num_entries == 0)
929 goto clear;
931 if (st_lookup(generic_iv_tbl, clone, &data)) {
932 st_free_table((st_table *)data);
933 st_insert(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
935 else {
936 st_add_direct(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
937 FL_SET(clone, FL_EXIVAR);
942 static VALUE
943 ivar_get(VALUE obj, ID id, int warn)
945 VALUE val, *ptr;
946 struct st_table *iv_index_tbl;
947 long len;
948 st_data_t index;
950 switch (TYPE(obj)) {
951 case T_OBJECT:
952 len = ROBJECT_NUMIV(obj);
953 ptr = ROBJECT_IVPTR(obj);
954 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
955 if (!iv_index_tbl) break;
956 if (!st_lookup(iv_index_tbl, id, &index)) break;
957 if (len <= index) break;
958 val = ptr[index];
959 if (val != Qundef)
960 return val;
961 break;
962 case T_CLASS:
963 case T_MODULE:
964 if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, &val))
965 return val;
966 break;
967 default:
968 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
969 return generic_ivar_get(obj, id, warn);
970 break;
972 if (warn) {
973 rb_warning("instance variable %s not initialized", rb_id2name(id));
975 return Qnil;
978 VALUE
979 rb_ivar_get(VALUE obj, ID id)
981 return ivar_get(obj, id, Qtrue);
984 VALUE
985 rb_attr_get(VALUE obj, ID id)
987 return ivar_get(obj, id, Qfalse);
990 VALUE
991 rb_ivar_set(VALUE obj, ID id, VALUE val)
993 struct st_table *iv_index_tbl;
994 st_data_t index;
995 long i, len;
996 int ivar_extended;
998 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
999 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
1000 if (OBJ_FROZEN(obj)) rb_error_frozen("object");
1001 switch (TYPE(obj)) {
1002 case T_OBJECT:
1003 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1004 if (!iv_index_tbl) {
1005 VALUE klass = rb_obj_class(obj);
1006 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass);
1007 if (!iv_index_tbl) {
1008 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
1011 ivar_extended = 0;
1012 if (!st_lookup(iv_index_tbl, id, &index)) {
1013 index = iv_index_tbl->num_entries;
1014 st_add_direct(iv_index_tbl, id, index);
1015 ivar_extended = 1;
1017 len = ROBJECT_NUMIV(obj);
1018 if (len <= index) {
1019 VALUE *ptr = ROBJECT_IVPTR(obj);
1020 if (index < ROBJECT_EMBED_LEN_MAX) {
1021 RBASIC(obj)->flags |= ROBJECT_EMBED;
1022 ptr = ROBJECT(obj)->as.ary;
1023 for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) {
1024 ptr[i] = Qundef;
1027 else {
1028 VALUE *newptr;
1029 long newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */
1030 if (!ivar_extended &&
1031 iv_index_tbl->num_entries < newsize) {
1032 newsize = iv_index_tbl->num_entries;
1034 if (RBASIC(obj)->flags & ROBJECT_EMBED) {
1035 newptr = ALLOC_N(VALUE, newsize);
1036 MEMCPY(newptr, ptr, VALUE, len);
1037 RBASIC(obj)->flags &= ~ROBJECT_EMBED;
1038 ROBJECT(obj)->as.heap.ivptr = newptr;
1040 else {
1041 REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize);
1042 newptr = ROBJECT(obj)->as.heap.ivptr;
1044 for (; len < newsize; len++)
1045 newptr[len] = Qundef;
1046 ROBJECT(obj)->as.heap.numiv = newsize;
1047 ROBJECT(obj)->as.heap.iv_index_tbl = iv_index_tbl;
1050 ROBJECT_IVPTR(obj)[index] = val;
1051 break;
1052 case T_CLASS:
1053 case T_MODULE:
1054 if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
1055 st_insert(RCLASS_IV_TBL(obj), id, val);
1056 break;
1057 default:
1058 generic_ivar_set(obj, id, val);
1059 break;
1061 return val;
1064 VALUE
1065 rb_ivar_defined(VALUE obj, ID id)
1067 VALUE val;
1068 struct st_table *iv_index_tbl;
1069 st_data_t index;
1070 switch (TYPE(obj)) {
1071 case T_OBJECT:
1072 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1073 if (!iv_index_tbl) break;
1074 if (!st_lookup(iv_index_tbl, id, &index)) break;
1075 if (ROBJECT_NUMIV(obj) <= index) break;
1076 val = ROBJECT_IVPTR(obj)[index];
1077 if (val != Qundef)
1078 return Qtrue;
1079 break;
1080 case T_CLASS:
1081 case T_MODULE:
1082 if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, 0))
1083 return Qtrue;
1084 break;
1085 default:
1086 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
1087 return generic_ivar_defined(obj, id);
1088 break;
1090 return Qfalse;
1093 struct obj_ivar_tag {
1094 VALUE obj;
1095 int (*func)(ID key, VALUE val, st_data_t arg);
1096 st_data_t arg;
1099 static int
1100 obj_ivar_i(ID key, VALUE index, struct obj_ivar_tag *data)
1102 if (index < ROBJECT_NUMIV(data->obj)) {
1103 VALUE val = ROBJECT_IVPTR(data->obj)[index];
1104 if (val != Qundef) {
1105 return (data->func)(key, val, data->arg);
1108 return ST_CONTINUE;
1111 static void
1112 obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
1114 st_table *tbl;
1115 struct obj_ivar_tag data;
1117 tbl = ROBJECT_IV_INDEX_TBL(obj);
1118 if (!tbl)
1119 return;
1121 data.obj = obj;
1122 data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
1123 data.arg = arg;
1125 st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
1128 void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
1130 switch (TYPE(obj)) {
1131 case T_OBJECT:
1132 obj_ivar_each(obj, func, arg);
1133 break;
1134 case T_CLASS:
1135 case T_MODULE:
1136 if (RCLASS_IV_TBL(obj)) {
1137 st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
1139 break;
1140 default:
1141 if (!generic_iv_tbl) break;
1142 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1143 st_data_t tbl;
1145 if (st_lookup(generic_iv_tbl, obj, &tbl)) {
1146 st_foreach_safe((st_table *)tbl, func, arg);
1149 break;
1153 static int
1154 ivar_i(ID key, VALUE val, VALUE ary)
1156 if (rb_is_instance_id(key)) {
1157 rb_ary_push(ary, ID2SYM(key));
1159 return ST_CONTINUE;
1163 * call-seq:
1164 * obj.instance_variables => array
1166 * Returns an array of instance variable names for the receiver. Note
1167 * that simply defining an accessor does not create the corresponding
1168 * instance variable.
1170 * class Fred
1171 * attr_accessor :a1
1172 * def initialize
1173 * @iv = 3
1174 * end
1175 * end
1176 * Fred.new.instance_variables #=> [:@iv]
1179 VALUE
1180 rb_obj_instance_variables(VALUE obj)
1182 VALUE ary;
1184 ary = rb_ary_new();
1185 rb_ivar_foreach(obj, ivar_i, ary);
1186 return ary;
1190 * call-seq:
1191 * obj.remove_instance_variable(symbol) => obj
1193 * Removes the named instance variable from <i>obj</i>, returning that
1194 * variable's value.
1196 * class Dummy
1197 * attr_reader :var
1198 * def initialize
1199 * @var = 99
1200 * end
1201 * def remove
1202 * remove_instance_variable(:@var)
1203 * end
1204 * end
1205 * d = Dummy.new
1206 * d.var #=> 99
1207 * d.remove #=> 99
1208 * d.var #=> nil
1211 VALUE
1212 rb_obj_remove_instance_variable(VALUE obj, VALUE name)
1214 VALUE val = Qnil;
1215 ID id = rb_to_id(name);
1216 struct st_table *iv_index_tbl;
1217 st_data_t index;
1219 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
1220 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
1221 if (OBJ_FROZEN(obj)) rb_error_frozen("object");
1222 if (!rb_is_instance_id(id)) {
1223 rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
1226 switch (TYPE(obj)) {
1227 case T_OBJECT:
1228 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
1229 if (!iv_index_tbl) break;
1230 if (!st_lookup(iv_index_tbl, id, &index)) break;
1231 if (ROBJECT_NUMIV(obj) <= index) break;
1232 val = ROBJECT_IVPTR(obj)[index];
1233 if (val != Qundef) {
1234 ROBJECT_IVPTR(obj)[index] = Qundef;
1235 return val;
1237 break;
1238 case T_CLASS:
1239 case T_MODULE:
1240 if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t*)&id, &val)) {
1241 return val;
1243 break;
1244 default:
1245 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
1246 if (generic_ivar_remove(obj, id, &val)) {
1247 return val;
1250 break;
1252 rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
1253 return Qnil; /* not reached */
1256 NORETURN(static void uninitialized_constant(VALUE, ID));
1257 static void
1258 uninitialized_constant(VALUE klass, ID id)
1260 if (klass && klass != rb_cObject)
1261 rb_name_error(id, "uninitialized constant %s::%s",
1262 rb_class2name(klass),
1263 rb_id2name(id));
1264 else {
1265 rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
1269 static VALUE
1270 const_missing(VALUE klass, ID id)
1272 return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
1277 * call-seq:
1278 * mod.const_missing(sym) => obj
1280 * Invoked when a reference is made to an undefined constant in
1281 * <i>mod</i>. It is passed a symbol for the undefined constant, and
1282 * returns a value to be used for that constant. The
1283 * following code is a (very bad) example: if reference is made to
1284 * an undefined constant, it attempts to load a file whose name is
1285 * the lowercase version of the constant (thus class <code>Fred</code> is
1286 * assumed to be in file <code>fred.rb</code>). If found, it returns the
1287 * value of the loaded class. It therefore implements a perverse
1288 * kind of autoload facility.
1290 * def Object.const_missing(name)
1291 * @looked_for ||= {}
1292 * str_name = name.to_s
1293 * raise "Class not found: #{name}" if @looked_for[str_name]
1294 * @looked_for[str_name] = 1
1295 * file = str_name.downcase
1296 * require file
1297 * klass = const_get(name)
1298 * return klass if klass
1299 * raise "Class not found: #{name}"
1300 * end
1304 VALUE
1305 rb_mod_const_missing(VALUE klass, VALUE name)
1307 rb_frame_pop(); /* pop frame for "const_missing" */
1308 uninitialized_constant(klass, rb_to_id(name));
1309 return Qnil; /* not reached */
1312 static struct st_table *
1313 check_autoload_table(VALUE av)
1315 Check_Type(av, T_DATA);
1316 if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
1317 RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
1318 VALUE desc = rb_inspect(av);
1319 rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING_PTR(desc));
1321 return (struct st_table *)DATA_PTR(av);
1324 void
1325 rb_autoload(VALUE mod, ID id, const char *file)
1327 VALUE av, fn;
1328 struct st_table *tbl;
1330 if (!rb_is_const_id(id)) {
1331 rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
1333 if (!file || !*file) {
1334 rb_raise(rb_eArgError, "empty file name");
1337 if ((tbl = RCLASS_IV_TBL(mod)) && st_lookup(tbl, id, &av) && av != Qundef)
1338 return;
1340 rb_const_set(mod, id, Qundef);
1341 tbl = RCLASS_IV_TBL(mod);
1342 if (st_lookup(tbl, autoload, &av)) {
1343 tbl = check_autoload_table(av);
1345 else {
1346 av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
1347 st_add_direct(tbl, autoload, av);
1348 DATA_PTR(av) = tbl = st_init_numtable();
1350 fn = rb_str_new2(file);
1351 FL_UNSET(fn, FL_TAINT);
1352 OBJ_FREEZE(fn);
1353 st_insert(tbl, id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0));
1356 static NODE*
1357 autoload_delete(VALUE mod, ID id)
1359 VALUE val;
1360 st_data_t load = 0;
1362 st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, 0);
1363 if (st_lookup(RCLASS_IV_TBL(mod), autoload, &val)) {
1364 struct st_table *tbl = check_autoload_table(val);
1366 st_delete(tbl, (st_data_t*)&id, &load);
1368 if (tbl->num_entries == 0) {
1369 DATA_PTR(val) = 0;
1370 st_free_table(tbl);
1371 id = autoload;
1372 if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
1373 rb_gc_force_recycle(val);
1378 return (NODE *)load;
1381 VALUE
1382 rb_autoload_load(VALUE klass, ID id)
1384 VALUE file;
1385 NODE *load = autoload_delete(klass, id);
1387 if (!load || !(file = load->nd_lit)) {
1388 return Qfalse;
1390 return rb_require_safe(file, load->nd_nth);
1393 static VALUE
1394 autoload_file(VALUE mod, ID id)
1396 VALUE val, file;
1397 struct st_table *tbl;
1398 st_data_t load;
1400 if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
1401 !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
1402 return Qnil;
1404 file = ((NODE *)load)->nd_lit;
1405 Check_Type(file, T_STRING);
1406 if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) {
1407 rb_raise(rb_eArgError, "empty file name");
1409 if (!rb_provided(RSTRING_PTR(file))) {
1410 return file;
1413 /* already loaded but not defined */
1414 st_delete(tbl, (st_data_t*)&id, 0);
1415 if (!tbl->num_entries) {
1416 DATA_PTR(val) = 0;
1417 st_free_table(tbl);
1418 id = autoload;
1419 if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
1420 rb_gc_force_recycle(val);
1423 return Qnil;
1426 VALUE
1427 rb_autoload_p(VALUE mod, ID id)
1429 struct st_table *tbl = RCLASS_IV_TBL(mod);
1430 VALUE val;
1432 if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
1433 return Qnil;
1435 return autoload_file(mod, id);
1438 static VALUE
1439 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
1441 VALUE value, tmp;
1442 int mod_retry = 0;
1444 tmp = klass;
1445 retry:
1446 while (RTEST(tmp)) {
1447 while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) {
1448 if (value == Qundef) {
1449 if (!RTEST(rb_autoload_load(tmp, id))) break;
1450 continue;
1452 if (exclude && tmp == rb_cObject && klass != rb_cObject) {
1453 rb_warn("toplevel constant %s referenced by %s::%s",
1454 rb_id2name(id), rb_class2name(klass), rb_id2name(id));
1456 return value;
1458 if (!recurse && klass != rb_cObject) break;
1459 tmp = RCLASS_SUPER(tmp);
1461 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
1462 mod_retry = 1;
1463 tmp = rb_cObject;
1464 goto retry;
1467 return const_missing(klass, id);
1470 VALUE
1471 rb_const_get_from(VALUE klass, ID id)
1473 return rb_const_get_0(klass, id, Qtrue, Qtrue);
1476 VALUE
1477 rb_const_get(VALUE klass, ID id)
1479 return rb_const_get_0(klass, id, Qfalse, Qtrue);
1482 VALUE
1483 rb_const_get_at(VALUE klass, ID id)
1485 return rb_const_get_0(klass, id, Qtrue, Qfalse);
1489 * call-seq:
1490 * remove_const(sym) => obj
1492 * Removes the definition of the given constant, returning that
1493 * constant's value. Predefined classes and singleton objects (such as
1494 * <i>true</i>) cannot be removed.
1497 VALUE
1498 rb_mod_remove_const(VALUE mod, VALUE name)
1500 ID id = rb_to_id(name);
1501 VALUE val;
1503 rb_vm_change_state();
1505 if (!rb_is_const_id(id)) {
1506 rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
1508 if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
1509 rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
1510 if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1512 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
1513 if (val == Qundef) {
1514 autoload_delete(mod, id);
1515 val = Qnil;
1517 return val;
1519 if (rb_const_defined_at(mod, id)) {
1520 rb_name_error(id, "cannot remove %s::%s",
1521 rb_class2name(mod), rb_id2name(id));
1523 rb_name_error(id, "constant %s::%s not defined",
1524 rb_class2name(mod), rb_id2name(id));
1525 return Qnil; /* not reached */
1528 static int
1529 sv_i(ID key, VALUE value, st_table *tbl)
1531 if (rb_is_const_id(key)) {
1532 if (!st_lookup(tbl, key, 0)) {
1533 st_insert(tbl, key, key);
1536 return ST_CONTINUE;
1539 void*
1540 rb_mod_const_at(VALUE mod, void *data)
1542 st_table *tbl = data;
1543 if (!tbl) {
1544 tbl = st_init_numtable();
1546 if (RCLASS_IV_TBL(mod)) {
1547 st_foreach_safe(RCLASS_IV_TBL(mod), sv_i, (st_data_t)tbl);
1549 return tbl;
1552 void*
1553 rb_mod_const_of(VALUE mod, void *data)
1555 VALUE tmp = mod;
1556 for (;;) {
1557 data = rb_mod_const_at(tmp, data);
1558 tmp = RCLASS_SUPER(tmp);
1559 if (!tmp) break;
1560 if (tmp == rb_cObject && mod != rb_cObject) break;
1562 return data;
1565 static int
1566 list_i(ID key, ID value, VALUE ary)
1568 rb_ary_push(ary, ID2SYM(key));
1569 return ST_CONTINUE;
1572 VALUE
1573 rb_const_list(void *data)
1575 st_table *tbl = data;
1576 VALUE ary;
1578 if (!tbl) return rb_ary_new2(0);
1579 ary = rb_ary_new2(tbl->num_entries);
1580 st_foreach_safe(tbl, list_i, ary);
1581 st_free_table(tbl);
1583 return ary;
1587 * call-seq:
1588 * mod.constants(inherit=true) => array
1590 * Returns an array of the names of the constants accessible in
1591 * <i>mod</i>. This includes the names of constants in any included
1592 * modules (example at start of section), unless the <i>all</i>
1593 * parameter is set to <code>false</code>.
1595 * IO.constants.include?(:SYNC) => true
1596 * IO.constants(false).include?(:SYNC) => false
1598 * Also see <code>Module::const_defined?</code>.
1601 VALUE
1602 rb_mod_constants(int argc, VALUE *argv, VALUE mod)
1604 VALUE inherit;
1605 st_table *tbl;
1607 if (argc == 0) {
1608 inherit = Qtrue;
1610 else {
1611 rb_scan_args(argc, argv, "01", &inherit);
1613 if (RTEST(inherit)) {
1614 tbl = rb_mod_const_of(mod, 0);
1616 else {
1617 tbl = rb_mod_const_at(mod, 0);
1619 return rb_const_list(tbl);
1622 static int
1623 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse)
1625 VALUE value, tmp;
1626 int mod_retry = 0;
1628 tmp = klass;
1629 retry:
1630 while (tmp) {
1631 if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) {
1632 if (value == Qundef && NIL_P(autoload_file(klass, id)))
1633 return Qfalse;
1634 return Qtrue;
1636 if (!recurse && klass != rb_cObject) break;
1637 tmp = RCLASS_SUPER(tmp);
1639 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
1640 mod_retry = 1;
1641 tmp = rb_cObject;
1642 goto retry;
1644 return Qfalse;
1648 rb_const_defined_from(VALUE klass, ID id)
1650 return rb_const_defined_0(klass, id, Qtrue, Qtrue);
1654 rb_const_defined(VALUE klass, ID id)
1656 return rb_const_defined_0(klass, id, Qfalse, Qtrue);
1660 rb_const_defined_at(VALUE klass, ID id)
1662 return rb_const_defined_0(klass, id, Qtrue, Qfalse);
1665 static void
1666 mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
1668 const char *dest = isconst ? "constant" : "class variable";
1670 if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4)
1671 rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
1672 if (OBJ_FROZEN(klass)) {
1673 if (BUILTIN_TYPE(klass) == T_MODULE) {
1674 rb_error_frozen("module");
1676 else {
1677 rb_error_frozen("class");
1680 if (!RCLASS_IV_TBL(klass)) {
1681 RCLASS_IV_TBL(klass) = st_init_numtable();
1683 else if (isconst) {
1684 VALUE value = Qfalse;
1686 if (st_lookup(RCLASS_IV_TBL(klass), id, &value)) {
1687 if (value == Qundef)
1688 autoload_delete(klass, id);
1689 else
1690 rb_warn("already initialized %s %s", dest, rb_id2name(id));
1694 if(isconst){
1695 rb_vm_change_state();
1697 st_insert(RCLASS_IV_TBL(klass), id, val);
1700 void
1701 rb_const_set(VALUE klass, ID id, VALUE val)
1703 if (NIL_P(klass)) {
1704 rb_raise(rb_eTypeError, "no class/module to define constant %s",
1705 rb_id2name(id));
1707 mod_av_set(klass, id, val, Qtrue);
1710 void
1711 rb_define_const(VALUE klass, const char *name, VALUE val)
1713 ID id = rb_intern(name);
1715 if (!rb_is_const_id(id)) {
1716 rb_warn("rb_define_const: invalid name `%s' for constant", name);
1718 if (klass == rb_cObject) {
1719 rb_secure(4);
1721 rb_const_set(klass, id, val);
1724 void
1725 rb_define_global_const(const char *name, VALUE val)
1727 rb_define_const(rb_cObject, name, val);
1730 static VALUE
1731 original_module(VALUE c)
1733 if (TYPE(c) == T_ICLASS)
1734 return RBASIC(c)->klass;
1735 return c;
1738 #define CVAR_LOOKUP(v,r) do {\
1739 if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
1742 if (FL_TEST(klass, FL_SINGLETON) ) {\
1743 VALUE obj = rb_iv_get(klass, "__attached__");\
1744 switch (TYPE(obj)) {\
1745 case T_MODULE:\
1746 case T_CLASS:\
1747 klass = obj;\
1748 break;\
1749 default:\
1750 klass = RCLASS_SUPER(klass);\
1751 break;\
1754 else {\
1755 klass = RCLASS_SUPER(klass);\
1757 while (klass) {\
1758 if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
1761 klass = RCLASS_SUPER(klass);\
1763 } while(0)
1765 void
1766 rb_cvar_set(VALUE klass, ID id, VALUE val)
1768 VALUE tmp, front = 0, target = 0;
1770 tmp = klass;
1771 CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
1772 if (target) {
1773 if (front && target != front) {
1774 ID did = id;
1776 if (RTEST(ruby_verbose)) {
1777 rb_warning("class variable %s of %s is overtaken by %s",
1778 rb_id2name(id), rb_class2name(original_module(front)),
1779 rb_class2name(original_module(target)));
1781 if (BUILTIN_TYPE(front) == T_CLASS) {
1782 st_delete(RCLASS_IV_TBL(front),&did,0);
1786 else {
1787 target = tmp;
1789 mod_av_set(target, id, val, Qfalse);
1792 VALUE
1793 rb_cvar_get(VALUE klass, ID id)
1795 VALUE value, tmp, front = 0, target = 0;
1797 tmp = klass;
1798 CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
1799 if (!target) {
1800 rb_name_error(id,"uninitialized class variable %s in %s",
1801 rb_id2name(id), rb_class2name(tmp));
1803 if (front && target != front) {
1804 ID did = id;
1806 if (RTEST(ruby_verbose)) {
1807 rb_warning("class variable %s of %s is overtaken by %s",
1808 rb_id2name(id), rb_class2name(original_module(front)),
1809 rb_class2name(original_module(target)));
1811 if (BUILTIN_TYPE(front) == T_CLASS) {
1812 st_delete(RCLASS_IV_TBL(front),&did,0);
1815 return value;
1818 VALUE
1819 rb_cvar_defined(VALUE klass, ID id)
1821 if (!klass) return Qfalse;
1822 CVAR_LOOKUP(0,return Qtrue);
1823 return Qfalse;
1826 void
1827 rb_cv_set(VALUE klass, const char *name, VALUE val)
1829 ID id = rb_intern(name);
1830 if (!rb_is_class_id(id)) {
1831 rb_name_error(id, "wrong class variable name %s", name);
1833 rb_cvar_set(klass, id, val);
1836 VALUE
1837 rb_cv_get(VALUE klass, const char *name)
1839 ID id = rb_intern(name);
1840 if (!rb_is_class_id(id)) {
1841 rb_name_error(id, "wrong class variable name %s", name);
1843 return rb_cvar_get(klass, id);
1846 void
1847 rb_define_class_variable(VALUE klass, const char *name, VALUE val)
1849 ID id = rb_intern(name);
1851 if (!rb_is_class_id(id)) {
1852 rb_name_error(id, "wrong class variable name %s", name);
1854 rb_cvar_set(klass, id, val);
1857 static int
1858 cv_i(ID key, VALUE value, VALUE ary)
1860 if (rb_is_class_id(key)) {
1861 VALUE kval = ID2SYM(key);
1862 if (!rb_ary_includes(ary, kval)) {
1863 rb_ary_push(ary, kval);
1866 return ST_CONTINUE;
1870 * call-seq:
1871 * mod.class_variables => array
1873 * Returns an array of the names of class variables in <i>mod</i>.
1875 * class One
1876 * @@var1 = 1
1877 * end
1878 * class Two < One
1879 * @@var2 = 2
1880 * end
1881 * One.class_variables #=> [:@@var1]
1882 * Two.class_variables #=> [:@@var2]
1885 VALUE
1886 rb_mod_class_variables(VALUE obj)
1888 VALUE ary = rb_ary_new();
1890 if (RCLASS_IV_TBL(obj)) {
1891 st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary);
1893 return ary;
1897 * call-seq:
1898 * remove_class_variable(sym) => obj
1900 * Removes the definition of the <i>sym</i>, returning that
1901 * constant's value.
1903 * class Dummy
1904 * @@var = 99
1905 * puts @@var
1906 * remove_class_variable(:@@var)
1907 * puts(defined? @@var)
1908 * end
1910 * <em>produces:</em>
1912 * 99
1913 * nil
1916 VALUE
1917 rb_mod_remove_cvar(VALUE mod, VALUE name)
1919 ID id = rb_to_id(name);
1920 VALUE val;
1922 if (!rb_is_class_id(id)) {
1923 rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
1925 if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
1926 rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
1927 if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
1929 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
1930 return val;
1932 if (rb_cvar_defined(mod, id)) {
1933 rb_name_error(id, "cannot remove %s for %s",
1934 rb_id2name(id), rb_class2name(mod));
1936 rb_name_error(id, "class variable %s not defined for %s",
1937 rb_id2name(id), rb_class2name(mod));
1938 return Qnil; /* not reached */
1941 VALUE
1942 rb_iv_get(VALUE obj, const char *name)
1944 ID id = rb_intern(name);
1946 return rb_ivar_get(obj, id);
1949 VALUE
1950 rb_iv_set(VALUE obj, const char *name, VALUE val)
1952 ID id = rb_intern(name);
1954 return rb_ivar_set(obj, id, val);