starter: Use automake LEX/YACC automatisms.
[strongswan.git] / src / starter / parser.y
1 %{
2 /* strongSwan config file parser (parser.y)
3  * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <freeswan.h>
21
22 #include "../pluto/constants.h"
23 #include "../pluto/defs.h"
24 #include "../pluto/log.h"
25 #include "ipsec-parser.h"
26
27 #define YYERROR_VERBOSE
28 #define ERRSTRING_LEN   256
29
30 /**
31  * Bison
32  */
33 static char parser_errstring[ERRSTRING_LEN+1];
34
35 extern void yyerror(const char *s);
36 extern int yylex (void);
37 extern void _parser_y_error(char *b, int size, const char *s);
38
39 /**
40  * Static Globals
41  */
42 static int _save_errors_;
43 static config_parsed_t *_parser_cfg;
44 static kw_list_t **_parser_kw, *_parser_kw_last;
45 static char errbuf[ERRSTRING_LEN+1];
46
47 /**
48  * Gperf
49  */
50 extern kw_entry_t *in_word_set (char *str, unsigned int len);
51
52 %}
53
54 %union { char *s; };
55 %token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN CA INCLUDE FILE_VERSION
56 %token <s> STRING
57
58 %%
59
60 /*
61  * Config file
62  */
63
64 config_file:
65         config_file section_or_include
66         | /* NULL */                
67         ;
68
69 section_or_include:
70         FILE_VERSION STRING EOL
71         {
72                 free($2);
73         }
74         | CONFIG SETUP EOL
75         {
76                 _parser_kw = &(_parser_cfg->config_setup);
77                 _parser_kw_last = NULL;
78         } kw_section
79         | CONN STRING EOL
80         {
81                 section_list_t *section = malloc_thing(section_list_t);
82                 
83                 section->name = clone_str($2);
84                 section->kw = NULL;
85                 section->next = NULL;
86                 _parser_kw = &(section->kw);
87                 if (!_parser_cfg->conn_first)
88                         _parser_cfg->conn_first = section;
89                 if (_parser_cfg->conn_last)
90                         _parser_cfg->conn_last->next = section;
91                 _parser_cfg->conn_last = section;
92                 _parser_kw_last = NULL;
93                 free($2);
94         } kw_section
95         | CA STRING EOL
96         {
97                 section_list_t *section = malloc_thing(section_list_t);
98                 section->name = clone_str($2);
99                 section->kw = NULL;
100                 section->next = NULL;
101                 _parser_kw = &(section->kw);
102                 if (!_parser_cfg->ca_first)
103                         _parser_cfg->ca_first = section;
104                 if (_parser_cfg->ca_last)
105                         _parser_cfg->ca_last->next = section;
106                 _parser_cfg->ca_last = section;
107                 _parser_kw_last = NULL;
108                 free($2);
109         } kw_section
110         | INCLUDE STRING
111         {
112                 extern void _parser_y_include (const char *f);
113                 _parser_y_include($2);
114                 free($2);
115         } EOL
116         | EOL
117         ;
118
119 kw_section:
120         FIRST_SPACES statement_kw EOL kw_section
121         |
122         ;
123
124 statement_kw:
125         STRING EQUAL STRING
126         {
127                 kw_list_t  *new;
128                 kw_entry_t *entry = in_word_set($1, strlen($1));
129
130                 if (entry == NULL)
131                 {
132                         snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", $1);
133                         yyerror(errbuf);
134                 }
135                 else if (_parser_kw)
136                 {
137                         new = (kw_list_t *)malloc_thing(kw_list_t);
138                         new->entry = entry;
139                         new->value = clone_str($3);
140                         new->next = NULL;
141                         if (_parser_kw_last)
142                                 _parser_kw_last->next = new;
143                         _parser_kw_last = new;
144                         if (!*_parser_kw)
145                                 *_parser_kw = new;
146                 }
147                 free($1);
148                 free($3);
149         }
150         | STRING EQUAL
151           {
152                 free($1);
153           }
154         |
155         ;
156
157 %%
158
159 void yyerror(const char *s)
160 {
161         if (_save_errors_)
162                 _parser_y_error(parser_errstring, ERRSTRING_LEN, s);
163 }
164
165 config_parsed_t *parser_load_conf(const char *file)
166 {
167         config_parsed_t *cfg = NULL;
168         int err = 0;
169         FILE *f;
170
171         extern void _parser_y_init(const char *f);
172         extern void _parser_y_fini(void);
173         extern FILE *yyin;
174
175         memset(parser_errstring, 0, ERRSTRING_LEN+1);
176
177         cfg = (config_parsed_t *)malloc_thing(config_parsed_t);
178         if (cfg)
179         {
180                 memset(cfg, 0, sizeof(config_parsed_t));
181                 f = fopen(file, "r");
182                 if (f)
183                 {
184                         yyin = f;
185                         _parser_y_init(file);
186                         _save_errors_ = 1;
187                         _parser_cfg = cfg;
188
189                         if (yyparse() !=0 )
190                         {
191                                 if (parser_errstring[0] == '\0')
192                                 {
193                                         snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error...");
194                                 }
195                                 _save_errors_ = 0;
196                                 while (yyparse() != 0);
197                                 err++;
198                         }
199                         else if (parser_errstring[0] != '\0')
200                         {
201                                 err++;
202                         }
203                         else
204                         {
205                                 /**
206                                  * Config valid
207                                  */
208                         }
209
210                         fclose(f);
211                 }
212                 else
213                 {
214                         snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file);
215                         err++;
216                 }
217         }
218         else
219         {
220                 snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory");
221                 err++;
222         }
223
224         if (err)
225         {
226                 plog("%s", parser_errstring);
227
228                 if (cfg)
229                         parser_free_conf(cfg);
230                 cfg = NULL;
231         }
232
233         _parser_y_fini();
234         return cfg;
235 }
236
237 static void parser_free_kwlist(kw_list_t *list)
238 {
239         kw_list_t *elt;
240
241         while (list)
242         {
243                 elt = list;
244                 list = list->next;
245                 free(elt->value);
246                 free(elt);
247         }
248 }
249
250 void parser_free_conf(config_parsed_t *cfg)
251 {
252         section_list_t *sec;
253         if (cfg)
254         {
255                 parser_free_kwlist(cfg->config_setup);
256                 while (cfg->conn_first)
257                 {
258                         sec = cfg->conn_first;
259                         cfg->conn_first = cfg->conn_first->next;
260                         free(sec->name);
261                         parser_free_kwlist(sec->kw);
262                         free(sec);
263                 }
264                 while (cfg->ca_first)
265                 {
266                         sec = cfg->ca_first;
267                         cfg->ca_first = cfg->ca_first->next;
268                         free(sec->name);
269                         parser_free_kwlist(sec->kw);
270                         free(sec);
271                 }
272                 free(cfg);
273         }
274 }