Ruby  2.0.0p247(2013-06-27revision41674)
variable.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   variable.c -
00004 
00005   $Author: nagachika $
00006   created at: Tue Apr 19 23:55:15 JST 1994
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
00011 
00012 **********************************************************************/
00013 
00014 #include "ruby/ruby.h"
00015 #include "ruby/st.h"
00016 #include "ruby/util.h"
00017 #include "ruby/encoding.h"
00018 #include "node.h"
00019 #include "constant.h"
00020 #include "internal.h"
00021 
00022 st_table *rb_global_tbl;
00023 st_table *rb_class_tbl;
00024 static ID autoload, classpath, tmp_classpath, classid;
00025 
00026 void
00027 Init_var_tables(void)
00028 {
00029     rb_global_tbl = st_init_numtable();
00030     rb_class_tbl = st_init_numtable();
00031     CONST_ID(autoload, "__autoload__");
00032     /* __classpath__: fully qualified class path */
00033     CONST_ID(classpath, "__classpath__");
00034     /* __tmp_classpath__: temporary class path which contains anonymous names */
00035     CONST_ID(tmp_classpath, "__tmp_classpath__");
00036     /* __classid__: name given to class/module under an anonymous namespace */
00037     CONST_ID(classid, "__classid__");
00038 }
00039 
00040 struct fc_result {
00041     ID name, preferred;
00042     VALUE klass;
00043     VALUE path;
00044     VALUE track;
00045     struct fc_result *prev;
00046 };
00047 
00048 static VALUE
00049 fc_path(struct fc_result *fc, ID name)
00050 {
00051     VALUE path, tmp;
00052 
00053     path = rb_str_dup(rb_id2str(name));
00054     while (fc) {
00055         st_data_t n;
00056         if (fc->track == rb_cObject) break;
00057         if (RCLASS_IV_TBL(fc->track) &&
00058             st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) {
00059             tmp = rb_str_dup((VALUE)n);
00060             rb_str_cat2(tmp, "::");
00061             rb_str_append(tmp, path);
00062             path = tmp;
00063             break;
00064         }
00065         tmp = rb_str_dup(rb_id2str(fc->name));
00066         rb_str_cat2(tmp, "::");
00067         rb_str_append(tmp, path);
00068         path = tmp;
00069         fc = fc->prev;
00070     }
00071     OBJ_FREEZE(path);
00072     return path;
00073 }
00074 
00075 static int
00076 fc_i(st_data_t k, st_data_t v, st_data_t a)
00077 {
00078     ID key = (ID)k;
00079     rb_const_entry_t *ce = (rb_const_entry_t *)v;
00080     struct fc_result *res = (struct fc_result *)a;
00081     VALUE value = ce->value;
00082     if (!rb_is_const_id(key)) return ST_CONTINUE;
00083 
00084     if (value == res->klass && (!res->preferred || key == res->preferred)) {
00085         res->path = fc_path(res, key);
00086         return ST_STOP;
00087     }
00088     if (RB_TYPE_P(value, T_MODULE) || RB_TYPE_P(value, T_CLASS)) {
00089         if (!RCLASS_CONST_TBL(value)) return ST_CONTINUE;
00090         else {
00091             struct fc_result arg;
00092             struct fc_result *list;
00093 
00094             list = res;
00095             while (list) {
00096                 if (list->track == value) return ST_CONTINUE;
00097                 list = list->prev;
00098             }
00099 
00100             arg.name = key;
00101             arg.preferred = res->preferred;
00102             arg.path = 0;
00103             arg.klass = res->klass;
00104             arg.track = value;
00105             arg.prev = res;
00106             st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg);
00107             if (arg.path) {
00108                 res->path = arg.path;
00109                 return ST_STOP;
00110             }
00111         }
00112     }
00113     return ST_CONTINUE;
00114 }
00115 
00123 static VALUE
00124 find_class_path(VALUE klass, ID preferred)
00125 {
00126     struct fc_result arg;
00127 
00128     arg.preferred = preferred;
00129     arg.name = 0;
00130     arg.path = 0;
00131     arg.klass = klass;
00132     arg.track = rb_cObject;
00133     arg.prev = 0;
00134     if (RCLASS_CONST_TBL(rb_cObject)) {
00135         st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg);
00136     }
00137     if (arg.path == 0) {
00138         st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
00139     }
00140     if (arg.path) {
00141         st_data_t tmp = tmp_classpath;
00142         if (!RCLASS_IV_TBL(klass)) {
00143             RCLASS_IV_TBL(klass) = st_init_numtable();
00144         }
00145         st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path);
00146         st_delete(RCLASS_IV_TBL(klass), &tmp, 0);
00147         return arg.path;
00148     }
00149     return Qnil;
00150 }
00151 
00159 static VALUE
00160 classname(VALUE klass, int *permanent)
00161 {
00162     VALUE path = Qnil;
00163     st_data_t n;
00164 
00165     if (!klass) klass = rb_cObject;
00166     *permanent = 1;
00167     if (RCLASS_IV_TBL(klass)) {
00168         if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) {
00169             ID cid = 0;
00170             if (st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) {
00171                 cid = SYM2ID(n);
00172                 path = find_class_path(klass, cid);
00173             }
00174             if (NIL_P(path)) {
00175                 path = find_class_path(klass, (ID)0);
00176             }
00177             if (NIL_P(path)) {
00178                 if (!cid || !st_lookup(RCLASS_IV_TBL(klass), (st_data_t)tmp_classpath, &n)) {
00179                     return Qnil;
00180                 }
00181                 *permanent = 0;
00182                 path = (VALUE)n;
00183                 return path;
00184             }
00185         }
00186         else {
00187             path = (VALUE)n;
00188         }
00189         if (!RB_TYPE_P(path, T_STRING)) {
00190             rb_bug("class path is not set properly");
00191         }
00192         return path;
00193     }
00194     return find_class_path(klass, (ID)0);
00195 }
00196 
00197 /*
00198  *  call-seq:
00199  *     mod.name    -> string
00200  *
00201  *  Returns the name of the module <i>mod</i>.  Returns nil for anonymous modules.
00202  */
00203 
00204 VALUE
00205 rb_mod_name(VALUE mod)
00206 {
00207     int permanent;
00208     VALUE path = classname(mod, &permanent);
00209 
00210     if (!NIL_P(path)) return rb_str_dup(path);
00211     return path;
00212 }
00213 
00214 typedef VALUE (*path_cache_func)(VALUE obj, ID id, VALUE val);
00215 
00216 static VALUE
00217 rb_tmp_class_path(VALUE klass, int *permanent, path_cache_func cache_path)
00218 {
00219     VALUE path = classname(klass, permanent);
00220     st_data_t n = (st_data_t)path;
00221 
00222     if (!NIL_P(path)) {
00223         return path;
00224     }
00225     if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
00226                                           (st_data_t)tmp_classpath, &n)) {
00227         *permanent = 0;
00228         return (VALUE)n;
00229     }
00230     else {
00231         const char *s = "Class";
00232 
00233         if (RB_TYPE_P(klass, T_MODULE)) {
00234             if (rb_obj_class(klass) == rb_cModule) {
00235                 s = "Module";
00236             }
00237             else {
00238                 int perm;
00239                 VALUE path;
00240 
00241                 path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, cache_path);
00242                 s = RSTRING_PTR(path);
00243             }
00244         }
00245         path = rb_sprintf("#<%s:%p>", s, (void*)klass);
00246         OBJ_FREEZE(path);
00247 
00248         cache_path(klass, tmp_classpath, path);
00249         *permanent = 0;
00250 
00251         return path;
00252     }
00253 }
00254 
00255 VALUE
00256 rb_class_path(VALUE klass)
00257 {
00258     int permanent;
00259     VALUE path = rb_tmp_class_path(klass, &permanent, rb_ivar_set);
00260     if (!NIL_P(path)) path = rb_str_dup(path);
00261     return path;
00262 }
00263 
00264 static VALUE
00265 null_cache(VALUE obj, ID id, VALUE val)
00266 {
00267     return Qnil;
00268 }
00269 
00270 VALUE
00271 rb_class_path_no_cache(VALUE klass)
00272 {
00273     int permanent;
00274     VALUE path = rb_tmp_class_path(klass, &permanent, null_cache);
00275     if (!NIL_P(path)) path = rb_str_dup(path);
00276     return path;
00277 }
00278 
00279 void
00280 rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
00281 {
00282     VALUE str;
00283     ID pathid = classpath;
00284 
00285     if (under == rb_cObject) {
00286         str = rb_str_new_frozen(name);
00287     }
00288     else {
00289         int permanent;
00290         str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set));
00291         rb_str_cat2(str, "::");
00292         rb_str_append(str, name);
00293         OBJ_FREEZE(str);
00294         if (!permanent) {
00295             pathid = tmp_classpath;
00296             rb_ivar_set(klass, classid, ID2SYM(rb_intern_str(name)));
00297         }
00298     }
00299     rb_ivar_set(klass, pathid, str);
00300 }
00301 
00302 void
00303 rb_set_class_path(VALUE klass, VALUE under, const char *name)
00304 {
00305     VALUE str;
00306     ID pathid = classpath;
00307 
00308     if (under == rb_cObject) {
00309         str = rb_str_new2(name);
00310     }
00311     else {
00312         int permanent;
00313         str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set));
00314         rb_str_cat2(str, "::");
00315         rb_str_cat2(str, name);
00316         if (!permanent) {
00317             pathid = tmp_classpath;
00318             rb_ivar_set(klass, classid, ID2SYM(rb_intern(name)));
00319         }
00320     }
00321     OBJ_FREEZE(str);
00322     rb_ivar_set(klass, pathid, str);
00323 }
00324 
00325 VALUE
00326 rb_path_to_class(VALUE pathname)
00327 {
00328     rb_encoding *enc = rb_enc_get(pathname);
00329     const char *pbeg, *p, *path = RSTRING_PTR(pathname);
00330     ID id;
00331     VALUE c = rb_cObject;
00332 
00333     if (!rb_enc_asciicompat(enc)) {
00334         rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
00335     }
00336     pbeg = p = path;
00337     if (path[0] == '#') {
00338         rb_raise(rb_eArgError, "can't retrieve anonymous class %"PRIsVALUE,
00339                  QUOTE(pathname));
00340     }
00341     while (*p) {
00342         while (*p && *p != ':') p++;
00343         id = rb_check_id_cstr(pbeg, p-pbeg, enc);
00344         if (p[0] == ':') {
00345             if (p[1] != ':') goto undefined_class;
00346             p += 2;
00347             pbeg = p;
00348         }
00349         if (!id || !rb_const_defined_at(c, id)) {
00350           undefined_class:
00351             rb_raise(rb_eArgError, "undefined class/module %.*"PRIsVALUE,
00352                      (int)(p-path), pathname);
00353         }
00354         c = rb_const_get_at(c, id);
00355         if (!RB_TYPE_P(c, T_MODULE) && !RB_TYPE_P(c, T_CLASS)) {
00356             rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
00357                      pathname);
00358         }
00359     }
00360     RB_GC_GUARD(pathname);
00361 
00362     return c;
00363 }
00364 
00365 VALUE
00366 rb_path2class(const char *path)
00367 {
00368     return rb_path_to_class(rb_str_new_cstr(path));
00369 }
00370 
00371 void
00372 rb_name_class(VALUE klass, ID id)
00373 {
00374     rb_ivar_set(klass, classid, ID2SYM(id));
00375 }
00376 
00377 VALUE
00378 rb_class_name(VALUE klass)
00379 {
00380     return rb_class_path(rb_class_real(klass));
00381 }
00382 
00383 const char *
00384 rb_class2name(VALUE klass)
00385 {
00386     VALUE name = rb_class_name(klass);
00387     return RSTRING_PTR(name);
00388 }
00389 
00390 const char *
00391 rb_obj_classname(VALUE obj)
00392 {
00393     return rb_class2name(CLASS_OF(obj));
00394 }
00395 
00396 #define global_variable rb_global_variable
00397 #define global_entry rb_global_entry
00398 
00399 #define gvar_getter_t rb_gvar_getter_t
00400 #define gvar_setter_t rb_gvar_setter_t
00401 #define gvar_marker_t rb_gvar_marker_t
00402 
00403 struct trace_var {
00404     int removed;
00405     void (*func)(VALUE arg, VALUE val);
00406     VALUE data;
00407     struct trace_var *next;
00408 };
00409 
00410 struct global_variable {
00411     int   counter;
00412     void *data;
00413     gvar_getter_t *getter;
00414     gvar_setter_t *setter;
00415     gvar_marker_t *marker;
00416     int block_trace;
00417     struct trace_var *trace;
00418 };
00419 
00420 #define undef_getter    rb_gvar_undef_getter
00421 #define undef_setter    rb_gvar_undef_setter
00422 #define undef_marker    rb_gvar_undef_marker
00423 
00424 #define val_getter      rb_gvar_val_getter
00425 #define val_setter      rb_gvar_val_setter
00426 #define val_marker      rb_gvar_val_marker
00427 
00428 #define var_getter      rb_gvar_var_getter
00429 #define var_setter      rb_gvar_var_setter
00430 #define var_marker      rb_gvar_var_marker
00431 
00432 #define readonly_setter rb_gvar_readonly_setter
00433 
00434 struct global_entry*
00435 rb_global_entry(ID id)
00436 {
00437     struct global_entry *entry;
00438     st_data_t data;
00439 
00440     if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
00441         struct global_variable *var;
00442         entry = ALLOC(struct global_entry);
00443         var = ALLOC(struct global_variable);
00444         entry->id = id;
00445         entry->var = var;
00446         var->counter = 1;
00447         var->data = 0;
00448         var->getter = undef_getter;
00449         var->setter = undef_setter;
00450         var->marker = undef_marker;
00451 
00452         var->block_trace = 0;
00453         var->trace = 0;
00454         st_add_direct(rb_global_tbl, id, (st_data_t)entry);
00455     }
00456     else {
00457         entry = (struct global_entry *)data;
00458     }
00459     return entry;
00460 }
00461 
00462 VALUE
00463 undef_getter(ID id, void *data, struct global_variable *var)
00464 {
00465     rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id));
00466 
00467     return Qnil;
00468 }
00469 
00470 void
00471 undef_setter(VALUE val, ID id, void *data, struct global_variable *var)
00472 {
00473     var->getter = val_getter;
00474     var->setter = val_setter;
00475     var->marker = val_marker;
00476 
00477     var->data = (void*)val;
00478 }
00479 
00480 void
00481 undef_marker(VALUE *var)
00482 {
00483 }
00484 
00485 VALUE
00486 val_getter(ID id, void *data, struct global_variable *var)
00487 {
00488     return (VALUE)data;
00489 }
00490 
00491 void
00492 val_setter(VALUE val, ID id, void *data, struct global_variable *var)
00493 {
00494     var->data = (void*)val;
00495 }
00496 
00497 void
00498 val_marker(VALUE *var)
00499 {
00500     VALUE data = (VALUE)var;
00501     if (data) rb_gc_mark_maybe(data);
00502 }
00503 
00504 VALUE
00505 var_getter(ID id, void *data, struct global_variable *gvar)
00506 {
00507     VALUE *var = data;
00508     if (!var) return Qnil;
00509     return *var;
00510 }
00511 
00512 void
00513 var_setter(VALUE val, ID id, void *data, struct global_variable *gvar)
00514 {
00515     *(VALUE *)data = val;
00516 }
00517 
00518 void
00519 var_marker(VALUE *var)
00520 {
00521     if (var) rb_gc_mark_maybe(*var);
00522 }
00523 
00524 void
00525 readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar)
00526 {
00527     rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id));
00528 }
00529 
00530 static int
00531 mark_global_entry(st_data_t k, st_data_t v, st_data_t a)
00532 {
00533     struct global_entry *entry = (struct global_entry *)v;
00534     struct trace_var *trace;
00535     struct global_variable *var = entry->var;
00536 
00537     (*var->marker)(var->data);
00538     trace = var->trace;
00539     while (trace) {
00540         if (trace->data) rb_gc_mark_maybe(trace->data);
00541         trace = trace->next;
00542     }
00543     return ST_CONTINUE;
00544 }
00545 
00546 void
00547 rb_gc_mark_global_tbl(void)
00548 {
00549     if (rb_global_tbl)
00550         st_foreach_safe(rb_global_tbl, mark_global_entry, 0);
00551 }
00552 
00553 static ID
00554 global_id(const char *name)
00555 {
00556     ID id;
00557 
00558     if (name[0] == '$') id = rb_intern(name);
00559     else {
00560         size_t len = strlen(name);
00561         char *buf = ALLOCA_N(char, len+1);
00562         buf[0] = '$';
00563         memcpy(buf+1, name, len);
00564         id = rb_intern2(buf, len+1);
00565     }
00566     return id;
00567 }
00568 
00569 void
00570 rb_define_hooked_variable(
00571     const char *name,
00572     VALUE *var,
00573     VALUE (*getter)(ANYARGS),
00574     void  (*setter)(ANYARGS))
00575 {
00576     volatile VALUE tmp = var ? *var : Qnil;
00577     ID id = global_id(name);
00578     struct global_variable *gvar = rb_global_entry(id)->var;
00579 
00580     gvar->data = (void*)var;
00581     gvar->getter = getter?(gvar_getter_t *)getter:var_getter;
00582     gvar->setter = setter?(gvar_setter_t *)setter:var_setter;
00583     gvar->marker = var_marker;
00584 
00585     RB_GC_GUARD(tmp);
00586 }
00587 
00588 void
00589 rb_define_variable(const char *name, VALUE *var)
00590 {
00591     rb_define_hooked_variable(name, var, 0, 0);
00592 }
00593 
00594 void
00595 rb_define_readonly_variable(const char *name, VALUE *var)
00596 {
00597     rb_define_hooked_variable(name, var, 0, readonly_setter);
00598 }
00599 
00600 void
00601 rb_define_virtual_variable(
00602     const char *name,
00603     VALUE (*getter)(ANYARGS),
00604     void  (*setter)(ANYARGS))
00605 {
00606     if (!getter) getter = val_getter;
00607     if (!setter) setter = readonly_setter;
00608     rb_define_hooked_variable(name, 0, getter, setter);
00609 }
00610 
00611 static void
00612 rb_trace_eval(VALUE cmd, VALUE val)
00613 {
00614     rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
00615 }
00616 
00617 /*
00618  *  call-seq:
00619  *     trace_var(symbol, cmd )             -> nil
00620  *     trace_var(symbol) {|val| block }    -> nil
00621  *
00622  *  Controls tracing of assignments to global variables. The parameter
00623  *  +symbol_ identifies the variable (as either a string name or a
00624  *  symbol identifier). _cmd_ (which may be a string or a
00625  *  +Proc+ object) or block is executed whenever the variable
00626  *  is assigned. The block or +Proc+ object receives the
00627  *  variable's new value as a parameter. Also see
00628  *  <code>Kernel::untrace_var</code>.
00629  *
00630  *     trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
00631  *     $_ = "hello"
00632  *     $_ = ' there'
00633  *
00634  *  <em>produces:</em>
00635  *
00636  *     $_ is now 'hello'
00637  *     $_ is now ' there'
00638  */
00639 
00640 VALUE
00641 rb_f_trace_var(int argc, VALUE *argv)
00642 {
00643     VALUE var, cmd;
00644     struct global_entry *entry;
00645     struct trace_var *trace;
00646 
00647     rb_secure(4);
00648     if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
00649         cmd = rb_block_proc();
00650     }
00651     if (NIL_P(cmd)) {
00652         return rb_f_untrace_var(argc, argv);
00653     }
00654     entry = rb_global_entry(rb_to_id(var));
00655     if (OBJ_TAINTED(cmd)) {
00656         rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
00657     }
00658     trace = ALLOC(struct trace_var);
00659     trace->next = entry->var->trace;
00660     trace->func = rb_trace_eval;
00661     trace->data = cmd;
00662     trace->removed = 0;
00663     entry->var->trace = trace;
00664 
00665     return Qnil;
00666 }
00667 
00668 static void
00669 remove_trace(struct global_variable *var)
00670 {
00671     struct trace_var *trace = var->trace;
00672     struct trace_var t;
00673     struct trace_var *next;
00674 
00675     t.next = trace;
00676     trace = &t;
00677     while (trace->next) {
00678         next = trace->next;
00679         if (next->removed) {
00680             trace->next = next->next;
00681             xfree(next);
00682         }
00683         else {
00684             trace = next;
00685         }
00686     }
00687     var->trace = t.next;
00688 }
00689 
00690 /*
00691  *  call-seq:
00692  *     untrace_var(symbol [, cmd] )   -> array or nil
00693  *
00694  *  Removes tracing for the specified command on the given global
00695  *  variable and returns +nil+. If no command is specified,
00696  *  removes all tracing for that variable and returns an array
00697  *  containing the commands actually removed.
00698  */
00699 
00700 VALUE
00701 rb_f_untrace_var(int argc, VALUE *argv)
00702 {
00703     VALUE var, cmd;
00704     ID id;
00705     struct global_entry *entry;
00706     struct trace_var *trace;
00707     st_data_t data;
00708 
00709     rb_secure(4);
00710     rb_scan_args(argc, argv, "11", &var, &cmd);
00711     id = rb_check_id(&var);
00712     if (!id) {
00713         rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
00714     }
00715     if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
00716         rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
00717     }
00718 
00719     trace = (entry = (struct global_entry *)data)->var->trace;
00720     if (NIL_P(cmd)) {
00721         VALUE ary = rb_ary_new();
00722 
00723         while (trace) {
00724             struct trace_var *next = trace->next;
00725             rb_ary_push(ary, (VALUE)trace->data);
00726             trace->removed = 1;
00727             trace = next;
00728         }
00729 
00730         if (!entry->var->block_trace) remove_trace(entry->var);
00731         return ary;
00732     }
00733     else {
00734         while (trace) {
00735             if (trace->data == cmd) {
00736                 trace->removed = 1;
00737                 if (!entry->var->block_trace) remove_trace(entry->var);
00738                 return rb_ary_new3(1, cmd);
00739             }
00740             trace = trace->next;
00741         }
00742     }
00743     return Qnil;
00744 }
00745 
00746 VALUE
00747 rb_gvar_get(struct global_entry *entry)
00748 {
00749     struct global_variable *var = entry->var;
00750     return (*var->getter)(entry->id, var->data, var);
00751 }
00752 
00753 struct trace_data {
00754     struct trace_var *trace;
00755     VALUE val;
00756 };
00757 
00758 static VALUE
00759 trace_ev(struct trace_data *data)
00760 {
00761     struct trace_var *trace = data->trace;
00762 
00763     while (trace) {
00764         (*trace->func)(trace->data, data->val);
00765         trace = trace->next;
00766     }
00767 
00768     return Qnil;
00769 }
00770 
00771 static VALUE
00772 trace_en(struct global_variable *var)
00773 {
00774     var->block_trace = 0;
00775     remove_trace(var);
00776     return Qnil;                /* not reached */
00777 }
00778 
00779 VALUE
00780 rb_gvar_set(struct global_entry *entry, VALUE val)
00781 {
00782     struct trace_data trace;
00783     struct global_variable *var = entry->var;
00784 
00785     if (rb_safe_level() >= 4)
00786         rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
00787     (*var->setter)(val, entry->id, var->data, var);
00788 
00789     if (var->trace && !var->block_trace) {
00790         var->block_trace = 1;
00791         trace.trace = var->trace;
00792         trace.val = val;
00793         rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
00794     }
00795     return val;
00796 }
00797 
00798 VALUE
00799 rb_gv_set(const char *name, VALUE val)
00800 {
00801     struct global_entry *entry;
00802 
00803     entry = rb_global_entry(global_id(name));
00804     return rb_gvar_set(entry, val);
00805 }
00806 
00807 VALUE
00808 rb_gv_get(const char *name)
00809 {
00810     struct global_entry *entry;
00811 
00812     entry = rb_global_entry(global_id(name));
00813     return rb_gvar_get(entry);
00814 }
00815 
00816 VALUE
00817 rb_gvar_defined(struct global_entry *entry)
00818 {
00819     if (entry->var->getter == undef_getter) return Qfalse;
00820     return Qtrue;
00821 }
00822 
00823 static int
00824 gvar_i(st_data_t k, st_data_t v, st_data_t a)
00825 {
00826     ID key = (ID)k;
00827     VALUE ary = (VALUE)a;
00828     rb_ary_push(ary, ID2SYM(key));
00829     return ST_CONTINUE;
00830 }
00831 
00832 /*
00833  *  call-seq:
00834  *     global_variables    -> array
00835  *
00836  *  Returns an array of the names of global variables.
00837  *
00838  *     global_variables.grep /std/   #=> [:$stdin, :$stdout, :$stderr]
00839  */
00840 
00841 VALUE
00842 rb_f_global_variables(void)
00843 {
00844     VALUE ary = rb_ary_new();
00845     char buf[2];
00846     int i;
00847 
00848     st_foreach_safe(rb_global_tbl, gvar_i, ary);
00849     buf[0] = '$';
00850     for (i = 1; i <= 9; ++i) {
00851         buf[1] = (char)(i + '0');
00852         rb_ary_push(ary, ID2SYM(rb_intern2(buf, 2)));
00853     }
00854     return ary;
00855 }
00856 
00857 void
00858 rb_alias_variable(ID name1, ID name2)
00859 {
00860     struct global_entry *entry1, *entry2;
00861     st_data_t data1;
00862 
00863     if (rb_safe_level() >= 4)
00864         rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
00865 
00866     entry2 = rb_global_entry(name2);
00867     if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) {
00868         entry1 = ALLOC(struct global_entry);
00869         entry1->id = name1;
00870         st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
00871     }
00872     else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) {
00873         struct global_variable *var = entry1->var;
00874         if (var->block_trace) {
00875             rb_raise(rb_eRuntimeError, "can't alias in tracer");
00876         }
00877         var->counter--;
00878         if (var->counter == 0) {
00879             struct trace_var *trace = var->trace;
00880             while (trace) {
00881                 struct trace_var *next = trace->next;
00882                 xfree(trace);
00883                 trace = next;
00884             }
00885             xfree(var);
00886         }
00887     }
00888     else {
00889         return;
00890     }
00891     entry2->var->counter++;
00892     entry1->var = entry2->var;
00893 }
00894 
00895 static int special_generic_ivar = 0;
00896 static st_table *generic_iv_tbl;
00897 
00898 st_table*
00899 rb_generic_ivar_table(VALUE obj)
00900 {
00901     st_data_t tbl;
00902 
00903     if (!FL_TEST(obj, FL_EXIVAR)) return 0;
00904     if (!generic_iv_tbl) return 0;
00905     if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0;
00906     return (st_table *)tbl;
00907 }
00908 
00909 static VALUE
00910 generic_ivar_get(VALUE obj, ID id, int warn)
00911 {
00912     st_data_t tbl, val;
00913 
00914     if (generic_iv_tbl) {
00915         if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
00916             if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) {
00917                 return (VALUE)val;
00918             }
00919         }
00920     }
00921     if (warn) {
00922         rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id));
00923     }
00924     return Qnil;
00925 }
00926 
00927 static void
00928 generic_ivar_set(VALUE obj, ID id, VALUE val)
00929 {
00930     st_table *tbl;
00931     st_data_t data;
00932 
00933     if (rb_special_const_p(obj)) {
00934         if (rb_obj_frozen_p(obj)) rb_error_frozen("object");
00935         special_generic_ivar = 1;
00936     }
00937     if (!generic_iv_tbl) {
00938         generic_iv_tbl = st_init_numtable();
00939     }
00940     if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
00941         FL_SET(obj, FL_EXIVAR);
00942         tbl = st_init_numtable();
00943         st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl);
00944         st_add_direct(tbl, (st_data_t)id, (st_data_t)val);
00945         return;
00946     }
00947     st_insert((st_table *)data, (st_data_t)id, (st_data_t)val);
00948 }
00949 
00950 static VALUE
00951 generic_ivar_defined(VALUE obj, ID id)
00952 {
00953     st_table *tbl;
00954     st_data_t data;
00955 
00956     if (!generic_iv_tbl) return Qfalse;
00957     if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse;
00958     tbl = (st_table *)data;
00959     if (st_lookup(tbl, (st_data_t)id, &data)) {
00960         return Qtrue;
00961     }
00962     return Qfalse;
00963 }
00964 
00965 static int
00966 generic_ivar_remove(VALUE obj, ID id, st_data_t *valp)
00967 {
00968     st_table *tbl;
00969     st_data_t data, key = (st_data_t)id;
00970     int status;
00971 
00972     if (!generic_iv_tbl) return 0;
00973     if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0;
00974     tbl = (st_table *)data;
00975     status = st_delete(tbl, &key, valp);
00976     if (tbl->num_entries == 0) {
00977         key = (st_data_t)obj;
00978         st_delete(generic_iv_tbl, &key, &data);
00979         st_free_table((st_table *)data);
00980     }
00981     return status;
00982 }
00983 
00984 void
00985 rb_mark_generic_ivar(VALUE obj)
00986 {
00987     st_data_t tbl;
00988 
00989     if (!generic_iv_tbl) return;
00990     if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
00991         rb_mark_tbl((st_table *)tbl);
00992     }
00993 }
00994 
00995 static int
00996 givar_mark_i(st_data_t k, st_data_t v, st_data_t a)
00997 {
00998     VALUE value = (VALUE)v;
00999     rb_gc_mark(value);
01000     return ST_CONTINUE;
01001 }
01002 
01003 static int
01004 givar_i(st_data_t k, st_data_t v, st_data_t a)
01005 {
01006     VALUE obj = (VALUE)k;
01007     st_table *tbl = (st_table *)v;
01008     if (rb_special_const_p(obj)) {
01009         st_foreach_safe(tbl, givar_mark_i, 0);
01010     }
01011     return ST_CONTINUE;
01012 }
01013 
01014 void
01015 rb_mark_generic_ivar_tbl(void)
01016 {
01017     if (!generic_iv_tbl) return;
01018     if (special_generic_ivar == 0) return;
01019     st_foreach_safe(generic_iv_tbl, givar_i, 0);
01020 }
01021 
01022 void
01023 rb_free_generic_ivar(VALUE obj)
01024 {
01025     st_data_t key = (st_data_t)obj, tbl;
01026 
01027     if (!generic_iv_tbl) return;
01028     if (st_delete(generic_iv_tbl, &key, &tbl))
01029         st_free_table((st_table *)tbl);
01030 }
01031 
01032 RUBY_FUNC_EXPORTED size_t
01033 rb_generic_ivar_memsize(VALUE obj)
01034 {
01035     st_data_t tbl;
01036     if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl))
01037         return st_memsize((st_table *)tbl);
01038     return 0;
01039 }
01040 
01041 void
01042 rb_copy_generic_ivar(VALUE clone, VALUE obj)
01043 {
01044     st_data_t data;
01045 
01046     if (!generic_iv_tbl) return;
01047     if (!FL_TEST(obj, FL_EXIVAR)) {
01048       clear:
01049         if (FL_TEST(clone, FL_EXIVAR)) {
01050             rb_free_generic_ivar(clone);
01051             FL_UNSET(clone, FL_EXIVAR);
01052         }
01053         return;
01054     }
01055     if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
01056         st_table *tbl = (st_table *)data;
01057 
01058         if (tbl->num_entries == 0)
01059             goto clear;
01060 
01061         if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) {
01062             st_free_table((st_table *)data);
01063             st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl));
01064         }
01065         else {
01066             st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl));
01067             FL_SET(clone, FL_EXIVAR);
01068         }
01069     }
01070 }
01071 
01072 static VALUE
01073 ivar_get(VALUE obj, ID id, int warn)
01074 {
01075     VALUE val, *ptr;
01076     struct st_table *iv_index_tbl;
01077     long len;
01078     st_data_t index;
01079 
01080     if (SPECIAL_CONST_P(obj)) goto generic;
01081     switch (BUILTIN_TYPE(obj)) {
01082       case T_OBJECT:
01083         len = ROBJECT_NUMIV(obj);
01084         ptr = ROBJECT_IVPTR(obj);
01085         iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01086         if (!iv_index_tbl) break;
01087         if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
01088         if (len <= (long)index) break;
01089         val = ptr[index];
01090         if (val != Qundef)
01091             return val;
01092         break;
01093       case T_CLASS:
01094       case T_MODULE:
01095         if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index))
01096             return (VALUE)index;
01097         break;
01098       default:
01099       generic:
01100         if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
01101             return generic_ivar_get(obj, id, warn);
01102         break;
01103     }
01104     if (warn) {
01105         rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id));
01106     }
01107     return Qnil;
01108 }
01109 
01110 VALUE
01111 rb_ivar_get(VALUE obj, ID id)
01112 {
01113     return ivar_get(obj, id, TRUE);
01114 }
01115 
01116 VALUE
01117 rb_attr_get(VALUE obj, ID id)
01118 {
01119     return ivar_get(obj, id, FALSE);
01120 }
01121 
01122 VALUE
01123 rb_ivar_set(VALUE obj, ID id, VALUE val)
01124 {
01125     struct st_table *iv_index_tbl;
01126     st_data_t index;
01127     long i, len;
01128     int ivar_extended;
01129 
01130     if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
01131         rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
01132     rb_check_frozen(obj);
01133     if (SPECIAL_CONST_P(obj)) goto generic;
01134     switch (BUILTIN_TYPE(obj)) {
01135       case T_OBJECT:
01136         iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01137         if (!iv_index_tbl) {
01138             VALUE klass = rb_obj_class(obj);
01139             iv_index_tbl = RCLASS_IV_INDEX_TBL(klass);
01140             if (!iv_index_tbl) {
01141                 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
01142             }
01143         }
01144         ivar_extended = 0;
01145         if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
01146             index = iv_index_tbl->num_entries;
01147             st_add_direct(iv_index_tbl, (st_data_t)id, index);
01148             ivar_extended = 1;
01149         }
01150         len = ROBJECT_NUMIV(obj);
01151         if (len <= (long)index) {
01152             VALUE *ptr = ROBJECT_IVPTR(obj);
01153             if (index < ROBJECT_EMBED_LEN_MAX) {
01154                 RBASIC(obj)->flags |= ROBJECT_EMBED;
01155                 ptr = ROBJECT(obj)->as.ary;
01156                 for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) {
01157                     ptr[i] = Qundef;
01158                 }
01159             }
01160             else {
01161                 VALUE *newptr;
01162                 long newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */
01163                 if (!ivar_extended &&
01164                     iv_index_tbl->num_entries < (st_index_t)newsize) {
01165                     newsize = iv_index_tbl->num_entries;
01166                 }
01167                 if (RBASIC(obj)->flags & ROBJECT_EMBED) {
01168                     newptr = ALLOC_N(VALUE, newsize);
01169                     MEMCPY(newptr, ptr, VALUE, len);
01170                     RBASIC(obj)->flags &= ~ROBJECT_EMBED;
01171                     ROBJECT(obj)->as.heap.ivptr = newptr;
01172                 }
01173                 else {
01174                     REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize);
01175                     newptr = ROBJECT(obj)->as.heap.ivptr;
01176                 }
01177                 for (; len < newsize; len++)
01178                     newptr[len] = Qundef;
01179                 ROBJECT(obj)->as.heap.numiv = newsize;
01180                 ROBJECT(obj)->as.heap.iv_index_tbl = iv_index_tbl;
01181             }
01182         }
01183         ROBJECT_IVPTR(obj)[index] = val;
01184         break;
01185       case T_CLASS:
01186       case T_MODULE:
01187         if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
01188         st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val);
01189         break;
01190       default:
01191       generic:
01192         generic_ivar_set(obj, id, val);
01193         break;
01194     }
01195     return val;
01196 }
01197 
01198 VALUE
01199 rb_ivar_defined(VALUE obj, ID id)
01200 {
01201     VALUE val;
01202     struct st_table *iv_index_tbl;
01203     st_data_t index;
01204     if (SPECIAL_CONST_P(obj)) goto generic;
01205     switch (BUILTIN_TYPE(obj)) {
01206       case T_OBJECT:
01207         iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01208         if (!iv_index_tbl) break;
01209         if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
01210         if (ROBJECT_NUMIV(obj) <= (long)index) break;
01211         val = ROBJECT_IVPTR(obj)[index];
01212         if (val != Qundef)
01213             return Qtrue;
01214         break;
01215       case T_CLASS:
01216       case T_MODULE:
01217         if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0))
01218             return Qtrue;
01219         break;
01220       default:
01221       generic:
01222         if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
01223             return generic_ivar_defined(obj, id);
01224         break;
01225     }
01226     return Qfalse;
01227 }
01228 
01229 struct obj_ivar_tag {
01230     VALUE obj;
01231     int (*func)(ID key, VALUE val, st_data_t arg);
01232     st_data_t arg;
01233 };
01234 
01235 static int
01236 obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg)
01237 {
01238     struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg;
01239     if ((long)index < ROBJECT_NUMIV(data->obj)) {
01240         VALUE val = ROBJECT_IVPTR(data->obj)[(long)index];
01241         if (val != Qundef) {
01242             return (data->func)((ID)key, val, data->arg);
01243         }
01244     }
01245     return ST_CONTINUE;
01246 }
01247 
01248 static void
01249 obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
01250 {
01251     st_table *tbl;
01252     struct obj_ivar_tag data;
01253 
01254     tbl = ROBJECT_IV_INDEX_TBL(obj);
01255     if (!tbl)
01256         return;
01257 
01258     data.obj = obj;
01259     data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
01260     data.arg = arg;
01261 
01262     st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
01263 }
01264 
01265 void
01266 rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
01267 {
01268     if (SPECIAL_CONST_P(obj)) goto generic;
01269     switch (BUILTIN_TYPE(obj)) {
01270       case T_OBJECT:
01271         obj_ivar_each(obj, func, arg);
01272         break;
01273       case T_CLASS:
01274       case T_MODULE:
01275         if (RCLASS_IV_TBL(obj)) {
01276             st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
01277         }
01278         break;
01279       default:
01280       generic:
01281         if (!generic_iv_tbl) break;
01282         if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
01283             st_data_t tbl;
01284 
01285             if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) {
01286                 st_foreach_safe((st_table *)tbl, func, arg);
01287             }
01288         }
01289         break;
01290     }
01291 }
01292 
01293 st_index_t
01294 rb_ivar_count(VALUE obj)
01295 {
01296     st_table *tbl;
01297     if (SPECIAL_CONST_P(obj)) goto generic;
01298     switch (BUILTIN_TYPE(obj)) {
01299       case T_OBJECT:
01300         if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) {
01301             st_index_t i, count, num = tbl->num_entries;
01302             const VALUE *const ivptr = ROBJECT_IVPTR(obj);
01303             for (i = count = 0; i < num; ++i) {
01304                 if (ivptr[i] != Qundef) {
01305                     count++;
01306                 }
01307             }
01308             return count;
01309         }
01310         break;
01311       case T_CLASS:
01312       case T_MODULE:
01313         if ((tbl = RCLASS_IV_TBL(obj)) != 0) {
01314             return tbl->num_entries;
01315         }
01316         break;
01317       default:
01318       generic:
01319         if (!generic_iv_tbl) break;
01320         if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
01321             st_data_t data;
01322 
01323             if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) &&
01324                 (tbl = (st_table *)data) != 0) {
01325                 return tbl->num_entries;
01326             }
01327         }
01328         break;
01329     }
01330     return 0;
01331 }
01332 
01333 static int
01334 ivar_i(st_data_t k, st_data_t v, st_data_t a)
01335 {
01336     ID key = (ID)k;
01337     VALUE ary = (VALUE)a;
01338 
01339     if (rb_is_instance_id(key)) {
01340         rb_ary_push(ary, ID2SYM(key));
01341     }
01342     return ST_CONTINUE;
01343 }
01344 
01345 /*
01346  *  call-seq:
01347  *     obj.instance_variables    -> array
01348  *
01349  *  Returns an array of instance variable names for the receiver. Note
01350  *  that simply defining an accessor does not create the corresponding
01351  *  instance variable.
01352  *
01353  *     class Fred
01354  *       attr_accessor :a1
01355  *       def initialize
01356  *         @iv = 3
01357  *       end
01358  *     end
01359  *     Fred.new.instance_variables   #=> [:@iv]
01360  */
01361 
01362 VALUE
01363 rb_obj_instance_variables(VALUE obj)
01364 {
01365     VALUE ary;
01366 
01367     ary = rb_ary_new();
01368     rb_ivar_foreach(obj, ivar_i, ary);
01369     return ary;
01370 }
01371 
01372 /*
01373  *  call-seq:
01374  *     obj.remove_instance_variable(symbol)    -> obj
01375  *
01376  *  Removes the named instance variable from <i>obj</i>, returning that
01377  *  variable's value.
01378  *
01379  *     class Dummy
01380  *       attr_reader :var
01381  *       def initialize
01382  *         @var = 99
01383  *       end
01384  *       def remove
01385  *         remove_instance_variable(:@var)
01386  *       end
01387  *     end
01388  *     d = Dummy.new
01389  *     d.var      #=> 99
01390  *     d.remove   #=> 99
01391  *     d.var      #=> nil
01392  */
01393 
01394 VALUE
01395 rb_obj_remove_instance_variable(VALUE obj, VALUE name)
01396 {
01397     VALUE val = Qnil;
01398     const ID id = rb_check_id(&name);
01399     st_data_t n, v;
01400     struct st_table *iv_index_tbl;
01401     st_data_t index;
01402 
01403     if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4)
01404         rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
01405     rb_check_frozen(obj);
01406     if (!id) {
01407         if (rb_is_instance_name(name)) {
01408             rb_name_error_str(name, "instance variable %"PRIsVALUE" not defined",
01409                               name);
01410         }
01411         else {
01412             rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as an instance variable name",
01413                               QUOTE(name));
01414         }
01415     }
01416     if (!rb_is_instance_id(id)) {
01417         rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
01418                       QUOTE_ID(id));
01419     }
01420 
01421     if (SPECIAL_CONST_P(obj)) goto generic;
01422     switch (BUILTIN_TYPE(obj)) {
01423       case T_OBJECT:
01424         iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
01425         if (!iv_index_tbl) break;
01426         if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
01427         if (ROBJECT_NUMIV(obj) <= (long)index) break;
01428         val = ROBJECT_IVPTR(obj)[index];
01429         if (val != Qundef) {
01430             ROBJECT_IVPTR(obj)[index] = Qundef;
01431             return val;
01432         }
01433         break;
01434       case T_CLASS:
01435       case T_MODULE:
01436         n = id;
01437         if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
01438             return (VALUE)v;
01439         }
01440         break;
01441       default:
01442       generic:
01443         if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
01444             v = val;
01445             if (generic_ivar_remove(obj, (st_data_t)id, &v)) {
01446                 return (VALUE)v;
01447             }
01448         }
01449         break;
01450     }
01451     rb_name_error(id, "instance variable %"PRIsVALUE" not defined", QUOTE_ID(id));
01452 
01453     UNREACHABLE;
01454 }
01455 
01456 NORETURN(static void uninitialized_constant(VALUE, ID));
01457 static void
01458 uninitialized_constant(VALUE klass, ID id)
01459 {
01460     if (klass && rb_class_real(klass) != rb_cObject)
01461         rb_name_error(id, "uninitialized constant %"PRIsVALUE"::%"PRIsVALUE"",
01462                       rb_class_name(klass),
01463                       QUOTE_ID(id));
01464     else {
01465         rb_name_error(id, "uninitialized constant %"PRIsVALUE"", QUOTE_ID(id));
01466     }
01467 }
01468 
01469 static VALUE
01470 const_missing(VALUE klass, ID id)
01471 {
01472     return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
01473 }
01474 
01475 
01476 /*
01477  * call-seq:
01478  *    mod.const_missing(sym)    -> obj
01479  *
01480  * Invoked when a reference is made to an undefined constant in
01481  * <i>mod</i>. It is passed a symbol for the undefined constant, and
01482  * returns a value to be used for that constant. The
01483  * following code is an example of the same:
01484  *
01485  *   def Foo.const_missing(name)
01486  *     name # return the constant name as Symbol
01487  *   end
01488  *
01489  *   Foo::UNDEFINED_CONST    #=> :UNDEFINED_CONST: symbol returned
01490  *
01491  * In the next example when a reference is made to an undefined constant,
01492  * it attempts to load a file whose name is the lowercase version of the
01493  * constant (thus class <code>Fred</code> is assumed to be in file
01494  * <code>fred.rb</code>).  If found, it returns the loaded class. It
01495  * therefore implements an autoload feature similar to Kernel#autoload and
01496  * Module#autoload.
01497  *
01498  *   def Object.const_missing(name)
01499  *     @looked_for ||= {}
01500  *     str_name = name.to_s
01501  *     raise "Class not found: #{name}" if @looked_for[str_name]
01502  *     @looked_for[str_name] = 1
01503  *     file = str_name.downcase
01504  *     require file
01505  *     klass = const_get(name)
01506  *     return klass if klass
01507  *     raise "Class not found: #{name}"
01508  *   end
01509  *
01510  */
01511 
01512 VALUE
01513 rb_mod_const_missing(VALUE klass, VALUE name)
01514 {
01515     rb_frame_pop(); /* pop frame for "const_missing" */
01516     uninitialized_constant(klass, rb_to_id(name));
01517 
01518     UNREACHABLE;
01519 }
01520 
01521 static void
01522 autoload_mark(void *ptr)
01523 {
01524     rb_mark_tbl((st_table *)ptr);
01525 }
01526 
01527 static void
01528 autoload_free(void *ptr)
01529 {
01530     st_free_table((st_table *)ptr);
01531 }
01532 
01533 static size_t
01534 autoload_memsize(const void *ptr)
01535 {
01536     const st_table *tbl = ptr;
01537     return st_memsize(tbl);
01538 }
01539 
01540 static const rb_data_type_t autoload_data_type = {
01541     "autoload",
01542     {autoload_mark, autoload_free, autoload_memsize,},
01543 };
01544 
01545 #define check_autoload_table(av) \
01546     (struct st_table *)rb_check_typeddata((av), &autoload_data_type)
01547 
01548 static VALUE
01549 autoload_data(VALUE mod, ID id)
01550 {
01551     struct st_table *tbl;
01552     st_data_t val;
01553 
01554     if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
01555             !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) {
01556         return 0;
01557     }
01558     return (VALUE)val;
01559 }
01560 
01561 struct autoload_data_i {
01562     VALUE feature;
01563     int safe_level;
01564     VALUE thread;
01565     VALUE value;
01566 };
01567 
01568 static void
01569 autoload_i_mark(void *ptr)
01570 {
01571     struct autoload_data_i *p = ptr;
01572     rb_gc_mark(p->feature);
01573     rb_gc_mark(p->thread);
01574     rb_gc_mark(p->value);
01575 }
01576 
01577 static void
01578 autoload_i_free(void *ptr)
01579 {
01580     struct autoload_data_i *p = ptr;
01581     xfree(p);
01582 }
01583 
01584 static size_t
01585 autoload_i_memsize(const void *ptr)
01586 {
01587     return sizeof(struct autoload_data_i);
01588 }
01589 
01590 static const rb_data_type_t autoload_data_i_type = {
01591     "autoload_i",
01592     {autoload_i_mark, autoload_i_free, autoload_i_memsize,},
01593 };
01594 
01595 #define check_autoload_data(av) \
01596     (struct autoload_data_i *)rb_check_typeddata((av), &autoload_data_i_type)
01597 
01598 void
01599 rb_autoload(VALUE mod, ID id, const char *file)
01600 {
01601     st_data_t av;
01602     VALUE ad, fn;
01603     struct st_table *tbl;
01604     struct autoload_data_i *ele;
01605 
01606     if (!rb_is_const_id(id)) {
01607         rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"",
01608                  QUOTE_ID(id));
01609     }
01610     if (!file || !*file) {
01611         rb_raise(rb_eArgError, "empty file name");
01612     }
01613 
01614     if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef)
01615         return;
01616 
01617     rb_const_set(mod, id, Qundef);
01618     tbl = RCLASS_IV_TBL(mod);
01619     if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) {
01620         tbl = check_autoload_table((VALUE)av);
01621     }
01622     else {
01623         if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable();
01624         av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0);
01625         st_add_direct(tbl, (st_data_t)autoload, av);
01626         DATA_PTR(av) = tbl = st_init_numtable();
01627     }
01628     fn = rb_str_new2(file);
01629     FL_UNSET(fn, FL_TAINT);
01630     OBJ_FREEZE(fn);
01631 
01632     ele = ALLOC(struct autoload_data_i);
01633     ele->feature = fn;
01634     ele->safe_level = rb_safe_level();
01635     ele->thread = Qnil;
01636     ele->value = Qundef;
01637     ad = TypedData_Wrap_Struct(0, &autoload_data_i_type, ele);
01638     st_insert(tbl, (st_data_t)id, (st_data_t)ad);
01639 }
01640 
01641 static void
01642 autoload_delete(VALUE mod, ID id)
01643 {
01644     st_data_t val, load = 0, n = id;
01645     rb_const_entry_t *ce;
01646 
01647     st_delete(RCLASS_CONST_TBL(mod), &n, &val);
01648     ce = (rb_const_entry_t*)val;
01649     if (ce) xfree(ce);
01650     if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) {
01651         struct st_table *tbl = check_autoload_table((VALUE)val);
01652 
01653         st_delete(tbl, &n, &load);
01654 
01655         if (tbl->num_entries == 0) {
01656             n = autoload;
01657             st_delete(RCLASS_IV_TBL(mod), &n, &val);
01658         }
01659     }
01660 }
01661 
01662 static VALUE
01663 autoload_provided(VALUE arg)
01664 {
01665     const char **p = (const char **)arg;
01666     return rb_feature_provided(*p, p);
01667 }
01668 
01669 static VALUE
01670 reset_safe(VALUE safe)
01671 {
01672     rb_set_safe_level_force((int)safe);
01673     return safe;
01674 }
01675 
01676 static VALUE
01677 check_autoload_required(VALUE mod, ID id, const char **loadingpath)
01678 {
01679     VALUE file, load;
01680     struct autoload_data_i *ele;
01681     const char *loading;
01682     int safe;
01683 
01684     if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) {
01685         return 0;
01686     }
01687     file = ele->feature;
01688     Check_Type(file, T_STRING);
01689     if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) {
01690         rb_raise(rb_eArgError, "empty file name");
01691     }
01692     loading = RSTRING_PTR(file);
01693     safe = rb_safe_level();
01694     rb_set_safe_level_force(0);
01695     if (!rb_ensure(autoload_provided, (VALUE)&loading, reset_safe, (VALUE)safe)) {
01696         return load;
01697     }
01698     if (loadingpath && loading) {
01699         *loadingpath = loading;
01700         return load;
01701     }
01702     return 0;
01703 }
01704 
01705 int
01706 rb_autoloading_value(VALUE mod, ID id, VALUE* value)
01707 {
01708     VALUE load;
01709     struct autoload_data_i *ele;
01710 
01711     if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) {
01712         return 0;
01713     }
01714     if (ele->thread == rb_thread_current()) {
01715         if (ele->value != Qundef) {
01716             if (value) {
01717                 *value = ele->value;
01718             }
01719             return 1;
01720         }
01721     }
01722     return 0;
01723 }
01724 
01725 static int
01726 autoload_defined_p(VALUE mod, ID id)
01727 {
01728     struct st_table *tbl = RCLASS_CONST_TBL(mod);
01729     st_data_t val;
01730 
01731     if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) {
01732         return 0;
01733     }
01734     return !rb_autoloading_value(mod, id, NULL);
01735 }
01736 
01737 struct autoload_const_set_args {
01738     VALUE mod;
01739     ID id;
01740     VALUE value;
01741 };
01742 
01743 static VALUE
01744 autoload_const_set(VALUE arg)
01745 {
01746     struct autoload_const_set_args* args = (struct autoload_const_set_args *)arg;
01747     autoload_delete(args->mod, args->id);
01748     rb_const_set(args->mod, args->id, args->value);
01749     return 0;                   /* ignored */
01750 }
01751 
01752 static VALUE
01753 autoload_require(VALUE arg)
01754 {
01755     struct autoload_data_i *ele = (struct autoload_data_i *)arg;
01756     return rb_require_safe(ele->feature, ele->safe_level);
01757 }
01758 
01759 VALUE
01760 rb_autoload_load(VALUE mod, ID id)
01761 {
01762     VALUE load, result;
01763     const char *loading = 0, *src;
01764     struct autoload_data_i *ele;
01765     int state = 0;
01766 
01767     if (!autoload_defined_p(mod, id)) return Qfalse;
01768     load = check_autoload_required(mod, id, &loading);
01769     if (!load) return Qfalse;
01770     src = rb_sourcefile();
01771     if (src && loading && strcmp(src, loading) == 0) return Qfalse;
01772 
01773     /* set ele->thread for a marker of autoloading thread */
01774     if (!(ele = check_autoload_data(load))) {
01775         return Qfalse;
01776     }
01777     if (ele->thread == Qnil) {
01778         ele->thread = rb_thread_current();
01779     }
01780     /* autoload_data_i can be deleted by another thread while require */
01781     result = rb_protect(autoload_require, (VALUE)ele, &state);
01782     if (ele->thread == rb_thread_current()) {
01783         ele->thread = Qnil;
01784     }
01785     if (state) rb_jump_tag(state);
01786 
01787     if (RTEST(result)) {
01788         /* At the last, move a value defined in autoload to constant table */
01789         if (ele->value != Qundef) {
01790             int safe_backup;
01791             struct autoload_const_set_args args;
01792             args.mod = mod;
01793             args.id = id;
01794             args.value = ele->value;
01795             safe_backup = rb_safe_level();
01796             rb_set_safe_level_force(ele->safe_level);
01797             rb_ensure(autoload_const_set, (VALUE)&args, reset_safe, (VALUE)safe_backup);
01798         }
01799     }
01800     RB_GC_GUARD(load);
01801     return result;
01802 }
01803 
01804 VALUE
01805 rb_autoload_p(VALUE mod, ID id)
01806 {
01807     VALUE load;
01808     struct autoload_data_i *ele;
01809 
01810     while (!autoload_defined_p(mod, id)) {
01811         mod = RCLASS_SUPER(mod);
01812         if (!mod) return Qnil;
01813     }
01814     load = check_autoload_required(mod, id, 0);
01815     if (!load) return Qnil;
01816     return (ele = check_autoload_data(load)) ? ele->feature : Qnil;
01817 }
01818 
01819 static VALUE
01820 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
01821 {
01822     VALUE value, tmp, av;
01823     int mod_retry = 0;
01824 
01825     tmp = klass;
01826   retry:
01827     while (RTEST(tmp)) {
01828         VALUE am = 0;
01829         st_data_t data;
01830         while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) {
01831             rb_const_entry_t *ce = (rb_const_entry_t *)data;
01832             if (visibility && ce->flag == CONST_PRIVATE) {
01833                 rb_name_error(id, "private constant %"PRIsVALUE"::%"PRIsVALUE" referenced",
01834                               rb_class_name(klass), QUOTE_ID(id));
01835             }
01836             value = ce->value;
01837             if (value == Qundef) {
01838                 if (am == tmp) break;
01839                 am = tmp;
01840                 if (rb_autoloading_value(tmp, id, &av)) return av;
01841                 rb_autoload_load(tmp, id);
01842                 continue;
01843             }
01844             if (exclude && tmp == rb_cObject && klass != rb_cObject) {
01845                 rb_warn("toplevel constant %"PRIsVALUE" referenced by %"PRIsVALUE"::%"PRIsVALUE"",
01846                         QUOTE_ID(id), rb_class_name(klass), QUOTE_ID(id));
01847             }
01848             return value;
01849         }
01850         if (!recurse) break;
01851         tmp = RCLASS_SUPER(tmp);
01852     }
01853     if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
01854         mod_retry = 1;
01855         tmp = rb_cObject;
01856         goto retry;
01857     }
01858 
01859     value = const_missing(klass, id);
01860     rb_vm_inc_const_missing_count();
01861     return value;
01862 }
01863 
01864 VALUE
01865 rb_const_get_from(VALUE klass, ID id)
01866 {
01867     return rb_const_get_0(klass, id, TRUE, TRUE, FALSE);
01868 }
01869 
01870 VALUE
01871 rb_const_get(VALUE klass, ID id)
01872 {
01873     return rb_const_get_0(klass, id, FALSE, TRUE, FALSE);
01874 }
01875 
01876 VALUE
01877 rb_const_get_at(VALUE klass, ID id)
01878 {
01879     return rb_const_get_0(klass, id, TRUE, FALSE, FALSE);
01880 }
01881 
01882 VALUE
01883 rb_public_const_get_from(VALUE klass, ID id)
01884 {
01885     return rb_const_get_0(klass, id, TRUE, TRUE, TRUE);
01886 }
01887 
01888 VALUE
01889 rb_public_const_get(VALUE klass, ID id)
01890 {
01891     return rb_const_get_0(klass, id, FALSE, TRUE, TRUE);
01892 }
01893 
01894 VALUE
01895 rb_public_const_get_at(VALUE klass, ID id)
01896 {
01897     return rb_const_get_0(klass, id, TRUE, FALSE, TRUE);
01898 }
01899 
01900 /*
01901  *  call-seq:
01902  *     remove_const(sym)   -> obj
01903  *
01904  *  Removes the definition of the given constant, returning that
01905  *  constant's previous value.  If that constant referred to
01906  *  a module, this will not change that module's name and can lead
01907  *  to confusion.
01908  */
01909 
01910 VALUE
01911 rb_mod_remove_const(VALUE mod, VALUE name)
01912 {
01913     const ID id = rb_check_id(&name);
01914 
01915     if (!id) {
01916         if (rb_is_const_name(name)) {
01917             rb_name_error_str(name, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
01918                               rb_class_name(mod), name);
01919         }
01920         else {
01921             rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as a constant name",
01922                               QUOTE(name));
01923         }
01924     }
01925     if (!rb_is_const_id(id)) {
01926         rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a constant name",
01927                       QUOTE_ID(id));
01928     }
01929     return rb_const_remove(mod, id);
01930 }
01931 
01932 VALUE
01933 rb_const_remove(VALUE mod, ID id)
01934 {
01935     VALUE val;
01936     st_data_t v, n = id;
01937 
01938     if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
01939         rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
01940     rb_check_frozen(mod);
01941     if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) {
01942         if (rb_const_defined_at(mod, id)) {
01943             rb_name_error(id, "cannot remove %"PRIsVALUE"::%"PRIsVALUE"",
01944                           rb_class_name(mod), QUOTE_ID(id));
01945         }
01946         rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
01947                       rb_class_name(mod), QUOTE_ID(id));
01948     }
01949 
01950     rb_vm_change_state();
01951 
01952     val = ((rb_const_entry_t*)v)->value;
01953     if (val == Qundef) {
01954         autoload_delete(mod, id);
01955         val = Qnil;
01956     }
01957     xfree((rb_const_entry_t*)v);
01958     return val;
01959 }
01960 
01961 static int
01962 sv_i(st_data_t k, st_data_t v, st_data_t a)
01963 {
01964     ID key = (ID)k;
01965     rb_const_entry_t *ce = (rb_const_entry_t *)v;
01966     st_table *tbl = (st_table *)a;
01967 
01968     if (rb_is_const_id(key)) {
01969         if (!st_lookup(tbl, (st_data_t)key, 0)) {
01970             st_insert(tbl, (st_data_t)key, (st_data_t)ce);
01971         }
01972     }
01973     return ST_CONTINUE;
01974 }
01975 
01976 void*
01977 rb_mod_const_at(VALUE mod, void *data)
01978 {
01979     st_table *tbl = data;
01980     if (!tbl) {
01981         tbl = st_init_numtable();
01982     }
01983     if (RCLASS_CONST_TBL(mod)) {
01984         st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl);
01985     }
01986     return tbl;
01987 }
01988 
01989 void*
01990 rb_mod_const_of(VALUE mod, void *data)
01991 {
01992     VALUE tmp = mod;
01993     for (;;) {
01994         data = rb_mod_const_at(tmp, data);
01995         tmp = RCLASS_SUPER(tmp);
01996         if (!tmp) break;
01997         if (tmp == rb_cObject && mod != rb_cObject) break;
01998     }
01999     return data;
02000 }
02001 
02002 static int
02003 list_i(st_data_t key, st_data_t value, VALUE ary)
02004 {
02005     ID sym = (ID)key;
02006     rb_const_entry_t *ce = (rb_const_entry_t *)value;
02007     if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym));
02008     return ST_CONTINUE;
02009 }
02010 
02011 VALUE
02012 rb_const_list(void *data)
02013 {
02014     st_table *tbl = data;
02015     VALUE ary;
02016 
02017     if (!tbl) return rb_ary_new2(0);
02018     ary = rb_ary_new2(tbl->num_entries);
02019     st_foreach_safe(tbl, list_i, ary);
02020     st_free_table(tbl);
02021 
02022     return ary;
02023 }
02024 
02025 /*
02026  *  call-seq:
02027  *     mod.constants(inherit=true)    -> array
02028  *
02029  *  Returns an array of the names of the constants accessible in
02030  *  <i>mod</i>. This includes the names of constants in any included
02031  *  modules (example at start of section), unless the <i>inherit</i>
02032  *  parameter is set to <code>false</code>.
02033  *
02034  *    IO.constants.include?(:SYNC)        #=> true
02035  *    IO.constants(false).include?(:SYNC) #=> false
02036  *
02037  *  Also see <code>Module::const_defined?</code>.
02038  */
02039 
02040 VALUE
02041 rb_mod_constants(int argc, VALUE *argv, VALUE mod)
02042 {
02043     VALUE inherit;
02044     st_table *tbl;
02045 
02046     if (argc == 0) {
02047         inherit = Qtrue;
02048     }
02049     else {
02050         rb_scan_args(argc, argv, "01", &inherit);
02051     }
02052     if (RTEST(inherit)) {
02053         tbl = rb_mod_const_of(mod, 0);
02054     }
02055     else {
02056         tbl = rb_mod_const_at(mod, 0);
02057     }
02058     return rb_const_list(tbl);
02059 }
02060 
02061 static int
02062 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
02063 {
02064     st_data_t value;
02065     VALUE tmp;
02066     int mod_retry = 0;
02067 
02068     tmp = klass;
02069   retry:
02070     while (tmp) {
02071         if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) {
02072             rb_const_entry_t *ce = (rb_const_entry_t *)value;
02073             if (visibility && ce->flag == CONST_PRIVATE) {
02074                 return (int)Qfalse;
02075             }
02076             if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) && !rb_autoloading_value(tmp, id, 0))
02077                 return (int)Qfalse;
02078             return (int)Qtrue;
02079         }
02080         if (!recurse) break;
02081         tmp = RCLASS_SUPER(tmp);
02082     }
02083     if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
02084         mod_retry = 1;
02085         tmp = rb_cObject;
02086         goto retry;
02087     }
02088     return (int)Qfalse;
02089 }
02090 
02091 int
02092 rb_const_defined_from(VALUE klass, ID id)
02093 {
02094     return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE);
02095 }
02096 
02097 int
02098 rb_const_defined(VALUE klass, ID id)
02099 {
02100     return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE);
02101 }
02102 
02103 int
02104 rb_const_defined_at(VALUE klass, ID id)
02105 {
02106     return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE);
02107 }
02108 
02109 int
02110 rb_public_const_defined_from(VALUE klass, ID id)
02111 {
02112     return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE);
02113 }
02114 
02115 int
02116 rb_public_const_defined(VALUE klass, ID id)
02117 {
02118     return rb_const_defined_0(klass, id, FALSE, TRUE, TRUE);
02119 }
02120 
02121 int
02122 rb_public_const_defined_at(VALUE klass, ID id)
02123 {
02124     return rb_const_defined_0(klass, id, TRUE, FALSE, TRUE);
02125 }
02126 
02127 static void
02128 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest)
02129 {
02130     if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4)
02131         rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
02132     rb_check_frozen(klass);
02133 }
02134 
02135 void
02136 rb_const_set(VALUE klass, ID id, VALUE val)
02137 {
02138     rb_const_entry_t *ce;
02139     VALUE visibility = CONST_PUBLIC;
02140 
02141     if (NIL_P(klass)) {
02142         rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
02143                  QUOTE_ID(id));
02144     }
02145 
02146     check_before_mod_set(klass, id, val, "constant");
02147     if (!RCLASS_CONST_TBL(klass)) {
02148         RCLASS_CONST_TBL(klass) = st_init_numtable();
02149     }
02150     else {
02151         st_data_t value;
02152 
02153         if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) {
02154             rb_const_entry_t *ce = (rb_const_entry_t*)value;
02155             if (ce->value == Qundef) {
02156                 VALUE load;
02157                 struct autoload_data_i *ele;
02158 
02159                 load = autoload_data(klass, id);
02160                 /* for autoloading thread, keep the defined value to autoloading storage */
02161                 if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) {
02162                     rb_vm_change_state();
02163                     ele->value = val;
02164                     return;
02165                 }
02166                 /* otherwise, allow to override */
02167                 autoload_delete(klass, id);
02168             }
02169             else {
02170                 VALUE name = QUOTE_ID(id);
02171                 visibility = ce->flag;
02172                 if (klass == rb_cObject)
02173                     rb_warn("already initialized constant %"PRIsVALUE"", name);
02174                 else
02175                     rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"",
02176                             rb_class_name(klass), name);
02177                 if (!NIL_P(ce->file) && ce->line) {
02178                     rb_compile_warn(RSTRING_PTR(ce->file), ce->line,
02179                                     "previous definition of %"PRIsVALUE" was here", name);
02180                 }
02181             }
02182         }
02183     }
02184 
02185     rb_vm_change_state();
02186 
02187     ce = ALLOC(rb_const_entry_t);
02188     ce->flag = (rb_const_flag_t)visibility;
02189     ce->value = val;
02190     ce->file = rb_sourcefilename();
02191     ce->line = rb_sourceline();
02192 
02193     st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
02194 }
02195 
02196 void
02197 rb_define_const(VALUE klass, const char *name, VALUE val)
02198 {
02199     ID id = rb_intern(name);
02200 
02201     if (!rb_is_const_id(id)) {
02202         rb_warn("rb_define_const: invalid name `%s' for constant", name);
02203     }
02204     if (klass == rb_cObject) {
02205         rb_secure(4);
02206     }
02207     rb_const_set(klass, id, val);
02208 }
02209 
02210 void
02211 rb_define_global_const(const char *name, VALUE val)
02212 {
02213     rb_define_const(rb_cObject, name, val);
02214 }
02215 
02216 static void
02217 set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag)
02218 {
02219     int i;
02220     st_data_t v;
02221     ID id;
02222 
02223     if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(mod)) {
02224         rb_raise(rb_eSecurityError,
02225                  "Insecure: can't change constant visibility");
02226     }
02227 
02228     if (argc == 0) {
02229         rb_warning("%"PRIsVALUE" with no argument is just ignored",
02230                    QUOTE_ID(rb_frame_this_func()));
02231     }
02232 
02233     for (i = 0; i < argc; i++) {
02234         VALUE val = argv[i];
02235         id = rb_check_id(&val);
02236         if (!id) {
02237             if (i > 0)
02238                 rb_clear_cache_by_class(mod);
02239             rb_name_error_str(val, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
02240                               rb_class_name(mod), QUOTE(val));
02241         }
02242         if (RCLASS_CONST_TBL(mod) &&
02243             st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) {
02244             ((rb_const_entry_t*)v)->flag = flag;
02245         }
02246         else {
02247             if (i > 0)
02248                 rb_clear_cache_by_class(mod);
02249             rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
02250                           rb_class_name(mod), QUOTE_ID(id));
02251         }
02252     }
02253     rb_clear_cache_by_class(mod);
02254 }
02255 
02256 /*
02257  *  call-seq:
02258  *     mod.private_constant(symbol, ...)    => mod
02259  *
02260  *  Makes a list of existing constants private.
02261  */
02262 
02263 VALUE
02264 rb_mod_private_constant(int argc, VALUE *argv, VALUE obj)
02265 {
02266     set_const_visibility(obj, argc, argv, CONST_PRIVATE);
02267     return obj;
02268 }
02269 
02270 /*
02271  *  call-seq:
02272  *     mod.public_constant(symbol, ...)    => mod
02273  *
02274  *  Makes a list of existing constants public.
02275  */
02276 
02277 VALUE
02278 rb_mod_public_constant(int argc, VALUE *argv, VALUE obj)
02279 {
02280     set_const_visibility(obj, argc, argv, CONST_PUBLIC);
02281     return obj;
02282 }
02283 
02284 static VALUE
02285 original_module(VALUE c)
02286 {
02287     if (RB_TYPE_P(c, T_ICLASS))
02288         return RBASIC(c)->klass;
02289     return c;
02290 }
02291 
02292 static int
02293 cvar_lookup_at(VALUE klass, ID id, st_data_t *v)
02294 {
02295     if (!RCLASS_IV_TBL(klass)) return 0;
02296     return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v);
02297 }
02298 
02299 static VALUE
02300 cvar_front_klass(VALUE klass)
02301 {
02302     if (FL_TEST(klass, FL_SINGLETON)) {
02303         VALUE obj = rb_iv_get(klass, "__attached__");
02304         if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
02305             return obj;
02306         }
02307     }
02308     return RCLASS_SUPER(klass);
02309 }
02310 
02311 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \
02312     for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \
02313         if (cvar_lookup_at(klass, id, (v))) { \
02314             r; \
02315         } \
02316     }
02317 
02318 #define CVAR_LOOKUP(v,r) do {\
02319     if (cvar_lookup_at(klass, id, (v))) {r;}\
02320     CVAR_FOREACH_ANCESTORS(klass, v, r);\
02321 } while(0)
02322 
02323 void
02324 rb_cvar_set(VALUE klass, ID id, VALUE val)
02325 {
02326     VALUE tmp, front = 0, target = 0;
02327 
02328     tmp = klass;
02329     CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
02330     if (target) {
02331         if (front && target != front) {
02332             st_data_t did = id;
02333 
02334             if (RTEST(ruby_verbose)) {
02335                 rb_warning("class variable %"PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
02336                            QUOTE_ID(id), rb_class_name(original_module(front)),
02337                            rb_class_name(original_module(target)));
02338             }
02339             if (BUILTIN_TYPE(front) == T_CLASS) {
02340                 st_delete(RCLASS_IV_TBL(front),&did,0);
02341             }
02342         }
02343     }
02344     else {
02345         target = tmp;
02346     }
02347 
02348     check_before_mod_set(target, id, val, "class variable");
02349     if (!RCLASS_IV_TBL(target)) {
02350         RCLASS_IV_TBL(target) = st_init_numtable();
02351     }
02352 
02353     st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val);
02354 }
02355 
02356 VALUE
02357 rb_cvar_get(VALUE klass, ID id)
02358 {
02359     VALUE tmp, front = 0, target = 0;
02360     st_data_t value;
02361 
02362     tmp = klass;
02363     CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
02364     if (!target) {
02365         rb_name_error(id, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"",
02366                       QUOTE_ID(id), rb_class_name(tmp));
02367     }
02368     if (front && target != front) {
02369         st_data_t did = id;
02370 
02371         if (RTEST(ruby_verbose)) {
02372             rb_warning("class variable %"PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
02373                        QUOTE_ID(id), rb_class_name(original_module(front)),
02374                        rb_class_name(original_module(target)));
02375         }
02376         if (BUILTIN_TYPE(front) == T_CLASS) {
02377             st_delete(RCLASS_IV_TBL(front),&did,0);
02378         }
02379     }
02380     return (VALUE)value;
02381 }
02382 
02383 VALUE
02384 rb_cvar_defined(VALUE klass, ID id)
02385 {
02386     if (!klass) return Qfalse;
02387     CVAR_LOOKUP(0,return Qtrue);
02388     return Qfalse;
02389 }
02390 
02391 void
02392 rb_cv_set(VALUE klass, const char *name, VALUE val)
02393 {
02394     ID id = rb_intern(name);
02395     if (!rb_is_class_id(id)) {
02396         rb_name_error(id, "wrong class variable name %s", name);
02397     }
02398     rb_cvar_set(klass, id, val);
02399 }
02400 
02401 VALUE
02402 rb_cv_get(VALUE klass, const char *name)
02403 {
02404     ID id = rb_intern(name);
02405     if (!rb_is_class_id(id)) {
02406         rb_name_error(id, "wrong class variable name %s", name);
02407     }
02408     return rb_cvar_get(klass, id);
02409 }
02410 
02411 void
02412 rb_define_class_variable(VALUE klass, const char *name, VALUE val)
02413 {
02414     ID id = rb_intern(name);
02415 
02416     if (!rb_is_class_id(id)) {
02417         rb_name_error(id, "wrong class variable name %s", name);
02418     }
02419     rb_cvar_set(klass, id, val);
02420 }
02421 
02422 static int
02423 cv_i(st_data_t k, st_data_t v, st_data_t a)
02424 {
02425     ID key = (ID)k;
02426     st_table *tbl = (st_table *)a;
02427 
02428     if (rb_is_class_id(key)) {
02429         if (!st_lookup(tbl, (st_data_t)key, 0)) {
02430             st_insert(tbl, (st_data_t)key, 0);
02431         }
02432     }
02433     return ST_CONTINUE;
02434 }
02435 
02436 static void*
02437 mod_cvar_at(VALUE mod, void *data)
02438 {
02439     st_table *tbl = data;
02440     if (!tbl) {
02441         tbl = st_init_numtable();
02442     }
02443     if (RCLASS_IV_TBL(mod)) {
02444         st_foreach_safe(RCLASS_IV_TBL(mod), cv_i, (st_data_t)tbl);
02445     }
02446     return tbl;
02447 }
02448 
02449 static void*
02450 mod_cvar_of(VALUE mod, void *data)
02451 {
02452     VALUE tmp = mod;
02453     for (;;) {
02454         data = mod_cvar_at(tmp, data);
02455         tmp = RCLASS_SUPER(tmp);
02456         if (!tmp) break;
02457     }
02458     return data;
02459 }
02460 
02461 static int
02462 cv_list_i(st_data_t key, st_data_t value, VALUE ary)
02463 {
02464     ID sym = (ID)key;
02465     rb_ary_push(ary, ID2SYM(sym));
02466     return ST_CONTINUE;
02467 }
02468 
02469 static VALUE
02470 cvar_list(void *data)
02471 {
02472     st_table *tbl = data;
02473     VALUE ary;
02474 
02475     if (!tbl) return rb_ary_new2(0);
02476     ary = rb_ary_new2(tbl->num_entries);
02477     st_foreach_safe(tbl, cv_list_i, ary);
02478     st_free_table(tbl);
02479 
02480     return ary;
02481 }
02482 
02483 /*
02484  *  call-seq:
02485  *     mod.class_variables(inherit=true)    -> array
02486  *
02487  *  Returns an array of the names of class variables in <i>mod</i>.
02488  *  This includes the names of class variables in any included
02489  *  modules, unless the <i>inherit</i> parameter is set to
02490  *  <code>false</code>.
02491  *
02492  *     class One
02493  *       @@var1 = 1
02494  *     end
02495  *     class Two < One
02496  *       @@var2 = 2
02497  *     end
02498  *     One.class_variables   #=> [:@@var1]
02499  *     Two.class_variables   #=> [:@@var2, :@@var1]
02500  */
02501 
02502 VALUE
02503 rb_mod_class_variables(int argc, VALUE *argv, VALUE mod)
02504 {
02505     VALUE inherit;
02506     st_table *tbl;
02507 
02508     if (argc == 0) {
02509         inherit = Qtrue;
02510     }
02511     else {
02512         rb_scan_args(argc, argv, "01", &inherit);
02513     }
02514     if (RTEST(inherit)) {
02515         tbl = mod_cvar_of(mod, 0);
02516     }
02517     else {
02518         tbl = mod_cvar_at(mod, 0);
02519     }
02520     return cvar_list(tbl);
02521 }
02522 
02523 /*
02524  *  call-seq:
02525  *     remove_class_variable(sym)    -> obj
02526  *
02527  *  Removes the definition of the <i>sym</i>, returning that
02528  *  constant's value.
02529  *
02530  *     class Dummy
02531  *       @@var = 99
02532  *       puts @@var
02533  *       remove_class_variable(:@@var)
02534  *       p(defined? @@var)
02535  *     end
02536  *
02537  *  <em>produces:</em>
02538  *
02539  *     99
02540  *     nil
02541  */
02542 
02543 VALUE
02544 rb_mod_remove_cvar(VALUE mod, VALUE name)
02545 {
02546     const ID id = rb_check_id(&name);
02547     st_data_t val, n = id;
02548 
02549     if (!id) {
02550         if (rb_is_class_name(name)) {
02551             rb_name_error_str(name, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"",
02552                               name, rb_class_name(mod));
02553         }
02554         else {
02555             rb_name_error_str(name, "wrong class variable name %"PRIsVALUE"", QUOTE(name));
02556         }
02557     }
02558     if (!rb_is_class_id(id)) {
02559         rb_name_error(id, "wrong class variable name %"PRIsVALUE"", QUOTE_ID(id));
02560     }
02561     if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4)
02562         rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
02563     rb_check_frozen(mod);
02564     if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
02565         return (VALUE)val;
02566     }
02567     if (rb_cvar_defined(mod, id)) {
02568         rb_name_error(id, "cannot remove %"PRIsVALUE" for %"PRIsVALUE"",
02569                  QUOTE_ID(id), rb_class_name(mod));
02570     }
02571     rb_name_error(id, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"",
02572                   QUOTE_ID(id), rb_class_name(mod));
02573 
02574     UNREACHABLE;
02575 }
02576 
02577 VALUE
02578 rb_iv_get(VALUE obj, const char *name)
02579 {
02580     ID id = rb_intern(name);
02581 
02582     return rb_ivar_get(obj, id);
02583 }
02584 
02585 VALUE
02586 rb_iv_set(VALUE obj, const char *name, VALUE val)
02587 {
02588     ID id = rb_intern(name);
02589 
02590     return rb_ivar_set(obj, id, val);
02591 }
02592