v0-0010-syncrep-parser-pure-parser-and-reentrant-scanner.patch
text/plain
Filename: v0-0010-syncrep-parser-pure-parser-and-reentrant-scanner.patch
Type: text/plain
Part: 9
Message:
pure parsers and reentrant scanners
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v0-0010
Subject: syncrep parser: pure parser and reentrant scanner
| File | + | − |
|---|---|---|
| src/backend/replication/syncrep.c | 4 | 3 |
| src/backend/replication/syncrep_gram.y | 7 | 5 |
| src/backend/replication/syncrep_scanner.l | 20 | 23 |
| src/include/replication/syncrep.h | 7 | 5 |
From 11e17f667d4f90d496c6c1ec99df8b198304492c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 2 Dec 2024 10:35:37 +0100
Subject: [PATCH v0 10/15] syncrep parser: pure parser and reentrant scanner
---
src/backend/replication/syncrep.c | 7 ++--
src/backend/replication/syncrep_gram.y | 12 ++++---
src/backend/replication/syncrep_scanner.l | 43 +++++++++++------------
src/include/replication/syncrep.h | 12 ++++---
4 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index e1126734ef5..22a2c7fc409 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -992,6 +992,7 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source)
{
if (*newval != NULL && (*newval)[0] != '\0')
{
+ yyscan_t scanner;
int parse_rc;
SyncRepConfigData *pconf;
@@ -1000,9 +1001,9 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source)
syncrep_parse_error_msg = NULL;
/* Parse the synchronous_standby_names string */
- syncrep_scanner_init(*newval);
- parse_rc = syncrep_yyparse();
- syncrep_scanner_finish();
+ syncrep_scanner_init(*newval, &scanner);
+ parse_rc = syncrep_yyparse(scanner);
+ syncrep_scanner_finish(scanner);
if (parse_rc != 0 || syncrep_parse_result == NULL)
{
diff --git a/src/backend/replication/syncrep_gram.y b/src/backend/replication/syncrep_gram.y
index e4d9962226c..00b5bf0e522 100644
--- a/src/backend/replication/syncrep_gram.y
+++ b/src/backend/replication/syncrep_gram.y
@@ -26,10 +26,6 @@ char *syncrep_parse_error_msg;
static SyncRepConfigData *create_syncrep_config(const char *num_sync,
List *members, uint8 syncrep_method);
-/* silence -Wmissing-variable-declarations */
-extern int syncrep_yychar;
-extern int syncrep_yynerrs;
-
/*
* Bison doesn't allocate anything that needs to live across parser calls,
* so we can easily have it use palloc instead of malloc. This prevents
@@ -40,6 +36,9 @@ extern int syncrep_yynerrs;
%}
+%parse-param {yyscan_t yyscanner}
+%lex-param {yyscan_t yyscanner}
+%pure-parser
%expect 0
%name-prefix="syncrep_yy"
@@ -60,7 +59,10 @@ extern int syncrep_yynerrs;
%%
result:
- standby_config { syncrep_parse_result = $1; }
+ standby_config {
+ syncrep_parse_result = $1;
+ (void) yynerrs; /* suppress compiler warning */
+ }
;
standby_config:
diff --git a/src/backend/replication/syncrep_scanner.l b/src/backend/replication/syncrep_scanner.l
index 6defb90f13b..b1edb780502 100644
--- a/src/backend/replication/syncrep_scanner.l
+++ b/src/backend/replication/syncrep_scanner.l
@@ -37,15 +37,14 @@ fprintf_to_ereport(const char *fmt, const char *msg)
ereport(ERROR, (errmsg_internal("%s", msg)));
}
-/* Handles to the buffer that the lexer uses internally */
-static YY_BUFFER_STATE scanbufhandle;
-
-static StringInfoData xdbuf;
+static StringInfoData xdbuf; /* FIXME */
/* LCOV_EXCL_START */
%}
+%option reentrant
+%option bison-bridge
%option 8bit
%option never-interactive
%option nodefault
@@ -92,28 +91,28 @@ xdinside [^"]+
appendStringInfoString(&xdbuf, yytext);
}
<xd>{xdstop} {
- syncrep_yylval.str = xdbuf.data;
+ yylval->str = xdbuf.data;
xdbuf.data = NULL;
BEGIN(INITIAL);
return NAME;
}
<xd><<EOF>> {
- syncrep_yyerror("unterminated quoted identifier");
+ syncrep_yyerror("unterminated quoted identifier", yyscanner);
return JUNK;
}
{identifier} {
- syncrep_yylval.str = pstrdup(yytext);
+ yylval->str = pstrdup(yytext);
return NAME;
}
{digit}+ {
- syncrep_yylval.str = pstrdup(yytext);
+ yylval->str = pstrdup(yytext);
return NUM;
}
"*" {
- syncrep_yylval.str = "*";
+ yylval->str = "*";
return NAME;
}
@@ -128,8 +127,10 @@ xdinside [^"]+
/* Needs to be here for access to yytext */
void
-syncrep_yyerror(const char *message)
+syncrep_yyerror(yyscan_t yyscanner, const char *message)
{
+ struct yyguts_t * yyg = (struct yyguts_t *) yyscanner; /* needed for yytext macro */
+
/* report only the first error in a parse operation */
if (syncrep_parse_error_msg)
return;
@@ -142,16 +143,16 @@ syncrep_yyerror(const char *message)
}
void
-syncrep_scanner_init(const char *str)
+syncrep_scanner_init(const char *str, yyscan_t *yyscannerp)
{
Size slen = strlen(str);
char *scanbuf;
+ yyscan_t yyscanner;
- /*
- * Might be left over after ereport()
- */
- if (YY_CURRENT_BUFFER)
- yy_delete_buffer(YY_CURRENT_BUFFER);
+ if (yylex_init(yyscannerp) != 0)
+ elog(ERROR, "yylex_init() failed: %m");
+
+ yyscanner = *yyscannerp;
/*
* Make a scan buffer with special termination needed by flex.
@@ -159,15 +160,11 @@ syncrep_scanner_init(const char *str)
scanbuf = (char *) palloc(slen + 2);
memcpy(scanbuf, str, slen);
scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
- scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
-
- /* Make sure we start in proper state */
- BEGIN(INITIAL);
+ yy_scan_buffer(scanbuf, slen + 2, yyscanner);
}
void
-syncrep_scanner_finish(void)
+syncrep_scanner_finish(yyscan_t yyscanner)
{
- yy_delete_buffer(scanbufhandle);
- scanbufhandle = NULL;
+ yylex_destroy(yyscanner);
}
diff --git a/src/include/replication/syncrep.h b/src/include/replication/syncrep.h
index ea439e6da60..b4134dbc91d 100644
--- a/src/include/replication/syncrep.h
+++ b/src/include/replication/syncrep.h
@@ -100,10 +100,12 @@ extern void SyncRepUpdateSyncStandbysDefined(void);
* Internal functions for parsing synchronous_standby_names grammar,
* in syncrep_gram.y and syncrep_scanner.l
*/
-extern int syncrep_yyparse(void);
-extern int syncrep_yylex(void);
-extern void syncrep_yyerror(const char *str);
-extern void syncrep_scanner_init(const char *str);
-extern void syncrep_scanner_finish(void);
+union YYSTYPE;
+typedef void *yyscan_t;
+extern int syncrep_yyparse(yyscan_t yyscanner);
+extern int syncrep_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner);
+extern void syncrep_yyerror(yyscan_t yyscanner, const char *str);
+extern void syncrep_scanner_init(const char *str, yyscan_t *yyscannerp);
+extern void syncrep_scanner_finish(yyscan_t yyscanner);
#endif /* _SYNCREP_H */
--
2.47.1