mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Gracefully handle files with no sections; extend the validate.sh test to try to validate an empty file.
173 lines
4.1 KiB
Plaintext
173 lines
4.1 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 }
|
|
|
|
%destructor { section_free ($$); } <sections>
|
|
%destructor { section_free ($$); } <section>
|
|
%destructor { field_free ($$); } <fields>
|
|
%destructor { field_free ($$); } <field>
|
|
|
|
%%
|
|
|
|
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; }
|
|
| emptylines
|
|
{ $$ = NULL; }
|
|
|
|
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, "%s%s%s%ssyntax error at line %d: %s\n",
|
|
context->program_name ? context->program_name : "",
|
|
context->program_name ? ": " : "",
|
|
context->input_file ? context->input_file : "",
|
|
context->input_file ? ": " : "",
|
|
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;
|
|
}
|