12
12
*
13
13
*
14
14
* IDENTIFICATION
15
- * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.136 2005/06/16 01:43:48 momjian Exp $
15
+ * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.137 2005/10/05 14:58:36 meskes Exp $
16
16
*
17
17
*-------------------------------------------------------------------------
18
18
*/
@@ -29,6 +29,8 @@ extern YYSTYPE yylval;
29
29
30
30
static int xcdepth = 0 ; /* depth of nesting in slash-star comments */
31
31
static char *dolqstart; /* current $foo$ quote start string */
32
+ bool escape_string_warning;
33
+ static bool warn_on_first_escape;
32
34
33
35
/*
34
36
* literalbuf is used to accumulate literal values when multiple rules
@@ -44,6 +46,7 @@ static int literalalloc; /* current allocated buffer size */
44
46
static void addlit (char *ytext, int yleng);
45
47
static void addlitchar (unsigned char );
46
48
static void parse_include (void );
49
+ static void check_escape_warning (void );
47
50
48
51
char *token_start;
49
52
int state_before;
@@ -111,48 +114,44 @@ static struct _if_value
111
114
/* Bit string
112
115
*/
113
116
xbstart [bB ]{quote }
114
- xbstop {quote }
115
117
xbinside [^ ' ]*
116
- xbcat {quote }{whitespace_with_newline }{quote }
117
118
118
- /* Hexadecimal number
119
- */
119
+ /* Hexadecimal number */
120
120
xhstart [xX ]{quote }
121
- xhstop {quote }
122
121
xhinside [^ ' ]*
123
- xhcat {quote }{whitespace_with_newline }{quote }
124
122
125
- /* National character
126
- */
123
+ /* National character */
127
124
xnstart [nN ]{quote }
128
125
129
- /* C version of hex number
130
- */
126
+ /* Quoted string that allows backslash escapes */
127
+ xestart [eE ]{quote }
128
+
129
+ /* C version of hex number */
131
130
xch 0[xX ][0 -9A -Fa -f ]*
132
131
133
132
/* Extended quote
134
- * xqdouble implements embedded quote
135
- * xqcat allows strings to cross input lines
133
+ * xqdouble implements embedded quote, ''''
136
134
*/
137
- quote '
138
135
xqstart {quote }
139
- xqstop {quote }
140
136
xqdouble {quote }{quote }
141
137
xqinside [^ \\ ' ]+
142
138
xqescape [\\ ][^ 0 -7 ]
143
139
xqoctesc [\\ ][0 -7 ]{1,3 }
144
140
xqhexesc [\\ ]x[0 -9A -Fa -f ]{1,2 }
145
- xqcat {quote }{whitespace_with_newline }{quote }
146
141
147
142
/* $foo$ style quotes ("dollar quoting")
148
143
* The quoted string starts with $foo$ where "foo" is an optional string
149
144
* in the form of an identifier, except that it may not contain "$",
150
145
* and extends to the first occurrence of an identical string.
151
146
* There is *no* processing of the quoted text.
147
+ *
148
+ * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim}
149
+ * fails to match its trailing "$".
152
150
*/
153
151
dolq_start [A -Za -z \200 -\377 _ ]
154
152
dolq_cont [A -Za -z \200 -\377 _0 -9 ]
155
153
dolqdelim \$ ({dolq_start }{dolq_cont }* )? \$
154
+ dolqfailed \$ {dolq_start }{dolq_cont }*
156
155
dolqinside [^ $ ]+
157
156
158
157
/* Double quote
@@ -218,11 +217,16 @@ operator {op_chars}+
218
217
/* we no longer allow unary minus in numbers.
219
218
* instead we pass it separately to parser. there it gets
220
219
* coerced via doNegate() -- Leon aug 20 1999
220
+ *
221
+ * {realfail1} and {realfail2} are added to prevent the need for scanner
222
+ * backup when the {real} rule fails to match completely.
221
223
*/
222
224
223
225
integer {digit }+
224
226
decimal (({digit }* \. {digit }+ )| ({digit }+ \. {digit }* ))
225
- real ((({digit }* \. {digit }+ )| ({digit }+ \. {digit }* )| ({digit }+ ))([Ee ][-+ ]? {digit }+ ))
227
+ real ({integer }| {decimal })[Ee ][-+ ]? {digit }+
228
+ realfail1 ({integer }| {decimal })[Ee ]
229
+ realfail2 ({integer }| {decimal })[Ee ][-+ ]
226
230
227
231
param \$ {integer }
228
232
@@ -262,6 +266,11 @@ whitespace ({space}+|{comment})
262
266
horiz_whitespace ({horiz_space }| {comment })
263
267
whitespace_with_newline ({horiz_whitespace }* {newline }{whitespace }* )
264
268
269
+ quote '
270
+ quotestop {quote }{whitespace }*
271
+ quotecontinue {quote }{whitespace_with_newline }{quote }
272
+ quotefail {quote }{whitespace }* " -"
273
+
265
274
/* special characters for other dbms */
266
275
/* we have to react differently in compat mode */
267
276
informix_special [\$ ]
@@ -343,6 +352,7 @@ cppline {space}*#(.*\\{space})*.*{newline}
343
352
344
353
<xc >{xcinside } { ECHO; }
345
354
<xc >{op_chars } { ECHO; }
355
+ <xc >\* + { ECHO; }
346
356
347
357
<xc ><<EOF>> { mmerror (PARSE_ERROR, ET_FATAL, " Unterminated /* comment" ); }
348
358
@@ -352,7 +362,9 @@ cppline {space}*#(.*\\{space})*.*{newline}
352
362
startlit ();
353
363
addlitchar (' b' );
354
364
}
355
- <xb >{xbstop } {
365
+ <xb >{quotestop } |
366
+ <xb >{quotefail } {
367
+ yyless (1 );
356
368
BEGIN (SQL);
357
369
if (literalbuf[strspn (literalbuf, " 01" ) + 1 ] != ' \0 ' )
358
370
mmerror (PARSE_ERROR, ET_ERROR, " invalid bit string input." );
@@ -362,53 +374,80 @@ cppline {space}*#(.*\\{space})*.*{newline}
362
374
363
375
<xh >{xhinside } |
364
376
<xb >{xbinside } { addlit (yytext, yyleng); }
365
- <xh >{xhcat } |
366
- <xb >{xbcat } { /* ignore */ }
377
+ <xh >{quotecontinue } |
378
+ <xb >{quotecontinue } { /* ignore */ }
367
379
<xb ><<EOF>> { mmerror (PARSE_ERROR, ET_FATAL, " Unterminated bit string" ); }
368
380
369
381
<SQL >{xhstart } {
370
382
token_start = yytext;
371
383
BEGIN (xh);
372
384
startlit ();
373
385
addlitchar (' x' );
374
- }
375
- <xh >{xhstop } {
376
- yylval.str = mm_strdup (literalbuf);
377
- return XCONST;
378
- }
386
+ }
387
+ <xh >{quotestop } |
388
+ <xh >{quotefail } {
389
+ yyless (1 );
390
+ BEGIN (SQL);
391
+ yylval.str = mm_strdup (literalbuf);
392
+ return XCONST;
393
+ }
379
394
380
395
<xh ><<EOF>> { mmerror (PARSE_ERROR, ET_FATAL, " Unterminated hexadecimal integer" ); }
381
396
<SQL >{xnstart } {
382
397
/* National character.
383
- * Need to remember type info to flow it forward into the parser.
384
- * Not yet implemented. - thomas 2002-06-17
398
+ * Transfer it as-is to the backend.
385
399
*/
386
400
token_start = yytext;
387
401
BEGIN (xq);
388
402
startlit ();
389
403
}
390
404
<C ,SQL >{xqstart } {
391
- token_start = yytext;
392
- state_before = YYSTATE;
393
- BEGIN (xq);
394
- startlit ();
395
- }
396
- <xq >{xqstop } {
397
- BEGIN (state_before);
398
- yylval.str = mm_strdup (literalbuf);
399
- return SCONST;
400
- }
405
+ warn_on_first_escape = true ;
406
+ token_start = yytext;
407
+ state_before = YYSTATE;
408
+ BEGIN (xq);
409
+ startlit ();
410
+ }
411
+ <C ,SQL >{xestart } {
412
+ warn_on_first_escape = false ;
413
+ token_start = yytext;
414
+ state_before = YYSTATE;
415
+ BEGIN (xq);
416
+ startlit ();
417
+ }
418
+ <xq >{quotestop } |
419
+ <xq >{quotefail } {
420
+ yyless (1 );
421
+ BEGIN (state_before);
422
+ yylval.str = mm_strdup (literalbuf);
423
+ return SCONST;
424
+ }
401
425
<xq >{xqdouble } { addlitchar (' \' ' ); }
402
426
<xq >{xqinside } { addlit (yytext, yyleng); }
403
- <xq >{xqescape } { addlit (yytext, yyleng); }
404
- <xq >{xqoctesc } { addlit (yytext, yyleng); }
405
- <xq >{xqhexesc } { addlit (yytext, yyleng); }
406
- <xq >{xqcat } { /* ignore */ }
427
+ <xq >{xqescape } {
428
+ check_escape_warning ();
429
+ addlit (yytext, yyleng);
430
+ }
431
+ <xq >{xqoctesc } {
432
+ check_escape_warning ();
433
+ addlit (yytext, yyleng);
434
+ }
435
+ <xq >{xqhexesc } {
436
+ check_escape_warning ();
437
+ addlit (yytext, yyleng);
438
+ }
439
+ <xq >{quotecontinue } { /* ignore */ }
407
440
<xq >. {
408
441
/* This is only needed for \ just before EOF */
409
442
addlitchar (yytext[0 ]);
410
443
}
411
444
<xq ><<EOF>> { mmerror (PARSE_ERROR, ET_FATAL, " Unterminated quoted string" ); }
445
+ <SQL >{dolqfailed } {
446
+ /* throw back all but the initial "$" */
447
+ yyless (1 );
448
+ /* and treat it as {other} */
449
+ return yytext[0 ];
450
+ }
412
451
<SQL >{dolqdelim } {
413
452
token_start = yytext;
414
453
dolqstart = mm_strdup (yytext);
@@ -434,9 +473,8 @@ cppline {space}*#(.*\\{space})*.*{newline}
434
473
yyless (yyleng-1 );
435
474
}
436
475
}
437
- <xdolq >{dolqinside } {
438
- addlit (yytext, yyleng);
439
- }
476
+ <xdolq >{dolqinside } { addlit (yytext, yyleng); }
477
+ <xdolq >{dolqfailed } { addlit (yytext, yyleng); }
440
478
<xdolq >. {
441
479
/* This is only needed for $ inside the quoted text */
442
480
addlitchar (yytext[0 ]);
@@ -588,11 +626,21 @@ cppline {space}*#(.*\\{space})*.*{newline}
588
626
{decimal } {
589
627
yylval.str = mm_strdup (yytext);
590
628
return FCONST;
591
- }
629
+ }
592
630
<C ,SQL >{real } {
593
631
yylval.str = mm_strdup (yytext);
594
632
return FCONST;
595
- }
633
+ }
634
+ <SQL >{realfail1 } {
635
+ yyless (yyleng-1 );
636
+ yylval.str = mm_strdup (yytext);
637
+ return FCONST;
638
+ }
639
+ <SQL >{realfail2 } {
640
+ yyless (yyleng-2 );
641
+ yylval.str = mm_strdup (yytext);
642
+ return FCONST;
643
+ }
596
644
<SQL >:{identifier }(((" ->" | \. ){identifier })| (\[ {array }\] ))* {
597
645
yylval.str = mm_strdup (yytext+1 );
598
646
return (CVARIABLE);
@@ -1189,3 +1237,11 @@ parse_include(void)
1189
1237
1190
1238
BEGIN C;
1191
1239
}
1240
+
1241
+ static void
1242
+ check_escape_warning (void )
1243
+ {
1244
+ if (warn_on_first_escape && escape_string_warning)
1245
+ mmerror (PARSE_ERROR, ET_WARNING, " nonstandard use of escape in a string literal" );
1246
+ warn_on_first_escape = false ; /* warn only once per string */
1247
+ }
0 commit comments