44 *
55 * Copyright (c) 2000-2005, PostgreSQL Global Development Group
66 *
7- * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.31 2005/07/08 18:41:40 tgl Exp $
7+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.32 2005/09/21 20:33:34 tgl Exp $
88 */
99
1010%{
3838
3939/* prototype, so compiler is happy with our high warnings setting */
4040int GUC_yylex (void );
41- static char *GUC_scanstr (char *);
41+ static char *GUC_scanstr (const char *s );
4242%}
4343
4444%option 8bit
@@ -64,7 +64,7 @@ ID {LETTER}{LETTER_OR_DIGIT}*
6464QUALIFIED_ID {ID}" ." {ID}
6565
6666UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
67- STRING \' ([^' \n]|\\.)*\'
67+ STRING \' ([^' \\\ n]|\\.|\ ' \' )*\'
6868
6969%%
7070
@@ -181,22 +181,16 @@ ProcessConfigFile(GucContext context)
181181 if (token == GUC_EQUALS)
182182 token = yylex();
183183
184- if (token != GUC_ID && token != GUC_STRING &&
184+ if (token != GUC_ID &&
185+ token != GUC_STRING &&
185186token != GUC_INTEGER &&
186187token != GUC_REAL &&
187188token != GUC_UNQUOTED_STRING)
188189 goto parse_error;
189- opt_value = pstrdup(yytext);
190- if (token == GUC_STRING)
191- {
192- /* remove the beginning and ending quote/apostrophe */
193- /* first: shift the whole thing down one character */
194- memmove(opt_value, opt_value+1, strlen(opt_value)-1);
195- /* second: null out the 2 characters we shifted */
196- opt_value[strlen(opt_value)-2] =' \0' ;
197- /* do the escape thing. pfree()'s the pstrdup above */
198- opt_value = GUC_scanstr(opt_value);
199- }
190+ if (token == GUC_STRING)/* strip quotes and escapes */
191+ opt_value = GUC_scanstr(yytext);
192+ else
193+ opt_value = pstrdup(yytext);
200194 parse_state = 2;
201195 break;
202196
@@ -280,34 +274,33 @@ ProcessConfigFile(GucContext context)
280274
281275
282276
283- /* ----------------
277+ /*
284278 *scanstr
285279 *
286- *if thestring passed in has escaped codes, map the escape codes to actual
287- *chars
280+ *Strip thequotes surrounding the given string, and collapse any embedded
281+ *'' sequences and backslash escapes.
288282 *
289283 * the string returned is palloc'd and should eventually be pfree'd by the
290- * caller; also we assume we should pfree the input string.
291- * ----------------
284+ * caller.
292285 */
293-
294286static char *
295- GUC_scanstr (char *s)
287+ GUC_scanstr (const char *s)
296288{
297289char *newStr;
298290int len,
299291i,
300292j;
301293
302- if (s ==NULL || s[0 ] ==' \0 ' )
303- {
304- if (s !=NULL )
305- pfree (s);
306- return pstrdup (" " );
307- }
294+ Assert (s !=NULL && s[0 ] ==' \' ' );
308295len =strlen (s);
296+ Assert (len >=2 );
297+ Assert (s[len-1 ] ==' \' ' );
298+
299+ /* Skip the leading quote; we'll handle the trailing quote below */
300+ s++, len--;
309301
310- newStr =palloc (len +1 );/* string cannot get longer */
302+ /* Since len still includes trailing quote, this is enough space */
303+ newStr =palloc (len);
311304
312305for (i =0 , j =0 ; i < len; i++)
313306{
@@ -354,13 +347,21 @@ GUC_scanstr(char *s)
354347default :
355348newStr[j] = s[i];
356349break ;
357- }
358350}/* switch */
351+ }
352+ else if (s[i] ==' \' ' && s[i+1 ] ==' \' ' )
353+ {
354+ /* doubled quote becomes just one quote */
355+ newStr[j] = s[++i];
356+ }
359357else
360358newStr[j] = s[i];
361359j++;
362360}
363- newStr[j] =' \0 ' ;
364- pfree (s);
361+
362+ /* We copied the ending quote to newStr, so replace with \0 */
363+ Assert (j >0 && j <= len);
364+ newStr[--j] =' \0 ' ;
365+
365366return newStr;
366367}