]> git.saurik.com Git - bison.git/commitdiff
Merge branch 'maint'
authorAkim Demaille <akim@lrde.epita.fr>
Wed, 10 Oct 2012 15:31:25 +0000 (17:31 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Thu, 11 Oct 2012 07:12:43 +0000 (09:12 +0200)
* 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

18 files changed:
NEWS
THANKS
data/c.m4
data/glr.c
data/lalr1.cc
data/yacc.c
doc/bison.texi
src/uniqstr.h
tests/atlocal.in
tests/c++.at
tests/calc.at
tests/existing.at
tests/input.at
tests/local.at
tests/regression.at
tests/skeletons.at
tests/synclines.at
tests/torture.at

diff --git a/NEWS b/NEWS
index fd1cadd4c4dc7dcf16cedc28137e1b4748485af5..eaa0a3de8040e56b504d291599f708dc67f6ccb4 100644 (file)
--- 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 b83ec0e5ee05409f15ca5d2f2106d26ff29a02cc..4fbbbb0b81db32278318587766dfabeeef94dd6e 100644 (file)
--- 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
index 3bc2c215df60c5373cc8bab1a5b039cb26af1f0e..179743c9f012e674d42bc11c64d822c02831cda8 100644 (file)
--- 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)))])])
 
 
 ## ---------##
index 46eaccc7c938d22de490e204f5eaa1fc3a27913b..e2363a2083bf184202dfc53ad1737eced8d11e23 100644 (file)
@@ -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[
 };
-\f
+
 /* 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
index 75eaf571e6c82afaa021c4245ac3b7fdcfa3d0e5..13f33d1e45038a9f2bca53bb1036c137fc89abca 100644 (file)
@@ -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)
index 44f96dda374ee4f0cf1a877efa88cbba8b28d83d..a1d45c43a7b93f0bf170968a392151106469b416 100644 (file)
@@ -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
index 4ab00c6545db048c0123401265463968881ca102..5b233a48a45fb1e9c39f3bf4a78b7f88b57f69ad 100644 (file)
@@ -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 ()
index 913da39f690caa0a09f438eb433cd1c658749e44..677ecc42968f8142a2f5d4ba38a5839593882eee 100644 (file)
@@ -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.  */
index 8adb3933f7347e708f17f5c0fdda29479f238a37..e350d137b23905cb445e4db3653c2028ca8034a9 100644 (file)
@@ -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
index 288ff8651e8b7761643ea9832457bc424493de67..0d49170921b0c66c041a14872802b9949f6e6cff 100644 (file)
@@ -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
index f785d6f07f2821a865fd452d4892b0662001cca2..1a481cf18bbf4be019fc642c25cc665267057c84 100644 (file)
@@ -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
 ])
 
 
index d5cb39d16c0bd189d6a1a866a7956c166b8087ee..20dbde82a1a788ac91e89e3880afa6ab9698d105 100644 (file)
@@ -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/^ $//']],
index 301072184e3b917ac57327c29df242ff20cc7569..736ee2524fb0f07e611d90fe4162b7837573b85c 100644 (file)
@@ -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], [],
index 4499e13f41dee5c3428180fb4075a4e5aee4c488..f9babdfa2afecdd748353d3b6518f3240825545f 100644 (file)
@@ -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
 ])
 
 
index 2fb180e90678c72614a0117c0c76240e9923f925..8a285af177776f9967b1e2fbc57df634e672fb62 100644 (file)
@@ -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
index ce079d62924fa369d0c27dc69e7c3741145a7d08..dafc74dab987bf2211d113b5d0639ff2616539df 100644 (file)
@@ -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"
index e2b7005d95fae1a41225aad41eae626d175854cb..041ae194bf00d363fac19c1ee75838a7f7217294 100644 (file)
@@ -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;
index 705e131efe39bb92aacfb5cd8026bf9640dc1ef8..a5e244b65086990b0e6884ff54005d2c95bc71ac 100644 (file)
@@ -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
 ])