starter: Add starter group and fix formatting of conf_parser_section_t enum
[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         \n                                      |
127         \\                                      {
128                 if (!streq(yytext, "\""))
129                 {
130                         if (streq(yytext, "\n"))
131                         {       /* put the newline back to fix the line numbers */
132                                 unput('\n');
133                                 yy_set_bol(0);
134                         }
135                         PARSER_DBG1(yyextra, "unterminated string detected");
136                 }
137                 if (yy_top_state(yyscanner) == inc)
138                 {       /* string include */
139                         include_files(yyextra);
140                         yy_pop_state(yyscanner);
141                         yy_pop_state(yyscanner);
142                 }
143                 else
144                 {
145                         yy_pop_state(yyscanner);
146                         yylval->s = yyextra->string_get(yyextra);
147                         return STRING;
148                 }
149         }
150         \\n     yyextra->string_add(yyextra, "\n");
151         \\r     yyextra->string_add(yyextra, "\r");
152         \\t     yyextra->string_add(yyextra, "\t");
153         \\b     yyextra->string_add(yyextra, "\b");
154         \\f     yyextra->string_add(yyextra, "\f");
155         \\(.|\n)                        {
156                 yyextra->string_add(yyextra, yytext+1);
157         }
158         [^\\\n"]+                       {
159                 yyextra->string_add(yyextra, yytext);
160         }
161 }
162
163 <<EOF>>                                 {
164         conf_parser_pop_buffer_state(yyscanner);
165         if (!conf_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
166         {
167                 yyterminate();
168         }
169 }
170
171 %%
172
173 /**
174  * Open the next file, if any is queued and readable, otherwise returns FALSE.
175  */
176 bool conf_parser_open_next_file(parser_helper_t *ctx)
177 {
178         FILE *file;
179
180         file = ctx->file_next(ctx);
181         if (!file)
182         {
183                 return FALSE;
184         }
185
186         conf_parser_set_in(file, ctx->scanner);
187         conf_parser_push_buffer_state(
188                         conf_parser__create_buffer(file, YY_BUF_SIZE,
189                                                                            ctx->scanner), ctx->scanner);
190         return TRUE;
191 }
192
193 /**
194  * Assumes that the file pattern to include is currently stored as string on
195  * the helper object.
196  */
197 static void include_files(parser_helper_t *ctx)
198 {
199         char *pattern = ctx->string_get(ctx);
200
201         ctx->file_include(ctx, pattern);
202         free(pattern);
203
204         conf_parser_open_next_file(ctx);
205 }