Statistics
| Branch: | Revision:

iof-bird-daemon / conf / cf-lex.l @ 49e7e5ee

History | View | Annotate | Download (4.22 KB)

1
/*
2
 *	BIRD -- Configuration Lexer
3
 *
4
 *	(c) 1998 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 "lib/string.h"
19
#include "conf/conf.h"
20
#include "conf/cf-parse.tab.h"
21

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

    
30
#define KW_HASH_SIZE 64
31
#define SYM_HASH_SIZE 128
32
#define SYM_MAX_LEN 32
33

    
34
static struct keyword *kw_hash[KW_HASH_SIZE];
35
static struct symbol **sym_hash;
36
static int allow_new_symbols;
37
static int cf_lino;
38
static int default_counter;
39

    
40
static int cf_hash(byte *c);
41
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
42

    
43
pool *cfg_pool;
44
linpool *cfg_mem;
45

    
46
int (*cf_read_hook)(byte *buf, unsigned int max);
47

    
48
#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
49
#define YY_NO_UNPUT
50
#define YY_FATAL_ERROR(msg) cf_error(msg)
51

    
52
%}
53

    
54
%option noyywrap
55

    
56
%x COMMENT CCOMM
57

    
58
ALPHA [a-zA-Z_]
59
DIGIT [0-9]
60
XIGIT [0-9a-fA-F]
61
ALNUM [a-zA-Z_0-9]
62
WHITE [ \t]
63

    
64
%%
65

    
66
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
67
  if (ip_pton(yytext, &cf_lval.a))
68
    return IPA;
69
  cf_error("Invalid IP address");
70
}
71

    
72
0x{DIGIT}+ {
73
  char *e;
74
  long int l;
75
  errno = 0;
76
  l = strtoul(yytext+2, &e, 16);
77
  if (e && *e || errno == ERANGE || (long int)(int) l != l)
78
    cf_error("Number out of range");
79
  cf_lval.i = l;
80
  return NUM;
81
}
82

    
83
{DIGIT}+ {
84
  char *e;
85
  long int l;
86
  errno = 0;
87
  l = strtoul(yytext, &e, 10);
88
  if (e && *e || errno == ERANGE || (long int)(int) l != l)
89
    cf_error("Number out of range");
90
  cf_lval.i = l;
91
  return NUM;
92
}
93

    
94
{ALPHA}{ALNUM}* {
95
  unsigned int h = cf_hash(yytext);
96
  struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)];
97
  while (k)
98
    {
99
      if (!strcmp(k->name, yytext))
100
	return k->value;
101
      k=k->next;
102
    }
103
  cf_lval.s = cf_find_sym(yytext, h);
104
  return SYM;
105
}
106

    
107
[={}:;,()+*/%-] {
108
  return yytext[0];
109
}
110

    
111
["][^"\n]*["] {
112
  cf_lval.t = yytext+1;
113
  yytext[yyleng-1] = 0;
114
  return TEXT;
115
}
116

    
117
["][^"\n]*\n	cf_error("Unterminated string");
118

    
119
<INITIAL,COMMENT><<EOF>>	return END;
120

    
121
{WHITE}+
122

    
123
\\\n {
124
  cf_lino++;
125
}
126

    
127
\n {
128
  cf_lino++;
129
  return ';';
130
}
131

    
132
#	{ BEGIN(COMMENT); }
133

    
134
\/\*	{ BEGIN(CCOMM); }
135

    
136
.	cf_error("Unknown character");
137

    
138
<COMMENT>\n {
139
  cf_lino++;
140
  BEGIN(INITIAL);
141
}
142

    
143
<COMMENT>.
144

    
145
<CCOMM>\*\/	BEGIN(INITIAL);
146
<CCOMM>\n	cf_lino++;
147
<CCOMM>\/\*	cf_error("Comment nesting not supported");
148
<CCOMM><<EOF>>	cf_error("Unterminated comment");
149
<CCOMM>.
150

    
151
%%
152

    
153
static int
154
cf_hash(byte *c)
155
{
156
  unsigned int h = 13;
157

    
158
  while (*c)
159
    h = (h * 37) + *c++;
160
  return h;
161
}
162

    
163
static struct symbol *
164
cf_find_sym(byte *c, unsigned int h0)
165
{
166
  unsigned int h = h0 & (SYM_HASH_SIZE-1);
167
  struct symbol *s = sym_hash[h];
168
  int l;
169

    
170
  while (s)
171
    if (!strcmp(s->name, c))
172
      return s;
173
  if (!allow_new_symbols)
174
    return NULL;
175
  l = strlen(c);
176
  if (l > SYM_MAX_LEN)
177
    cf_error("Symbol too long");
178
  s = cfg_alloc(sizeof(struct symbol) + l);
179
  s->next = sym_hash[h];
180
  sym_hash[h] = s;
181
  s->class = SYM_VOID;
182
  s->def = NULL;
183
  s->aux = 0;
184
  strcpy(s->name, c);
185
  return s;
186
}
187

    
188
struct symbol *
189
cf_default_name(char *prefix)
190
{
191
  char buf[32];
192
  struct symbol *s;
193

    
194
  do
195
    {
196
      sprintf(buf, "%s%d", prefix, default_counter++);
197
      s = cf_find_sym(buf, cf_hash(buf));
198
      if (!s) cf_error("Unable to generate default name");
199
    }
200
  while (s->class != SYM_VOID);
201
  return s;
202
}
203

    
204
void
205
cf_lex_init(int flag)
206
{
207
  if (allow_new_symbols = flag)
208
    sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
209
  cf_lino = 1;
210
  default_counter = 1;
211
}
212

    
213
void
214
cf_lex_init_tables(void)
215
{
216
  struct keyword *k;
217

    
218
  for(k=keyword_list; k->name; k++)
219
    {
220
      unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1);
221
      k->next = kw_hash[h];
222
      kw_hash[h] = k;
223
    }
224
}
225

    
226
void
227
cf_error(char *msg, ...)
228
{
229
  /* FIXME */
230

    
231
  char buf[1024];
232
  va_list args;
233

    
234
  va_start(args, msg);
235
  bvsprintf(buf, msg, args);
236
  die(PATH_CONFIG ", line %d: %s", cf_lino, buf);
237
}
238

    
239
void
240
cf_allocate(void)
241
{
242
  if (cfg_pool)
243
    rfree(cfg_pool);
244
  cfg_pool = rp_new(&root_pool, "Config");
245
  cfg_mem = lp_new(cfg_pool, 1024);
246
}
247

    
248
char *
249
cfg_strdup(char *c)
250
{
251
  int l = strlen(c) + 1;
252
  char *z = cfg_allocu(l);
253
  memcpy(z, c, l);
254
  return z;
255
}
256