2000-05-01 13:42:38 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
variable.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
$Date$
|
|
|
|
created at: Tue Apr 19 23:55:15 JST 1994
|
|
|
|
|
2003-01-16 10:34:03 +03:00
|
|
|
Copyright (C) 1993-2003 Yukihiro Matsumoto
|
2000-05-01 13:42:38 +04:00
|
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
2000-05-09 08:53:16 +04:00
|
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
2000-05-01 13:42:38 +04:00
|
|
|
|
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
#include "ruby.h"
|
|
|
|
#include "env.h"
|
|
|
|
#include "node.h"
|
|
|
|
#include "st.h"
|
2001-05-30 13:12:34 +04:00
|
|
|
#include "util.h"
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
static st_table *rb_global_tbl;
|
|
|
|
st_table *rb_class_tbl;
|
2003-08-02 09:02:43 +04:00
|
|
|
static ID autoload, classpath, tmp_classpath;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
Init_var_tables()
|
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_global_tbl = st_init_numtable();
|
|
|
|
rb_class_tbl = st_init_numtable();
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
autoload = rb_intern("__autoload__");
|
2003-08-02 09:02:43 +04:00
|
|
|
classpath = rb_intern("__classpath__");
|
|
|
|
tmp_classpath = rb_intern("__tmp_classpath__");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
struct fc_result {
|
|
|
|
ID name;
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE path;
|
|
|
|
VALUE track;
|
|
|
|
struct fc_result *prev;
|
|
|
|
};
|
|
|
|
|
2001-06-06 10:42:23 +04:00
|
|
|
static VALUE
|
|
|
|
fc_path(fc, name)
|
|
|
|
struct fc_result *fc;
|
|
|
|
ID name;
|
|
|
|
{
|
|
|
|
VALUE path, tmp;
|
|
|
|
|
|
|
|
path = rb_str_new2(rb_id2name(name));
|
|
|
|
while (fc) {
|
|
|
|
if (fc->track == rb_cObject) break;
|
|
|
|
if (ROBJECT(fc->track)->iv_tbl &&
|
2003-08-02 09:02:43 +04:00
|
|
|
st_lookup(ROBJECT(fc->track)->iv_tbl, classpath, &tmp)) {
|
2001-06-06 10:42:23 +04:00
|
|
|
tmp = rb_str_dup(tmp);
|
|
|
|
rb_str_cat2(tmp, "::");
|
|
|
|
rb_str_append(tmp, path);
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
tmp = rb_str_new2(rb_id2name(fc->name));
|
|
|
|
rb_str_cat2(tmp, "::");
|
|
|
|
rb_str_append(tmp, path);
|
|
|
|
path = tmp;
|
|
|
|
fc = fc->prev;
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static int
|
|
|
|
fc_i(key, value, res)
|
|
|
|
ID key;
|
|
|
|
VALUE value;
|
|
|
|
struct fc_result *res;
|
|
|
|
{
|
1999-12-14 09:50:43 +03:00
|
|
|
if (!rb_is_const_id(key)) return ST_CONTINUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
if (value == res->klass) {
|
2001-06-06 10:42:23 +04:00
|
|
|
res->path = fc_path(res, key);
|
1998-01-16 15:13:05 +03:00
|
|
|
return ST_STOP;
|
|
|
|
}
|
2001-06-06 10:42:23 +04:00
|
|
|
switch (TYPE(value)) {
|
|
|
|
case T_MODULE:
|
|
|
|
case T_CLASS:
|
1998-01-16 15:13:05 +03:00
|
|
|
if (!RCLASS(value)->iv_tbl) return ST_CONTINUE;
|
2001-06-06 10:42:23 +04:00
|
|
|
else {
|
|
|
|
struct fc_result arg;
|
|
|
|
struct fc_result *list;
|
|
|
|
|
|
|
|
list = res;
|
|
|
|
while (list) {
|
|
|
|
if (list->track == value) return ST_CONTINUE;
|
|
|
|
list = list->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg.name = key;
|
|
|
|
arg.path = 0;
|
|
|
|
arg.klass = res->klass;
|
|
|
|
arg.track = value;
|
|
|
|
arg.prev = res;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_foreach(RCLASS(value)->iv_tbl, fc_i, (st_data_t)&arg);
|
2001-06-06 10:42:23 +04:00
|
|
|
if (arg.path) {
|
|
|
|
res->path = arg.path;
|
|
|
|
return ST_STOP;
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-06-06 10:42:23 +04:00
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-06-06 10:42:23 +04:00
|
|
|
default:
|
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
find_class_path(klass)
|
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
struct fc_result arg;
|
|
|
|
|
|
|
|
arg.name = 0;
|
|
|
|
arg.path = 0;
|
1999-01-20 07:59:39 +03:00
|
|
|
arg.klass = klass;
|
|
|
|
arg.track = rb_cObject;
|
1998-01-16 15:13:05 +03:00
|
|
|
arg.prev = 0;
|
1999-01-20 07:59:39 +03:00
|
|
|
if (RCLASS(rb_cObject)->iv_tbl) {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, (st_data_t)&arg);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-06-06 10:42:23 +04:00
|
|
|
if (arg.path == 0) {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_foreach(rb_class_tbl, fc_i, (st_data_t)&arg);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-06-06 10:42:23 +04:00
|
|
|
if (arg.path) {
|
2001-12-18 11:47:06 +03:00
|
|
|
if (!ROBJECT(klass)->iv_tbl) {
|
|
|
|
ROBJECT(klass)->iv_tbl = st_init_numtable();
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
2003-08-02 09:02:43 +04:00
|
|
|
st_insert(ROBJECT(klass)->iv_tbl, classpath, arg.path);
|
|
|
|
st_delete(RCLASS(klass)->iv_tbl, &tmp_classpath, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
return arg.path;
|
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
classname(klass)
|
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-08-13 09:45:20 +04:00
|
|
|
VALUE path = Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (!klass) klass = rb_cObject;
|
2003-04-10 12:37:12 +04:00
|
|
|
if (ROBJECT(klass)->iv_tbl) {
|
|
|
|
if (!st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
|
|
|
|
ID classid = rb_intern("__classid__");
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-04-10 12:37:12 +04:00
|
|
|
if (!st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
|
2003-08-02 09:02:43 +04:00
|
|
|
return find_class_path(klass);
|
2003-04-10 12:37:12 +04:00
|
|
|
}
|
2000-04-10 09:48:43 +04:00
|
|
|
path = rb_str_new2(rb_id2name(SYM2ID(path)));
|
1999-01-20 07:59:39 +03:00
|
|
|
st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
|
2003-07-25 09:36:55 +04:00
|
|
|
st_delete(RCLASS(klass)->iv_tbl, (st_data_t*)&classid, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2003-04-10 12:37:12 +04:00
|
|
|
if (TYPE(path) != T_STRING) {
|
|
|
|
rb_bug("class path is not set properly");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
2003-08-02 09:02:43 +04:00
|
|
|
return find_class_path(klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.name => string
|
|
|
|
*
|
|
|
|
* Returns the name of the module <i>mod</i>.
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_mod_name(mod)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE mod;
|
|
|
|
{
|
2002-02-04 11:09:14 +03:00
|
|
|
VALUE path = classname(mod);
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2003-04-10 12:37:12 +04:00
|
|
|
if (!NIL_P(path)) return rb_str_dup(path);
|
|
|
|
return rb_str_new(0,0);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_class_path(klass)
|
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2002-02-04 11:09:14 +03:00
|
|
|
VALUE path = classname(klass);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2003-04-10 12:37:12 +04:00
|
|
|
if (!NIL_P(path)) return path;
|
2003-08-02 09:02:43 +04:00
|
|
|
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl,
|
|
|
|
tmp_classpath, &path)) {
|
|
|
|
return path;
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
else {
|
|
|
|
char *s = "Class";
|
|
|
|
|
2001-10-03 11:19:19 +04:00
|
|
|
if (TYPE(klass) == T_MODULE) {
|
2002-08-28 18:59:01 +04:00
|
|
|
if (rb_obj_class(klass) == rb_cModule) {
|
2001-10-03 11:19:19 +04:00
|
|
|
s = "Module";
|
2002-08-28 18:59:01 +04:00
|
|
|
}
|
|
|
|
else {
|
2001-10-03 11:19:19 +04:00
|
|
|
s = rb_class2name(RBASIC(klass)->klass);
|
2002-08-28 18:59:01 +04:00
|
|
|
}
|
2001-10-03 11:19:19 +04:00
|
|
|
}
|
2003-04-10 12:37:12 +04:00
|
|
|
path = rb_str_new(0, 2 + strlen(s) + 3 + 2 * SIZEOF_LONG + 1);
|
|
|
|
sprintf(RSTRING(path)->ptr, "#<%s:0x%lx>", s, klass);
|
|
|
|
RSTRING(path)->len = strlen(RSTRING(path)->ptr);
|
2003-08-02 09:02:43 +04:00
|
|
|
rb_ivar_set(klass, tmp_classpath, path);
|
2002-08-28 18:59:01 +04:00
|
|
|
|
2003-04-10 12:37:12 +04:00
|
|
|
return path;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_set_class_path(klass, under, name)
|
|
|
|
VALUE klass, under;
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
VALUE str;
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (under == rb_cObject) {
|
|
|
|
str = rb_str_new2(name);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
1999-01-20 07:59:39 +03:00
|
|
|
str = rb_str_dup(rb_class_path(under));
|
2000-04-10 09:48:43 +04:00
|
|
|
rb_str_cat2(str, "::");
|
|
|
|
rb_str_cat2(str, name);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2003-08-02 09:02:43 +04:00
|
|
|
rb_ivar_set(klass, classpath, str);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_path2class(path)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *path;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2002-09-05 13:42:56 +04:00
|
|
|
const char *pbeg, *p;
|
|
|
|
ID id;
|
|
|
|
VALUE c = rb_cObject;
|
1999-11-29 09:33:02 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
if (path[0] == '#') {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2002-09-05 13:42:56 +04:00
|
|
|
pbeg = p = path;
|
|
|
|
while (*p) {
|
|
|
|
VALUE str;
|
|
|
|
|
|
|
|
while (*p && *p != ':') p++;
|
|
|
|
str = rb_str_new(pbeg, p-pbeg);
|
|
|
|
id = rb_intern(RSTRING(str)->ptr);
|
|
|
|
if (p[0] == ':') {
|
|
|
|
if (p[1] != ':') goto undefined_class;
|
|
|
|
p += 2;
|
|
|
|
pbeg = p;
|
|
|
|
}
|
|
|
|
if (!rb_const_defined(c, id)) {
|
|
|
|
undefined_class:
|
2003-08-02 09:02:43 +04:00
|
|
|
rb_raise(rb_eArgError, "undefined class/module %.*s", p-path, path);
|
2002-09-05 13:42:56 +04:00
|
|
|
}
|
|
|
|
c = rb_const_get_at(c, id);
|
|
|
|
switch (TYPE(c)) {
|
|
|
|
case T_MODULE:
|
|
|
|
case T_CLASS:
|
|
|
|
break;
|
|
|
|
default:
|
2002-10-23 12:20:35 +04:00
|
|
|
rb_raise(rb_eTypeError, "%s does not refer class/module", path);
|
2002-09-05 13:42:56 +04:00
|
|
|
}
|
1999-11-29 09:33:02 +03:00
|
|
|
}
|
2002-09-05 13:42:56 +04:00
|
|
|
|
1999-11-29 09:33:02 +03:00
|
|
|
return c;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_name_class(klass, id)
|
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
{
|
2000-04-10 09:48:43 +04:00
|
|
|
rb_iv_set(klass, "__classid__", ID2SYM(id));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-19 12:19:31 +03:00
|
|
|
VALUE
|
|
|
|
rb_class_name(klass)
|
|
|
|
VALUE klass;
|
|
|
|
{
|
|
|
|
return rb_class_path(rb_class_real(klass));
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
char *
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_class2name(klass)
|
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2004-01-19 12:19:31 +03:00
|
|
|
return RSTRING(rb_class_name(klass))->ptr;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-01-31 07:00:17 +03:00
|
|
|
char *
|
|
|
|
rb_obj_classname(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
2003-01-31 07:16:51 +03:00
|
|
|
return rb_class2name(CLASS_OF(obj));
|
2003-01-31 07:00:17 +03:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
struct trace_var {
|
1998-01-16 15:19:22 +03:00
|
|
|
int removed;
|
1998-01-16 15:13:05 +03:00
|
|
|
void (*func)();
|
2001-03-19 06:20:24 +03:00
|
|
|
VALUE data;
|
1998-01-16 15:13:05 +03:00
|
|
|
struct trace_var *next;
|
|
|
|
};
|
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable {
|
|
|
|
int counter;
|
1998-01-16 15:13:05 +03:00
|
|
|
void *data;
|
|
|
|
VALUE (*getter)();
|
|
|
|
void (*setter)();
|
|
|
|
void (*marker)();
|
|
|
|
int block_trace;
|
|
|
|
struct trace_var *trace;
|
|
|
|
};
|
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_entry {
|
|
|
|
struct global_variable *var;
|
|
|
|
ID id;
|
|
|
|
};
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static VALUE undef_getter();
|
|
|
|
static void undef_setter();
|
|
|
|
static void undef_marker();
|
|
|
|
|
|
|
|
static VALUE val_getter();
|
|
|
|
static void val_setter();
|
|
|
|
static void val_marker();
|
|
|
|
|
|
|
|
static VALUE var_getter();
|
|
|
|
static void var_setter();
|
|
|
|
static void var_marker();
|
|
|
|
|
|
|
|
struct global_entry*
|
|
|
|
rb_global_entry(id)
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
struct global_entry *entry;
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(rb_global_tbl, id, (st_data_t *)&entry)) {
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var;
|
1998-01-16 15:13:05 +03:00
|
|
|
entry = ALLOC(struct global_entry);
|
2001-10-22 20:20:14 +04:00
|
|
|
var = ALLOC(struct global_variable);
|
1998-01-16 15:13:05 +03:00
|
|
|
entry->id = id;
|
2001-10-22 20:20:14 +04:00
|
|
|
entry->var = var;
|
|
|
|
var->counter = 1;
|
|
|
|
var->data = 0;
|
|
|
|
var->getter = undef_getter;
|
|
|
|
var->setter = undef_setter;
|
|
|
|
var->marker = undef_marker;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
var->block_trace = 0;
|
|
|
|
var->trace = 0;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_add_direct(rb_global_tbl, id, (st_data_t)entry);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
undef_getter(id)
|
|
|
|
ID id;
|
|
|
|
{
|
2002-04-11 14:03:01 +04:00
|
|
|
rb_warning("global variable `%s' not initialized", rb_id2name(id));
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-22 20:20:14 +04:00
|
|
|
undef_setter(val, id, data, var)
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
ID id;
|
|
|
|
void *data;
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
var->getter = val_getter;
|
|
|
|
var->setter = val_setter;
|
|
|
|
var->marker = val_marker;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
var->data = (void*)val;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
undef_marker()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
val_getter(id, val)
|
|
|
|
ID id;
|
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-10-22 20:20:14 +04:00
|
|
|
val_setter(val, id, data, var)
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
ID id;
|
|
|
|
void *data;
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
var->data = (void*)val;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
val_marker(data)
|
2001-03-19 06:20:24 +03:00
|
|
|
VALUE data;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
if (data) rb_gc_mark_maybe(data);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
var_getter(id, var)
|
|
|
|
ID id;
|
|
|
|
VALUE *var;
|
|
|
|
{
|
2001-11-13 11:19:52 +03:00
|
|
|
if (!var) return Qnil;
|
1998-01-16 15:13:05 +03:00
|
|
|
return *var;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
var_setter(val, id, var)
|
|
|
|
VALUE val;
|
|
|
|
ID id;
|
|
|
|
VALUE *var;
|
|
|
|
{
|
|
|
|
*var = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
var_marker(var)
|
2001-03-19 06:20:24 +03:00
|
|
|
VALUE *var;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
if (var) rb_gc_mark_maybe(*var);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
readonly_setter(val, id, var)
|
|
|
|
VALUE val;
|
|
|
|
ID id;
|
|
|
|
void *var;
|
|
|
|
{
|
2003-05-15 08:20:31 +04:00
|
|
|
rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mark_global_entry(key, entry)
|
|
|
|
ID key;
|
|
|
|
struct global_entry *entry;
|
|
|
|
{
|
|
|
|
struct trace_var *trace;
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var = entry->var;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
(*var->marker)(var->data);
|
|
|
|
trace = var->trace;
|
1998-01-16 15:13:05 +03:00
|
|
|
while (trace) {
|
1999-01-20 07:59:39 +03:00
|
|
|
if (trace->data) rb_gc_mark_maybe(trace->data);
|
1998-01-16 15:13:05 +03:00
|
|
|
trace = trace->next;
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_gc_mark_global_tbl()
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
st_foreach(rb_global_tbl, mark_global_entry, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static ID
|
|
|
|
global_id(name)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
ID id;
|
|
|
|
|
|
|
|
if (name[0] == '$') id = rb_intern(name);
|
|
|
|
else {
|
|
|
|
char *buf = ALLOCA_N(char, strlen(name)+2);
|
|
|
|
buf[0] = '$';
|
|
|
|
strcpy(buf+1, name);
|
|
|
|
id = rb_intern(buf);
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_hooked_variable(name, var, getter, setter)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE *var;
|
|
|
|
VALUE (*getter)();
|
|
|
|
void (*setter)();
|
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *gvar;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id = global_id(name);
|
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
gvar = rb_global_entry(id)->var;
|
|
|
|
gvar->data = (void*)var;
|
|
|
|
gvar->getter = getter?getter:var_getter;
|
|
|
|
gvar->setter = setter?setter:var_setter;
|
|
|
|
gvar->marker = var_marker;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_variable(name, var)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE *var;
|
|
|
|
{
|
|
|
|
rb_define_hooked_variable(name, var, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_readonly_variable(name, var)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE *var;
|
|
|
|
{
|
|
|
|
rb_define_hooked_variable(name, var, 0, readonly_setter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_virtual_variable(name, getter, setter)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE (*getter)();
|
|
|
|
void (*setter)();
|
|
|
|
{
|
|
|
|
if (!getter) getter = val_getter;
|
|
|
|
if (!setter) setter = readonly_setter;
|
|
|
|
rb_define_hooked_variable(name, 0, getter, setter);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rb_trace_eval(cmd, val)
|
|
|
|
VALUE cmd, val;
|
|
|
|
{
|
2001-11-13 11:19:52 +03:00
|
|
|
rb_eval_cmd(cmd, rb_ary_new3(1, val), 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-29 06:56:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* trace_var(symbol, cmd ) => nil
|
|
|
|
* trace_var(symbol) {|val| block } => nil
|
|
|
|
*
|
|
|
|
* Controls tracing of assignments to global variables. The parameter
|
|
|
|
* +symbol_ identifies the variable (as either a string name or a
|
|
|
|
* symbol identifier). _cmd_ (which may be a string or a
|
|
|
|
* +Proc+ object) or block is executed whenever the variable
|
|
|
|
* is assigned. The block or +Proc+ object receives the
|
|
|
|
* variable's new value as a parameter. Also see
|
|
|
|
* <code>Kernel::untrace_var</code>.
|
|
|
|
*
|
|
|
|
* trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
|
|
|
|
* $_ = "hello"
|
|
|
|
* $_ = ' there'
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* $_ is now 'hello'
|
|
|
|
* $_ is now ' there'
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_f_trace_var(argc, argv)
|
1998-01-16 15:13:05 +03:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
VALUE var, cmd;
|
|
|
|
struct global_entry *entry;
|
|
|
|
struct trace_var *trace;
|
|
|
|
|
2001-11-13 11:19:52 +03:00
|
|
|
rb_secure(4);
|
1998-01-16 15:13:05 +03:00
|
|
|
if (rb_scan_args(argc, argv, "11", &var, &cmd) == 1) {
|
2003-06-16 11:14:50 +04:00
|
|
|
cmd = rb_block_proc();
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
if (NIL_P(cmd)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
return rb_f_untrace_var(argc, argv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-11-13 11:19:52 +03:00
|
|
|
entry = rb_global_entry(rb_to_id(var));
|
|
|
|
if (OBJ_TAINTED(cmd)) {
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: tainted variable trace");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
trace = ALLOC(struct trace_var);
|
2001-10-22 20:20:14 +04:00
|
|
|
trace->next = entry->var->trace;
|
1998-01-16 15:13:05 +03:00
|
|
|
trace->func = rb_trace_eval;
|
2001-03-19 06:20:24 +03:00
|
|
|
trace->data = cmd;
|
1998-01-16 15:19:22 +03:00
|
|
|
trace->removed = 0;
|
2001-10-22 20:20:14 +04:00
|
|
|
entry->var->trace = trace;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
static void
|
2001-10-22 20:20:14 +04:00
|
|
|
remove_trace(var)
|
|
|
|
struct global_variable *var;
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
struct trace_var *trace = var->trace;
|
1998-01-16 15:19:22 +03:00
|
|
|
struct trace_var t;
|
|
|
|
struct trace_var *next;
|
|
|
|
|
|
|
|
t.next = trace;
|
|
|
|
trace = &t;
|
|
|
|
while (trace->next) {
|
|
|
|
next = trace->next;
|
|
|
|
if (next->removed) {
|
|
|
|
trace->next = next->next;
|
|
|
|
free(next);
|
|
|
|
}
|
2001-10-21 17:22:54 +04:00
|
|
|
else {
|
|
|
|
trace = next;
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2001-10-22 20:20:14 +04:00
|
|
|
var->trace = t.next;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2003-12-29 06:56:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* untrace_var(symbol [, cmd] ) => array or nil
|
|
|
|
*
|
|
|
|
* Removes tracing for the specified command on the given global
|
|
|
|
* variable and returns +nil+. If no command is specified,
|
|
|
|
* removes all tracing for that variable and returns an array
|
|
|
|
* containing the commands actually removed.
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_f_untrace_var(argc, argv)
|
1998-01-16 15:13:05 +03:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
VALUE var, cmd;
|
|
|
|
ID id;
|
|
|
|
struct global_entry *entry;
|
|
|
|
struct trace_var *trace;
|
|
|
|
|
|
|
|
rb_scan_args(argc, argv, "11", &var, &cmd);
|
|
|
|
id = rb_to_id(var);
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(rb_global_tbl, id, (st_data_t *)&entry)) {
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
trace = entry->var->trace;
|
1998-01-16 15:13:05 +03:00
|
|
|
if (NIL_P(cmd)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE ary = rb_ary_new();
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
while (trace) {
|
|
|
|
struct trace_var *next = trace->next;
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_ary_push(ary, (VALUE)trace->data);
|
1998-01-16 15:19:22 +03:00
|
|
|
trace->removed = 1;
|
1998-01-16 15:13:05 +03:00
|
|
|
trace = next;
|
|
|
|
}
|
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
if (!entry->var->block_trace) remove_trace(entry->var);
|
1998-01-16 15:13:05 +03:00
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
else {
|
1998-01-16 15:19:22 +03:00
|
|
|
while (trace) {
|
2001-03-19 06:20:24 +03:00
|
|
|
if (trace->data == cmd) {
|
1998-01-16 15:19:22 +03:00
|
|
|
trace->removed = 1;
|
2001-10-22 20:20:14 +04:00
|
|
|
if (!entry->var->block_trace) remove_trace(entry->var);
|
1999-01-20 07:59:39 +03:00
|
|
|
return rb_ary_new3(1, cmd);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
trace = trace->next;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
}
|
2001-10-17 09:28:02 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
|
|
|
rb_gvar_get(entry)
|
|
|
|
struct global_entry *entry;
|
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var = entry->var;
|
|
|
|
return (*var->getter)(entry->id, var->data, var);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
struct trace_data {
|
|
|
|
struct trace_var *trace;
|
|
|
|
VALUE val;
|
|
|
|
};
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
1998-01-16 15:13:05 +03:00
|
|
|
trace_ev(data)
|
|
|
|
struct trace_data *data;
|
|
|
|
{
|
|
|
|
struct trace_var *trace = data->trace;
|
|
|
|
|
|
|
|
while (trace) {
|
|
|
|
(*trace->func)(trace->data, data->val);
|
|
|
|
trace = trace->next;
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qnil; /* not reached */
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
2001-10-22 20:20:14 +04:00
|
|
|
trace_en(var)
|
|
|
|
struct global_variable *var;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
var->block_trace = 0;
|
|
|
|
remove_trace(var);
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qnil; /* not reached */
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_gvar_set(entry, val)
|
|
|
|
struct global_entry *entry;
|
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
struct trace_data trace;
|
2001-10-22 20:20:14 +04:00
|
|
|
struct global_variable *var = entry->var;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
if (rb_safe_level() >= 4)
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
|
2001-10-22 20:20:14 +04:00
|
|
|
(*var->setter)(val, entry->id, var->data, var);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
if (var->trace && !var->block_trace) {
|
|
|
|
var->block_trace = 1;
|
|
|
|
trace.trace = var->trace;
|
1998-01-16 15:13:05 +03:00
|
|
|
trace.val = val;
|
2001-10-22 20:20:14 +04:00
|
|
|
rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
1999-11-17 10:30:37 +03:00
|
|
|
rb_gv_set(name, val)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
struct global_entry *entry;
|
|
|
|
|
|
|
|
entry = rb_global_entry(global_id(name));
|
|
|
|
return rb_gvar_set(entry, val);
|
|
|
|
}
|
|
|
|
|
1999-11-17 10:30:37 +03:00
|
|
|
VALUE
|
|
|
|
rb_gv_get(name)
|
|
|
|
const char *name;
|
|
|
|
{
|
|
|
|
struct global_entry *entry;
|
|
|
|
|
|
|
|
entry = rb_global_entry(global_id(name));
|
|
|
|
return rb_gvar_get(entry);
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
|
|
|
rb_gvar_defined(entry)
|
|
|
|
struct global_entry *entry;
|
|
|
|
{
|
2001-10-22 20:20:14 +04:00
|
|
|
if (entry->var->getter == undef_getter) return Qfalse;
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
static int
|
|
|
|
gvar_i(key, entry, ary)
|
|
|
|
ID key;
|
|
|
|
struct global_entry *entry;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
1998-01-16 15:19:22 +03:00
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2003-12-29 06:56:22 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* global_variables => array
|
|
|
|
*
|
|
|
|
* Returns an array of the names of global variables.
|
|
|
|
*
|
|
|
|
* global_variables.grep /std/ #=> ["$stderr", "$stdout", "$stdin"]
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_f_global_variables()
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
char buf[4];
|
|
|
|
char *s = "&`'+123456789";
|
1998-01-16 15:19:22 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
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));
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
|
|
|
rb_alias_variable(name1, name2)
|
|
|
|
ID name1;
|
|
|
|
ID name2;
|
|
|
|
{
|
|
|
|
struct global_entry *entry1, *entry2;
|
|
|
|
|
2001-05-22 12:28:11 +04:00
|
|
|
if (rb_safe_level() >= 4)
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2001-10-22 20:20:14 +04:00
|
|
|
entry2 = rb_global_entry(name2);
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(rb_global_tbl, name1, (st_data_t *)&entry1)) {
|
2001-10-22 20:20:14 +04:00
|
|
|
entry1 = ALLOC(struct global_entry);
|
|
|
|
entry1->id = name1;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_add_direct(rb_global_tbl, name1, (st_data_t)entry1);
|
2001-10-22 20:20:14 +04:00
|
|
|
}
|
|
|
|
else if (entry1->var != entry2->var) {
|
|
|
|
struct global_variable *var = entry1->var;
|
|
|
|
if (var->block_trace) {
|
|
|
|
rb_raise(rb_eRuntimeError, "can't alias in tracer");
|
|
|
|
}
|
|
|
|
var->counter--;
|
|
|
|
if (var->counter == 0) {
|
|
|
|
struct trace_var *trace = var->trace;
|
|
|
|
while (trace) {
|
|
|
|
struct trace_var *next = trace->next;
|
|
|
|
free(trace);
|
|
|
|
trace = next;
|
|
|
|
}
|
|
|
|
free(var);
|
|
|
|
}
|
2001-10-17 09:28:02 +04:00
|
|
|
}
|
2001-10-22 20:20:14 +04:00
|
|
|
else {
|
|
|
|
return;
|
2001-10-17 09:28:02 +04:00
|
|
|
}
|
2001-10-22 20:20:14 +04:00
|
|
|
entry2->var->counter++;
|
|
|
|
entry1->var = entry2->var;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static int special_generic_ivar = 0;
|
|
|
|
static st_table *generic_iv_tbl;
|
|
|
|
|
2000-01-05 07:41:21 +03:00
|
|
|
st_table*
|
|
|
|
rb_generic_ivar_table(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
|
2003-10-09 21:45:53 +04:00
|
|
|
if (!FL_TEST(obj, FL_EXIVAR)) return 0;
|
2000-01-05 07:41:21 +03:00
|
|
|
if (!generic_iv_tbl) return 0;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return 0;
|
2000-01-05 07:41:21 +03:00
|
|
|
return tbl;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
static VALUE
|
|
|
|
generic_ivar_get(obj, id)
|
|
|
|
VALUE obj;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
VALUE val;
|
|
|
|
|
2002-12-19 12:20:20 +03:00
|
|
|
if (generic_iv_tbl) {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
|
2002-12-19 12:20:20 +03:00
|
|
|
if (st_lookup(tbl, id, &val)) {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2002-12-19 12:20:20 +03:00
|
|
|
|
|
|
|
rb_warning("instance variable %s not initialized", rb_id2name(id));
|
1999-01-20 07:59:39 +03:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
FL_SET(obj, FL_EXIVAR);
|
|
|
|
tbl = st_init_numtable();
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_add_direct(generic_iv_tbl, obj, (st_data_t)tbl);
|
1999-01-20 07:59:39 +03:00
|
|
|
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;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return Qfalse;
|
1999-01-20 07:59:39 +03:00
|
|
|
if (st_lookup(tbl, id, &val)) {
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2002-04-10 12:45:26 +04:00
|
|
|
static int
|
|
|
|
generic_ivar_remove(obj, id, valp)
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE obj;
|
|
|
|
ID id;
|
2002-04-10 12:45:26 +04:00
|
|
|
VALUE *valp;
|
1999-01-20 07:59:39 +03:00
|
|
|
{
|
|
|
|
st_table *tbl;
|
2002-04-10 12:45:26 +04:00
|
|
|
int status;
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2002-04-10 12:45:26 +04:00
|
|
|
if (!generic_iv_tbl) return 0;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (!st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) return 0;
|
2002-04-10 12:45:26 +04:00
|
|
|
status = st_delete(tbl, &id, valp);
|
1999-01-20 07:59:39 +03:00
|
|
|
if (tbl->num_entries == 0) {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_delete(generic_iv_tbl, &obj, (st_data_t *)&tbl);
|
1999-01-20 07:59:39 +03:00
|
|
|
st_free_table(tbl);
|
|
|
|
}
|
2002-04-10 12:45:26 +04:00
|
|
|
return status;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_mark_generic_ivar(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
if (!generic_iv_tbl) return;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_mark_tbl(tbl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
static int
|
|
|
|
givar_mark_i(key, value)
|
|
|
|
ID key;
|
|
|
|
VALUE value;
|
|
|
|
{
|
|
|
|
rb_gc_mark(value);
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
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 (!generic_iv_tbl) return;
|
1999-08-13 09:45:20 +04:00
|
|
|
if (special_generic_ivar == 0) return;
|
1999-01-20 07:59:39 +03:00
|
|
|
st_foreach(generic_iv_tbl, givar_i, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_free_generic_ivar(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_delete(generic_iv_tbl, &obj, (st_data_t *)&tbl))
|
1999-01-20 07:59:39 +03:00
|
|
|
st_free_table(tbl);
|
|
|
|
}
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
void
|
2001-07-14 19:17:19 +04:00
|
|
|
rb_copy_generic_ivar(clone, obj)
|
1999-08-13 09:45:20 +04:00
|
|
|
VALUE clone, obj;
|
|
|
|
{
|
|
|
|
st_table *tbl;
|
|
|
|
|
|
|
|
if (!generic_iv_tbl) return;
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
|
2002-09-03 09:20:14 +04:00
|
|
|
st_table *old;
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_lookup(generic_iv_tbl, clone, (st_data_t *)&old)) {
|
2002-09-03 09:20:14 +04:00
|
|
|
st_free_table(old);
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_insert(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
|
2002-09-03 09:20:14 +04:00
|
|
|
}
|
|
|
|
else {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_add_direct(generic_iv_tbl, clone, (st_data_t)st_copy(tbl));
|
2002-09-03 09:20:14 +04:00
|
|
|
}
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-02-18 17:30:17 +03:00
|
|
|
static VALUE
|
|
|
|
ivar_get(obj, id, warn)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE obj;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
2003-02-18 17:30:17 +03:00
|
|
|
int warn;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
VALUE val;
|
|
|
|
|
|
|
|
switch (TYPE(obj)) {
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_CLASS:
|
|
|
|
case T_MODULE:
|
1998-01-16 15:19:22 +03:00
|
|
|
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
|
1998-01-16 15:13:05 +03:00
|
|
|
return val;
|
1999-01-20 07:59:39 +03:00
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
default:
|
1999-01-20 07:59:39 +03:00
|
|
|
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
|
|
|
|
return generic_ivar_get(obj, id);
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
}
|
2003-02-18 17:30:17 +03:00
|
|
|
if (warn && ruby_verbose) {
|
|
|
|
rb_warning("instance variable %s not initialized", rb_id2name(id));
|
|
|
|
}
|
2002-04-11 14:03:01 +04:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2003-02-18 17:30:17 +03:00
|
|
|
VALUE
|
|
|
|
rb_ivar_get(obj, id)
|
|
|
|
VALUE obj;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
return ivar_get(obj, id, Qtrue);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_attr_get(obj, id)
|
|
|
|
VALUE obj;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
return ivar_get(obj, id, Qfalse);
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
|
|
|
rb_ivar_set(obj, id, val)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE obj;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
VALUE val;
|
|
|
|
{
|
1999-12-14 09:50:43 +03:00
|
|
|
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
|
1999-08-13 09:45:20 +04:00
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
|
2000-02-01 06:12:21 +03:00
|
|
|
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
|
1998-01-16 15:13:05 +03:00
|
|
|
switch (TYPE(obj)) {
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_CLASS:
|
|
|
|
case T_MODULE:
|
1999-01-20 07:59:39 +03:00
|
|
|
if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
|
1998-01-16 15:19:22 +03:00
|
|
|
st_insert(ROBJECT(obj)->iv_tbl, id, val);
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
default:
|
1999-01-20 07:59:39 +03:00
|
|
|
generic_ivar_set(obj, id, val);
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_ivar_defined(obj, id)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE obj;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
switch (TYPE(obj)) {
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_CLASS:
|
|
|
|
case T_MODULE:
|
1998-01-16 15:19:22 +03:00
|
|
|
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qtrue;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
|
|
|
|
return generic_ivar_defined(obj, id);
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qfalse;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
static int
|
1999-01-20 07:59:39 +03:00
|
|
|
ivar_i(key, entry, ary)
|
1998-01-16 15:19:22 +03:00
|
|
|
ID key;
|
1999-01-20 07:59:39 +03:00
|
|
|
struct global_entry *entry;
|
|
|
|
VALUE ary;
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
|
|
|
if (rb_is_instance_id(key)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* obj.instance_variables => array
|
|
|
|
*
|
|
|
|
* Returns an array of instance variable names for the receiver. Note
|
|
|
|
* that simply defining an accessor does not create the corresponding
|
|
|
|
* instance variable.
|
|
|
|
*
|
|
|
|
* class Fred
|
|
|
|
* attr_accessor :a1
|
|
|
|
* def initialize
|
|
|
|
* @iv = 3
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* Fred.new.instance_variables #=> ["@iv"]
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_obj_instance_variables(obj)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE obj;
|
|
|
|
{
|
1999-12-14 09:50:43 +03:00
|
|
|
VALUE ary;
|
1998-01-16 15:19:22 +03:00
|
|
|
|
1999-12-14 09:50:43 +03:00
|
|
|
ary = rb_ary_new();
|
1998-01-16 15:19:22 +03:00
|
|
|
switch (TYPE(obj)) {
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_CLASS:
|
|
|
|
case T_MODULE:
|
|
|
|
if (ROBJECT(obj)->iv_tbl) {
|
1999-01-20 07:59:39 +03:00
|
|
|
st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary);
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
1999-10-04 08:51:08 +04:00
|
|
|
break;
|
1998-01-16 15:19:22 +03:00
|
|
|
default:
|
1999-10-04 08:51:08 +04:00
|
|
|
if (!generic_iv_tbl) break;
|
1999-01-20 07:59:39 +03:00
|
|
|
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
|
|
|
|
st_table *tbl;
|
|
|
|
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
st_foreach(tbl, ivar_i, ary);
|
|
|
|
}
|
|
|
|
}
|
1999-10-04 08:51:08 +04:00
|
|
|
break;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
1999-10-04 08:51:08 +04:00
|
|
|
return ary;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* obj.remove_instance_variable(symbol) => obj
|
|
|
|
*
|
|
|
|
* Removes the named instance variable from <i>obj</i>, returning that
|
|
|
|
* variable's value.
|
|
|
|
*
|
|
|
|
* class Dummy
|
|
|
|
* attr_reader :var
|
|
|
|
* def initialize
|
|
|
|
* @var = 99
|
|
|
|
* end
|
|
|
|
* def remove
|
|
|
|
* remove_instance_variable(:@var)
|
|
|
|
* end
|
|
|
|
* end
|
|
|
|
* d = Dummy.new
|
|
|
|
* d.var #=> 99
|
|
|
|
* d.remove #=> 99
|
|
|
|
* d.var #=> nil
|
|
|
|
*/
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_obj_remove_instance_variable(obj, name)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE obj, name;
|
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE val = Qnil;
|
1998-01-16 15:19:22 +03:00
|
|
|
ID id = rb_to_id(name);
|
|
|
|
|
1999-12-14 09:50:43 +03:00
|
|
|
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
|
1999-08-13 09:45:20 +04:00
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
|
2000-02-01 06:12:21 +03:00
|
|
|
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
|
1999-01-20 07:59:39 +03:00
|
|
|
if (!rb_is_instance_id(id)) {
|
2003-04-09 22:33:52 +04:00
|
|
|
rb_name_error(id, "`%s' is not allowed as an instance variable name", rb_id2name(id));
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (TYPE(obj)) {
|
|
|
|
case T_OBJECT:
|
|
|
|
case T_CLASS:
|
|
|
|
case T_MODULE:
|
2003-07-25 09:36:55 +04:00
|
|
|
if (ROBJECT(obj)->iv_tbl && st_delete(ROBJECT(obj)->iv_tbl, (st_data_t*)&id, &val)) {
|
2002-04-10 12:45:26 +04:00
|
|
|
return val;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2002-04-10 12:45:26 +04:00
|
|
|
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
|
|
|
|
if (generic_ivar_remove(obj, id, &val)) {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
break;
|
|
|
|
}
|
2002-04-10 12:45:26 +04:00
|
|
|
rb_name_error(id, "instance variable %s not defined", rb_id2name(id));
|
|
|
|
return Qnil; /* not reached */
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
NORETURN(static void uninitialized_constant _((VALUE, ID)));
|
|
|
|
static void
|
|
|
|
uninitialized_constant(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
if (klass && klass != rb_cObject)
|
|
|
|
rb_name_error(id, "uninitialized constant %s::%s",
|
2004-01-19 12:19:31 +03:00
|
|
|
rb_class2name(klass),
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_id2name(id));
|
|
|
|
else {
|
2003-05-30 01:21:23 +04:00
|
|
|
rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-22 12:42:47 +04:00
|
|
|
static VALUE
|
|
|
|
const_missing(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
return rb_funcall(klass, rb_intern("const_missing"), 1, ID2SYM(id));
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.const_missing(sym) => obj
|
|
|
|
*
|
|
|
|
* Invoked when a reference is made to an undefined constant in
|
|
|
|
* <i>mod</i>. It is passed a symbol for the undefined constant, and
|
|
|
|
* returns a value to be used for that constant. The
|
|
|
|
* following code is a (very bad) example: if reference is made to
|
|
|
|
* an undefined constant, it attempts to load a file whose name is
|
|
|
|
* the lowercase version of the constant (thus class <code>Fred</code> is
|
|
|
|
* assumed to be in file <code>fred.rb</code>). If found, it returns the
|
|
|
|
* value of the loaded class. It therefore implements a perverse
|
|
|
|
* kind of autoload facility.
|
|
|
|
*
|
|
|
|
* def Object.const_missing(name)
|
|
|
|
* @looked_for ||= {}
|
|
|
|
* str_name = name.to_s
|
|
|
|
* raise "Class not found: #{name}" if @looked_for[str_name]
|
|
|
|
* @looked_for[str_name] = 1
|
|
|
|
* file = str_name.downcase
|
|
|
|
* require file
|
|
|
|
* klass = const_get(name)
|
|
|
|
* return klass if klass
|
|
|
|
* raise "Class not found: #{name}"
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2003-07-22 12:42:47 +04:00
|
|
|
VALUE
|
|
|
|
rb_mod_const_missing(klass, name)
|
|
|
|
VALUE klass, name;
|
|
|
|
{
|
2003-07-26 06:26:08 +04:00
|
|
|
ruby_frame = ruby_frame->prev; /* pop frame for "const_missing" */
|
2003-07-22 12:42:47 +04:00
|
|
|
uninitialized_constant(klass, rb_to_id(name));
|
|
|
|
return Qnil; /* not reached */
|
|
|
|
}
|
|
|
|
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
static struct st_table *
|
|
|
|
check_autoload_table(av)
|
|
|
|
VALUE av;
|
|
|
|
{
|
|
|
|
Check_Type(av, T_DATA);
|
|
|
|
if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
|
|
|
|
RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
|
|
|
|
rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING(rb_inspect(av))->ptr);
|
|
|
|
}
|
|
|
|
return (struct st_table *)DATA_PTR(av);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_autoload(mod, id, file)
|
|
|
|
VALUE mod;
|
|
|
|
ID id;
|
|
|
|
const char *file;
|
|
|
|
{
|
2003-10-13 18:57:36 +04:00
|
|
|
VALUE av, fn;
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
struct st_table *tbl;
|
|
|
|
|
|
|
|
if (!rb_is_const_id(id)) {
|
2003-09-12 07:16:31 +04:00
|
|
|
rb_raise(rb_eNameError, "autoload must be constant name", rb_id2name(id));
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
|
|
|
if (!file || !*file) {
|
|
|
|
rb_raise(rb_eArgError, "empty file name");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tbl = RCLASS(mod)->iv_tbl) && st_lookup(tbl, id, &av) && av != Qundef)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rb_const_set(mod, id, Qundef);
|
|
|
|
tbl = RCLASS(mod)->iv_tbl;
|
|
|
|
if (st_lookup(tbl, autoload, &av)) {
|
|
|
|
tbl = check_autoload_table(av);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
av = Data_Wrap_Struct(rb_cData, rb_mark_tbl, st_free_table, 0);
|
|
|
|
st_add_direct(tbl, autoload, av);
|
|
|
|
DATA_PTR(av) = tbl = st_init_numtable();
|
|
|
|
}
|
2003-10-13 18:57:36 +04:00
|
|
|
fn = rb_str_new2(file);
|
|
|
|
FL_UNSET(fn, FL_TAINT);
|
|
|
|
OBJ_FREEZE(fn);
|
|
|
|
st_insert(tbl, id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, ruby_safe_level, 0));
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
|
|
|
|
2003-10-13 18:57:36 +04:00
|
|
|
static NODE*
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
autoload_delete(mod, id)
|
|
|
|
VALUE mod;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-10-13 18:57:36 +04:00
|
|
|
VALUE val;
|
|
|
|
st_data_t load = 0;
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
|
2003-07-25 09:36:55 +04:00
|
|
|
st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) {
|
|
|
|
struct st_table *tbl = check_autoload_table(val);
|
|
|
|
|
2003-10-13 18:57:36 +04:00
|
|
|
st_delete(tbl, (st_data_t*)&id, &load);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
|
2003-06-25 09:28:24 +04:00
|
|
|
if (tbl->num_entries == 0) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
DATA_PTR(val) = 0;
|
|
|
|
st_free_table(tbl);
|
|
|
|
id = autoload;
|
2003-07-25 09:36:55 +04:00
|
|
|
if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_gc_force_recycle(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-13 18:57:36 +04:00
|
|
|
return (NODE *)load;
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_autoload_load(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-07-24 22:33:50 +04:00
|
|
|
VALUE file;
|
2003-10-13 18:57:36 +04:00
|
|
|
NODE *load = autoload_delete(klass, id);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
|
2003-10-13 18:57:36 +04:00
|
|
|
if (!load || !(file = load->nd_lit) || rb_provided(RSTRING(file)->ptr)) {
|
2003-08-30 04:04:02 +04:00
|
|
|
const_missing(klass, id);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
2003-10-13 18:57:36 +04:00
|
|
|
rb_require_safe(file, load->nd_nth);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
autoload_file(mod, id)
|
|
|
|
VALUE mod;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
VALUE val, file;
|
|
|
|
struct st_table *tbl;
|
2003-10-13 18:57:36 +04:00
|
|
|
st_data_t load;
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
|
|
|
|
if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) ||
|
2003-10-13 18:57:36 +04:00
|
|
|
!(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
return Qnil;
|
|
|
|
}
|
2003-10-13 18:57:36 +04:00
|
|
|
file = ((NODE *)load)->nd_lit;
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
Check_Type(file, T_STRING);
|
|
|
|
if (!RSTRING(file)->ptr) {
|
|
|
|
rb_raise(rb_eArgError, "empty file name");
|
|
|
|
}
|
|
|
|
if (!rb_provided(RSTRING(file)->ptr)) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* already loaded but not defined */
|
2003-07-25 09:36:55 +04:00
|
|
|
st_delete(tbl, (st_data_t*)&id, 0);
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
if (!tbl->num_entries) {
|
|
|
|
DATA_PTR(val) = 0;
|
|
|
|
st_free_table(tbl);
|
|
|
|
id = autoload;
|
2003-07-25 09:36:55 +04:00
|
|
|
if (st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, &val)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_gc_force_recycle(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_autoload_p(mod, id)
|
|
|
|
VALUE mod;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
struct st_table *tbl = RCLASS(mod)->iv_tbl;
|
|
|
|
VALUE val;
|
|
|
|
|
|
|
|
if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
return autoload_file(mod, id);
|
|
|
|
}
|
|
|
|
|
2003-06-20 11:11:44 +04:00
|
|
|
static VALUE
|
2003-08-28 12:35:43 +04:00
|
|
|
rb_const_get_0(klass, id, exclude, recurse)
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
2003-08-30 04:04:02 +04:00
|
|
|
int exclude, recurse;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2001-05-02 08:22:21 +04:00
|
|
|
VALUE value, tmp;
|
|
|
|
int mod_retry = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
tmp = klass;
|
2001-05-02 08:22:21 +04:00
|
|
|
retry:
|
1998-01-16 15:13:05 +03:00
|
|
|
while (tmp) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
|
|
|
|
if (value == Qundef) {
|
|
|
|
rb_autoload_load(tmp, id);
|
|
|
|
continue;
|
|
|
|
}
|
2003-07-10 02:28:42 +04:00
|
|
|
if (exclude && tmp == rb_cObject && klass != rb_cObject) {
|
|
|
|
rb_warn("toplevel constant %s referenced by %s::%s",
|
|
|
|
rb_id2name(id), rb_class2name(klass), rb_id2name(id));
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
return value;
|
|
|
|
}
|
2003-08-28 12:35:43 +04:00
|
|
|
if (!recurse && klass != rb_cObject) break;
|
1998-01-16 15:19:22 +03:00
|
|
|
tmp = RCLASS(tmp)->super;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2003-10-01 20:06:19 +04:00
|
|
|
if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
|
2001-05-02 08:22:21 +04:00
|
|
|
mod_retry = 1;
|
|
|
|
tmp = rb_cObject;
|
|
|
|
goto retry;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2000-07-12 13:36:21 +04:00
|
|
|
|
2003-07-22 12:42:47 +04:00
|
|
|
return const_missing(klass, id);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-06-20 11:11:44 +04:00
|
|
|
VALUE
|
|
|
|
rb_const_get_from(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-08-28 12:35:43 +04:00
|
|
|
return rb_const_get_0(klass, id, Qtrue, Qtrue);
|
2003-06-20 11:11:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_const_get(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-08-28 12:35:43 +04:00
|
|
|
return rb_const_get_0(klass, id, Qfalse, Qtrue);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_const_get_at(klass, id)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-10-01 20:06:19 +04:00
|
|
|
return rb_const_get_0(klass, id, Qtrue, Qfalse);
|
2003-06-20 11:11:44 +04:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* remove_const(sym) => obj
|
|
|
|
*
|
|
|
|
* Removes the definition of the given constant, returning that
|
|
|
|
* constant's value. Predefined classes and singleton objects (such as
|
|
|
|
* <i>true</i>) cannot be removed.
|
|
|
|
*/
|
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE
|
1999-12-14 09:50:43 +03:00
|
|
|
rb_mod_remove_const(mod, name)
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE mod, name;
|
|
|
|
{
|
|
|
|
ID id = rb_to_id(name);
|
|
|
|
VALUE val;
|
|
|
|
|
1999-12-14 09:50:43 +03:00
|
|
|
if (!rb_is_const_id(id)) {
|
2003-04-09 22:33:52 +04:00
|
|
|
rb_name_error(id, "`%s' is not allowed as a constant name", rb_id2name(id));
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2000-02-01 06:12:21 +03:00
|
|
|
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
|
|
|
|
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-07-25 09:36:55 +04:00
|
|
|
if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) {
|
2003-05-30 01:21:23 +04:00
|
|
|
if (val == Qundef) {
|
|
|
|
autoload_delete(mod, id);
|
|
|
|
val = Qnil;
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
return val;
|
|
|
|
}
|
1999-12-14 09:50:43 +03:00
|
|
|
if (rb_const_defined_at(mod, id)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_name_error(id, "cannot remove %s::%s",
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_class2name(mod), rb_id2name(id));
|
|
|
|
}
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_name_error(id, "constant %s::%s not defined",
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_class2name(mod), rb_id2name(id));
|
1999-01-20 07:59:39 +03:00
|
|
|
return Qnil; /* not reached */
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
static int
|
2001-06-05 11:19:39 +04:00
|
|
|
sv_i(key, value, tbl)
|
|
|
|
ID key;
|
|
|
|
VALUE value;
|
|
|
|
st_table *tbl;
|
|
|
|
{
|
|
|
|
if (rb_is_const_id(key)) {
|
|
|
|
if (!st_lookup(tbl, key, 0)) {
|
|
|
|
st_insert(tbl, key, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
rb_mod_const_at(mod, data)
|
|
|
|
VALUE mod;
|
|
|
|
void *data;
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2001-06-05 11:19:39 +04:00
|
|
|
st_table *tbl = data;
|
|
|
|
if (!tbl) {
|
|
|
|
tbl = st_init_numtable();
|
|
|
|
}
|
1998-01-16 15:19:22 +03:00
|
|
|
if (RCLASS(mod)->iv_tbl) {
|
* st.h, st.c: Introduce new conventional typedef's, st_data_t,
st_compare_func_t, st_hash_func_t and st_each_func_t.
* st.h, st.c: Do explicit function declarations and do not rely on
implicit declarations. On such platforms as IA64, int argument
values are NOT automatically promoted to long (64bit) values, so
explicit declarations are mandatory for those functions that
take long values or pointers. This fixes miniruby's coredump on
FreeBSD/IA64.
* class.c, eval.c, gc.c, hash.c, marshal.c, parse.y, variable.c:
Add proper casts to avoid warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3303 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-01-06 18:55:43 +03:00
|
|
|
st_foreach(RCLASS(mod)->iv_tbl, sv_i, (st_data_t)tbl);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-06-05 11:19:39 +04:00
|
|
|
return tbl;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
|
|
|
|
2001-06-05 11:19:39 +04:00
|
|
|
void*
|
|
|
|
rb_mod_const_of(mod, data)
|
1998-01-16 15:19:22 +03:00
|
|
|
VALUE mod;
|
2001-06-05 11:19:39 +04:00
|
|
|
void *data;
|
1998-01-16 15:19:22 +03:00
|
|
|
{
|
2003-07-03 15:02:53 +04:00
|
|
|
VALUE tmp = mod;
|
1998-01-16 15:19:22 +03:00
|
|
|
for (;;) {
|
2003-07-03 15:02:53 +04:00
|
|
|
data = rb_mod_const_at(tmp, data);
|
|
|
|
tmp = RCLASS(tmp)->super;
|
|
|
|
if (!tmp) break;
|
|
|
|
if (tmp == rb_cObject && mod != rb_cObject) break;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2001-06-05 11:19:39 +04:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
list_i(key, value, ary)
|
|
|
|
ID key, value;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
|
|
|
rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_const_list(data)
|
|
|
|
void *data;
|
|
|
|
{
|
|
|
|
st_table *tbl = data;
|
|
|
|
VALUE ary;
|
|
|
|
|
|
|
|
if (!tbl) return rb_ary_new2(0);
|
|
|
|
ary = rb_ary_new2(tbl->num_entries);
|
|
|
|
st_foreach(tbl, list_i, ary);
|
2002-03-20 14:15:19 +03:00
|
|
|
st_free_table(tbl);
|
2001-06-05 11:19:39 +04:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
return ary;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.constants => array
|
|
|
|
*
|
|
|
|
* Returns an array of the names of the constants accessible in
|
|
|
|
* <i>mod</i>. This includes the names of constants in any included
|
|
|
|
* modules (example at start of section).
|
|
|
|
*/
|
|
|
|
|
1999-11-17 10:30:37 +03:00
|
|
|
VALUE
|
|
|
|
rb_mod_constants(mod)
|
|
|
|
VALUE mod;
|
|
|
|
{
|
2001-06-05 11:19:39 +04:00
|
|
|
return rb_const_list(rb_mod_const_of(mod, 0));
|
1999-11-17 10:30:37 +03:00
|
|
|
}
|
|
|
|
|
2003-08-30 04:04:02 +04:00
|
|
|
static int
|
|
|
|
rb_const_defined_0(klass, id, exclude, recurse)
|
2003-06-20 11:11:44 +04:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
2003-08-30 04:04:02 +04:00
|
|
|
int exclude, recurse;
|
2003-06-20 11:11:44 +04:00
|
|
|
{
|
2003-10-02 07:00:23 +04:00
|
|
|
VALUE value, tmp;
|
|
|
|
int mod_retry = 0;
|
2003-06-20 11:11:44 +04:00
|
|
|
|
2003-10-02 07:00:23 +04:00
|
|
|
tmp = klass;
|
|
|
|
retry:
|
2003-06-20 11:11:44 +04:00
|
|
|
while (tmp) {
|
|
|
|
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) {
|
|
|
|
if (value == Qundef && NIL_P(autoload_file(klass, id)))
|
|
|
|
return Qfalse;
|
|
|
|
return Qtrue;
|
|
|
|
}
|
2003-08-30 04:04:02 +04:00
|
|
|
if (!recurse && klass != rb_cObject) break;
|
2003-06-20 11:11:44 +04:00
|
|
|
tmp = RCLASS(tmp)->super;
|
|
|
|
}
|
2003-10-02 07:00:23 +04:00
|
|
|
if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
|
|
|
|
mod_retry = 1;
|
|
|
|
tmp = rb_cObject;
|
|
|
|
goto retry;
|
2003-08-30 04:04:02 +04:00
|
|
|
}
|
2003-06-20 11:11:44 +04:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
int
|
2003-10-01 20:06:19 +04:00
|
|
|
rb_const_defined_from(klass, id)
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
{
|
2003-10-01 20:06:19 +04:00
|
|
|
return rb_const_defined_0(klass, id, Qtrue, Qtrue);
|
2003-08-30 04:04:02 +04:00
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-08-30 04:04:02 +04:00
|
|
|
int
|
2003-10-01 20:06:19 +04:00
|
|
|
rb_const_defined(klass, id)
|
2003-08-30 04:04:02 +04:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
return rb_const_defined_0(klass, id, Qfalse, Qtrue);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2003-10-01 20:06:19 +04:00
|
|
|
rb_const_defined_at(klass, id)
|
2003-08-30 04:04:02 +04:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
2003-10-01 20:06:19 +04:00
|
|
|
return rb_const_defined_0(klass, id, Qtrue, Qfalse);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2000-02-18 09:59:36 +03:00
|
|
|
static void
|
2000-12-08 10:10:38 +03:00
|
|
|
mod_av_set(klass, id, val, isconst)
|
1999-01-20 07:59:39 +03:00
|
|
|
VALUE klass;
|
1998-01-16 15:13:05 +03:00
|
|
|
ID id;
|
|
|
|
VALUE val;
|
2000-12-08 10:10:38 +03:00
|
|
|
int isconst;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2000-12-08 10:10:38 +03:00
|
|
|
char *dest = isconst ? "constant" : "class variable";
|
|
|
|
|
1999-12-14 09:50:43 +03:00
|
|
|
if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
|
2000-02-18 09:59:36 +03:00
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-22 07:00:03 +03:00
|
|
|
if (OBJ_FROZEN(klass)) {
|
|
|
|
if (BUILTIN_TYPE(klass) == T_MODULE) {
|
|
|
|
rb_error_frozen("module");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_error_frozen("class");
|
|
|
|
}
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
if (!RCLASS(klass)->iv_tbl) {
|
|
|
|
RCLASS(klass)->iv_tbl = st_init_numtable();
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2001-08-23 10:02:15 +04:00
|
|
|
else if (isconst) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
VALUE value = Qfalse;
|
|
|
|
|
2003-07-01 05:36:25 +04:00
|
|
|
if (st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
if (value == Qundef)
|
|
|
|
autoload_delete(klass, id);
|
|
|
|
else
|
|
|
|
rb_warn("already initialized %s %s", dest, rb_id2name(id));
|
2001-08-23 10:02:15 +04:00
|
|
|
}
|
2000-02-01 06:12:21 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
st_insert(RCLASS(klass)->iv_tbl, id, val);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2000-12-08 10:10:38 +03:00
|
|
|
|
2000-02-18 09:59:36 +03:00
|
|
|
void
|
|
|
|
rb_const_set(klass, id, val)
|
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
VALUE val;
|
|
|
|
{
|
2000-12-08 10:10:38 +03:00
|
|
|
mod_av_set(klass, id, val, Qtrue);
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
void
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_const(klass, name, val)
|
|
|
|
VALUE klass;
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
ID id = rb_intern(name);
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2003-07-24 09:18:47 +04:00
|
|
|
if (!rb_is_const_id(id)) {
|
|
|
|
rb_warn("rb_define_const: invalide name `%s' for constant", name);
|
|
|
|
}
|
1999-01-20 07:59:39 +03:00
|
|
|
if (klass == rb_cObject) {
|
|
|
|
rb_secure(4);
|
|
|
|
}
|
1999-12-14 09:50:43 +03:00
|
|
|
rb_const_set(klass, id, val);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_global_const(name, val)
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
{
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_define_const(rb_cObject, name, val);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2001-11-13 11:19:52 +03:00
|
|
|
static VALUE
|
|
|
|
original_module(c)
|
|
|
|
VALUE c;
|
|
|
|
{
|
|
|
|
if (TYPE(c) == T_ICLASS)
|
|
|
|
return RBASIC(c)->klass;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2001-08-20 08:29:58 +04:00
|
|
|
static void
|
2001-11-13 11:19:52 +03:00
|
|
|
cvar_override_check(id, a)
|
2002-09-17 13:36:05 +04:00
|
|
|
ID id;
|
2001-11-13 11:19:52 +03:00
|
|
|
VALUE a;
|
2001-08-20 08:29:58 +04:00
|
|
|
{
|
2001-11-13 11:19:52 +03:00
|
|
|
VALUE base = original_module(a);
|
|
|
|
|
2001-08-20 08:29:58 +04:00
|
|
|
a = RCLASS(a)->super;
|
|
|
|
while (a) {
|
2001-10-29 08:07:26 +03:00
|
|
|
if (RCLASS(a)->iv_tbl) {
|
|
|
|
if (st_lookup(RCLASS(a)->iv_tbl,id,0)) {
|
|
|
|
rb_warning("class variable %s of %s is overridden by %s",
|
2001-11-13 11:19:52 +03:00
|
|
|
rb_id2name(id), rb_class2name(original_module(a)),
|
|
|
|
rb_class2name(base));
|
2001-10-29 08:07:26 +03:00
|
|
|
}
|
2001-08-20 08:29:58 +04:00
|
|
|
}
|
|
|
|
a = RCLASS(a)->super;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-02-18 09:59:36 +03:00
|
|
|
void
|
2002-02-15 09:14:26 +03:00
|
|
|
rb_cvar_set(klass, id, val, warn)
|
2000-02-18 09:59:36 +03:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
VALUE val;
|
2002-02-15 09:14:26 +03:00
|
|
|
int warn;
|
2000-02-18 09:59:36 +03:00
|
|
|
{
|
|
|
|
VALUE tmp;
|
|
|
|
|
|
|
|
tmp = klass;
|
|
|
|
while (tmp) {
|
2001-12-21 12:23:28 +03:00
|
|
|
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
|
|
|
|
if (OBJ_FROZEN(tmp)) rb_error_frozen("class/module");
|
|
|
|
if (!OBJ_TAINTED(tmp) && rb_safe_level() >= 4)
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't modify class variable");
|
2002-04-11 14:03:01 +04:00
|
|
|
if (warn && RTEST(ruby_verbose) && klass != tmp) {
|
2001-08-14 12:13:31 +04:00
|
|
|
rb_warning("already initialized class variable %s", rb_id2name(id));
|
|
|
|
}
|
2000-09-07 10:59:46 +04:00
|
|
|
st_insert(RCLASS(tmp)->iv_tbl,id,val);
|
2002-04-11 14:03:01 +04:00
|
|
|
if (RTEST(ruby_verbose)) {
|
2001-11-13 11:19:52 +03:00
|
|
|
cvar_override_check(id, tmp);
|
2001-08-20 08:29:58 +04:00
|
|
|
}
|
2000-09-07 10:59:46 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
tmp = RCLASS(tmp)->super;
|
|
|
|
}
|
|
|
|
|
2000-12-08 10:10:38 +03:00
|
|
|
mod_av_set(klass, id, val, Qfalse);
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
2000-03-23 11:37:35 +03:00
|
|
|
rb_cvar_get(klass, id)
|
2000-02-18 09:59:36 +03:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
VALUE value;
|
|
|
|
VALUE tmp;
|
|
|
|
|
|
|
|
tmp = klass;
|
|
|
|
while (tmp) {
|
2001-10-29 08:07:26 +03:00
|
|
|
if (RCLASS(tmp)->iv_tbl) {
|
|
|
|
if (st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
|
2002-04-11 14:03:01 +04:00
|
|
|
if (RTEST(ruby_verbose)) {
|
2001-11-13 11:19:52 +03:00
|
|
|
cvar_override_check(id, tmp);
|
2001-10-29 08:07:26 +03:00
|
|
|
}
|
|
|
|
return value;
|
2001-08-20 08:29:58 +04:00
|
|
|
}
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
|
|
|
tmp = RCLASS(tmp)->super;
|
|
|
|
}
|
|
|
|
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id,"uninitialized class variable %s in %s",
|
|
|
|
rb_id2name(id), rb_class2name(klass));
|
2000-02-18 09:59:36 +03:00
|
|
|
return Qnil; /* not reached */
|
|
|
|
}
|
|
|
|
|
2000-12-08 10:10:38 +03:00
|
|
|
VALUE
|
2000-03-23 11:37:35 +03:00
|
|
|
rb_cvar_defined(klass, id)
|
2000-02-18 09:59:36 +03:00
|
|
|
VALUE klass;
|
|
|
|
ID id;
|
|
|
|
{
|
|
|
|
VALUE tmp;
|
|
|
|
|
|
|
|
tmp = klass;
|
|
|
|
while (tmp) {
|
|
|
|
if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
tmp = RCLASS(tmp)->super;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-03-23 11:37:35 +03:00
|
|
|
rb_cv_set(klass, name, val)
|
|
|
|
VALUE klass;
|
|
|
|
const char *name;
|
|
|
|
VALUE val;
|
|
|
|
{
|
2001-05-02 08:22:21 +04:00
|
|
|
ID id = rb_intern(name);
|
|
|
|
if (!rb_is_class_id(id)) {
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id, "wrong class variable name %s", name);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
2002-02-15 09:14:26 +03:00
|
|
|
rb_cvar_set(klass, id, val, Qfalse);
|
2000-03-23 11:37:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_cv_get(klass, name)
|
|
|
|
VALUE klass;
|
|
|
|
const char *name;
|
|
|
|
{
|
2001-05-02 08:22:21 +04:00
|
|
|
ID id = rb_intern(name);
|
|
|
|
if (!rb_is_class_id(id)) {
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id, "wrong class variable name %s", name);
|
2001-05-02 08:22:21 +04:00
|
|
|
}
|
|
|
|
return rb_cvar_get(klass, id);
|
2000-03-23 11:37:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rb_define_class_variable(klass, name, val)
|
2000-02-18 09:59:36 +03:00
|
|
|
VALUE klass;
|
|
|
|
const char *name;
|
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
ID id = rb_intern(name);
|
|
|
|
|
2000-03-23 11:37:35 +03:00
|
|
|
if (!rb_is_class_id(id)) {
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id, "wrong class variable name %s", name);
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
2002-02-15 09:14:26 +03:00
|
|
|
rb_cvar_set(klass, id, val, Qtrue);
|
2000-02-18 09:59:36 +03:00
|
|
|
}
|
|
|
|
|
2000-09-15 10:00:30 +04:00
|
|
|
static int
|
|
|
|
cv_i(key, value, ary)
|
|
|
|
ID key;
|
|
|
|
VALUE value;
|
|
|
|
VALUE ary;
|
|
|
|
{
|
|
|
|
if (rb_is_class_id(key)) {
|
|
|
|
VALUE kval = rb_str_new2(rb_id2name(key));
|
|
|
|
if (!rb_ary_includes(ary, kval)) {
|
|
|
|
rb_ary_push(ary, kval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ST_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* mod.class_variables => array
|
|
|
|
*
|
|
|
|
* Returns an array of the names of class variables in <i>mod</i> and
|
|
|
|
* the ancestors of <i>mod</i>.
|
|
|
|
*
|
|
|
|
* class One
|
|
|
|
* @@var1 = 1
|
|
|
|
* end
|
|
|
|
* class Two < One
|
|
|
|
* @@var2 = 2
|
|
|
|
* end
|
|
|
|
* One.class_variables #=> ["@@var1"]
|
|
|
|
* Two.class_variables #=> ["@@var2", "@@var1"]
|
|
|
|
*/
|
|
|
|
|
2000-09-15 10:00:30 +04:00
|
|
|
VALUE
|
|
|
|
rb_mod_class_variables(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (RCLASS(obj)->iv_tbl) {
|
|
|
|
st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary);
|
|
|
|
}
|
|
|
|
obj = RCLASS(obj)->super;
|
|
|
|
if (!obj) break;
|
|
|
|
}
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2003-12-28 09:33:07 +03:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* remove_class_variable(sym) => obj
|
|
|
|
*
|
|
|
|
* Removes the definition of the <i>sym</i>, returning that
|
|
|
|
* constant's value.
|
|
|
|
*
|
|
|
|
* class Dummy
|
|
|
|
* @@var = 99
|
|
|
|
* puts @@var
|
|
|
|
* remove_class_variable(:@@var)
|
|
|
|
* puts(defined? @@var)
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* 99
|
|
|
|
* nil
|
|
|
|
*/
|
|
|
|
|
2000-12-08 10:10:38 +03:00
|
|
|
VALUE
|
|
|
|
rb_mod_remove_cvar(mod, name)
|
|
|
|
VALUE mod, name;
|
|
|
|
{
|
|
|
|
ID id = rb_to_id(name);
|
|
|
|
VALUE val;
|
|
|
|
|
|
|
|
if (!rb_is_class_id(id)) {
|
2002-01-16 12:25:59 +03:00
|
|
|
rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
|
2000-12-08 10:10:38 +03:00
|
|
|
}
|
|
|
|
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
|
|
|
|
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
|
|
|
|
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
|
|
|
|
|
2003-07-25 09:36:55 +04:00
|
|
|
if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, (st_data_t*)&id, &val)) {
|
2000-12-08 10:10:38 +03:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
if (rb_cvar_defined(mod, id)) {
|
* eval.c (ev_const_defined, ev_const_get), variable.c
(rb_const_get_at, rb_const_get, rb_mod_remove_const): use Qundef
as autoload marker. [ruby-dev:18103], [ruby-dev:18184]
* eval.c (rb_mod_autoload, rb_mod_autoload_p): new method;
Module#autoload, Module#autoload?.
* variable.c (rb_autoload, rb_autoload_load, rb_autoload_p):
manage autoload constants per classes/modules.
* variable.c (rb_const_defined_at, rb_const_defined): return false
for autoloading constants.
* class.c (rb_define_class, rb_define_module), eval.c (rb_eval),
variable.c (rb_mod_const_at, rb_const_assign): removed autoload
stuff.
* intern.h: prototypes; rb_autoload, rb_autoload_load,
rb_autoload_p.
* lib/optparse.rb (OptionParser::Switch::PlacedArgument::parse):
do not treat unmatched argument as an option.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-05-29 04:11:11 +04:00
|
|
|
rb_name_error(id, "cannot remove %s for %s",
|
2000-12-08 10:10:38 +03:00
|
|
|
rb_id2name(id), rb_class2name(mod));
|
|
|
|
}
|
2001-07-02 12:46:28 +04:00
|
|
|
rb_name_error(id, "class variable %s not defined for %s",
|
|
|
|
rb_id2name(id), rb_class2name(mod));
|
2000-12-08 10:10:38 +03:00
|
|
|
return Qnil; /* not reached */
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE
|
|
|
|
rb_iv_get(obj, name)
|
|
|
|
VALUE obj;
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
ID id = rb_intern(name);
|
|
|
|
|
|
|
|
return rb_ivar_get(obj, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
rb_iv_set(obj, name, val)
|
|
|
|
VALUE obj;
|
1999-08-13 09:45:20 +04:00
|
|
|
const char *name;
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE val;
|
|
|
|
{
|
|
|
|
ID id = rb_intern(name);
|
|
|
|
|
|
|
|
return rb_ivar_set(obj, id, val);
|
|
|
|
}
|