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