1998-11-27 19:35:50 +00:00
|
|
|
/*
|
|
|
|
* BIRD -- Configuration Lexer
|
|
|
|
*
|
2000-01-17 11:52:50 +00:00
|
|
|
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
1998-11-27 19:35:50 +00:00
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
2000-06-03 18:23:00 +00:00
|
|
|
/**
|
2000-06-07 12:29:08 +00:00
|
|
|
* DOC: Lexical analyzer
|
2000-06-03 18:23:00 +00:00
|
|
|
*
|
2000-06-07 12:29:08 +00:00
|
|
|
* The lexical analyzer used for configuration files and CLI commands
|
2000-06-07 13:25:53 +00:00
|
|
|
* is generated using the |flex| tool accompanied by a couple of
|
2000-06-03 18:23:00 +00:00
|
|
|
* functions maintaining the hash tables containing information about
|
|
|
|
* symbols and keywords.
|
|
|
|
*
|
|
|
|
* Each symbol is represented by a &symbol structure containing name
|
2013-07-25 20:33:57 +00:00
|
|
|
* of the symbol, its lexical scope, symbol class (%SYM_PROTO for a
|
|
|
|
* name of a protocol, %SYM_CONSTANT for a constant etc.) and class
|
|
|
|
* dependent data. When an unknown symbol is encountered, it's
|
|
|
|
* automatically added to the symbol table with class %SYM_VOID.
|
2000-06-03 18:23:00 +00:00
|
|
|
*
|
|
|
|
* The keyword tables are generated from the grammar templates
|
|
|
|
* using the |gen_keywords.m4| script.
|
|
|
|
*/
|
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
%{
|
1998-12-06 23:10:28 +00:00
|
|
|
#undef REJECT /* Avoid name clashes */
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2011-03-13 10:33:50 +00:00
|
|
|
#define PARSER 1
|
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
#include "nest/bird.h"
|
1999-11-15 11:35:41 +00:00
|
|
|
#include "nest/route.h"
|
2010-02-19 23:03:31 +00:00
|
|
|
#include "nest/protocol.h"
|
1999-11-15 11:35:41 +00:00
|
|
|
#include "filter/filter.h"
|
1998-11-27 19:35:50 +00:00
|
|
|
#include "conf/conf.h"
|
2018-08-13 09:41:27 +00:00
|
|
|
#include "conf/parser.h"
|
1998-11-27 19:35:50 +00:00
|
|
|
#include "conf/cf-parse.tab.h"
|
2000-01-17 11:52:50 +00:00
|
|
|
#include "lib/string.h"
|
2017-05-25 21:30:39 +00:00
|
|
|
#include "lib/hash.h"
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2000-04-28 15:12:03 +00:00
|
|
|
struct keyword {
|
1998-11-27 19:35:50 +00:00
|
|
|
byte *name;
|
|
|
|
int value;
|
|
|
|
struct keyword *next;
|
2000-04-28 15:12:03 +00:00
|
|
|
};
|
|
|
|
|
1999-01-10 00:18:32 +00:00
|
|
|
#include "conf/keywords.h"
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2017-05-30 12:43:49 +00:00
|
|
|
/* Could be defined by Bison in cf-parse.tab.h, inteferes with SYM hash */
|
|
|
|
#ifdef SYM
|
|
|
|
#undef SYM
|
|
|
|
#endif
|
|
|
|
|
1999-11-30 14:03:36 +00:00
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2017-05-25 21:30:39 +00:00
|
|
|
#define KW_KEY(n) n->name
|
|
|
|
#define KW_NEXT(n) n->next
|
|
|
|
#define KW_EQ(a,b) !strcmp(a,b)
|
|
|
|
#define KW_FN(k) cf_hash(k)
|
|
|
|
#define KW_ORDER 8 /* Fixed */
|
|
|
|
|
|
|
|
HASH(struct keyword) kw_hash;
|
1999-11-04 13:51:52 +00:00
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
#define YY_NO_UNPUT
|
2018-08-13 09:41:27 +00:00
|
|
|
#define CTX cfx_get_extra(yyscanner)
|
|
|
|
#define COR (CTX->order)
|
|
|
|
#define CST (CTX->order->state)
|
|
|
|
#define YY_INPUT(buf,result,max) result = COR->cf_read_hook(COR, buf, max);
|
|
|
|
#define YY_FATAL_ERROR(...) cf_error(CTX, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define cf_lval (* (cfx_get_lval(yyscanner)))
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
static void cf_include(char *arg, int alen, yyscan_t yyscanner);
|
|
|
|
static int check_eof(yyscan_t yyscanner);
|
2011-09-11 19:21:47 +00:00
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
%}
|
|
|
|
|
|
|
|
%option noyywrap
|
2010-05-02 20:41:40 +00:00
|
|
|
%option noinput
|
|
|
|
%option nounput
|
|
|
|
%option noreject
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
%option reentrant bison-bridge
|
|
|
|
%option extra-type="struct cf_context *"
|
|
|
|
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
%x COMMENT CCOMM CLI
|
1998-11-27 19:35:50 +00:00
|
|
|
|
|
|
|
ALPHA [a-zA-Z_]
|
|
|
|
DIGIT [0-9]
|
|
|
|
XIGIT [0-9a-fA-F]
|
|
|
|
ALNUM [a-zA-Z_0-9]
|
|
|
|
WHITE [ \t]
|
2011-09-11 19:21:47 +00:00
|
|
|
include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
|
1998-11-27 19:35:50 +00:00
|
|
|
|
|
|
|
%%
|
2012-07-18 17:29:33 +00:00
|
|
|
{include} {
|
|
|
|
char *start, *end;
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
if (!COR->cf_include)
|
|
|
|
YY_FATAL_ERROR("Include not allowed in CLI");
|
2012-07-18 17:29:33 +00:00
|
|
|
|
|
|
|
start = strchr(yytext, '"');
|
|
|
|
start++;
|
|
|
|
|
|
|
|
end = strchr(start, '"');
|
|
|
|
*end = 0;
|
|
|
|
|
|
|
|
if (start == end)
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Include with empty argument");
|
2012-07-18 17:29:33 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_include(start, end-start, yyscanner);
|
2012-07-18 17:29:33 +00:00
|
|
|
}
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2017-03-28 15:35:32 +00:00
|
|
|
{DIGIT}+:{DIGIT}+ {
|
2017-05-18 12:51:36 +00:00
|
|
|
uint len1 UNUSED, len2;
|
|
|
|
u64 l;
|
2017-03-28 15:35:32 +00:00
|
|
|
char *e;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
l = strtoul(yytext, &e, 10);
|
|
|
|
if (e && (*e != ':') || (errno == ERANGE) || (l >> 32))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("ASN out of range");
|
2017-03-28 15:35:32 +00:00
|
|
|
|
|
|
|
if (l >> 16)
|
|
|
|
{
|
|
|
|
len1 = 32;
|
|
|
|
len2 = 16;
|
|
|
|
cf_lval.i64 = (2ULL << 48) | (((u64) l) << len2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
len1 = 16;
|
|
|
|
len2 = 32;
|
|
|
|
cf_lval.i64 = 0 | (((u64) l) << len2);
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
l = strtoul(e+1, &e, 10);
|
|
|
|
if (e && *e || (errno == ERANGE) || (l >> len2))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Number out of range");
|
2017-03-28 15:35:32 +00:00
|
|
|
cf_lval.i64 |= l;
|
|
|
|
|
|
|
|
return VPN_RD;
|
|
|
|
}
|
|
|
|
|
2016-02-09 13:53:29 +00:00
|
|
|
[02]:{DIGIT}+:{DIGIT}+ {
|
2017-05-18 12:51:36 +00:00
|
|
|
uint len1, len2;
|
|
|
|
u64 l;
|
2016-02-09 13:53:29 +00:00
|
|
|
char *e;
|
|
|
|
|
|
|
|
if (yytext[0] == '0')
|
2017-02-20 01:26:45 +00:00
|
|
|
{
|
2016-02-09 13:53:29 +00:00
|
|
|
cf_lval.i64 = 0;
|
2017-02-20 01:26:45 +00:00
|
|
|
len1 = 16;
|
|
|
|
len2 = 32;
|
|
|
|
}
|
2016-02-09 13:53:29 +00:00
|
|
|
else
|
2017-02-20 01:26:45 +00:00
|
|
|
{
|
|
|
|
cf_lval.i64 = 2ULL << 48;
|
|
|
|
len1 = 32;
|
|
|
|
len2 = 16;
|
|
|
|
}
|
2016-02-09 13:53:29 +00:00
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
l = strtoul(yytext+2, &e, 10);
|
2017-02-20 01:26:45 +00:00
|
|
|
if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("ASN out of range");
|
2017-02-20 01:26:45 +00:00
|
|
|
cf_lval.i64 |= ((u64) l) << len2;
|
|
|
|
|
2016-02-09 13:53:29 +00:00
|
|
|
errno = 0;
|
|
|
|
l = strtoul(e+1, &e, 10);
|
2017-02-20 01:26:45 +00:00
|
|
|
if (e && *e || (errno == ERANGE) || (l >> len2))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Number out of range");
|
2016-02-09 13:53:29 +00:00
|
|
|
cf_lval.i64 |= l;
|
2017-02-20 01:26:45 +00:00
|
|
|
|
2016-02-09 13:53:29 +00:00
|
|
|
return VPN_RD;
|
|
|
|
}
|
|
|
|
|
2017-03-28 15:35:32 +00:00
|
|
|
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
|
2016-02-09 13:53:29 +00:00
|
|
|
unsigned long int l;
|
|
|
|
ip4_addr ip4;
|
2017-02-20 01:26:45 +00:00
|
|
|
char *e;
|
|
|
|
|
|
|
|
cf_lval.i64 = 1ULL << 48;
|
|
|
|
|
2017-03-28 15:35:32 +00:00
|
|
|
e = strchr(yytext, ':');
|
2017-02-20 01:26:45 +00:00
|
|
|
*e++ = '\0';
|
2017-03-28 15:35:32 +00:00
|
|
|
if (!ip4_pton(yytext, &ip4))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Invalid IPv4 address %s in Route Distinguisher", yytext);
|
2017-02-20 01:26:45 +00:00
|
|
|
cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
|
|
|
|
|
2016-02-09 13:53:29 +00:00
|
|
|
errno = 0;
|
|
|
|
l = strtoul(e, &e, 10);
|
2017-02-20 01:26:45 +00:00
|
|
|
if (e && *e || (errno == ERANGE) || (l >> 16))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Number out of range");
|
2017-02-20 01:26:45 +00:00
|
|
|
cf_lval.i64 |= l;
|
|
|
|
|
2016-02-09 13:53:29 +00:00
|
|
|
return VPN_RD;
|
|
|
|
}
|
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
|
2015-11-05 11:48:52 +00:00
|
|
|
if (!ip4_pton(yytext, &cf_lval.ip4))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Invalid IPv4 address %s", yytext);
|
2015-11-05 11:48:52 +00:00
|
|
|
return IP4;
|
1999-08-03 19:36:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
|
2015-11-05 11:48:52 +00:00
|
|
|
if (!ip6_pton(yytext, &cf_lval.ip6))
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Invalid IPv6 address %s", yytext);
|
2015-11-05 11:48:52 +00:00
|
|
|
return IP6;
|
1998-11-27 19:35:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-02 20:41:40 +00:00
|
|
|
0x{XIGIT}+ {
|
1998-11-27 19:35:50 +00:00
|
|
|
char *e;
|
2011-12-22 12:44:43 +00:00
|
|
|
unsigned long int l;
|
1998-11-27 19:35:50 +00:00
|
|
|
errno = 0;
|
|
|
|
l = strtoul(yytext+2, &e, 16);
|
2011-12-22 12:44:43 +00:00
|
|
|
if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Number out of range");
|
1998-11-27 19:35:50 +00:00
|
|
|
cf_lval.i = l;
|
|
|
|
return NUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
{DIGIT}+ {
|
|
|
|
char *e;
|
2011-12-22 12:44:43 +00:00
|
|
|
unsigned long int l;
|
1998-11-27 19:35:50 +00:00
|
|
|
errno = 0;
|
|
|
|
l = strtoul(yytext, &e, 10);
|
2011-12-22 12:44:43 +00:00
|
|
|
if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l)
|
2018-08-13 09:41:27 +00:00
|
|
|
YY_FATAL_ERROR("Number out of range");
|
1998-11-27 19:35:50 +00:00
|
|
|
cf_lval.i = l;
|
|
|
|
return NUM;
|
|
|
|
}
|
|
|
|
|
2011-03-23 11:49:53 +00:00
|
|
|
else: {
|
|
|
|
/* Hack to distinguish if..else from else: in case */
|
|
|
|
return ELSECOL;
|
|
|
|
}
|
|
|
|
|
2013-08-15 11:29:33 +00:00
|
|
|
({ALPHA}{ALNUM}*|[']({ALNUM}|[-]|[\.]|[:])*[']) {
|
2010-02-10 11:30:14 +00:00
|
|
|
if(*yytext == '\'') {
|
|
|
|
yytext[yyleng-1] = 0;
|
|
|
|
yytext++;
|
|
|
|
}
|
2017-05-25 21:30:39 +00:00
|
|
|
|
|
|
|
struct keyword *k = HASH_FIND(kw_hash, KW, yytext);
|
|
|
|
if (k)
|
|
|
|
{
|
|
|
|
if (k->value > 0)
|
|
|
|
return k->value;
|
|
|
|
else
|
1998-11-27 19:35:50 +00:00
|
|
|
{
|
2017-05-25 21:30:39 +00:00
|
|
|
cf_lval.i = -k->value;
|
|
|
|
return ENUM;
|
1998-11-27 19:35:50 +00:00
|
|
|
}
|
2017-05-25 21:30:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_lval.s = cf_get_symbol(CTX, yytext);
|
1998-11-27 19:35:50 +00:00
|
|
|
return SYM;
|
|
|
|
}
|
|
|
|
|
1999-12-02 12:04:39 +00:00
|
|
|
<CLI>(.|\n) {
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
BEGIN(INITIAL);
|
2018-08-23 18:44:04 +00:00
|
|
|
yyless(0);
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
return CLI_MARKER;
|
|
|
|
}
|
|
|
|
|
2011-05-06 20:00:54 +00:00
|
|
|
\.\. {
|
|
|
|
return DDOT;
|
|
|
|
}
|
|
|
|
|
2009-01-27 16:35:00 +00:00
|
|
|
[={}:;,.()+*/%<>~\[\]?!\|-] {
|
1998-11-27 19:35:50 +00:00
|
|
|
return yytext[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
["][^"\n]*["] {
|
1998-11-29 21:59:37 +00:00
|
|
|
yytext[yyleng-1] = 0;
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_lval.t = cf_strdup(CTX, yytext+1);
|
2016-11-16 10:03:39 +00:00
|
|
|
yytext[yyleng-1] = '"';
|
1998-11-27 19:35:50 +00:00
|
|
|
return TEXT;
|
|
|
|
}
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
["][^"\n]*\n YY_FATAL_ERROR("Unterminated string");
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
<INITIAL,COMMENT><<EOF>> { if (check_eof(yyscanner)) return END; }
|
1998-11-27 19:35:50 +00:00
|
|
|
|
|
|
|
{WHITE}+
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
\n CST->lino++;
|
1998-11-27 19:35:50 +00:00
|
|
|
|
1999-02-13 21:34:33 +00:00
|
|
|
# BEGIN(COMMENT);
|
1998-11-27 19:35:50 +00:00
|
|
|
|
1999-02-13 21:34:33 +00:00
|
|
|
\/\* BEGIN(CCOMM);
|
1998-11-27 19:35:50 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
. YY_FATAL_ERROR("Unknown character");
|
1998-11-27 19:35:50 +00:00
|
|
|
|
|
|
|
<COMMENT>\n {
|
2018-08-13 09:41:27 +00:00
|
|
|
CST->lino++;
|
1998-11-27 19:35:50 +00:00
|
|
|
BEGIN(INITIAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
<COMMENT>.
|
|
|
|
|
|
|
|
<CCOMM>\*\/ BEGIN(INITIAL);
|
2018-08-13 09:41:27 +00:00
|
|
|
<CCOMM>\n CST->lino++;
|
|
|
|
<CCOMM>\/\* YY_FATAL_ERROR("Comment nesting not supported");
|
|
|
|
<CCOMM><<EOF>> YY_FATAL_ERROR("Unterminated comment");
|
1998-11-27 19:35:50 +00:00
|
|
|
<CCOMM>.
|
|
|
|
|
2000-03-10 20:21:12 +00:00
|
|
|
\!\= return NEQ;
|
2016-09-20 13:13:01 +00:00
|
|
|
\!\~ return NMA;
|
2000-03-10 20:21:12 +00:00
|
|
|
\<\= return LEQ;
|
|
|
|
\>\= return GEQ;
|
2000-06-01 08:43:29 +00:00
|
|
|
\&\& return AND;
|
|
|
|
\|\| return OR;
|
2000-03-10 20:21:12 +00:00
|
|
|
|
2009-03-14 11:43:10 +00:00
|
|
|
\[\= return PO;
|
|
|
|
\=\] return PC;
|
|
|
|
|
1998-11-27 19:35:50 +00:00
|
|
|
%%
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
uint
|
1998-11-27 19:35:50 +00:00
|
|
|
cf_hash(byte *c)
|
|
|
|
{
|
2017-05-25 21:30:39 +00:00
|
|
|
uint h = 13 << 24;
|
1998-11-27 19:35:50 +00:00
|
|
|
|
|
|
|
while (*c)
|
2017-05-25 21:30:39 +00:00
|
|
|
h = h + (h >> 2) + (h >> 5) + ((uint) *c++ << 24);
|
1998-11-27 19:35:50 +00:00
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
static void
|
|
|
|
cf_init_state(struct cf_context *ctx, struct conf_state *cs)
|
2012-07-18 17:29:33 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
cs->buffer = yy_create_buffer(NULL, YY_BUF_SIZE, ctx->yyscanner);
|
2012-07-18 17:29:33 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
struct conf_state *
|
|
|
|
cf_new_state(struct cf_context *ctx, const char *name)
|
2011-09-11 19:21:47 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
struct conf_state *cs = cfg_alloc(sizeof(struct conf_state));
|
|
|
|
*cs = (struct conf_state) {
|
|
|
|
.name = cfg_strdup(name),
|
|
|
|
.lino = 1,
|
|
|
|
};
|
|
|
|
cf_init_state(ctx, cs);
|
|
|
|
return cs;
|
2012-07-18 17:29:33 +00:00
|
|
|
}
|
2011-09-11 19:21:47 +00:00
|
|
|
|
2014-03-25 13:58:00 +00:00
|
|
|
void
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_free_state(struct cf_context *ctx, struct conf_state *cs)
|
2014-03-25 13:58:00 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
yy_delete_buffer(cs->buffer, ctx->yyscanner);
|
|
|
|
/* The state structure is allocated from linpool, will be auto-freed. */
|
2014-03-25 13:58:00 +00:00
|
|
|
}
|
|
|
|
|
2012-07-18 17:29:33 +00:00
|
|
|
static void
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_include(char *arg, int alen, yyscan_t yyscanner)
|
2012-07-18 17:29:33 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
COR->cf_include(COR, arg, alen);
|
|
|
|
yy_switch_to_buffer(CST->buffer, yyscanner);
|
2011-09-11 19:21:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-08-13 09:41:27 +00:00
|
|
|
check_eof(yyscan_t yyscanner)
|
1999-05-17 20:06:19 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
if (!COR->cf_outclude)
|
|
|
|
return 1;
|
1999-05-17 20:06:19 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
if (COR->cf_outclude(COR))
|
|
|
|
return 1;
|
1998-11-27 21:07:02 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
yy_switch_to_buffer(CST->buffer, yyscanner);
|
|
|
|
return 0;
|
1999-05-17 20:06:19 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
void
|
|
|
|
cf_init_kh(void)
|
1999-11-30 14:03:36 +00:00
|
|
|
{
|
2017-05-25 21:30:39 +00:00
|
|
|
HASH_INIT(kw_hash, &root_pool, KW_ORDER);
|
1999-11-30 14:03:36 +00:00
|
|
|
|
2017-05-25 21:30:39 +00:00
|
|
|
struct keyword *k;
|
|
|
|
for (k=keyword_list; k->name; k++)
|
|
|
|
HASH_INSERT(kw_hash, KW, k);
|
1999-11-30 14:03:36 +00:00
|
|
|
}
|
|
|
|
|
2000-06-03 18:23:00 +00:00
|
|
|
/**
|
2018-08-13 09:41:27 +00:00
|
|
|
* cf_new_context - initialize the lexer
|
2000-06-03 18:23:00 +00:00
|
|
|
* @is_cli: true if we're going to parse CLI command, false for configuration
|
2016-05-12 13:49:44 +00:00
|
|
|
* @c: configuration structure
|
2000-06-03 18:23:00 +00:00
|
|
|
*
|
2018-08-13 09:41:27 +00:00
|
|
|
* cf_new_context() initializes the lexical analyzer and prepares it for
|
2000-06-03 18:23:00 +00:00
|
|
|
* parsing of a new input.
|
|
|
|
*/
|
2018-08-13 09:41:27 +00:00
|
|
|
struct cf_context *
|
|
|
|
cf_new_context(int is_cli, struct conf_order *order)
|
1998-11-27 19:35:50 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
struct cf_context *ctx = order->ctx = lp_allocz(order->new_config->mem, sizeof(struct cf_context));
|
|
|
|
*ctx = (struct cf_context) {
|
|
|
|
.new_config = order->new_config,
|
|
|
|
.cfg_mem = order->new_config->mem,
|
|
|
|
.order = order,
|
|
|
|
};
|
2012-07-18 17:29:33 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
cfx_lex_init_extra(ctx, &(ctx->yyscanner));
|
|
|
|
struct yyguts_t *yyg = ctx->yyscanner;
|
2012-07-18 17:29:33 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_init_state(ctx, order->state);
|
|
|
|
yy_switch_to_buffer(order->state->buffer, yyg);
|
2012-07-18 17:29:33 +00:00
|
|
|
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
if (is_cli)
|
|
|
|
BEGIN(CLI);
|
|
|
|
else
|
|
|
|
BEGIN(INITIAL);
|
2012-07-18 17:29:33 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
ctx->sym_scope = cfg_allocz(sizeof(struct sym_scope));
|
|
|
|
ctx->sym_scope->active = 1;
|
1999-11-04 13:51:52 +00:00
|
|
|
|
2018-08-13 09:41:27 +00:00
|
|
|
return ctx;
|
1999-11-04 13:51:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-08-13 09:41:27 +00:00
|
|
|
cf_free_context(struct cf_context *ctx)
|
1999-11-04 13:51:52 +00:00
|
|
|
{
|
2018-08-13 09:41:27 +00:00
|
|
|
cfx_lex_destroy(ctx->yyscanner);
|
1999-11-04 13:51:52 +00:00
|
|
|
}
|
2000-01-19 12:30:19 +00:00
|
|
|
|
2000-06-04 15:22:20 +00:00
|
|
|
/**
|
|
|
|
* DOC: Parser
|
|
|
|
*
|
2000-06-07 12:29:08 +00:00
|
|
|
* Both the configuration and CLI commands are analyzed using a syntax
|
2000-06-04 15:22:20 +00:00
|
|
|
* driven parser generated by the |bison| tool from a grammar which
|
|
|
|
* is constructed from information gathered from grammar snippets by
|
|
|
|
* the |gen_parser.m4| script.
|
|
|
|
*
|
|
|
|
* Grammar snippets are files (usually with extension |.Y|) contributed
|
2000-06-07 13:25:53 +00:00
|
|
|
* by various BIRD modules in order to provide information about syntax of their
|
2000-06-04 15:22:20 +00:00
|
|
|
* configuration and their CLI commands. Each snipped consists of several
|
2000-06-08 12:37:21 +00:00
|
|
|
* sections, each of them starting with a special keyword: |CF_HDR| for
|
2000-06-04 15:22:20 +00:00
|
|
|
* a list of |#include| directives needed by the C code, |CF_DEFINES|
|
|
|
|
* for a list of C declarations, |CF_DECLS| for |bison| declarations
|
|
|
|
* including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR|
|
2000-06-07 12:29:08 +00:00
|
|
|
* for the grammar rules, |CF_CODE| for auxiliary C code and finally
|
2000-06-04 15:22:20 +00:00
|
|
|
* |CF_END| at the end of the snippet.
|
|
|
|
*
|
|
|
|
* To create references between the snippets, it's possible to define
|
|
|
|
* multi-part rules by utilizing the |CF_ADDTO| macro which adds a new
|
|
|
|
* alternative to a multi-part rule.
|
|
|
|
*
|
|
|
|
* CLI commands are defined using a |CF_CLI| macro. Its parameters are:
|
2000-06-07 12:29:08 +00:00
|
|
|
* the list of keywords determining the command, the list of parameters,
|
2000-06-04 15:22:20 +00:00
|
|
|
* help text for the parameters and help text for the command.
|
|
|
|
*
|
|
|
|
* Values of |enum| filter types can be defined using |CF_ENUM| with
|
|
|
|
* the following parameters: name of filter type, prefix common for all
|
2000-06-08 12:37:21 +00:00
|
|
|
* literals of this type and names of all the possible values.
|
2000-06-04 15:22:20 +00:00
|
|
|
*/
|