v1-0010-syncrep-parser-pure-parser-and-reentrant-scanner.patch

text/plain

Filename: v1-0010-syncrep-parser-pure-parser-and-reentrant-scanner.patch
Type: text/plain
Part: 9
Message: Re: 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 v1-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 172e52feb05b37adbca1b3688c14a054baf712fb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 2 Dec 2024 10:35:37 +0100
Subject: [PATCH v1 10/19] 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