diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
commit | 62e648e148b3cb9f96dcce808c55c02b7ccb4486 (patch) | |
tree | 9708892ece92e860d81559ab55e6b1f9400d7ffc /variable.c | |
parent | aeb049c573be4dc24dd20650f40e4777e0f698cf (diff) |
ruby 1.3 cycle
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/RUBY@372 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 613 |
1 files changed, 396 insertions, 217 deletions
diff --git a/variable.c b/variable.c index 0115b87d68..03262c5d83 100644 --- a/variable.c +++ b/variable.c @@ -13,24 +13,18 @@ #include "node.h" #include "st.h" +#ifdef USE_CWGUSI +char* strdup(char*); +#endif + static st_table *rb_global_tbl; st_table *rb_class_tbl; -#define global_tbl rb_global_tbl -#define class_tbl rb_class_tbl - -int rb_const_defined(); - -st_table* -new_idhash() -{ - return st_init_numtable(); -} void Init_var_tables() { - global_tbl = new_idhash(); - class_tbl = new_idhash(); + rb_global_tbl = st_init_numtable(); + rb_class_tbl = st_init_numtable(); } struct fc_result { @@ -41,8 +35,6 @@ struct fc_result { struct fc_result *prev; }; -extern VALUE cModule; - static int fc_i(key, value, res) ID key; @@ -56,19 +48,19 @@ fc_i(key, value, res) name = rb_id2name(key); if (res->path) { - path = str_dup(res->path); - str_cat(path, "::", 2); - str_cat(path, name, strlen(name)); + path = rb_str_dup(res->path); + rb_str_cat(path, "::", 2); + rb_str_cat(path, name, strlen(name)); } else { - path = str_new2(name); + path = rb_str_new2(name); } if (value == res->klass) { res->name = key; res->path = path; return ST_STOP; } - if (obj_is_kind_of(value, cModule)) { + if (rb_obj_is_kind_of(value, rb_cModule)) { struct fc_result arg; struct fc_result *list; @@ -97,99 +89,108 @@ fc_i(key, value, res) } static VALUE -find_class_path(cls) - VALUE cls; +find_class_path(klass) + VALUE klass; { struct fc_result arg; arg.name = 0; arg.path = 0; - arg.klass = cls; - arg.track = cObject; + arg.klass = klass; + arg.track = rb_cObject; arg.prev = 0; - if (RCLASS(cObject)->iv_tbl) { - st_foreach(RCLASS(cObject)->iv_tbl, fc_i, &arg); + if (RCLASS(rb_cObject)->iv_tbl) { + st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, &arg); } if (arg.name == 0) { - st_foreach(class_tbl, fc_i, &arg); + st_foreach(rb_class_tbl, fc_i, &arg); } if (arg.name) { - rb_iv_set(cls, "__classpath__", arg.path); + rb_iv_set(klass, "__classpath__", arg.path); return arg.path; } return Qnil; } static VALUE -classname(cls) - VALUE cls; +classname(klass) + VALUE klass; { VALUE path; + ID classpath = rb_intern("__classpath__"); - while (TYPE(cls) == T_ICLASS || FL_TEST(cls, FL_SINGLETON)) { - cls = (VALUE)RCLASS(cls)->super; + while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) { + klass = (VALUE)RCLASS(klass)->super; } - path = rb_iv_get(cls, "__classpath__"); - if (NIL_P(path)) { - path = rb_iv_get(cls, "__classid__"); + if (!klass) klass = rb_cObject; + if (!ROBJECT(klass)->iv_tbl || + !st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) { + ID classid = rb_intern("__classid__"); + + path = rb_ivar_get(klass, classid); if (!NIL_P(path)) { - path = str_new2(rb_id2name(FIX2INT(path))); + path = rb_str_new2(rb_id2name(FIX2INT(path))); + if (!ROBJECT(klass)->iv_tbl) + ROBJECT(klass)->iv_tbl = st_init_numtable(); + st_insert(ROBJECT(klass)->iv_tbl, classpath, path); + st_delete(RCLASS(klass)->iv_tbl, &classid, 0); } } if (NIL_P(path)) { - path = find_class_path(cls); + path = find_class_path(klass); if (NIL_P(path)) { return 0; } return path; } - if (TYPE(path) != T_STRING) Bug("class path is not set properly"); + if (TYPE(path) != T_STRING) + rb_bug("class path is not set properly"); return path; } VALUE -mod_name(mod) +rb_mod_name(mod) VALUE mod; { VALUE path = classname(mod); - if (path) return path; - return str_new(0,0); + if (path) return rb_str_dup(path); + return rb_str_new(0,0); } VALUE -rb_class_path(cls) - VALUE cls; +rb_class_path(klass) + VALUE klass; { - VALUE path = classname(cls); + VALUE path = classname(klass); if (path) return path; else { char buf[256]; char *s = "Class"; - if (TYPE(cls) == T_MODULE) s = "Module"; - sprintf(buf, "#<%s 0x%x>", s, cls); - return str_new2(buf); + if (TYPE(klass) == T_MODULE) s = "Module"; + sprintf(buf, "#<%s 0x%x>", s, klass); + return rb_str_new2(buf); } } void -rb_set_class_path(cls, under, name) - VALUE cls, under; +rb_set_class_path(klass, under, name) + VALUE klass, under; char *name; { VALUE str; - if (under == cObject) { - str = str_new2(name); + if (under == rb_cObject) { + str = rb_str_new2(name); } else { - str = str_dup(rb_class_path(under)); - str_cat(str, "::", 2); - str_cat(str, name, strlen(name)); + str = rb_str_dup(rb_class_path(under)); + rb_str_cat(str, "::", 2); + rb_str_cat(str, name, strlen(name)); } - rb_iv_set(cls, "__classpath__", str); + rb_iv_set(klass, "__classpath__", str); } VALUE @@ -197,24 +198,17 @@ rb_path2class(path) char *path; { if (path[0] == '#') { - ArgError("can't retrieve anonymous class %s", path); + rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path); } return rb_eval_string(path); } void -rb_name_class(cls, id) - VALUE cls; +rb_name_class(klass, id) + VALUE klass; ID id; { - extern VALUE cString; - - if (cString) { - rb_iv_set(cls, "__classpath__", str_new2(rb_id2name(id))); - } - else { - rb_iv_set(cls, "__classid__", INT2FIX(id)); - } + rb_iv_set(klass, "__classid__", INT2FIX(id)); } static st_table *autoload_tbl = 0; @@ -225,38 +219,36 @@ rb_autoload_id(id, filename) char *filename; { if (!rb_is_const_id(id)) { - NameError("autoload must be constant name", rb_id2name(id)); + rb_raise(rb_eNameError, "autoload must be constant name", + rb_id2name(id)); } if (!autoload_tbl) { - autoload_tbl = new_idhash(); + autoload_tbl = st_init_numtable(); } st_insert(autoload_tbl, id, strdup(filename)); } void -rb_autoload(cls, filename) - char *cls, *filename; +rb_autoload(klass, filename) + char *klass, *filename; { - rb_autoload_id(rb_intern(cls), filename); + rb_autoload_id(rb_intern(klass), filename); } VALUE -f_autoload(obj, cls, file) - VALUE obj, cls, file; +rb_f_autoload(obj, klass, file) + VALUE obj, klass, file; { - ID id = rb_to_id(cls); - - Check_Type(file, T_STRING); - rb_autoload_id(id, RSTRING(file)->ptr); + rb_autoload_id(rb_to_id(klass), STR2CSTR(file)); return Qnil; } char * -rb_class2name(cls) - VALUE cls; +rb_class2name(klass) + VALUE klass; { - return RSTRING(rb_class_path(cls))->ptr; + return RSTRING(rb_class_path(klass))->ptr; } struct trace_var { @@ -294,9 +286,9 @@ rb_global_entry(id) { struct global_entry *entry; - if (!st_lookup(global_tbl, id, &entry)) { + if (!st_lookup(rb_global_tbl, id, &entry)) { entry = ALLOC(struct global_entry); - st_insert(global_tbl, id, entry); + st_add_direct(rb_global_tbl, id, entry); entry->id = id; entry->data = 0; entry->getter = undef_getter; @@ -313,7 +305,9 @@ static VALUE undef_getter(id) ID id; { - Warning("global variable `%s' not initialized", rb_id2name(id)); + if (rb_verbose) { + rb_warning("global variable `%s' not initialized", rb_id2name(id)); + } return Qnil; } @@ -358,7 +352,7 @@ static void val_marker(data) void *data; { - if (data) gc_mark_maybe(data); + if (data) rb_gc_mark_maybe(data); } static VALUE @@ -383,7 +377,7 @@ static void var_marker(var) VALUE **var; { - if (var) gc_mark_maybe(*var); + if (var) rb_gc_mark_maybe(*var); } static void @@ -392,7 +386,7 @@ readonly_setter(val, id, var) ID id; void *var; { - NameError("Can't set variable %s", rb_id2name(id)); + rb_raise(rb_eNameError, "Can't set variable %s", rb_id2name(id)); } static int @@ -405,16 +399,16 @@ mark_global_entry(key, entry) (*entry->marker)(entry->data); trace = entry->trace; while (trace) { - if (trace->data) gc_mark_maybe(trace->data); + if (trace->data) rb_gc_mark_maybe(trace->data); trace = trace->next; } return ST_CONTINUE; } void -gc_mark_global_tbl() +rb_gc_mark_global_tbl() { - st_foreach(global_tbl, mark_global_entry, 0); + st_foreach(rb_global_tbl, mark_global_entry, 0); } static ID @@ -481,11 +475,11 @@ static void rb_trace_eval(cmd, val) VALUE cmd, val; { - rb_eval_cmd(cmd, ary_new3(1, val)); + rb_eval_cmd(cmd, rb_ary_new3(1, val)); } VALUE -f_trace_var(argc, argv) +rb_f_trace_var(argc, argv) int argc; VALUE *argv; { @@ -495,14 +489,15 @@ f_trace_var(argc, argv) struct trace_var *trace; if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) { - cmd = f_lambda(); + cmd = rb_f_lambda(); } if (NIL_P(cmd)) { - return f_untrace_var(argc, argv); + return rb_f_untrace_var(argc, argv); } id = rb_to_id(var); - if (!st_lookup(global_tbl, id, &entry)) { - NameError("undefined global variable %s", rb_id2name(id)); + if (!st_lookup(rb_global_tbl, id, &entry)) { + rb_raise(rb_eNameError, "undefined global variable %s", + rb_id2name(id)); } trace = ALLOC(struct trace_var); trace->next = entry->trace; @@ -536,7 +531,7 @@ remove_trace(entry) } VALUE -f_untrace_var(argc, argv) +rb_f_untrace_var(argc, argv) int argc; VALUE *argv; { @@ -547,16 +542,18 @@ f_untrace_var(argc, argv) rb_scan_args(argc, argv, "11", &var, &cmd); id = rb_to_id(var); - if (!st_lookup(global_tbl, id, &entry)) { - NameError("undefined global variable %s", rb_id2name(id)); + if (!st_lookup(rb_global_tbl, id, &entry)) { + rb_raise(rb_eNameError, "undefined global variable %s", + rb_id2name(id)); } + + trace = entry->trace; if (NIL_P(cmd)) { - VALUE ary = ary_new(); + VALUE ary = rb_ary_new(); - trace = entry->trace; while (trace) { struct trace_var *next = trace->next; - ary_push(ary, (VALUE)trace->data); + rb_ary_push(ary, (VALUE)trace->data); trace->removed = 1; trace = next; } @@ -570,7 +567,7 @@ f_untrace_var(argc, argv) if (trace->data == (void*)cmd) { trace->removed = 1; if (!entry->block_trace) remove_trace(entry); - return ary_new3(1, cmd); + return rb_ary_new3(1, cmd); } trace = trace->next; } @@ -589,7 +586,7 @@ struct trace_data { VALUE val; }; -static void +static VALUE trace_ev(data) struct trace_data *data; { @@ -599,14 +596,16 @@ trace_ev(data) (*trace->func)(trace->data, data->val); trace = trace->next; } + return Qnil; /* not reached */ } -static void +static VALUE trace_en(entry) struct global_entry *entry; { entry->block_trace = 0; remove_trace(entry); + return Qnil; /* not reached */ } VALUE @@ -616,17 +615,15 @@ rb_gvar_set(entry, val) { struct trace_data trace; - if (rb_safe_level() >= 4) { - extern VALUE eSecurityError; - Raise(eSecurityError, "cannot change global variable value"); - } + if (rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't change global variable value"); (*entry->setter)(val, entry->id, entry->data, entry); if (entry->trace && !entry->block_trace) { entry->block_trace = 1; trace.trace = entry->trace; trace.val = val; - rb_ensure(trace_ev, &trace, trace_en, entry); + rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)entry); } return val; } @@ -646,8 +643,8 @@ VALUE rb_gvar_defined(entry) struct global_entry *entry; { - if (entry->getter == undef_getter) return FALSE; - return TRUE; + if (entry->getter == undef_getter) return Qfalse; + return Qtrue; } static int @@ -656,21 +653,23 @@ gvar_i(key, entry, ary) struct global_entry *entry; VALUE ary; { - ary_push(ary, str_new2(rb_id2name(entry->id))); + rb_ary_push(ary, rb_str_new2(rb_id2name(key))); return ST_CONTINUE; } VALUE -f_global_variables() +rb_f_global_variables() { - VALUE ary = ary_new(); - char buf[3]; - char *s = "^&`'+123456789"; + VALUE ary = rb_ary_new(); + char buf[4]; + char *s = "&`'+123456789"; - st_foreach(global_tbl, gvar_i, ary); - while (*s) { - sprintf(buf, "$%c", *s++); - ary_push(ary, str_new2(buf)); + st_foreach(rb_global_tbl, gvar_i, ary); + if (!NIL_P(rb_backref_get())) { + while (*s) { + sprintf(buf, "$%c", *s++); + rb_ary_push(ary, rb_str_new2(buf)); + } } return ary; } @@ -691,6 +690,133 @@ rb_alias_variable(name1, name2) entry1->marker = entry2->marker; } +static int special_generic_ivar = 0; +static st_table *generic_iv_tbl; + +static VALUE +generic_ivar_get(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qnil; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil; + if (st_lookup(tbl, id, &val)) { + return val; + } + return Qnil; +} + +static void +generic_ivar_set(obj, id, val) + VALUE obj; + ID id; + VALUE val; +{ + st_table *tbl; + + if (rb_special_const_p(obj)) { + special_generic_ivar = 1; + } + if (!generic_iv_tbl) { + generic_iv_tbl = st_init_numtable(); + } + + if (!st_lookup(generic_iv_tbl, obj, &tbl)) { + FL_SET(obj, FL_EXIVAR); + tbl = st_init_numtable(); + st_add_direct(generic_iv_tbl, obj, tbl); + st_add_direct(tbl, id, val); + return; + } + st_insert(tbl, id, val); +} + +static VALUE +generic_ivar_defined(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qfalse; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qfalse; + if (st_lookup(tbl, id, &val)) { + return Qtrue; + } + return Qfalse; +} + +static VALUE +generic_ivar_remove(obj, id) + VALUE obj; + ID id; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return Qnil; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return Qnil; + st_delete(tbl, &id, &val); + if (tbl->num_entries == 0) { + st_delete(generic_iv_tbl, &obj, &tbl); + st_free_table(tbl); + } + return val; +} + +static int +givar_mark_i(key, value) + ID key; + VALUE value; +{ + rb_gc_mark(value); + return ST_CONTINUE; +} + +void +rb_mark_generic_ivar(obj) + VALUE obj; +{ + st_table *tbl; + + if (st_lookup(generic_iv_tbl, obj, &tbl)) { + rb_mark_tbl(tbl); + } +} + +static int +givar_i(obj, tbl) + VALUE obj; + st_table *tbl; +{ + if (rb_special_const_p(obj)) { + st_foreach(tbl, givar_mark_i, 0); + } + return ST_CONTINUE; +} + +void +rb_mark_generic_ivar_tbl() +{ + if (special_generic_ivar == 0) return; + if (!generic_iv_tbl) return; + st_foreach(generic_iv_tbl, givar_i, 0); +} + +void +rb_free_generic_ivar(obj) + VALUE obj; +{ + st_table *tbl; + + if (st_delete(generic_iv_tbl, &obj, &tbl)) + st_free_table(tbl); +} + VALUE rb_ivar_get(obj, id) VALUE obj; @@ -702,15 +828,18 @@ rb_ivar_get(obj, id) case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val)) return val; - return Qnil; + break; default: - TypeError("class %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_get(obj, id); break; } - Warning("instance var %s not initialized", rb_id2name(id)); + if (rb_verbose) { + rb_warning("instance var %s not initialized", rb_id2name(id)); + } return Qnil; } @@ -720,20 +849,18 @@ rb_ivar_set(obj, id, val) ID id; VALUE val; { - if (rb_safe_level() >= 5) { - extern VALUE eSecurityError; - Raise(eSecurityError, "cannot change object status"); - } switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: case T_MODULE: - if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = new_idhash(); + case T_FILE: + if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT)) + rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); + if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable(); st_insert(ROBJECT(obj)->iv_tbl, id, val); break; default: - TypeError("class %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + generic_ivar_set(obj, id, val); break; } return val; @@ -744,119 +871,136 @@ rb_ivar_defined(obj, id) VALUE obj; ID id; { - if (!rb_is_instance_id(id)) return FALSE; + if (!rb_is_instance_id(id)) return Qfalse; switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0)) - return TRUE; + return Qtrue; + break; + default: + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_defined(obj, id); break; } - return FALSE; + return Qfalse; } static int -ivar_i(key, value, hash) +ivar_i(key, entry, ary) ID key; - VALUE value; - VALUE hash; + struct global_entry *entry; + VALUE ary; { if (rb_is_instance_id(key)) { - hash_aset(hash, str_new2(rb_id2name(key)), value); + rb_ary_push(ary, rb_str_new2(rb_id2name(key))); } return ST_CONTINUE; } VALUE -obj_instance_variables(obj) +rb_obj_instance_variables(obj) VALUE obj; { - VALUE hash = hash_new(); + VALUE ary; switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: + ary = rb_ary_new(); if (ROBJECT(obj)->iv_tbl) { - st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, hash); + st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary); } - break; + return ary; default: - break; + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { + st_table *tbl; + + if (st_lookup(generic_iv_tbl, obj, &tbl)) { + ary = rb_ary_new(); + st_foreach(tbl, ivar_i, ary); + return ary; + } + } } - return hash; + return Qnil; } VALUE -obj_remove_instance_variable(obj, name) +rb_obj_remove_instance_variable(obj, name) VALUE obj, name; { - VALUE val; + VALUE val = Qnil; ID id = rb_to_id(name); - if (rb_ivar_defined(obj, id)) { - NameError("`%s' is not an instance variable", rb_id2name(id)); + if (!rb_is_instance_id(id)) { + rb_raise(rb_eNameError, "`%s' is not an instance variable", + rb_id2name(id)); } switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: case T_MODULE: + case T_FILE: if (ROBJECT(obj)->iv_tbl) { st_delete(ROBJECT(obj)->iv_tbl, &id, &val); } break; default: - TypeError("object %s can not have instance variables", - rb_class2name(CLASS_OF(obj))); + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_remove(obj, id); break; } - return obj; + return val; } VALUE -rb_const_get_at(cls, id) - VALUE cls; +rb_const_get_at(klass, id) + VALUE klass; ID id; { VALUE value; - if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, &value)) { + if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { return value; } - if (cls == cObject) { - return rb_const_get(cls, id); + if (klass == rb_cObject) { + return rb_const_get(klass, id); } - NameError("Uninitialized constant %s::%s", - RSTRING(rb_class_path(cls))->ptr, - rb_id2name(id)); - /* not reached */ + rb_raise(rb_eNameError, "Uninitialized constant %s::%s", + RSTRING(rb_class_path(klass))->ptr, + rb_id2name(id)); + return Qnil; /* not reached */ } VALUE -rb_const_get(cls, id) - VALUE cls; +rb_const_get(klass, id) + VALUE klass; ID id; { VALUE value; VALUE tmp; - tmp = cls; + tmp = klass; while (tmp) { if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { return value; } tmp = RCLASS(tmp)->super; } - if (BUILTIN_TYPE(cls) == T_MODULE) { - return rb_const_get(cObject, id); + if (BUILTIN_TYPE(klass) == T_MODULE) { + return rb_const_get(rb_cObject, id); } /* pre-defined class */ - if (st_lookup(class_tbl, id, &value)) return value; + if (st_lookup(rb_class_tbl, id, &value)) return value; /* autoload */ if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { @@ -864,21 +1008,21 @@ rb_const_get(cls, id) VALUE module; st_delete(autoload_tbl, &id, &modname); - module = str_new2(modname); + module = rb_str_new2(modname); free(modname); - f_require(0, module); - return rb_const_get(cls, id); + rb_f_require(Qnil, module); + return rb_const_get(klass, id); } /* Uninitialized constant */ - if (cls && cls != cObject) - NameError("Uninitialized constant %s::%s", - RSTRING(rb_class_path(cls))->ptr, - rb_id2name(id)); + if (klass && klass != rb_cObject) + rb_raise(rb_eNameError, "Uninitialized constant %s::%s", + RSTRING(rb_class_path(klass))->ptr, + rb_id2name(id)); else { - NameError("Uninitialized constant %s",rb_id2name(id)); + rb_raise(rb_eNameError, "Uninitialized constant %s",rb_id2name(id)); } - /* not reached */ + return Qnil; /* not reached */ } static int @@ -888,36 +1032,59 @@ const_i(key, value, ary) VALUE ary; { if (rb_is_const_id(key)) { - VALUE kval = str_new2(rb_id2name(key)); - if (!ary_includes(ary, kval)) { - ary_push(ary, kval); + VALUE kval = rb_str_new2(rb_id2name(key)); + if (!rb_ary_includes(ary, kval)) { + rb_ary_push(ary, kval); } } return ST_CONTINUE; } +VALUE +rb_mod_remove_const(mod, name) + VALUE mod, name; +{ + ID id = rb_to_id(name); + VALUE val; + + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "`%s' is not constant", rb_id2name(id)); + } + + if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) { + return val; + } + if (rb_const_defined_at(mod, id)) { + rb_raise(rb_eNameError, "cannot remove %s::%s", + rb_class2name(mod), rb_id2name(id)); + } + rb_raise(rb_eNameError, "constant %s::%s not defined", + rb_class2name(mod), rb_id2name(id)); + return Qnil; /* not reached */ +} + static int autoload_i(key, name, ary) ID key; char *name; VALUE ary; { - VALUE kval = str_new2(rb_id2name(key)); - if (!ary_includes(ary, kval)) { - ary_push(ary, kval); + VALUE kval = rb_str_new2(rb_id2name(key)); + if (!rb_ary_includes(ary, kval)) { + rb_ary_push(ary, kval); } return ST_CONTINUE; } VALUE -mod_const_at(mod, ary) +rb_mod_const_at(mod, ary) VALUE mod, ary; { if (RCLASS(mod)->iv_tbl) { st_foreach(RCLASS(mod)->iv_tbl, const_i, ary); } - if ((VALUE)mod == cObject) { - st_foreach(class_tbl, const_i, ary); + if ((VALUE)mod == rb_cObject) { + st_foreach(rb_class_tbl, const_i, ary); if (autoload_tbl) { st_foreach(autoload_tbl, autoload_i, ary); } @@ -926,38 +1093,38 @@ mod_const_at(mod, ary) } VALUE -mod_constants(mod) +rb_mod_constants(mod) VALUE mod; { - return mod_const_at(mod, ary_new()); + return rb_mod_const_at(mod, rb_ary_new()); } VALUE -mod_const_of(mod, ary) +rb_mod_const_of(mod, ary) VALUE mod; VALUE ary; { - mod_const_at(mod, ary); + rb_mod_const_at(mod, ary); for (;;) { mod = RCLASS(mod)->super; if (!mod) break; - mod_const_at(mod, ary); + rb_mod_const_at(mod, ary); } return ary; } int -rb_const_defined_at(cls, id) - VALUE cls; +rb_const_defined_at(klass, id) + VALUE klass; ID id; { - if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { - return TRUE; + if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { + return Qtrue; } - if (cls == cObject) { - return rb_const_defined(cls, id); + if (klass == rb_cObject) { + return rb_const_defined(klass, id); } - return FALSE; + return Qfalse; } int @@ -965,53 +1132,65 @@ rb_autoload_defined(id) ID id; { if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) - return TRUE; - return FALSE; + return Qtrue; + return Qfalse; } int -rb_const_defined(cls, id) - VALUE cls; +rb_const_defined(klass, id) + VALUE klass; ID id; { - while (cls) { - if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { - return TRUE; + VALUE tmp = klass; + + while (tmp) { + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { + return Qtrue; } - cls = RCLASS(cls)->super; + tmp = RCLASS(tmp)->super; + } + if (BUILTIN_TYPE(klass) == T_MODULE) { + return rb_const_defined(rb_cObject, id); } - if (st_lookup(class_tbl, id, 0)) - return TRUE; + if (st_lookup(rb_class_tbl, id, 0)) + return Qtrue; return rb_autoload_defined(id); } void -rb_const_set(cls, id, val) - VALUE cls; +rb_const_set(klass, id, val) + VALUE klass; ID id; VALUE val; { - if (!RCLASS(cls)->iv_tbl) { - RCLASS(cls)->iv_tbl = new_idhash(); + if (rb_safe_level() >= 4 && !FL_TEST(klass, FL_TAINT)) + rb_raise(rb_eSecurityError, "Insecure: can't set constant"); + if (!RCLASS(klass)->iv_tbl) { + RCLASS(klass)->iv_tbl = st_init_numtable(); } - else if (st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { - NameError("already initialized constant %s", rb_id2name(id)); + else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { + rb_raise(rb_eNameError, "already initialized constant %s", + rb_id2name(id)); } - st_insert(RCLASS(cls)->iv_tbl, id, val); + st_add_direct(RCLASS(klass)->iv_tbl, id, val); } void -rb_define_const(cls, name, val) - VALUE cls; +rb_define_const(klass, name, val) + VALUE klass; char *name; VALUE val; { ID id = rb_intern(name); + + if (klass == rb_cObject) { + rb_secure(4); + } if (!rb_is_const_id(id)) { - NameError("wrong constant name %s", name); + rb_raise(rb_eNameError, "wrong constant name %s", name); } - rb_const_set(cls, id, val); + rb_const_set(klass, id, val); } void @@ -1019,7 +1198,7 @@ rb_define_global_const(name, val) char *name; VALUE val; { - rb_define_const(cObject, name, val); + rb_define_const(rb_cObject, name, val); } VALUE |