From: Akim Demaille Date: Wed, 10 Oct 2012 15:31:25 +0000 (+0200) Subject: Merge branch 'maint' X-Git-Tag: v2.7.90~302 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/23d13411c85d3a8705f9507219f61eddea57a218?hp=2b45240d6c1b9177533aa5d83ac1c879198111c5 Merge branch 'maint' * origin/maint: NEWS: warnings with clang warnings: avoid warnings from clang tests: no longer disable -O compiler options yacc.c: initialize yylval in pure-parser mode skeletons: style changes lalr1.cc: document exception safety lalr1.cc: check exception safety of error handling lalr1.cc: check (and fix) %printer exception safety lalr1.cc: check (and fix) %initial-action exception safety lalr1.cc: fix exception safety lalr1.cc: check exception safety. lalr1.cc: indentation fixes. lalr1.cc: don't leave macros define to nothing tests: minor improvements tests: use $PERL instead of perl build: look for Perl in configure. tests: fix sed portability issues tests: diff -u is not portable Conflicts: data/c.m4 data/glr.c data/lalr1.cc data/yacc.c doc/Makefile.am tests/atlocal.in tests/calc.at --- diff --git a/NEWS b/NEWS index fd1cadd4..eaa0a3de 100644 --- a/NEWS +++ b/NEWS @@ -240,7 +240,7 @@ GNU Bison NEWS ** 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. @@ -275,6 +275,32 @@ GNU Bison NEWS 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 diff --git a/THANKS b/THANKS index b83ec0e5..4fbbbb0b 100644 --- a/THANKS +++ b/THANKS @@ -81,6 +81,7 @@ Nicolas Tisserand nicolas.tisserand@epita.fr 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 diff --git a/data/c.m4 b/data/c.m4 index 3bc2c215..179743c9 100644 --- a/data/c.m4 +++ b/data/c.m4 @@ -202,7 +202,7 @@ m4_define([b4_table_value_equals], [m4_if(m4_eval($3 < m4_indir([b4_]$1[_min]) || m4_indir([b4_]$1[_max]) < $3), [1], [[0]], - [[((]$2[) == (]$3[))]])]) + [(!!(($2) == ($3)))])]) ## ---------## diff --git a/data/glr.c b/data/glr.c index 46eaccc7..e2363a20 100644 --- a/data/glr.c +++ b/data/glr.c @@ -250,19 +250,19 @@ b4_percent_code_get[]dnl # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* 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 @@ -288,8 +288,9 @@ b4_percent_code_get[]dnl #ifndef YYSETJMP # include # 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 /*-----------------. @@ -312,7 +313,7 @@ b4_percent_code_get[]dnl #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. */ @@ -406,7 +407,7 @@ dnl We probably ought to introduce a type for confl. { ]b4_conflicting_rules[ }; - + /* Error token number */ #define YYTERROR 1 @@ -913,8 +914,8 @@ yylhsNonterm (yyRuleNum yyrule) 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). */ @@ -931,8 +932,8 @@ yydefaultAction (yyStateNum yystate) 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 diff --git a/data/lalr1.cc b/data/lalr1.cc index 75eaf571..13f33d1e 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -683,6 +683,10 @@ m4_if(b4_prefix, [yy], [], /// 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], [ @@ -955,7 +959,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ /* 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_ (); @@ -963,6 +967,23 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ 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) diff --git a/data/yacc.c b/data/yacc.c index 44f96dda..a1d45c43 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -172,6 +172,28 @@ m4_define([b4_declare_scanner_communication_variables], [[ /* 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([[ @@ -397,19 +419,19 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* 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]])[ @@ -602,13 +624,13 @@ static const ]b4_int_type_for([b4_toknum])[ yytoknum[] = #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[ @@ -1454,8 +1476,9 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[ 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[; @@ -1641,7 +1664,9 @@ yyread_pushed_token:]])[ 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; @@ -1861,7 +1886,9 @@ yyerrlab1: 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 diff --git a/doc/bison.texi b/doc/bison.texi index 4ab00c65..5b233a48 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -4783,6 +4783,10 @@ incoming terminals during the second phase of error recovery, 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 @@ -9888,6 +9892,11 @@ Instantiate a syntax-error exception. @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 () diff --git a/src/uniqstr.h b/src/uniqstr.h index 913da39f..677ecc42 100644 --- a/src/uniqstr.h +++ b/src/uniqstr.h @@ -36,7 +36,7 @@ uniqstr uniqstr_vsprintf (char const *format, ...) __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. */ diff --git a/tests/atlocal.in b/tests/atlocal.in index 8adb3933..e350d137 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -29,16 +29,10 @@ CPPFLAGS="-I$abs_top_builddir/lib @CPPFLAGS@" # 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@" @@ -51,7 +45,6 @@ BISON_CXX_WORKS='@BISON_CXX_WORKS@' 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 @@ -63,21 +56,12 @@ fi ## 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@'} @@ -86,6 +70,15 @@ CONF_JAVA='@CONF_JAVA@' 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 diff --git a/tests/c++.at b/tests/c++.at index 288ff865..0d491709 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -1,4 +1,4 @@ -# Checking the output filenames. -*- Autotest -*- +# Checking the C++ Features. -*- Autotest -*- # Copyright (C) 2004-2005, 2007-2012 Free Software Foundation, Inc. @@ -216,6 +216,7 @@ m4_define([AT_CHECK_DOXYGEN], [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 @@ -224,10 +225,7 @@ AT_DATA([input.yy], %% 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) @@ -280,6 +278,7 @@ EXTRACT_STATIC = AT_DOXYGEN_PRIVATE AT_CHECK([doxygen --version || exit 77], 0, ignore) AT_CHECK([doxygen], 0, [], [ignore]) +AT_BISON_OPTION_POPDEFS AT_CLEANUP m4_popdef([AT_DOXYGEN_PRIVATE]) @@ -531,3 +530,236 @@ caught error ]]) 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 + #include // size_t and getenv. + #include + #include + + bool debug = false; + + /// A class that counts its number of instances. + struct Object + { + typedef std::list 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 + #include // strchr + #include + 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 $$; } ; +%printer +{ + yyo << $$ << " '" << $$->val << '\''; + if ($$->val == 'p') + throw std::runtime_error ("printer"); +} ; + +%token 'a' 'E' 'e' 'p' 'R' 's' 'T' +%type 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 diff --git a/tests/calc.at b/tests/calc.at index f785d6f0..1a481cf1 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -503,14 +503,17 @@ AT_CHECK([cat stderr], 0, [expout]) # 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 ]) diff --git a/tests/existing.at b/tests/existing.at index d5cb39d1..20dbde82 100644 --- a/tests/existing.at +++ b/tests/existing.at @@ -35,7 +35,10 @@ dnl time comes, just use sed to drop the line numbers. For now, as LR(1) 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/^ $//']], diff --git a/tests/input.at b/tests/input.at index 30107218..736ee252 100644 --- a/tests/input.at +++ b/tests/input.at @@ -1321,7 +1321,7 @@ AT_DATA([empty.y], 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] @@ -1336,7 +1336,7 @@ AT_DATA([two.y], 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] @@ -1351,7 +1351,7 @@ AT_DATA([three.y], 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] @@ -1380,7 +1380,7 @@ start: '\777' '\0' '\xfff' '\x0' # 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], [], diff --git a/tests/local.at b/tests/local.at index 4499e13f..f9babdfa 100644 --- a/tests/local.at +++ b/tests/local.at @@ -38,7 +38,7 @@ m4_define([m4_null_if], # 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 @@ -408,7 +408,8 @@ void public void yyerror (String s) { System.err.println (s); -}]])])dnl + }]])], +[m4_fatal([$0: invalid language: ]AT_LANG)])dnl ]) diff --git a/tests/regression.at b/tests/regression.at index 2fb180e9..8a285af1 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -1474,17 +1474,17 @@ AT_CHECK([[grep 'syntax error,' stderr.txt]], [[0]], # 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 diff --git a/tests/skeletons.at b/tests/skeletons.at index ce079d62..dafc74da 100644 --- a/tests/skeletons.at +++ b/tests/skeletons.at @@ -315,7 +315,7 @@ print '@output(@,@)', "\n"; (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" diff --git a/tests/synclines.at b/tests/synclines.at index e2b7005d..041ae194 100644 --- a/tests/synclines.at +++ b/tests/synclines.at @@ -64,7 +64,7 @@ m4_define([AT_SYNCLINES_COMPILE], # 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; diff --git a/tests/torture.at b/tests/torture.at index 705e131e..a5e244b6 100644 --- a/tests/torture.at +++ b/tests/torture.at @@ -125,7 +125,7 @@ EOF ]]) 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 ]) @@ -214,7 +214,7 @@ main (void) 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 ]) @@ -350,7 +350,7 @@ main (void) 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 ])