** Bug fixes
- Bugs in the test suite have been fixed.
+ Bugs and portability issues in the test suite have been fixed.
Some errors in translations have been addressed, and --help now directs
users to the appropriate place to report them.
will use YY_CALC_LIB_PARSE_H_INCLUDED as guard.
+** Exception safety (lalr1.cc)
+
+ The parse function now catches exceptions, uses the %destructors to
+ release memory (the lookahead symbol and the symbols pushed on the stack)
+ before rethrowing the exception.
+
+ This feature is somewhat experimental. User feedback would be
+ appreciated.
+
+** Fix compiler warnings in the generated parser (yacc.c, glr.c)
+
+ The compilation of pure parsers (%define api.pure) can trigger GCC
+ warnings such as:
+
+ input.c: In function 'yyparse':
+ input.c:1503:12: warning: 'yylval' may be used uninitialized in this
+ function [-Wmaybe-uninitialized]
+ *++yyvsp = yylval;
+ ^
+
+ This is now fixed; pragmas to avoid these warnings are no longer needed.
+
+ Warnings from clang ("equality comparison with extraneous parentheses" and
+ "function declared 'noreturn' should not return") have also been
+ addressed.
+
* Noteworthy changes in release 2.6.2 (2012-08-03) [stable]
** Bug fixes
Noah Friedman friedman@gnu.org
Odd Arild Olsen oao@fibula.no
Oleg Smolsky oleg.smolsky@pacific-simulators.co.nz
+Oleksii Taran oleksii.taran@gmail.com
Paolo Bonzini bonzini@gnu.org
Pascal Bart pascal.bart@epita.fr
Paul Eggert eggert@cs.ucla.edu
[m4_if(m4_eval($3 < m4_indir([b4_]$1[_min])
|| m4_indir([b4_]$1[_max]) < $3), [1],
[[0]],
- [[((]$2[) == (]$3[))]])])
+ [(!!(($2) == ($3)))])])
## ---------##
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#ifdef __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
#ifndef YYFREE
#ifndef YYSETJMP
# include <setjmp.h>
# define YYJMP_BUF jmp_buf
-# define YYSETJMP(env) setjmp (env)
-# define YYLONGJMP(env, val) longjmp (env, val)
+# define YYSETJMP(Env) setjmp (Env)
+// Pacify clang.
+# define YYLONGJMP(Env, Val) (longjmp (Env, Val), YYASSERT (0))
#endif
/*-----------------.
#endif])[
#ifndef YYASSERT
-# define YYASSERT(condition) ((void) ((condition) || (abort (), 0)))
+# define YYASSERT(Condition) ((void) ((Condition) || (abort (), 0)))
#endif
/* YYFINAL -- State number of the termination state. */
{
]b4_conflicting_rules[
};
-\f
+
/* Error token number */
#define YYTERROR 1
return yyr1[yyrule];
}
-#define yypact_value_is_default(yystate) \
- ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
+#define yypact_value_is_default(Yystate) \
+ ]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[
/** True iff LR state YYSTATE has only a default reduction (regardless
* of token). */
return yydefact[yystate];
}
-#define yytable_value_is_error(yytable_value) \
- ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
+#define yytable_value_is_error(Yytable_value) \
+ ]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[
/** Set *YYACTION to the action to take in YYSTATE on seeing YYTOKEN.
* Result R means
/// The return value of parse ().
int yyresult;
+ // FIXME: This shoud be completely indented. It is not yet to
+ // avoid gratuitous conflicts when merging into the master branch.
+ try
+ {
YYCDEBUG << "Starting parse" << std::endl;
]m4_ifdef([b4_initial_action], [
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
yypop_ (yylen);
- while (yystack_.size () != 1)
+ while (1 < yystack_.size ())
{
yy_destroy_ ("Cleanup: popping", yystack_[0]);
yypop_ ();
return yyresult;
}
+ catch (...)
+ {
+ YYCDEBUG << "Exception caught: cleaning lookahead and stack"
+ << std::endl;
+ // Do not try to display the values of the reclaimed symbols,
+ // as their printer might throw an exception.
+ if (!yyempty)
+ yy_destroy_ (YY_NULL, yyla);
+
+ while (1 < yystack_.size ())
+ {
+ yy_destroy_ (YY_NULL, yystack_[0]);
+ yypop_ ();
+ }
+ throw;
+ }
+ }
void
]b4_parser_class_name[::error (const syntax_error& yyexc)
/* The lookahead symbol. */
int yychar;
+]b4_pure_if([[
+#if defined __GNUC__ && (4 < __GNUC__ + (6 <= __GNUC_MINOR__))
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+static YYSTYPE yyval_default;
+# define YYLVAL_INITIALIZE() (yylval = yyval_default)
+#endif]])[
+#ifndef YYLVAL_INITIALIZE
+# define YYLVAL_INITIALIZE()
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;]b4_locations_if([[
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#ifdef __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
#if ]b4_lac_if([[1]], [[! defined yyoverflow || YYERROR_VERBOSE]])[
#define YYPACT_NINF ]b4_pact_ninf[
-#define yypact_value_is_default(yystate) \
- ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
+#define yypact_value_is_default(Yystate) \
+ ]b4_table_value_equals([[pact]], [[Yystate]], [b4_pact_ninf])[
#define YYTABLE_NINF ]b4_table_ninf[
-#define yytable_value_is_error(yytable_value) \
- ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
+#define yytable_value_is_error(Yytable_value) \
+ ]b4_table_value_equals([[table]], [[Yytable_value]], [b4_table_ninf])[
]b4_parser_tables_define[
The wasted elements are never initialized. */
yyssp = yyss;
yyvsp = yyvs;]b4_locations_if([[
- yylsp = yyls;
+ yylsp = yyls;]])[
+ YYLVAL_INITIALIZE ();]b4_locations_if([[
#if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
/* Initialize the default location before parsing starts. */
yylloc.first_line = yylloc.last_line = ]b4_location_initial_line[;
YY_LAC_DISCARD ("shift");]])[
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
]b4_locations_if([ *++yylsp = yylloc;])[
goto yynewstate;
current lookahead token, the shift below will for sure. */
YY_LAC_DISCARD ("error recovery");]])[
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
]b4_locations_if([[
yyerror_range[2] = yylloc;
/* Using YYLLOC is tempting, but would change the location of
the current lookahead and the entire stack (except the current
right-hand side symbols) when the parser returns immediately, and
@item
+the current lookahead and the entire stack (including the current right-hand
+side symbols) when the C++ parser (@file{lalr1.cc}) catches an exception in
+@code{parse},
+@item
the start symbol, when the parser succeeds.
@end itemize
@deftypemethod {parser} {int} parse ()
Run the syntactic analysis, and return 0 on success, 1 otherwise.
+
+@cindex exceptions
+The whole function is wrapped in a @code{try}/@code{catch} block, so that
+when an exception is thrown, the @code{%destructor}s are called to release
+the lookahead symbol, and the symbols pushed on the stack.
@end deftypemethod
@deftypemethod {parser} {std::ostream&} debug_stream ()
__attribute__ ((__format__ (__printf__, 1, 2)));
/* Two uniqstr values have the same value iff they are the same. */
-#define UNIQSTR_EQ(USTR1, USTR2) ((USTR1) == (USTR2))
+#define UNIQSTR_EQ(USTR1, USTR2) (!!((USTR1) == (USTR2)))
/* Compare two uniqstr a la strcmp: negative for <, nul for =, and
positive for >. Undefined order, relies on addresses. */
# Is the compiler GCC?
GCC='@GCC@'
-# We want no optimization, as they uncover warnings (therefore,
-# failures) about uninitialized variables in the test suite. FIXME:
-# fix the warnings, not the flags.
- O0CFLAGS=`echo '@CFLAGS@' | sed 's/-O[0-9s] *//g'`
-O0CXXFLAGS=`echo '@CXXFLAGS@' | sed 's/-O[0-9s] *//g'`
-
# Sometimes a test group needs to ignore gcc warnings, so it locally
# sets CFLAGS to this.
- NO_WERROR_CFLAGS="$O0CFLAGS @WARN_CFLAGS@ @WARN_CFLAGS_TEST@"
-NO_WERROR_CXXFLAGS="$O0CXXFLAGS @WARN_CXXFLAGS@ @WARN_CXXFLAGS_TEST@"
+ NO_WERROR_CFLAGS='@CFLAGS@ @WARN_CFLAGS@ @WARN_CFLAGS_TEST@'
+NO_WERROR_CXXFLAGS='@CXXFLAGS@ @WARN_CXXFLAGS@ @WARN_CXXFLAGS_TEST@'
# But most of the time, we want -Werror.
CFLAGS="$NO_WERROR_CFLAGS @WERROR_CFLAGS@"
if "$at_arg_compile_c_with_cxx"; then
CC_IS_CXX=1
CC=$CXX
- O0CFLAGS=$O0CXXFLAGS
NO_WERROR_CFLAGS=$NO_WERROR_CXXFLAGS
CFLAGS=$CXXFLAGS
else
## Other. ##
## ------- ##
-# Are special link options needed?
-LDFLAGS='@LDFLAGS@'
-
-# Are special libraries needed?
-LIBS="$abs_top_builddir/lib/libbison.a @LIBS@ @INTLLIBS@"
-
# Empty if no javac was found
CONF_JAVAC='@CONF_JAVAC@'
# Empty if no Java VM was found
CONF_JAVA='@CONF_JAVA@'
-# Empty if no xsltproc was found
-: ${XSLTPROC='@XSLTPROC@'}
-
# We need egrep and perl.
: ${EGREP='@EGREP@'}
: ${PERL='@PERL@'}
LC_CTYPE=C
export LC_CTYPE
+# Are special link options needed?
+LDFLAGS='@LDFLAGS@'
+
+# Are special libraries needed?
+LIBS="$abs_top_builddir/lib/libbison.a @LIBS@ @INTLLIBS@"
+
+# Empty if no xsltproc was found
+: ${XSLTPROC='@XSLTPROC@'}
+
# Handle --compile-c-with-cxx here, once CXX and CXXFLAGS are known.
if "$at_arg_compile_c_with_cxx"; then
-# Checking the output filenames. -*- Autotest -*-
+# Checking the C++ Features. -*- Autotest -*-
# Copyright (C) 2004-2005, 2007-2012 Free Software Foundation, Inc.
[m4_fatal([invalid argument: $1])])
AT_SETUP([Doxygen $1 Documentation])
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
AT_DATA([input.yy],
[[%skeleton "lalr1.cc"
%locations
%%
exp:;
%%
-yy::parser::error (const location& l, const std::string& m)
-{
- std::cerr << l << s << std::endl;
-}
+]AT_YYERROR_DEFINE[
]])
AT_BISON_CHECK([-o input.cc input.yy], 0)
AT_CHECK([doxygen --version || exit 77], 0, ignore)
AT_CHECK([doxygen], 0, [], [ignore])
+AT_BISON_OPTION_POPDEFS
AT_CLEANUP
m4_popdef([AT_DOXYGEN_PRIVATE])
]])
AT_CLEANUP
+
+
+## ------------------ ##
+## Exception safety. ##
+## ------------------ ##
+
+AT_SETUP([[Exception safety]])
+
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+
+AT_DATA_GRAMMAR([[input.yy]],
+[[%skeleton "lalr1.cc"
+%defines // FIXME: Mandated in 2.6.
+%debug
+%error-verbose
+
+%code requires
+{
+ #include <cassert>
+ #include <cstdlib> // size_t and getenv.
+ #include <iostream>
+ #include <list>
+
+ bool debug = false;
+
+ /// A class that counts its number of instances.
+ struct Object
+ {
+ typedef std::list<const Object*> objects;
+ static objects instances;
+ char val;
+
+ static bool
+ empty ()
+ {
+ return instances.empty();
+ }
+
+ static void
+ log (Object const *o, const std::string& msg)
+ {
+ if (debug)
+ {
+ if (o)
+ std::cerr << o << "->";
+ std::cerr << msg << " {";
+ const char* sep = " ";
+ for (objects::const_iterator i = instances.begin(),
+ i_end = instances.end();
+ i != i_end;
+ ++i)
+ {
+ std::cerr << sep << *i;
+ sep = ", ";
+ }
+ std::cerr << " }" << std::endl;
+ }
+ }
+
+ Object (char v)
+ : val (v)
+ {
+ instances.push_back(this);
+ log (this, "Object::Object");
+ }
+
+ ~Object ()
+ {
+ instances.remove(this);
+ log (this, "Object::~Object");
+ }
+ };
+}
+
+%code
+{
+ #include <cassert>
+ #include <cstring> // strchr
+ #include <stdexcept>
+ int yylex (yy::parser::semantic_type *);
+ Object::objects Object::instances;
+ static char const *input;
+}
+
+%union
+{
+ Object *obj;
+}
+
+%initial-action
+{
+ if (strchr (input, 'i'))
+ throw std::runtime_error ("initial-action");
+}
+
+%destructor { delete $$; } <obj>;
+%printer
+{
+ yyo << $$ << " '" << $$->val << '\'';
+ if ($$->val == 'p')
+ throw std::runtime_error ("printer");
+} <obj>;
+
+%token <obj> 'a' 'E' 'e' 'p' 'R' 's' 'T'
+%type <obj> list item
+
+%%
+
+start: list { delete $1; };
+
+list:
+ item { $$ = $1; }
+| item list { $$ = $1; delete $2; } // Right recursion to load the stack.
+;
+
+item:
+ 'a' { $$ = $1; }
+| 'e' { YYUSE ($$); YYUSE($1); error ("syntax error"); }
+// Not just 'E', otherwise we reduce when 'E' is the lookahead, and
+// then the stack is emptied, defeating the point of the test.
+| 'E' 'a' { YYUSE($1); $$ = $2; }
+| 'R' { $$ = YY_NULL; delete $1; YYERROR; }
+| 'p' { $$ = $1; }
+| 's' { $$ = $1; throw std::runtime_error ("reduction"); }
+| 'T' { $$ = YY_NULL; delete $1; YYABORT; }
+| error { $$ = YY_NULL; yyerrok; }
+;
+%%
+
+int
+yylex (yy::parser::semantic_type *lvalp)
+{
+ // 'a': no error.
+ // 'e': user action calls error.
+ // 'E': syntax error, with yyerror that throws.
+ // 'i': initial action throws.
+ // 'l': yylex throws.
+ // 'R': call YYERROR in the action
+ // 's': reduction throws.
+ // 'T': call YYABORT in the action
+ switch (int res = *input++)
+ {
+ case 'l':
+ throw std::runtime_error ("yylex");
+ default:
+ lvalp->obj = new Object (res);
+ // Fall through.
+ case 0:
+ return res;
+ }
+}
+
+/* A C++ error reporting function. */
+void
+yy::parser::error (const std::string& m)
+{
+ throw std::runtime_error (m);
+}
+
+int
+main (int argc, const char *argv[])
+{
+ switch (argc)
+ {
+ case 2:
+ input = argv[1];
+ break;
+ case 3:
+ assert (!strcmp (argv[1], "--debug"));
+ debug = 1;
+ input = argv[2];
+ break;
+ default:
+ abort ();
+ }
+
+ yy::parser parser;
+ debug |= !!getenv ("YYDEBUG");
+ parser.set_debug_level (debug);
+ int res = 2;
+ try
+ {
+ res = parser.parse ();
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "exception caught: " << e.what () << std::endl;
+ }
+ catch (...)
+ {
+ std::cerr << "unknown exception caught" << std::endl;
+ }
+ Object::log (YY_NULL, "end");
+ assert (Object::empty());
+ return res;
+}
+]])
+AT_BISON_CHECK([[-o input.cc --report=all input.yy]])
+AT_COMPILE_CXX([[input]])
+
+AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]],
+[[exception caught: reduction
+]])
+
+AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]],
+[[exception caught: yylex
+]])
+
+AT_PARSER_CHECK([[./input i]], [[2]], [[]],
+[[exception caught: initial-action
+]])
+
+AT_PARSER_CHECK([[./input aaaap]])
+
+AT_PARSER_CHECK([[./input --debug aaaap]], [[2]], [[]], [[stderr]])
+AT_PARSER_CHECK([[grep '^exception caught: printer$' stderr]], [], [ignore])
+
+AT_PARSER_CHECK([[./input aaaae]], [[2]], [[]],
+[[exception caught: syntax error
+]])
+
+AT_PARSER_CHECK([[./input aaaaE]], [[2]], [[]],
+[[exception caught: syntax error, unexpected $end, expecting 'a'
+]])
+
+AT_PARSER_CHECK([[./input aaaaT]], [[1]])
+
+# There is error-recovery, so exit success.
+AT_PARSER_CHECK([[./input aaaaR]], [[0]])
+
+AT_BISON_OPTION_POPDEFS
+
+AT_CLEANUP
# Make sure we did not introduce bad spaces. Checked here because all
# the skeletons are (or should be) exercized here.
m4_define([AT_CHECK_SPACES],
-[# No initial empty lines.
-AT_CHECK([sed -ne '/./q;=;p;' $1])
-# No trailing spaces.
-AT_CHECK([sed -ne '/[ ]$/{=;p;}' $1])
-# No tabulations.
-AT_CHECK([sed -ne '/[ ]/{=;p;}' $1])
-# No final empty lines.
-AT_CHECK([sed -ne '${/^$/{=;p;};}' $1])
+[AT_CHECK([$PERL -ne '
+ chomp;
+ print "$.: {$_}\n"
+ if (# No starting/ending empty lines.
+ (eof || $. == 1) && /^\s*$/
+ # No trailing space.
+ || /\s$/
+ # No tabs.
+ || /\t/
+ )' $1
+])dnl
])
dnl support is rapidly evolving, let's keep that information to be careful.
dnl However, we don't do diffs for canonical LR(1) because the diff is huge.
m4_pushdef([AT_LALR1_DIFF_CHECK],
-[AT_CHECK([[sed 's/^%define lr.type .*$//' input.y > input-lalr.y]])
+[dnl We need diff -u, which is not portable.
+AT_CHECK([diff -u /dev/null /dev/null || exit 77], [0], [ignore])
+
+AT_CHECK([[sed 's/^%define lr.type .*$//' input.y > input-lalr.y]])
AT_BISON_CHECK([[--report=all input-lalr.y]], [[0]], [ignore], [ignore])
AT_CHECK([[diff -u input-lalr.output input.output \
| sed -n '/^@@/,$p' | sed 's/^ $//']],
start: '';
start: '
]])
-AT_CHECK([[perl -e "print 'start: \'';" >> empty.y || exit 77]])
+AT_CHECK([[$PERL -e "print 'start: \'';" >> empty.y || exit 77]])
AT_BISON_CHECK([empty.y], [1], [],
[[empty.y:2.8-9: warning: empty character literal [-Wother]
start: 'ab';
start: 'ab
]])
-AT_CHECK([[perl -e "print 'start: \'ab';" >> two.y || exit 77]])
+AT_CHECK([[$PERL -e "print 'start: \'ab';" >> two.y || exit 77]])
AT_BISON_CHECK([two.y], [1], [],
[[two.y:2.8-11: warning: extra characters in character literal [-Wother]
start: 'abc';
start: 'abc
]])
-AT_CHECK([[perl -e "print 'start: \'abc';" >> three.y || exit 77]])
+AT_CHECK([[$PERL -e "print 'start: \'abc';" >> three.y || exit 77]])
AT_BISON_CHECK([three.y], [1], [],
[[three.y:2.8-12: warning: extra characters in character literal [-Wother]
# Beside we cannot even expect "echo '\0'" to output two characters
# (well three with \n): at least Bash 3.2 converts the two-character
# sequence "\0" into a single NUL character.
-AT_CHECK([[perl -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
+AT_CHECK([[$PERL -e 'print "start: \"\\\t\\\f\\\0\\\1\" ;";' >> input.y \
|| exit 77]])
AT_BISON_CHECK([input.y], [1], [],
# Expect COUNT matches of the PERL-REGEXP in FILE. The file is
# taken in "slurp" mode, i.e., one can match end-of-lines.
m4_define([AT_MATCHES_CHECK],
-[AT_CHECK([perl -0777 -ne '
+[AT_CHECK([$PERL -0777 -ne '
my $count = 0;
s{$2}{ ++$count; "" }gem;
printf "$count\n";' $1], [0], [$3
public void yyerror (String s)
{
System.err.println (s);
-}]])])dnl
+ }]])],
+[m4_fatal([$0: invalid language: ]AT_LANG)])dnl
])
# Check number of default reductions in inconsistent states to be sure
# syntax error is detected before unnecessary reductions are performed.
-AT_CHECK([[perl -0777 -ne 'print s/inconsistent default reduction//g;' \
+AT_CHECK([[$PERL -0777 -ne 'print s/inconsistent default reduction//g;' \
< stdout.txt || exit 77]], [[0]], [[14]])
# Check number of default reductions in consistent states to be sure
# it is performed before the syntax error is detected.
-AT_CHECK([[perl -0777 -ne 'print s/\bconsistent default reduction//g;' \
+AT_CHECK([[$PERL -0777 -ne 'print s/\bconsistent default reduction//g;' \
< stdout.txt || exit 77]], [[0]], [[2]])
# Check number of reallocs to be sure reallocated memory isn't somehow
# lost between LAC invocations.
-AT_CHECK([[perl -0777 -ne 'print s/\(realloc//g;' < stderr.txt \
+AT_CHECK([[$PERL -0777 -ne 'print s/\(realloc//g;' < stderr.txt \
|| exit 77]], [[0]], [[3]])
AT_BISON_OPTION_POPDEFS
(print "garbage"x10, "\n") for (1..1000);
print "${M4}_divert_pop(0)\n";
]])
-AT_CHECK([[perl gen-skel.pl > skel.c || exit 77]])
+AT_CHECK([[$PERL gen-skel.pl > skel.c || exit 77]])
AT_DATA([[input.y]],
[[%skeleton "./skel.c"
# distcc[35882] (dcc_connect_by_name) ERROR: failed to look up host "chrisimac": Unknown host
# distcc[35882] Warning: failed to distribute input.c to chrisimac/4, running locally instead
-AT_CHECK([[perl -p -0777 - stderr <<\EOF
+AT_CHECK([[$PERL -p -0777 - stderr <<\EOF
s/^distcc\[\d+\] .*\n//gm;
s/^([^:]+:\d+)[.:][^:]+:(.+)$/$][1:$][2/gm;
s/^([^:]+:\d+):[^#]*( #error)/$][1:$][2/gm;
]])
AT_BISON_OPTION_POPDEFS
-AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
+AT_CHECK([$PERL -w ./gengram.pl $2 || exit 77], 0, [stdout])
mv stdout $1
])
EOF
]])
-AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
+AT_CHECK([$PERL -w ./gengram.pl $2 || exit 77], 0, [stdout])
mv stdout $1
AT_BISON_OPTION_POPDEFS
])
EOF
]])
-AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout])
+AT_CHECK([$PERL -w ./gengram.pl $2 || exit 77], 0, [stdout])
mv stdout $1
AT_BISON_OPTION_POPDEFS
])