From: Michael Tremer Date: Sat, 1 May 2021 18:46:41 +0000 (+0000) Subject: parser: Make it re-entrant X-Git-Tag: 0.9.28~1285^2~155 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffbcfe7288b21d44b739cbbe3f87d35ee8693ee7;p=pakfire.git parser: Make it re-entrant Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/parser/grammar.y b/src/libpakfire/parser/grammar.y index f67a5c7ed..8b45d5b48 100644 --- a/src/libpakfire/parser/grammar.y +++ b/src/libpakfire/parser/grammar.y @@ -18,7 +18,16 @@ # # #############################################################################*/ -%parse-param {Pakfire pakfire} {PakfireParser* result} {struct pakfire_parser_error** error} +%lex-param {yyscan_t* scanner} + +%parse-param + {yyscan_t* scanner} + {PakfireParser* parser} + {Pakfire pakfire} + {struct pakfire_parser_error** error} + +// Make the parser reentrant +%define api.pure full // Generate verbose error messages %define parse.error verbose @@ -44,12 +53,17 @@ int yydebug = 1; #endif +typedef void* yyscan_t; +extern int yylex_init(yyscan_t* scanner); +int yylex_destroy(yyscan_t scanner); + typedef struct yy_buffer_state* YY_BUFFER_STATE; -extern YY_BUFFER_STATE yy_scan_bytes(const char* buffer, size_t len); -extern void yy_delete_buffer(YY_BUFFER_STATE buffer); +extern YY_BUFFER_STATE yy_scan_bytes(const char* buffer, size_t len, yyscan_t scanner); +extern void yy_delete_buffer(YY_BUFFER_STATE buffer, yyscan_t scanner); -extern int yylex(); -extern int yyparse(); +#include "grammar.h" + +extern int yylex (YYSTYPE* yylval_param, yyscan_t yyscanner); extern int num_lines; @@ -59,13 +73,13 @@ enum operator { OP_EQUALS = 0, }; -static void yyerror(Pakfire pakfire, PakfireParser* result, +static void yyerror(yyscan_t* scanner, PakfireParser* parser, Pakfire pakfire, struct pakfire_parser_error** error, const char* s) { ERROR(pakfire, "Error (line %d): %s\n", num_lines, s); // Create a new error object if (error) { - int r = pakfire_parser_error_create(error, *result, NULL, num_lines, s); + int r = pakfire_parser_error_create(error, *parser, NULL, num_lines, s); if (r) { ERROR(pakfire, "Could not create error object: %s\n", strerror(errno)); } @@ -162,8 +176,8 @@ grammar : %empty if (!$$) ABORT; - if (!*result) - *result = pakfire_parser_ref($$); + if (!*parser) + *parser = pakfire_parser_ref($$); } | grammar declaration { @@ -316,7 +330,7 @@ subparser_name : T_SUBPARSER if_stmt : T_IF T_STRING T_EQUALS T_STRING T_EOL subgrammar else_stmt T_END T_EOL { - $$ = make_if_stmt(pakfire, result, OP_EQUALS, $2, $4, $6, $7); + $$ = make_if_stmt(pakfire, parser, OP_EQUALS, $2, $4, $6, $7); pakfire_parser_unref($6); pakfire_parser_unref($7); @@ -338,6 +352,7 @@ else_stmt : T_ELSE T_EOL subgrammar int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len, struct pakfire_parser_error** error) { Pakfire pakfire = pakfire_parser_get_pakfire(parent); + yyscan_t scanner; #ifdef ENABLE_DEBUG DEBUG(pakfire, "Parsing the following data (%zu):\n%.*s\n", @@ -347,14 +362,17 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len clock_t t_start = clock(); #endif + // Initialise scanner + yylex_init(&scanner); + // Create a new sub-parser PakfireParser parser = NULL; num_lines = 1; - YY_BUFFER_STATE buffer = yy_scan_bytes(data, len); - int r = yyparse(pakfire, &parser, error); - yy_delete_buffer(buffer); + YY_BUFFER_STATE buffer = yy_scan_bytes(data, len, scanner); + int r = yyparse(scanner, &parser, pakfire, error); + yy_delete_buffer(buffer, scanner); // If everything was parsed successfully, we merge the sub-parser into // the parent parser. That way, it will be untouched if something could @@ -383,6 +401,7 @@ int pakfire_parser_parse_data(PakfireParser parent, const char* data, size_t len // Cleanup pakfire_unref(pakfire); + yylex_destroy(scanner); return r; } diff --git a/src/libpakfire/parser/scanner.l b/src/libpakfire/parser/scanner.l index 50e1ca7a8..500cbde68 100644 --- a/src/libpakfire/parser/scanner.l +++ b/src/libpakfire/parser/scanner.l @@ -18,8 +18,10 @@ # # #############################################################################*/ +%option bison-bridge %option noinput noyywrap yylineno %option nodefault +%option reentrant %option stack noyy_top_state %option warn @@ -27,7 +29,7 @@ /* %option debug */ %{ -#define YY_DECL int yylex() +#define YY_DECL int yylex (YYSTYPE* yylval_param, yyscan_t yyscanner) int num_lines; @@ -161,7 +163,7 @@ scriptlet script(let)? // Jump back into indentation processing after a newline current_indent = 0; - yy_push_state(INDENT); + yy_push_state(INDENT, yyscanner); return T_EOL; } @@ -170,23 +172,23 @@ scriptlet script(let)? {keys}$ { // Leave NOKEYWORD immediately again - yy_pop_state(); + yy_pop_state(yyscanner); // Copy the value - yylval.string = strdup(yytext); + yylval->string = strdup(yytext); // Enter into READLINES mode - yy_push_state(READLINES); + yy_push_state(READLINES, yyscanner); return T_KEY; } {keys} { // Leave NOKEYWORD immediately again - yy_pop_state(); + yy_pop_state(yyscanner); // Copy the value - yylval.string = strdup(yytext); + yylval->string = strdup(yytext); return T_KEY; } @@ -198,15 +200,15 @@ scriptlet script(let)? } ^{subparsers}$ { - yylval.string = strdup(yytext); + yylval->string = strdup(yytext); return T_SUBPARSER; } {named_subparsers} { - yy_push_state(READLINE); + yy_push_state(READLINE, yyscanner); - yylval.string = strdup(yytext); + yylval->string = strdup(yytext); return T_SUBPARSER; } @@ -220,7 +222,7 @@ scriptlet script(let)? {quoted_string} { // Remove quotes - yylval.string = unquote(yytext); + yylval->string = unquote(yytext); return T_STRING; } @@ -236,14 +238,14 @@ scriptlet script(let)? "=" { // Read everything after this - yy_push_state(READLINE); + yy_push_state(READLINE, yyscanner); return T_ASSIGN; } "+=" { // Read everything after this - yy_push_state(READLINE); + yy_push_state(READLINE, yyscanner); return T_APPEND; } @@ -253,7 +255,7 @@ scriptlet script(let)? yyless(0); // None of the keywords have matched - yy_push_state(NOKEYWORD); + yy_push_state(NOKEYWORD, yyscanner); } .*\\\n { @@ -263,10 +265,10 @@ scriptlet script(let)? .*$ { // Return to caller - yy_pop_state(); + yy_pop_state(yyscanner); // Copy the entire string - yylval.string = copy_string(yytext); + yylval->string = copy_string(yytext); return T_STRING; } @@ -297,19 +299,19 @@ scriptlet script(let)? // If we found the same or less indentation we go back // to the previous state and continue parsing there } else { - yy_pop_state(); + yy_pop_state(yyscanner); } } // <-- ? else if (current_indent < readline_indent) { readline_indent = 0; - yy_pop_state(); + yy_pop_state(yyscanner); return T_OUTDENT; // The indentation stayed the same, read the next line } else { - yy_push_state(READLINE); + yy_push_state(READLINE, yyscanner); } } @@ -326,20 +328,20 @@ scriptlet script(let)? // --> - More indentation? if (current_indent > indent_level) { indent_level++; - yy_pop_state(); + yy_pop_state(yyscanner); return T_INDENT; // <-- - If indentation has become less } else if (current_indent < indent_level) { indent_level--; - yy_pop_state(); + yy_pop_state(yyscanner); return T_OUTDENT; // If indentation has stayed the same } else { - yy_pop_state(); + yy_pop_state(yyscanner); } }