diff options
Diffstat (limited to 'conf')
-rw-r--r-- | conf/cf-lex.l | 59 | ||||
-rw-r--r-- | conf/conf.h | 49 | ||||
-rw-r--r-- | conf/confbase.Y | 5 |
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); } ; |