2 * BIRD -- Configuration Lexer
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
10 * DOC: Lexical analyser
12 * The lexical analyser used for configuration files and CLI commands
13 * is generated using the |flex| tool accompanied with a couple of
14 * functions maintaining the hash tables containing information about
15 * symbols and keywords.
17 * Each symbol is represented by a &symbol structure containing name
18 * of the symbol, its scope, symbol class (%SYM_PROTO for a name of a protocol,
19 * %SYM_NUMBER for a numeric constant etc.) and class dependent data.
20 * When an unknown symbol is encountered, it's automatically added to the
21 * symbol table with class %SYM_VOID.
23 * The keyword tables are generated from the grammar templates
24 * using the |gen_keywords.m4| script.
28 #undef REJECT /* Avoid name clashes */
34 #include "nest/bird.h"
35 #include "nest/route.h"
36 #include "filter/filter.h"
37 #include "conf/conf.h"
38 #include "conf/cf-parse.tab.h"
39 #include "lib/string.h"
47 #include "conf/keywords.h"
49 #define KW_HASH_SIZE 64
50 static struct keyword *kw_hash[KW_HASH_SIZE];
51 static int kw_hash_inited;
53 #define SYM_HASH_SIZE 128
54 #define SYM_MAX_LEN 32
57 struct sym_scope *next; /* Next on scope stack */
58 struct symbol *name; /* Name of this scope */
59 int active; /* Currently entered */
61 static struct sym_scope *conf_this_scope;
65 static int cf_hash(byte *c);
66 static struct symbol *cf_find_sym(byte *c, unsigned int h0);
70 int (*cf_read_hook)(byte *buf, unsigned int max);
72 #define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
74 #define YY_FATAL_ERROR(msg) cf_error(msg)
90 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
92 if (ipv4_pton_u32(yytext, &cf_lval.i32))
94 cf_error("Invalid IPv4 address %s", yytext);
96 if (ip_pton(yytext, &cf_lval.a))
98 cf_error("Invalid IP address %s", yytext);
102 ({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
104 if (ip_pton(yytext, &cf_lval.a))
106 cf_error("Invalid IP address %s", yytext);
108 cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
116 l = strtoul(yytext+2, &e, 16);
117 if (e && *e || errno == ERANGE || (long int)(int) l != l)
118 cf_error("Number out of range");
127 l = strtoul(yytext, &e, 10);
128 if (e && *e || errno == ERANGE || (long int)(int) l != l)
129 cf_error("Number out of range");
135 unsigned int h = cf_hash(yytext);
136 struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)];
139 if (!strcmp(k->name, yytext))
145 cf_lval.i = -k->value;
151 cf_lval.s = cf_find_sym(yytext, h);
160 [={}:;,.()+*/%<>~\[\]?!-] {
165 yytext[yyleng-1] = 0;
166 cf_lval.t = cfg_strdup(yytext+1);
170 ["][^"\n]*\n cf_error("Unterminated string");
172 <INITIAL,COMMENT><<EOF>> return END;
182 . cf_error("Unknown character");
191 <CCOMM>\*\/ BEGIN(INITIAL);
192 <CCOMM>\n conf_lino++;
193 <CCOMM>\/\* cf_error("Comment nesting not supported");
194 <CCOMM><<EOF>> cf_error("Unterminated comment");
215 static struct symbol *
216 cf_new_sym(byte *c, unsigned int h)
218 struct symbol *s, **ht;
221 if (!new_config->sym_hash)
222 new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
223 ht = new_config->sym_hash;
226 cf_error("Symbol too long");
227 s = cfg_alloc(sizeof(struct symbol) + l);
230 s->scope = conf_this_scope;
238 static struct symbol *
239 cf_find_sym(byte *c, unsigned int h0)
241 unsigned int h = h0 & (SYM_HASH_SIZE-1);
242 struct symbol *s, **ht;
244 if (ht = new_config->sym_hash)
246 for(s = ht[h]; s; s=s->next)
247 if (!strcmp(s->name, c) && s->scope->active)
250 if (new_config->sym_fallback)
252 /* We know only top-level scope is active */
253 for(s = new_config->sym_fallback[h]; s; s=s->next)
254 if (!strcmp(s->name, c) && s->scope->active)
257 return cf_new_sym(c, h);
261 * cf_find_symbol - find a symbol by name
264 * This functions searches the symbol table for a symbol of given
265 * name. First it examines the current scope, then the second recent
266 * one and so on until it either finds the symbol and returns a pointer
267 * to its &symbol structure or reaches the end of the scope chain
268 * and returns %NULL to signify no match.
271 cf_find_symbol(byte *c)
273 return cf_find_sym(c, cf_hash(c));
277 cf_default_name(char *template, int *counter)
281 char *perc = strchr(template, '%');
285 bsprintf(buf, template, ++(*counter));
286 s = cf_find_sym(buf, cf_hash(buf));
289 if (s->class == SYM_VOID)
294 cf_error("Unable to generate default name");
298 * cf_define_symbol - define meaning of a symbol
299 * @sym: symbol to be defined
300 * @type: symbol class to assign
301 * @def: class dependent data
303 * Defines new meaning of a symbol. If the symbol is an undefined
304 * one (%SYM_VOID), it's just re-defined to the new type. If it's defined
305 * in different scope, a new symbol in current scope is created and the
306 * meaning is assigned to it. If it's already defined in the current scope,
307 * an error is reported via cf_error().
309 * Result: Pointer to the newly defined symbol. If we are in the top-level
310 * scope, it's the same @sym as passed to the function.
313 cf_define_symbol(struct symbol *sym, int type, void *def)
317 if (sym->scope == conf_this_scope)
318 cf_error("Symbol already defined");
319 sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
331 for(k=keyword_list; k->name; k++)
333 unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1);
334 k->next = kw_hash[h];
341 * cf_lex_init - initialize the lexer
342 * @is_cli: true if we're going to parse CLI command, false for configuration
344 * cf_lex_init() initializes the lexical analyser and prepares it for
345 * parsing of a new input.
348 cf_lex_init(int is_cli)
358 conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
359 conf_this_scope->active = 1;
363 * cf_push_scope - enter new scope
364 * @sym: symbol representing scope name
366 * If we want to enter a new scope to process declarations inside
367 * a nested block, we can just call cf_push_scope() to push a new
368 * scope onto the scope stack which will cause all new symbols to be
369 * defined in this scope and all existing symbols to be sought for
370 * in all scopes stored on the stack.
373 cf_push_scope(struct symbol *sym)
375 struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
377 s->next = conf_this_scope;
384 * cf_pop_scope - leave a scope
386 * cf_pop_scope() pops the topmost scope from the scope stack,
387 * leaving all its symbols in the symbol table, but making them
388 * invisible to the rest of the config.
393 conf_this_scope->active = 0;
394 conf_this_scope = conf_this_scope->next;
395 ASSERT(conf_this_scope);
399 cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos)
405 if (*pos >= SYM_HASH_SIZE)
407 sym = cf->sym_hash[(*pos)++];
411 if (sym && sym->scope->active)
417 * cf_symbol_class_name - get name of a symbol class
420 * This function returns a string representing the class
421 * of the given symbol.
424 cf_symbol_class_name(struct symbol *sym)
433 return "numeric constant";
439 return "routing table";
441 return "network address";
443 return "unknown type";
451 * Both the configuration and CLI commands are analysed using a syntax
452 * driven parser generated by the |bison| tool from a grammar which
453 * is constructed from information gathered from grammar snippets by
454 * the |gen_parser.m4| script.
456 * Grammar snippets are files (usually with extension |.Y|) contributed
457 * by various BIRD modules to provide information about syntax of their
458 * configuration and their CLI commands. Each snipped consists of several
459 * section, each of them starting with a special keyword: |CF_HDR| for
460 * a list of |#include| directives needed by the C code, |CF_DEFINES|
461 * for a list of C declarations, |CF_DECLS| for |bison| declarations
462 * including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR|
463 * for the grammar rules, |CF_CODE| for auxillary C code and finally
464 * |CF_END| at the end of the snippet.
466 * To create references between the snippets, it's possible to define
467 * multi-part rules by utilizing the |CF_ADDTO| macro which adds a new
468 * alternative to a multi-part rule.
470 * CLI commands are defined using a |CF_CLI| macro. Its parameters are:
471 * the list of keywords determining the command, the list of paramaters,
472 * help text for the parameters and help text for the command.
474 * Values of |enum| filter types can be defined using |CF_ENUM| with
475 * the following parameters: name of filter type, prefix common for all
476 * literals of this type, names of all the possible values.