3 * Copyright (C) 2013-2014 Tobias Brunner
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #define _GNU_SOURCE /* for asprintf() */
20 #include <utils/parser_helper.h>
21 #include <settings/settings_types.h>
22 #include <parser/conf_parser.h>
29 * Defined by the lexer
31 int conf_parser_lex(YYSTYPE *lvalp, void *scanner);
32 int conf_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
33 int conf_parser_lex_destroy(void *scanner);
34 int conf_parser_set_in(FILE *in, void *scanner);
35 void conf_parser_set_debug(int debug, void *scanner);
36 char *conf_parser_get_text(void *scanner);
37 int conf_parser_get_leng(void *scanner);
38 int conf_parser_get_lineno(void *scanner);
39 /* Custom functions in lexer */
40 bool conf_parser_open_next_file(parser_helper_t *ctx);
45 static void conf_parser_error(parser_helper_t *ctx, const char *s);
48 * Make sure to call lexer with the proper context
51 static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
53 return conf_parser_lex(lvalp, ctx->scanner);
59 /* generate verbose error messages */
61 /* generate a reentrant parser */
63 /* prefix function/variable declarations */
64 %name-prefix "conf_parser_"
66 /* interact properly with the reentrant lexer */
67 %lex-param {parser_helper_t *ctx}
68 %parse-param {parser_helper_t *ctx}
70 /* types for terminal symbols... */
73 conf_parser_section_t t;
76 %token EQ SPACES NEWLINE CONFIG_SETUP CONN CA
78 /* ...and other symbols */
79 %type <t> section_type
80 %type <s> section_name value
82 /* make the equal sign left associative */
85 /* properly destroy STRING tokens, which are strdup()ed, on errors */
86 %destructor { free($$); } STRING section_name value
88 /* there are two shift/reduce conflicts because we allow empty lines (and lines
89 * with spaces) within settings and anywhere else (i.e. in the beginning) */
95 * ipsec.conf grammar rules
100 | statements statement
109 section_type section_name
111 if ($1 != CONF_PARSER_CONFIG_SETUP && (!$2 || !strlen($2)))
113 PARSER_DBG1(ctx, "section name missing");
117 conf_parser_t *parser = (conf_parser_t*)ctx->context;
118 parser->add_section(parser, $1, $2);
125 $$ = CONF_PARSER_CONFIG_SETUP;
130 $$ = CONF_PARSER_CONN;
157 PARSER_DBG1(ctx, "setting name can't be empty");
162 conf_parser_t *parser = (conf_parser_t*)ctx->context;
163 parser->add_setting(parser, $1, $value);
170 PARSER_DBG1(ctx, "setting name can't be empty");
174 conf_parser_t *parser = (conf_parser_t*)ctx->context;
175 parser->add_setting(parser, $1, NULL);
180 PARSER_DBG1(ctx, "missing value for setting '%s'", $1);
189 { /* just put a single space between them, use strings for more */
190 if (asprintf(&$$, "%s %s", $1, $2) < 0)
204 * Referenced by the generated parser
206 static void conf_parser_error(parser_helper_t *ctx, const char *s)
208 char *text = conf_parser_get_text(ctx->scanner);
209 int len = conf_parser_get_leng(ctx->scanner);
211 if (len && text[len-1] == '\n')
212 { /* cut off newline at the end to avoid muti-line log messages */
215 PARSER_DBG1(ctx, "%s [%.*s]", s, (int)len, text);
219 * Parse the given file
221 bool conf_parser_parse_file(conf_parser_t *this, char *name)
223 parser_helper_t *helper;
224 bool success = FALSE;
226 helper = parser_helper_create(this);
227 helper->get_lineno = conf_parser_get_lineno;
228 if (conf_parser_lex_init_extra(helper, &helper->scanner) != 0)
230 helper->destroy(helper);
233 helper->file_include(helper, name);
234 if (!conf_parser_open_next_file(helper))
236 DBG1(DBG_CFG, "failed to open config file '%s'", name);
240 if (getenv("DEBUG_CONF_PARSER"))
243 conf_parser_set_debug(1, helper->scanner);
245 success = yyparse(helper) == 0;
248 DBG1(DBG_CFG, "invalid config file '%s'", name);
251 conf_parser_lex_destroy(helper->scanner);
252 helper->destroy(helper);