]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/cf-lex.l
Lexer supports fallback symbol tables and uses them to recognize
[thirdparty/bird.git] / conf / cf-lex.l
CommitLineData
82fc7be7
MM
1/*
2 * BIRD -- Configuration Lexer
3 *
31b3e1bb 4 * (c) 1998--1999 Martin Mares <mj@ucw.cz>
82fc7be7
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9%{
cc12cf05 10#undef REJECT /* Avoid name clashes */
82fc7be7
MM
11
12#include <errno.h>
13#include <stdlib.h>
14#include <string.h>
cc12cf05 15#include <stdarg.h>
82fc7be7
MM
16
17#include "nest/bird.h"
944f008a
MM
18#include "nest/route.h"
19#include "filter/filter.h"
82fc7be7
MM
20#include "conf/conf.h"
21#include "conf/cf-parse.tab.h"
22
23static struct keyword {
24 byte *name;
25 int value;
26 struct keyword *next;
27} keyword_list[] = {
49e7e5ee 28#include "conf/keywords.h"
82fc7be7
MM
29 { NULL, -1 } };
30
31#define KW_HASH_SIZE 64
c9aae7f4
MM
32static struct keyword *kw_hash[KW_HASH_SIZE];
33static int kw_hash_inited;
34
82fc7be7
MM
35#define SYM_HASH_SIZE 128
36#define SYM_MAX_LEN 32
37
c8f61a01
MM
38struct sym_scope {
39 struct sym_scope *next; /* Next on scope stack */
40 struct symbol *name; /* Name of this scope */
41 int active; /* Currently entered */
42};
43static struct sym_scope *conf_this_scope;
44
31b3e1bb
MM
45int conf_lino;
46
82fc7be7
MM
47static int cf_hash(byte *c);
48static struct symbol *cf_find_sym(byte *c, unsigned int h0);
49
b35d72ac 50linpool *cfg_mem;
82fc7be7
MM
51
52int (*cf_read_hook)(byte *buf, unsigned int max);
53
54#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
55#define YY_NO_UNPUT
56#define YY_FATAL_ERROR(msg) cf_error(msg)
57
58%}
59
60%option noyywrap
61
bc2fb680 62%x COMMENT CCOMM CLI
82fc7be7
MM
63
64ALPHA [a-zA-Z_]
65DIGIT [0-9]
66XIGIT [0-9a-fA-F]
67ALNUM [a-zA-Z_0-9]
68WHITE [ \t]
69
70%%
71
72{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
dce26783
MM
73#ifdef IPV6
74 if (ipv4_pton_u32(yytext, &cf_lval.i32))
75 return RTRID;
76 cf_error("Invalid IPv4 address %s", yytext);
77#else
82fc7be7
MM
78 if (ip_pton(yytext, &cf_lval.a))
79 return IPA;
dce26783
MM
80 cf_error("Invalid IP address %s", yytext);
81#endif
82}
83
84({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
85#ifdef IPV6
86 if (ip_pton(yytext, &cf_lval.a))
87 return IPA;
88 cf_error("Invalid IP address %s", yytext);
89#else
90 cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
91#endif
82fc7be7
MM
92}
93
940x{DIGIT}+ {
95 char *e;
96 long int l;
97 errno = 0;
98 l = strtoul(yytext+2, &e, 16);
99 if (e && *e || errno == ERANGE || (long int)(int) l != l)
100 cf_error("Number out of range");
101 cf_lval.i = l;
102 return NUM;
103}
104
105{DIGIT}+ {
106 char *e;
107 long int l;
108 errno = 0;
109 l = strtoul(yytext, &e, 10);
110 if (e && *e || errno == ERANGE || (long int)(int) l != l)
111 cf_error("Number out of range");
112 cf_lval.i = l;
113 return NUM;
114}
115
116{ALPHA}{ALNUM}* {
117 unsigned int h = cf_hash(yytext);
118 struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)];
119 while (k)
120 {
121 if (!strcmp(k->name, yytext))
944f008a
MM
122 {
123 if (k->value > 0)
124 return k->value;
125 else
126 {
127 cf_lval.i = -k->value;
128 return ENUM;
129 }
130 }
82fc7be7
MM
131 k=k->next;
132 }
133 cf_lval.s = cf_find_sym(yytext, h);
134 return SYM;
135}
136
bc2fb680
MM
137<CLI>! {
138 BEGIN(INITIAL);
139 return CLI_MARKER;
140}
141
38506f71 142[={}:;,()+*/%-<>~\[\]] {
82fc7be7
MM
143 return yytext[0];
144}
145
146["][^"\n]*["] {
147 cf_lval.t = yytext+1;
49e4a4d1 148 yytext[yyleng-1] = 0;
82fc7be7
MM
149 return TEXT;
150}
151
152["][^"\n]*\n cf_error("Unterminated string");
153
154<INITIAL,COMMENT><<EOF>> return END;
155
156{WHITE}+
157
7f400d1c 158\n conf_lino++;
82fc7be7 159
72614174 160# BEGIN(COMMENT);
82fc7be7 161
72614174 162\/\* BEGIN(CCOMM);
82fc7be7
MM
163
164. cf_error("Unknown character");
165
166<COMMENT>\n {
31b3e1bb 167 conf_lino++;
82fc7be7
MM
168 BEGIN(INITIAL);
169}
170
171<COMMENT>.
172
173<CCOMM>\*\/ BEGIN(INITIAL);
31b3e1bb 174<CCOMM>\n conf_lino++;
82fc7be7
MM
175<CCOMM>\/\* cf_error("Comment nesting not supported");
176<CCOMM><<EOF>> cf_error("Unterminated comment");
177<CCOMM>.
178
179%%
180
181static int
182cf_hash(byte *c)
183{
184 unsigned int h = 13;
185
186 while (*c)
187 h = (h * 37) + *c++;
188 return h;
189}
190
191static struct symbol *
192cf_find_sym(byte *c, unsigned int h0)
193{
194 unsigned int h = h0 & (SYM_HASH_SIZE-1);
c9aae7f4 195 struct symbol *s, **ht;
82fc7be7
MM
196 int l;
197
c9aae7f4
MM
198 if (ht = new_config->sym_hash)
199 {
200 for(s = ht[h]; s; s=s->next)
201 if (!strcmp(s->name, c) && s->scope->active)
202 return s;
203 }
204 if (new_config->sym_fallback)
205 {
206 /* We know only top-level scope is active */
207 for(s = new_config->sym_fallback[h]; s; s=s->next)
c8f61a01 208 if (!strcmp(s->name, c) && s->scope->active)
bc2fb680 209 return s;
c9aae7f4
MM
210 }
211 if (!ht)
212 ht = new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
82fc7be7
MM
213 l = strlen(c);
214 if (l > SYM_MAX_LEN)
215 cf_error("Symbol too long");
49e4a4d1 216 s = cfg_alloc(sizeof(struct symbol) + l);
c9aae7f4
MM
217 s->next = ht[h];
218 ht[h] = s;
c8f61a01 219 s->scope = conf_this_scope;
82fc7be7
MM
220 s->class = SYM_VOID;
221 s->def = NULL;
0b62c3a7 222 s->aux = 0;
82fc7be7
MM
223 strcpy(s->name, c);
224 return s;
225}
226
4107df1d
MM
227struct symbol *
228cf_find_symbol(byte *c)
229{
230 return cf_find_sym(c, cf_hash(c));
231}
232
8450be97 233struct symbol *
4ba84ebc 234cf_default_name(char *prefix, int *counter)
8450be97
MM
235{
236 char buf[32];
237 struct symbol *s;
238
239 do
240 {
4ba84ebc 241 sprintf(buf, "%s%d", prefix, ++(*counter));
8450be97
MM
242 s = cf_find_sym(buf, cf_hash(buf));
243 if (!s) cf_error("Unable to generate default name");
244 }
245 while (s->class != SYM_VOID);
246 return s;
247}
248
4107df1d
MM
249void
250cf_define_symbol(struct symbol *sym, int type, void *def)
251{
252 if (sym->class)
253 cf_error("Symbol already defined");
254 sym->class = type;
255 sym->def = def;
256}
257
c9aae7f4
MM
258static void
259cf_lex_init_kh(void)
260{
261 struct keyword *k;
262
263 for(k=keyword_list; k->name; k++)
264 {
265 unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1);
266 k->next = kw_hash[h];
267 kw_hash[h] = k;
268 }
269 kw_hash_inited = 1;
270}
271
82fc7be7 272void
bc2fb680 273cf_lex_init(int is_cli)
82fc7be7 274{
c9aae7f4
MM
275 if (!kw_hash_inited)
276 cf_lex_init_kh();
31b3e1bb 277 conf_lino = 1;
bc2fb680
MM
278 yyrestart(NULL);
279 if (is_cli)
280 BEGIN(CLI);
281 else
282 BEGIN(INITIAL);
c8f61a01
MM
283 conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
284 conf_this_scope->active = 1;
82fc7be7
MM
285}
286
c8f61a01
MM
287void
288cf_push_scope(struct symbol *sym)
289{
290 struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
291
292 s->next = conf_this_scope;
293 conf_this_scope = s;
294 s->active = 1;
295 s->name = sym;
296}
297
298void
299cf_pop_scope(void)
300{
301 conf_this_scope->active = 0;
302 conf_this_scope = conf_this_scope->next;
303 ASSERT(conf_this_scope);
304}