summaryrefslogtreecommitdiffstats
path: root/src/backend/replication/syncrep_scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/replication/syncrep_scanner.l')
-rw-r--r--src/backend/replication/syncrep_scanner.l173
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;
+}