]> git.ipfire.org Git - thirdparty/bird.git/blob - conf/cf-lex.l
Nested scopes could never have worked. My fault I wrote such a buggy code,
[thirdparty/bird.git] / conf / cf-lex.l
1 /*
2 * BIRD -- Configuration Lexer
3 *
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 /**
10 * DOC: Lexical analyser
11 *
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.
16 *
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.
22 *
23 * The keyword tables are generated from the grammar templates
24 * using the |gen_keywords.m4| script.
25 */
26
27 %{
28 #undef REJECT /* Avoid name clashes */
29
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33
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"
40
41 struct keyword {
42 byte *name;
43 int value;
44 struct keyword *next;
45 };
46
47 #include "conf/keywords.h"
48
49 #define KW_HASH_SIZE 64
50 static struct keyword *kw_hash[KW_HASH_SIZE];
51 static int kw_hash_inited;
52
53 #define SYM_HASH_SIZE 128
54 #define SYM_MAX_LEN 32
55
56 struct sym_scope {
57 struct sym_scope *next; /* Next on scope stack */
58 struct symbol *name; /* Name of this scope */
59 int active; /* Currently entered */
60 };
61 static struct sym_scope *conf_this_scope;
62
63 int conf_lino;
64
65 static int cf_hash(byte *c);
66 static struct symbol *cf_find_sym(byte *c, unsigned int h0);
67
68 linpool *cfg_mem;
69
70 int (*cf_read_hook)(byte *buf, unsigned int max);
71
72 #define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
73 #define YY_NO_UNPUT
74 #define YY_FATAL_ERROR(msg) cf_error(msg)
75
76 %}
77
78 %option noyywrap
79
80 %x COMMENT CCOMM CLI
81
82 ALPHA [a-zA-Z_]
83 DIGIT [0-9]
84 XIGIT [0-9a-fA-F]
85 ALNUM [a-zA-Z_0-9]
86 WHITE [ \t]
87
88 %%
89
90 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
91 #ifdef IPV6
92 if (ipv4_pton_u32(yytext, &cf_lval.i32))
93 return RTRID;
94 cf_error("Invalid IPv4 address %s", yytext);
95 #else
96 if (ip_pton(yytext, &cf_lval.a))
97 return IPA;
98 cf_error("Invalid IP address %s", yytext);
99 #endif
100 }
101
102 ({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
103 #ifdef IPV6
104 if (ip_pton(yytext, &cf_lval.a))
105 return IPA;
106 cf_error("Invalid IP address %s", yytext);
107 #else
108 cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
109 #endif
110 }
111
112 0x{DIGIT}+ {
113 char *e;
114 long int l;
115 errno = 0;
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");
119 cf_lval.i = l;
120 return NUM;
121 }
122
123 {DIGIT}+ {
124 char *e;
125 long int l;
126 errno = 0;
127 l = strtoul(yytext, &e, 10);
128 if (e && *e || errno == ERANGE || (long int)(int) l != l)
129 cf_error("Number out of range");
130 cf_lval.i = l;
131 return NUM;
132 }
133
134 {ALPHA}{ALNUM}* {
135 unsigned int h = cf_hash(yytext);
136 struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)];
137 while (k)
138 {
139 if (!strcmp(k->name, yytext))
140 {
141 if (k->value > 0)
142 return k->value;
143 else
144 {
145 cf_lval.i = -k->value;
146 return ENUM;
147 }
148 }
149 k=k->next;
150 }
151 cf_lval.s = cf_find_sym(yytext, h);
152 return SYM;
153 }
154
155 <CLI>(.|\n) {
156 BEGIN(INITIAL);
157 return CLI_MARKER;
158 }
159
160 [={}:;,.()+*/%<>~\[\]?!-] {
161 return yytext[0];
162 }
163
164 ["][^"\n]*["] {
165 yytext[yyleng-1] = 0;
166 cf_lval.t = cfg_strdup(yytext+1);
167 return TEXT;
168 }
169
170 ["][^"\n]*\n cf_error("Unterminated string");
171
172 <INITIAL,COMMENT><<EOF>> return END;
173
174 {WHITE}+
175
176 \n conf_lino++;
177
178 # BEGIN(COMMENT);
179
180 \/\* BEGIN(CCOMM);
181
182 . cf_error("Unknown character");
183
184 <COMMENT>\n {
185 conf_lino++;
186 BEGIN(INITIAL);
187 }
188
189 <COMMENT>.
190
191 <CCOMM>\*\/ BEGIN(INITIAL);
192 <CCOMM>\n conf_lino++;
193 <CCOMM>\/\* cf_error("Comment nesting not supported");
194 <CCOMM><<EOF>> cf_error("Unterminated comment");
195 <CCOMM>.
196
197 \!\= return NEQ;
198 \<\= return LEQ;
199 \>\= return GEQ;
200 \&\& return AND;
201 \|\| return OR;
202
203 %%
204
205 static int
206 cf_hash(byte *c)
207 {
208 unsigned int h = 13;
209
210 while (*c)
211 h = (h * 37) + *c++;
212 return h;
213 }
214
215 static struct symbol *
216 cf_new_sym(byte *c, unsigned int h)
217 {
218 struct symbol *s, **ht;
219 int l;
220
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;
224 l = strlen(c);
225 if (l > SYM_MAX_LEN)
226 cf_error("Symbol too long");
227 s = cfg_alloc(sizeof(struct symbol) + l);
228 s->next = ht[h];
229 ht[h] = s;
230 s->scope = conf_this_scope;
231 s->class = SYM_VOID;
232 s->def = NULL;
233 s->aux = 0;
234 strcpy(s->name, c);
235 return s;
236 }
237
238 static struct symbol *
239 cf_find_sym(byte *c, unsigned int h0)
240 {
241 unsigned int h = h0 & (SYM_HASH_SIZE-1);
242 struct symbol *s, **ht;
243
244 if (ht = new_config->sym_hash)
245 {
246 for(s = ht[h]; s; s=s->next)
247 if (!strcmp(s->name, c) && s->scope->active)
248 return s;
249 }
250 if (new_config->sym_fallback)
251 {
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)
255 return s;
256 }
257 return cf_new_sym(c, h);
258 }
259
260 /**
261 * cf_find_symbol - find a symbol by name
262 * @c: symbol name
263 *
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.
269 */
270 struct symbol *
271 cf_find_symbol(byte *c)
272 {
273 return cf_find_sym(c, cf_hash(c));
274 }
275
276 struct symbol *
277 cf_default_name(char *template, int *counter)
278 {
279 char buf[32];
280 struct symbol *s;
281 char *perc = strchr(template, '%');
282
283 for(;;)
284 {
285 bsprintf(buf, template, ++(*counter));
286 s = cf_find_sym(buf, cf_hash(buf));
287 if (!s)
288 break;
289 if (s->class == SYM_VOID)
290 return s;
291 if (!perc)
292 break;
293 }
294 cf_error("Unable to generate default name");
295 }
296
297 /**
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
302 *
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().
308 *
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.
311 */
312 struct symbol *
313 cf_define_symbol(struct symbol *sym, int type, void *def)
314 {
315 if (sym->class)
316 {
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));
320 }
321 sym->class = type;
322 sym->def = def;
323 return sym;
324 }
325
326 static void
327 cf_lex_init_kh(void)
328 {
329 struct keyword *k;
330
331 for(k=keyword_list; k->name; k++)
332 {
333 unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1);
334 k->next = kw_hash[h];
335 kw_hash[h] = k;
336 }
337 kw_hash_inited = 1;
338 }
339
340 /**
341 * cf_lex_init - initialize the lexer
342 * @is_cli: true if we're going to parse CLI command, false for configuration
343 *
344 * cf_lex_init() initializes the lexical analyser and prepares it for
345 * parsing of a new input.
346 */
347 void
348 cf_lex_init(int is_cli)
349 {
350 if (!kw_hash_inited)
351 cf_lex_init_kh();
352 conf_lino = 1;
353 yyrestart(NULL);
354 if (is_cli)
355 BEGIN(CLI);
356 else
357 BEGIN(INITIAL);
358 conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
359 conf_this_scope->active = 1;
360 }
361
362 /**
363 * cf_push_scope - enter new scope
364 * @sym: symbol representing scope name
365 *
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.
371 */
372 void
373 cf_push_scope(struct symbol *sym)
374 {
375 struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
376
377 s->next = conf_this_scope;
378 conf_this_scope = s;
379 s->active = 1;
380 s->name = sym;
381 }
382
383 /**
384 * cf_pop_scope - leave a scope
385 *
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.
389 */
390 void
391 cf_pop_scope(void)
392 {
393 conf_this_scope->active = 0;
394 conf_this_scope = conf_this_scope->next;
395 ASSERT(conf_this_scope);
396 }
397
398 struct symbol *
399 cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos)
400 {
401 for(;;)
402 {
403 if (!sym)
404 {
405 if (*pos >= SYM_HASH_SIZE)
406 return NULL;
407 sym = cf->sym_hash[(*pos)++];
408 }
409 else
410 sym = sym->next;
411 if (sym && sym->scope->active)
412 return sym;
413 }
414 }
415
416 /**
417 * cf_symbol_class_name - get name of a symbol class
418 * @sym: symbol
419 *
420 * This function returns a string representing the class
421 * of the given symbol.
422 */
423 char *
424 cf_symbol_class_name(struct symbol *sym)
425 {
426 switch (sym->class)
427 {
428 case SYM_VOID:
429 return "undefined";
430 case SYM_PROTO:
431 return "protocol";
432 case SYM_NUMBER:
433 return "numeric constant";
434 case SYM_FUNCTION:
435 return "function";
436 case SYM_FILTER:
437 return "filter";
438 case SYM_TABLE:
439 return "routing table";
440 case SYM_IPA:
441 return "network address";
442 default:
443 return "unknown type";
444 }
445 }
446
447
448 /**
449 * DOC: Parser
450 *
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.
455 *
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.
465 *
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.
469 *
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.
473 *
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.
477 */