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