Subject: [PATCH] {yacc-work} yacc: extension of headers modelled after extension of sources

From: Stefano Lattarini <[email-masked]>
Date: Fri, 28 Jan 2011 14:06:23 +0100

Hello automakers.  The reasons of this patch should be
explained in details in the ChangeLog entry (see below).

OK for the 'yacc-work' branch?

Regards,
   Stefano

-*-*-

With this change, if '-d' is in *YFLAGS, a yacc input file named
foo.y++ will cause a foo.h++ header to be generated, instead of a
foo.h header.  Similarly for foo.ypp, foo.yxx and foo.yy.
This way, the name of the files generated by an automake-created
`ylwrap' invocation should be consistent with those generated by
a `bison -o' call.

Related to automake bug#7648 and PR automake/491.

* lib/am/yacc.am (am__yacc_c2h): New internal variable.
(?GENERIC?%EXT%%DERIVED-EXT%, ?!GENERIC?%OBJ%): Get the name of
the header dynamically at make runtime, so that its extension is
modelled after the extension of the source.
* automake.in (lang_yacc_target_hook): Adjust the calculation of
`$header' accordingly.
* tests/yacc-cxx.test: New test.
* tests/yacc-d-cxx.test: Likewise.
* tests/yacc-weirdnames.test: Likewise.
* tests/yacc-basic.test: Update comments.
* tests/yacc-d-basic.test: Likewise.
* tests/yaccpp.test: Updated and extended.
* tests/Makefile.am (TESTS): Update.
From e3d6064f7faf582d70871bed40a9d19c9d4c98d4 Mon Sep 17 00:00:00 2001
From: Stefano Lattarini <[email-masked]>
Date: Fri, 21 Jan 2011 17:47:42 +0100
Subject: [PATCH] yacc: extension of headers modelled after extension of sources

With this change, if '-d' is in *YFLAGS, a yacc input file named
foo.y++ will cause a foo.h++ header to be generated, instead of a
foo.h header.  Similarly for foo.ypp, foo.yxx and foo.yy.
This way, the name of the files generated by an automake-created
`ylwrap' invocation should be consistent with those generated by
a `bison -o' call.

Related to automake bug#7648 and PR automake/491.

* lib/am/yacc.am (am__yacc_c2h): New internal variable.
(?GENERIC?%EXT%%DERIVED-EXT%, ?!GENERIC?%OBJ%): Get the name of
the header dynamically at make runtime, so that its extension is
modelled after the extension of the source.
* automake.in (lang_yacc_target_hook): Adjust the calculation of
`$header' accordingly.
* tests/yacc-cxx.test: New test.
* tests/yacc-d-cxx.test: Likewise.
* tests/yacc-weirdnames.test: Likewise.
* tests/yacc-basic.test: Update comments.
* tests/yacc-d-basic.test: Likewise.
* tests/yaccpp.test: Updated and extended.
* tests/Makefile.am (TESTS): Update.
---
 ChangeLog                  |   24 +++++
 automake.in                |   20 ++++-
 lib/am/yacc.am             |   11 ++-
 tests/Makefile.am          |    3 +
 tests/Makefile.in          |    3 +
 tests/yacc-basic.test      |    3 +-
 tests/yacc-cxx.test        |  138 ++++++++++++++++++++++++++
 tests/yacc-d-basic.test    |    7 +-
 tests/yacc-d-cxx.test      |  229 ++++++++++++++++++++++++++++++++++++++++++++
 tests/yacc-weirdnames.test |   56 +++++++++++
 tests/yaccpp.test          |   41 ++++++++-
 11 files changed, 522 insertions(+), 13 deletions(-)
 create mode 100755 tests/yacc-cxx.test
 create mode 100755 tests/yacc-d-cxx.test
 create mode 100755 tests/yacc-weirdnames.test

diff --git a/ChangeLog b/ChangeLog
index 31adec7..054ac58 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2011-01-28   Stefano Lattarini  <[email-masked]>
+
+	yacc: extension of headers modelled after extension of sources
+	With this change, if '-d' is in *YFLAGS, a yacc input file named
+	foo.y++ will cause a foo.h++ header to be generated, instead of a
+	foo.h header.  Similarly for foo.ypp, foo.yxx and foo.yy.
+	This way, the name of the files generated by an automake-created
+	`ylwrap' invocation should be consistent with those generated by
+	a `bison -o' call.
+	Related to automake bug#7648 and PR automake/491.
+	* lib/am/yacc.am (am__yacc_c2h): New internal variable.
+	(?GENERIC?%EXT%%DERIVED-EXT%, ?!GENERIC?%OBJ%): Get the name of
+	the header dynamically at make runtime, so that its extension is
+	modelled after the extension of the source.
+	* automake.in (lang_yacc_target_hook): Adjust the calculation of
+	`$header' accordingly.
+	* tests/yacc-cxx.test: New test.
+	* tests/yacc-d-cxx.test: Likewise.
+	* tests/yacc-weirdnames.test: Likewise.
+	* tests/yacc-basic.test: Update comments.
+	* tests/yacc-d-basic.test: Likewise.
+	* tests/yaccpp.test: Updated and extended.
+	* tests/Makefile.am (TESTS): Update.
+
 2011-01-12   Stefano Lattarini  <[email-masked]>
 
 	docs: clustered '-d' not recognized in YFLAGS
diff --git a/automake.in b/automake.in
index fa458d6..e2e67b9 100755
--- a/automake.in
+++ b/automake.in
@@ -6084,12 +6084,26 @@ sub lang_yacc_target_hook
 
     if ($yflags_contains_minus_d)
       {
-	(my $output_base = $output) =~ s/$KNOWN_EXTENSIONS_PATTERN$//;
-	my $header = $output_base . '.h';
-
 	# Found a `-d' that applies to the compilation of this file.
 	# Add a dependency for the generated header file, and arrange
 	# for that file to be included in the distribution.
+
+	# The extension of the output file (e.g., `.c' or `.cxx').
+	# We'll need it to compute the name of the generated header file.
+	(my $output_ext = basename ($output)) =~ s/.*(\.[^.]+)$/$1/;
+
+	# We know that a yacc input should be turned into either a C or
+	# C++ output file.  We depend on this fact (here and in yacc.am),
+	# so check that it really holds.
+	my $lang = $languages{$extension_map{$output_ext}};
+	prog_error "invalid output name `$output' for yacc file `$input'"
+	  if (!$lang || ($lang->name ne 'c' && $lang->name ne 'cxx'));
+
+	(my $header_ext = $output_ext) =~ s/c/h/g;
+        # Quote $output_ext in the regexp, so that dots in it are taken
+        # as literal dots, not as metacharacters.
+	(my $header = $output) =~ s/\Q$output_ext\E$/$header_ext/;
+
 	foreach my $cond (Automake::Rule::define (${header}, 'internal',
 						  RULE_AUTOMAKE, TRUE,
 						  INTERNAL))
diff --git a/lib/am/yacc.am b/lib/am/yacc.am
index 6d35cd4..8ad4074 100644
--- a/lib/am/yacc.am
+++ b/lib/am/yacc.am
@@ -33,16 +33,19 @@
 ## distributed or not.  We cannot have a generic rule that works in
 ## both cases, so we ensure in automake that nodist_ parsers always
 ## use non-generic rules.
-if %?MAINTAINER-MODE%
 if %?FIRST%
+if %?MAINTAINER-MODE%
 @MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
-endif %?FIRST%
 endif %?MAINTAINER-MODE%
+## The 's/c$/h/' substitution *must* be the last one.
+am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
+		   -e s/c++$$/h++/ -e s/c$$/h/
+endif %?FIRST%
 
 ?GENERIC?%EXT%%DERIVED-EXT%:
 ?!GENERIC?%OBJ%: %SOURCE%
-?GENERIC?	%VERBOSE%$(am__skipyacc) $(SHELL) $(YLWRAP) %SOURCE% y.tab.c %OBJ% y.tab.h %BASE%.h y.output %BASE%.output -- %COMPILE%
+?GENERIC?	%VERBOSE%$(am__skipyacc) $(SHELL) $(YLWRAP) %SOURCE% y.tab.c %OBJ% y.tab.h `echo %OBJ% | $(am__yacc_c2h)` y.output %BASE%.output -- %COMPILE%
 ?!GENERIC?	%VERBOSE% \
 ?!GENERIC??DIST_SOURCE?	$(am__skipyacc) \
 ## For non-suffix rules, we must emulate a VPATH search on %SOURCE%.
-?!GENERIC?	$(SHELL) $(YLWRAP) `test -f '%SOURCE%' || echo '$(srcdir)/'`%SOURCE% y.tab.c %OBJ% y.tab.h %BASE%.h y.output %BASE%.output -- %COMPILE%
+?!GENERIC?	$(SHELL) $(YLWRAP) `test -f '%SOURCE%' || echo '$(srcdir)/'`%SOURCE% y.tab.c %OBJ% y.tab.h `echo %OBJ% | $(am__yacc_c2h)` y.output %BASE%.output -- %COMPILE%
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 39f1a39..6230466 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -797,6 +797,8 @@ xsource.test \
 xz.test \
 yacc-basic.test \
 yacc-d-basic.test \
+yacc-cxx.test \
+yacc-d-cxx.test \
 yacc-clean.test \
 yacc.test \
 yacc2.test \
@@ -811,6 +813,7 @@ yacc-nodist.test \
 yaccpp.test \
 yaccvpath.test \
 yacc-d-vpath.test \
+yacc-weirdnames.test \
 yflags.test \
 yflags2.test \
 yflags-cmdline-override.test \
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 0ea9825..060bd83 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -1064,6 +1064,8 @@ xsource.test \
 xz.test \
 yacc-basic.test \
 yacc-d-basic.test \
+yacc-cxx.test \
+yacc-d-cxx.test \
 yacc-clean.test \
 yacc.test \
 yacc2.test \
@@ -1078,6 +1080,7 @@ yacc-nodist.test \
 yaccpp.test \
 yaccvpath.test \
 yacc-d-vpath.test \
+yacc-weirdnames.test \
 yflags.test \
 yflags2.test \
 yflags-cmdline-override.test \
diff --git a/tests/yacc-basic.test b/tests/yacc-basic.test
index 4faea95..9e87cbb 100755
--- a/tests/yacc-basic.test
+++ b/tests/yacc-basic.test
@@ -14,7 +14,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Basic semantic checks on Yacc support.
+# Basic semantic checks on Yacc support (without yacc-generated headers).
+# Keep in sync with sister test `yacc-cxx.test'.
 
 required=yacc
 . ./defs || Exit 1
diff --git a/tests/yacc-cxx.test b/tests/yacc-cxx.test
new file mode 100755
index 0000000..86693d6
--- /dev/null
+++ b/tests/yacc-cxx.test
@@ -0,0 +1,138 @@
+#! /bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Basic semantic checks on Yacc + C++ support (when yacc-generated
+# headers are not involved).
+# Keep in sync with sister test `yacc-basic.test'.
+
+required=yacc
+. ./defs || Exit 1
+
+distdir=$me-1.0
+
+cat >> configure.in << 'END'
+AC_PROG_CXX
+AC_PROG_YACC
+AC_OUTPUT
+END
+
+cat > Makefile.am << 'END'
+bin_PROGRAMS = foo1 foo2 foo3 foo4
+foo1_SOURCES = parse1.yy  foo.cc
+foo2_SOURCES = parse2.y++ bar.c++
+foo3_SOURCES = parse3.yxx foo.cc
+foo4_SOURCES = parse4.ypp bar.cxx
+foo3_YFLAGS = -v
+foo4_YFLAGS = $(foo3_YFLAGS)
+
+.PHONY: echo-distcom
+echo-distcom:
+	@echo ' ' $(DIST_COMMON) ' '
+END
+
+cat > parse1.yy << 'END'
+%{
+// Valid as C++, but deliberatly invalid as C.
+#include <cstdio>
+#include <cstdlib>
+int yylex (void) { return (getchar ()); }
+void yyerror (const char *s) { return; }
+%}
+%%
+a : 'a' { exit(0); };
+END
+cp parse1.yy parse2.y++
+cp parse1.yy parse3.yxx
+cp parse1.yy parse4.ypp
+
+cat > foo.cc << 'END'
+// Valid as C++, but deliberatly invalid as C.
+using namespace std;
+int main (int argc, char **argv)
+{
+  int yyparse (void);
+  yyparse ();
+  return 1;
+}
+END
+cp foo.cc bar.c++
+cp foo.cc bar.cxx
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+
+./configure
+
+$MAKE
+
+# The Yacc-derived C++ sources must be created, and not removed once
+# compiled (i.e., not treated like "intermediate files" in the GNU
+# make sense).
+test -f parse1.cc
+test -f parse2.c++
+test -f foo3-parse3.cxx
+test -f foo4-parse4.cpp
+# Check that per-object flags are honored.
+test -f foo3-parse3.output
+test -f foo4-parse4.output
+
+for i in 1 2 3 4; do
+  echo a | ./foo$i
+  echo b | ./foo$i && Exit 1
+done
+
+# The Yacc-derived C++ sources must be shipped.
+$MAKE echo-distcom
+$MAKE -s echo-distcom | grep '[ /]parse1\.cc '
+$MAKE -s echo-distcom | grep '[ /]parse2\.c++ '
+$MAKE -s echo-distcom | grep '[ /]foo3-parse3\.cxx '
+$MAKE -s echo-distcom | grep '[ /]foo4-parse4\.cpp '
+$MAKE distdir
+ls -l $distdir
+test -f $distdir/parse1.cc
+test -f $distdir/parse2.c++
+test -f $distdir/foo3-parse3.cxx
+test -f $distdir/foo4-parse4.cpp
+
+# Sanity check on distribution.
+# Note that, for this to succeed, foo3-parse3.output and foo4-parse4.output
+# must either not be distributed, or properly cleaned by automake-generated
+# rules.  We don't want to set the exact semantics yet, but want to ensure
+# they are are consistent.
+$MAKE distcheck
+
+# Make sure that the Yacc-derived C++ sources are erased by
+# maintainer-clean, and not by distclean.
+test -f parse1.cc
+test -f parse2.c++
+test -f foo3-parse3.cxx
+test -f foo4-parse4.cpp
+$MAKE distclean
+ls -l
+test -f parse1.cc
+test -f parse2.c++
+test -f foo3-parse3.cxx
+test -f foo4-parse4.cpp
+./configure # we must re-create `Makefile'
+$MAKE maintainer-clean
+ls -l
+test ! -f parse1.cc
+test ! -f parse2.c++
+test ! -f foo3-parse3.cxx
+test ! -f foo4-parse4.cpp
+
+:
diff --git a/tests/yacc-d-basic.test b/tests/yacc-d-basic.test
index 11e5ba3..6cb5e99 100755
--- a/tests/yacc-d-basic.test
+++ b/tests/yacc-d-basic.test
@@ -14,8 +14,9 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Tests on basic Yacc support for when we have -d in YFLAGS, AM_YFLAGS
-# or maude_YFLAGS.
+# Tests Yacc support with yacc-generated headers
+# (i.e., '-d' in *YFLAGS).
+# Keep in sync with sister test `yacc-d-cxx.test'.
 
 required=yacc
 . ./defs || Exit 1
@@ -111,7 +112,7 @@ test -f bar/parse.h
 test -f baz/zardoz-parse.c
 test -f baz/zardoz-parse.h
 
-# The generated C and header files must be shipped.
+# The generated C source and header files must be shipped.
 for dir in foo bar; do
   cd $dir
   $MAKE echo-distcom
diff --git a/tests/yacc-d-cxx.test b/tests/yacc-d-cxx.test
new file mode 100755
index 0000000..b94b14d
--- /dev/null
+++ b/tests/yacc-d-cxx.test
@@ -0,0 +1,229 @@
+#! /bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Various tests on Yacc/C++ support with yacc-generated headers
+# (i.e., '-d' in *YFLAGS).
+# Keep in sync with sister test `yacc-d-basic.test'.
+
+required=yacc
+. ./defs || Exit 1
+
+set -e
+
+tab='	'
+distdir=$me-1.0
+
+write_parse ()
+{
+  header=$1
+  sed 's/^ *//' <<END
+    %{
+    // Valid as C++, but deliberatly invalid as C.
+    #include <cstdlib>
+    #include "$header"
+    int yylex (void) { return 0; }
+    void yyerror (const char *s) {}
+    %}
+    %%
+    x : 'x' {};
+    %%
+END
+}
+
+write_main ()
+{
+  header=$1
+  sed 's/^ *//' <<END
+    // Valid as C++, but deliberatly invalid as C.
+    #include <cstdio>
+    #include "$header"
+    int main (int argc, char **argv)
+    {
+      int yyparse (void);
+      return yyparse ();
+    }
+END
+}
+
+cat >> configure.in << 'END'
+AC_PROG_CXX
+AC_PROG_YACC
+AC_CONFIG_FILES([foo/Makefile bar/Makefile baz/Makefile qux/Makefile])
+AC_OUTPUT
+END
+
+cat > Makefile.am <<'END'
+SUBDIRS = foo bar baz qux
+END
+
+mkdir foo bar baz qux baz/sub
+
+# These makefiles will be extended later.
+cat > foo/Makefile.am <<'END'
+.PHONY: echo-distcom
+echo-distcom:
+	@echo ' ' $(DIST_COMMON) ' '
+END
+cp foo/Makefile.am bar/Makefile.am
+cp foo/Makefile.am baz/Makefile.am
+cp foo/Makefile.am qux/Makefile.am
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE Makefile
+
+cp $testsrcdir/../lib/ylwrap .
+
+# Try with -d in $(YFLAGS) (don't do this in real life!).
+cat >> foo/Makefile.am <<END
+bin_PROGRAMS = zardoz
+zardoz_SOURCES = parse.yy main.cc
+BUILT_SOURCES = parse.hh
+YFLAGS=\
+-d
+END
+
+$AUTOMAKE -Wno-gnu foo/Makefile
+
+write_parse parse.hh > foo/parse.yy
+write_main parse.hh > foo/main.cc
+
+# Try with -d in $(AM_YFLAGS).
+cat >> bar/Makefile.am <<END
+bin_PROGRAMS = zardoz
+zardoz_SOURCES = parse.ypp main.cpp
+BUILT_SOURCES = parse.hpp
+AM_YFLAGS${tab}=  -d ${tab}
+END
+
+$AUTOMAKE bar/Makefile
+
+write_parse parse.hpp > bar/parse.ypp
+write_main parse.hpp > bar/main.cpp
+
+# Try with -d in $(AM_YFLAGS), and a subdir parser.
+cat >> baz/Makefile.am <<END
+AUTOMAKE_OPTIONS = subdir-objects
+bin_PROGRAMS = joe
+joe_SOURCES = sub/parse.y++ sub/main.c++
+BUILT_SOURCES = sub/parse.h++
+AM_YFLAGS = \
+${tab}-d
+END
+
+$AUTOMAKE baz/Makefile
+
+write_parse sub/parse.h++ > baz/sub/parse.y++
+write_main sub/parse.h++ > baz/sub/main.c++
+
+# Try with -d in $(xxx_YFLAGS) (per-object flag).
+cat >> qux/Makefile.am <<END
+bin_PROGRAMS = maude
+maude_SOURCES = parse.yxx main.cxx
+maude_YFLAGS=${tab}  -d${tab}
+BUILT_SOURCES = maude-parse.hxx
+END
+
+$AUTOMAKE qux/Makefile
+
+write_parse maude-parse.hxx > qux/parse.yxx
+write_main maude-parse.hxx > qux/main.cxx
+
+./configure
+
+$MAKE
+ls -l . foo bar baz baz/sub qux # For debugging.
+
+test -f foo/parse.cc
+test -f foo/parse.hh
+test -f bar/parse.cpp
+test -f bar/parse.hpp
+test -f baz/sub/parse.c++
+test -f baz/sub/parse.h++
+test -f qux/maude-parse.cxx
+test -f qux/maude-parse.hxx
+
+# The generated C++ source and header files must be shipped.
+cd foo
+$MAKE echo-distcom
+$MAKE -s echo-distcom | grep '[ /]parse\.cc '
+$MAKE -s echo-distcom | grep '[ /]parse\.hh '
+cd ..
+cd bar
+$MAKE echo-distcom
+$MAKE -s echo-distcom | grep '[ /]parse\.cpp '
+$MAKE -s echo-distcom | grep '[ /]parse\.hpp '
+cd ..
+cd baz
+$MAKE echo-distcom
+$MAKE -s echo-distcom | grep '[ /]sub/parse\.c++ '
+$MAKE -s echo-distcom | grep '[ /]sub/parse\.h++ '
+cd ..
+cd qux
+$MAKE echo-distcom
+$MAKE -s echo-distcom | grep '[ /]maude-parse\.cxx '
+$MAKE -s echo-distcom | grep '[ /]maude-parse\.hxx '
+cd ..
+
+$MAKE distdir
+find $distdir # For debugging.
+
+test -f $distdir/foo/parse.cc
+test -f $distdir/foo/parse.hh
+test -f $distdir/bar/parse.cpp
+test -f $distdir/bar/parse.hpp
+test -f $distdir/baz/sub/parse.c++
+test -f $distdir/baz/sub/parse.h++
+test -f $distdir/qux/maude-parse.cxx
+test -f $distdir/qux/maude-parse.hxx
+
+# The Yacc-derived C++ sources must be created, and not removed once
+# compiled (i.e., not treated like "intermediate files" in the GNU
+# make sense).
+$MAKE distcheck
+
+# Check that we can recover from deleted headers.
+$MAKE clean
+rm -f foo/parse.hh bar/parse.hpp baz/sub/parse.h++ qux/maude-parse.hxx
+$MAKE
+test -f foo/parse.hh
+test -f bar/parse.hpp
+test -f baz/sub/parse.h++
+test -f qux/maude-parse.hxx
+
+# Make sure that the Yacc-derived C++ sources are erased by
+# maintainer-clean, and not by distclean.
+$MAKE distclean
+test -f foo/parse.cc
+test -f foo/parse.hh
+test -f bar/parse.cpp
+test -f bar/parse.hpp
+test -f baz/sub/parse.c++
+test -f baz/sub/parse.h++
+test -f qux/maude-parse.cxx
+test -f qux/maude-parse.hxx
+./configure # We must re-create `Makefile'.
+$MAKE maintainer-clean
+test ! -f foo/parse.cc
+test ! -f foo/parse.hh
+test ! -f bar/parse.cpp
+test ! -f bar/parse.hpp
+test ! -f baz/sub/parse.c++
+test ! -f baz/sub/parse.h++
+test ! -f qux/maude-parse.cxx
+test ! -f qux/maude-parse.hxx
+
+:
diff --git a/tests/yacc-weirdnames.test b/tests/yacc-weirdnames.test
new file mode 100755
index 0000000..8f0424e
--- /dev/null
+++ b/tests/yacc-weirdnames.test
@@ -0,0 +1,56 @@
+#! /bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that yacc sources with many dots in their name are handled
+# correctly.
+
+. ./defs || Exit 1
+
+set -e
+
+cat >> configure.in << 'END'
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_YACC
+AC_OUTPUT
+END
+
+cat > Makefile.am << 'END'
+bin_PROGRAMS = foo bar foo2 bar2
+
+foo_SOURCES = parse.y.y
+bar_SOURCES = parse.s.f..y
+bar_YFLAGS = -d
+
+foo2_SOURCES = parse..5.y++
+bar2_SOURCES = parse.yxx.yy
+bar2_YFLAGS = -d
+END
+
+outputs=' parse.y.c      bar-parse.s.f..c   bar-parse.s.f..h
+          parse..5.c++   bar2-parse.yxx.cc  bar2-parse.yxx.hh '
+
+$ACLOCAL
+$AUTOMAKE -a
+
+$EGREP '(\.[ch]|parse)' Makefile.in # For debugging.
+
+# All expected files should be mentioned in the generated Makefile.in.
+for s in $outputs; do
+  $FGREP $s Makefile.in
+done
+
+:
diff --git a/tests/yaccpp.test b/tests/yaccpp.test
index 9c4ae24..e5c9e31 100755
--- a/tests/yaccpp.test
+++ b/tests/yaccpp.test
@@ -15,8 +15,10 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Test to make sure Yacc + C++ is supported.
-# Please keep this is sync with sister test lexcpp.test.
+# Test to make sure Yacc + C++ is not obviously broken.
+# See also related tests `yacc-cxx.test' and `yacc-d-cxx.test',
+# which does much more in-depth checks (but requires an actual
+# Yacc program and a working C++ compiler).
 
 . ./defs || Exit 1
 
@@ -38,10 +40,45 @@ END
 $ACLOCAL
 $AUTOMAKE -a
 
+$EGREP '(\.[ch]|foo|bar|baz|qux)' Makefile.in # For debugging.
+
+$EGREP '(foo|bar|baz|qux)\.h' Makefile.in && Exit 1
+
 sed -e 's/^/ /' -e 's/$/ /' Makefile.in >mk
+
 $FGREP ' foo.c++ ' mk
 $FGREP ' bar.cpp ' mk
 $FGREP ' baz.cc '  mk
 $FGREP ' qux.cxx ' mk
 
+cat >> Makefile.am <<END
+AM_YFLAGS = -d
+qux_YFLAGS = foo
+END
+
+$AUTOMAKE
+
+$EGREP '(\.[ch]|foo|bar|baz|qux)' Makefile.in # For debugging.
+
+sed -e 's/^/ /' -e 's/$/ /' Makefile.in >mk
+
+$FGREP ' foo.c++ ' mk
+$FGREP ' foo.h++ ' mk
+$FGREP ' bar.cpp ' mk
+$FGREP ' bar.hpp ' mk
+$FGREP ' baz.cc '  mk
+$FGREP ' baz.hh '  mk
+
+$EGREP '(^| )foo\.h\+\+(:| .*:)' Makefile.in
+$EGREP '(^| )bar\.hpp(:| .*:)'   Makefile.in
+$EGREP '(^| )baz\.hh(:| .*:)'    Makefile.in
+
+grep ' foo\.h[ :]' mk && Exit 1
+grep ' bar\.h[ :]' mk && Exit 1
+grep ' baz\.h[ :]' mk && Exit 1
+
+$FGREP ' qux-qux.cxx ' mk
+$EGREP '(^| )qux-qux\.cxx(:| .*:)' Makefile.in
+grep 'qux\.h.*:' Makefile.in && Exit 1
+
 :
-- 
1.7.2.3