* variable.c (rb_global_entry): reconstruct global variable
aliasing (sharing global_entry->var with other global_entry). * variable.c (undef_getter): ditto. * variable.c (undef_setter): ditto. * variable.c (val_setter): ditto. * variable.c (mark_global_entry): ditto. * variable.c (rb_define_hooked_variable): ditto. * variable.c (rb_f_trace_var): ditto. * variable.c (remove_trace): ditto. * variable.c (rb_f_untrace_var): ditto. * variable.c (rb_gvar_get): ditto. * variable.c (trace_en): ditto. * variable.c (rb_gvar_set): ditto. * variable.c (rb_gvar_defined): ditto. * variable.c (rb_alias_variable): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1797 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c4712cbc50
commit
96baf2c092
32
ChangeLog
32
ChangeLog
@ -1,3 +1,34 @@
|
|||||||
|
Tue Oct 23 01:15:43 2001 K.Kosako <kosako@sofnec.co.jp>
|
||||||
|
|
||||||
|
* variable.c (rb_global_entry): reconstruct global variable
|
||||||
|
aliasing (sharing global_entry->var with other global_entry).
|
||||||
|
|
||||||
|
* variable.c (undef_getter): ditto.
|
||||||
|
|
||||||
|
* variable.c (undef_setter): ditto.
|
||||||
|
|
||||||
|
* variable.c (val_setter): ditto.
|
||||||
|
|
||||||
|
* variable.c (mark_global_entry): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_define_hooked_variable): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_f_trace_var): ditto.
|
||||||
|
|
||||||
|
* variable.c (remove_trace): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_f_untrace_var): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_gvar_get): ditto.
|
||||||
|
|
||||||
|
* variable.c (trace_en): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_gvar_set): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_gvar_defined): ditto.
|
||||||
|
|
||||||
|
* variable.c (rb_alias_variable): ditto.
|
||||||
|
|
||||||
Mon Oct 22 15:21:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
Mon Oct 22 15:21:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* class.c (rb_mod_clone): should not copy class name, since clone
|
* class.c (rb_mod_clone): should not copy class name, since clone
|
||||||
@ -51,7 +82,6 @@ Tue Oct 16 13:18:47 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
|||||||
* object.c (rb_mod_initialize): optional block with
|
* object.c (rb_mod_initialize): optional block with
|
||||||
Module.new. [new] (from 2001-10-10)
|
Module.new. [new] (from 2001-10-10)
|
||||||
|
|
||||||
>>>>>>> 1.591
|
|
||||||
Tue Oct 16 00:07:06 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
Tue Oct 16 00:07:06 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
||||||
|
|
||||||
* parse.y (yylex): disallow alpha-numeric and mbchar for
|
* parse.y (yylex): disallow alpha-numeric and mbchar for
|
||||||
|
181
variable.c
181
variable.c
@ -291,8 +291,8 @@ struct trace_var {
|
|||||||
struct trace_var *next;
|
struct trace_var *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct global_entry {
|
struct global_variable {
|
||||||
ID id;
|
int counter;
|
||||||
void *data;
|
void *data;
|
||||||
VALUE (*getter)();
|
VALUE (*getter)();
|
||||||
void (*setter)();
|
void (*setter)();
|
||||||
@ -301,6 +301,11 @@ struct global_entry {
|
|||||||
struct trace_var *trace;
|
struct trace_var *trace;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct global_entry {
|
||||||
|
struct global_variable *var;
|
||||||
|
ID id;
|
||||||
|
};
|
||||||
|
|
||||||
static VALUE undef_getter();
|
static VALUE undef_getter();
|
||||||
static void undef_setter();
|
static void undef_setter();
|
||||||
static void undef_marker();
|
static void undef_marker();
|
||||||
@ -313,9 +318,6 @@ static VALUE var_getter();
|
|||||||
static void var_setter();
|
static void var_setter();
|
||||||
static void var_marker();
|
static void var_marker();
|
||||||
|
|
||||||
static VALUE alias_getter();
|
|
||||||
static void alias_setter();
|
|
||||||
|
|
||||||
struct global_entry*
|
struct global_entry*
|
||||||
rb_global_entry(id)
|
rb_global_entry(id)
|
||||||
ID id;
|
ID id;
|
||||||
@ -323,16 +325,20 @@ rb_global_entry(id)
|
|||||||
struct global_entry *entry;
|
struct global_entry *entry;
|
||||||
|
|
||||||
if (!st_lookup(rb_global_tbl, id, &entry)) {
|
if (!st_lookup(rb_global_tbl, id, &entry)) {
|
||||||
|
struct global_variable *var;
|
||||||
entry = ALLOC(struct global_entry);
|
entry = ALLOC(struct global_entry);
|
||||||
st_add_direct(rb_global_tbl, id, entry);
|
st_add_direct(rb_global_tbl, id, entry);
|
||||||
|
var = ALLOC(struct global_variable);
|
||||||
entry->id = id;
|
entry->id = id;
|
||||||
entry->data = 0;
|
entry->var = var;
|
||||||
entry->getter = undef_getter;
|
var->counter = 1;
|
||||||
entry->setter = undef_setter;
|
var->data = 0;
|
||||||
entry->marker = undef_marker;
|
var->getter = undef_getter;
|
||||||
|
var->setter = undef_setter;
|
||||||
|
var->marker = undef_marker;
|
||||||
|
|
||||||
entry->block_trace = 0;
|
var->block_trace = 0;
|
||||||
entry->trace = 0;
|
var->trace = 0;
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
@ -348,17 +354,17 @@ undef_getter(id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
undef_setter(val, id, data, entry)
|
undef_setter(val, id, data, var)
|
||||||
VALUE val;
|
VALUE val;
|
||||||
ID id;
|
ID id;
|
||||||
void *data;
|
void *data;
|
||||||
struct global_entry *entry;
|
struct global_variable *var;
|
||||||
{
|
{
|
||||||
entry->getter = val_getter;
|
var->getter = val_getter;
|
||||||
entry->setter = val_setter;
|
var->setter = val_setter;
|
||||||
entry->marker = val_marker;
|
var->marker = val_marker;
|
||||||
|
|
||||||
entry->data = (void*)val;
|
var->data = (void*)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -375,13 +381,13 @@ val_getter(id, val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
val_setter(val, id, data, entry)
|
val_setter(val, id, data, var)
|
||||||
VALUE val;
|
VALUE val;
|
||||||
ID id;
|
ID id;
|
||||||
void *data;
|
void *data;
|
||||||
struct global_entry *entry;
|
struct global_variable *var;
|
||||||
{
|
{
|
||||||
entry->data = (void*)val;
|
var->data = (void*)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -425,53 +431,16 @@ readonly_setter(val, id, var)
|
|||||||
rb_name_error(id, "can't set variable %s", rb_id2name(id));
|
rb_name_error(id, "can't set variable %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
alias_fixup(entry1, entry2)
|
|
||||||
struct global_entry *entry1, *entry2;
|
|
||||||
{
|
|
||||||
if (entry2->getter != val_getter) return 0;
|
|
||||||
entry1->data = &entry2->data;
|
|
||||||
entry1->getter = var_getter;
|
|
||||||
if (entry2->setter == val_setter)
|
|
||||||
entry1->setter = var_setter;
|
|
||||||
else
|
|
||||||
entry1->setter = entry2->setter;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
alias_getter(id, data, entry)
|
|
||||||
ID id;
|
|
||||||
void *data;
|
|
||||||
struct global_entry *entry;
|
|
||||||
{
|
|
||||||
struct global_entry *entry2 = data;
|
|
||||||
VALUE val = (*entry2->getter)(id, entry2->data, entry2);
|
|
||||||
alias_fixup(entry, entry2);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
alias_setter(val, id, data, entry)
|
|
||||||
VALUE val;
|
|
||||||
ID id;
|
|
||||||
void *data;
|
|
||||||
struct global_entry *entry;
|
|
||||||
{
|
|
||||||
struct global_entry *entry2 = data;
|
|
||||||
(*entry2->setter)(val, id, entry2->data, entry2);
|
|
||||||
alias_fixup(entry, entry2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mark_global_entry(key, entry)
|
mark_global_entry(key, entry)
|
||||||
ID key;
|
ID key;
|
||||||
struct global_entry *entry;
|
struct global_entry *entry;
|
||||||
{
|
{
|
||||||
struct trace_var *trace;
|
struct trace_var *trace;
|
||||||
|
struct global_variable *var = entry->var;
|
||||||
|
|
||||||
(*entry->marker)(entry->data);
|
(*var->marker)(var->data);
|
||||||
trace = entry->trace;
|
trace = var->trace;
|
||||||
while (trace) {
|
while (trace) {
|
||||||
if (trace->data) rb_gc_mark_maybe(trace->data);
|
if (trace->data) rb_gc_mark_maybe(trace->data);
|
||||||
trace = trace->next;
|
trace = trace->next;
|
||||||
@ -508,14 +477,14 @@ rb_define_hooked_variable(name, var, getter, setter)
|
|||||||
VALUE (*getter)();
|
VALUE (*getter)();
|
||||||
void (*setter)();
|
void (*setter)();
|
||||||
{
|
{
|
||||||
struct global_entry *entry;
|
struct global_variable *gvar;
|
||||||
ID id = global_id(name);
|
ID id = global_id(name);
|
||||||
|
|
||||||
entry = rb_global_entry(id);
|
gvar = rb_global_entry(id)->var;
|
||||||
entry->data = (void*)var;
|
gvar->data = (void*)var;
|
||||||
entry->getter = getter?getter:var_getter;
|
gvar->getter = getter?getter:var_getter;
|
||||||
entry->setter = setter?setter:var_setter;
|
gvar->setter = setter?setter:var_setter;
|
||||||
entry->marker = var_marker;
|
gvar->marker = var_marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -573,20 +542,20 @@ rb_f_trace_var(argc, argv)
|
|||||||
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
trace = ALLOC(struct trace_var);
|
trace = ALLOC(struct trace_var);
|
||||||
trace->next = entry->trace;
|
trace->next = entry->var->trace;
|
||||||
trace->func = rb_trace_eval;
|
trace->func = rb_trace_eval;
|
||||||
trace->data = cmd;
|
trace->data = cmd;
|
||||||
trace->removed = 0;
|
trace->removed = 0;
|
||||||
entry->trace = trace;
|
entry->var->trace = trace;
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_trace(entry)
|
remove_trace(var)
|
||||||
struct global_entry *entry;
|
struct global_variable *var;
|
||||||
{
|
{
|
||||||
struct trace_var *trace = entry->trace;
|
struct trace_var *trace = var->trace;
|
||||||
struct trace_var t;
|
struct trace_var t;
|
||||||
struct trace_var *next;
|
struct trace_var *next;
|
||||||
|
|
||||||
@ -602,7 +571,7 @@ remove_trace(entry)
|
|||||||
trace = next;
|
trace = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry->trace = t.next;
|
var->trace = t.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
@ -621,7 +590,7 @@ rb_f_untrace_var(argc, argv)
|
|||||||
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
trace = entry->trace;
|
trace = entry->var->trace;
|
||||||
if (NIL_P(cmd)) {
|
if (NIL_P(cmd)) {
|
||||||
VALUE ary = rb_ary_new();
|
VALUE ary = rb_ary_new();
|
||||||
|
|
||||||
@ -632,14 +601,14 @@ rb_f_untrace_var(argc, argv)
|
|||||||
trace = next;
|
trace = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry->block_trace) remove_trace(entry);
|
if (!entry->var->block_trace) remove_trace(entry->var);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (trace) {
|
while (trace) {
|
||||||
if (trace->data == cmd) {
|
if (trace->data == cmd) {
|
||||||
trace->removed = 1;
|
trace->removed = 1;
|
||||||
if (!entry->block_trace) remove_trace(entry);
|
if (!entry->var->block_trace) remove_trace(entry->var);
|
||||||
return rb_ary_new3(1, cmd);
|
return rb_ary_new3(1, cmd);
|
||||||
}
|
}
|
||||||
trace = trace->next;
|
trace = trace->next;
|
||||||
@ -652,7 +621,8 @@ VALUE
|
|||||||
rb_gvar_get(entry)
|
rb_gvar_get(entry)
|
||||||
struct global_entry *entry;
|
struct global_entry *entry;
|
||||||
{
|
{
|
||||||
return (*entry->getter)(entry->id, entry->data, entry);
|
struct global_variable *var = entry->var;
|
||||||
|
return (*var->getter)(entry->id, var->data, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct trace_data {
|
struct trace_data {
|
||||||
@ -674,11 +644,11 @@ trace_ev(data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
trace_en(entry)
|
trace_en(var)
|
||||||
struct global_entry *entry;
|
struct global_variable *var;
|
||||||
{
|
{
|
||||||
entry->block_trace = 0;
|
var->block_trace = 0;
|
||||||
remove_trace(entry);
|
remove_trace(var);
|
||||||
return Qnil; /* not reached */
|
return Qnil; /* not reached */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,16 +658,17 @@ rb_gvar_set(entry, val)
|
|||||||
VALUE val;
|
VALUE val;
|
||||||
{
|
{
|
||||||
struct trace_data trace;
|
struct trace_data trace;
|
||||||
|
struct global_variable *var = entry->var;
|
||||||
|
|
||||||
if (rb_safe_level() >= 4)
|
if (rb_safe_level() >= 4)
|
||||||
rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
|
rb_raise(rb_eSecurityError, "Insecure: can't change global variable value");
|
||||||
(*entry->setter)(val, entry->id, entry->data, entry);
|
(*var->setter)(val, entry->id, var->data, var);
|
||||||
|
|
||||||
if (entry->trace && !entry->block_trace) {
|
if (var->trace && !var->block_trace) {
|
||||||
entry->block_trace = 1;
|
var->block_trace = 1;
|
||||||
trace.trace = entry->trace;
|
trace.trace = var->trace;
|
||||||
trace.val = val;
|
trace.val = val;
|
||||||
rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)entry);
|
rb_ensure(trace_ev, (VALUE)&trace, trace_en, (VALUE)var);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -727,9 +698,7 @@ VALUE
|
|||||||
rb_gvar_defined(entry)
|
rb_gvar_defined(entry)
|
||||||
struct global_entry *entry;
|
struct global_entry *entry;
|
||||||
{
|
{
|
||||||
if (entry->getter == alias_getter && !alias_fixup(entry, entry->data))
|
if (entry->var->getter == undef_getter) return Qfalse;
|
||||||
entry = entry->data;
|
|
||||||
if (entry->getter == undef_getter) return Qfalse;
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,20 +738,34 @@ rb_alias_variable(name1, name2)
|
|||||||
|
|
||||||
if (rb_safe_level() >= 4)
|
if (rb_safe_level() >= 4)
|
||||||
rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
|
rb_raise(rb_eSecurityError, "Insecure: can't alias global variable");
|
||||||
entry1 = rb_global_entry(name1);
|
|
||||||
entry2 = rb_global_entry(name2);
|
|
||||||
|
|
||||||
if (entry2->getter == undef_getter) {
|
entry2 = rb_global_entry(name2);
|
||||||
entry1->data = entry2;
|
if (!st_lookup(rb_global_tbl, name1, &entry1)) {
|
||||||
entry1->getter = alias_getter;
|
entry1 = ALLOC(struct global_entry);
|
||||||
entry1->setter = alias_setter;
|
st_add_direct(rb_global_tbl, name1, entry1);
|
||||||
|
entry1->id = name1;
|
||||||
}
|
}
|
||||||
else if (!alias_fixup(entry1, entry2)) {
|
else if (entry1->var != entry2->var) {
|
||||||
entry1->data = entry2->data;
|
struct global_variable *var = entry1->var;
|
||||||
entry1->getter = entry2->getter;
|
if (var->block_trace) {
|
||||||
entry1->setter = entry2->setter;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
entry1->marker = undef_marker;
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry2->var->counter++;
|
||||||
|
entry1->var = entry2->var;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int special_generic_ivar = 0;
|
static int special_generic_ivar = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user