1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
%top{
/*-------------------------------------------------------------------------
*
* syncrep_scanner.l
* a lexical scanner for synchronous_standby_names
*
* Portions Copyright (c) 1996-2025, 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)));
}
struct syncrep_yy_extra_type
{
StringInfoData xdbuf;
};
/*
* Better keep this definition here than put it in replication/syncrep.h and
* save a bit of duplication. Putting it in replication/syncrep.h would leak
* the definition to other parts and possibly affect other scanners.
*/
#define YY_DECL extern int syncrep_yylex(union YYSTYPE *yylval_param, char **syncrep_parse_error_msg_p, yyscan_t yyscanner)
/* LCOV_EXCL_START */
%}
%option reentrant
%option bison-bridge
%option 8bit
%option never-interactive
%option nodefault
%option noinput
%option nounput
%option noyywrap
%option noyyalloc
%option noyyrealloc
%option noyyfree
%option warn
%option prefix="syncrep_yy"
%option extra-type="struct syncrep_yy_extra_type *"
/*
* <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(&yyextra->xdbuf);
BEGIN(xd);
}
<xd>{xddouble} {
appendStringInfoChar(&yyextra->xdbuf, '"');
}
<xd>{xdinside} {
appendStringInfoString(&yyextra->xdbuf, yytext);
}
<xd>{xdstop} {
yylval->str = yyextra->xdbuf.data;
yyextra->xdbuf.data = NULL;
BEGIN(INITIAL);
return NAME;
}
<xd><<EOF>> {
syncrep_yyerror(NULL, syncrep_parse_error_msg_p, yyscanner, "unterminated quoted identifier");
return JUNK;
}
{identifier} {
yylval->str = pstrdup(yytext);
return NAME;
}
{digit}+ {
yylval->str = pstrdup(yytext);
return NUM;
}
"*" {
yylval->str = "*";
return NAME;
}
"," { return ','; }
"(" { return '('; }
")" { return ')'; }
. { return JUNK; }
%%
/* LCOV_EXCL_STOP */
/* see scan.l */
#undef yyextra
#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
/*
* This yyerror() function does not raise an error (elog or similar), it just
* collects the error message in *syncrep_parse_error_msg_p and leaves it to
* the ultimate caller of the syncrep parser to raise the error. (The
* ultimate caller will do that with special GUC error functions.)
*
* (The first argument is enforced by Bison to match the first argument of
* yyparse(), but it is not used here.)
*/
void
syncrep_yyerror(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner, const char *message)
{
struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext
* macro */
char *syncrep_parse_error_msg = *syncrep_parse_error_msg_p;
/* 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, yyscan_t *yyscannerp)
{
yyscan_t yyscanner;
struct syncrep_yy_extra_type *yyext = palloc0_object(struct syncrep_yy_extra_type);
if (yylex_init(yyscannerp) != 0)
elog(ERROR, "yylex_init() failed: %m");
yyscanner = *yyscannerp;
yyset_extra(yyext, yyscanner);
yy_scan_string(str, yyscanner);
}
void
syncrep_scanner_finish(yyscan_t yyscanner)
{
pfree(yyextra);
yylex_destroy(yyscanner);
}
/*
* Interface functions to make flex use palloc() instead of malloc().
* It'd be better to make these static, but flex insists otherwise.
*/
void *
yyalloc(yy_size_t size, yyscan_t yyscanner)
{
return palloc(size);
}
void *
yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
{
if (ptr)
return repalloc(ptr, size);
else
return palloc(size);
}
void
yyfree(void *ptr, yyscan_t yyscanner)
{
if (ptr)
pfree(ptr);
}
|