Code

store: Store a service/metric's parent hostname as an attribute.
[sysdb.git] / src / liboconfig / parser.y
1 /**
2  * SysDB - src/liboconfig/parser.y
3  * Based on collectd's oconfig, <http://collectd.org>
4  * Copyright (C) 2007,2008  Florian Forster
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
25 %{
26 #if HAVE_CONFIG_H
27 #       include "config.h"
28 #endif /* HAVE_CONFIG_H */
30 #include <stdlib.h>
31 #include <string.h>
32 #include "oconfig.h"
33 #include "aux_types.h"
35 static char *unquote (const char *orig);
36 static int yyerror (const char *s);
38 /* Lexer variables */
39 extern int yylineno;
40 extern char *yytext;
42 /* Lexer functions */
43 int yylex (void);
45 extern oconfig_item_t *ci_root;
46 extern char           *c_file;
47 %}
49 %start entire_file
51 %union {
52         double  number;
53         int     boolean;
54         char   *string;
55         oconfig_value_t  cv;
56         oconfig_item_t   ci;
57         argument_list_t  al;
58         statement_list_t sl;
59 }
61 %token <number> NUMBER
62 %token <boolean> BTRUE BFALSE
63 %token <string> QUOTED_STRING UNQUOTED_STRING
64 %token SLASH OPENBRAC CLOSEBRAC EOL
66 %type <string> string
67 %type <string> identifier
68 /* arguments */
69 %type <cv> argument
70 %type <al> argument_list
71 /* blocks */
72 %type <ci> block_begin
73 %type <ci> block
74 %type <string> block_end
75 /* statements */
76 %type <ci> option
77 %type <ci> statement
78 %type <sl> statement_list
79 %type <ci> entire_file
81 /* pass an verbose, specific error message to yyerror() */
82 %error-verbose
84 %%
85 string:
86         QUOTED_STRING           {$$ = unquote ($1);}
87         | UNQUOTED_STRING       {$$ = strdup ($1);}
88         ;
90 argument:
91         NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
92         | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
93         | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
94         | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
95         ;
97 argument_list:
98         argument_list argument
99         {
100          $$ = $1;
101          $$.argument_num++;
102          $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
103          $$.argument[$$.argument_num-1] = $2;
104         }
105         | argument
106         {
107          $$.argument = malloc (sizeof (oconfig_value_t));
108          $$.argument[0] = $1;
109          $$.argument_num = 1;
110         }
111         ;
113 identifier:
114         UNQUOTED_STRING                 {$$ = strdup ($1);}
115         ;
117 option:
118         identifier argument_list EOL
119         {
120          memset (&$$, '\0', sizeof ($$));
121          $$.key = $1;
122          $$.values = $2.argument;
123          $$.values_num = $2.argument_num;
124         }
125         ;
127 block_begin:
128         OPENBRAC identifier CLOSEBRAC EOL
129         {
130          memset (&$$, '\0', sizeof ($$));
131          $$.key = $2;
132         }
133         |
134         OPENBRAC identifier argument_list CLOSEBRAC EOL
135         {
136          memset (&$$, '\0', sizeof ($$));
137          $$.key = $2;
138          $$.values = $3.argument;
139          $$.values_num = $3.argument_num;
140         }
141         ;
143 block_end:
144         OPENBRAC SLASH identifier CLOSEBRAC EOL
145         {
146          $$ = $3;
147         }
148         ;
150 block:
151         block_begin statement_list block_end
152         {
153          if (strcmp ($1.key, $3) != 0)
154          {
155                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
156                 yyerror ("Block not closed..\n");
157                 exit (1);
158          }
159          free ($3); $3 = NULL;
160          $$ = $1;
161          $$.children = $2.statement;
162          $$.children_num = $2.statement_num;
163         }
164         | block_begin block_end
165         {
166          if (strcmp ($1.key, $2) != 0)
167          {
168                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
169                 yyerror ("Block not closed..\n");
170                 exit (1);
171          }
172          free ($2); $2 = NULL;
173          $$ = $1;
174          $$.children = NULL;
175          $$.children_num = 0;
176         }
177         ;
179 statement:
180         option          {$$ = $1;}
181         | block         {$$ = $1;}
182         | EOL           {$$.values_num = 0;}
183         ;
185 statement_list:
186         statement_list statement
187         {
188          $$ = $1;
189          if (($2.values_num > 0) || ($2.children_num > 0))
190          {
191                  $$.statement_num++;
192                  $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
193                  $$.statement[$$.statement_num-1] = $2;
194          }
195         }
196         | statement
197         {
198          if (($1.values_num > 0) || ($1.children_num > 0))
199          {
200                  $$.statement = malloc (sizeof (oconfig_item_t));
201                  $$.statement[0] = $1;
202                  $$.statement_num = 1;
203          }
204          else
205          {
206                 $$.statement = NULL;
207                 $$.statement_num = 0;
208          }
209         }
210         ;
212 entire_file:
213         statement_list
214         {
215          ci_root = malloc (sizeof (oconfig_item_t));
216          memset (ci_root, '\0', sizeof (oconfig_item_t));
217          ci_root->children = $1.statement;
218          ci_root->children_num = $1.statement_num;
219         }
220         | /* epsilon */
221         {
222          ci_root = malloc (sizeof (oconfig_item_t));
223          memset (ci_root, '\0', sizeof (oconfig_item_t));
224          ci_root->children = NULL;
225          ci_root->children_num = 0;
226         }
227         ;
229 %%
230 static int yyerror (const char *s)
232         char *text;
234         if (*yytext == '\n')
235                 text = "<newline>";
236         else
237                 text = yytext;
239         fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
240                 c_file, yylineno, text, s);
241         return (-1);
242 } /* int yyerror */
244 static char *unquote (const char *orig)
246         char *ret = strdup (orig);
247         int len;
248         int i;
250         if (ret == NULL)
251                 return (NULL);
253         len = strlen (ret);
255         if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
256                 return (ret);
258         len -= 2;
259         memmove (ret, ret + 1, len);
260         ret[len] = '\0';
262         for (i = 0; i < len; i++)
263         {
264                 if (ret[i] == '\\')
265                 {
266                         memmove (ret + i, ret + (i + 1), len - i);
267                         len--;
268                 }
269         }
271         return (ret);
272 } /* char *unquote */