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

Generated on Thu Sep 8 2011 03:50:48 for Ruby by  doxygen 1.7.1