174 lines
3.4 KiB
Plaintext
174 lines
3.4 KiB
Plaintext
%top{
|
|
/*-------------------------------------------------------------------------
|
|
*
|
|
* syncrep_scanner.l
|
|
* a lexical scanner for synchronous_standby_names
|
|
*
|
|
* Portions Copyright (c) 1996-2024, 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;
|
|
}
|