Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_lexer.l, 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: #include <utils/parser_helper.h>
18:
19: #include "settings_parser.h"
20:
21: bool settings_parser_open_next_file(parser_helper_t *ctx);
22:
23: static void include_files(parser_helper_t *ctx);
24:
25: %}
26: %option debug
27: %option warn
28:
29: /* use start conditions stack */
30: %option stack
31:
32: /* do not declare unneeded functions */
33: %option noinput noyywrap
34:
35: /* do not include unistd.h as it might conflict with our scanner states */
36: %option nounistd
37: /* due to that disable interactive mode, which requires isatty() */
38: %option never-interactive
39:
40: /* don't use global variables, and interact properly with bison */
41: %option reentrant bison-bridge
42:
43: /* maintain the line number */
44: %option yylineno
45:
46: /* don't generate a default rule */
47: %option nodefault
48:
49: /* prefix function/variable declarations */
50: %option prefix="settings_parser_"
51: /* don't change the name of the output file otherwise autotools has issues */
52: %option outfile="lex.yy.c"
53:
54: /* type of our extra data */
55: %option extra-type="parser_helper_t*"
56:
57: /* state used to scan references */
58: %x ref
59: /* state used to scan values */
60: %x val
61: /* state used to scan include file patterns */
62: %x inc
63: /* state used to scan quoted strings */
64: %x str
65:
66: /* pattern for section/key names */
67: NAME [^#{}:.,="\r\n\t ]
68:
69: %%
70:
71: [\t ]*#[^\r\n]* /* eat comments */
72: [\t\r ]+ /* eat whitespace */
73: \n|#.*\n /* eat newlines and comments at the end of a line */
74:
75: "{" |
76: "}" return yytext[0];
77:
78: "." return DOT;
79: "," return COMMA;
80:
81: ":" {
82: yy_push_state(ref, yyscanner);
83: return COLON;
84: }
85:
86: "=" {
87: yy_push_state(val, yyscanner);
88: return yytext[0];
89: }
90:
91: "include"[\t ]+/[^=] {
92: yyextra->string_init(yyextra);
93: yy_push_state(inc, yyscanner);
94: }
95:
96: "\"" {
97: PARSER_DBG1(yyextra, "unexpected string detected");
98: return STRING_ERROR;
99: }
100:
101: {NAME}+ {
102: yylval->s = strdup(yytext);
103: return NAME;
104: }
105:
106: <ref>{
107: [\t ]*#[^\r\n]* /* eat comments */
108: [\t\r ]+ /* eat whitespace */
109: \n|#.*\n /* eat newlines and comments at the end of a line */
110:
111: "," return COMMA;
112:
113: {NAME}+(\.{NAME}+)* {
114: yylval->s = strdup(yytext);
115: return NAME;
116: }
117:
118: . {
119: unput(yytext[0]);
120: yy_pop_state(yyscanner);
121: }
122: }
123:
124: <val>{
125: \r /* just ignore these */
126: [\t ]+
127: <<EOF>> |
128: [#}\n] {
129: if (*yytext)
130: {
131: switch (yytext[0])
132: {
133: case '\n':
134: /* put the newline back to fix the line numbers */
135: unput('\n');
136: yy_set_bol(0);
137: break;
138: case '#':
139: case '}':
140: /* these are parsed outside of this start condition */
141: unput(yytext[0]);
142: break;
143: }
144: }
145: yy_pop_state(yyscanner);
146: return NEWLINE;
147: }
148:
149: "\"" {
150: yyextra->string_init(yyextra);
151: yy_push_state(str, yyscanner);
152: }
153:
154: /* same as above, but allow more characters */
155: [^#}"\r\n\t ]+ {
156: yylval->s = strdup(yytext);
157: return NAME;
158: }
159: }
160:
161: <inc>{
162: \r /* just ignore these */
163: /* we allow all characters except #, } and spaces, they can be escaped */
164: <<EOF>> |
165: [#}\n\t ] {
166: if (*yytext)
167: {
168: switch (yytext[0])
169: {
170: case '\n':
171: /* put the newline back to fix the line numbers */
172: unput('\n');
173: yy_set_bol(0);
174: break;
175: case '#':
176: case '}':
177: /* these are parsed outside of this start condition */
178: unput(yytext[0]);
179: break;
180: }
181: }
182: include_files(yyextra);
183: yy_pop_state(yyscanner);
184: }
185: "\"" { /* string include */
186: yy_push_state(str, yyscanner);
187: }
188: \\ {
189: yyextra->string_add(yyextra, yytext);
190: }
191: \\["#} ] {
192: yyextra->string_add(yyextra, yytext+1);
193: }
194: [^"\\#}\r\n\t ]+ {
195: yyextra->string_add(yyextra, yytext);
196: }
197: }
198:
199: <str>{
200: \r /* just ignore these */
201: "\"" |
202: <<EOF>> |
203: \\ {
204: if (!streq(yytext, "\""))
205: {
206: PARSER_DBG1(yyextra, "unterminated string detected");
207: return STRING_ERROR;
208: }
209: if (yy_top_state(yyscanner) == inc)
210: { /* string include */
211: include_files(yyextra);
212: yy_pop_state(yyscanner);
213: yy_pop_state(yyscanner);
214: }
215: else
216: {
217: yy_pop_state(yyscanner);
218: yylval->s = yyextra->string_get(yyextra);
219: return STRING;
220: }
221: }
222:
223: \\n yyextra->string_add(yyextra, "\n");
224: \\r yyextra->string_add(yyextra, "\r");
225: \\t yyextra->string_add(yyextra, "\t");
226: \\\r?\n /* merge lines that end with escaped EOL characters */
227: \\. yyextra->string_add(yyextra, yytext+1);
228: [^\\\r"]+ {
229: yyextra->string_add(yyextra, yytext);
230: }
231: }
232:
233: <<EOF>> {
234: settings_parser_pop_buffer_state(yyscanner);
235: if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
236: {
237: yyterminate();
238: }
239: }
240:
241: %%
242:
243: /**
244: * Open the next file, if any is queued and readable, otherwise returns FALSE.
245: */
246: bool settings_parser_open_next_file(parser_helper_t *ctx)
247: {
248: FILE *file;
249:
250: file = ctx->file_next(ctx);
251: if (!file)
252: {
253: return FALSE;
254: }
255:
256: settings_parser_set_in(file, ctx->scanner);
257: settings_parser_push_buffer_state(
258: settings_parser__create_buffer(file, YY_BUF_SIZE,
259: ctx->scanner), ctx->scanner);
260: return TRUE;
261: }
262:
263: /**
264: * Assumes that the file pattern to include is currently stored as string on
265: * the helper object.
266: */
267: static void include_files(parser_helper_t *ctx)
268: {
269: char *pattern = ctx->string_get(ctx);
270:
271: ctx->file_include(ctx, pattern);
272: free(pattern);
273:
274: settings_parser_open_next_file(ctx);
275: }
276:
277: /**
278: * Load the given string to be parsed next
279: */
280: void settings_parser_load_string(parser_helper_t *ctx, const char *content)
281: {
282: settings_parser__scan_string(content, ctx->scanner);
283: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>