|
Ruby
2.0.0p481(2014-05-08revision45883)
|
00001 /********************************************************************** 00002 00003 variable.c - 00004 00005 $Author: nagachika $ 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 #include "constant.h" 00020 #include "internal.h" 00021 00022 st_table *rb_global_tbl; 00023 st_table *rb_class_tbl; 00024 static ID autoload, classpath, tmp_classpath, classid; 00025 00026 void 00027 Init_var_tables(void) 00028 { 00029 rb_global_tbl = st_init_numtable(); 00030 rb_class_tbl = st_init_numtable(); 00031 CONST_ID(autoload, "__autoload__"); 00032 /* __classpath__: fully qualified class path */ 00033 CONST_ID(classpath, "__classpath__"); 00034 /* __tmp_classpath__: temporary class path which contains anonymous names */ 00035 CONST_ID(tmp_classpath, "__tmp_classpath__"); 00036 /* __classid__: name given to class/module under an anonymous namespace */ 00037 CONST_ID(classid, "__classid__"); 00038 } 00039 00040 struct fc_result { 00041 ID name, preferred; 00042 VALUE klass; 00043 VALUE path; 00044 VALUE track; 00045 struct fc_result *prev; 00046 }; 00047 00048 static VALUE 00049 fc_path(struct fc_result *fc, ID name) 00050 { 00051 VALUE path, tmp; 00052 00053 path = rb_str_dup(rb_id2str(name)); 00054 while (fc) { 00055 st_data_t n; 00056 if (fc->track == rb_cObject) break; 00057 if (RCLASS_IV_TBL(fc->track) && 00058 st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { 00059 tmp = rb_str_dup((VALUE)n); 00060 rb_str_cat2(tmp, "::"); 00061 rb_str_append(tmp, path); 00062 path = tmp; 00063 break; 00064 } 00065 tmp = rb_str_dup(rb_id2str(fc->name)); 00066 rb_str_cat2(tmp, "::"); 00067 rb_str_append(tmp, path); 00068 path = tmp; 00069 fc = fc->prev; 00070 } 00071 OBJ_FREEZE(path); 00072 return path; 00073 } 00074 00075 static int 00076 fc_i(st_data_t k, st_data_t v, st_data_t a) 00077 { 00078 ID key = (ID)k; 00079 rb_const_entry_t *ce = (rb_const_entry_t *)v; 00080 struct fc_result *res = (struct fc_result *)a; 00081 VALUE value = ce->value; 00082 if (!rb_is_const_id(key)) return ST_CONTINUE; 00083 00084 if (value == res->klass && (!res->preferred || key == res->preferred)) { 00085 res->path = fc_path(res, key); 00086 return ST_STOP; 00087 } 00088 if (RB_TYPE_P(value, T_MODULE) || RB_TYPE_P(value, T_CLASS)) { 00089 if (!RCLASS_CONST_TBL(value)) return ST_CONTINUE; 00090 else { 00091 struct fc_result arg; 00092 struct fc_result *list; 00093 00094 list = res; 00095 while (list) { 00096 if (list->track == value) return ST_CONTINUE; 00097 list = list->prev; 00098 } 00099 00100 arg.name = key; 00101 arg.preferred = res->preferred; 00102 arg.path = 0; 00103 arg.klass = res->klass; 00104 arg.track = value; 00105 arg.prev = res; 00106 st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); 00107 if (arg.path) { 00108 res->path = arg.path; 00109 return ST_STOP; 00110 } 00111 } 00112 } 00113 return ST_CONTINUE; 00114 } 00115 00123 static VALUE 00124 find_class_path(VALUE klass, ID preferred) 00125 { 00126 struct fc_result arg; 00127 00128 arg.preferred = preferred; 00129 arg.name = 0; 00130 arg.path = 0; 00131 arg.klass = klass; 00132 arg.track = rb_cObject; 00133 arg.prev = 0; 00134 if (RCLASS_CONST_TBL(rb_cObject)) { 00135 st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); 00136 } 00137 if (arg.path == 0) { 00138 st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); 00139 } 00140 if (arg.path) { 00141 st_data_t tmp = tmp_classpath; 00142 if (!RCLASS_IV_TBL(klass)) { 00143 RCLASS_IV_TBL(klass) = st_init_numtable(); 00144 } 00145 st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); 00146 st_delete(RCLASS_IV_TBL(klass), &tmp, 0); 00147 return arg.path; 00148 } 00149 return Qnil; 00150 } 00151 00159 static VALUE 00160 classname(VALUE klass, int *permanent) 00161 { 00162 VALUE path = Qnil; 00163 st_data_t n; 00164 00165 if (!klass) klass = rb_cObject; 00166 *permanent = 1; 00167 if (RCLASS_IV_TBL(klass)) { 00168 if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { 00169 ID cid = 0; 00170 if (st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { 00171 cid = SYM2ID(n); 00172 path = find_class_path(klass, cid); 00173 } 00174 if (NIL_P(path)) { 00175 path = find_class_path(klass, (ID)0); 00176 } 00177 if (NIL_P(path)) { 00178 if (!cid) { 00179 return Qnil; 00180 } 00181 if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)tmp_classpath, &n)) { 00182 path = rb_str_dup(rb_id2str(cid)); 00183 OBJ_FREEZE(path); 00184 return path; 00185 } 00186 *permanent = 0; 00187 path = (VALUE)n; 00188 return path; 00189 } 00190 } 00191 else { 00192 path = (VALUE)n; 00193 } 00194 if (!RB_TYPE_P(path, T_STRING)) { 00195 rb_bug("class path is not set properly"); 00196 } 00197 return path; 00198 } 00199 return find_class_path(klass, (ID)0); 00200 } 00201 00202 /* 00203 * call-seq: 00204 * mod.name -> string 00205 * 00206 * Returns the name of the module <i>mod</i>. Returns nil for anonymous modules. 00207 */ 00208 00209 VALUE 00210 rb_mod_name(VALUE mod) 00211 { 00212 int permanent; 00213 VALUE path = classname(mod, &permanent); 00214 00215 if (!NIL_P(path)) return rb_str_dup(path); 00216 return path; 00217 } 00218 00219 typedef VALUE (*path_cache_func)(VALUE obj, ID id, VALUE val); 00220 00221 static VALUE 00222 rb_tmp_class_path(VALUE klass, int *permanent, path_cache_func cache_path) 00223 { 00224 VALUE path = classname(klass, permanent); 00225 st_data_t n = (st_data_t)path; 00226 00227 if (!NIL_P(path)) { 00228 return path; 00229 } 00230 if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), 00231 (st_data_t)tmp_classpath, &n)) { 00232 *permanent = 0; 00233 return (VALUE)n; 00234 } 00235 else { 00236 const char *s = "Class"; 00237 00238 if (RB_TYPE_P(klass, T_MODULE)) { 00239 if (rb_obj_class(klass) == rb_cModule) { 00240 s = "Module"; 00241 } 00242 else { 00243 int perm; 00244 VALUE path; 00245 00246 path = rb_tmp_class_path(RBASIC(klass)->klass, &perm, cache_path); 00247 s = RSTRING_PTR(path); 00248 } 00249 } 00250 path = rb_sprintf("#<%s:%p>", s, (void*)klass); 00251 OBJ_FREEZE(path); 00252 00253 cache_path(klass, tmp_classpath, path); 00254 *permanent = 0; 00255 00256 return path; 00257 } 00258 } 00259 00260 VALUE 00261 rb_class_path(VALUE klass) 00262 { 00263 int permanent; 00264 VALUE path = rb_tmp_class_path(klass, &permanent, rb_ivar_set); 00265 if (!NIL_P(path)) path = rb_str_dup(path); 00266 return path; 00267 } 00268 00269 static VALUE 00270 null_cache(VALUE obj, ID id, VALUE val) 00271 { 00272 return Qnil; 00273 } 00274 00275 VALUE 00276 rb_class_path_no_cache(VALUE klass) 00277 { 00278 int permanent; 00279 VALUE path = rb_tmp_class_path(klass, &permanent, null_cache); 00280 if (!NIL_P(path)) path = rb_str_dup(path); 00281 return path; 00282 } 00283 00284 void 00285 rb_set_class_path_string(VALUE klass, VALUE under, VALUE name) 00286 { 00287 VALUE str; 00288 ID pathid = classpath; 00289 00290 if (under == rb_cObject) { 00291 str = rb_str_new_frozen(name); 00292 } 00293 else { 00294 int permanent; 00295 str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set)); 00296 rb_str_cat2(str, "::"); 00297 rb_str_append(str, name); 00298 OBJ_FREEZE(str); 00299 if (!permanent) { 00300 pathid = tmp_classpath; 00301 rb_ivar_set(klass, classid, ID2SYM(rb_intern_str(name))); 00302 } 00303 } 00304 rb_ivar_set(klass, pathid, str); 00305 } 00306 00307 void 00308 rb_set_class_path(VALUE klass, VALUE under, const char *name) 00309 { 00310 VALUE str; 00311 ID pathid = classpath; 00312 00313 if (under == rb_cObject) { 00314 str = rb_str_new2(name); 00315 } 00316 else { 00317 int permanent; 00318 str = rb_str_dup(rb_tmp_class_path(under, &permanent, rb_ivar_set)); 00319 rb_str_cat2(str, "::"); 00320 rb_str_cat2(str, name); 00321 if (!permanent) { 00322 pathid = tmp_classpath; 00323 rb_ivar_set(klass, classid, ID2SYM(rb_intern(name))); 00324 } 00325 } 00326 OBJ_FREEZE(str); 00327 rb_ivar_set(klass, pathid, str); 00328 } 00329 00330 VALUE 00331 rb_path_to_class(VALUE pathname) 00332 { 00333 rb_encoding *enc = rb_enc_get(pathname); 00334 const char *pbeg, *p, *path = RSTRING_PTR(pathname); 00335 ID id; 00336 VALUE c = rb_cObject; 00337 00338 if (!rb_enc_asciicompat(enc)) { 00339 rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)"); 00340 } 00341 pbeg = p = path; 00342 if (path[0] == '#') { 00343 rb_raise(rb_eArgError, "can't retrieve anonymous class %"PRIsVALUE, 00344 QUOTE(pathname)); 00345 } 00346 while (*p) { 00347 while (*p && *p != ':') p++; 00348 id = rb_check_id_cstr(pbeg, p-pbeg, enc); 00349 if (p[0] == ':') { 00350 if (p[1] != ':') goto undefined_class; 00351 p += 2; 00352 pbeg = p; 00353 } 00354 if (!id || !rb_const_defined_at(c, id)) { 00355 undefined_class: 00356 rb_raise(rb_eArgError, "undefined class/module %.*"PRIsVALUE, 00357 (int)(p-path), pathname); 00358 } 00359 c = rb_const_get_at(c, id); 00360 if (!RB_TYPE_P(c, T_MODULE) && !RB_TYPE_P(c, T_CLASS)) { 00361 rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module", 00362 pathname); 00363 } 00364 } 00365 RB_GC_GUARD(pathname); 00366 00367 return c; 00368 } 00369 00370 VALUE 00371 rb_path2class(const char *path) 00372 { 00373 return rb_path_to_class(rb_str_new_cstr(path)); 00374 } 00375 00376 void 00377 rb_name_class(VALUE klass, ID id) 00378 { 00379 rb_ivar_set(klass, classid, ID2SYM(id)); 00380 } 00381 00382 VALUE 00383 rb_class_name(VALUE klass) 00384 { 00385 return rb_class_path(rb_class_real(klass)); 00386 } 00387 00388 const char * 00389 rb_class2name(VALUE klass) 00390 { 00391 VALUE name = rb_class_name(klass); 00392 return RSTRING_PTR(name); 00393 } 00394 00395 const char * 00396 rb_obj_classname(VALUE obj) 00397 { 00398 return rb_class2name(CLASS_OF(obj)); 00399 } 00400 00401 #define global_variable rb_global_variable 00402 #define global_entry rb_global_entry 00403 00404 #define gvar_getter_t rb_gvar_getter_t 00405 #define gvar_setter_t rb_gvar_setter_t 00406 #define gvar_marker_t rb_gvar_marker_t 00407 00408 struct trace_var { 00409 int removed; 00410 void (*func)(VALUE arg, VALUE val); 00411 VALUE data; 00412 struct trace_var *next; 00413 }; 00414 00415 struct global_variable { 00416 int counter; 00417 void *data; 00418 gvar_getter_t *getter; 00419 gvar_setter_t *setter; 00420 gvar_marker_t *marker; 00421 int block_trace; 00422 struct trace_var *trace; 00423 }; 00424 00425 #define undef_getter rb_gvar_undef_getter 00426 #define undef_setter rb_gvar_undef_setter 00427 #define undef_marker rb_gvar_undef_marker 00428 00429 #define val_getter rb_gvar_val_getter 00430 #define val_setter rb_gvar_val_setter 00431 #define val_marker rb_gvar_val_marker 00432 00433 #define var_getter rb_gvar_var_getter 00434 #define var_setter rb_gvar_var_setter 00435 #define var_marker rb_gvar_var_marker 00436 00437 #define readonly_setter rb_gvar_readonly_setter 00438 00439 struct global_entry* 00440 rb_global_entry(ID id) 00441 { 00442 struct global_entry *entry; 00443 st_data_t data; 00444 00445 if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { 00446 struct global_variable *var; 00447 entry = ALLOC(struct global_entry); 00448 var = ALLOC(struct global_variable); 00449 entry->id = id; 00450 entry->var = var; 00451 var->counter = 1; 00452 var->data = 0; 00453 var->getter = undef_getter; 00454 var->setter = undef_setter; 00455 var->marker = undef_marker; 00456 00457 var->block_trace = 0; 00458 var->trace = 0; 00459 st_add_direct(rb_global_tbl, id, (st_data_t)entry); 00460 } 00461 else { 00462 entry = (struct global_entry *)data; 00463 } 00464 return entry; 00465 } 00466 00467 VALUE 00468 undef_getter(ID id, void *data, struct global_variable *var) 00469 { 00470 rb_warning("global variable `%"PRIsVALUE"' not initialized", QUOTE_ID(id)); 00471 00472 return Qnil; 00473 } 00474 00475 void 00476 undef_setter(VALUE val, ID id, void *data, struct global_variable *var) 00477 { 00478 var->getter = val_getter; 00479 var->setter = val_setter; 00480 var->marker = val_marker; 00481 00482 var->data = (void*)val; 00483 } 00484 00485 void 00486 undef_marker(VALUE *var) 00487 { 00488 } 00489 00490 VALUE 00491 val_getter(ID id, void *data, struct global_variable *var) 00492 { 00493 return (VALUE)data; 00494 } 00495 00496 void 00497 val_setter(VALUE val, ID id, void *data, struct global_variable *var) 00498 { 00499 var->data = (void*)val; 00500 } 00501 00502 void 00503 val_marker(VALUE *var) 00504 { 00505 VALUE data = (VALUE)var; 00506 if (data) rb_gc_mark_maybe(data); 00507 } 00508 00509 VALUE 00510 var_getter(ID id, void *data, struct global_variable *gvar) 00511 { 00512 VALUE *var = data; 00513 if (!var) return Qnil; 00514 return *var; 00515 } 00516 00517 void 00518 var_setter(VALUE val, ID id, void *data, struct global_variable *gvar) 00519 { 00520 *(VALUE *)data = val; 00521 } 00522 00523 void 00524 var_marker(VALUE *var) 00525 { 00526 if (var) rb_gc_mark_maybe(*var); 00527 } 00528 00529 void 00530 readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) 00531 { 00532 rb_name_error(id, "%"PRIsVALUE" is a read-only variable", QUOTE_ID(id)); 00533 } 00534 00535 static int 00536 mark_global_entry(st_data_t k, st_data_t v, st_data_t a) 00537 { 00538 struct global_entry *entry = (struct global_entry *)v; 00539 struct trace_var *trace; 00540 struct global_variable *var = entry->var; 00541 00542 (*var->marker)(var->data); 00543 trace = var->trace; 00544 while (trace) { 00545 if (trace->data) rb_gc_mark_maybe(trace->data); 00546 trace = trace->next; 00547 } 00548 return ST_CONTINUE; 00549 } 00550 00551 void 00552 rb_gc_mark_global_tbl(void) 00553 { 00554 if (rb_global_tbl) 00555 st_foreach_safe(rb_global_tbl, mark_global_entry, 0); 00556 } 00557 00558 static ID 00559 global_id(const char *name) 00560 { 00561 ID id; 00562 00563 if (name[0] == '$') id = rb_intern(name); 00564 else { 00565 size_t len = strlen(name); 00566 char *buf = ALLOCA_N(char, len+1); 00567 buf[0] = '$'; 00568 memcpy(buf+1, name, len); 00569 id = rb_intern2(buf, len+1); 00570 } 00571 return id; 00572 } 00573 00574 void 00575 rb_define_hooked_variable( 00576 const char *name, 00577 VALUE *var, 00578 VALUE (*getter)(ANYARGS), 00579 void (*setter)(ANYARGS)) 00580 { 00581 volatile VALUE tmp = var ? *var : Qnil; 00582 ID id = global_id(name); 00583 struct global_variable *gvar = rb_global_entry(id)->var; 00584 00585 gvar->data = (void*)var; 00586 gvar->getter = getter?(gvar_getter_t *)getter:var_getter; 00587 gvar->setter = setter?(gvar_setter_t *)setter:var_setter; 00588 gvar->marker = var_marker; 00589 00590 RB_GC_GUARD(tmp); 00591 } 00592 00593 void 00594 rb_define_variable(const char *name, VALUE *var) 00595 { 00596 rb_define_hooked_variable(name, var, 0, 0); 00597 } 00598 00599 void 00600 rb_define_readonly_variable(const char *name, VALUE *var) 00601 { 00602 rb_define_hooked_variable(name, var, 0, readonly_setter); 00603 } 00604 00605 void 00606 rb_define_virtual_variable( 00607 const char *name, 00608 VALUE (*getter)(ANYARGS), 00609 void (*setter)(ANYARGS)) 00610 { 00611 if (!getter) getter = val_getter; 00612 if (!setter) setter = readonly_setter; 00613 rb_define_hooked_variable(name, 0, getter, setter); 00614 } 00615 00616 static void 00617 rb_trace_eval(VALUE cmd, VALUE val) 00618 { 00619 rb_eval_cmd(cmd, rb_ary_new3(1, val), 0); 00620 } 00621 00622 /* 00623 * call-seq: 00624 * trace_var(symbol, cmd ) -> nil 00625 * trace_var(symbol) {|val| block } -> nil 00626 * 00627 * Controls tracing of assignments to global variables. The parameter 00628 * +symbol_ identifies the variable (as either a string name or a 00629 * symbol identifier). _cmd_ (which may be a string or a 00630 * +Proc+ object) or block is executed whenever the variable 00631 * is assigned. The block or +Proc+ object receives the 00632 * variable's new value as a parameter. Also see 00633 * <code>Kernel::untrace_var</code>. 00634 * 00635 * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" } 00636 * $_ = "hello" 00637 * $_ = ' there' 00638 * 00639 * <em>produces:</em> 00640 * 00641 * $_ is now 'hello' 00642 * $_ is now ' there' 00643 */ 00644 00645 VALUE 00646 rb_f_trace_var(int argc, VALUE *argv) 00647 { 00648 VALUE var, cmd; 00649 struct global_entry *entry; 00650 struct trace_var *trace; 00651 00652 rb_secure(4); 00653 if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) { 00654 cmd = rb_block_proc(); 00655 } 00656 if (NIL_P(cmd)) { 00657 return rb_f_untrace_var(argc, argv); 00658 } 00659 entry = rb_global_entry(rb_to_id(var)); 00660 if (OBJ_TAINTED(cmd)) { 00661 rb_raise(rb_eSecurityError, "Insecure: tainted variable trace"); 00662 } 00663 trace = ALLOC(struct trace_var); 00664 trace->next = entry->var->trace; 00665 trace->func = rb_trace_eval; 00666 trace->data = cmd; 00667 trace->removed = 0; 00668 entry->var->trace = trace; 00669 00670 return Qnil; 00671 } 00672 00673 static void 00674 remove_trace(struct global_variable *var) 00675 { 00676 struct trace_var *trace = var->trace; 00677 struct trace_var t; 00678 struct trace_var *next; 00679 00680 t.next = trace; 00681 trace = &t; 00682 while (trace->next) { 00683 next = trace->next; 00684 if (next->removed) { 00685 trace->next = next->next; 00686 xfree(next); 00687 } 00688 else { 00689 trace = next; 00690 } 00691 } 00692 var->trace = t.next; 00693 } 00694 00695 /* 00696 * call-seq: 00697 * untrace_var(symbol [, cmd] ) -> array or nil 00698 * 00699 * Removes tracing for the specified command on the given global 00700 * variable and returns +nil+. If no command is specified, 00701 * removes all tracing for that variable and returns an array 00702 * containing the commands actually removed. 00703 */ 00704 00705 VALUE 00706 rb_f_untrace_var(int argc, VALUE *argv) 00707 { 00708 VALUE var, cmd; 00709 ID id; 00710 struct global_entry *entry; 00711 struct trace_var *trace; 00712 st_data_t data; 00713 00714 rb_secure(4); 00715 rb_scan_args(argc, argv, "11", &var, &cmd); 00716 id = rb_check_id(&var); 00717 if (!id) { 00718 rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var)); 00719 } 00720 if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { 00721 rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id)); 00722 } 00723 00724 trace = (entry = (struct global_entry *)data)->var->trace; 00725 if (NIL_P(cmd)) { 00726 VALUE ary = rb_ary_new(); 00727 00728 while (trace) { 00729 struct trace_var *next = trace->next; 00730 rb_ary_push(ary, (VALUE)trace->data); 00731 trace->removed = 1; 00732 trace = next; 00733 } 00734 00735 if (!entry->var->block_trace) remove_trace(entry->var); 00736 return ary; 00737 } 00738 else { 00739 while (trace) { 00740 if (trace->data == cmd) { 00741 trace->removed = 1; 00742 if (!entry->var->block_trace) remove_trace(entry->var); 00743 return rb_ary_new3(1, cmd); 00744 } 00745 trace = trace->next; 00746 } 00747 } 00748 return Qnil; 00749 } 00750 00751 VALUE 00752 rb_gvar_get(struct global_entry *entry) 00753 { 00754 struct global_variable *var = entry->var; 00755 return (*var->getter)(entry->id, var->data, var); 00756 } 00757 00758 struct trace_data { 00759 struct trace_var *trace; 00760 VALUE val; 00761 }; 00762 00763 static VALUE 00764 trace_ev(struct trace_data *data) 00765 { 00766 struct trace_var *trace = data->trace; 00767 00768 while (trace) { 00769 (*trace->func)(trace->data, data->val); 00770 trace = trace->next; 00771 } 00772 00773 return Qnil; 00774 } 00775 00776 static VALUE 00777 trace_en(struct global_variable *var) 00778 { 00779 var->block_trace = 0; 00780 remove_trace(var); 00781 return Qnil; /* not reached */ 00782 } 00783 00784 VALUE 00785 rb_gvar_set(struct global_entry *entry, VALUE val) 00786 { 00787 struct trace_data trace; 00788 struct global_variable *var = entry->var; 00789 00790 if (rb_safe_level() >= 4) 00791 rb_raise(rb_eSecurityError, "Insecure: can't change global variable value"); 00792 (*var->setter)(val, entry->id, var->data, var); 00793 00794 if (var->trace && !var->block_trace) { 00795 var->block_trace = 1; 00796 trace.trace = var->trace; 00797 trace.val = val; 00798 rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var); 00799 } 00800 return val; 00801 } 00802 00803 VALUE 00804 rb_gv_set(const char *name, VALUE val) 00805 { 00806 struct global_entry *entry; 00807 00808 entry = rb_global_entry(global_id(name)); 00809 return rb_gvar_set(entry, val); 00810 } 00811 00812 VALUE 00813 rb_gv_get(const char *name) 00814 { 00815 struct global_entry *entry; 00816 00817 entry = rb_global_entry(global_id(name)); 00818 return rb_gvar_get(entry); 00819 } 00820 00821 VALUE 00822 rb_gvar_defined(struct global_entry *entry) 00823 { 00824 if (entry->var->getter == undef_getter) return Qfalse; 00825 return Qtrue; 00826 } 00827 00828 static int 00829 gvar_i(st_data_t k, st_data_t v, st_data_t a) 00830 { 00831 ID key = (ID)k; 00832 VALUE ary = (VALUE)a; 00833 rb_ary_push(ary, ID2SYM(key)); 00834 return ST_CONTINUE; 00835 } 00836 00837 /* 00838 * call-seq: 00839 * global_variables -> array 00840 * 00841 * Returns an array of the names of global variables. 00842 * 00843 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr] 00844 */ 00845 00846 VALUE 00847 rb_f_global_variables(void) 00848 { 00849 VALUE ary = rb_ary_new(); 00850 char buf[2]; 00851 int i; 00852 00853 st_foreach_safe(rb_global_tbl, gvar_i, ary); 00854 buf[0] = '$'; 00855 for (i = 1; i <= 9; ++i) { 00856 buf[1] = (char)(i + '0'); 00857 rb_ary_push(ary, ID2SYM(rb_intern2(buf, 2))); 00858 } 00859 return ary; 00860 } 00861 00862 void 00863 rb_alias_variable(ID name1, ID name2) 00864 { 00865 struct global_entry *entry1, *entry2; 00866 st_data_t data1; 00867 00868 if (rb_safe_level() >= 4) 00869 rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); 00870 00871 entry2 = rb_global_entry(name2); 00872 if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { 00873 entry1 = ALLOC(struct global_entry); 00874 entry1->id = name1; 00875 st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); 00876 } 00877 else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { 00878 struct global_variable *var = entry1->var; 00879 if (var->block_trace) { 00880 rb_raise(rb_eRuntimeError, "can't alias in tracer"); 00881 } 00882 var->counter--; 00883 if (var->counter == 0) { 00884 struct trace_var *trace = var->trace; 00885 while (trace) { 00886 struct trace_var *next = trace->next; 00887 xfree(trace); 00888 trace = next; 00889 } 00890 xfree(var); 00891 } 00892 } 00893 else { 00894 return; 00895 } 00896 entry2->var->counter++; 00897 entry1->var = entry2->var; 00898 } 00899 00900 static int special_generic_ivar = 0; 00901 static st_table *generic_iv_tbl; 00902 00903 st_table* 00904 rb_generic_ivar_table(VALUE obj) 00905 { 00906 st_data_t tbl; 00907 00908 if (!FL_TEST(obj, FL_EXIVAR)) return 0; 00909 if (!generic_iv_tbl) return 0; 00910 if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; 00911 return (st_table *)tbl; 00912 } 00913 00914 static VALUE 00915 generic_ivar_get(VALUE obj, ID id, int warn) 00916 { 00917 st_data_t tbl, val; 00918 00919 if (generic_iv_tbl) { 00920 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { 00921 if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { 00922 return (VALUE)val; 00923 } 00924 } 00925 } 00926 if (warn) { 00927 rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); 00928 } 00929 return Qnil; 00930 } 00931 00932 static void 00933 generic_ivar_set(VALUE obj, ID id, VALUE val) 00934 { 00935 st_table *tbl; 00936 st_data_t data; 00937 00938 if (rb_special_const_p(obj)) { 00939 if (rb_obj_frozen_p(obj)) rb_error_frozen("object"); 00940 special_generic_ivar = 1; 00941 } 00942 if (!generic_iv_tbl) { 00943 generic_iv_tbl = st_init_numtable(); 00944 } 00945 if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { 00946 FL_SET(obj, FL_EXIVAR); 00947 tbl = st_init_numtable(); 00948 st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); 00949 st_add_direct(tbl, (st_data_t)id, (st_data_t)val); 00950 return; 00951 } 00952 st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); 00953 } 00954 00955 static VALUE 00956 generic_ivar_defined(VALUE obj, ID id) 00957 { 00958 st_table *tbl; 00959 st_data_t data; 00960 00961 if (!generic_iv_tbl) return Qfalse; 00962 if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; 00963 tbl = (st_table *)data; 00964 if (st_lookup(tbl, (st_data_t)id, &data)) { 00965 return Qtrue; 00966 } 00967 return Qfalse; 00968 } 00969 00970 static int 00971 generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) 00972 { 00973 st_table *tbl; 00974 st_data_t data, key = (st_data_t)id; 00975 int status; 00976 00977 if (!generic_iv_tbl) return 0; 00978 if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; 00979 tbl = (st_table *)data; 00980 status = st_delete(tbl, &key, valp); 00981 if (tbl->num_entries == 0) { 00982 key = (st_data_t)obj; 00983 st_delete(generic_iv_tbl, &key, &data); 00984 st_free_table((st_table *)data); 00985 } 00986 return status; 00987 } 00988 00989 void 00990 rb_mark_generic_ivar(VALUE obj) 00991 { 00992 st_data_t tbl; 00993 00994 if (!generic_iv_tbl) return; 00995 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { 00996 rb_mark_tbl((st_table *)tbl); 00997 } 00998 } 00999 01000 static int 01001 givar_mark_i(st_data_t k, st_data_t v, st_data_t a) 01002 { 01003 VALUE value = (VALUE)v; 01004 rb_gc_mark(value); 01005 return ST_CONTINUE; 01006 } 01007 01008 static int 01009 givar_i(st_data_t k, st_data_t v, st_data_t a) 01010 { 01011 VALUE obj = (VALUE)k; 01012 st_table *tbl = (st_table *)v; 01013 if (rb_special_const_p(obj)) { 01014 st_foreach_safe(tbl, givar_mark_i, 0); 01015 } 01016 return ST_CONTINUE; 01017 } 01018 01019 void 01020 rb_mark_generic_ivar_tbl(void) 01021 { 01022 if (!generic_iv_tbl) return; 01023 if (special_generic_ivar == 0) return; 01024 st_foreach_safe(generic_iv_tbl, givar_i, 0); 01025 } 01026 01027 void 01028 rb_free_generic_ivar(VALUE obj) 01029 { 01030 st_data_t key = (st_data_t)obj, tbl; 01031 01032 if (!generic_iv_tbl) return; 01033 if (st_delete(generic_iv_tbl, &key, &tbl)) 01034 st_free_table((st_table *)tbl); 01035 } 01036 01037 RUBY_FUNC_EXPORTED size_t 01038 rb_generic_ivar_memsize(VALUE obj) 01039 { 01040 st_data_t tbl; 01041 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) 01042 return st_memsize((st_table *)tbl); 01043 return 0; 01044 } 01045 01046 void 01047 rb_copy_generic_ivar(VALUE clone, VALUE obj) 01048 { 01049 st_data_t data; 01050 01051 if (!generic_iv_tbl) return; 01052 if (!FL_TEST(obj, FL_EXIVAR)) { 01053 clear: 01054 if (FL_TEST(clone, FL_EXIVAR)) { 01055 rb_free_generic_ivar(clone); 01056 FL_UNSET(clone, FL_EXIVAR); 01057 } 01058 return; 01059 } 01060 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { 01061 st_table *tbl = (st_table *)data; 01062 01063 if (tbl->num_entries == 0) 01064 goto clear; 01065 01066 if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { 01067 st_free_table((st_table *)data); 01068 st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); 01069 } 01070 else { 01071 st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); 01072 FL_SET(clone, FL_EXIVAR); 01073 } 01074 } 01075 } 01076 01077 static VALUE 01078 ivar_get(VALUE obj, ID id, int warn) 01079 { 01080 VALUE val, *ptr; 01081 struct st_table *iv_index_tbl; 01082 long len; 01083 st_data_t index; 01084 01085 if (SPECIAL_CONST_P(obj)) goto generic; 01086 switch (BUILTIN_TYPE(obj)) { 01087 case T_OBJECT: 01088 len = ROBJECT_NUMIV(obj); 01089 ptr = ROBJECT_IVPTR(obj); 01090 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01091 if (!iv_index_tbl) break; 01092 if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; 01093 if (len <= (long)index) break; 01094 val = ptr[index]; 01095 if (val != Qundef) 01096 return val; 01097 break; 01098 case T_CLASS: 01099 case T_MODULE: 01100 if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) 01101 return (VALUE)index; 01102 break; 01103 default: 01104 generic: 01105 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) 01106 return generic_ivar_get(obj, id, warn); 01107 break; 01108 } 01109 if (warn) { 01110 rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id)); 01111 } 01112 return Qnil; 01113 } 01114 01115 VALUE 01116 rb_ivar_get(VALUE obj, ID id) 01117 { 01118 return ivar_get(obj, id, TRUE); 01119 } 01120 01121 VALUE 01122 rb_attr_get(VALUE obj, ID id) 01123 { 01124 return ivar_get(obj, id, FALSE); 01125 } 01126 01127 VALUE 01128 rb_ivar_set(VALUE obj, ID id, VALUE val) 01129 { 01130 struct st_table *iv_index_tbl; 01131 st_data_t index; 01132 long i, len; 01133 int ivar_extended; 01134 01135 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) 01136 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); 01137 rb_check_frozen(obj); 01138 if (SPECIAL_CONST_P(obj)) goto generic; 01139 switch (BUILTIN_TYPE(obj)) { 01140 case T_OBJECT: 01141 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01142 if (!iv_index_tbl) { 01143 VALUE klass = rb_obj_class(obj); 01144 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); 01145 if (!iv_index_tbl) { 01146 iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); 01147 } 01148 } 01149 ivar_extended = 0; 01150 if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { 01151 index = iv_index_tbl->num_entries; 01152 st_add_direct(iv_index_tbl, (st_data_t)id, index); 01153 ivar_extended = 1; 01154 } 01155 len = ROBJECT_NUMIV(obj); 01156 if (len <= (long)index) { 01157 VALUE *ptr = ROBJECT_IVPTR(obj); 01158 if (index < ROBJECT_EMBED_LEN_MAX) { 01159 RBASIC(obj)->flags |= ROBJECT_EMBED; 01160 ptr = ROBJECT(obj)->as.ary; 01161 for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) { 01162 ptr[i] = Qundef; 01163 } 01164 } 01165 else { 01166 VALUE *newptr; 01167 long newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */ 01168 if (!ivar_extended && 01169 iv_index_tbl->num_entries < (st_index_t)newsize) { 01170 newsize = iv_index_tbl->num_entries; 01171 } 01172 if (RBASIC(obj)->flags & ROBJECT_EMBED) { 01173 newptr = ALLOC_N(VALUE, newsize); 01174 MEMCPY(newptr, ptr, VALUE, len); 01175 RBASIC(obj)->flags &= ~ROBJECT_EMBED; 01176 ROBJECT(obj)->as.heap.ivptr = newptr; 01177 } 01178 else { 01179 REALLOC_N(ROBJECT(obj)->as.heap.ivptr, VALUE, newsize); 01180 newptr = ROBJECT(obj)->as.heap.ivptr; 01181 } 01182 for (; len < newsize; len++) 01183 newptr[len] = Qundef; 01184 ROBJECT(obj)->as.heap.numiv = newsize; 01185 ROBJECT(obj)->as.heap.iv_index_tbl = iv_index_tbl; 01186 } 01187 } 01188 ROBJECT_IVPTR(obj)[index] = val; 01189 break; 01190 case T_CLASS: 01191 case T_MODULE: 01192 if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); 01193 st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); 01194 break; 01195 default: 01196 generic: 01197 generic_ivar_set(obj, id, val); 01198 break; 01199 } 01200 return val; 01201 } 01202 01203 VALUE 01204 rb_ivar_defined(VALUE obj, ID id) 01205 { 01206 VALUE val; 01207 struct st_table *iv_index_tbl; 01208 st_data_t index; 01209 if (SPECIAL_CONST_P(obj)) goto generic; 01210 switch (BUILTIN_TYPE(obj)) { 01211 case T_OBJECT: 01212 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01213 if (!iv_index_tbl) break; 01214 if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; 01215 if (ROBJECT_NUMIV(obj) <= (long)index) break; 01216 val = ROBJECT_IVPTR(obj)[index]; 01217 if (val != Qundef) 01218 return Qtrue; 01219 break; 01220 case T_CLASS: 01221 case T_MODULE: 01222 if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) 01223 return Qtrue; 01224 break; 01225 default: 01226 generic: 01227 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) 01228 return generic_ivar_defined(obj, id); 01229 break; 01230 } 01231 return Qfalse; 01232 } 01233 01234 struct obj_ivar_tag { 01235 VALUE obj; 01236 int (*func)(ID key, VALUE val, st_data_t arg); 01237 st_data_t arg; 01238 }; 01239 01240 static int 01241 obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) 01242 { 01243 struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; 01244 if ((long)index < ROBJECT_NUMIV(data->obj)) { 01245 VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; 01246 if (val != Qundef) { 01247 return (data->func)((ID)key, val, data->arg); 01248 } 01249 } 01250 return ST_CONTINUE; 01251 } 01252 01253 static void 01254 obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) 01255 { 01256 st_table *tbl; 01257 struct obj_ivar_tag data; 01258 01259 tbl = ROBJECT_IV_INDEX_TBL(obj); 01260 if (!tbl) 01261 return; 01262 01263 data.obj = obj; 01264 data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; 01265 data.arg = arg; 01266 01267 st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); 01268 } 01269 01270 void 01271 rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) 01272 { 01273 if (SPECIAL_CONST_P(obj)) goto generic; 01274 switch (BUILTIN_TYPE(obj)) { 01275 case T_OBJECT: 01276 obj_ivar_each(obj, func, arg); 01277 break; 01278 case T_CLASS: 01279 case T_MODULE: 01280 if (RCLASS_IV_TBL(obj)) { 01281 st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); 01282 } 01283 break; 01284 default: 01285 generic: 01286 if (!generic_iv_tbl) break; 01287 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { 01288 st_data_t tbl; 01289 01290 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { 01291 st_foreach_safe((st_table *)tbl, func, arg); 01292 } 01293 } 01294 break; 01295 } 01296 } 01297 01298 st_index_t 01299 rb_ivar_count(VALUE obj) 01300 { 01301 st_table *tbl; 01302 if (SPECIAL_CONST_P(obj)) goto generic; 01303 switch (BUILTIN_TYPE(obj)) { 01304 case T_OBJECT: 01305 if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { 01306 st_index_t i, count, num = tbl->num_entries; 01307 const VALUE *const ivptr = ROBJECT_IVPTR(obj); 01308 for (i = count = 0; i < num; ++i) { 01309 if (ivptr[i] != Qundef) { 01310 count++; 01311 } 01312 } 01313 return count; 01314 } 01315 break; 01316 case T_CLASS: 01317 case T_MODULE: 01318 if ((tbl = RCLASS_IV_TBL(obj)) != 0) { 01319 return tbl->num_entries; 01320 } 01321 break; 01322 default: 01323 generic: 01324 if (!generic_iv_tbl) break; 01325 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { 01326 st_data_t data; 01327 01328 if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && 01329 (tbl = (st_table *)data) != 0) { 01330 return tbl->num_entries; 01331 } 01332 } 01333 break; 01334 } 01335 return 0; 01336 } 01337 01338 static int 01339 ivar_i(st_data_t k, st_data_t v, st_data_t a) 01340 { 01341 ID key = (ID)k; 01342 VALUE ary = (VALUE)a; 01343 01344 if (rb_is_instance_id(key)) { 01345 rb_ary_push(ary, ID2SYM(key)); 01346 } 01347 return ST_CONTINUE; 01348 } 01349 01350 /* 01351 * call-seq: 01352 * obj.instance_variables -> array 01353 * 01354 * Returns an array of instance variable names for the receiver. Note 01355 * that simply defining an accessor does not create the corresponding 01356 * instance variable. 01357 * 01358 * class Fred 01359 * attr_accessor :a1 01360 * def initialize 01361 * @iv = 3 01362 * end 01363 * end 01364 * Fred.new.instance_variables #=> [:@iv] 01365 */ 01366 01367 VALUE 01368 rb_obj_instance_variables(VALUE obj) 01369 { 01370 VALUE ary; 01371 01372 ary = rb_ary_new(); 01373 rb_ivar_foreach(obj, ivar_i, ary); 01374 return ary; 01375 } 01376 01377 /* 01378 * call-seq: 01379 * obj.remove_instance_variable(symbol) -> obj 01380 * 01381 * Removes the named instance variable from <i>obj</i>, returning that 01382 * variable's value. 01383 * 01384 * class Dummy 01385 * attr_reader :var 01386 * def initialize 01387 * @var = 99 01388 * end 01389 * def remove 01390 * remove_instance_variable(:@var) 01391 * end 01392 * end 01393 * d = Dummy.new 01394 * d.var #=> 99 01395 * d.remove #=> 99 01396 * d.var #=> nil 01397 */ 01398 01399 VALUE 01400 rb_obj_remove_instance_variable(VALUE obj, VALUE name) 01401 { 01402 VALUE val = Qnil; 01403 const ID id = rb_check_id(&name); 01404 st_data_t n, v; 01405 struct st_table *iv_index_tbl; 01406 st_data_t index; 01407 01408 if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) 01409 rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); 01410 rb_check_frozen(obj); 01411 if (!id) { 01412 if (rb_is_instance_name(name)) { 01413 rb_name_error_str(name, "instance variable %"PRIsVALUE" not defined", 01414 name); 01415 } 01416 else { 01417 rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as an instance variable name", 01418 QUOTE(name)); 01419 } 01420 } 01421 if (!rb_is_instance_id(id)) { 01422 rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name", 01423 QUOTE_ID(id)); 01424 } 01425 01426 if (SPECIAL_CONST_P(obj)) goto generic; 01427 switch (BUILTIN_TYPE(obj)) { 01428 case T_OBJECT: 01429 iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); 01430 if (!iv_index_tbl) break; 01431 if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; 01432 if (ROBJECT_NUMIV(obj) <= (long)index) break; 01433 val = ROBJECT_IVPTR(obj)[index]; 01434 if (val != Qundef) { 01435 ROBJECT_IVPTR(obj)[index] = Qundef; 01436 return val; 01437 } 01438 break; 01439 case T_CLASS: 01440 case T_MODULE: 01441 n = id; 01442 if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { 01443 return (VALUE)v; 01444 } 01445 break; 01446 default: 01447 generic: 01448 if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { 01449 v = val; 01450 if (generic_ivar_remove(obj, (st_data_t)id, &v)) { 01451 return (VALUE)v; 01452 } 01453 } 01454 break; 01455 } 01456 rb_name_error(id, "instance variable %"PRIsVALUE" not defined", QUOTE_ID(id)); 01457 01458 UNREACHABLE; 01459 } 01460 01461 NORETURN(static void uninitialized_constant(VALUE, ID)); 01462 static void 01463 uninitialized_constant(VALUE klass, ID id) 01464 { 01465 if (klass && rb_class_real(klass) != rb_cObject) 01466 rb_name_error(id, "uninitialized constant %"PRIsVALUE"::%"PRIsVALUE"", 01467 rb_class_name(klass), 01468 QUOTE_ID(id)); 01469 else { 01470 rb_name_error(id, "uninitialized constant %"PRIsVALUE"", QUOTE_ID(id)); 01471 } 01472 } 01473 01474 static VALUE 01475 const_missing(VALUE klass, ID id) 01476 { 01477 return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id)); 01478 } 01479 01480 01481 /* 01482 * call-seq: 01483 * mod.const_missing(sym) -> obj 01484 * 01485 * Invoked when a reference is made to an undefined constant in 01486 * <i>mod</i>. It is passed a symbol for the undefined constant, and 01487 * returns a value to be used for that constant. The 01488 * following code is an example of the same: 01489 * 01490 * def Foo.const_missing(name) 01491 * name # return the constant name as Symbol 01492 * end 01493 * 01494 * Foo::UNDEFINED_CONST #=> :UNDEFINED_CONST: symbol returned 01495 * 01496 * In the next example when a reference is made to an undefined constant, 01497 * it attempts to load a file whose name is the lowercase version of the 01498 * constant (thus class <code>Fred</code> is assumed to be in file 01499 * <code>fred.rb</code>). If found, it returns the loaded class. It 01500 * therefore implements an autoload feature similar to Kernel#autoload and 01501 * Module#autoload. 01502 * 01503 * def Object.const_missing(name) 01504 * @looked_for ||= {} 01505 * str_name = name.to_s 01506 * raise "Class not found: #{name}" if @looked_for[str_name] 01507 * @looked_for[str_name] = 1 01508 * file = str_name.downcase 01509 * require file 01510 * klass = const_get(name) 01511 * return klass if klass 01512 * raise "Class not found: #{name}" 01513 * end 01514 * 01515 */ 01516 01517 VALUE 01518 rb_mod_const_missing(VALUE klass, VALUE name) 01519 { 01520 rb_frame_pop(); /* pop frame for "const_missing" */ 01521 uninitialized_constant(klass, rb_to_id(name)); 01522 01523 UNREACHABLE; 01524 } 01525 01526 static void 01527 autoload_mark(void *ptr) 01528 { 01529 rb_mark_tbl((st_table *)ptr); 01530 } 01531 01532 static void 01533 autoload_free(void *ptr) 01534 { 01535 st_free_table((st_table *)ptr); 01536 } 01537 01538 static size_t 01539 autoload_memsize(const void *ptr) 01540 { 01541 const st_table *tbl = ptr; 01542 return st_memsize(tbl); 01543 } 01544 01545 static const rb_data_type_t autoload_data_type = { 01546 "autoload", 01547 {autoload_mark, autoload_free, autoload_memsize,}, 01548 }; 01549 01550 #define check_autoload_table(av) \ 01551 (struct st_table *)rb_check_typeddata((av), &autoload_data_type) 01552 01553 static VALUE 01554 autoload_data(VALUE mod, ID id) 01555 { 01556 struct st_table *tbl; 01557 st_data_t val; 01558 01559 if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || 01560 !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { 01561 return 0; 01562 } 01563 return (VALUE)val; 01564 } 01565 01566 struct autoload_data_i { 01567 VALUE feature; 01568 int safe_level; 01569 VALUE thread; 01570 VALUE value; 01571 }; 01572 01573 static void 01574 autoload_i_mark(void *ptr) 01575 { 01576 struct autoload_data_i *p = ptr; 01577 rb_gc_mark(p->feature); 01578 rb_gc_mark(p->thread); 01579 rb_gc_mark(p->value); 01580 } 01581 01582 static void 01583 autoload_i_free(void *ptr) 01584 { 01585 struct autoload_data_i *p = ptr; 01586 xfree(p); 01587 } 01588 01589 static size_t 01590 autoload_i_memsize(const void *ptr) 01591 { 01592 return sizeof(struct autoload_data_i); 01593 } 01594 01595 static const rb_data_type_t autoload_data_i_type = { 01596 "autoload_i", 01597 {autoload_i_mark, autoload_i_free, autoload_i_memsize,}, 01598 }; 01599 01600 #define check_autoload_data(av) \ 01601 (struct autoload_data_i *)rb_check_typeddata((av), &autoload_data_i_type) 01602 01603 void 01604 rb_autoload(VALUE mod, ID id, const char *file) 01605 { 01606 st_data_t av; 01607 VALUE ad, fn; 01608 struct st_table *tbl; 01609 struct autoload_data_i *ele; 01610 01611 if (!rb_is_const_id(id)) { 01612 rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"", 01613 QUOTE_ID(id)); 01614 } 01615 if (!file || !*file) { 01616 rb_raise(rb_eArgError, "empty file name"); 01617 } 01618 01619 if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) 01620 return; 01621 01622 rb_const_set(mod, id, Qundef); 01623 tbl = RCLASS_IV_TBL(mod); 01624 if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { 01625 tbl = check_autoload_table((VALUE)av); 01626 } 01627 else { 01628 if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); 01629 av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); 01630 st_add_direct(tbl, (st_data_t)autoload, av); 01631 DATA_PTR(av) = tbl = st_init_numtable(); 01632 } 01633 fn = rb_str_new2(file); 01634 FL_UNSET(fn, FL_TAINT); 01635 OBJ_FREEZE(fn); 01636 01637 ele = ALLOC(struct autoload_data_i); 01638 ele->feature = fn; 01639 ele->safe_level = rb_safe_level(); 01640 ele->thread = Qnil; 01641 ele->value = Qundef; 01642 ad = TypedData_Wrap_Struct(0, &autoload_data_i_type, ele); 01643 st_insert(tbl, (st_data_t)id, (st_data_t)ad); 01644 } 01645 01646 static void 01647 autoload_delete(VALUE mod, ID id) 01648 { 01649 st_data_t val, load = 0, n = id; 01650 rb_const_entry_t *ce; 01651 01652 st_delete(RCLASS_CONST_TBL(mod), &n, &val); 01653 ce = (rb_const_entry_t*)val; 01654 if (ce) xfree(ce); 01655 if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { 01656 struct st_table *tbl = check_autoload_table((VALUE)val); 01657 01658 st_delete(tbl, &n, &load); 01659 01660 if (tbl->num_entries == 0) { 01661 n = autoload; 01662 st_delete(RCLASS_IV_TBL(mod), &n, &val); 01663 } 01664 } 01665 } 01666 01667 static VALUE 01668 autoload_provided(VALUE arg) 01669 { 01670 const char **p = (const char **)arg; 01671 return rb_feature_provided(*p, p); 01672 } 01673 01674 static VALUE 01675 reset_safe(VALUE safe) 01676 { 01677 rb_set_safe_level_force((int)safe); 01678 return safe; 01679 } 01680 01681 static VALUE 01682 check_autoload_required(VALUE mod, ID id, const char **loadingpath) 01683 { 01684 VALUE file, load; 01685 struct autoload_data_i *ele; 01686 const char *loading; 01687 int safe; 01688 01689 if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) { 01690 return 0; 01691 } 01692 file = ele->feature; 01693 Check_Type(file, T_STRING); 01694 if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) { 01695 rb_raise(rb_eArgError, "empty file name"); 01696 } 01697 loading = RSTRING_PTR(file); 01698 safe = rb_safe_level(); 01699 rb_set_safe_level_force(0); 01700 if (!rb_ensure(autoload_provided, (VALUE)&loading, reset_safe, (VALUE)safe)) { 01701 return load; 01702 } 01703 if (loadingpath && loading) { 01704 *loadingpath = loading; 01705 return load; 01706 } 01707 return 0; 01708 } 01709 01710 int 01711 rb_autoloading_value(VALUE mod, ID id, VALUE* value) 01712 { 01713 VALUE load; 01714 struct autoload_data_i *ele; 01715 01716 if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) { 01717 return 0; 01718 } 01719 if (ele->thread == rb_thread_current()) { 01720 if (ele->value != Qundef) { 01721 if (value) { 01722 *value = ele->value; 01723 } 01724 return 1; 01725 } 01726 } 01727 return 0; 01728 } 01729 01730 static int 01731 autoload_defined_p(VALUE mod, ID id) 01732 { 01733 struct st_table *tbl = RCLASS_CONST_TBL(mod); 01734 st_data_t val; 01735 01736 if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { 01737 return 0; 01738 } 01739 return !rb_autoloading_value(mod, id, NULL); 01740 } 01741 01742 struct autoload_const_set_args { 01743 VALUE mod; 01744 ID id; 01745 VALUE value; 01746 }; 01747 01748 static VALUE 01749 autoload_const_set(VALUE arg) 01750 { 01751 struct autoload_const_set_args* args = (struct autoload_const_set_args *)arg; 01752 autoload_delete(args->mod, args->id); 01753 rb_const_set(args->mod, args->id, args->value); 01754 return 0; /* ignored */ 01755 } 01756 01757 static VALUE 01758 autoload_require(VALUE arg) 01759 { 01760 struct autoload_data_i *ele = (struct autoload_data_i *)arg; 01761 return rb_require_safe(ele->feature, ele->safe_level); 01762 } 01763 01764 VALUE 01765 rb_autoload_load(VALUE mod, ID id) 01766 { 01767 VALUE load, result; 01768 const char *loading = 0, *src; 01769 struct autoload_data_i *ele; 01770 int state = 0; 01771 01772 if (!autoload_defined_p(mod, id)) return Qfalse; 01773 load = check_autoload_required(mod, id, &loading); 01774 if (!load) return Qfalse; 01775 src = rb_sourcefile(); 01776 if (src && loading && strcmp(src, loading) == 0) return Qfalse; 01777 01778 /* set ele->thread for a marker of autoloading thread */ 01779 if (!(ele = check_autoload_data(load))) { 01780 return Qfalse; 01781 } 01782 if (ele->thread == Qnil) { 01783 ele->thread = rb_thread_current(); 01784 } 01785 /* autoload_data_i can be deleted by another thread while require */ 01786 result = rb_protect(autoload_require, (VALUE)ele, &state); 01787 if (ele->thread == rb_thread_current()) { 01788 ele->thread = Qnil; 01789 } 01790 if (state) rb_jump_tag(state); 01791 01792 if (RTEST(result)) { 01793 /* At the last, move a value defined in autoload to constant table */ 01794 if (ele->value != Qundef) { 01795 int safe_backup; 01796 struct autoload_const_set_args args; 01797 args.mod = mod; 01798 args.id = id; 01799 args.value = ele->value; 01800 safe_backup = rb_safe_level(); 01801 rb_set_safe_level_force(ele->safe_level); 01802 rb_ensure(autoload_const_set, (VALUE)&args, reset_safe, (VALUE)safe_backup); 01803 } 01804 } 01805 RB_GC_GUARD(load); 01806 return result; 01807 } 01808 01809 VALUE 01810 rb_autoload_p(VALUE mod, ID id) 01811 { 01812 VALUE load; 01813 struct autoload_data_i *ele; 01814 01815 while (!autoload_defined_p(mod, id)) { 01816 mod = RCLASS_SUPER(mod); 01817 if (!mod) return Qnil; 01818 } 01819 load = check_autoload_required(mod, id, 0); 01820 if (!load) return Qnil; 01821 return (ele = check_autoload_data(load)) ? ele->feature : Qnil; 01822 } 01823 01824 static VALUE 01825 rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) 01826 { 01827 VALUE value, tmp, av; 01828 int mod_retry = 0; 01829 01830 tmp = klass; 01831 retry: 01832 while (RTEST(tmp)) { 01833 VALUE am = 0; 01834 st_data_t data; 01835 while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { 01836 rb_const_entry_t *ce = (rb_const_entry_t *)data; 01837 if (visibility && ce->flag == CONST_PRIVATE) { 01838 rb_name_error(id, "private constant %"PRIsVALUE"::%"PRIsVALUE" referenced", 01839 rb_class_name(klass), QUOTE_ID(id)); 01840 } 01841 value = ce->value; 01842 if (value == Qundef) { 01843 if (am == tmp) break; 01844 am = tmp; 01845 if (rb_autoloading_value(tmp, id, &av)) return av; 01846 rb_autoload_load(tmp, id); 01847 continue; 01848 } 01849 if (exclude && tmp == rb_cObject && klass != rb_cObject) { 01850 rb_warn("toplevel constant %"PRIsVALUE" referenced by %"PRIsVALUE"::%"PRIsVALUE"", 01851 QUOTE_ID(id), rb_class_name(klass), QUOTE_ID(id)); 01852 } 01853 return value; 01854 } 01855 if (!recurse) break; 01856 tmp = RCLASS_SUPER(tmp); 01857 } 01858 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) { 01859 mod_retry = 1; 01860 tmp = rb_cObject; 01861 goto retry; 01862 } 01863 01864 value = const_missing(klass, id); 01865 rb_vm_inc_const_missing_count(); 01866 return value; 01867 } 01868 01869 VALUE 01870 rb_const_get_from(VALUE klass, ID id) 01871 { 01872 return rb_const_get_0(klass, id, TRUE, TRUE, FALSE); 01873 } 01874 01875 VALUE 01876 rb_const_get(VALUE klass, ID id) 01877 { 01878 return rb_const_get_0(klass, id, FALSE, TRUE, FALSE); 01879 } 01880 01881 VALUE 01882 rb_const_get_at(VALUE klass, ID id) 01883 { 01884 return rb_const_get_0(klass, id, TRUE, FALSE, FALSE); 01885 } 01886 01887 VALUE 01888 rb_public_const_get_from(VALUE klass, ID id) 01889 { 01890 return rb_const_get_0(klass, id, TRUE, TRUE, TRUE); 01891 } 01892 01893 VALUE 01894 rb_public_const_get(VALUE klass, ID id) 01895 { 01896 return rb_const_get_0(klass, id, FALSE, TRUE, TRUE); 01897 } 01898 01899 VALUE 01900 rb_public_const_get_at(VALUE klass, ID id) 01901 { 01902 return rb_const_get_0(klass, id, TRUE, FALSE, TRUE); 01903 } 01904 01905 /* 01906 * call-seq: 01907 * remove_const(sym) -> obj 01908 * 01909 * Removes the definition of the given constant, returning that 01910 * constant's previous value. If that constant referred to 01911 * a module, this will not change that module's name and can lead 01912 * to confusion. 01913 */ 01914 01915 VALUE 01916 rb_mod_remove_const(VALUE mod, VALUE name) 01917 { 01918 const ID id = rb_check_id(&name); 01919 01920 if (!id) { 01921 if (rb_is_const_name(name)) { 01922 rb_name_error_str(name, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", 01923 rb_class_name(mod), name); 01924 } 01925 else { 01926 rb_name_error_str(name, "`%"PRIsVALUE"' is not allowed as a constant name", 01927 QUOTE(name)); 01928 } 01929 } 01930 if (!rb_is_const_id(id)) { 01931 rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a constant name", 01932 QUOTE_ID(id)); 01933 } 01934 return rb_const_remove(mod, id); 01935 } 01936 01937 VALUE 01938 rb_const_remove(VALUE mod, ID id) 01939 { 01940 VALUE val; 01941 st_data_t v, n = id; 01942 01943 if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) 01944 rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); 01945 rb_check_frozen(mod); 01946 if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { 01947 if (rb_const_defined_at(mod, id)) { 01948 rb_name_error(id, "cannot remove %"PRIsVALUE"::%"PRIsVALUE"", 01949 rb_class_name(mod), QUOTE_ID(id)); 01950 } 01951 rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", 01952 rb_class_name(mod), QUOTE_ID(id)); 01953 } 01954 01955 rb_vm_change_state(); 01956 01957 val = ((rb_const_entry_t*)v)->value; 01958 if (val == Qundef) { 01959 autoload_delete(mod, id); 01960 val = Qnil; 01961 } 01962 xfree((rb_const_entry_t*)v); 01963 return val; 01964 } 01965 01966 static int 01967 sv_i(st_data_t k, st_data_t v, st_data_t a) 01968 { 01969 ID key = (ID)k; 01970 rb_const_entry_t *ce = (rb_const_entry_t *)v; 01971 st_table *tbl = (st_table *)a; 01972 01973 if (rb_is_const_id(key)) { 01974 if (!st_lookup(tbl, (st_data_t)key, 0)) { 01975 st_insert(tbl, (st_data_t)key, (st_data_t)ce); 01976 } 01977 } 01978 return ST_CONTINUE; 01979 } 01980 01981 void* 01982 rb_mod_const_at(VALUE mod, void *data) 01983 { 01984 st_table *tbl = data; 01985 if (!tbl) { 01986 tbl = st_init_numtable(); 01987 } 01988 if (RCLASS_CONST_TBL(mod)) { 01989 st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); 01990 } 01991 return tbl; 01992 } 01993 01994 void* 01995 rb_mod_const_of(VALUE mod, void *data) 01996 { 01997 VALUE tmp = mod; 01998 for (;;) { 01999 data = rb_mod_const_at(tmp, data); 02000 tmp = RCLASS_SUPER(tmp); 02001 if (!tmp) break; 02002 if (tmp == rb_cObject && mod != rb_cObject) break; 02003 } 02004 return data; 02005 } 02006 02007 static int 02008 list_i(st_data_t key, st_data_t value, VALUE ary) 02009 { 02010 ID sym = (ID)key; 02011 rb_const_entry_t *ce = (rb_const_entry_t *)value; 02012 if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); 02013 return ST_CONTINUE; 02014 } 02015 02016 VALUE 02017 rb_const_list(void *data) 02018 { 02019 st_table *tbl = data; 02020 VALUE ary; 02021 02022 if (!tbl) return rb_ary_new2(0); 02023 ary = rb_ary_new2(tbl->num_entries); 02024 st_foreach_safe(tbl, list_i, ary); 02025 st_free_table(tbl); 02026 02027 return ary; 02028 } 02029 02030 /* 02031 * call-seq: 02032 * mod.constants(inherit=true) -> array 02033 * 02034 * Returns an array of the names of the constants accessible in 02035 * <i>mod</i>. This includes the names of constants in any included 02036 * modules (example at start of section), unless the <i>inherit</i> 02037 * parameter is set to <code>false</code>. 02038 * 02039 * IO.constants.include?(:SYNC) #=> true 02040 * IO.constants(false).include?(:SYNC) #=> false 02041 * 02042 * Also see <code>Module::const_defined?</code>. 02043 */ 02044 02045 VALUE 02046 rb_mod_constants(int argc, VALUE *argv, VALUE mod) 02047 { 02048 VALUE inherit; 02049 st_table *tbl; 02050 02051 if (argc == 0) { 02052 inherit = Qtrue; 02053 } 02054 else { 02055 rb_scan_args(argc, argv, "01", &inherit); 02056 } 02057 if (RTEST(inherit)) { 02058 tbl = rb_mod_const_of(mod, 0); 02059 } 02060 else { 02061 tbl = rb_mod_const_at(mod, 0); 02062 } 02063 return rb_const_list(tbl); 02064 } 02065 02066 static int 02067 rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) 02068 { 02069 st_data_t value; 02070 VALUE tmp; 02071 int mod_retry = 0; 02072 02073 tmp = klass; 02074 retry: 02075 while (tmp) { 02076 if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { 02077 rb_const_entry_t *ce = (rb_const_entry_t *)value; 02078 if (visibility && ce->flag == CONST_PRIVATE) { 02079 return (int)Qfalse; 02080 } 02081 if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) && !rb_autoloading_value(tmp, id, 0)) 02082 return (int)Qfalse; 02083 return (int)Qtrue; 02084 } 02085 if (!recurse) break; 02086 tmp = RCLASS_SUPER(tmp); 02087 } 02088 if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) { 02089 mod_retry = 1; 02090 tmp = rb_cObject; 02091 goto retry; 02092 } 02093 return (int)Qfalse; 02094 } 02095 02096 int 02097 rb_const_defined_from(VALUE klass, ID id) 02098 { 02099 return rb_const_defined_0(klass, id, TRUE, TRUE, FALSE); 02100 } 02101 02102 int 02103 rb_const_defined(VALUE klass, ID id) 02104 { 02105 return rb_const_defined_0(klass, id, FALSE, TRUE, FALSE); 02106 } 02107 02108 int 02109 rb_const_defined_at(VALUE klass, ID id) 02110 { 02111 return rb_const_defined_0(klass, id, TRUE, FALSE, FALSE); 02112 } 02113 02114 int 02115 rb_public_const_defined_from(VALUE klass, ID id) 02116 { 02117 return rb_const_defined_0(klass, id, TRUE, TRUE, TRUE); 02118 } 02119 02120 int 02121 rb_public_const_defined(VALUE klass, ID id) 02122 { 02123 return rb_const_defined_0(klass, id, FALSE, TRUE, TRUE); 02124 } 02125 02126 int 02127 rb_public_const_defined_at(VALUE klass, ID id) 02128 { 02129 return rb_const_defined_0(klass, id, TRUE, FALSE, TRUE); 02130 } 02131 02132 static void 02133 check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest) 02134 { 02135 if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4) 02136 rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest); 02137 rb_check_frozen(klass); 02138 } 02139 02140 void 02141 rb_const_set(VALUE klass, ID id, VALUE val) 02142 { 02143 rb_const_entry_t *ce; 02144 VALUE visibility = CONST_PUBLIC; 02145 02146 if (NIL_P(klass)) { 02147 rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"", 02148 QUOTE_ID(id)); 02149 } 02150 02151 check_before_mod_set(klass, id, val, "constant"); 02152 if (!RCLASS_CONST_TBL(klass)) { 02153 RCLASS_CONST_TBL(klass) = st_init_numtable(); 02154 } 02155 else { 02156 st_data_t value; 02157 02158 if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { 02159 rb_const_entry_t *ce = (rb_const_entry_t*)value; 02160 if (ce->value == Qundef) { 02161 VALUE load; 02162 struct autoload_data_i *ele; 02163 02164 load = autoload_data(klass, id); 02165 /* for autoloading thread, keep the defined value to autoloading storage */ 02166 if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) { 02167 rb_vm_change_state(); 02168 ele->value = val; 02169 return; 02170 } 02171 /* otherwise, allow to override */ 02172 autoload_delete(klass, id); 02173 } 02174 else { 02175 VALUE name = QUOTE_ID(id); 02176 visibility = ce->flag; 02177 if (klass == rb_cObject) 02178 rb_warn("already initialized constant %"PRIsVALUE"", name); 02179 else 02180 rb_warn("already initialized constant %"PRIsVALUE"::%"PRIsVALUE"", 02181 rb_class_name(klass), name); 02182 if (!NIL_P(ce->file) && ce->line) { 02183 rb_compile_warn(RSTRING_PTR(ce->file), ce->line, 02184 "previous definition of %"PRIsVALUE" was here", name); 02185 } 02186 st_delete(RCLASS_CONST_TBL(klass), &id, 0); 02187 xfree(ce); 02188 } 02189 } 02190 } 02191 02192 rb_vm_change_state(); 02193 02194 ce = ALLOC(rb_const_entry_t); 02195 ce->flag = (rb_const_flag_t)visibility; 02196 ce->value = val; 02197 ce->file = rb_sourcefilename(); 02198 ce->line = rb_sourceline(); 02199 02200 st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); 02201 } 02202 02203 void 02204 rb_define_const(VALUE klass, const char *name, VALUE val) 02205 { 02206 ID id = rb_intern(name); 02207 02208 if (!rb_is_const_id(id)) { 02209 rb_warn("rb_define_const: invalid name `%s' for constant", name); 02210 } 02211 if (klass == rb_cObject) { 02212 rb_secure(4); 02213 } 02214 rb_const_set(klass, id, val); 02215 } 02216 02217 void 02218 rb_define_global_const(const char *name, VALUE val) 02219 { 02220 rb_define_const(rb_cObject, name, val); 02221 } 02222 02223 static void 02224 set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) 02225 { 02226 int i; 02227 st_data_t v; 02228 ID id; 02229 02230 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(mod)) { 02231 rb_raise(rb_eSecurityError, 02232 "Insecure: can't change constant visibility"); 02233 } 02234 02235 if (argc == 0) { 02236 rb_warning("%"PRIsVALUE" with no argument is just ignored", 02237 QUOTE_ID(rb_frame_this_func())); 02238 } 02239 02240 for (i = 0; i < argc; i++) { 02241 VALUE val = argv[i]; 02242 id = rb_check_id(&val); 02243 if (!id) { 02244 if (i > 0) 02245 rb_clear_cache_by_class(mod); 02246 rb_name_error_str(val, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", 02247 rb_class_name(mod), QUOTE(val)); 02248 } 02249 if (RCLASS_CONST_TBL(mod) && 02250 st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { 02251 ((rb_const_entry_t*)v)->flag = flag; 02252 } 02253 else { 02254 if (i > 0) 02255 rb_clear_cache_by_class(mod); 02256 rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined", 02257 rb_class_name(mod), QUOTE_ID(id)); 02258 } 02259 } 02260 rb_clear_cache_by_class(mod); 02261 } 02262 02263 /* 02264 * call-seq: 02265 * mod.private_constant(symbol, ...) => mod 02266 * 02267 * Makes a list of existing constants private. 02268 */ 02269 02270 VALUE 02271 rb_mod_private_constant(int argc, VALUE *argv, VALUE obj) 02272 { 02273 set_const_visibility(obj, argc, argv, CONST_PRIVATE); 02274 return obj; 02275 } 02276 02277 /* 02278 * call-seq: 02279 * mod.public_constant(symbol, ...) => mod 02280 * 02281 * Makes a list of existing constants public. 02282 */ 02283 02284 VALUE 02285 rb_mod_public_constant(int argc, VALUE *argv, VALUE obj) 02286 { 02287 set_const_visibility(obj, argc, argv, CONST_PUBLIC); 02288 return obj; 02289 } 02290 02291 static VALUE 02292 original_module(VALUE c) 02293 { 02294 if (RB_TYPE_P(c, T_ICLASS)) 02295 return RBASIC(c)->klass; 02296 return c; 02297 } 02298 02299 static int 02300 cvar_lookup_at(VALUE klass, ID id, st_data_t *v) 02301 { 02302 if (!RCLASS_IV_TBL(klass)) return 0; 02303 return st_lookup(RCLASS_IV_TBL(klass), (st_data_t)id, v); 02304 } 02305 02306 static VALUE 02307 cvar_front_klass(VALUE klass) 02308 { 02309 if (FL_TEST(klass, FL_SINGLETON)) { 02310 VALUE obj = rb_iv_get(klass, "__attached__"); 02311 if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) { 02312 return obj; 02313 } 02314 } 02315 return RCLASS_SUPER(klass); 02316 } 02317 02318 #define CVAR_FOREACH_ANCESTORS(klass, v, r) \ 02319 for (klass = cvar_front_klass(klass); klass; klass = RCLASS_SUPER(klass)) { \ 02320 if (cvar_lookup_at(klass, id, (v))) { \ 02321 r; \ 02322 } \ 02323 } 02324 02325 #define CVAR_LOOKUP(v,r) do {\ 02326 if (cvar_lookup_at(klass, id, (v))) {r;}\ 02327 CVAR_FOREACH_ANCESTORS(klass, v, r);\ 02328 } while(0) 02329 02330 void 02331 rb_cvar_set(VALUE klass, ID id, VALUE val) 02332 { 02333 VALUE tmp, front = 0, target = 0; 02334 02335 tmp = klass; 02336 CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); 02337 if (target) { 02338 if (front && target != front) { 02339 st_data_t did = id; 02340 02341 if (RTEST(ruby_verbose)) { 02342 rb_warning("class variable %"PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"", 02343 QUOTE_ID(id), rb_class_name(original_module(front)), 02344 rb_class_name(original_module(target))); 02345 } 02346 if (BUILTIN_TYPE(front) == T_CLASS) { 02347 st_delete(RCLASS_IV_TBL(front),&did,0); 02348 } 02349 } 02350 } 02351 else { 02352 target = tmp; 02353 } 02354 02355 check_before_mod_set(target, id, val, "class variable"); 02356 if (!RCLASS_IV_TBL(target)) { 02357 RCLASS_IV_TBL(target) = st_init_numtable(); 02358 } 02359 02360 st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); 02361 } 02362 02363 VALUE 02364 rb_cvar_get(VALUE klass, ID id) 02365 { 02366 VALUE tmp, front = 0, target = 0; 02367 st_data_t value; 02368 02369 tmp = klass; 02370 CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;}); 02371 if (!target) { 02372 rb_name_error(id, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"", 02373 QUOTE_ID(id), rb_class_name(tmp)); 02374 } 02375 if (front && target != front) { 02376 st_data_t did = id; 02377 02378 if (RTEST(ruby_verbose)) { 02379 rb_warning("class variable %"PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"", 02380 QUOTE_ID(id), rb_class_name(original_module(front)), 02381 rb_class_name(original_module(target))); 02382 } 02383 if (BUILTIN_TYPE(front) == T_CLASS) { 02384 st_delete(RCLASS_IV_TBL(front),&did,0); 02385 } 02386 } 02387 return (VALUE)value; 02388 } 02389 02390 VALUE 02391 rb_cvar_defined(VALUE klass, ID id) 02392 { 02393 if (!klass) return Qfalse; 02394 CVAR_LOOKUP(0,return Qtrue); 02395 return Qfalse; 02396 } 02397 02398 void 02399 rb_cv_set(VALUE klass, const char *name, VALUE val) 02400 { 02401 ID id = rb_intern(name); 02402 if (!rb_is_class_id(id)) { 02403 rb_name_error(id, "wrong class variable name %s", name); 02404 } 02405 rb_cvar_set(klass, id, val); 02406 } 02407 02408 VALUE 02409 rb_cv_get(VALUE klass, const char *name) 02410 { 02411 ID id = rb_intern(name); 02412 if (!rb_is_class_id(id)) { 02413 rb_name_error(id, "wrong class variable name %s", name); 02414 } 02415 return rb_cvar_get(klass, id); 02416 } 02417 02418 void 02419 rb_define_class_variable(VALUE klass, const char *name, VALUE val) 02420 { 02421 ID id = rb_intern(name); 02422 02423 if (!rb_is_class_id(id)) { 02424 rb_name_error(id, "wrong class variable name %s", name); 02425 } 02426 rb_cvar_set(klass, id, val); 02427 } 02428 02429 static int 02430 cv_i(st_data_t k, st_data_t v, st_data_t a) 02431 { 02432 ID key = (ID)k; 02433 st_table *tbl = (st_table *)a; 02434 02435 if (rb_is_class_id(key)) { 02436 if (!st_lookup(tbl, (st_data_t)key, 0)) { 02437 st_insert(tbl, (st_data_t)key, 0); 02438 } 02439 } 02440 return ST_CONTINUE; 02441 } 02442 02443 static void* 02444 mod_cvar_at(VALUE mod, void *data) 02445 { 02446 st_table *tbl = data; 02447 if (!tbl) { 02448 tbl = st_init_numtable(); 02449 } 02450 if (RCLASS_IV_TBL(mod)) { 02451 st_foreach_safe(RCLASS_IV_TBL(mod), cv_i, (st_data_t)tbl); 02452 } 02453 return tbl; 02454 } 02455 02456 static void* 02457 mod_cvar_of(VALUE mod, void *data) 02458 { 02459 VALUE tmp = mod; 02460 for (;;) { 02461 data = mod_cvar_at(tmp, data); 02462 tmp = RCLASS_SUPER(tmp); 02463 if (!tmp) break; 02464 } 02465 return data; 02466 } 02467 02468 static int 02469 cv_list_i(st_data_t key, st_data_t value, VALUE ary) 02470 { 02471 ID sym = (ID)key; 02472 rb_ary_push(ary, ID2SYM(sym)); 02473 return ST_CONTINUE; 02474 } 02475 02476 static VALUE 02477 cvar_list(void *data) 02478 { 02479 st_table *tbl = data; 02480 VALUE ary; 02481 02482 if (!tbl) return rb_ary_new2(0); 02483 ary = rb_ary_new2(tbl->num_entries); 02484 st_foreach_safe(tbl, cv_list_i, ary); 02485 st_free_table(tbl); 02486 02487 return ary; 02488 } 02489 02490 /* 02491 * call-seq: 02492 * mod.class_variables(inherit=true) -> array 02493 * 02494 * Returns an array of the names of class variables in <i>mod</i>. 02495 * This includes the names of class variables in any included 02496 * modules, unless the <i>inherit</i> parameter is set to 02497 * <code>false</code>. 02498 * 02499 * class One 02500 * @@var1 = 1 02501 * end 02502 * class Two < One 02503 * @@var2 = 2 02504 * end 02505 * One.class_variables #=> [:@@var1] 02506 * Two.class_variables #=> [:@@var2, :@@var1] 02507 * Two.class_variables(false) #=> [:@@var2] 02508 */ 02509 02510 VALUE 02511 rb_mod_class_variables(int argc, VALUE *argv, VALUE mod) 02512 { 02513 VALUE inherit; 02514 st_table *tbl; 02515 02516 if (argc == 0) { 02517 inherit = Qtrue; 02518 } 02519 else { 02520 rb_scan_args(argc, argv, "01", &inherit); 02521 } 02522 if (RTEST(inherit)) { 02523 tbl = mod_cvar_of(mod, 0); 02524 } 02525 else { 02526 tbl = mod_cvar_at(mod, 0); 02527 } 02528 return cvar_list(tbl); 02529 } 02530 02531 /* 02532 * call-seq: 02533 * remove_class_variable(sym) -> obj 02534 * 02535 * Removes the definition of the <i>sym</i>, returning that 02536 * constant's value. 02537 * 02538 * class Dummy 02539 * @@var = 99 02540 * puts @@var 02541 * remove_class_variable(:@@var) 02542 * p(defined? @@var) 02543 * end 02544 * 02545 * <em>produces:</em> 02546 * 02547 * 99 02548 * nil 02549 */ 02550 02551 VALUE 02552 rb_mod_remove_cvar(VALUE mod, VALUE name) 02553 { 02554 const ID id = rb_check_id(&name); 02555 st_data_t val, n = id; 02556 02557 if (!id) { 02558 if (rb_is_class_name(name)) { 02559 rb_name_error_str(name, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"", 02560 name, rb_class_name(mod)); 02561 } 02562 else { 02563 rb_name_error_str(name, "wrong class variable name %"PRIsVALUE"", QUOTE(name)); 02564 } 02565 } 02566 if (!rb_is_class_id(id)) { 02567 rb_name_error(id, "wrong class variable name %"PRIsVALUE"", QUOTE_ID(id)); 02568 } 02569 if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) 02570 rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); 02571 rb_check_frozen(mod); 02572 if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { 02573 return (VALUE)val; 02574 } 02575 if (rb_cvar_defined(mod, id)) { 02576 rb_name_error(id, "cannot remove %"PRIsVALUE" for %"PRIsVALUE"", 02577 QUOTE_ID(id), rb_class_name(mod)); 02578 } 02579 rb_name_error(id, "class variable %"PRIsVALUE" not defined for %"PRIsVALUE"", 02580 QUOTE_ID(id), rb_class_name(mod)); 02581 02582 UNREACHABLE; 02583 } 02584 02585 VALUE 02586 rb_iv_get(VALUE obj, const char *name) 02587 { 02588 ID id = rb_intern(name); 02589 02590 return rb_ivar_get(obj, id); 02591 } 02592 02593 VALUE 02594 rb_iv_set(VALUE obj, const char *name, VALUE val) 02595 { 02596 ID id = rb_intern(name); 02597 02598 return rb_ivar_set(obj, id, val); 02599 } 02600
1.7.6.1