|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3