Nested scopes could never have worked. My fault I wrote such a buggy code,
Pavel's fault that he's never tested shadowing of declarations in the filters. cf_define_symbol() has been modified to check the scope of the symbol it's given and it if it's an already defined symbol, but in a different scope, a copy is created in the current scope and redefined to the new meaning, the consequence being that it cf_define_symbol() now returns the new symbol you need to use when assigning aux and aux2.
This commit is contained in:
parent
dab6651916
commit
04dc62a011
2 changed files with 40 additions and 21 deletions
|
@ -212,12 +212,34 @@ cf_hash(byte *c)
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct symbol *
|
||||||
|
cf_new_sym(byte *c, unsigned int h)
|
||||||
|
{
|
||||||
|
struct symbol *s, **ht;
|
||||||
|
int l;
|
||||||
|
|
||||||
|
if (!new_config->sym_hash)
|
||||||
|
new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
|
||||||
|
ht = new_config->sym_hash;
|
||||||
|
l = strlen(c);
|
||||||
|
if (l > SYM_MAX_LEN)
|
||||||
|
cf_error("Symbol too long");
|
||||||
|
s = cfg_alloc(sizeof(struct symbol) + l);
|
||||||
|
s->next = ht[h];
|
||||||
|
ht[h] = s;
|
||||||
|
s->scope = conf_this_scope;
|
||||||
|
s->class = SYM_VOID;
|
||||||
|
s->def = NULL;
|
||||||
|
s->aux = 0;
|
||||||
|
strcpy(s->name, c);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
static struct symbol *
|
static struct symbol *
|
||||||
cf_find_sym(byte *c, unsigned int h0)
|
cf_find_sym(byte *c, unsigned int h0)
|
||||||
{
|
{
|
||||||
unsigned int h = h0 & (SYM_HASH_SIZE-1);
|
unsigned int h = h0 & (SYM_HASH_SIZE-1);
|
||||||
struct symbol *s, **ht;
|
struct symbol *s, **ht;
|
||||||
int l;
|
|
||||||
|
|
||||||
if (ht = new_config->sym_hash)
|
if (ht = new_config->sym_hash)
|
||||||
{
|
{
|
||||||
|
@ -232,20 +254,7 @@ cf_find_sym(byte *c, unsigned int h0)
|
||||||
if (!strcmp(s->name, c) && s->scope->active)
|
if (!strcmp(s->name, c) && s->scope->active)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
if (!ht)
|
return cf_new_sym(c, h);
|
||||||
ht = new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
|
|
||||||
l = strlen(c);
|
|
||||||
if (l > SYM_MAX_LEN)
|
|
||||||
cf_error("Symbol too long");
|
|
||||||
s = cfg_alloc(sizeof(struct symbol) + l);
|
|
||||||
s->next = ht[h];
|
|
||||||
ht[h] = s;
|
|
||||||
s->scope = conf_this_scope;
|
|
||||||
s->class = SYM_VOID;
|
|
||||||
s->def = NULL;
|
|
||||||
s->aux = 0;
|
|
||||||
strcpy(s->name, c);
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -291,17 +300,27 @@ cf_default_name(char *template, int *counter)
|
||||||
* @type: symbol class to assign
|
* @type: symbol class to assign
|
||||||
* @def: class dependent data
|
* @def: class dependent data
|
||||||
*
|
*
|
||||||
* This function takes a symbol, checks whether it's really
|
* Defines new meaning of a symbol. If the symbol is an undefined
|
||||||
* an undefined one (else it raises an error) and assigns the
|
* one (%SYM_VOID), it's just re-defined to the new type. If it's defined
|
||||||
* given class and definition to it.
|
* in different scope, a new symbol in current scope is created and the
|
||||||
|
* meaning is assigned to it. If it's already defined in the current scope,
|
||||||
|
* an error is reported via cf_error().
|
||||||
|
*
|
||||||
|
* Result: Pointer to the newly defined symbol. If we are in the top-level
|
||||||
|
* scope, it's the same @sym as passed to the function.
|
||||||
*/
|
*/
|
||||||
void
|
struct symbol *
|
||||||
cf_define_symbol(struct symbol *sym, int type, void *def)
|
cf_define_symbol(struct symbol *sym, int type, void *def)
|
||||||
{
|
{
|
||||||
if (sym->class)
|
if (sym->class)
|
||||||
|
{
|
||||||
|
if (sym->scope == conf_this_scope)
|
||||||
cf_error("Symbol already defined");
|
cf_error("Symbol already defined");
|
||||||
|
sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
|
||||||
|
}
|
||||||
sym->class = type;
|
sym->class = type;
|
||||||
sym->def = def;
|
sym->def = def;
|
||||||
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -98,7 +98,7 @@ int cf_lex(void);
|
||||||
void cf_lex_init(int is_cli);
|
void cf_lex_init(int is_cli);
|
||||||
struct symbol *cf_find_symbol(byte *c);
|
struct symbol *cf_find_symbol(byte *c);
|
||||||
struct symbol *cf_default_name(char *template, int *counter);
|
struct symbol *cf_default_name(char *template, int *counter);
|
||||||
void cf_define_symbol(struct symbol *symbol, int type, void *def);
|
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
|
||||||
void cf_push_scope(struct symbol *);
|
void cf_push_scope(struct symbol *);
|
||||||
void cf_pop_scope(void);
|
void cf_pop_scope(void);
|
||||||
struct symbol *cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos);
|
struct symbol *cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos);
|
||||||
|
|
Loading…
Reference in a new issue