summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
Diffstat (limited to 'conf')
-rw-r--r--conf/cf-lex.l59
-rw-r--r--conf/conf.h49
-rw-r--r--conf/confbase.Y5
3 files changed, 69 insertions, 44 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 6cc09425..f1b402a0 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -539,11 +539,8 @@ cf_new_symbol(byte *c)
if (l > SYM_MAX_LEN)
cf_error("Symbol too long");
- s = cfg_alloc(sizeof(struct symbol) + l);
- s->scope = conf_this_scope;
- s->class = SYM_VOID;
- s->def = NULL;
- s->aux = 0;
+ s = cfg_allocz(sizeof(struct symbol) + l + 1);
+ *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
strcpy(s->name, c);
if (!new_config->sym_hash.data)
@@ -574,6 +571,7 @@ cf_find_symbol(struct config *cfg, byte *c)
(s = HASH_FIND(cfg->sym_hash, SYM, c, 1)))
return s;
+ /* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */
if (cfg->fallback &&
cfg->fallback->sym_hash.data &&
(s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1)))
@@ -597,6 +595,28 @@ cf_get_symbol(byte *c)
return cf_find_symbol(new_config, c) ?: cf_new_symbol(c);
}
+/**
+ * cf_localize_symbol - get the local instance of given symbol
+ * @sym: the symbol to localize
+ *
+ * This functions finds the symbol that is local to current scope
+ * for purposes of cf_define_symbol().
+ */
+struct symbol *
+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");
+
+ /* Not allocated here yet, doing it now. */
+ return cf_new_symbol(sym->name);
+}
+
struct symbol *
cf_default_name(char *template, int *counter)
{
@@ -616,35 +636,6 @@ cf_default_name(char *template, int *counter)
cf_error("Unable to generate default name");
}
-/**
- * cf_define_symbol - define meaning of a symbol
- * @sym: symbol to be defined
- * @type: symbol class to assign
- * @def: class dependent data
- *
- * 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.
- */
-struct symbol *
-cf_define_symbol(struct symbol *sym, int type, void *def)
-{
- if (sym->class)
- {
- if (sym->scope == conf_this_scope)
- cf_error("Symbol already defined");
- sym = cf_new_symbol(sym->name);
- }
- sym->class = type;
- sym->def = def;
- return sym;
-}
-
static void
cf_lex_init_kh(void)
{
diff --git a/conf/conf.h b/conf/conf.h
index 4e3addb3..21d4f1e2 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -105,11 +105,19 @@ extern int (*cf_read_hook)(byte *buf, uint max, int fd);
struct symbol {
struct symbol *next;
struct sym_scope *scope;
- int class;
- int aux;
- uint aux2;
- void *def;
- char name[1];
+ int class; /* SYM_* */
+ uint flags; /* SYM_FLAG_* */
+
+ union {
+ struct proto_config *proto; /* For SYM_PROTO and SYM_TEMPLATE */
+ const struct f_line *function; /* For SYM_FUNCTION */
+ const struct filter *filter; /* For SYM_FILTER */
+ struct rtable_config *table; /* For SYM_TABLE */
+ struct f_dynamic_attr *attribute; /* For SYM_ATTRIBUTE */
+ struct f_val *val; /* For SYM_CONSTANT or SYM_VARIABLE */
+ };
+
+ char name[0];
};
struct sym_scope {
@@ -134,8 +142,11 @@ struct sym_scope {
#define SYM_CONSTANT 0x200 /* 0x200-0x2ff are variable types */
#define SYM_CONSTANT_RANGE SYM_CONSTANT ... (SYM_CONSTANT | 0xff)
-#define SYM_TYPE(s) (((struct f_val *) (s)->def)->type)
-#define SYM_VAL(s) (((struct f_val *) (s)->def)->val)
+#define SYM_TYPE(s) ((s)->val->type)
+#define SYM_VAL(s) ((s)->val->val)
+
+/* Symbol flags */
+#define SYM_FLAG_SAME 0x1 /* For SYM_FUNCTION and SYM_FILTER */
struct include_file_stack {
void *buffer; /* Internal lexer state */
@@ -160,7 +171,29 @@ struct symbol *cf_find_symbol(struct config *cfg, byte *c);
struct symbol *cf_get_symbol(byte *c);
struct symbol *cf_default_name(char *template, int *counter);
-struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
+struct symbol *cf_localize_symbol(struct symbol *sym);
+
+/**
+ * cf_define_symbol - define meaning of a symbol
+ * @sym: symbol to be defined
+ * @type: symbol class to assign
+ * @def: class dependent data
+ *
+ * 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.
+ */
+#define cf_define_symbol(sym_, type_, var_, def_) ({ \
+ struct symbol *sym = cf_localize_symbol(sym_); \
+ sym->class = type_; \
+ sym->var_ = def_; \
+ sym; })
+
void cf_push_scope(struct symbol *);
void cf_pop_scope(void);
char *cf_symbol_class_name(struct symbol *sym);
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 2195e8fc..62415b4c 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -56,7 +56,8 @@ CF_DECLS
struct f_dynamic_attr fda;
struct f_static_attr fsa;
struct f_lval flv;
- struct filter *f;
+ const struct f_line *fl;
+ const struct filter *f;
struct f_tree *e;
struct f_trie *trie;
struct f_val v;
@@ -130,7 +131,7 @@ definition:
DEFINE CF_SYM_VOID '=' term ';' {
struct f_val *val = cfg_alloc(sizeof(struct f_val));
if (f_eval(f_postfixify($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
- cf_define_symbol($2, SYM_CONSTANT | val->type, val);
+ cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
}
;