diff --git a/builder/index-parse.y b/builder/index-parse.y index a8d2f6250..dee2aec9e 100644 --- a/builder/index-parse.y +++ b/builder/index-parse.y @@ -24,9 +24,14 @@ #include #include "index-struct.h" +#include "index-parse.h" -extern void yyerror (const char *); -extern int yylex (void); +#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 * @@ -52,6 +57,14 @@ concat_newline (const char *str1, const char *str2) %} +%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 { @@ -71,13 +84,19 @@ concat_newline (const char *str1, const char *str2) %type fields field %type continuations +%pure-parser + +%lex-param { yyscan_t scanner } +%parse-param { yyscan_t scanner } +%parse-param { struct parse_context *context } + %% index: sections - { parsed_index = $1; } + { context->parsed_index = $1; } | PGP_PROLOGUE sections PGP_EPILOGUE - { parsed_index = $2; } + { context->parsed_index = $2; } sections: section emptylines @@ -122,8 +141,21 @@ emptylines: %% void -yyerror (const char *msg) +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); + 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; } diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c index fbbebffb9..7aeb6d0cb 100644 --- a/builder/index-parser-c.c +++ b/builder/index-parser-c.c @@ -43,7 +43,7 @@ extern void unix_error (int errcode, char * cmdname, value arg) Noreturn; #include "index-struct.h" #include "index-parse.h" -extern FILE *yyin; +extern int do_parse (struct parse_context *context, FILE *in); value virt_builder_parse_index (value filenamev) @@ -52,26 +52,30 @@ virt_builder_parse_index (value filenamev) CAMLlocal5 (rv, v, sv, sv2, fv); struct section *sections; size_t i, nr_sections; + struct parse_context context; + FILE *in; - yyin = fopen (String_val (filenamev), "r"); - if (yyin == NULL) + parse_context_init (&context); + + in = fopen (String_val (filenamev), "r"); + if (in == NULL) unix_error (errno, (char *) "fopen", filenamev); - if (yyparse () != 0) { - fclose (yyin); + if (do_parse (&context, in) != 0) { + fclose (in); caml_invalid_argument ("parse error"); } - if (fclose (yyin) == EOF) + if (fclose (in) == EOF) unix_error (errno, (char *) "fclose", filenamev); /* Convert the parsed data to OCaml structures. */ nr_sections = 0; - for (sections = parsed_index; sections != NULL; sections = sections->next) + for (sections = context.parsed_index; sections != NULL; sections = sections->next) nr_sections++; rv = caml_alloc (nr_sections, 0); - for (i = 0, sections = parsed_index; sections != NULL; + for (i = 0, sections = context.parsed_index; sections != NULL; i++, sections = sections->next) { struct field *fields; size_t j, nr_fields; @@ -105,8 +109,8 @@ virt_builder_parse_index (value filenamev) Store_field (rv, i, v); /* assign to return array of sections */ } - /* Free parsed global data. */ - free_index (); + /* Free parsed data. */ + parse_context_free (&context); CAMLreturn (rv); } diff --git a/builder/index-scan.l b/builder/index-scan.l index 832ea516d..073d85fb9 100644 --- a/builder/index-scan.l +++ b/builder/index-scan.l @@ -23,18 +23,22 @@ #include #include -#include "index-parse.h" #include "index-struct.h" +#include "index-parse.h" -#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; +#define YY_EXTRA_TYPE struct parse_context * +#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; -extern void yyerror (const char *); +extern void yyerror (YYLTYPE * yylloc, yyscan_t scanner, struct parse_context *context, const char *msg); %} %option nounput %option noyywrap %option yylineno +%option reentrant +%option bison-bridge +%option bison-locations %% @@ -46,38 +50,38 @@ extern void yyerror (const char *); */ /* Ignore comments - '#' MUST appear at the start of a line. */ -^"#".*\n { seen_comments++; } +^"#".*\n { yyextra->seen_comments++; } /* An empty line is significant. */ ^\n { return EMPTY_LINE; } /* [...] marks beginning of a section. */ ^"["[-A-Za-z0-9._]+"]"\n { - yylval.str = strndup (yytext+1, yyleng-3); + yylval->str = strndup (yytext+1, yyleng-3); return SECTION_HEADER; } /* field=value or field[subfield]=value */ ^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n { size_t i = strcspn (yytext, "=["); - yylval.field = malloc (sizeof (struct field)); - yylval.field->next = NULL; - yylval.field->key = strndup (yytext, i); + yylval->field = malloc (sizeof (struct field)); + yylval->field->next = NULL; + yylval->field->key = strndup (yytext, i); if (yytext[i] == '[') { size_t j = strcspn (yytext+i+1, "]"); - yylval.field->subkey = strndup (yytext+i+1, j); + yylval->field->subkey = strndup (yytext+i+1, j); i += 1+j+1; } else { - yylval.field->subkey = NULL; + yylval->field->subkey = NULL; } /* Note we chop the final \n off here. */ - yylval.field->value = strndup (yytext+i+1, yyleng-(i+2)); + yylval->field->value = strndup (yytext+i+1, yyleng-(i+2)); return FIELD; } /* Continuation line for multi-line values. */ ^[[:blank:]].*\n { - yylval.str = strndup (yytext+1, yyleng-2); + yylval->str = strndup (yytext+1, yyleng-2); return VALUE_CONT; } @@ -86,7 +90,7 @@ extern void yyerror (const char *); int c, prevnl = 0; /* Eat everything to the first blank line. */ - while ((c = input ()) != EOF) { + while ((c = input (yyscanner)) != EOF) { if (c == '\n' && prevnl) break; prevnl = c == '\n'; @@ -98,7 +102,7 @@ extern void yyerror (const char *); /* Hack to eat the PGP epilogue. */ ^"-----BEGIN PGP SIGNATURE-----\n" { /* Eat everything to the end of the file. */ - while (input () != EOF) + while (input (yyscanner) != EOF) ; return PGP_EPILOGUE; @@ -106,6 +110,22 @@ extern void yyerror (const char *); /* anything else is an error */ . { - yyerror ("unexpected character in input"); + yyerror (yylloc, yyscanner, yyextra, "unexpected character in input"); exit (EXIT_FAILURE); } + +%% + +void +scanner_init (yyscan_t *scanner, struct parse_context *context, FILE *in) +{ + yylex_init (scanner); + yyset_extra (context, *scanner); + yyset_in (in, *scanner); +} + +void +scanner_destroy (yyscan_t scanner) +{ + yylex_destroy (scanner); +} diff --git a/builder/index-struct.c b/builder/index-struct.c index fe5b0e386..f32534cae 100644 --- a/builder/index-struct.c +++ b/builder/index-struct.c @@ -20,19 +20,23 @@ #include #include +#include #include "index-struct.h" -struct section *parsed_index = NULL; -int seen_comments = 0; - static void free_section (struct section *section); static void free_field (struct field *field); void -free_index (void) +parse_context_init (struct parse_context *context) { - free_section (parsed_index); + memset (context, 0, sizeof *context); +} + +void +parse_context_free (struct parse_context *context) +{ + free_section (context->parsed_index); } static void diff --git a/builder/index-struct.h b/builder/index-struct.h index f92e01d37..94805261a 100644 --- a/builder/index-struct.h +++ b/builder/index-struct.h @@ -36,14 +36,19 @@ struct field { char *value; }; -/* The parser (yyparse) stores the result here. */ -extern struct section *parsed_index; +/* A struct holding the data needed during the parsing. */ +struct parse_context { + struct section *parsed_index; /* The result of the parsing. */ + /* yyparse sets this if any comments were seen. Required for checking + * compatibility with virt-builder 1.24. + */ + int seen_comments; +}; -/* yyparse sets this if any comments were seen. Required for checking - * compatibility with virt-builder 1.24. - */ -extern int seen_comments; +/* Initialize the content of a parse_context. */ +extern void parse_context_init (struct parse_context *state); -extern void free_index (void); +/* Free the content of a parse_context. The actual pointer is not freed. */ +extern void parse_context_free (struct parse_context *state); #endif /* INDEX_STRUCT_H */ diff --git a/builder/index-validate.c b/builder/index-validate.c index 7f02ffb30..4b7fe9377 100644 --- a/builder/index-validate.c +++ b/builder/index-validate.c @@ -33,7 +33,7 @@ #include "index-struct.h" #include "index-parse.h" -extern FILE *yyin; +extern int do_parse (struct parse_context *context, FILE *in); static void usage (int exit_status) @@ -60,11 +60,15 @@ main (int argc, char *argv[]) int compat_1_24_1 = 0; const char *input; struct section *sections; + struct parse_context context; + FILE *in; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); + parse_context_init (&context); + for (;;) { c = getopt_long (argc, argv, options, long_options, &option_index); if (c == -1) break; @@ -99,32 +103,32 @@ main (int argc, char *argv[]) input = argv[optind++]; - yyin = fopen (input, "r"); - if (yyin == NULL) { + in = fopen (input, "r"); + if (in == NULL) { perror (input); exit (EXIT_FAILURE); } - if (yyparse () != 0) { + if (do_parse (&context, in) != 0) { fprintf (stderr, _("%s: '%s' could not be validated, see errors above\n"), program_name, input); exit (EXIT_FAILURE); } - if (fclose (yyin) == EOF) { + if (fclose (in) == EOF) { fprintf (stderr, _("%s: %s: error reading input file: %m\n"), program_name, input); exit (EXIT_FAILURE); } - if (compat_1_24_1 && seen_comments) { + if (compat_1_24_1 && context.seen_comments) { fprintf (stderr, _("%s: %s contains comments which will not work with virt-builder 1.24.1\n"), program_name, input); exit (EXIT_FAILURE); } /* Iterate over the parsed sections, semantically validating it. */ - for (sections = parsed_index; sections != NULL; sections = sections->next) { + for (sections = context.parsed_index; sections != NULL; sections = sections->next) { int seen_sig = 0; struct field *fields; @@ -165,7 +169,7 @@ main (int argc, char *argv[]) } /* Free the parsed data. */ - free_index (); + parse_context_free (&context); printf ("%s validated OK\n", input);