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