diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 179b66a4..20399165 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -79,7 +79,8 @@ static uint cf_hash(const byte *c); HASH_DEFINE_REHASH_FN(SYM, struct symbol) /* Global symbol scopes */ -static pool *global_root_scope_pool; +pool *global_root_scope_pool; +linpool *global_root_scope_linpool; static struct sym_scope global_root_scope = { .active = 1, @@ -567,7 +568,7 @@ check_eof(void) static inline void cf_swap_soft_scope(struct config *conf); -static struct symbol * +struct symbol * cf_new_symbol(struct sym_scope *scope, pool *p, struct linpool *lp, const byte *c) { if (scope->readonly) @@ -594,14 +595,20 @@ cf_new_symbol(struct sym_scope *scope, pool *p, struct linpool *lp, const byte * return s; } -static struct symbol * +struct symbol * cf_root_symbol(const byte *c, struct sym_scope *ss) { uint l = strlen(c); if (l > SYM_MAX_LEN) bug("Root symbol %s too long", c); - struct symbol *s = mb_alloc(&root_pool, sizeof(struct symbol) + l + 1); + if (!global_root_scope_pool) + { + global_root_scope_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Keywords pool"); + global_root_scope_linpool = lp_new(global_root_scope_pool); + } + + struct symbol *s = lp_alloc(global_root_scope_linpool, sizeof(struct symbol) + l + 1); *s = (struct symbol) { .scope = ss, .class = SYM_VOID, }; memcpy(s->name, c, l+1); @@ -715,6 +722,8 @@ cf_lex_symbol(const char *data) cf_lval.i = -val; return ENUM; } + case SYM_METHOD: + return sym->method->arg_num ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE; case SYM_VOID: return CF_SYM_UNDEFINED; default: @@ -753,6 +762,8 @@ ea_class_find_by_name(const char *name) return sym->attribute; } +void f_type_methods_register(void); + /** * cf_lex_init - initialize the lexer * @is_cli: true if we're going to parse CLI command, false for configuration @@ -764,10 +775,8 @@ ea_class_find_by_name(const char *name) void cf_lex_init(int is_cli, struct config *c) { - if (!global_root_scope_pool) + if (!global_root_scope.readonly) { - global_root_scope_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Keywords pool"); - for (const struct keyword *k = keyword_list; k->name; k++) { struct symbol *s = cf_root_symbol(k->name, &global_root_scope); @@ -777,6 +786,8 @@ cf_lex_init(int is_cli, struct config *c) global_root_scope.readonly = 1; global_filter_scope.readonly = 1; + + f_type_methods_register(); } ifs_head = ifs = push_ifs(NULL); diff --git a/conf/conf.h b/conf/conf.h index f7833d9e..762ba3c1 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -81,6 +81,7 @@ int config_status(void); btime config_timer_status(void); void config_init(void); void cf_error(const char *msg, ...) NORET; +#define cf_warn(msg, args...) log(L_WARN "%s:%d:%d: " msg, ifs->file_name, ifs->lino, ifs->chno - ifs->toklen + 1, ##args) void config_add_obstacle(struct config *); void config_del_obstacle(struct config *); void order_shutdown(int gr); @@ -129,6 +130,7 @@ struct symbol { struct f_val *val; /* For SYM_CONSTANT */ uint offset; /* For SYM_VARIABLE */ const struct keyword *keyword; /* For SYM_KEYWORD */ + const struct f_method *method; /* For SYM_METHOD */ }; char name[0]; @@ -150,6 +152,9 @@ struct sym_scope { void cf_enter_filters(void); void cf_exit_filters(void); +extern pool *global_root_scope_pool; +extern linpool *global_root_scope_linpool; + struct bytestring { size_t length; byte data[]; @@ -166,6 +171,7 @@ struct bytestring { #define SYM_TABLE 5 #define SYM_ATTRIBUTE 6 #define SYM_KEYWORD 7 +#define SYM_METHOD 8 #define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */ #define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff) @@ -213,6 +219,10 @@ struct symbol *cf_localize_symbol(struct config *conf, struct symbol *sym); static inline int cf_symbol_is_local(struct config *conf, struct symbol *sym) { return (sym->scope == conf->current_scope) && !conf->current_scope->soft_scopes; } +/* internal */ +struct symbol *cf_new_symbol(struct sym_scope *scope, pool *p, struct linpool *lp, const byte *c); +struct symbol *cf_root_symbol(const byte *, struct sym_scope *); + /** * cf_define_symbol - define meaning of a symbol * @sym: symbol to be defined diff --git a/conf/confbase.Y b/conf/confbase.Y index eaa57541..d86c2ef5 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -106,7 +106,7 @@ CF_DECLS %token IP4 %token IP6 %token VPN_RD -%token CF_SYM_KNOWN CF_SYM_UNDEFINED +%token CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS %token TEXT %token BYTETEXT %type ipa_scope @@ -137,7 +137,7 @@ CF_DECLS %start config -CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM) +CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS) CF_GRAMMAR diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4 index af4b1455..b7167d7a 100644 --- a/conf/gen_parser.m4 +++ b/conf/gen_parser.m4 @@ -33,6 +33,8 @@ m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)') m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])') m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks )DNL') +m4_define(CF_METHODS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks +)DNL') # CLI commands m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL diff --git a/doc/bird.sgml b/doc/bird.sgml index 7487e4f8..f11b4cbe 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -551,7 +551,7 @@ include "tablename.conf";; Define a filter. You can learn more about filters in the following chapter. -