+/**
+ * oconfig - src/parser.y
+ * Copyright (C) 2007 Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
%{
#include <stdlib.h>
#include <string.h>
#include "oconfig.h"
+#include "aux_types.h"
-static oconfig_item_t *ci_root;
-static oconfig_item_t *ci_current;
-
-static oconfig_item_t *statement_list;
-static int statement_list_num;
-
-static oconfig_value_t *argument_list;
-static int argument_list_num;
-
-struct statement_list_s
-{
- oconfig_item_t *statement;
- int statement_num;
-};
-typedef struct statement_list_s statement_list_t;
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
-struct argument_list_s
-{
- oconfig_value_t *argument;
- int argument_num;
-};
-typedef struct argument_list_s argument_list_t;
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
-static void dump_ci (oconfig_item_t *ci, int shift);
+extern oconfig_item_t *ci_root;
%}
%start entire_file
int boolean;
char *string;
oconfig_value_t cv;
- oconfig_value_t *cvp;
oconfig_item_t ci;
argument_list_t al;
statement_list_t sl;
%type <string> string
%type <string> identifier
-%type <string> block_end
+/* arguments */
%type <cv> argument
%type <al> argument_list
+/* blocks */
%type <ci> block_begin
%type <ci> block
+%type <string> block_end
+/* statements */
%type <ci> option
%type <ci> statement
%type <sl> statement_list
+%type <ci> entire_file
%%
string:
- QUOTED_STRING {$$ = $1;}
- | UNQUOTED_STRING {$$ = $1;}
+ QUOTED_STRING {$$ = unquote ($1);}
+ | UNQUOTED_STRING {$$ = strdup ($1);}
;
argument:
{
$$ = $1;
$$.argument_num++;
- $$.argument = realloc ($$.argument, $$.argument_num * sizeof (argument_list_t));
+ $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
$$.argument[$$.argument_num-1] = $2;
}
| argument
{
- $$.argument = malloc (sizeof (argument_list_t));
+ $$.argument = malloc (sizeof (oconfig_value_t));
$$.argument[0] = $1;
$$.argument_num = 1;
}
;
identifier:
- UNQUOTED_STRING {$$ = $1;}
+ UNQUOTED_STRING {$$ = strdup ($1);}
;
option:
$$.key = $1;
$$.values = $2.argument;
$$.values_num = $2.argument_num;
- printf ("Option `%s' has %i arguments\n", $$.key, $$.values_num);
}
;
$$.key = $2;
$$.values = $3.argument;
$$.values_num = $3.argument_num;
- printf ("Begin block `%s'\n", $2);
}
;
block_end:
- OPENBRAC SLASH identifier CLOSEBRAC EOL {$$ = $3; printf ("End block `%s'\n", $3);}
+ OPENBRAC SLASH identifier CLOSEBRAC EOL
+ {
+ $$ = $3;
+ }
;
block:
block_begin statement_list block_end
{
if (strcmp ($1.key, $3) != 0)
- yyerror ("Block %s not closed..\n", $1);
+ {
+ printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
+ yyerror ("Block not closed..\n");
+ exit (1);
+ }
$$ = $1;
$$.children = $2.statement;
+ $$.children_num = $2.statement_num;
}
;
statement:
option {$$ = $1;}
| block {$$ = $1;}
- | EOL {/* ignore */}
+ | EOL {$$.values_num = 0;}
;
statement_list:
statement_list statement
{
$$ = $1;
- $$.statement_num++;
- $$.statement = realloc ($$.statement, $$.statement_num * sizeof (statement_list_t));
- $$.statement[$$.statement_num-1] = $2;
- printf ("statement_list: length = %i\n", $$.statement_num);
+ if ($2.values_num > 0)
+ {
+ $$.statement_num++;
+ $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
+ $$.statement[$$.statement_num-1] = $2;
+ }
}
| statement
{
- $$.statement = malloc (sizeof (statement_list_t));
- $$.statement[0] = $1;
- $$.statement_num = 1;
+ if ($1.values_num > 0)
+ {
+ $$.statement = malloc (sizeof (oconfig_item_t));
+ $$.statement[0] = $1;
+ $$.statement_num = 1;
+ }
+ else
+ {
+ $$.statement = NULL;
+ $$.statement_num = 0;
+ }
}
;
entire_file:
statement_list
{
- int i;
- for (i = 0; i < $1.statement_num; i++)
- dump_ci ($1.statement + i, 0);
+ ci_root = malloc (sizeof (oconfig_item_t));
+ memset (ci_root, '\0', sizeof (oconfig_item_t));
+ ci_root->children = $1.statement;
+ ci_root->children_num = $1.statement_num;
}
;
%%
-#include "lex.yy.c"
-
-/*
-void yyerror (char *s)
+static int yyerror (const char *s)
{
- fprintf (stderr, "%s\n", s);
-}
+ fprintf (stderr, "Error in line %i near `%s': %s\n", yylineno, yytext, s);
+ return (-1);
+} /* int yyerror */
-int yylex (void)
+static char *unquote (const char *orig)
{
- return (getc (stdin));
-}
-*/
+ char *ret = strdup (orig);
+ int len;
+ int i;
-int main (int argc, char **argv)
-{
- yyparse ();
- return (0);
-}
+ if (ret == NULL)
+ return (NULL);
-static void dump_ci (oconfig_item_t *ci, int shift)
-{
- int i;
+ len = strlen (ret);
- if (shift > 0)
- printf ("%*s", "", shift);
+ if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+ return (ret);
- printf ("%s", ci->key);
- for (i = 0; i < ci->values_num; i++)
+ ret++;
+ len -= 2;
+ ret[len] = '\0';
+
+ for (i = 0; i < len; i++)
{
- oconfig_value_t cv = ci->values[i];
-
- if (cv.type == OCONFIG_TYPE_STRING)
- printf (" `%s'", cv.value.string);
- else if (cv.type == OCONFIG_TYPE_NUMBER)
- printf (" %lf", cv.value.number);
- else if (cv.type == OCONFIG_TYPE_BOOLEAN)
- printf (" %s", cv.value.boolean ? "true" : "false");
- else
- printf ("<unknown type %i>", cv.type);
+ if (ret[i] == '\\')
+ {
+ memmove (ret + i, ret + (i + 1), len - i);
+ len--;
+ }
}
- printf ("\n");
- for (i = 0; i < ci->children_num; i++)
- dump_ci (ci->children + i, shift + 1);
-}
+ return (ret);
+} /* char *unquote */