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