Age Owner Branch data TLA 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
3419 tgl@sss.pgh.pa.us 35 :UBC 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 */ }
3419 tgl@sss.pgh.pa.us 91 :CBC 10 :
92 : : /* brute-force case insensitivity is safer than relying on flex -i */
3032 93 : 4 :
94 : 4 : [Aa][Nn][Yy] { return ANY; }
95 : 2 : [Ff][Ii][Rr][Ss][Tt] { return FIRST; }
3183 fujii@postgresql.org 96 : 2 :
3440 fujii@postgresql.org 97 :UBC 0 : {xdstart} {
278 peter@eisentraut.org 98 : 0 : initStringInfo(&yyextra->xdbuf);
3440 fujii@postgresql.org 99 : 0 : BEGIN(xd);
100 : : }
101 : 0 : <xd>{xddouble} {
278 peter@eisentraut.org 102 : 0 : appendStringInfoChar(&yyextra->xdbuf, '"');
103 : : }
3440 fujii@postgresql.org 104 : 0 : <xd>{xdinside} {
278 peter@eisentraut.org 105 : 0 : appendStringInfoString(&yyextra->xdbuf, yytext);
106 : : }
3440 fujii@postgresql.org 107 : 0 : <xd>{xdstop} {
278 peter@eisentraut.org 108 : 0 : yylval->str = yyextra->xdbuf.data;
109 : 0 : yyextra->xdbuf.data = NULL;
3440 fujii@postgresql.org 110 : 0 : BEGIN(INITIAL);
111 : 0 : return NAME;
112 : : }
113 : : <xd><<EOF>> {
225 peter@eisentraut.org 114 : 0 : syncrep_yyerror(NULL, syncrep_parse_error_msg_p, yyscanner, "unterminated quoted identifier");
3419 tgl@sss.pgh.pa.us 115 : 0 : return JUNK;
116 : : }
117 : :
3419 tgl@sss.pgh.pa.us 118 :CBC 79 : {identifier} {
278 peter@eisentraut.org 119 : 79 : yylval->str = pstrdup(yytext);
3419 tgl@sss.pgh.pa.us 120 : 79 : return NAME;
121 : : }
122 : :
123 : 18 : {digit}+ {
278 peter@eisentraut.org 124 : 18 : yylval->str = pstrdup(yytext);
3419 tgl@sss.pgh.pa.us 125 : 18 : return NUM;
126 : : }
127 : :
128 : 27 : "*" {
278 peter@eisentraut.org 129 : 27 : yylval->str = "*";
3440 fujii@postgresql.org 130 : 27 : return NAME;
131 : : }
132 : :
3419 tgl@sss.pgh.pa.us 133 : 30 : "," { return ','; }
134 : 18 : "(" { return '('; }
135 : 18 : ")" { return ')'; }
136 : 18 :
3419 tgl@sss.pgh.pa.us 137 :UBC 0 : . { return JUNK; }
3440 fujii@postgresql.org 138 : 0 : %%
139 : 0 :
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
225 peter@eisentraut.org 156 : 0 : syncrep_yyerror(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner, const char *message)
157 : : {
255 158 : 0 : struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext
159 : : * macro */
160 : :
161 : : /* report only the first error in a parse operation */
44 rhaas@postgresql.org 162 [ # # ]: 0 : if (*syncrep_parse_error_msg_p)
3419 tgl@sss.pgh.pa.us 163 : 0 : return;
164 [ # # ]: 0 : if (yytext[0])
44 rhaas@postgresql.org 165 : 0 : *syncrep_parse_error_msg_p = psprintf("%s at or near \"%s\"",
166 : : message, yytext);
167 : : else
168 : 0 : *syncrep_parse_error_msg_p = psprintf("%s at end of input",
169 : : message);
170 : : }
171 : :
172 : : void
278 peter@eisentraut.org 173 :CBC 76 : syncrep_scanner_init(const char *str, yyscan_t *yyscannerp)
174 : : {
175 : : yyscan_t yyscanner;
176 : 76 : struct syncrep_yy_extra_type *yyext = palloc0_object(struct syncrep_yy_extra_type);
177 : :
178 [ - + ]: 76 : if (yylex_init(yyscannerp) != 0)
278 peter@eisentraut.org 179 [ # # ]:UBC 0 : elog(ERROR, "yylex_init() failed: %m");
180 : :
278 peter@eisentraut.org 181 :CBC 76 : yyscanner = *yyscannerp;
182 : :
183 : 76 : yyset_extra(yyext, yyscanner);
184 : :
185 : 76 : yy_scan_string(str, yyscanner);
186 : 76 : }
187 : :
188 : : void
189 : 76 : syncrep_scanner_finish(yyscan_t yyscanner)
190 : : {
191 : 76 : pfree(yyextra);
192 : 76 : yylex_destroy(yyscanner);
193 : 76 : }
194 : :
195 : : /*
196 : : * Interface functions to make flex use palloc() instead of malloc().
197 : : * It'd be better to make these static, but flex insists otherwise.
198 : : */
199 : :
200 : : void *
201 : 304 : yyalloc(yy_size_t size, yyscan_t yyscanner)
202 : : {
203 : 304 : return palloc(size);
204 : : }
205 : :
206 : : void *
278 peter@eisentraut.org 207 :UBC 0 : yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
208 : : {
209 [ # # ]: 0 : if (ptr)
210 : 0 : return repalloc(ptr, size);
211 : : else
212 : 0 : return palloc(size);
213 : : }
214 : :
215 : : void
278 peter@eisentraut.org 216 :CBC 380 : yyfree(void *ptr, yyscan_t yyscanner)
217 : : {
218 [ + + ]: 380 : if (ptr)
219 : 304 : pfree(ptr);
3440 fujii@postgresql.org 220 : 380 : }
|