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 

Generated on Wed Aug 10 09:17:15 2011 for Ruby by  doxygen 1.4.7