Statistics
| Branch: | Revision:

iof-bird-daemon / conf / cf-lex.l @ 8c4da7e0

History | View | Annotate | Download (15.4 KB)

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 analyzer
11
 *
12
 * The lexical analyzer used for configuration files and CLI commands
13
 * is generated using the |flex| tool accompanied by 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 lexical 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
#include <unistd.h>
34
#include <libgen.h>
35
#include <glob.h>
36
#include <fcntl.h>
37
#include <sys/stat.h>
38
#include <sys/types.h>
39
#include <sys/stat.h>
40

    
41
#define PARSER 1
42

    
43
#include "nest/bird.h"
44
#include "nest/route.h"
45
#include "nest/protocol.h"
46
#include "filter/filter.h"
47
#include "conf/conf.h"
48
#include "conf/cf-parse.tab.h"
49
#include "lib/string.h"
50

    
51
struct keyword {
52
  byte *name;
53
  int value;
54
  struct keyword *next;
55
};
56

    
57
#include "conf/keywords.h"
58

    
59
#define KW_HASH_SIZE 64
60
static struct keyword *kw_hash[KW_HASH_SIZE];
61
static int kw_hash_inited;
62

    
63
#define SYM_HASH_SIZE 128
64
#define SYM_MAX_LEN 32
65

    
66
struct sym_scope {
67
  struct sym_scope *next;		/* Next on scope stack */
68
  struct symbol *name;			/* Name of this scope */
69
  int active;				/* Currently entered */
70
};
71
static struct sym_scope *conf_this_scope;
72

    
73
static int cf_hash(byte *c);
74
static struct symbol *cf_find_sym(byte *c, unsigned int h0);
75

    
76
linpool *cfg_mem;
77

    
78
int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
79
struct include_file_stack *ifs;
80
static struct include_file_stack *ifs_head;
81

    
82
#define MAX_INCLUDE_DEPTH 8
83

    
84
#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd);
85
#define YY_NO_UNPUT
86
#define YY_FATAL_ERROR(msg) cf_error(msg)
87

    
88
static void cf_include(char *arg, int alen);
89
static int check_eof(void);
90

    
91
%}
92

    
93
%option noyywrap
94
%option noinput
95
%option nounput
96
%option noreject
97

    
98
%x COMMENT CCOMM CLI
99

    
100
ALPHA [a-zA-Z_]
101
DIGIT [0-9]
102
XIGIT [0-9a-fA-F]
103
ALNUM [a-zA-Z_0-9]
104
WHITE [ \t]
105
include   ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
106

    
107
%%
108
{include} {
109
  char *start, *end;
110

    
111
  if (!ifs->depth)
112
    cf_error("Include not allowed in CLI");
113

    
114
  start = strchr(yytext, '"');
115
  start++;
116

    
117
  end = strchr(start, '"');
118
  *end = 0;
119

    
120
  if (start == end)
121
    cf_error("Include with empty argument");
122

    
123
  cf_include(start, end-start);
124
}
125

    
126
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
127
#ifdef IPV6
128
  if (ipv4_pton_u32(yytext, &cf_lval.i32))
129
    return RTRID;
130
  cf_error("Invalid IPv4 address %s", yytext);
131
#else
132
  if (ip_pton(yytext, &cf_lval.a))
133
    return IPA;
134
  cf_error("Invalid IP address %s", yytext);
135
#endif
136
}
137

    
138
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
139
#ifdef IPV6
140
  if (ip_pton(yytext, &cf_lval.a))
141
    return IPA;
142
  cf_error("Invalid IP address %s", yytext);
143
#else
144
  cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
145
#endif
146
}
147

    
148
0x{XIGIT}+ {
149
  char *e;
150
  unsigned long int l;
151
  errno = 0;
152
  l = strtoul(yytext+2, &e, 16);
153
  if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
154
    cf_error("Number out of range");
155
  cf_lval.i = l;
156
  return NUM;
157
}
158

    
159
{DIGIT}+ {
160
  char *e;
161
  unsigned long int l;
162
  errno = 0;
163
  l = strtoul(yytext, &e, 10);
164
  if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
165
    cf_error("Number out of range");
166
  cf_lval.i = l;
167
  return NUM;
168
}
169

    
170
else: {
171
  /* Hack to distinguish if..else from else: in case */
172
  return ELSECOL;
173
}
174

    
175
({ALPHA}{ALNUM}*|[']({ALNUM}|[-]|[\.])*[']) {
176
  if(*yytext == '\'') {
177
    yytext[yyleng-1] = 0;
178
    yytext++;
179
  }
180
  unsigned int h = cf_hash(yytext);
181
  struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)];
182
  while (k)
183
    {
184
      if (!strcmp(k->name, yytext))
185
	{
186
	  if (k->value > 0)
187
	    return k->value;
188
	  else
189
	    {
190
	      cf_lval.i = -k->value;
191
	      return ENUM;
192
	    }
193
	}
194
      k=k->next;
195
    }
196
  cf_lval.s = cf_find_sym(yytext, h);
197
  return SYM;
198
}
199

    
200
<CLI>(.|\n) {
201
  BEGIN(INITIAL);
202
  return CLI_MARKER;
203
}
204

    
205
\.\. {
206
  return DDOT;
207
}
208

    
209
[={}:;,.()+*/%<>~\[\]?!\|-] {
210
  return yytext[0];
211
}
212

    
213
["][^"\n]*["] {
214
  yytext[yyleng-1] = 0;
215
  cf_lval.t = cfg_strdup(yytext+1);
216
  return TEXT;
217
}
218

    
219
["][^"\n]*\n	cf_error("Unterminated string");
220

    
221
<INITIAL,COMMENT><<EOF>>	{ if (check_eof()) return END; }
222

    
223
{WHITE}+
224

    
225
\n	ifs->lino++;
226

    
227
#	BEGIN(COMMENT);
228

    
229
\/\*	BEGIN(CCOMM);
230

    
231
.	cf_error("Unknown character");
232

    
233
<COMMENT>\n {
234
  ifs->lino++;
235
  BEGIN(INITIAL);
236
}
237

    
238
<COMMENT>.
239

    
240
<CCOMM>\*\/	BEGIN(INITIAL);
241
<CCOMM>\n	ifs->lino++;
242
<CCOMM>\/\*	cf_error("Comment nesting not supported");
243
<CCOMM><<EOF>>	cf_error("Unterminated comment");
244
<CCOMM>.
245

    
246
\!\= return NEQ;
247
\<\= return LEQ;
248
\>\= return GEQ;
249
\&\& return AND;
250
\|\| return OR;
251

    
252
\[\= return PO;
253
\=\] return PC;
254

    
255
%%
256

    
257
static int
258
cf_hash(byte *c)
259
{
260
  unsigned int h = 13;
261

    
262
  while (*c)
263
    h = (h * 37) + *c++;
264
  return h;
265
}
266

    
267

    
268
/*
269
 * IFS stack - it contains structures needed for recursive processing
270
 * of include in config files. On the top of the stack is a structure
271
 * for currently processed file. Other structures are either for
272
 * active files interrupted because of include directive (these have
273
 * fd and flex buffer) or for inactive files scheduled to be processed
274
 * later (when parent requested including of several files by wildcard
275
 * match - these do not have fd and flex buffer yet).
276
 *
277
 * FIXME: Most of these ifs and include functions are really sysdep/unix.
278
 *
279
 * FIXME: Resources (fd, flex buffers and glob data) in IFS stack
280
 * are not freed when cf_error() is called.
281
 */
282

    
283
static struct include_file_stack *
284
push_ifs(struct include_file_stack *old)
285
{
286
  struct include_file_stack *ret;
287
  ret = cfg_allocz(sizeof(struct include_file_stack));
288
  ret->lino = 1;
289
  ret->prev = old;
290
  return ret;
291
}
292

    
293
static struct include_file_stack *
294
pop_ifs(struct include_file_stack *old)
295
{
296
 yy_delete_buffer(old->buffer);
297
 close(old->fd);
298
 return old->prev;
299
}
300

    
301
static void
302
enter_ifs(struct include_file_stack *new)
303
{
304
  if (!new->buffer)
305
    {
306
      new->fd = open(new->file_name, O_RDONLY);
307
      if (new->fd < 0)
308
        {
309
          ifs = ifs->up;
310
	  cf_error("Unable to open included file %s: %m", new->file_name);
311
        }
312

    
313
      new->buffer = yy_create_buffer(NULL, YY_BUF_SIZE);
314
    }
315

    
316
  yy_switch_to_buffer(new->buffer);
317
}
318

    
319
static void
320
cf_include(char *arg, int alen)
321
{
322
  struct include_file_stack *base_ifs = ifs;
323
  int new_depth, rv, i;
324
  char *patt;
325
  glob_t g;
326

    
327
  new_depth = ifs->depth + 1;
328
  if (new_depth > MAX_INCLUDE_DEPTH)
329
    cf_error("Max include depth reached");
330

    
331
  /* expand arg to properly handle relative filenames */
332
  if (*arg != '/')
333
    {
334
      int dlen = strlen(ifs->file_name);
335
      char *dir = alloca(dlen + 1);
336
      patt = alloca(dlen + alen + 2);
337
      memcpy(dir, ifs->file_name, dlen + 1);
338
      sprintf(patt, "%s/%s", dirname(dir), arg);
339
    }
340
  else
341
    patt = arg;
342

    
343
  /* Skip globbing if there are no wildcards, mainly to get proper
344
     response when the included config file is missing */
345
  if (!strpbrk(arg, "?*["))
346
    {
347
      ifs = push_ifs(ifs);
348
      ifs->file_name = cfg_strdup(patt);
349
      ifs->depth = new_depth;
350
      ifs->up = base_ifs;
351
      enter_ifs(ifs);
352
      return;
353
    }
354

    
355
  /* Expand the pattern */
356
  rv = glob(patt, GLOB_ERR | GLOB_NOESCAPE, NULL, &g);
357
  if (rv == GLOB_ABORTED)
358
    cf_error("Unable to match pattern %s: %m", patt);
359
  if ((rv != 0) || (g.gl_pathc <= 0))
360
    return;
361

    
362
  /*
363
   * Now we put all found files to ifs stack in reverse order, they
364
   * will be activated and processed in order as ifs stack is popped
365
   * by pop_ifs() and enter_ifs() in check_eof().
366
   */
367
  for(i = g.gl_pathc - 1; i >= 0; i--)
368
    {
369
      char *fname = g.gl_pathv[i];
370
      struct stat fs;
371

    
372
      if (stat(fname, &fs) < 0)
373
        cf_error("Unable to stat included file %s: %m", fname);
374

    
375
      if (fs.st_mode & S_IFDIR)
376
        continue;
377

    
378
      /* Prepare new stack item */
379
      ifs = push_ifs(ifs);
380
      ifs->file_name = cfg_strdup(fname);
381
      ifs->depth = new_depth;
382
      ifs->up = base_ifs;
383
    }
384

    
385
  globfree(&g);
386
  enter_ifs(ifs);
387
}
388

    
389
static int
390
check_eof(void)
391
{
392
  if (ifs == ifs_head)
393
    {
394
      /* EOF in main config file */
395
      ifs->lino = 1; /* Why this? */
396
      return 1;
397
    }
398

    
399
  ifs = pop_ifs(ifs);
400
  enter_ifs(ifs);
401
  return 0;
402
}
403

    
404
static struct symbol *
405
cf_new_sym(byte *c, unsigned int h)
406
{
407
  struct symbol *s, **ht;
408
  int l;
409

    
410
  if (!new_config->sym_hash)
411
    new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
412
  ht = new_config->sym_hash;
413
  l = strlen(c);
414
  if (l > SYM_MAX_LEN)
415
    cf_error("Symbol too long");
416
  s = cfg_alloc(sizeof(struct symbol) + l);
417
  s->next = ht[h];
418
  ht[h] = s;
419
  s->scope = conf_this_scope;
420
  s->class = SYM_VOID;
421
  s->def = NULL;
422
  s->aux = 0;
423
  strcpy(s->name, c);
424
  return s;
425
}
426

    
427
static struct symbol *
428
cf_find_sym(byte *c, unsigned int h0)
429
{
430
  unsigned int h = h0 & (SYM_HASH_SIZE-1);
431
  struct symbol *s, **ht;
432

    
433
  if (ht = new_config->sym_hash)
434
    {
435
      for(s = ht[h]; s; s=s->next)
436
	if (!strcmp(s->name, c) && s->scope->active)
437
	  return s;
438
    }
439
  if (new_config->sym_fallback)
440
    {
441
      /* We know only top-level scope is active */
442
      for(s = new_config->sym_fallback[h]; s; s=s->next)
443
	if (!strcmp(s->name, c) && s->scope->active)
444
	  return s;
445
    }
446
  return cf_new_sym(c, h);
447
}
448

    
449
/**
450
 * cf_find_symbol - find a symbol by name
451
 * @c: symbol name
452
 *
453
 * This functions searches the symbol table for a symbol of given
454
 * name. First it examines the current scope, then the second recent
455
 * one and so on until it either finds the symbol and returns a pointer
456
 * to its &symbol structure or reaches the end of the scope chain
457
 * and returns %NULL to signify no match.
458
 */
459
struct symbol *
460
cf_find_symbol(byte *c)
461
{
462
  return cf_find_sym(c, cf_hash(c));
463
}
464

    
465
struct symbol *
466
cf_default_name(char *template, int *counter)
467
{
468
  char buf[32];
469
  struct symbol *s;
470
  char *perc = strchr(template, '%');
471

    
472
  for(;;)
473
    {
474
      bsprintf(buf, template, ++(*counter));
475
      s = cf_find_sym(buf, cf_hash(buf));
476
      if (!s)
477
	break;
478
      if (s->class == SYM_VOID)
479
	return s;
480
      if (!perc)
481
	break;
482
    }
483
  cf_error("Unable to generate default name");
484
}
485

    
486
/**
487
 * cf_define_symbol - define meaning of a symbol
488
 * @sym: symbol to be defined
489
 * @type: symbol class to assign
490
 * @def: class dependent data
491
 *
492
 * Defines new meaning of a symbol. If the symbol is an undefined
493
 * one (%SYM_VOID), it's just re-defined to the new type. If it's defined
494
 * in different scope, a new symbol in current scope is created and the
495
 * meaning is assigned to it. If it's already defined in the current scope,
496
 * an error is reported via cf_error().
497
 *
498
 * Result: Pointer to the newly defined symbol. If we are in the top-level
499
 * scope, it's the same @sym as passed to the function.
500
 */
501
struct symbol *
502
cf_define_symbol(struct symbol *sym, int type, void *def)
503
{
504
  if (sym->class)
505
    {
506
      if (sym->scope == conf_this_scope)
507
	cf_error("Symbol already defined");
508
      sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
509
    }
510
  sym->class = type;
511
  sym->def = def;
512
  return sym;
513
}
514

    
515
static void
516
cf_lex_init_kh(void)
517
{
518
  struct keyword *k;
519

    
520
  for(k=keyword_list; k->name; k++)
521
    {
522
      unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1);
523
      k->next = kw_hash[h];
524
      kw_hash[h] = k;
525
    }
526
  kw_hash_inited = 1;
527
}
528

    
529
/**
530
 * cf_lex_init - initialize the lexer
531
 * @is_cli: true if we're going to parse CLI command, false for configuration
532
 *
533
 * cf_lex_init() initializes the lexical analyzer and prepares it for
534
 * parsing of a new input.
535
 */
536
void
537
cf_lex_init(int is_cli, struct config *c)
538
{
539
  if (!kw_hash_inited)
540
    cf_lex_init_kh();
541

    
542
  ifs_head = ifs = push_ifs(NULL);
543
  if (!is_cli) 
544
    {
545
      ifs->file_name = c->file_name;
546
      ifs->fd = c->file_fd;
547
      ifs->depth = 1;
548
    }
549

    
550
  yyrestart(NULL);
551
  ifs->buffer = YY_CURRENT_BUFFER;
552

    
553
  if (is_cli)
554
    BEGIN(CLI);
555
  else
556
    BEGIN(INITIAL);
557

    
558
  conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
559
  conf_this_scope->active = 1;
560
}
561

    
562
/**
563
 * cf_push_scope - enter new scope
564
 * @sym: symbol representing scope name
565
 *
566
 * If we want to enter a new scope to process declarations inside
567
 * a nested block, we can just call cf_push_scope() to push a new
568
 * scope onto the scope stack which will cause all new symbols to be
569
 * defined in this scope and all existing symbols to be sought for
570
 * in all scopes stored on the stack.
571
 */
572
void
573
cf_push_scope(struct symbol *sym)
574
{
575
  struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
576

    
577
  s->next = conf_this_scope;
578
  conf_this_scope = s;
579
  s->active = 1;
580
  s->name = sym;
581
}
582

    
583
/**
584
 * cf_pop_scope - leave a scope
585
 *
586
 * cf_pop_scope() pops the topmost scope from the scope stack,
587
 * leaving all its symbols in the symbol table, but making them
588
 * invisible to the rest of the config.
589
 */
590
void
591
cf_pop_scope(void)
592
{
593
  conf_this_scope->active = 0;
594
  conf_this_scope = conf_this_scope->next;
595
  ASSERT(conf_this_scope);
596
}
597

    
598
struct symbol *
599
cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos)
600
{
601
  for(;;)
602
    {
603
      if (!sym)
604
	{
605
	  if (*pos >= SYM_HASH_SIZE)
606
	    return NULL;
607
	  sym = cf->sym_hash[(*pos)++];
608
	}
609
      else
610
	sym = sym->next;
611
      if (sym && sym->scope->active)
612
	return sym;
613
    }
614
}
615

    
616
/**
617
 * cf_symbol_class_name - get name of a symbol class
618
 * @sym: symbol
619
 *
620
 * This function returns a string representing the class
621
 * of the given symbol.
622
 */
623
char *
624
cf_symbol_class_name(struct symbol *sym)
625
{
626
  switch (sym->class)
627
    {
628
    case SYM_VOID:
629
      return "undefined";
630
    case SYM_PROTO:
631
      return "protocol";
632
    case SYM_NUMBER:
633
      return "numeric constant";
634
    case SYM_FUNCTION:
635
      return "function";
636
    case SYM_FILTER:
637
      return "filter";
638
    case SYM_TABLE:
639
      return "routing table";
640
    case SYM_IPA:
641
      return "network address";
642
    case SYM_TEMPLATE:
643
      return "protocol template";
644
    case SYM_ROA:
645
      return "ROA table";
646
    default:
647
      return "unknown type";
648
    }
649
}
650

    
651

    
652
/**
653
 * DOC: Parser
654
 *
655
 * Both the configuration and CLI commands are analyzed using a syntax
656
 * driven parser generated by the |bison| tool from a grammar which
657
 * is constructed from information gathered from grammar snippets by
658
 * the |gen_parser.m4| script.
659
 *
660
 * Grammar snippets are files (usually with extension |.Y|) contributed
661
 * by various BIRD modules in order to provide information about syntax of their
662
 * configuration and their CLI commands. Each snipped consists of several
663
 * sections, each of them starting with a special keyword: |CF_HDR| for
664
 * a list of |#include| directives needed by the C code, |CF_DEFINES|
665
 * for a list of C declarations, |CF_DECLS| for |bison| declarations
666
 * including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR|
667
 * for the grammar rules, |CF_CODE| for auxiliary C code and finally
668
 * |CF_END| at the end of the snippet.
669
 *
670
 * To create references between the snippets, it's possible to define
671
 * multi-part rules by utilizing the |CF_ADDTO| macro which adds a new
672
 * alternative to a multi-part rule.
673
 *
674
 * CLI commands are defined using a |CF_CLI| macro. Its parameters are:
675
 * the list of keywords determining the command, the list of parameters,
676
 * help text for the parameters and help text for the command.
677
 *
678
 * Values of |enum| filter types can be defined using |CF_ENUM| with
679
 * the following parameters: name of filter type, prefix common for all
680
 * literals of this type and names of all the possible values.
681
 */