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