Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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