yysyntax_error: avoid duplicate lookahead collection.

Except when memory reallocation is required, this change
eliminates the need to invoke yysyntax_error twice and thus to
repeat the collection of lookaheads.  It also prepares for
future extensions that will make those repetitions more
expensive and that will require additional memory management in
yysyntax_error.  Finally, it fixes an obscure bug already
exercised in the test suite.
* data/yacc.c (yysyntax_error): Add arguments for message
buffer variables stored in the parser.  Instead of size, return
status similar to yyparse status but indicating success of
message creation.  Other than the actual reallocation of the
message buffer, import and clean up memory management code
from...
(yyparse, yypush_parse): ... here.
* tests/regression.at (parse.error=verbose overflow): No longer
an expected failure.
This commit is contained in:
Joel E. Denny
2009-09-23 17:39:39 -04:00
parent 52cea04ad3
commit 45319f1365
5 changed files with 470 additions and 437 deletions

View File

@@ -1,3 +1,23 @@
2009-09-23 Joel E. Denny <jdenny@clemson.edu>
yysyntax_error: avoid duplicate lookahead collection.
Except when memory reallocation is required, this change
eliminates the need to invoke yysyntax_error twice and thus to
repeat the collection of lookaheads. It also prepares for
future extensions that will make those repetitions more
expensive and that will require additional memory management in
yysyntax_error. Finally, it fixes an obscure bug already
exercised in the test suite.
* data/yacc.c (yysyntax_error): Add arguments for message
buffer variables stored in the parser. Instead of size, return
status similar to yyparse status but indicating success of
message creation. Other than the actual reallocation of the
message buffer, import and clean up memory management code
from...
(yyparse, yypush_parse): ... here.
* tests/regression.at (parse.error=verbose overflow): No longer
an expected failure.
2009-09-23 Joel E. Denny <jdenny@clemson.edu>
yysyntax_error: test memory management more.

View File

@@ -889,26 +889,27 @@ yytnamerr (char *yyres, const char *yystr)
}
# endif
/* Copy into YYRESULT an error message about the unexpected token
YYTOKEN while in state YYSTATE. Return the number of bytes copied,
including the terminating null byte. If YYRESULT is null, do not
copy anything; just return the number of bytes that would be
copied. As a special case, return 0 if an ordinary "syntax error"
message will do. Return YYSIZE_MAXIMUM if overflow occurs during
size calculation. */
static YYSIZE_T
yysyntax_error (char *yyresult, int yystate, int yytoken)
/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
about the unexpected token YYTOKEN while in state YYSTATE.
Return 0 if *YYMSG was successfully written. Return 1 if an ordinary
"syntax error" message will suffice instead. Return 2 if *YYMSG is
not large enough to hold the message. In the last case, also set
*YYMSG_ALLOC to either (a) the required number of bytes or (b) zero
if the required number of bytes is too large to store. */
static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
int yystate, int yytoken)
{
int yyn = yypact[yystate];
if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
return 0;
return 1;
else
{
YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
int yysize_overflow = 0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
const char *yyformat = 0;
@@ -942,11 +943,17 @@ yysyntax_error (char *yyresult, int yystate, int yytoken)
}
yyarg[yycount++] = yytname[yyx];
yysize1 = yysize + yytnamerr (0, yytname[yyx]);
yysize_overflow |= (yysize1 < yysize);
if (! (yysize <= yysize1
&& yysize1 <= YYSTACK_ALLOC_MAXIMUM))
{
/* Overflow. */
*yymsg_alloc = 0;
return 2;
}
yysize = yysize1;
}
switch (yycount)
switch (yycount)
{
#define YYCASE_(N, S) \
case N: \
@@ -961,32 +968,42 @@ yysyntax_error (char *yyresult, int yystate, int yytoken)
}
yysize1 = yysize + yystrlen (yyformat);
yysize_overflow |= (yysize1 < yysize);
if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
{
/* Overflow. */
*yymsg_alloc = 0;
return 2;
}
yysize = yysize1;
if (yysize_overflow)
return YYSIZE_MAXIMUM;
if (*yymsg_alloc < yysize)
{
*yymsg_alloc = 2 * yysize;
if (! (yysize <= *yymsg_alloc
&& *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
*yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
return 2;
}
if (yyresult)
{
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
char *yyp = yyresult;
int yyi = 0;
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyformat += 2;
}
else
{
yyp++;
yyformat++;
}
}
return yysize;
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
{
char *yyp = *yymsg;
int yyi = 0;
while ((*yyp = *yyformat) != '\0')
if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyformat += 2;
}
else
{
yyp++;
yyformat++;
}
}
return 0;
}
}
#endif /* YYERROR_VERBOSE */
@@ -1431,37 +1448,28 @@ yyerrlab:
#if ! YYERROR_VERBOSE
yyerror (]b4_yyerror_args[YY_("syntax error"));
#else
{
YYSIZE_T yysize = yysyntax_error (0, yystate, yytoken);
if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
{
YYSIZE_T yyalloc = 2 * yysize;
if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
yyalloc = YYSTACK_ALLOC_MAXIMUM;
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yyalloc);
if (yymsg)
yymsg_alloc = yyalloc;
else
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
}
}
if (0 < yysize && yysize <= yymsg_alloc)
{
(void) yysyntax_error (yymsg, yystate, yytoken);
yyerror (]b4_yyerror_args[yymsg);
}
else
{
yyerror (]b4_yyerror_args[YY_("syntax error"));
if (yysize != 0)
goto yyexhaustedlab;
}
}
while (1)
{
int yysyntax_error_status =
yysyntax_error (&yymsg_alloc, &yymsg, yystate, yytoken);
if (yysyntax_error_status == 2 && 0 < yymsg_alloc)
{
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
if (yymsg)
continue;
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
}
if (yysyntax_error_status == 0)
yyerror (]b4_yyerror_args[yymsg);
else
yyerror (]b4_yyerror_args[YY_("syntax error"));
if (yysyntax_error_status == 2)
goto yyexhaustedlab;
break;
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 2.4.404-c6ab. */
/* A Bison parser, made by GNU Bison 2.4.425-305c-dirty. */
/* Interface for Bison's Yacc-like parsers in C
@@ -31,7 +31,7 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* "%code requires" blocks. */
/* Line 1616 of yacc.c */
/* Line 1624 of yacc.c */
#line 201 "src/parse-gram.y"
# ifndef PARAM_TYPE
@@ -46,7 +46,7 @@
# endif
/* Line 1616 of yacc.c */
/* Line 1624 of yacc.c */
#line 51 "src/parse-gram.h"
/* Tokens. */
@@ -173,7 +173,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 1616 of yacc.c */
/* Line 1624 of yacc.c */
#line 88 "src/parse-gram.y"
assoc assoc;
@@ -186,13 +186,13 @@ typedef union YYSTYPE
uniqstr uniqstr;
unsigned char character;
/* Line 1616 of yacc.c */
/* Line 1624 of yacc.c */
#line 225 "src/parse-gram.y"
param_type param;
/* Line 1616 of yacc.c */
/* Line 1624 of yacc.c */
#line 197 "src/parse-gram.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1

View File

@@ -1350,16 +1350,13 @@ AT_CLEANUP
# Imagine the case where YYSTACK_ALLOC_MAXIMUM = YYSIZE_MAXIMUM and an
# invocation of yysyntax_error has caused yymsg_alloc to grow to exactly
# YYSTACK_ALLOC_MAXIMUM (perhaps because the normal doubling of size had
# to be clipped to YYSTACK_ALLOC_MAXIMUM). Now imagine a subsequent
# invocation of yysyntax_error that overflows during its size
# calculation and thus returns YYSIZE_MAXIMUM to yyparse. Then, yyparse
# will invoke yyerror using the old contents of yymsg. This bug needs
# to be fixed.
# to be clipped to YYSTACK_ALLOC_MAXIMUM). In an old version of yacc.c,
# a subsequent invocation of yysyntax_error that overflows during its
# size calculation would return YYSIZE_MAXIMUM to yyparse. Then,
# yyparse would invoke yyerror using the old contents of yymsg.
AT_SETUP([[parse.error=verbose overflow]])
AT_XFAIL_IF([[:]])
AT_DATA_GRAMMAR([input.y],
[[%code {
#include <stdio.h>