Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_parser.y, revision 1.1.1.2
1.1 misho 1: %{
2: /*
3: * Copyright (C) 2014-2018 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 <library.h>
21: #include <collections/array.h>
22: #include <settings/settings_types.h>
23: #include <utils/parser_helper.h>
24:
25: #include "settings_parser.h"
26:
27: #define YYDEBUG 1
28:
29: /**
30: * Defined by the lexer
31: */
32: int settings_parser_lex(YYSTYPE *lvalp, void *scanner);
33: int settings_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
34: int settings_parser_lex_destroy(void *scanner);
35: int settings_parser_set_in(FILE *in, void *scanner);
36: void settings_parser_set_debug(int debug, void *scanner);
37: char *settings_parser_get_text(void *scanner);
38: int settings_parser_get_leng(void *scanner);
39: int settings_parser_get_lineno(void *scanner);
40: /* Custom functions in lexer */
41: bool settings_parser_open_next_file(parser_helper_t *ctx);
42: bool settings_parser_load_string(parser_helper_t *ctx, const char *content);
43:
44: /**
45: * Forward declarations
46: */
47: static void settings_parser_error(parser_helper_t *ctx, const char *s);
48: static section_t *push_section(parser_helper_t *ctx, char *name);
49: static section_t *pop_section(parser_helper_t *ctx);
50: static void add_section(parser_helper_t *ctx, section_t *section);
51: static void add_setting(parser_helper_t *ctx, kv_t *kv);
52: static void add_references(parser_helper_t *ctx, array_t *references);
53:
54: /**
55: * Make sure to call lexer with the proper context
56: */
57: #undef yylex
1.1.1.2 ! misho 58: static int yylex(SETTINGS_PARSER_STYPE *yylval, parser_helper_t *ctx)
1.1 misho 59: {
1.1.1.2 ! misho 60: return settings_parser_lex(yylval, ctx->scanner);
1.1 misho 61: }
62:
63: %}
64: %debug
65:
66: /* generate verbose error messages */
1.1.1.2 ! misho 67: %define parse.error verbose
1.1 misho 68: /* generate a reentrant parser */
69: %define api.pure
70: /* prefix function/variable declarations */
1.1.1.2 ! misho 71: %define api.prefix {settings_parser_}
! 72: /* make sure flex uses the right definition */
! 73: %code provides
! 74: {
! 75: #define YY_DECL \
! 76: int settings_parser_lex(SETTINGS_PARSER_STYPE *yylval, void *yyscanner)
! 77: YY_DECL;
! 78: }
1.1 misho 79:
80: /* interact properly with the reentrant lexer */
81: %lex-param {parser_helper_t *ctx}
82: %parse-param {parser_helper_t *ctx}
83:
84: /* types for terminal symbols... (can't use the typedef'd types) */
85: %union {
86: char *s;
87: struct section_t *sec;
88: struct kv_t *kv;
89: array_t *refs;
90: }
91: %token <s> NAME STRING
92: %token DOT "."
93: %token COMMA ","
94: %token COLON ":"
95: %token NEWLINE STRING_ERROR
96:
97: /* ...and other symbols */
98: %type <s> value valuepart
99: %type <sec> section_start section
100: %type <kv> setting
101: %type <refs> references
102:
103: /* properly destroy string tokens that are strdup()ed on error */
104: %destructor { free($$); } NAME STRING value valuepart
105: /* properly destroy parse results on error */
106: %destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
107: %destructor { settings_kv_destroy($$, NULL); } setting
108: %destructor { array_destroy_function($$, (void*)free, NULL); } references
109:
110: /* there are two shift/reduce conflicts because of the "NAME = NAME" and
111: * "NAME {" ambiguity, and the "NAME =" rule) */
112: %expect 2
113:
114: %%
115:
116: /**
117: * strongswan.conf grammar rules
118: */
119: statements:
120: /* empty */
121: | statements NEWLINE
122: | statements statement
123: ;
124:
125: statement:
126: section
127: {
128: add_section(ctx, $section);
129: }
130: | setting
131: {
132: add_setting(ctx, $setting);
133: }
134: ;
135:
136: section:
137: section_start statements '}'
138: {
139: pop_section(ctx);
140: $$ = $section_start;
141: }
142: ;
143:
144: section_start:
145: NAME '{'
146: {
147: $$ = push_section(ctx, $NAME);
148: }
149: |
150: NAME ":" references '{'
151: {
152: $$ = push_section(ctx, $NAME);
153: add_references(ctx, $references);
154: array_destroy($references);
155: }
156: ;
157:
158: references:
159: NAME
160: {
161: $$ = array_create(0, 0);
162: array_insert($$, ARRAY_TAIL, $1);
163: }
164: | references "," NAME
165: {
166: array_insert($1, ARRAY_TAIL, $3);
167: $$ = $1;
168: }
169: ;
170:
171: setting:
172: NAME '=' value
173: {
174: $$ = settings_kv_create($NAME, $value);
175: }
176: |
177: NAME '='
178: {
179: $$ = settings_kv_create($NAME, NULL);
180: }
181: ;
182:
183: value:
184: valuepart
185: | value valuepart
186: { /* just put a single space between them, use strings for more */
187: if (asprintf(&$$, "%s %s", $1, $2) < 0)
188: {
189: free($1);
190: free($2);
191: YYERROR;
192: }
193: free($1);
194: free($2);
195: }
196: ;
197:
198: valuepart:
199: NAME
200: | STRING
201: ;
202:
203: %%
204:
205: /**
206: * Referenced by the generated parser
207: */
208: static void settings_parser_error(parser_helper_t *ctx, const char *s)
209: {
210: char *text = settings_parser_get_text(ctx->scanner);
211: int len = settings_parser_get_leng(ctx->scanner);
212:
213: if (len && text[len-1] == '\n')
214: { /* cut off newline at the end to avoid muti-line log messages */
215: len--;
216: }
217: PARSER_DBG1(ctx, "%s [%.*s]", s, len, text);
218: }
219:
220: /**
221: * Create a section and push it to the stack (the name is adopted), returns
222: * the created section
223: */
224: static section_t *push_section(parser_helper_t *ctx, char *name)
225: {
226: array_t *sections = (array_t*)ctx->context;
227: section_t *section;
228:
229: section = settings_section_create(name);
230: array_insert(sections, ARRAY_TAIL, section);
231: return section;
232: }
233:
234: /**
235: * Removes the top section of the stack and returns it
236: */
237: static section_t *pop_section(parser_helper_t *ctx)
238: {
239: array_t *sections = (array_t*)ctx->context;
240: section_t *section;
241:
242: array_remove(sections, ARRAY_TAIL, §ion);
243: return section;
244: }
245:
246: /**
247: * Adds the given section to the section on top of the stack
248: */
249: static void add_section(parser_helper_t *ctx, section_t *section)
250: {
251: array_t *sections = (array_t*)ctx->context;
252: section_t *parent;
253:
254: array_get(sections, ARRAY_TAIL, &parent);
255: settings_section_add(parent, section, NULL);
256: }
257:
258: /**
259: * Adds the given key/value pair to the section on top of the stack
260: */
261: static void add_setting(parser_helper_t *ctx, kv_t *kv)
262: {
263: array_t *sections = (array_t*)ctx->context;
264: section_t *section;
265:
266: array_get(sections, ARRAY_TAIL, §ion);
267: settings_kv_add(section, kv, NULL);
268: }
269:
270: /**
271: * Adds the given references to the section on top of the stack
272: */
273: static void add_references(parser_helper_t *ctx, array_t *references)
274: {
275: array_t *sections = (array_t*)ctx->context;
276: section_t *section;
277: enumerator_t *refs;
278: char *ref;
279:
280: array_get(sections, ARRAY_TAIL, §ion);
281:
282: refs = array_create_enumerator(references);
283: while (refs->enumerate(refs, &ref))
284: {
285: settings_reference_add(section, ref, FALSE);
286: array_remove_at(references, refs);
287: }
288: refs->destroy(refs);
289: }
290:
291: /**
292: * Parse the given file and add all sections and key/value pairs to the
293: * given section.
294: */
295: bool settings_parser_parse_file(section_t *root, char *name)
296: {
297: parser_helper_t *helper;
298: array_t *sections = NULL;
299: bool success = FALSE;
300:
301: array_insert_create(§ions, ARRAY_TAIL, root);
302: helper = parser_helper_create(sections);
303: helper->get_lineno = settings_parser_get_lineno;
304: if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
305: {
306: helper->destroy(helper);
307: array_destroy(sections);
308: return FALSE;
309: }
310: helper->file_include(helper, name);
311: if (!settings_parser_open_next_file(helper))
312: {
313: if (lib->conf && streq(name, lib->conf))
314: {
315: DBG2(DBG_CFG, "failed to open config file '%s'", name);
316: }
317: else
318: {
319: DBG1(DBG_CFG, "failed to open config file '%s'", name);
320: }
321: }
322: else
323: {
324: if (getenv("DEBUG_SETTINGS_PARSER"))
325: {
326: yydebug = 1;
327: settings_parser_set_debug(1, helper->scanner);
328: }
329: success = yyparse(helper) == 0;
330: if (!success)
331: {
332: DBG1(DBG_CFG, "invalid config file '%s'", name);
333: }
334: }
335: array_destroy(sections);
336: settings_parser_lex_destroy(helper->scanner);
337: helper->destroy(helper);
338: return success;
339: }
340:
341: /**
342: * Parse the given string and add all sections and key/value pairs to the
343: * given section.
344: */
345: bool settings_parser_parse_string(section_t *root, char *settings)
346: {
347: parser_helper_t *helper;
348: array_t *sections = NULL;
349: bool success = FALSE;
350:
351: array_insert_create(§ions, ARRAY_TAIL, root);
352: helper = parser_helper_create(sections);
353: helper->get_lineno = settings_parser_get_lineno;
354: if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
355: {
356: helper->destroy(helper);
357: array_destroy(sections);
358: return FALSE;
359: }
360: settings_parser_load_string(helper, settings);
361: if (getenv("DEBUG_SETTINGS_PARSER"))
362: {
363: yydebug = 1;
364: settings_parser_set_debug(1, helper->scanner);
365: }
366: success = yyparse(helper) == 0;
367: if (!success)
368: {
369: DBG1(DBG_CFG, "failed to parse settings '%s'", settings);
370: }
371: array_destroy(sections);
372: settings_parser_lex_destroy(helper->scanner);
373: helper->destroy(helper);
374: return success;
375: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>