%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" /* * 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); } {xddouble} { appendStringInfoChar(&xdbuf, '"'); } {xdinside} { appendStringInfoString(&xdbuf, yytext); } {xdstop} { syncrep_yylval.str = xdbuf.data; xdbuf.data = NULL; BEGIN(INITIAL); return NAME; } <> { 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; }