]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/cf-lex.l
Updated TODO file.
[thirdparty/bird.git] / conf / cf-lex.l
CommitLineData
82fc7be7
MM
1/*
2 * BIRD -- Configuration Lexer
3 *
d272fe22 4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
82fc7be7
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
06607335
MM
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
82fc7be7 27%{
cc12cf05 28#undef REJECT /* Avoid name clashes */
82fc7be7
MM
29
30#include <errno.h>
31#include <stdlib.h>
cc12cf05 32#include <stdarg.h>
82fc7be7
MM
33
34#include "nest/bird.h"
944f008a
MM
35#include "nest/route.h"
36#include "filter/filter.h"
82fc7be7
MM
37#include "conf/conf.h"
38#include "conf/cf-parse.tab.h"
d272fe22 39#include "lib/string.h"
82fc7be7 40
a412f01e 41struct keyword {
82fc7be7
MM
42 byte *name;
43 int value;
44 struct keyword *next;
a412f01e
MM
45};
46
49e7e5ee 47#include "conf/keywords.h"
82fc7be7
MM
48
49#define KW_HASH_SIZE 64
c9aae7f4
MM
50static struct keyword *kw_hash[KW_HASH_SIZE];
51static int kw_hash_inited;
52
82fc7be7
MM
53#define SYM_HASH_SIZE 128
54#define SYM_MAX_LEN 32
55
c8f61a01
MM
56struct 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};
61static struct sym_scope *conf_this_scope;
62
31b3e1bb
MM
63int conf_lino;
64
82fc7be7
MM
65static int cf_hash(byte *c);
66static struct symbol *cf_find_sym(byte *c, unsigned int h0);
67
b35d72ac 68linpool *cfg_mem;
82fc7be7
MM
69
70int (*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
bc2fb680 80%x COMMENT CCOMM CLI
82fc7be7
MM
81
82ALPHA [a-zA-Z_]
83DIGIT [0-9]
84XIGIT [0-9a-fA-F]
85ALNUM [a-zA-Z_0-9]
86WHITE [ \t]
87
88%%
89
90{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
dce26783
MM
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
82fc7be7
MM
96 if (ip_pton(yytext, &cf_lval.a))
97 return IPA;
dce26783
MM
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
82fc7be7
MM
110}
111
1120x{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))
944f008a
MM
140 {
141 if (k->value > 0)
142 return k->value;
143 else
144 {
145 cf_lval.i = -k->value;
146 return ENUM;
147 }
148 }
82fc7be7
MM
149 k=k->next;
150 }
151 cf_lval.s = cf_find_sym(yytext, h);
152 return SYM;
153}
154
efe51e38 155<CLI>(.|\n) {
bc2fb680
MM
156 BEGIN(INITIAL);
157 return CLI_MARKER;
158}
159
69a20d2e 160[={}:;,.()+*/%<>~\[\]?!-] {
82fc7be7
MM
161 return yytext[0];
162}
163
164["][^"\n]*["] {
49e4a4d1 165 yytext[yyleng-1] = 0;
ca0edc53 166 cf_lval.t = cfg_strdup(yytext+1);
82fc7be7
MM
167 return TEXT;
168}
169
170["][^"\n]*\n cf_error("Unterminated string");
171
172<INITIAL,COMMENT><<EOF>> return END;
173
174{WHITE}+
175
7f400d1c 176\n conf_lino++;
82fc7be7 177
72614174 178# BEGIN(COMMENT);
82fc7be7 179
72614174 180\/\* BEGIN(CCOMM);
82fc7be7
MM
181
182. cf_error("Unknown character");
183
184<COMMENT>\n {
31b3e1bb 185 conf_lino++;
82fc7be7
MM
186 BEGIN(INITIAL);
187}
188
189<COMMENT>.
190
191<CCOMM>\*\/ BEGIN(INITIAL);
31b3e1bb 192<CCOMM>\n conf_lino++;
82fc7be7
MM
193<CCOMM>\/\* cf_error("Comment nesting not supported");
194<CCOMM><<EOF>> cf_error("Unterminated comment");
195<CCOMM>.
196
c8d5ffaf
PM
197\!\= return NEQ;
198\<\= return LEQ;
199\>\= return GEQ;
5f4aee76
PM
200\&\& return AND;
201\|\| return OR;
c8d5ffaf 202
82fc7be7
MM
203%%
204
205static int
206cf_hash(byte *c)
207{
208 unsigned int h = 13;
209
210 while (*c)
211 h = (h * 37) + *c++;
212 return h;
213}
214
04dc62a0
MM
215static struct symbol *
216cf_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
82fc7be7
MM
238static struct symbol *
239cf_find_sym(byte *c, unsigned int h0)
240{
241 unsigned int h = h0 & (SYM_HASH_SIZE-1);
c9aae7f4 242 struct symbol *s, **ht;
82fc7be7 243
c9aae7f4
MM
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)
c8f61a01 254 if (!strcmp(s->name, c) && s->scope->active)
bc2fb680 255 return s;
c9aae7f4 256 }
04dc62a0 257 return cf_new_sym(c, h);
82fc7be7
MM
258}
259
06607335
MM
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 */
4107df1d
MM
270struct symbol *
271cf_find_symbol(byte *c)
272{
273 return cf_find_sym(c, cf_hash(c));
274}
275
8450be97 276struct symbol *
d272fe22 277cf_default_name(char *template, int *counter)
8450be97
MM
278{
279 char buf[32];
280 struct symbol *s;
d272fe22 281 char *perc = strchr(template, '%');
8450be97 282
d272fe22 283 for(;;)
8450be97 284 {
d272fe22 285 bsprintf(buf, template, ++(*counter));
8450be97 286 s = cf_find_sym(buf, cf_hash(buf));
d272fe22
MM
287 if (!s)
288 break;
289 if (s->class == SYM_VOID)
290 return s;
291 if (!perc)
292 break;
8450be97 293 }
d272fe22 294 cf_error("Unable to generate default name");
8450be97
MM
295}
296
06607335
MM
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 *
04dc62a0
MM
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.
06607335 311 */
04dc62a0 312struct symbol *
4107df1d
MM
313cf_define_symbol(struct symbol *sym, int type, void *def)
314{
315 if (sym->class)
04dc62a0
MM
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 }
4107df1d
MM
321 sym->class = type;
322 sym->def = def;
04dc62a0 323 return sym;
4107df1d
MM
324}
325
c9aae7f4
MM
326static void
327cf_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
06607335
MM
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 */
82fc7be7 347void
bc2fb680 348cf_lex_init(int is_cli)
82fc7be7 349{
c9aae7f4
MM
350 if (!kw_hash_inited)
351 cf_lex_init_kh();
31b3e1bb 352 conf_lino = 1;
bc2fb680
MM
353 yyrestart(NULL);
354 if (is_cli)
355 BEGIN(CLI);
356 else
357 BEGIN(INITIAL);
c8f61a01
MM
358 conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
359 conf_this_scope->active = 1;
82fc7be7
MM
360}
361
06607335
MM
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 */
c8f61a01
MM
372void
373cf_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
06607335
MM
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 */
c8f61a01
MM
390void
391cf_pop_scope(void)
392{
393 conf_this_scope->active = 0;
394 conf_this_scope = conf_this_scope->next;
395 ASSERT(conf_this_scope);
396}
4b87e256
MM
397
398struct symbol *
399cf_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
06607335
MM
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 */
4b87e256
MM
423char *
424cf_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";
c0b2f646
MM
440 case SYM_IPA:
441 return "network address";
4b87e256
MM
442 default:
443 return "unknown type";
444 }
445}
58f94537
MM
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 */