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