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