4
4
*
5
5
* Copyright 2000 by PostgreSQL Global Development Group
6
6
*
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 $
8
8
*/
9
9
10
10
%{
16
16
#include < sys/stat.h>
17
17
#include < unistd.h>
18
18
#include < errno.h>
19
+ #include < ctype.h>
19
20
20
21
#include " miscadmin.h"
21
22
#include " storage/fd.h"
32
33
GUC_INTEGER = 3 ,
33
34
GUC_REAL = 4 ,
34
35
GUC_EQUALS = 5 ,
36
+ GUC_UNQUOTED_STRING = 6 ,
35
37
GUC_EOL = 99 ,
36
38
GUC_ERROR = 100
37
39
};
45
47
46
48
/* prototype, so compiler is happy with our high warnings setting */
47
49
int GUC_yylex (void );
48
-
50
+ char * GUC_scanstr ( char *);
49
51
%}
50
52
51
53
SIGN (" -" |" +" )
@@ -61,16 +63,9 @@ LETTER [A-Za-z_\200-\377]
61
63
LETTER_OR_DIGIT [A-Za-z_0-9 \200 -\377 ]
62
64
63
65
ID {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 ]|\\ .)*\'
74
69
75
70
%%
76
71
@@ -80,6 +75,7 @@ STRING \'([^'\n]|\\.)*'
80
75
81
76
{ID} return GUC_ID;
82
77
{STRING} return GUC_STRING;
78
+ {UNQUOTED_STRING} return GUC_UNQUOTED_STRING;
83
79
{INTEGER} return GUC_INTEGER;
84
80
{REAL} return GUC_REAL;
85
81
= return GUC_EQUALS;
@@ -139,7 +135,8 @@ ProcessConfigFile(GucContext context)
139
135
int elevel;
140
136
FILE * fp;
141
137
142
- Assert(context == PGC_POSTMASTER || context == PGC_BACKEND || context == PGC_SIGHUP);
138
+ Assert(context == PGC_POSTMASTER || context == PGC_BACKEND
139
+ || context == PGC_SIGHUP);
143
140
Assert(DataDir);
144
141
elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR;
145
142
@@ -210,11 +207,24 @@ ProcessConfigFile(GucContext context)
210
207
if (token == GUC_EQUALS)
211
208
token = yylex();
212
209
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)
214
213
goto parse_error;
215
214
opt_value = strdup(yytext);
216
215
if (opt_value == NULL)
217
216
goto 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
+ }
218
228
parse_state = 2 ;
219
229
break ;
220
230
@@ -266,7 +276,8 @@ ProcessConfigFile(GucContext context)
266
276
FreeFile (fp);
267
277
free (filename);
268
278
free_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);
270
281
return ;
271
282
272
283
out_of_memory:
@@ -284,3 +295,88 @@ yywrap(void)
284
295
{
285
296
return 1 ;
286
297
}
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
+ }
0 commit comments