mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Switch the lex/yacc parser into reentrant mode, to ease the handling of parsing-specific data; introduce a new parser_context struct for that, which is added as extra data to the parser. This should cause no behaviour changes in the parsing, just no more global variables used for getting data in/out the parser.
162 lines
3.7 KiB
Plaintext
162 lines
3.7 KiB
Plaintext
/* libguestfs virt-builder tool -*- fundamental -*-
|
|
* Copyright (C) 2013 Red Hat Inc.
|
|
*
|
|
* 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; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
%{
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "index-struct.h"
|
|
#include "index-parse.h"
|
|
|
|
#define YY_EXTRA_TYPE struct parse_context *
|
|
|
|
extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg);
|
|
extern int yylex (YYSTYPE * yylval, YYLTYPE * yylloc, yyscan_t scanner);
|
|
extern void scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in);
|
|
extern void scanner_destroy (yyscan_t scanner);
|
|
|
|
/* Join two strings with \n */
|
|
static char *
|
|
concat_newline (const char *str1, const char *str2)
|
|
{
|
|
size_t len1, len2, len;
|
|
char *ret;
|
|
|
|
if (str2 == NULL)
|
|
return strdup (str1);
|
|
|
|
len1 = strlen (str1);
|
|
len2 = strlen (str2);
|
|
len = len1 + 1 /* \n */ + len2 + 1 /* \0 */;
|
|
ret = malloc (len);
|
|
memcpy (ret, str1, len1);
|
|
ret[len1] = '\n';
|
|
memcpy (ret + len1 + 1, str2, len2);
|
|
ret[len-1] = '\0';
|
|
|
|
return ret;
|
|
}
|
|
|
|
%}
|
|
|
|
%code requires {
|
|
#include "index-parse.h"
|
|
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
|
#define YY_TYPEDEF_YY_SCANNER_T
|
|
typedef void *yyscan_t;
|
|
#endif
|
|
}
|
|
|
|
%locations
|
|
|
|
%union {
|
|
struct section *section;
|
|
struct field *field;
|
|
char *str;
|
|
}
|
|
|
|
%token <str> SECTION_HEADER
|
|
%token <field> FIELD
|
|
%token <str> VALUE_CONT
|
|
%token EMPTY_LINE
|
|
%token PGP_PROLOGUE
|
|
%token PGP_EPILOGUE
|
|
|
|
%type <section> sections section
|
|
%type <field> fields field
|
|
%type <str> continuations
|
|
|
|
%pure-parser
|
|
|
|
%lex-param { yyscan_t scanner }
|
|
%parse-param { yyscan_t scanner }
|
|
%parse-param { struct parse_context *context }
|
|
|
|
%%
|
|
|
|
index:
|
|
sections
|
|
{ context->parsed_index = $1; }
|
|
| PGP_PROLOGUE sections PGP_EPILOGUE
|
|
{ context->parsed_index = $2; }
|
|
|
|
sections:
|
|
section emptylines
|
|
{ $$ = $1; }
|
|
| section EMPTY_LINE emptylines sections
|
|
{ $$ = $1; $$->next = $4; }
|
|
|
|
section:
|
|
SECTION_HEADER fields
|
|
{ $$ = malloc (sizeof (struct section));
|
|
$$->next = NULL;
|
|
$$->name = $1;
|
|
$$->fields = $2; }
|
|
|
|
fields:
|
|
/* empty */
|
|
{ $$ = NULL; }
|
|
| field fields
|
|
{ $$ = $1; $$->next = $2; }
|
|
|
|
field: FIELD continuations
|
|
{ $$ = $1;
|
|
char *old_value = $$->value;
|
|
$$->value = concat_newline (old_value, $2);
|
|
free (old_value);
|
|
free ($2); }
|
|
|
|
continuations:
|
|
/* empty */
|
|
{ $$ = NULL; }
|
|
| VALUE_CONT continuations
|
|
{ $$ = concat_newline ($1, $2);
|
|
free ($1);
|
|
free ($2); }
|
|
|
|
emptylines:
|
|
/* empty */
|
|
{}
|
|
| EMPTY_LINE emptylines
|
|
{}
|
|
|
|
%%
|
|
|
|
void
|
|
yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg)
|
|
{
|
|
fprintf (stderr, "syntax error at line %d: %s\n",
|
|
yylloc->first_line, msg);
|
|
}
|
|
|
|
int
|
|
do_parse (struct parse_context *context, FILE *in)
|
|
{
|
|
yyscan_t scanner;
|
|
int res;
|
|
|
|
scanner_init (&scanner, context, in);
|
|
res = yyparse (scanner, context);
|
|
scanner_destroy (scanner);
|
|
|
|
return res;
|
|
}
|