Rewrite ProcessConfigFile() to avoid misbehavior at EOF, as per report

from Andrus Moor.  The former state-machine-style coding wasn't actually
doing much except obscuring the control flow, and it didn't extend
readily to fix this case, so I just took it out.  Also, add a
YY_FLUSH_BUFFER call to ensure the lexer is reset correctly if the
previous scan failed partway through the file.
This commit is contained in:
Tom Lane 2006-01-01 19:52:40 +00:00
parent 0898033b1e
commit fc6da31ae1
1 changed files with 72 additions and 73 deletions

View File

@ -4,7 +4,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.32 2005/09/21 20:33:34 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.33 2006/01/01 19:52:40 tgl Exp $
*/
%{
@ -126,7 +126,7 @@ void
ProcessConfigFile(GucContext context)
{
int elevel;
int token, parse_state;
int token;
char *opt_name, *opt_value;
struct name_value_pair *item, *head, *tail;
FILE *fp;
@ -158,29 +158,28 @@ ProcessConfigFile(GucContext context)
* Parse
*/
yyin = fp;
parse_state = 0;
YY_FLUSH_BUFFER; /* in case we abandoned a prior scan */
head = tail = NULL;
opt_name = opt_value = NULL;
ConfigFileLineno = 1;
/* This loop iterates once per logical line */
while ((token = yylex()))
{
switch(parse_state)
{
case 0: /* no previous input */
if (token == GUC_EOL) /* empty line */
if (token == GUC_EOL) /* empty or comment line */
continue;
/* first token on line is option name */
if (token != GUC_ID && token != GUC_QUALIFIED_ID)
goto parse_error;
opt_name = pstrdup(yytext);
parse_state = 1;
break;
case 1: /* found name */
/* ignore equals sign */
/* next we have an optional equal sign; discard if present */
token = yylex();
if (token == GUC_EQUALS)
token = yylex();
/* now we must have the option value */
if (token != GUC_ID &&
token != GUC_STRING &&
token != GUC_INTEGER &&
@ -191,13 +190,13 @@ ProcessConfigFile(GucContext context)
opt_value = GUC_scanstr(yytext);
else
opt_value = pstrdup(yytext);
parse_state = 2;
break;
case 2: /* now we'd like an end of line */
if (token != GUC_EOL)
/* now we'd like an end of line, or possibly EOF */
token = yylex();
if (token != GUC_EOL && token != 0)
goto parse_error;
/* OK, save the option name and value */
if (strcmp(opt_name, "custom_variable_classes") == 0)
{
/*
@ -229,10 +228,10 @@ ProcessConfigFile(GucContext context)
tail = item;
}
parse_state = 0;
/* break out of loop if read EOF, else loop for next line */
if (token == 0)
break;
}
}
FreeFile(fp);
@ -260,7 +259,7 @@ ProcessConfigFile(GucContext context)
parse_error:
FreeFile(fp);
free_name_value_list(head);
if (token == GUC_EOL)
if (token == GUC_EOL || token == 0)
ereport(elevel,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error in file \"%s\" line %u, near end of line",