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-2024, 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 : /* Handles to the buffer that the lexer uses internally */ 41 : static YY_BUFFER_STATE scanbufhandle; 42 : 43 : static StringInfoData xdbuf; 44 : 45 : /* LCOV_EXCL_START */ 46 : 47 : %} 48 : 49 : %option 8bit 50 : %option never-interactive 51 : %option nodefault 52 : %option noinput 53 : %option nounput 54 : %option noyywrap 55 : %option warn 56 : %option prefix="syncrep_yy" 57 : 58 : /* 59 : * <xd> delimited identifiers (double-quoted identifiers) 60 : */ 61 : %x xd 62 : 63 : space [ \t\n\r\f\v] 64 : 65 : digit [0-9] 66 : ident_start [A-Za-z\200-\377_] 67 : ident_cont [A-Za-z\200-\377_0-9\$] 68 : identifier {ident_start}{ident_cont}* 69 : 70 : dquote \" 71 : xdstart {dquote} 72 : xdstop {dquote} 73 : xddouble {dquote}{dquote} 74 : xdinside [^"]+ 75 : 76 : %% 77 : {space}+ { /* ignore */ } 78 : 79 : /* brute-force case insensitivity is safer than relying on flex -i */ 80 : 81 : [Aa][Nn][Yy] { return ANY; } 82 : [Ff][Ii][Rr][Ss][Tt] { return FIRST; } 83 : 84 : {xdstart} { 85 : initStringInfo(&xdbuf); 86 : BEGIN(xd); 87 : } 88 : <xd>{xddouble} { 89 : appendStringInfoChar(&xdbuf, '"'); 90 : } 91 : <xd>{xdinside} { 92 : appendStringInfoString(&xdbuf, yytext); 93 : } 94 : <xd>{xdstop} { 95 : syncrep_yylval.str = xdbuf.data; 96 : xdbuf.data = NULL; 97 : BEGIN(INITIAL); 98 : return NAME; 99 : } 100 : <xd><<EOF>> { 101 : syncrep_yyerror("unterminated quoted identifier"); 102 : return JUNK; 103 : } 104 : 105 : {identifier} { 106 : syncrep_yylval.str = pstrdup(yytext); 107 : return NAME; 108 : } 109 : 110 : {digit}+ { 111 : syncrep_yylval.str = pstrdup(yytext); 112 : return NUM; 113 : } 114 : 115 : "*" { 116 : syncrep_yylval.str = "*"; 117 : return NAME; 118 : } 119 : 120 : "," { return ','; } 121 : "(" { return '('; } 122 : ")" { return ')'; } 123 : 124 : . { return JUNK; } 125 : %% 126 : 127 : /* LCOV_EXCL_STOP */ 128 : 129 : /* Needs to be here for access to yytext */ 130 : void 131 0 : syncrep_yyerror(const char *message) 132 : { 133 : /* report only the first error in a parse operation */ 134 0 : if (syncrep_parse_error_msg) 135 0 : return; 136 0 : if (yytext[0]) 137 0 : syncrep_parse_error_msg = psprintf("%s at or near \"%s\"", 138 : message, yytext); 139 : else 140 0 : syncrep_parse_error_msg = psprintf("%s at end of input", 141 : message); 142 : } 143 : 144 : void 145 130 : syncrep_scanner_init(const char *str) 146 : { 147 130 : Size slen = strlen(str); 148 : char *scanbuf; 149 : 150 : /* 151 : * Might be left over after ereport() 152 : */ 153 130 : if (YY_CURRENT_BUFFER) 154 0 : yy_delete_buffer(YY_CURRENT_BUFFER); 155 : 156 : /* 157 : * Make a scan buffer with special termination needed by flex. 158 : */ 159 130 : scanbuf = (char *) palloc(slen + 2); 160 130 : memcpy(scanbuf, str, slen); 161 130 : scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; 162 130 : scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); 163 : 164 : /* Make sure we start in proper state */ 165 130 : BEGIN(INITIAL); 166 130 : } 167 : 168 : void 169 130 : syncrep_scanner_finish(void) 170 : { 171 130 : yy_delete_buffer(scanbufhandle); 172 130 : scanbufhandle = NULL; 173 130 : }