2424 * Portions Copyright (c) 1994, Regents of the University of California
2525 *
2626 * IDENTIFICATION
27- * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.130 2006/03/05 15:58:34 momjian Exp $
27+ * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.131 2006/03/06 19:49:20 momjian Exp $
2828 *
2929 *-------------------------------------------------------------------------
3030*/
@@ -51,13 +51,14 @@ static intxcdepth = 0;/* depth of nesting in slash-star comments */
5151static char *dolqstart;/* current $foo$ quote start string*/
5252
5353/*
54- * GUCvariable . This is a DIRECT violation of the warning given at the
54+ * GUCvariables . This is a DIRECT violation of the warning given at the
5555 * head of gram.y, ie flex/bison code must not depend on any GUC variables;
5656 * as such, changing its value can induce very unintuitive behavior.
5757 * But we shall have to live with it as a short-term thing until the switch
5858 * to SQL-standard string syntax is complete.
5959*/
6060bool escape_string_warning;
61+ bool standard_conforming_strings;
6162
6263static bool warn_on_first_escape;
6364
@@ -77,6 +78,7 @@ static void addlitchar(unsigned char ychar);
7778static char *litbufdup (void );
7879static int pg_err_position (void );
7980static void check_escape_warning (void );
81+ static void check_string_escape_warning (unsigned char ychar);
8082
8183/*
8284 * When we parse a token that requires multiple lexer rules to process,
@@ -119,14 +121,16 @@ static unsigned char unescape_single_char(unsigned char c);
119121 * <xc> extended C-style comments
120122 * <xd> delimited identifiers (double-quoted identifiers)
121123 * <xh> hexadecimal numeric string
122- * <xq> quoted strings
124+ * <xq> standard quoted strings
125+ * <xe> extended quoted strings (support backslash escape sequences)
123126 * <xdolq> $foo$ quoted strings
124127 */
125128
126129%x xb
127130%x xc
128131%x xd
129132%x xh
133+ %x xe
130134%x xq
131135%x xdolq
132136
@@ -200,16 +204,18 @@ xnstart[nN]{quote}
200204
201205/* Quoted string that allows backslash escapes */
202206xestart [eE ]{quote }
207+ xeinside [^ \\ ' ]+
208+ xeescape [\\ ][^ 0 -7 ]
209+ xeoctesc [\\ ][0 -7 ]{1,3 }
210+ xehexesc [\\ ]x[0 -9A -Fa -f ]{1,2 }
203211
204212/* Extended quote
205213 * xqdouble implements embedded quote, ''''
206214 */
207215xqstart {quote }
208216xqdouble {quote }{quote }
209217xqinside [^ \\ ' ]+
210- xqescape [\\ ][^ 0 -7 ]
211- xqoctesc [\\ ][0 -7 ]{1,3 }
212- xqhexesc [\\ ]x[0 -9A -Fa -f ]{1,2 }
218+ xqbackslash [\\ ]
213219
214220/* $foo$ style quotes ("dollar quoting")
215221 * The quoted string starts with $foo$ where "foo" is an optional string
@@ -428,73 +434,62 @@ other.
428434{xqstart }{
429435warn_on_first_escape =true ;
430436token_start = yytext;
431- BEGIN (xq);
437+ if (standard_conforming_strings)
438+ BEGIN (xq);
439+ else
440+ BEGIN (xe);
432441startlit ();
433442}
434443{xestart }{
435444warn_on_first_escape =false ;
436445token_start = yytext;
437- BEGIN (xq );
446+ BEGIN (xe );
438447startlit ();
439448}
440- <xq >{quotestop }|
441- <xq >{quotefail } {
449+ <xq , xe >{quotestop }|
450+ <xq , xe >{quotefail } {
442451yyless (1 );
443452BEGIN (INITIAL);
444453yylval.str =litbufdup ();
445454return SCONST;
446455}
447- <xq >{xqdouble } {
456+ <xq , xe >{xqdouble } {
448457addlitchar (' \' ' );
449458}
450459<xq >{xqinside } {
451460addlit (yytext, yyleng);
452461}
453- <xq >{xqescape } {
454- if (yytext[1 ] ==' \' ' )
455- {
456- if (warn_on_first_escape && escape_string_warning)
457- ereport (WARNING,
458- (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
459- errmsg (" nonstandard use of\\ ' in a string literal" ),
460- errhint (" Use '' to write quotes in strings, or use the escape string syntax (E'...')." ),
461- errposition (pg_err_position ())));
462- warn_on_first_escape =false ;/* warn only once per string */
463- }
464- else if (yytext[1 ] ==' \\ ' )
465- {
466- if (warn_on_first_escape && escape_string_warning)
467- ereport (WARNING,
468- (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
469- errmsg (" nonstandard use of\\\\ in a string literal" ),
470- errhint (" Use the escape string syntax for backslashes, e.g., E'\\\\ '." ),
471- errposition (pg_err_position ())));
472- warn_on_first_escape =false ;/* warn only once per string */
473- }
474- else
475- check_escape_warning ();
462+ <xe >{xeinside } {
463+ addlit (yytext, yyleng);
464+ }
465+ <xq >{xqbackslash } {
466+ check_string_escape_warning (yytext[1 ]);
467+ addlitchar (' \\ ' );
468+ }
469+ <xe >{xeescape } {
470+ check_string_escape_warning (yytext[1 ]);
476471addlitchar (unescape_single_char (yytext[1 ]));
477472}
478- <xq >{ xqoctesc } {
473+ <xe >{ xeoctesc } {
479474unsigned char c =strtoul (yytext+1 ,NULL ,8 );
480475
481476check_escape_warning ();
482477addlitchar (c);
483478}
484- <xq >{ xqhexesc } {
479+ <xe >{ xehexesc } {
485480unsigned char c =strtoul (yytext+2 ,NULL ,16 );
486481
487482check_escape_warning ();
488483addlitchar (c);
489484}
490- <xq >{quotecontinue } {
485+ <xq , xe >{quotecontinue } {
491486/* ignore */
492487}
493- <xq >. {
488+ <xe >. {
494489/* This is only needed for \ just before EOF */
495490addlitchar (yytext[0 ]);
496491}
497- <xq ><<EOF>> {yyerror (" unterminated quoted string" ); }
492+ <xq , xe ><<EOF>> {yyerror (" unterminated quoted string" ); }
498493
499494{dolqdelim }{
500495token_start = yytext;
@@ -875,6 +870,33 @@ unescape_single_char(unsigned char c)
875870}
876871}
877872
873+ static void
874+ check_string_escape_warning (unsigned char ychar)
875+ {
876+ if (ychar ==' \' ' )
877+ {
878+ if (warn_on_first_escape && escape_string_warning)
879+ ereport (WARNING,
880+ (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
881+ errmsg (" nonstandard use of\\ ' in a string literal" ),
882+ errhint (" Use '' to write quotes in strings, or use the escape string syntax (E'...')." ),
883+ errposition (pg_err_position ())));
884+ warn_on_first_escape =false ;/* warn only once per string */
885+ }
886+ else if (ychar ==' \\ ' )
887+ {
888+ if (warn_on_first_escape && escape_string_warning)
889+ ereport (WARNING,
890+ (errcode (ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
891+ errmsg (" nonstandard use of\\\\ in a string literal" ),
892+ errhint (" Use the escape string syntax for backslashes, e.g., E'\\\\ '." ),
893+ errposition (pg_err_position ())));
894+ warn_on_first_escape =false ;/* warn only once per string */
895+ }
896+ else
897+ check_escape_warning ();
898+ }
899+
878900static void
879901check_escape_warning (void )
880902{