]> git.ipfire.org Git - pakfire.git/commitdiff
parser: Make it re-entrant
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 1 May 2021 18:46:41 +0000 (18:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 1 May 2021 18:46:41 +0000 (18:46 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/parser/grammar.y
src/libpakfire/parser/scanner.l

index f67a5c7edfbc4d5a66c92bf6bff39e276633a430..8b45d5b486787cdffd12f5d5da6ec1eecae178ef 100644 (file)
 #                                                                             #
 #############################################################################*/
 
-%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
        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;
 }
index 50e1ca7a8c4c659bee965e2cc1d7643fa7c63321..500cbde686611c1e0a87b23ab04f79c6e6ad5ece 100644 (file)
 #                                                                             #
 #############################################################################*/
 
+%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)?
 
 <NOKEYWORD>{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;
                                                }
 
 <NOKEYWORD>{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);
                                                }
 
 <READLINE>.*\\\n               {
@@ -263,10 +265,10 @@ scriptlet                         script(let)?
 
 <READLINE>.*$                  {
                                                        // 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);
                                                        }
                                                }