Problem reported by twlevo@xs4all.nl.
* data/glr.c (struct yyGLRStack): Remove yyerrflag member.
All uses removed.
(yyStackOverflow): Just longjmp, but with value 2 so that caller
can handle the problem.
(YYCHK1): Use goto (a la yacc.c) rather than setting a flag.
(yyparse): New local variable yyresult to record the result.
Use result of setjmp to set it, rather than storing itinto
struct.
(yyDone): Remove label.
(yyacceptlab, yyabortlab, yyoverflowlab, yyreturn): New labels,
to mimic yacc.c. Do not discard lookahead if it's EOF (possible
if YYABORT is used).
* tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Exit with
yyparse status; put status > 1 into diagnostic.
Check that status==2 works.
* tests/calc.at, tests/cxx-type.at, tests/glr-regression.at:
Use exit status 3 for failure to open (which shouldn't happen).
+2005-07-18 Paul Eggert <eggert@cs.ucla.edu>
+
+ Improve tests for stack overflow in GLR parser.
+ Problem reported by twlevo@xs4all.nl.
+ * data/glr.c (struct yyGLRStack): Remove yyerrflag member.
+ All uses removed.
+ (yyStackOverflow): Just longjmp, but with value 2 so that caller
+ can handle the problem.
+ (YYCHK1): Use goto (a la yacc.c) rather than setting a flag.
+ (yyparse): New local variable yyresult to record the result.
+ Use result of setjmp to set it, rather than storing itinto
+ struct.
+ (yyDone): Remove label.
+ (yyacceptlab, yyabortlab, yyoverflowlab, yyreturn): New labels,
+ to mimic yacc.c. Do not discard lookahead if it's EOF (possible
+ if YYABORT is used).
+ * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Exit with
+ yyparse status; put status > 1 into diagnostic.
+ Check that status==2 works.
+ * tests/calc.at, tests/cxx-type.at, tests/glr-regression.at:
+ Use exit status 3 for failure to open (which shouldn't happen).
+
2005-07-17 Paul Eggert <eggert@cs.ucla.edu>
* tests/conflicts.at (%nonassoc and eof): Don't exit with status
};
struct yyGLRStack {
- int yyerrflag;
int yyerrState;
]b4_location_if([[ /* To compute the location of the error token. */
yyGLRStackItem yyerror_range[3];]])[
static void
yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yymsg)
{
- yystack->yyerrflag = 1;
if (yymsg != NULL)
yyerror (]b4_yyerror_args[yymsg);
longjmp (yystack->yyexception_buffer, 1);
static void
yyStackOverflow (yyGLRStack* yystack]b4_pure_formals[)
{
- yyFail (yystack]b4_pure_args[, "parser stack overflow");
+ longjmp (yystack->yyexception_buffer, 2);
}
#if YYDEBUG || YYERROR_VERBOSE
static yybool
yyinitGLRStack (yyGLRStack* yystack, size_t yysize)
{
- yystack->yyerrflag = 0;
yystack->yyerrState = 0;
yynerrs = 0;
yystack->yyspaceLeft = yysize;
default: \
break; \
case yyabort: \
- yystack.yyerrflag = 1; \
- goto yyDone; \
+ goto yyabortlab; \
case yyaccept: \
- yystack.yyerrflag = 0; \
- goto yyDone; \
+ goto yyacceptlab; \
case yyerr: \
goto yyuser_error; \
} \
]b4_c_ansi_function_def([yyparse], [int], b4_parse_param)[
{
+ int yyresult;
yySymbol yytoken;
yyGLRStack yystack;
size_t yyposn;
/* Line __line__ of glr.c. */
b4_syncline([@oline@], [@ofile@])])dnl
[
- if (setjmp (yystack.yyexception_buffer) != 0)
- goto yyDone;
if (! yyinitGLRStack (&yystack, YYINITDEPTH))
- yyStackOverflow (&yystack]b4_lpure_args[);
+ goto yyoverflowlab;
+ switch (setjmp (yystack.yyexception_buffer))
+ {
+ case 1: goto yyabortlab;
+ case 2: goto yyoverflowlab;
+ }
yystack.yytokenp = &yytoken;
yyglrShift (&yystack, 0, 0, 0, yylval, &yylloc]b4_user_args[);
yyposn = 0;
yyStateNum yystate = yystack.yytops.yystates[0]->yylrState;
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
if (yystate == YYFINAL)
- goto yyDone;
+ goto yyacceptlab;
if (yyisDefaultedState (yystate))
{
yyrule = yydefaultAction (yystate);
yyrecoverSyntaxError (&yystack, yylvalp, yyllocp]b4_user_args[);
yyposn = yystack.yytops.yystates[0]->yyposn;
}
- yyDone:
- /* On YYABORT, free the lookahead. */
- if (yystack.yyerrflag == 1 && yytoken != YYEMPTY)
+
+ yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+ yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+ yyoverflowlab:
+ yyerror (]b4_lyyerror_args["parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+
+ yyreturn:
+ if (yytoken != YYEOF && yytoken != YYEMPTY)
yydestruct ("Error: discarding lookahead",
yytoken, yylvalp]b4_location_if([, yyllocp])[);
yyfreeGLRStack (&yystack);
- return yystack.yyerrflag;
+ return yyresult;
}
/* DEBUGGING ONLY */
int
main (int argc, const char *argv[])
{
+ int status;
yydebug = !!getenv ("YYDEBUG");
assert (argc == 2);
yysource = argv[1];
- if (yyparse ())
+ status = yyparse ();
+ switch (status)
{
- printf ("Parsing FAILED.\n");
- exit (1);
+ case 0: printf ("Successful parse.\n"); break;
+ case 1: printf ("Parsing FAILED.\n"); break;
+ default: printf ("Parsing FAILED (status %d).\n", status); break;
}
- printf ("Successful parse.\n");
- return 0;
+ return status;
}
]])
# Upon stack overflow, all symbols on the stack should be destroyed.
# Only check for yacc.c.
AT_YACC_IF([
-AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 1,
+AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2,
[[sending: '(' (0@0-9)
sending: 'x' (1@10-19)
thing (1@10-19): 'x' (1@10-19)
Freeing nterm line (6@60-89)
Freeing nterm line (3@30-59)
Freeing nterm line (0@0-29)
-Parsing FAILED.
+Parsing FAILED (status 2).
]])
])
{
int res = 1;
if (exponent < 0)
- exit (1);
+ exit (3);
for (/* Niente */; exponent; --exponent)
res *= base;
return res;
if (!yyin)
{
perror (argv[1]);
- exit (1);
+ return 3;
}
]AT_LALR1_CC_IF([], [m4_bmatch([$4], [%debug],
if (argc != 2)
abort ();
if (!freopen (argv[1], "r", stdin))
- abort ();
- exit (yyparse ());
+ return 3;
+ return yyparse ();
}
int
main (int argc, char **argv)
{
yyin = stdin;
- if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1;
+ if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3;
return yyparse ();
}
]])
int main(int argc, char* argv[]) {
yyin = stdin;
- if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 1;
+ if (argc == 2 && !(yyin = fopen (argv[1], "r"))) return 3;
return yyparse ();
}
]])