~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/utils/misc/guc-file.l

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*-pgsql-c-*- */
 
2
/*
 
3
 * Scanner for the configuration file
 
4
 *
 
5
 * Copyright (c) 2000-2011, PostgreSQL Global Development Group
 
6
 *
 
7
 * src/backend/utils/misc/guc-file.l
 
8
 */
 
9
 
 
10
%{
 
11
 
 
12
#include "postgres.h"
 
13
 
 
14
#include <ctype.h>
 
15
#include <unistd.h>
 
16
 
 
17
#include "miscadmin.h"
 
18
#include "storage/fd.h"
 
19
#include "utils/guc.h"
 
20
 
 
21
 
 
22
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
 
23
#undef fprintf
 
24
#define fprintf(file, fmt, msg)  ereport(ERROR, (errmsg_internal("%s", msg)))
 
25
 
 
26
enum {
 
27
        GUC_ID = 1,
 
28
        GUC_STRING = 2,
 
29
        GUC_INTEGER = 3,
 
30
        GUC_REAL = 4,
 
31
        GUC_EQUALS = 5,
 
32
        GUC_UNQUOTED_STRING = 6,
 
33
        GUC_QUALIFIED_ID = 7,
 
34
        GUC_EOL = 99,
 
35
        GUC_ERROR = 100
 
36
};
 
37
 
 
38
static unsigned int ConfigFileLineno;
 
39
 
 
40
/* flex fails to supply a prototype for yylex, so provide one */
 
41
int GUC_yylex(void);
 
42
 
 
43
static char *GUC_scanstr(const char *s);
 
44
 
 
45
%}
 
46
 
 
47
%option 8bit
 
48
%option never-interactive
 
49
%option nodefault
 
50
%option noinput
 
51
%option nounput
 
52
%option noyywrap
 
53
%option prefix="GUC_yy"
 
54
 
 
55
 
 
56
SIGN            ("-"|"+")
 
57
DIGIT           [0-9]
 
58
HEXDIGIT        [0-9a-fA-F]
 
59
 
 
60
UNIT_LETTER     [a-zA-Z]
 
61
 
 
62
INTEGER         {SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}*
 
63
 
 
64
EXPONENT        [Ee]{SIGN}?{DIGIT}+
 
65
REAL            {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
 
66
 
 
67
LETTER          [A-Za-z_\200-\377]
 
68
LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
 
69
 
 
70
ID              {LETTER}{LETTER_OR_DIGIT}*
 
71
QUALIFIED_ID    {ID}"."{ID}
 
72
 
 
73
UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
 
74
STRING          \'([^'\\\n]|\\.|\'\')*\'
 
75
 
 
76
%%
 
77
 
 
78
\n              ConfigFileLineno++; return GUC_EOL;
 
79
[ \t\r]+        /* eat whitespace */
 
80
#.*             /* eat comment (.* matches anything until newline) */
 
81
 
 
82
{ID}            return GUC_ID;
 
83
{QUALIFIED_ID}  return GUC_QUALIFIED_ID;
 
84
{STRING}        return GUC_STRING;
 
85
{UNQUOTED_STRING} return GUC_UNQUOTED_STRING;
 
86
{INTEGER}       return GUC_INTEGER;
 
87
{REAL}          return GUC_REAL;
 
88
=               return GUC_EQUALS;
 
89
 
 
90
.               return GUC_ERROR;
 
91
 
 
92
%%
 
93
 
 
94
 
 
95
 
 
96
/*
 
97
 * Exported function to read and process the configuration file. The
 
98
 * parameter indicates in what context the file is being read --- either
 
99
 * postmaster startup (including standalone-backend startup) or SIGHUP.
 
100
 * All options mentioned in the configuration file are set to new values.
 
101
 * If an error occurs, no values will be changed.
 
102
 */
 
103
void
 
104
ProcessConfigFile(GucContext context)
 
105
{
 
106
        int                     elevel;
 
107
        ConfigVariable *item,
 
108
                                   *head,
 
109
                                   *tail;
 
110
        char       *cvc = NULL;
 
111
        struct config_string *cvc_struct;
 
112
        const char *envvar;
 
113
        int                     i;
 
114
 
 
115
        Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
 
116
 
 
117
        if (context == PGC_SIGHUP)
 
118
        {
 
119
                /*
 
120
                 * To avoid cluttering the log, only the postmaster bleats loudly
 
121
                 * about problems with the config file.
 
122
                 */
 
123
                elevel = IsUnderPostmaster ? DEBUG2 : LOG;
 
124
        }
 
125
        else
 
126
                elevel = ERROR;
 
127
 
 
128
        /* Parse the file into a list of option names and values */
 
129
        head = tail = NULL;
 
130
 
 
131
        if (!ParseConfigFile(ConfigFileName, NULL, 0, elevel, &head, &tail))
 
132
                goto cleanup_list;
 
133
 
 
134
        /*
 
135
         * We need the proposed new value of custom_variable_classes to check
 
136
         * custom variables with.  ParseConfigFile ensured that if it's in
 
137
         * the file, it's first in the list.  But first check to see if we
 
138
         * have an active value from the command line, which should override
 
139
         * the file in any case.  (Since there's no relevant env var, the
 
140
         * only possible nondefault sources are the file and ARGV.)
 
141
         */
 
142
        cvc_struct = (struct config_string *)
 
143
                find_option("custom_variable_classes", false, elevel);
 
144
        Assert(cvc_struct);
 
145
        if (cvc_struct->gen.reset_source > PGC_S_FILE)
 
146
        {
 
147
                cvc = guc_strdup(elevel, cvc_struct->reset_val);
 
148
                if (cvc == NULL)
 
149
                        goto cleanup_list;
 
150
        }
 
151
        else if (head != NULL &&
 
152
                         guc_name_compare(head->name, "custom_variable_classes") == 0)
 
153
        {
 
154
                /*
 
155
                 * Need to canonicalize the value by calling the check hook.
 
156
                 */
 
157
                void   *extra = NULL;
 
158
 
 
159
                cvc = guc_strdup(elevel, head->value);
 
160
                if (cvc == NULL)
 
161
                        goto cleanup_list;
 
162
                if (!call_string_check_hook(cvc_struct, &cvc, &extra,
 
163
                                                                        PGC_S_FILE, elevel))
 
164
                        goto cleanup_list;
 
165
                if (extra)
 
166
                        free(extra);
 
167
        }
 
168
 
 
169
        /*
 
170
         * Mark all extant GUC variables as not present in the config file.
 
171
         * We need this so that we can tell below which ones have been removed
 
172
         * from the file since we last processed it.
 
173
         */
 
174
        for (i = 0; i < num_guc_variables; i++)
 
175
        {
 
176
                struct config_generic *gconf = guc_variables[i];
 
177
 
 
178
                gconf->status &= ~GUC_IS_IN_FILE;
 
179
        }
 
180
 
 
181
        /*
 
182
         * Check if all options are valid.  As a side-effect, the GUC_IS_IN_FILE
 
183
         * flag is set on each GUC variable mentioned in the list.
 
184
         */
 
185
        for (item = head; item; item = item->next)
 
186
        {
 
187
                char *sep = strchr(item->name, GUC_QUALIFIER_SEPARATOR);
 
188
 
 
189
                if (sep)
 
190
                {
 
191
                        /*
 
192
                         * We have to consider three cases for custom variables:
 
193
                         *
 
194
                         * 1. The class name is not valid according to the (new) setting
 
195
                         * of custom_variable_classes.  If so, reject.  We don't care
 
196
                         * which side is at fault.
 
197
                         */
 
198
                        if (!is_custom_class(item->name, sep - item->name, cvc))
 
199
                        {
 
200
                                ereport(elevel,
 
201
                                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
202
                                                 errmsg("unrecognized configuration parameter \"%s\"",
 
203
                                                                item->name)));
 
204
                                goto cleanup_list;
 
205
                        }
 
206
                        /*
 
207
                         * 2. There is no GUC entry.  If we called set_config_option then
 
208
                         * it would make a placeholder, which we don't want to do yet,
 
209
                         * since we could still fail further down the list.  Do nothing
 
210
                         * (assuming that making the placeholder will succeed later).
 
211
                         */
 
212
                        if (find_option(item->name, false, elevel) == NULL)
 
213
                                continue;
 
214
                        /*
 
215
                         * 3. There is already a GUC entry (either real or placeholder) for
 
216
                         * the variable.  In this case we should let set_config_option
 
217
                         * check it, since the assignment could well fail if it's a real
 
218
                         * entry.
 
219
                         */
 
220
                }
 
221
 
 
222
                if (!set_config_option(item->name, item->value, context,
 
223
                                                           PGC_S_FILE, GUC_ACTION_SET, false))
 
224
                        goto cleanup_list;
 
225
        }
 
226
 
 
227
        /*
 
228
         * Check for variables having been removed from the config file, and
 
229
         * revert their reset values (and perhaps also effective values) to the
 
230
         * boot-time defaults.  If such a variable can't be changed after startup,
 
231
         * just throw a warning and continue.  (This is analogous to the fact that
 
232
         * set_config_option only throws a warning for a new but different value.
 
233
         * If we wanted to make it a hard error, we'd need an extra pass over the
 
234
         * list so that we could throw the error before starting to apply
 
235
         * changes.)
 
236
         */
 
237
        for (i = 0; i < num_guc_variables; i++)
 
238
        {
 
239
                struct config_generic *gconf = guc_variables[i];
 
240
                GucStack   *stack;
 
241
 
 
242
                if (gconf->reset_source != PGC_S_FILE ||
 
243
                        (gconf->status & GUC_IS_IN_FILE))
 
244
                        continue;
 
245
                if (gconf->context < PGC_SIGHUP)
 
246
                {
 
247
                        ereport(elevel,
 
248
                                        (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
 
249
                                         errmsg("parameter \"%s\" cannot be changed without restarting the server",
 
250
                                                        gconf->name)));
 
251
                        continue;
 
252
                }
 
253
 
 
254
                /*
 
255
                 * Reset any "file" sources to "default", else set_config_option
 
256
                 * will not override those settings.
 
257
                 */
 
258
                if (gconf->reset_source == PGC_S_FILE)
 
259
                        gconf->reset_source = PGC_S_DEFAULT;
 
260
                if (gconf->source == PGC_S_FILE)
 
261
                        gconf->source = PGC_S_DEFAULT;
 
262
                for (stack = gconf->stack; stack; stack = stack->prev)
 
263
                {
 
264
                        if (stack->source == PGC_S_FILE)
 
265
                                stack->source = PGC_S_DEFAULT;
 
266
                }
 
267
 
 
268
                /* Now we can re-apply the wired-in default */
 
269
                set_config_option(gconf->name, NULL, context, PGC_S_DEFAULT,
 
270
                                                  GUC_ACTION_SET, true);
 
271
                if (context == PGC_SIGHUP)
 
272
                        ereport(elevel,
 
273
                                        (errmsg("parameter \"%s\" removed from configuration file, reset to default",
 
274
                                                        gconf->name)));
 
275
        }
 
276
 
 
277
        /*
 
278
         * Restore any variables determined by environment variables.  This
 
279
         * is a no-op except in the case where one of these had been in the
 
280
         * config file and is now removed.  PGC_S_ENV_VAR will override the
 
281
         * wired-in default we just applied, but cannot override any other source.
 
282
         *
 
283
         * Keep this list in sync with InitializeGUCOptions()!
 
284
         * PGPORT can be ignored, because it cannot be changed without restart.
 
285
         * We assume rlimit hasn't changed, either.
 
286
         */
 
287
        envvar = getenv("PGDATESTYLE");
 
288
        if (envvar != NULL)
 
289
                set_config_option("datestyle", envvar, PGC_POSTMASTER,
 
290
                                                  PGC_S_ENV_VAR, GUC_ACTION_SET, true);
 
291
 
 
292
        envvar = getenv("PGCLIENTENCODING");
 
293
        if (envvar != NULL)
 
294
                set_config_option("client_encoding", envvar, PGC_POSTMASTER,
 
295
                                                  PGC_S_ENV_VAR, GUC_ACTION_SET, true);
 
296
 
 
297
 
 
298
        /* If we got here all the options checked out okay, so apply them. */
 
299
        for (item = head; item; item = item->next)
 
300
        {
 
301
                char   *pre_value = NULL;
 
302
 
 
303
                /* In SIGHUP cases in the postmaster, report changes */
 
304
                if (context == PGC_SIGHUP && !IsUnderPostmaster)
 
305
                {
 
306
                        const char *preval = GetConfigOption(item->name, false);
 
307
 
 
308
                        /* string variables could be NULL; treat that as empty */
 
309
                        if (!preval)
 
310
                                preval = "";
 
311
                        /* must dup, else might have dangling pointer below */
 
312
                        pre_value = pstrdup(preval);
 
313
                }
 
314
 
 
315
                if (set_config_option(item->name, item->value, context,
 
316
                                                                 PGC_S_FILE, GUC_ACTION_SET, true))
 
317
                {
 
318
                        set_config_sourcefile(item->name, item->filename,
 
319
                                                                  item->sourceline);
 
320
 
 
321
                        if (pre_value)
 
322
                        {
 
323
                                const char *post_value = GetConfigOption(item->name, false);
 
324
 
 
325
                                if (!post_value)
 
326
                                        post_value = "";
 
327
                                if (strcmp(pre_value, post_value) != 0)
 
328
                                        ereport(elevel,
 
329
                                                        (errmsg("parameter \"%s\" changed to \"%s\"",
 
330
                                                                        item->name, item->value)));
 
331
                        }
 
332
                }
 
333
 
 
334
                if (pre_value)
 
335
                        pfree(pre_value);
 
336
        }
 
337
 
 
338
        /* Remember when we last successfully loaded the config file. */
 
339
        PgReloadTime = GetCurrentTimestamp();
 
340
 
 
341
 cleanup_list:
 
342
        FreeConfigVariables(head);
 
343
        if (cvc)
 
344
                free(cvc);
 
345
}
 
346
 
 
347
/*
 
348
 * See next function for details. This one will just work with a config_file
 
349
 * name rather than an already opened File Descriptor
 
350
 */
 
351
bool
 
352
ParseConfigFile(const char *config_file, const char *calling_file,
 
353
                                int depth, int elevel,
 
354
                                ConfigVariable **head_p,
 
355
                                ConfigVariable **tail_p)
 
356
{
 
357
        bool            OK = true;
 
358
        FILE       *fp;
 
359
        char            abs_path[MAXPGPATH];
 
360
 
 
361
        /*
 
362
         * Reject too-deep include nesting depth.  This is just a safety check
 
363
         * to avoid dumping core due to stack overflow if an include file loops
 
364
         * back to itself.  The maximum nesting depth is pretty arbitrary.
 
365
         */
 
366
        if (depth > 10)
 
367
        {
 
368
                ereport(elevel,
 
369
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
370
                                 errmsg("could not open configuration file \"%s\": maximum nesting depth exceeded",
 
371
                                                config_file)));
 
372
                return false;
 
373
        }
 
374
 
 
375
        /*
 
376
         * If config_file is a relative path, convert to absolute.  We consider
 
377
         * it to be relative to the directory holding the calling file.
 
378
         */
 
379
        if (!is_absolute_path(config_file))
 
380
        {
 
381
                if (calling_file != NULL)
 
382
                {
 
383
                        strlcpy(abs_path, calling_file, sizeof(abs_path));
 
384
                        get_parent_directory(abs_path);
 
385
                        join_path_components(abs_path, abs_path, config_file);
 
386
                        canonicalize_path(abs_path);
 
387
                        config_file = abs_path;
 
388
                }
 
389
                else
 
390
                {
 
391
                        /*
 
392
                         * calling_file is NULL, we make an absolute path from $PGDATA
 
393
                         */
 
394
                        join_path_components(abs_path, data_directory, config_file);
 
395
                        canonicalize_path(abs_path);
 
396
                        config_file = abs_path;
 
397
                }
 
398
        }
 
399
 
 
400
        fp = AllocateFile(config_file, "r");
 
401
        if (!fp)
 
402
        {
 
403
                ereport(elevel,
 
404
                                (errcode_for_file_access(),
 
405
                                 errmsg("could not open configuration file \"%s\": %m",
 
406
                                                config_file)));
 
407
                return false;
 
408
        }
 
409
 
 
410
        OK = ParseConfigFp(fp, config_file, depth, elevel, head_p, tail_p);
 
411
 
 
412
        FreeFile(fp);
 
413
 
 
414
        return OK;
 
415
}
 
416
 
 
417
/*
 
418
 * Read and parse a single configuration file.  This function recurses
 
419
 * to handle "include" directives.
 
420
 *
 
421
 * Input parameters:
 
422
 *      fp: file pointer from AllocateFile for the configuration file to parse
 
423
 *      config_file: absolute or relative path of file to read
 
424
 *      depth: recursion depth (used only to prevent infinite recursion)
 
425
 *      elevel: error logging level determined by ProcessConfigFile()
 
426
 * Output parameters:
 
427
 *      head_p, tail_p: head and tail of linked list of name/value pairs
 
428
 *
 
429
 * *head_p and *tail_p must be initialized to NULL before calling the outer
 
430
 * recursion level.  On exit, they contain a list of name-value pairs read
 
431
 * from the input file(s).
 
432
 *
 
433
 * Returns TRUE if successful, FALSE if an error occurred.  The error has
 
434
 * already been ereport'd, it is only necessary for the caller to clean up
 
435
 * its own state and release the name/value pairs list.
 
436
 *
 
437
 * Note: if elevel >= ERROR then an error will not return control to the
 
438
 * caller, and internal state such as open files will not be cleaned up.
 
439
 * This case occurs only during postmaster or standalone-backend startup,
 
440
 * where an error will lead to immediate process exit anyway; so there is
 
441
 * no point in contorting the code so it can clean up nicely.
 
442
 */
 
443
bool
 
444
ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
 
445
                          ConfigVariable **head_p, ConfigVariable **tail_p)
 
446
{
 
447
        bool            OK = true;
 
448
        YY_BUFFER_STATE lex_buffer;
 
449
        int                     token;
 
450
 
 
451
        /*
 
452
         * Parse
 
453
         */
 
454
        lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE);
 
455
        yy_switch_to_buffer(lex_buffer);
 
456
 
 
457
        ConfigFileLineno = 1;
 
458
 
 
459
        /* This loop iterates once per logical line */
 
460
        while ((token = yylex()))
 
461
        {
 
462
                char       *opt_name, *opt_value;
 
463
                ConfigVariable *item;
 
464
 
 
465
                if (token == GUC_EOL)   /* empty or comment line */
 
466
                        continue;
 
467
 
 
468
                /* first token on line is option name */
 
469
                if (token != GUC_ID && token != GUC_QUALIFIED_ID)
 
470
                        goto parse_error;
 
471
                opt_name = pstrdup(yytext);
 
472
 
 
473
                /* next we have an optional equal sign; discard if present */
 
474
                token = yylex();
 
475
                if (token == GUC_EQUALS)
 
476
                        token = yylex();
 
477
 
 
478
                /* now we must have the option value */
 
479
                if (token != GUC_ID &&
 
480
                        token != GUC_STRING &&
 
481
                        token != GUC_INTEGER &&
 
482
                        token != GUC_REAL &&
 
483
                        token != GUC_UNQUOTED_STRING)
 
484
                        goto parse_error;
 
485
                if (token == GUC_STRING)        /* strip quotes and escapes */
 
486
                        opt_value = GUC_scanstr(yytext);
 
487
                else
 
488
                        opt_value = pstrdup(yytext);
 
489
 
 
490
                /* now we'd like an end of line, or possibly EOF */
 
491
                token = yylex();
 
492
                if (token != GUC_EOL)
 
493
                {
 
494
                        if (token != 0)
 
495
                                goto parse_error;
 
496
                        /* treat EOF like \n for line numbering purposes, cf bug 4752 */
 
497
                        ConfigFileLineno++;
 
498
                }
 
499
 
 
500
                /* OK, process the option name and value */
 
501
                if (guc_name_compare(opt_name, "include") == 0)
 
502
                {
 
503
                        /*
 
504
                         * An include directive isn't a variable and should be processed
 
505
                         * immediately.
 
506
                         */
 
507
                        unsigned int save_ConfigFileLineno = ConfigFileLineno;
 
508
 
 
509
                        if (!ParseConfigFile(opt_value, config_file,
 
510
                                                                 depth + 1, elevel,
 
511
                                                                 head_p, tail_p))
 
512
                        {
 
513
                                pfree(opt_name);
 
514
                                pfree(opt_value);
 
515
                                OK = false;
 
516
                                goto cleanup_exit;
 
517
                        }
 
518
                        yy_switch_to_buffer(lex_buffer);
 
519
                        ConfigFileLineno = save_ConfigFileLineno;
 
520
                        pfree(opt_name);
 
521
                        pfree(opt_value);
 
522
                }
 
523
                else if (guc_name_compare(opt_name, "custom_variable_classes") == 0)
 
524
                {
 
525
                        /*
 
526
                         * This variable must be processed first as it controls
 
527
                         * the validity of other variables; so it goes at the head
 
528
                         * of the result list.  If we already found a value for it,
 
529
                         * replace with this one.
 
530
                         */
 
531
                        item = *head_p;
 
532
                        if (item != NULL &&
 
533
                                guc_name_compare(item->name, "custom_variable_classes") == 0)
 
534
                        {
 
535
                                /* replace existing head item */
 
536
                                pfree(item->name);
 
537
                                pfree(item->value);
 
538
                                item->name = opt_name;
 
539
                                item->value = opt_value;
 
540
                                item->filename = pstrdup(config_file);
 
541
                                item->sourceline = ConfigFileLineno-1;
 
542
                        }
 
543
                        else
 
544
                        {
 
545
                                /* prepend to list */
 
546
                                item = palloc(sizeof *item);
 
547
                                item->name = opt_name;
 
548
                                item->value = opt_value;
 
549
                                item->filename = pstrdup(config_file);
 
550
                                item->sourceline = ConfigFileLineno-1;
 
551
                                item->next = *head_p;
 
552
                                *head_p = item;
 
553
                                if (*tail_p == NULL)
 
554
                                        *tail_p = item;
 
555
                        }
 
556
                }
 
557
                else
 
558
                {
 
559
                        /* ordinary variable, append to list */
 
560
                        item = palloc(sizeof *item);
 
561
                        item->name = opt_name;
 
562
                        item->value = opt_value;
 
563
                        item->filename = pstrdup(config_file);
 
564
                        item->sourceline = ConfigFileLineno-1;
 
565
                        item->next = NULL;
 
566
                        if (*head_p == NULL)
 
567
                                *head_p = item;
 
568
                        else
 
569
                                (*tail_p)->next = item;
 
570
                        *tail_p = item;
 
571
                }
 
572
 
 
573
                /* break out of loop if read EOF, else loop for next line */
 
574
                if (token == 0)
 
575
                        break;
 
576
        }
 
577
 
 
578
        /* successful completion of parsing */
 
579
        goto cleanup_exit;
 
580
 
 
581
 parse_error:
 
582
        if (token == GUC_EOL || token == 0)
 
583
                ereport(elevel,
 
584
                                (errcode(ERRCODE_SYNTAX_ERROR),
 
585
                                 errmsg("syntax error in file \"%s\" line %u, near end of line",
 
586
                                                config_file, ConfigFileLineno - 1)));
 
587
        else
 
588
                ereport(elevel,
 
589
                                (errcode(ERRCODE_SYNTAX_ERROR),
 
590
                                 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
 
591
                                                config_file, ConfigFileLineno, yytext)));
 
592
        OK = false;
 
593
 
 
594
cleanup_exit:
 
595
        yy_delete_buffer(lex_buffer);
 
596
        return OK;
 
597
}
 
598
 
 
599
 
 
600
/*
 
601
 * Free a list of ConfigVariables, including the names and the values
 
602
 */
 
603
void
 
604
FreeConfigVariables(ConfigVariable *list)
 
605
{
 
606
        ConfigVariable *item;
 
607
 
 
608
        item = list;
 
609
        while (item)
 
610
        {
 
611
                ConfigVariable *next = item->next;
 
612
 
 
613
                pfree(item->name);
 
614
                pfree(item->value);
 
615
                pfree(item->filename);
 
616
                pfree(item);
 
617
                item = next;
 
618
        }
 
619
}
 
620
 
 
621
 
 
622
/*
 
623
 *              scanstr
 
624
 *
 
625
 * Strip the quotes surrounding the given string, and collapse any embedded
 
626
 * '' sequences and backslash escapes.
 
627
 *
 
628
 * the string returned is palloc'd and should eventually be pfree'd by the
 
629
 * caller.
 
630
 */
 
631
static char *
 
632
GUC_scanstr(const char *s)
 
633
{
 
634
        char       *newStr;
 
635
        int                     len,
 
636
                                i,
 
637
                                j;
 
638
 
 
639
        Assert(s != NULL && s[0] == '\'');
 
640
        len = strlen(s);
 
641
        Assert(len >= 2);
 
642
        Assert(s[len-1] == '\'');
 
643
 
 
644
        /* Skip the leading quote; we'll handle the trailing quote below */
 
645
        s++, len--;
 
646
 
 
647
        /* Since len still includes trailing quote, this is enough space */
 
648
        newStr = palloc(len);
 
649
 
 
650
        for (i = 0, j = 0; i < len; i++)
 
651
        {
 
652
                if (s[i] == '\\')
 
653
                {
 
654
                        i++;
 
655
                        switch (s[i])
 
656
                        {
 
657
                                case 'b':
 
658
                                        newStr[j] = '\b';
 
659
                                        break;
 
660
                                case 'f':
 
661
                                        newStr[j] = '\f';
 
662
                                        break;
 
663
                                case 'n':
 
664
                                        newStr[j] = '\n';
 
665
                                        break;
 
666
                                case 'r':
 
667
                                        newStr[j] = '\r';
 
668
                                        break;
 
669
                                case 't':
 
670
                                        newStr[j] = '\t';
 
671
                                        break;
 
672
                                case '0':
 
673
                                case '1':
 
674
                                case '2':
 
675
                                case '3':
 
676
                                case '4':
 
677
                                case '5':
 
678
                                case '6':
 
679
                                case '7':
 
680
                                        {
 
681
                                                int                     k;
 
682
                                                long            octVal = 0;
 
683
 
 
684
                                                for (k = 0;
 
685
                                                         s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
 
686
                                                         k++)
 
687
                                                        octVal = (octVal << 3) + (s[i + k] - '0');
 
688
                                                i += k - 1;
 
689
                                                newStr[j] = ((char) octVal);
 
690
                                        }
 
691
                                        break;
 
692
                                default:
 
693
                                        newStr[j] = s[i];
 
694
                                        break;
 
695
                        }                                       /* switch */
 
696
                }
 
697
                else if (s[i] == '\'' && s[i+1] == '\'')
 
698
                {
 
699
                        /* doubled quote becomes just one quote */
 
700
                        newStr[j] = s[++i];
 
701
                }
 
702
                else
 
703
                        newStr[j] = s[i];
 
704
                j++;
 
705
        }
 
706
 
 
707
        /* We copied the ending quote to newStr, so replace with \0 */
 
708
        Assert(j > 0 && j <= len);
 
709
        newStr[--j] = '\0';
 
710
 
 
711
        return newStr;
 
712
}