bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FYI: merge maint into master


From: Akim Demaille
Subject: FYI: merge maint into master
Date: Thu, 11 Oct 2012 09:23:55 +0200

commit 23d13411c85d3a8705f9507219f61eddea57a218
Merge: 2b45240 c12c4c5
Author: Akim Demaille <address@hidden>
Date:   Wed Oct 10 17:31:25 2012 +0200

    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 fd1cadd..eaa0a3d 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 b83ec0e..4fbbbb0 100644
--- a/THANKS
+++ b/THANKS
@@ -81,6 +81,7 @@ Nicolas Tisserand         address@hidden
 Noah Friedman             address@hidden
 Odd Arild Olsen           address@hidden
 Oleg Smolsky              address@hidden
+Oleksii Taran             address@hidden
 Paolo Bonzini             address@hidden
 Pascal Bart               address@hidden
 Paul Eggert               address@hidden
diff --git a/data/c.m4 b/data/c.m4
index 3bc2c21..179743c 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 46eaccc..e2363a2 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 <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
@@ -288,8 +288,9 @@ b4_percent_code_get[]dnl
 #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
 
 /*-----------------.
@@ -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 75eaf57..13f33d1 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 44f96dd..a1d45c4 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 <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]])[
@@ -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 4ab00c6..5b233a4 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
address@hidden,
address@hidden
 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.
+
address@hidden 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 913da39..677ecc4 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 8adb393..e350d13 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 288ff86..0d49170 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 <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
diff --git a/tests/calc.at b/tests/calc.at
index f785d6f..1a481cf 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 d5cb39d..20dbde8 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 3010721..736ee25 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 4499e13..f9babdf 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 2fb180e..8a285af 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 ce079d6..dafc74d 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 e2b7005..041ae19 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 705e131..a5e244b 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
 ])




reply via email to

[Prev in Thread] Current Thread [Next in Thread]