|
Ruby 1.9.2p180(2011-02-18revision30909)
|
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
1.7.3