diff options
Diffstat (limited to 'src/backend/replication/syncrep_scanner.l')
-rw-r--r-- | src/backend/replication/syncrep_scanner.l | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/backend/replication/syncrep_scanner.l b/src/backend/replication/syncrep_scanner.l new file mode 100644 index 0000000..97c88f8 --- /dev/null +++ b/src/backend/replication/syncrep_scanner.l @@ -0,0 +1,173 @@ +%top{ +/*------------------------------------------------------------------------- + * + * syncrep_scanner.l + * a lexical scanner for synchronous_standby_names + * + * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/replication/syncrep_scanner.l + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "lib/stringinfo.h" +#include "nodes/pg_list.h" + +/* + * NB: include syncrep_gram.h only AFTER including syncrep.h, because syncrep.h + * includes node definitions needed for YYSTYPE. + */ +#include "replication/syncrep.h" +#include "syncrep_gram.h" +} + +%{ +/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ +#undef fprintf +#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg) + +static void +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; + +/* LCOV_EXCL_START */ + +%} + +%option 8bit +%option never-interactive +%option nodefault +%option noinput +%option nounput +%option noyywrap +%option warn +%option prefix="syncrep_yy" + +/* + * <xd> delimited identifiers (double-quoted identifiers) + */ +%x xd + +space [ \t\n\r\f\v] + +digit [0-9] +ident_start [A-Za-z\200-\377_] +ident_cont [A-Za-z\200-\377_0-9\$] +identifier {ident_start}{ident_cont}* + +dquote \" +xdstart {dquote} +xdstop {dquote} +xddouble {dquote}{dquote} +xdinside [^"]+ + +%% +{space}+ { /* ignore */ } + + /* brute-force case insensitivity is safer than relying on flex -i */ + +[Aa][Nn][Yy] { return ANY; } +[Ff][Ii][Rr][Ss][Tt] { return FIRST; } + +{xdstart} { + initStringInfo(&xdbuf); + BEGIN(xd); + } +<xd>{xddouble} { + appendStringInfoChar(&xdbuf, '"'); + } +<xd>{xdinside} { + appendStringInfoString(&xdbuf, yytext); + } +<xd>{xdstop} { + syncrep_yylval.str = xdbuf.data; + xdbuf.data = NULL; + BEGIN(INITIAL); + return NAME; + } +<xd><<EOF>> { + syncrep_yyerror("unterminated quoted identifier"); + return JUNK; + } + +{identifier} { + syncrep_yylval.str = pstrdup(yytext); + return NAME; + } + +{digit}+ { + syncrep_yylval.str = pstrdup(yytext); + return NUM; + } + +"*" { + syncrep_yylval.str = "*"; + return NAME; + } + +"," { return ','; } +"(" { return '('; } +")" { return ')'; } + +. { return JUNK; } +%% + +/* LCOV_EXCL_STOP */ + +/* Needs to be here for access to yytext */ +void +syncrep_yyerror(const char *message) +{ + /* report only the first error in a parse operation */ + if (syncrep_parse_error_msg) + return; + if (yytext[0]) + syncrep_parse_error_msg = psprintf("%s at or near \"%s\"", + message, yytext); + else + syncrep_parse_error_msg = psprintf("%s at end of input", + message); +} + +void +syncrep_scanner_init(const char *str) +{ + Size slen = strlen(str); + char *scanbuf; + + /* + * Might be left over after ereport() + */ + if (YY_CURRENT_BUFFER) + yy_delete_buffer(YY_CURRENT_BUFFER); + + /* + * Make a scan buffer with special termination needed by flex. + */ + 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); +} + +void +syncrep_scanner_finish(void) +{ + yy_delete_buffer(scanbufhandle); + scanbufhandle = NULL; +} |