Statistics
| Branch: | Revision:

iof-bird-daemon / conf / cf-lex.l @ ca0edc53

History | View | Annotate | Download (5.52 KB)

1
/*
2
 *	BIRD -- Configuration Lexer
3
 *
4
 *	(c) 1998--1999 Martin Mares <mj@ucw.cz>
5
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
%{
10
#undef REJECT     /* Avoid name clashes */
11

    
12
#include <errno.h>
13
#include <stdlib.h>
14
#include <string.h>
15
#include <stdarg.h>
16

    
17
#include "nest/bird.h"
18
#include "nest/route.h"
19
#include "filter/filter.h"
20
#include "conf/conf.h"
21
#include "conf/cf-parse.tab.h"
22

    
23
static struct keyword {
24
  byte *name;
25
  int value;
26
  struct keyword *next;
27
} keyword_list[] = {
28
#include "conf/keywords.h"
29
  { NULL, -1 } };
30

    
31
#define KW_HASH_SIZE 64
32
static struct keyword *kw_hash[KW_HASH_SIZE];
33
static int kw_hash_inited;
34

    
35
#define SYM_HASH_SIZE 128
36
#define SYM_MAX_LEN 32
37

    
38
struct 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
};
43
static struct sym_scope *conf_this_scope;
44

    
45
int conf_lino;
46

    
47
static int cf_hash(byte *c);
48
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
49

    
50
linpool *cfg_mem;
51

    
52
int (*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

    
62
%x COMMENT CCOMM CLI
63

    
64
ALPHA [a-zA-Z_]
65
DIGIT [0-9]
66
XIGIT [0-9a-fA-F]
67
ALNUM [a-zA-Z_0-9]
68
WHITE [ \t]
69

    
70
%%
71

    
72
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
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
78
  if (ip_pton(yytext, &cf_lval.a))
79
    return IPA;
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
92
}
93

    
94
0x{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))
122
	{
123
	  if (k->value > 0)
124
	    return k->value;
125
	  else
126
	    {
127
	      cf_lval.i = -k->value;
128
	      return ENUM;
129
	    }
130
	}
131
      k=k->next;
132
    }
133
  cf_lval.s = cf_find_sym(yytext, h);
134
  return SYM;
135
}
136

    
137
<CLI>(.|\n) {
138
  BEGIN(INITIAL);
139
  return CLI_MARKER;
140
}
141

    
142
[={}:;,()+*/%-<>~\[\]] {
143
  return yytext[0];
144
}
145

    
146
["][^"\n]*["] {
147
  yytext[yyleng-1] = 0;
148
  cf_lval.t = cfg_strdup(yytext+1);
149
  return TEXT;
150
}
151

    
152
["][^"\n]*\n	cf_error("Unterminated string");
153

    
154
<INITIAL,COMMENT><<EOF>>	return END;
155

    
156
{WHITE}+
157

    
158
\n	conf_lino++;
159

    
160
#	BEGIN(COMMENT);
161

    
162
\/\*	BEGIN(CCOMM);
163

    
164
.	cf_error("Unknown character");
165

    
166
<COMMENT>\n {
167
  conf_lino++;
168
  BEGIN(INITIAL);
169
}
170

    
171
<COMMENT>.
172

    
173
<CCOMM>\*\/	BEGIN(INITIAL);
174
<CCOMM>\n	conf_lino++;
175
<CCOMM>\/\*	cf_error("Comment nesting not supported");
176
<CCOMM><<EOF>>	cf_error("Unterminated comment");
177
<CCOMM>.
178

    
179
%%
180

    
181
static int
182
cf_hash(byte *c)
183
{
184
  unsigned int h = 13;
185

    
186
  while (*c)
187
    h = (h * 37) + *c++;
188
  return h;
189
}
190

    
191
static struct symbol *
192
cf_find_sym(byte *c, unsigned int h0)
193
{
194
  unsigned int h = h0 & (SYM_HASH_SIZE-1);
195
  struct symbol *s, **ht;
196
  int l;
197

    
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)
208
	if (!strcmp(s->name, c) && s->scope->active)
209
	  return s;
210
    }
211
  if (!ht)
212
    ht = new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
213
  l = strlen(c);
214
  if (l > SYM_MAX_LEN)
215
    cf_error("Symbol too long");
216
  s = cfg_alloc(sizeof(struct symbol) + l);
217
  s->next = ht[h];
218
  ht[h] = s;
219
  s->scope = conf_this_scope;
220
  s->class = SYM_VOID;
221
  s->def = NULL;
222
  s->aux = 0;
223
  strcpy(s->name, c);
224
  return s;
225
}
226

    
227
struct symbol *
228
cf_find_symbol(byte *c)
229
{
230
  return cf_find_sym(c, cf_hash(c));
231
}
232

    
233
struct symbol *
234
cf_default_name(char *prefix, int *counter)
235
{
236
  char buf[32];
237
  struct symbol *s;
238

    
239
  do
240
    {
241
      sprintf(buf, "%s%d", prefix, ++(*counter));
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

    
249
void
250
cf_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

    
258
static void
259
cf_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

    
272
void
273
cf_lex_init(int is_cli)
274
{
275
  if (!kw_hash_inited)
276
    cf_lex_init_kh();
277
  conf_lino = 1;
278
  yyrestart(NULL);
279
  if (is_cli)
280
    BEGIN(CLI);
281
  else
282
    BEGIN(INITIAL);
283
  conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
284
  conf_this_scope->active = 1;
285
}
286

    
287
void
288
cf_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

    
298
void
299
cf_pop_scope(void)
300
{
301
  conf_this_scope->active = 0;
302
  conf_this_scope = conf_this_scope->next;
303
  ASSERT(conf_this_scope);
304
}