summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
Diffstat (limited to 'conf')
-rw-r--r--conf/cf-lex.l58
-rw-r--r--conf/conf.h9
-rw-r--r--conf/confbase.Y5
3 files changed, 66 insertions, 6 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index c9d2f5a5..d6f46223 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -574,6 +574,8 @@ check_eof(void)
return 0;
}
+static inline void cf_swap_soft_scope(void);
+
static struct symbol *
cf_new_symbol(const byte *c)
{
@@ -583,6 +585,8 @@ cf_new_symbol(const byte *c)
if (l > SYM_MAX_LEN)
cf_error("Symbol too long");
+ cf_swap_soft_scope();
+
s = cfg_allocz(sizeof(struct symbol) + l + 1);
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
strcpy(s->name, c);
@@ -654,10 +658,10 @@ cf_localize_symbol(struct symbol *sym)
/* If the symbol type is void, it has been recently allocated just in this scope. */
if (!sym->class)
return sym;
-
+
/* If the scope is the current, it is already defined in this scope. */
- if (sym->scope == conf_this_scope)
- cf_error("Symbol already defined");
+ if (cf_symbol_is_local(sym))
+ cf_error("Symbol '%s' already defined", sym->name);
/* Not allocated here yet, doing it now. */
return cf_new_symbol(sym->name);
@@ -787,6 +791,8 @@ cf_push_scope(struct symbol *sym)
void
cf_pop_scope(void)
{
+ ASSERT(!conf_this_scope->soft_scopes);
+
conf_this_scope->active = 0;
conf_this_scope = conf_this_scope->next;
@@ -794,6 +800,52 @@ cf_pop_scope(void)
}
/**
+ * cf_push_soft_scope - enter new soft scope
+ *
+ * If we want to enter a new anonymous scope that most likely will not contain
+ * any symbols, we can use cf_push_soft_scope() insteas of cf_push_scope().
+ * Such scope will be converted to a regular scope on first use.
+ */
+void
+cf_push_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes < 0xfe)
+ conf_this_scope->soft_scopes++;
+ else
+ cf_push_scope(NULL);
+}
+
+/**
+ * cf_pop_soft_scope - leave a soft scope
+ *
+ * Leave a soft scope entered by cf_push_soft_scope().
+ */
+void
+cf_pop_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes)
+ conf_this_scope->soft_scopes--;
+ else
+ cf_pop_scope();
+}
+
+/**
+ * cf_swap_soft_scope - convert soft scope to regular scope
+ *
+ * Soft scopes cannot hold symbols, so they must be converted to regular scopes
+ * on first use. It is done automatically by cf_new_symbol().
+ */
+static inline void
+cf_swap_soft_scope(void)
+{
+ if (conf_this_scope->soft_scopes)
+ {
+ conf_this_scope->soft_scopes--;
+ cf_push_scope(NULL);
+ }
+}
+
+/**
* cf_symbol_class_name - get name of a symbol class
* @sym: symbol
*
diff --git a/conf/conf.h b/conf/conf.h
index 55cb9c58..e0f94b63 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -134,7 +134,8 @@ struct sym_scope {
struct sym_scope *next; /* Next on scope stack */
struct symbol *name; /* Name of this scope */
uint slots; /* Variable slots */
- int active; /* Currently entered */
+ byte active; /* Currently entered */
+ byte soft_scopes; /* Number of soft scopes above */
};
struct bytestring {
@@ -191,6 +192,9 @@ struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_localize_symbol(struct symbol *sym);
+static inline int cf_symbol_is_local(struct symbol *sym)
+{ return (sym->scope == conf_this_scope) && !conf_this_scope->soft_scopes; }
+
/**
* cf_define_symbol - define meaning of a symbol
* @sym: symbol to be defined
@@ -214,6 +218,9 @@ struct symbol *cf_localize_symbol(struct symbol *sym);
void cf_push_scope(struct symbol *);
void cf_pop_scope(void);
+void cf_push_soft_scope(void);
+void cf_pop_soft_scope(void);
+
char *cf_symbol_class_name(struct symbol *sym);
/* Parser */
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 5f45c507..1d5738ff 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -75,6 +75,7 @@ CF_DECLS
struct f_static_attr fsa;
struct f_lval flv;
struct f_line *fl;
+ struct f_arg *fa;
const struct filter *f;
struct f_tree *e;
struct f_trie *trie;
@@ -152,14 +153,14 @@ conf: definition ;
definition:
DEFINE symbol '=' term ';' {
struct f_val *val = cfg_allocz(sizeof(struct f_val));
- if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
+ if (f_eval(f_linearize($4, 1), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
}
;
expr:
NUM
- | '(' term ')' { $$ = f_eval_int(f_linearize($2)); }
+ | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); }
| CF_SYM_KNOWN {
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
$$ = SYM_VAL($1).i; }