parser-helper: Make parser_helper_file_t private
[strongswan.git] / src / libstrongswan / settings / settings_lexer.l
1 %{
2 /*
3  * Copyright (C) 2014 Tobias Brunner
4  * 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 perf-report
28
29 %option warn
30
31 /* use start conditions stack */
32 %option stack
33
34 /* do not declare unneded functions */
35 %option noinput noyywrap
36
37 /* don't use global variables, and interact properly with bison */
38 %option reentrant bison-bridge
39
40 /* maintain the line number */
41 %option yylineno
42
43 /* don't generate a default rule */
44 %option nodefault
45
46 /* prefix function/variable declarations */
47 %option prefix="settings_parser_"
48 /* don't change the name of the output file otherwise autotools has issues */
49 %option outfile="lex.yy.c"
50
51 /* type of our extra data */
52 %option extra-type="parser_helper_t*"
53
54 /* state used to scan include file patterns */
55 %x inc
56 /* state used to scan quoted strings */
57 %x str
58
59 %%
60
61 [\t ]*#[^\n]*                   /* eat comments */
62 [\t ]+                                  /* eat whitespace */
63 \n|#.*\n                                return NEWLINE; /* also eats comments at the end of a line */
64
65 "{"                                             |
66 "}"                                             |
67 "="                                             return yytext[0];
68
69 "include"[\t ]+/[^=]    {
70         yyextra->string_init(yyextra);
71         yy_push_state(inc, yyscanner);
72 }
73
74 "\""                                    {
75         yyextra->string_init(yyextra);
76         yy_push_state(str, yyscanner);
77 }
78
79 [^#{}="\n\t ]+                  {
80         yylval->s = strdup(yytext);
81         return NAME;
82 }
83
84 <inc>{
85         /* we allow all characters except #, } and spaces, they can be escaped */
86         <<EOF>>                         |
87         \n|#.*\n                        |
88         [\t ]                           {
89                 if (*yytext && yytext[strlen(yytext) - 1] == '\n')
90                 {       /* put the newline back to fix the line numbers */
91                         unput('\n');
92                         yy_set_bol(0);
93                 }
94                 include_files(yyextra);
95                 yy_pop_state(yyscanner);
96         }
97         "\""                            {       /* string include */
98                 yy_push_state(str, yyscanner);
99         }
100         \\                                      {
101                 yyextra->string_add(yyextra, yytext);
102         }
103         \\["#} ]                        {
104                 yyextra->string_add(yyextra, yytext+1);
105         }
106         [^"\\#}\n\t ]+ {
107                 yyextra->string_add(yyextra, yytext);
108         }
109 }
110
111 <str>{
112         "\""                            |
113         <<EOF>>                         |
114         \n                                      |
115         \\                                      {
116                 if (!streq(yytext, "\""))
117                 {
118                         if (streq(yytext, "\n"))
119                         {       /* put the newline back to fix the line numbers */
120                                 unput('\n');
121                                 yy_set_bol(0);
122                         }
123                         PARSER_DBG1(yyextra, "unterminated string detected");
124                 }
125                 if (yy_top_state(yyscanner) == inc)
126                 {       /* string include */
127                         include_files(yyextra);
128                         yy_pop_state(yyscanner);
129                         yy_pop_state(yyscanner);
130                 }
131                 else
132                 {
133                         yy_pop_state(yyscanner);
134                         yylval->s = yyextra->string_get(yyextra);
135                         return STRING;
136                 }
137         }
138         \\n     yyextra->string_add(yyextra, "\n");
139         \\r     yyextra->string_add(yyextra, "\r");
140         \\t     yyextra->string_add(yyextra, "\t");
141         \\b     yyextra->string_add(yyextra, "\b");
142         \\f     yyextra->string_add(yyextra, "\f");
143         \\(.|\n)                        {
144                 yyextra->string_add(yyextra, yytext+1);
145         }
146         [^\\\n"]+                       {
147                 yyextra->string_add(yyextra, yytext);
148         }
149 }
150
151 <<EOF>>                                 {
152         settings_parser_pop_buffer_state(yyscanner);
153         if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
154         {
155                 yyterminate();
156         }
157 }
158
159 %%
160
161 /**
162  * Open the next file, if any is queued and readable, otherwise returns FALSE.
163  */
164 bool settings_parser_open_next_file(parser_helper_t *ctx)
165 {
166         FILE *file;
167
168         file = ctx->file_next(ctx);
169         if (!file)
170         {
171                 return FALSE;
172         }
173
174         settings_parser_set_in(file, ctx->scanner);
175         settings_parser_push_buffer_state(
176                         settings_parser__create_buffer(file, YY_BUF_SIZE,
177                                                                                    ctx->scanner), ctx->scanner);
178         return TRUE;
179 }
180
181 /**
182  * Assumes that the file pattern to include is currently stored as string on
183  * the helper object.
184  */
185 static void include_files(parser_helper_t *ctx)
186 {
187         char *pattern = ctx->string_get(ctx);
188
189         ctx->file_include(ctx, pattern);
190         free(pattern);
191
192         settings_parser_open_next_file(ctx);
193 }