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