Annotation of embedaddon/strongswan/src/starter/parser/parser.y, revision 1.1.1.2
1.1 misho 1: %{
2: /*
3: * Copyright (C) 2013-2014 Tobias Brunner
4: * HSR Hochschule fuer Technik Rapperswil
5: *
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>.
10: *
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
14: * for more details.
15: */
16:
17: #define _GNU_SOURCE /* for asprintf() */
18: #include <stdio.h>
19:
20: #include <utils/parser_helper.h>
21: #include <settings/settings_types.h>
22: #include <parser/conf_parser.h>
23:
24: #include "parser.h"
25:
26: #define YYDEBUG 1
27:
28: /**
29: * Defined by the lexer
30: */
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);
41:
42: /**
43: * Forward declaration
44: */
45: static void conf_parser_error(parser_helper_t *ctx, const char *s);
46:
47: /**
48: * Make sure to call lexer with the proper context
49: */
50: #undef yylex
1.1.1.2 ! misho 51: static int yylex(CONF_PARSER_STYPE *yylval, parser_helper_t *ctx)
1.1 misho 52: {
1.1.1.2 ! misho 53: return conf_parser_lex(yylval, ctx->scanner);
1.1 misho 54: }
55:
56: %}
57: %debug
58:
59: /* generate verbose error messages */
1.1.1.2 ! misho 60: %define parse.error verbose
1.1 misho 61: /* generate a reentrant parser */
62: %define api.pure
63: /* prefix function/variable declarations */
1.1.1.2 ! misho 64: %define api.prefix {conf_parser_}
! 65: /* make sure flex uses the right definition */
! 66: %code provides
! 67: {
! 68: #define YY_DECL \
! 69: int conf_parser_lex(CONF_PARSER_STYPE *yylval, void *yyscanner)
! 70: YY_DECL;
! 71: }
1.1 misho 72:
73: /* interact properly with the reentrant lexer */
74: %lex-param {parser_helper_t *ctx}
75: %parse-param {parser_helper_t *ctx}
76:
77: /* types for terminal symbols... */
78: %union {
79: char *s;
80: conf_parser_section_t t;
81: }
82: %token <s> STRING
83: %token EQ SPACES NEWLINE CONFIG_SETUP CONN CA STRING_ERROR
84:
85: /* ...and other symbols */
86: %type <t> section_type
87: %type <s> section_name value
88:
89: /* make the equal sign left associative */
90: %left EQ
91:
92: /* properly destroy STRING tokens, which are strdup()ed, on errors */
93: %destructor { free($$); } STRING section_name value
94:
95: /* there are two shift/reduce conflicts because we allow empty lines (and lines
96: * with spaces) within settings and anywhere else (i.e. in the beginning) */
97: //%expect 2
98:
99: %%
100:
101: /**
102: * ipsec.conf grammar rules
103: */
104: statements:
105: /* empty */
106: | statements NEWLINE
107: | statements statement
108: ;
109:
110: statement:
111: section
112: | SPACES setting
113: ;
114:
115: section:
116: section_type section_name
117: {
118: if ($1 != CONF_PARSER_CONFIG_SETUP && (!$2 || !strlen($2)))
119: {
120: PARSER_DBG1(ctx, "section name missing");
121: free($2);
122: YYERROR;
123: }
124: conf_parser_t *parser = (conf_parser_t*)ctx->context;
125: parser->add_section(parser, $1, $2);
126: }
127: ;
128:
129: section_type:
130: CONFIG_SETUP
131: {
132: $$ = CONF_PARSER_CONFIG_SETUP;
133: }
134: |
135: CONN
136: {
137: $$ = CONF_PARSER_CONN;
138: }
139: |
140: CA
141: {
142: $$ = CONF_PARSER_CA;
143: }
144: ;
145:
146: section_name:
147: /* empty */
148: {
149: $$ = NULL;
150: }
151: | STRING
152: {
153: $$ = $1;
154: }
155: ;
156:
157: setting:
158: /* empty */
159: |
160: STRING EQ value
161: {
162: if (!strlen($1))
163: {
164: PARSER_DBG1(ctx, "setting name can't be empty");
165: free($1);
166: free($3);
167: YYERROR;
168: }
169: conf_parser_t *parser = (conf_parser_t*)ctx->context;
170: parser->add_setting(parser, $1, $value);
171: }
172: |
173: STRING EQ
174: {
175: if (!strlen($1))
176: {
177: PARSER_DBG1(ctx, "setting name can't be empty");
178: free($1);
179: YYERROR;
180: }
181: conf_parser_t *parser = (conf_parser_t*)ctx->context;
182: parser->add_setting(parser, $1, NULL);
183: }
184: |
185: STRING
186: {
187: PARSER_DBG1(ctx, "missing value for setting '%s'", $1);
188: free($1);
189: YYERROR;
190: }
191: ;
192:
193: value:
194: STRING
195: | value STRING
196: { /* just put a single space between them, use strings for more */
197: if (asprintf(&$$, "%s %s", $1, $2) < 0)
198: {
199: free($1);
200: free($2);
201: YYERROR;
202: }
203: free($1);
204: free($2);
205: }
206: ;
207:
208: %%
209:
210: /**
211: * Referenced by the generated parser
212: */
213: static void conf_parser_error(parser_helper_t *ctx, const char *s)
214: {
215: char *text = conf_parser_get_text(ctx->scanner);
216: int len = conf_parser_get_leng(ctx->scanner);
217:
218: if (len && text[len-1] == '\n')
219: { /* cut off newline at the end to avoid muti-line log messages */
220: len--;
221: }
222: PARSER_DBG1(ctx, "%s [%.*s]", s, (int)len, text);
223: }
224:
225: /**
226: * Parse the given file
227: */
228: bool conf_parser_parse_file(conf_parser_t *this, char *name)
229: {
230: parser_helper_t *helper;
231: bool success = FALSE;
232:
233: helper = parser_helper_create(this);
234: helper->get_lineno = conf_parser_get_lineno;
235: if (conf_parser_lex_init_extra(helper, &helper->scanner) != 0)
236: {
237: helper->destroy(helper);
238: return FALSE;
239: }
240: helper->file_include(helper, name);
241: if (!conf_parser_open_next_file(helper))
242: {
243: DBG1(DBG_CFG, "failed to open config file '%s'", name);
244: }
245: else
246: {
247: if (getenv("DEBUG_CONF_PARSER"))
248: {
249: yydebug = 1;
250: conf_parser_set_debug(1, helper->scanner);
251: }
252: success = yyparse(helper) == 0;
253: if (!success)
254: {
255: DBG1(DBG_CFG, "invalid config file '%s'", name);
256: }
257: }
258: conf_parser_lex_destroy(helper->scanner);
259: helper->destroy(helper);
260: return success;
261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>