From 8a5fe6eb7e613b6a25329b8ad976939e654aa2df Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 2 Dec 2024 10:35:37 +0100 Subject: [PATCH v2 05/11] 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 | 15 +++++--- 4 files changed, 41 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..add936fdd32 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); } {xdstop} { - syncrep_yylval.str = xdbuf.data; + yylval->str = xdbuf.data; xdbuf.data = NULL; BEGIN(INITIAL); return NAME; } <> { - syncrep_yyerror("unterminated quoted identifier"); + syncrep_yyerror(yyscanner, "unterminated quoted identifier"); 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..3fe44a880cf 100644 --- a/src/include/replication/syncrep.h +++ b/src/include/replication/syncrep.h @@ -100,10 +100,15 @@ 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; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif +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