]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nested scopes could never have worked. My fault I wrote such a buggy code,
authorMartin Mares <mj@ucw.cz>
Sun, 4 Jun 2000 19:30:13 +0000 (19:30 +0000)
committerMartin Mares <mj@ucw.cz>
Sun, 4 Jun 2000 19:30:13 +0000 (19:30 +0000)
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.

conf/cf-lex.l
conf/conf.h

index 8f8fcfbdebf741b30a295ee5877f6a378b488c72..9ded49c523573ef126a63c90cb5184ff0f8bcd63 100644 (file)
@@ -212,12 +212,34 @@ cf_hash(byte *c)
   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 *
 cf_find_sym(byte *c, unsigned int h0)
 {
   unsigned int h = h0 & (SYM_HASH_SIZE-1);
   struct symbol *s, **ht;
-  int l;
 
   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)
          return s;
     }
-  if (!ht)
-    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;
+  return cf_new_sym(c, h);
 }
 
 /**
@@ -291,17 +300,27 @@ cf_default_name(char *template, int *counter)
  * @type: symbol class to assign
  * @def: class dependent data
  *
- * This function takes a symbol, checks whether it's really
- * an undefined one (else it raises an error) and assigns the
- * given class and definition to it.
+ * Defines new meaning of a symbol. If the symbol is an undefined
+ * one (%SYM_VOID), it's just re-defined to the new type. If it's defined
+ * 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)
 {
   if (sym->class)
-    cf_error("Symbol already defined");
+    {
+      if (sym->scope == conf_this_scope)
+       cf_error("Symbol already defined");
+      sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
+    }
   sym->class = type;
   sym->def = def;
+  return sym;
 }
 
 static void
index 24e3217d19ebd02703e58673dff70639ef4e4c84..5d5e4bc528e8a6a8164b1f0b471a3ee802f66ca1 100644 (file)
@@ -98,7 +98,7 @@ int cf_lex(void);
 void cf_lex_init(int is_cli);
 struct symbol *cf_find_symbol(byte *c);
 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_pop_scope(void);
 struct symbol *cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos);