44 *
55 * Copyright 2000 by PostgreSQL Global Development Group
66 *
7- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc-file.l,v 1.4 2000/07/27 19:49:18 momjian Exp $
7+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc-file.l,v 1.5 2000/11/16 05:50:01 momjian Exp $
88 */
99
1010%{
1616#include < sys/stat.h>
1717#include < unistd.h>
1818#include < errno.h>
19+ #include < ctype.h>
1920
2021#include " miscadmin.h"
2122#include " storage/fd.h"
3233GUC_INTEGER =3 ,
3334GUC_REAL =4 ,
3435GUC_EQUALS =5 ,
36+ GUC_UNQUOTED_STRING =6 ,
3537GUC_EOL =99 ,
3638GUC_ERROR =100
3739};
4547
4648/* prototype, so compiler is happy with our high warnings setting */
4749int GUC_yylex (void );
48-
50+ char * GUC_scanstr ( char *);
4951%}
5052
5153SIGN (" -" |" +" )
@@ -61,16 +63,9 @@ LETTER [A-Za-z_\200-\377]
6163LETTER_OR_DIGIT [A-Za-z_0-9 \200 -\377 ]
6264
6365ID {LETTER}{LETTER_OR_DIGIT}*
64- /*
65- * FIXME: This string syntax is nice and all but of course the quotes
66- * need to be stripped before we can make any use of the string value.
67- * There is a function in parser/scansup.c that does this but it uses
68- * palloc and there might be a little more magic needed to get it to
69- * work right. Now there are no string options, and if there were then
70- * the unquoted (`ID') tokens should still work. Of course this only
71- * affects the configuration file.
72- */
73- STRING \' ([^' \n]|\\.)*'
66+
67+ UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
68+ STRING \' ([^' " \n ]|\\ .)*\'
7469
7570%%
7671
@@ -80,6 +75,7 @@ STRING \'([^'\n]|\\.)*'
8075
8176{ID} return GUC_ID;
8277{STRING} return GUC_STRING;
78+ {UNQUOTED_STRING} return GUC_UNQUOTED_STRING;
8379{INTEGER} return GUC_INTEGER;
8480{REAL} return GUC_REAL;
8581= return GUC_EQUALS;
@@ -139,7 +135,8 @@ ProcessConfigFile(GucContext context)
139135int elevel;
140136FILE * fp;
141137
142- Assert(context == PGC_POSTMASTER || context == PGC_BACKEND || context == PGC_SIGHUP);
138+ Assert(context == PGC_POSTMASTER || context == PGC_BACKEND
139+ || context == PGC_SIGHUP);
143140Assert(DataDir);
144141elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR;
145142
@@ -210,11 +207,24 @@ ProcessConfigFile(GucContext context)
210207 if (token == GUC_EQUALS)
211208 token = yylex();
212209
213- if (token != GUC_ID && token != GUC_STRING && token != GUC_INTEGER && token != GUC_REAL)
210+ if (token != GUC_ID && token != GUC_STRING &&
211+ token != GUC_INTEGER && token != GUC_REAL &&
212+ token != GUC_UNQUOTED_STRING)
214213 goto parse_error;
215214 opt_value = strdup(yytext);
216215if (opt_value == NULL)
217216goto out_of_memory;
217+ if (token == GUC_STRING)
218+ {
219+ /* remove the beginning and ending quote/apostrophe */
220+ /* first: shift the whole shooting match down one
221+ character */
222+ memmove(opt_value,opt_value+1,strlen(opt_value)-1);
223+ /* second: null out the 2 characters we shifted */
224+ opt_value[strlen(opt_value)-2]=' \0' ;
225+ /* do the escape thing. free()'s the strdup above */
226+ opt_value=GUC_scanstr(opt_value);
227+ }
218228 parse_state =2 ;
219229break ;
220230
@@ -266,7 +276,8 @@ ProcessConfigFile(GucContext context)
266276FreeFile (fp);
267277free (filename);
268278free_name_value_list (head);
269- elog(elevel, CONFIG_FILENAME" :%u: syntax error" , ConfigFileLineno);
279+ elog (elevel, CONFIG_FILENAME" :%u: syntax error, token=\" %s\" " ,
280+ ConfigFileLineno,yytext);
270281return ;
271282
272283 out_of_memory:
@@ -284,3 +295,88 @@ yywrap(void)
284295{
285296return 1 ;
286297}
298+
299+ /* ----------------
300+ *scanstr
301+ *
302+ * if the string passed in has escaped codes, map the escape codes to actual
303+ * chars
304+ *
305+ * the string returned is malloc'd and should eventually be free'd by the
306+ * caller!
307+ * ----------------
308+ */
309+
310+ char *
311+ GUC_scanstr (char *s)
312+ {
313+ char *newStr;
314+ int len,
315+ i,
316+ j;
317+
318+ if (s ==NULL || s[0 ] ==' \0 ' )
319+ {
320+ if (s !=NULL )free (s);
321+ return strdup (" " );
322+
323+ }
324+ len =strlen (s);
325+
326+ newStr =malloc (len +1 );/* string cannot get longer */
327+
328+ for (i =0 , j =0 ; i < len; i++)
329+ {
330+ if (s[i] ==' \\ ' )
331+ {
332+ i++;
333+ switch (s[i])
334+ {
335+ case ' b' :
336+ newStr[j] =' \b ' ;
337+ break ;
338+ case ' f' :
339+ newStr[j] =' \f ' ;
340+ break ;
341+ case ' n' :
342+ newStr[j] =' \n ' ;
343+ break ;
344+ case ' r' :
345+ newStr[j] =' \r ' ;
346+ break ;
347+ case ' t' :
348+ newStr[j] =' \t ' ;
349+ break ;
350+ case ' 0' :
351+ case ' 1' :
352+ case ' 2' :
353+ case ' 3' :
354+ case ' 4' :
355+ case ' 5' :
356+ case ' 6' :
357+ case ' 7' :
358+ {
359+ int k;
360+ long octVal =0 ;
361+
362+ for (k =0 ;
363+ s[i + k] >=' 0' && s[i + k] <=' 7' && k <3 ;
364+ k++)
365+ octVal = (octVal <<3 ) + (s[i + k] -' 0' );
366+ i += k -1 ;
367+ newStr[j] = ((char ) octVal);
368+ }
369+ break ;
370+ default :
371+ newStr[j] = s[i];
372+ break ;
373+ }
374+ }/* switch */
375+ else
376+ newStr[j] = s[i];
377+ j++;
378+ }
379+ newStr[j] =' \0 ' ;
380+ free (s);
381+ return newStr;
382+ }