Code

plugin: Make sdb_plugin_info_t public.
[sysdb.git] / src / liboconfig / parser.y
1 /**
2  * oconfig - src/parser.y
3  * Copyright (C) 2007,2008  Florian octo Forster <octo at verplant.org>
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; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  */
19 %{
20 #if HAVE_CONFIG_H
21 #       include "config.h"
22 #endif /* HAVE_CONFIG_H */
24 #include <stdlib.h>
25 #include <string.h>
26 #include "oconfig.h"
27 #include "aux_types.h"
29 static char *unquote (const char *orig);
30 static int yyerror (const char *s);
32 /* Lexer variables */
33 extern int yylineno;
34 extern char *yytext;
36 /* Lexer functions */
37 int yylex (void);
39 extern oconfig_item_t *ci_root;
40 extern char           *c_file;
41 %}
43 %start entire_file
45 %union {
46         double  number;
47         int     boolean;
48         char   *string;
49         oconfig_value_t  cv;
50         oconfig_item_t   ci;
51         argument_list_t  al;
52         statement_list_t sl;
53 }
55 %token <number> NUMBER
56 %token <boolean> BTRUE BFALSE
57 %token <string> QUOTED_STRING UNQUOTED_STRING
58 %token SLASH OPENBRAC CLOSEBRAC EOL
60 %type <string> string
61 %type <string> identifier
62 /* arguments */
63 %type <cv> argument
64 %type <al> argument_list
65 /* blocks */
66 %type <ci> block_begin
67 %type <ci> block
68 %type <string> block_end
69 /* statements */
70 %type <ci> option
71 %type <ci> statement
72 %type <sl> statement_list
73 %type <ci> entire_file
75 /* pass an verbose, specific error message to yyerror() */
76 %error-verbose
78 %%
79 string:
80         QUOTED_STRING           {$$ = unquote ($1);}
81         | UNQUOTED_STRING       {$$ = strdup ($1);}
82         ;
84 argument:
85         NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
86         | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
87         | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
88         | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
89         ;
91 argument_list:
92         argument_list argument
93         {
94          $$ = $1;
95          $$.argument_num++;
96          $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
97          $$.argument[$$.argument_num-1] = $2;
98         }
99         | argument
100         {
101          $$.argument = malloc (sizeof (oconfig_value_t));
102          $$.argument[0] = $1;
103          $$.argument_num = 1;
104         }
105         ;
107 identifier:
108         UNQUOTED_STRING                 {$$ = strdup ($1);}
109         ;
111 option:
112         identifier argument_list EOL
113         {
114          memset (&$$, '\0', sizeof ($$));
115          $$.key = $1;
116          $$.values = $2.argument;
117          $$.values_num = $2.argument_num;
118         }
119         ;
121 block_begin:
122         OPENBRAC identifier CLOSEBRAC EOL
123         {
124          memset (&$$, '\0', sizeof ($$));
125          $$.key = $2;
126         }
127         |
128         OPENBRAC identifier argument_list CLOSEBRAC EOL
129         {
130          memset (&$$, '\0', sizeof ($$));
131          $$.key = $2;
132          $$.values = $3.argument;
133          $$.values_num = $3.argument_num;
134         }
135         ;
137 block_end:
138         OPENBRAC SLASH identifier CLOSEBRAC EOL
139         {
140          $$ = $3;
141         }
142         ;
144 block:
145         block_begin statement_list block_end
146         {
147          if (strcmp ($1.key, $3) != 0)
148          {
149                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
150                 yyerror ("Block not closed..\n");
151                 exit (1);
152          }
153          free ($3); $3 = NULL;
154          $$ = $1;
155          $$.children = $2.statement;
156          $$.children_num = $2.statement_num;
157         }
158         | block_begin block_end
159         {
160          if (strcmp ($1.key, $2) != 0)
161          {
162                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
163                 yyerror ("Block not closed..\n");
164                 exit (1);
165          }
166          free ($2); $2 = NULL;
167          $$ = $1;
168          $$.children = NULL;
169          $$.children_num = 0;
170         }
171         ;
173 statement:
174         option          {$$ = $1;}
175         | block         {$$ = $1;}
176         | EOL           {$$.values_num = 0;}
177         ;
179 statement_list:
180         statement_list statement
181         {
182          $$ = $1;
183          if (($2.values_num > 0) || ($2.children_num > 0))
184          {
185                  $$.statement_num++;
186                  $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
187                  $$.statement[$$.statement_num-1] = $2;
188          }
189         }
190         | statement
191         {
192          if (($1.values_num > 0) || ($1.children_num > 0))
193          {
194                  $$.statement = malloc (sizeof (oconfig_item_t));
195                  $$.statement[0] = $1;
196                  $$.statement_num = 1;
197          }
198          else
199          {
200                 $$.statement = NULL;
201                 $$.statement_num = 0;
202          }
203         }
204         ;
206 entire_file:
207         statement_list
208         {
209          ci_root = malloc (sizeof (oconfig_item_t));
210          memset (ci_root, '\0', sizeof (oconfig_item_t));
211          ci_root->children = $1.statement;
212          ci_root->children_num = $1.statement_num;
213         }
214         | /* epsilon */
215         {
216          ci_root = malloc (sizeof (oconfig_item_t));
217          memset (ci_root, '\0', sizeof (oconfig_item_t));
218          ci_root->children = NULL;
219          ci_root->children_num = 0;
220         }
221         ;
223 %%
224 static int yyerror (const char *s)
226         char *text;
228         if (*yytext == '\n')
229                 text = "<newline>";
230         else
231                 text = yytext;
233         fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
234                 c_file, yylineno, text, s);
235         return (-1);
236 } /* int yyerror */
238 static char *unquote (const char *orig)
240         char *ret = strdup (orig);
241         int len;
242         int i;
244         if (ret == NULL)
245                 return (NULL);
247         len = strlen (ret);
249         if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
250                 return (ret);
252         len -= 2;
253         memmove (ret, ret + 1, len);
254         ret[len] = '\0';
256         for (i = 0; i < len; i++)
257         {
258                 if (ret[i] == '\\')
259                 {
260                         memmove (ret + i, ret + (i + 1), len - i);
261                         len--;
262                 }
263         }
265         return (ret);
266 } /* char *unquote */