3 * Scanner for the configuration file
5 * Copyright (c) 2000-2005, PostgreSQL Global Development Group
7 * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.33 2006/01/01 19:52:40 tgl Exp $
17 #include "miscadmin.h"
18 #include "storage/fd.h"
19 #include "utils/guc.h"
21 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
23 #define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg)))
25 static unsigned ConfigFileLineno;
33 GUC_UNQUOTED_STRING = 6,
39 /* prototype, so compiler is happy with our high warnings setting */
41 static char *GUC_scanstr(const char *s);
45 %option never-interactive
55 INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+)
57 EXPONENT [Ee]{SIGN}?{DIGIT}+
58 REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
60 LETTER [A-Za-z_\200-\377]
61 LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
63 ID {LETTER}{LETTER_OR_DIGIT}*
64 QUALIFIED_ID {ID}"."{ID}
66 UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
67 STRING \'([^'\\\n]|\\.|\'\')*\'
71 \n ConfigFileLineno++; return GUC_EOL;
72 [ \t\r]+ /* eat whitespace */
73 #.* /* eat comment (.* matches anything until newline) */
76 {QUALIFIED_ID} return GUC_QUALIFIED_ID;
77 {STRING} return GUC_STRING;
78 {UNQUOTED_STRING} return GUC_UNQUOTED_STRING;
79 {INTEGER} return GUC_INTEGER;
80 {REAL} return GUC_REAL;
88 struct name_value_pair
92 struct name_value_pair *next;
97 * Free a list of name/value pairs, including the names and the values
100 free_name_value_list(struct name_value_pair * list)
102 struct name_value_pair *item;
107 struct name_value_pair *save;
119 * Official function to read and process the configuration file. The
120 * parameter indicates in what context the file is being read --- either
121 * postmaster startup (including standalone-backend startup) or SIGHUP.
122 * All options mentioned in the configuration file are set to new values.
123 * If an error occurs, no values will be changed.
126 ProcessConfigFile(GucContext context)
130 char *opt_name, *opt_value;
131 struct name_value_pair *item, *head, *tail;
134 Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
136 if (context == PGC_SIGHUP)
139 * To avoid cluttering the log, only the postmaster bleats loudly
140 * about problems with the config file.
142 elevel = IsUnderPostmaster ? DEBUG2 : LOG;
147 fp = AllocateFile(ConfigFileName, "r");
151 (errcode_for_file_access(),
152 errmsg("could not open configuration file \"%s\": %m",
161 YY_FLUSH_BUFFER; /* in case we abandoned a prior scan */
163 opt_name = opt_value = NULL;
164 ConfigFileLineno = 1;
166 /* This loop iterates once per logical line */
167 while ((token = yylex()))
169 if (token == GUC_EOL) /* empty or comment line */
172 /* first token on line is option name */
173 if (token != GUC_ID && token != GUC_QUALIFIED_ID)
175 opt_name = pstrdup(yytext);
177 /* next we have an optional equal sign; discard if present */
179 if (token == GUC_EQUALS)
182 /* now we must have the option value */
183 if (token != GUC_ID &&
184 token != GUC_STRING &&
185 token != GUC_INTEGER &&
187 token != GUC_UNQUOTED_STRING)
189 if (token == GUC_STRING) /* strip quotes and escapes */
190 opt_value = GUC_scanstr(yytext);
192 opt_value = pstrdup(yytext);
194 /* now we'd like an end of line, or possibly EOF */
196 if (token != GUC_EOL && token != 0)
199 /* OK, save the option name and value */
200 if (strcmp(opt_name, "custom_variable_classes") == 0)
203 * This variable must be processed first as it controls
204 * the validity of other variables; so apply immediately.
206 if (!set_config_option(opt_name, opt_value, context,
207 PGC_S_FILE, false, true))
220 item = palloc(sizeof *item);
221 item->name = opt_name;
222 item->value = opt_value;
231 /* break out of loop if read EOF, else loop for next line */
239 * Check if all options are valid
241 for(item = head; item; item=item->next)
243 if (!set_config_option(item->name, item->value, context,
244 PGC_S_FILE, false, false))
248 /* If we got here all the options parsed okay, so apply them. */
249 for(item = head; item; item=item->next)
251 set_config_option(item->name, item->value, context,
252 PGC_S_FILE, false, true);
256 free_name_value_list(head);
261 free_name_value_list(head);
262 if (token == GUC_EOL || token == 0)
264 (errcode(ERRCODE_SYNTAX_ERROR),
265 errmsg("syntax error in file \"%s\" line %u, near end of line",
266 ConfigFileName, ConfigFileLineno - 1)));
269 (errcode(ERRCODE_SYNTAX_ERROR),
270 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
271 ConfigFileName, ConfigFileLineno, yytext)));
279 * Strip the quotes surrounding the given string, and collapse any embedded
280 * '' sequences and backslash escapes.
282 * the string returned is palloc'd and should eventually be pfree'd by the
286 GUC_scanstr(const char *s)
293 Assert(s != NULL && s[0] == '\'');
296 Assert(s[len-1] == '\'');
298 /* Skip the leading quote; we'll handle the trailing quote below */
301 /* Since len still includes trailing quote, this is enough space */
302 newStr = palloc(len);
304 for (i = 0, j = 0; i < len; i++)
339 s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
341 octVal = (octVal << 3) + (s[i + k] - '0');
343 newStr[j] = ((char) octVal);
351 else if (s[i] == '\'' && s[i+1] == '\'')
353 /* doubled quote becomes just one quote */
361 /* We copied the ending quote to newStr, so replace with \0 */
362 Assert(j > 0 && j <= len);