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 analyzer
12 * The lexical analyzer used for configuration files and CLI commands
13 * is generated using the |flex| tool accompanied by 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 lexical scope, symbol class (%SYM_PROTO for a
19 * name of a protocol, %SYM_CONSTANT for a constant etc.) and class
20 * dependent data. When an unknown symbol is encountered, it's
21 * automatically added to the 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 */
39 #include <sys/types.h>
44 #include "nest/bird.h"
45 #include "nest/route.h"
46 #include "nest/protocol.h"
47 #include "filter/filter.h"
48 #include "filter/f-inst.h"
49 #include "conf/conf.h"
50 #include "conf/cf-parse.tab.h"
51 #include "lib/string.h"
60 #include "conf/keywords.h"
62 /* Could be defined by Bison in cf-parse.tab.h, inteferes with SYM hash */
68 static uint cf_hash(const byte *c);
70 #define KW_KEY(n) n->name
71 #define KW_NEXT(n) n->next
72 #define KW_EQ(a,b) !strcmp(a,b)
73 #define KW_FN(k) cf_hash(k)
74 #define KW_ORDER 8 /* Fixed */
76 #define SYM_KEY(n) n->name, n->scope->active
77 #define SYM_NEXT(n) n->next
78 #define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2
79 #define SYM_FN(k,s) cf_hash(k)
80 #define SYM_ORDER 6 /* Initial */
82 #define SYM_REHASH sym_rehash
83 #define SYM_PARAMS /8, *1, 2, 2, 6, 20
86 HASH_DEFINE_REHASH_FN(SYM, struct symbol)
88 HASH(struct keyword) kw_hash;
91 struct sym_scope *conf_this_scope;
95 int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
96 struct include_file_stack *ifs;
97 static struct include_file_stack *ifs_head;
99 #define QUOTED_BUFFER_SIZE 4096
100 static BUFFER_(char) quoted_buffer;
101 static char quoted_buffer_data[QUOTED_BUFFER_SIZE];
102 static inline void quoted_buffer_init(void) {
103 quoted_buffer.used = 0;
104 quoted_buffer.size = QUOTED_BUFFER_SIZE;
105 quoted_buffer.data = quoted_buffer_data;
108 #define MAX_INCLUDE_DEPTH 8
110 #define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd);
112 #define YY_FATAL_ERROR(msg) cf_error(msg)
113 #define YY_USER_ACTION ifs->chno += yyleng; ifs->toklen = yyleng;
115 static void cf_include(char *arg, int alen);
116 static int check_eof(void);
118 static enum yytokentype cf_lex_symbol(const char *data);
127 %x COMMENT CCOMM CLI QUOTED APOSTROPHED INCLUDE
136 ^{WHITE}*include{WHITE}*\" {
138 cf_error("Include not allowed in CLI");
143 <INCLUDE>[^"\n]+["]{WHITE}*; {
148 end = strchr(start, '"');
152 cf_error("Include with empty argument");
154 cf_include(start, end-start);
159 <INCLUDE>["] cf_error("Include with empty argument");
160 <INCLUDE>. cf_error("Unterminated include");
161 <INCLUDE>\n cf_error("Unterminated include");
162 <INCLUDE><<EOF>> cf_error("Unterminated include");
166 uint len1 UNUSED, len2;
171 l = bstrtoul10(yytext, &e);
172 if (e && (*e != ':') || (errno == ERANGE) || (l >> 32))
173 cf_error("ASN out of range");
179 cf_lval.i64 = (2ULL << 48) | (((u64) l) << len2);
185 cf_lval.i64 = 0 | (((u64) l) << len2);
189 l = bstrtoul10(e+1, &e);
190 if (e && *e || (errno == ERANGE) || (l >> len2))
191 cf_error("Number out of range");
197 [02]:{DIGIT}+:{DIGIT}+ {
202 if (yytext[0] == '0')
210 cf_lval.i64 = 2ULL << 48;
216 l = bstrtoul10(yytext+2, &e);
217 if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
218 cf_error("ASN out of range");
219 cf_lval.i64 |= ((u64) l) << len2;
222 l = bstrtoul10(e+1, &e);
223 if (e && *e || (errno == ERANGE) || (l >> len2))
224 cf_error("Number out of range");
230 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
235 cf_lval.i64 = 1ULL << 48;
237 e = strchr(yytext, ':');
239 if (!ip4_pton(yytext, &ip4))
240 cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext);
241 cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
244 l = bstrtoul10(e, &e);
245 if (e && *e || (errno == ERANGE) || (l >> 16))
246 cf_error("Number out of range");
252 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
253 if (!ip4_pton(yytext, &cf_lval.ip4))
254 cf_error("Invalid IPv4 address %s", yytext);
258 ({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
259 if (!ip6_pton(yytext, &cf_lval.ip6))
260 cf_error("Invalid IPv6 address %s", yytext);
268 l = bstrtoul16(yytext+2, &e);
269 if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
270 cf_error("Number out of range");
279 l = bstrtoul10(yytext, &e);
280 if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
281 cf_error("Number out of range");
287 /* Hack to distinguish if..else from else: in case */
293 quoted_buffer_init();
296 <APOSTROPHED>{ALNUM}|[-]|[.:] BUFFER_PUSH(quoted_buffer) = yytext[0];
297 <APOSTROPHED>\n cf_error("Unterminated symbol");
298 <APOSTROPHED><<EOF>> cf_error("Unterminated symbol");
301 BUFFER_PUSH(quoted_buffer) = 0;
302 return cf_lex_symbol(quoted_buffer_data);
304 <APOSTROPHED>. cf_error("Invalid character in apostrophed symbol");
307 return cf_lex_symbol(yytext);
319 [={}:;,.()+*/%<>~\[\]?!\|-] {
325 quoted_buffer_init();
328 <QUOTED>\n cf_error("Unterminated string");
329 <QUOTED><<EOF>> cf_error("Unterminated string");
332 BUFFER_PUSH(quoted_buffer) = 0;
333 cf_lval.t = cfg_strdup(quoted_buffer_data);
337 <QUOTED>. BUFFER_PUSH(quoted_buffer) = yytext[0];
339 <INITIAL,COMMENT><<EOF>> { if (check_eof()) return END; }
343 \n ifs->lino++; ifs->chno = 0;
349 . cf_error("Unknown character");
359 <CCOMM>\*\/ BEGIN(INITIAL);
360 <CCOMM>\n ifs->lino++; ifs->chno = 0;
361 <CCOMM>\/\* cf_error("Comment nesting not supported");
362 <CCOMM><<EOF>> cf_error("Unterminated comment");
378 cf_hash(const byte *c)
383 h = h + (h >> 2) + (h >> 5) + ((uint) *c++ << 24);
388 * IFS stack - it contains structures needed for recursive processing
389 * of include in config files. On the top of the stack is a structure
390 * for currently processed file. Other structures are either for
391 * active files interrupted because of include directive (these have
392 * fd and flex buffer) or for inactive files scheduled to be processed
393 * later (when parent requested including of several files by wildcard
394 * match - these do not have fd and flex buffer yet).
396 * FIXME: Most of these ifs and include functions are really sysdep/unix.
399 static struct include_file_stack *
400 push_ifs(struct include_file_stack *old)
402 struct include_file_stack *ret;
403 ret = cfg_allocz(sizeof(struct include_file_stack));
409 static struct include_file_stack *
410 pop_ifs(struct include_file_stack *old)
412 yy_delete_buffer(old->buffer);
418 enter_ifs(struct include_file_stack *new)
422 new->fd = open(new->file_name, O_RDONLY);
426 cf_error("Unable to open included file %s: %m", new->file_name);
429 new->buffer = yy_create_buffer(NULL, YY_BUF_SIZE);
432 yy_switch_to_buffer(new->buffer);
436 * cf_lex_unwind - unwind lexer state during error
438 * cf_lex_unwind() frees the internal state on IFS stack when the lexical
439 * analyzer is terminated by cf_error().
444 struct include_file_stack *n;
446 for (n = ifs; n != ifs_head; n = n->prev)
448 /* Memory is freed automatically */
450 yy_delete_buffer(n->buffer);
459 cf_include(char *arg, int alen)
461 struct include_file_stack *base_ifs = ifs;
462 int new_depth, rv, i;
466 new_depth = ifs->depth + 1;
467 if (new_depth > MAX_INCLUDE_DEPTH)
468 cf_error("Max include depth reached");
470 /* expand arg to properly handle relative filenames */
473 int dlen = strlen(ifs->file_name);
474 char *dir = alloca(dlen + 1);
475 patt = alloca(dlen + alen + 2);
476 memcpy(dir, ifs->file_name, dlen + 1);
477 sprintf(patt, "%s/%s", dirname(dir), arg);
482 /* Skip globbing if there are no wildcards, mainly to get proper
483 response when the included config file is missing */
484 if (!strpbrk(arg, "?*["))
487 ifs->file_name = cfg_strdup(patt);
488 ifs->depth = new_depth;
494 /* Expand the pattern */
495 rv = glob(patt, GLOB_ERR | GLOB_NOESCAPE, NULL, &g);
496 if (rv == GLOB_ABORTED)
497 cf_error("Unable to match pattern %s: %m", patt);
498 if ((rv != 0) || (g.gl_pathc <= 0))
502 * Now we put all found files to ifs stack in reverse order, they
503 * will be activated and processed in order as ifs stack is popped
504 * by pop_ifs() and enter_ifs() in check_eof().
506 for(i = g.gl_pathc - 1; i >= 0; i--)
508 char *fname = g.gl_pathv[i];
511 if (stat(fname, &fs) < 0)
514 cf_error("Unable to stat included file %s: %m", fname);
517 if (fs.st_mode & S_IFDIR)
520 /* Prepare new stack item */
522 ifs->file_name = cfg_strdup(fname);
523 ifs->depth = new_depth;
536 /* EOF in main config file */
537 ifs->lino = 1; /* Why this? */
546 static struct symbol *
547 cf_new_symbol(const byte *c)
553 cf_error("Symbol too long");
555 s = cfg_allocz(sizeof(struct symbol) + l + 1);
556 *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
559 if (!new_config->sym_hash.data)
560 HASH_INIT(new_config->sym_hash, new_config->pool, SYM_ORDER);
562 HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s);
564 add_tail(&(new_config->symbols), &(s->n));
570 * cf_find_symbol - find a symbol by name
571 * @cfg: specificed config
574 * This functions searches the symbol table in the config @cfg for a symbol of
575 * given name. First it examines the current scope, then the second recent one
576 * and so on until it either finds the symbol and returns a pointer to its
577 * &symbol structure or reaches the end of the scope chain and returns %NULL to
581 cf_find_symbol(const struct config *cfg, const byte *c)
585 if (cfg->sym_hash.data &&
586 (s = HASH_FIND(cfg->sym_hash, SYM, c, 1)))
589 /* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */
591 cfg->fallback->sym_hash.data &&
592 (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1)))
599 * cf_get_symbol - get a symbol by name
602 * This functions searches the symbol table of the currently parsed config
603 * (@new_config) for a symbol of given name. It returns either the already
604 * existing symbol or a newly allocated undefined (%SYM_VOID) symbol if no
605 * existing symbol is found.
608 cf_get_symbol(const byte *c)
610 return cf_find_symbol(new_config, c) ?: cf_new_symbol(c);
614 * cf_localize_symbol - get the local instance of given symbol
615 * @sym: the symbol to localize
617 * This functions finds the symbol that is local to current scope
618 * for purposes of cf_define_symbol().
621 cf_localize_symbol(struct symbol *sym)
623 /* If the symbol type is void, it has been recently allocated just in this scope. */
627 /* If the scope is the current, it is already defined in this scope. */
628 if (sym->scope == conf_this_scope)
629 cf_error("Symbol already defined");
631 /* Not allocated here yet, doing it now. */
632 return cf_new_symbol(sym->name);
636 cf_default_name(char *template, int *counter)
638 char buf[SYM_MAX_LEN];
640 char *perc = strchr(template, '%');
644 bsprintf(buf, template, ++(*counter));
645 s = cf_get_symbol(buf);
646 if (s->class == SYM_VOID)
651 cf_error("Unable to generate default name");
654 static enum yytokentype
655 cf_lex_symbol(const char *data)
657 /* Have we defined such a symbol? */
658 struct symbol *sym = cf_get_symbol(data);
661 if (sym->class != SYM_VOID)
664 /* Is it a keyword? */
665 struct keyword *k = HASH_FIND(kw_hash, KW, data);
672 cf_lval.i = -k->value;
677 /* OK, undefined symbol */
679 return CF_SYM_UNDEFINED;
685 HASH_INIT(kw_hash, &root_pool, KW_ORDER);
688 for (k=keyword_list; k->name; k++)
689 HASH_INSERT(kw_hash, KW, k);
693 * cf_lex_init - initialize the lexer
694 * @is_cli: true if we're going to parse CLI command, false for configuration
695 * @c: configuration structure
697 * cf_lex_init() initializes the lexical analyzer and prepares it for
698 * parsing of a new input.
701 cf_lex_init(int is_cli, struct config *c)
706 ifs_head = ifs = push_ifs(NULL);
709 ifs->file_name = c->file_name;
710 ifs->fd = c->file_fd;
715 ifs->buffer = YY_CURRENT_BUFFER;
722 c->root_scope = cfg_allocz(sizeof(struct sym_scope));
723 conf_this_scope = c->root_scope;
724 conf_this_scope->active = 1;
728 * cf_push_scope - enter new scope
729 * @sym: symbol representing scope name
731 * If we want to enter a new scope to process declarations inside
732 * a nested block, we can just call cf_push_scope() to push a new
733 * scope onto the scope stack which will cause all new symbols to be
734 * defined in this scope and all existing symbols to be sought for
735 * in all scopes stored on the stack.
738 cf_push_scope(struct symbol *sym)
740 struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
742 s->next = conf_this_scope;
750 * cf_pop_scope - leave a scope
752 * cf_pop_scope() pops the topmost scope from the scope stack,
753 * leaving all its symbols in the symbol table, but making them
754 * invisible to the rest of the config.
759 conf_this_scope->active = 0;
760 conf_this_scope = conf_this_scope->next;
762 ASSERT(conf_this_scope);
766 * cf_symbol_class_name - get name of a symbol class
769 * This function returns a string representing the class
770 * of the given symbol.
773 cf_symbol_class_name(struct symbol *sym)
782 return "protocol template";
788 return "routing table";
790 return "custom attribute";
791 case SYM_CONSTANT_RANGE:
793 case SYM_VARIABLE_RANGE:
796 return "unknown type";
804 * Both the configuration and CLI commands are analyzed using a syntax
805 * driven parser generated by the |bison| tool from a grammar which
806 * is constructed from information gathered from grammar snippets by
807 * the |gen_parser.m4| script.
809 * Grammar snippets are files (usually with extension |.Y|) contributed
810 * by various BIRD modules in order to provide information about syntax of their
811 * configuration and their CLI commands. Each snipped consists of several
812 * sections, each of them starting with a special keyword: |CF_HDR| for
813 * a list of |#include| directives needed by the C code, |CF_DEFINES|
814 * for a list of C declarations, |CF_DECLS| for |bison| declarations
815 * including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR|
816 * for the grammar rules, |CF_CODE| for auxiliary C code and finally
817 * |CF_END| at the end of the snippet.
819 * To create references between the snippets, it's possible to define
820 * multi-part rules by utilizing the |CF_ADDTO| macro which adds a new
821 * alternative to a multi-part rule.
823 * CLI commands are defined using a |CF_CLI| macro. Its parameters are:
824 * the list of keywords determining the command, the list of parameters,
825 * help text for the parameters and help text for the command.
827 * Values of |enum| filter types can be defined using |CF_ENUM| with
828 * the following parameters: name of filter type, prefix common for all
829 * literals of this type and names of all the possible values.