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
|
%{
/*-------------------------------------------------------------------------
*
* syncrep_scanner.l
* a lexical scanner for synchronous_standby_names
*
* Portions Copyright (c) 1996-2016, 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 "miscadmin.h"
#include "lib/stringinfo.h"
/*
* flex emits a yy_fatal_error() function that it calls in response to
* critical errors like malloc failure, file I/O errors, and detection of
* internal inconsistency. That function prints a message and calls exit().
* Mutate it to instead call ereport(FATAL), which terminates this process.
*
* The process that causes this fatal error should be terminated.
* Otherwise it has to abandon the new setting value of
* synchronous_standby_names and keep running with the previous one
* while the other processes switch to the new one.
* This inconsistency of the setting that each process is based on
* can cause a serious problem. Though it's basically not good idea to
* use FATAL here because it can take down the postmaster,
* we should do that in order to avoid such an inconsistency.
*/
#undef fprintf
#define fprintf(file, fmt, msg) syncrep_flex_fatal(fmt, msg)
static void
syncrep_flex_fatal(const char *fmt, const char *msg)
{
ereport(FATAL, (errmsg_internal("%s", msg)));
}
/* Handles to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle;
static StringInfoData xdbuf;
%}
%option 8bit
%option never-interactive
%option nounput
%option noinput
%option noyywrap
%option warn
%option prefix="syncrep_yy"
/*
* <xd> delimited identifiers (double-quoted identifiers)
*/
%x xd
space [ \t\n\r\f\v]
undquoted_start [^ ,\(\)\"]
undquoted_cont [^ ,\(\)]
undquoted_name {undquoted_start}{undquoted_cont}*
dquoted_name [^\"]+
/* Double-quoted string */
dquote \"
xdstart {dquote}
xddouble {dquote}{dquote}
xdstop {dquote}
xdinside {dquoted_name}
%%
{space}+ { /* ignore */ }
{xdstart} {
initStringInfo(&xdbuf);
BEGIN(xd);
}
<xd>{xddouble} {
appendStringInfoChar(&xdbuf, '\"');
}
<xd>{xdinside} {
appendStringInfoString(&xdbuf, yytext);
}
<xd>{xdstop} {
yylval.str = pstrdup(xdbuf.data);
pfree(xdbuf.data);
BEGIN(INITIAL);
return NAME;
}
"," { return ','; }
"(" { return '('; }
")" { return ')'; }
[1-9][0-9]* {
yylval.str = pstrdup(yytext);
return NUM;
}
{undquoted_name} {
yylval.str = pstrdup(yytext);
return NAME;
}
%%
void
yyerror(const char *message)
{
ereport(IsUnderPostmaster ? DEBUG2 : LOG,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("%s at or near \"%s\"", message, yytext)));
}
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);
}
void
syncrep_scanner_finish(void)
{
yy_delete_buffer(scanbufhandle);
scanbufhandle = NULL;
}
|