starter: Remove all ties to pluto/libfreeswan.
[strongswan.git] / src / starter / lexer.l
1 %option noinput
2 %option nounput
3 %{
4 /* FreeS/WAN config file parser (parser.l)
5  * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2 of the License, or (at your
10  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * for more details.
16  */
17
18 #include <string.h>
19 #include <stdlib.h>
20
21 #ifdef HAVE_GLOB_H
22 #include <glob.h>
23 #endif
24
25 #include "parser.h"
26
27 #define MAX_INCLUDE_DEPTH  20
28
29 extern void yyerror(const char *);
30 extern int yylex(void);
31 extern int yylex_destroy(void);
32
33 static struct {
34         int stack_ptr;
35         YY_BUFFER_STATE stack[MAX_INCLUDE_DEPTH];
36         FILE *file[MAX_INCLUDE_DEPTH];
37         unsigned int line[MAX_INCLUDE_DEPTH];
38         char *filename[MAX_INCLUDE_DEPTH];
39 } __parser_y_private;
40
41 void _parser_y_error(char *b, int size, const char *s);
42 void _parser_y_init (const char *f);
43 void _parser_y_fini (void);
44 int _parser_y_include (const char *filename);
45
46 void _parser_y_error(char *b, int size, const char *s)
47 {
48         extern char *yytext; // was: char yytext[];
49
50         snprintf(b, size, "%s:%d: %s [%s]",
51                         __parser_y_private.filename[__parser_y_private.stack_ptr],
52                         __parser_y_private.line[__parser_y_private.stack_ptr],
53                         s, yytext);
54 }
55
56 void _parser_y_init (const char *f)
57 {
58         memset(&__parser_y_private, 0, sizeof(__parser_y_private));
59         __parser_y_private.line[0] = 1;
60         __parser_y_private.filename[0] = strdup(f);
61 }
62
63 void _parser_y_fini (void)
64 {
65         unsigned int i;
66
67         for (i = 0; i < MAX_INCLUDE_DEPTH; i++)
68         {
69                 if (__parser_y_private.filename[i])
70                         free(__parser_y_private.filename[i]);
71                 if (__parser_y_private.file[i])
72                         fclose(__parser_y_private.file[i]);
73         }
74         memset(&__parser_y_private, 0, sizeof(__parser_y_private));
75         yylex_destroy();
76 }
77
78 /**
79  * parse the file located at filename
80  */
81 int include_file(char *filename)
82 {
83         unsigned int p = __parser_y_private.stack_ptr + 1;
84         FILE *f;
85
86         if (p >= MAX_INCLUDE_DEPTH)
87         {
88                 yyerror("max inclusion depth reached");
89                 return 1;
90         }
91
92         f = fopen(filename, "r");
93         if (!f)
94         {
95                 yyerror("can't open include filename");
96                 return 0; /* ignore this error */
97         }
98
99         __parser_y_private.stack_ptr++;
100         __parser_y_private.file[p] = f;
101         __parser_y_private.stack[p] = YY_CURRENT_BUFFER;
102         __parser_y_private.line[p] = 1;
103         __parser_y_private.filename[p] = strdup(filename);
104
105         yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
106         return 0;
107 }
108
109 int _parser_y_include (const char *filename)
110 {
111         int ret = 0;
112 #ifdef HAVE_GLOB_H
113         {
114                 glob_t files;
115                 int i;
116
117                 ret = glob(filename, GLOB_ERR, NULL, &files);
118                 if (ret)
119                 {
120                         const char *err;
121
122                         switch (ret)
123                         {
124                                 case GLOB_NOSPACE:
125                                         err = "include files ran out of memory";
126                                         break;
127                                 case GLOB_ABORTED:
128                                         err = "include files aborted due to read error";
129                                         break;
130                                 case GLOB_NOMATCH:
131                                         err = "include files found no matches";
132                                         break;
133                                 default:
134                                         err = "unknown include files error";
135                         }
136                         globfree(&files);
137                         yyerror(err);
138                         return 1;
139                 }
140
141                 for (i = 0; i < files.gl_pathc; i++)
142                 {
143                         if ((ret = include_file(files.gl_pathv[i])))
144                         {
145                                 break;
146                         }
147                 }
148                 globfree(&files);
149         }
150 #else /* HAVE_GLOB_H */
151         /* if glob(3) is not available, try to load pattern directly */
152         ret = include_file(filename);
153 #endif /* HAVE_GLOB_H */
154         return ret;
155 }
156
157 %}
158
159 %%
160
161 <<EOF>> {
162                 if (__parser_y_private.filename[__parser_y_private.stack_ptr]) {
163                                 free(__parser_y_private.filename[__parser_y_private.stack_ptr]);
164                                 __parser_y_private.filename[__parser_y_private.stack_ptr] = NULL;
165                 }
166                 if (__parser_y_private.file[__parser_y_private.stack_ptr]) {
167                                 fclose(__parser_y_private.file[__parser_y_private.stack_ptr]);
168                                 __parser_y_private.file[__parser_y_private.stack_ptr] = NULL;
169                                 yy_delete_buffer (YY_CURRENT_BUFFER);
170                                 yy_switch_to_buffer
171                                                 (__parser_y_private.stack[__parser_y_private.stack_ptr]);
172                 }
173                 if (--__parser_y_private.stack_ptr < 0) {
174                                 yyterminate();
175                 }
176 }
177
178 ^[\t ]+                 return FIRST_SPACES;
179
180 [\t ]+                  /* ignore spaces in line */ ;
181
182 =                               return EQUAL;
183
184 \n|#.*\n                {
185                                                                                 __parser_y_private.line[__parser_y_private.stack_ptr]++;
186                                                                                 return EOL;
187                                                                 }
188
189 config                  return CONFIG;
190 setup                   return SETUP;
191 conn                    return CONN;
192 ca                      return CA;
193 include                 return INCLUDE;
194 version                 return FILE_VERSION;
195
196 [^\"= \t\n]+    {
197                                                                                 yylval.s = strdup(yytext);
198                                                                                 return STRING;
199                                                                 }
200
201 \"[^\"\n]*\"    {
202                                                                                 yylval.s = strdup(yytext+1);
203                                                                                 if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0';
204                                                                                 return STRING;
205                                                                 }
206
207 .                               yyerror(yytext);
208
209 %%
210
211 int yywrap(void)
212 {
213         return 1;
214 }
215