guc: reentrant scanner
authorPeter Eisentraut <peter@eisentraut.org>
Wed, 25 Dec 2024 13:18:07 +0000 (14:18 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Wed, 25 Dec 2024 13:18:07 +0000 (14:18 +0100)
Use the flex %option reentrant to make the generated scanner
reentrant, and perhaps eventually thread-safe, but that will require
additional work.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Discussion: https://www.postgresql.org/message-id/flat/eb6faeac-2a8a-4b69-9189-c33c520e5b7b@eisentraut.org

src/backend/utils/misc/guc-file.l

index 73be80076da7390b50deb6ef0471e21fcbdc7024..6c7b8fdec20a0aa3881791083ae5432231c32667 100644 (file)
@@ -57,6 +57,7 @@ static int    GUC_flex_fatal(const char *msg);
 
 %}
 
+%option reentrant
 %option 8bit
 %option never-interactive
 %option nodefault
@@ -353,6 +354,8 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
        unsigned int save_ConfigFileLineno = ConfigFileLineno;
        sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp;
        sigjmp_buf      flex_fatal_jmp;
+       yyscan_t        scanner;
+       struct yyguts_t *yyg;           /* needed for yytext macro */
        volatile YY_BUFFER_STATE lex_buffer = NULL;
        int                     errorcount;
        int                     token;
@@ -381,11 +384,15 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
        ConfigFileLineno = 1;
        errorcount = 0;
 
-       lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE);
-       yy_switch_to_buffer(lex_buffer);
+       if (yylex_init(&scanner) != 0)
+               elog(elevel, "yylex_init() failed: %m");
+       yyg = (struct yyguts_t *) scanner;
+
+       lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE, scanner);
+       yy_switch_to_buffer(lex_buffer, scanner);
 
        /* This loop iterates once per logical line */
-       while ((token = yylex()))
+       while ((token = yylex(scanner)))
        {
                char       *opt_name = NULL;
                char       *opt_value = NULL;
@@ -400,9 +407,9 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                opt_name = pstrdup(yytext);
 
                /* next we have an optional equal sign; discard if present */
-               token = yylex();
+               token = yylex(scanner);
                if (token == GUC_EQUALS)
-                       token = yylex();
+                       token = yylex(scanner);
 
                /* now we must have the option value */
                if (token != GUC_ID &&
@@ -417,7 +424,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                        opt_value = pstrdup(yytext);
 
                /* now we'd like an end of line, or possibly EOF */
-               token = yylex();
+               token = yylex(scanner);
                if (token != GUC_EOL)
                {
                        if (token != 0)
@@ -438,7 +445,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                                                                          depth + 1, elevel,
                                                                          head_p, tail_p))
                                OK = false;
-                       yy_switch_to_buffer(lex_buffer);
+                       yy_switch_to_buffer(lex_buffer, scanner);
                        pfree(opt_name);
                        pfree(opt_value);
                }
@@ -453,7 +460,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                                                                 depth + 1, elevel,
                                                                 head_p, tail_p))
                                OK = false;
-                       yy_switch_to_buffer(lex_buffer);
+                       yy_switch_to_buffer(lex_buffer, scanner);
                        pfree(opt_name);
                        pfree(opt_value);
                }
@@ -468,7 +475,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
                                                                 depth + 1, elevel,
                                                                 head_p, tail_p))
                                OK = false;
-                       yy_switch_to_buffer(lex_buffer);
+                       yy_switch_to_buffer(lex_buffer, scanner);
                        pfree(opt_name);
                        pfree(opt_value);
                }
@@ -545,14 +552,15 @@ parse_error:
 
                /* resync to next end-of-line or EOF */
                while (token != GUC_EOL && token != 0)
-                       token = yylex();
+                       token = yylex(scanner);
                /* break out of loop on EOF */
                if (token == 0)
                        break;
        }
 
 cleanup:
-       yy_delete_buffer(lex_buffer);
+       yy_delete_buffer(lex_buffer, scanner);
+       yylex_destroy(scanner);
        /* Each recursion level must save and restore these static variables. */
        ConfigFileLineno = save_ConfigFileLineno;
        GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp;