diff --git a/Makefile.am b/Makefile.am
index 339a3c63..becd1d39 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,8 +24,10 @@ SUBDIRS = po runtime-po .
aclocaldir = @aclocaldir@
aclocal_DATA = m4/bison-i18n.m4
-EXTRA_DIST = .prev-version .version \
- cfg.mk ChangeLog-1998 ChangeLog-2012 PACKAGING
+EXTRA_DIST = .prev-version .version cfg.mk PACKAGING \
+ ChangeLog-1998 ChangeLog-2012 ChangeLog
+
+dist_doc_DATA = AUTHORS COPYING NEWS README THANKS TODO
## Running the bison from this tarball. To generate our own parser,
## but also to run the tests. Of course, you ought to keep a sane
diff --git a/NEWS b/NEWS
index 39322da8..e6521bf9 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,41 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Bug fixes
+
+*** Redeclarations are reported in proper order
+
+ On
+
+ %token FOO "foo"
+ %printer {} "foo"
+ %printer {} FOO
+
+ bison used to report:
+
+ /tmp/foo.yy:2.10-11: error: %printer redeclaration for FOO
+ %printer {} "foo"
+ ^^
+ /tmp/foo.yy:3.10-11: previous declaration
+ %printer {} FOO
+ ^^
+
+ Now, the "previous" declaration is always the first one.
+
+
+** Documentation
+
+ Bison now installs various files in its docdir (which defaults to
+ '/usr/local/share/doc/bison'), including the three fully blown examples
+ extracted from the documentation:
+
+ - rpcalc
+ Reverse polish calculator, a simple introductory example.
+ - mfcalc
+ Multi-function Calc, a calculator with memory and functions and located
+ error messages.
+ - calc++
+ a calculator in C++ using variant support and token constructors.
* Noteworthy changes in release 3.0.2 (2013-12-05) [stable]
diff --git a/configure.ac b/configure.ac
index f3dcdfd8..2658d73e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,12 +71,15 @@ AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
CFLAGS=$save_CFLAGS])
AC_ARG_ENABLE([gcc-warnings],
-[ --enable-gcc-warnings turn on lots of GCC warnings (not recommended)],
+[ --enable-gcc-warnings turn on lots of GCC warnings (not recommended).
+ Also, issue synclines from the examples/ to
+ the corresponding source in the Texinfo doc.],
[case $enable_gcc_warnings in
yes|no) ;;
*) AC_MSG_ERROR([invalid value for --gcc-warnings: $enable_gcc_warnings]);;
esac],
[enable_gcc_warnings=no])
+AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes])
if test "$enable_gcc_warnings" = yes; then
warn_common='-Wall-Wextra -Wno-sign-compare -Wcast-align -Wdocumentation
-Wformat -Wpointer-arith -Wwrite-strings'
diff --git a/examples/calc++/local.mk b/examples/calc++/local.mk
index d920e634..018d007a 100644
--- a/examples/calc++/local.mk
+++ b/examples/calc++/local.mk
@@ -27,11 +27,11 @@ SUFFIXES += .yy .stamp
$(AM_V_at)$(YACCCOMPILE) -o $*.cc $<
$(AM_V_at)mv -f $@.tmp $@
-$(calc_sources_generated): %D%/calc++-parser.stamp
+$(calcxx_sources_generated): %D%/calc++-parser.stamp
@test -f $@ || rm -f %D%/calc++-parser.stamp
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/calc++-parser.stamp
CLEANFILES += \
- $(calc_sources_generated) \
+ $(calcxx_sources_generated) \
%D%/calc++-parser.output \
%D%/calc++-parser.stamp \
%D%/calc++-scanner.cc
@@ -42,31 +42,31 @@ CLEANFILES += \
## -------------------- ##
# Avoid using BUILT_SOURCES which is too global.
-$(%C%_calc___OBJECTS): $(calc_sources_generated)
+$(%C%_calc___OBJECTS): $(calcxx_sources_generated)
-calc_sources_extracted = \
+calcxx_sources_extracted = \
%D%/calc++-driver.cc \
%D%/calc++-driver.hh \
%D%/calc++-scanner.ll \
%D%/calc++.cc
-calc_extracted = \
- $(calc_sources_extracted) \
+calcxx_extracted = \
+ $(calcxx_sources_extracted) \
%D%/calc++-parser.yy
-extracted += $(calc_extracted)
-calc_sources_generated = \
+extracted += $(calcxx_extracted)
+calcxx_sources_generated = \
%D%/calc++-parser.cc \
%D%/calc++-parser.hh \
%D%/location.hh \
%D%/position.hh \
%D%/stack.hh
-calc_sources = \
- $(calc_sources_extracted) \
- $(calc_sources_generated)
+calcxx_sources = \
+ $(calcxx_sources_extracted) \
+ $(calcxx_sources_generated)
if FLEX_CXX_WORKS
check_PROGRAMS += %D%/calc++
nodist_%C%_calc___SOURCES = \
- $(calc_sources)
+ $(calcxx_sources)
%C%_calc___CPPFLAGS = -I$(top_builddir)/%D%
%C%_calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS)
@@ -74,3 +74,11 @@ dist_TESTS += %D%/calc++.test
else
EXTRA_DIST += %D%/calc++.test
endif
+
+
+## ------------ ##
+## Installing. ##
+## ------------ ##
+
+calcxxdir = $(docdir)/examples/calc++
+calcxx_DATA = $(calcxx_extracted)
diff --git a/examples/extexi b/examples/extexi
index 24a005eb..d4ce653d 100755
--- a/examples/extexi
+++ b/examples/extexi
@@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-# Usage: extexi input-file.texi ... -- [FILES to extract]
+# Usage: extexi [OPTION...] input-file.texi ... -- [FILES to extract]
# Look for @example environments preceded with lines such as:
#
@@ -35,6 +35,9 @@
use strict;
+# Whether we generate synclines.
+my $synclines = 0;
+
# normalize($block)
# -----------------
# Remove Texinfo mark up.
@@ -102,7 +105,7 @@ sub process ($)
{
# Bison supports synclines, but not Flex.
$input .= sprintf ("#line %s \"$in\"\n", $. + 1)
- if $file =~ /\.[chy]*$/;
+ if $synclines && $file =~ /\.[chy]*$/;
next;
}
elsif (/^\@end (small)?example$/)
@@ -136,15 +139,19 @@ my @input;
my $seen_dash = 0;
for my $arg (@ARGV)
{
- if ($arg eq '--')
- {
- $seen_dash = 1;
- }
- elsif ($seen_dash)
+ if ($seen_dash)
{
use File::Basename;
$file_wanted{basename($arg)} = $arg;
}
+ elsif ($arg eq '--')
+ {
+ $seen_dash = 1;
+ }
+ elsif ($arg eq '--synclines')
+ {
+ $synclines = 1;
+ }
else
{
push @input, $arg;
diff --git a/examples/local.mk b/examples/local.mk
index 9f7863c1..8274e007 100644
--- a/examples/local.mk
+++ b/examples/local.mk
@@ -25,7 +25,10 @@ AM_CXXFLAGS = \
doc = $(top_srcdir)/doc/bison.texi
extexi = $(top_srcdir)/%D%/extexi
-extract = VERSION="$(VERSION)" $(PERL) $(extexi) $(doc) --
+if ENABLE_GCC_WARNINGS
+extexiFLAGS = --synclines
+endif
+extract = VERSION="$(VERSION)" $(PERL) $(extexi) $(extexiFLAGS) $(doc) --
extracted =
CLEANFILES += $(extracted) %D%/extracted.stamp
%D%/extracted.stamp: $(doc) $(extexi)
diff --git a/examples/mfcalc/local.mk b/examples/mfcalc/local.mk
index 97ea63b3..361a4a5f 100644
--- a/examples/mfcalc/local.mk
+++ b/examples/mfcalc/local.mk
@@ -30,3 +30,10 @@ nodist_%C%_mfcalc_SOURCES = $(mfcalc_sources)
%C%_mfcalc_CPPFLAGS = -I$(top_builddir)/%D%
dist_TESTS += %D%/mfcalc.test
+
+## ------------ ##
+## Installing. ##
+## ------------ ##
+
+mfcalcdir = $(docdir)/examples/mfcalc
+mfcalc_DATA = $(mfcalc_extracted)
diff --git a/examples/rpcalc/local.mk b/examples/rpcalc/local.mk
index 97f35356..125bb3ba 100644
--- a/examples/rpcalc/local.mk
+++ b/examples/rpcalc/local.mk
@@ -30,3 +30,10 @@ nodist_%C%_rpcalc_SOURCES = $(rpcalc_sources)
%C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D%
dist_TESTS += %D%/rpcalc.test
+
+## ------------ ##
+## Installing. ##
+## ------------ ##
+
+rpcalcdir = $(docdir)/examples/rpcalc
+rpcalc_DATA = $(rpcalc_extracted)
diff --git a/src/symtab.c b/src/symtab.c
index f6761c4a..5a8b6169 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -138,6 +138,42 @@ symbol_free (void *ptr)
if (!sym->is_alias)
sym_content_free (sym->content);
free (sym);
+
+}
+
+/* If needed, swap first and second so that first has the earliest
+ location (according to location_cmp).
+
+ Many symbol features (e.g., user token numbers) are not assigned
+ during the parsing, but in a second step, via a traversal of the
+ symbol table sorted on tag.
+
+ However, error messages make more sense if we keep the first
+ declaration first.
+*/
+
+static
+void symbols_sort (symbol **first, symbol **second)
+{
+ if (0 < location_cmp ((*first)->location, (*second)->location))
+ {
+ symbol* tmp = *first;
+ *first = *second;
+ *second = tmp;
+ }
+}
+
+/* Likewise, for locations. */
+
+static
+void locations_sort (location *first, location *second)
+{
+ if (0 < location_cmp (*first, *second))
+ {
+ location tmp = *first;
+ *first = *second;
+ *second = tmp;
+ }
}
char const *
@@ -250,6 +286,7 @@ symbol_redeclaration (symbol *s, const char *what, location first,
location second)
{
unsigned i = 0;
+ locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%s redeclaration for %s"), what, s->tag);
i += SUB_INDENT;
@@ -262,6 +299,7 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first,
location second)
{
unsigned i = 0;
+ locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag);
i += SUB_INDENT;
@@ -570,17 +608,7 @@ static void
user_token_number_redeclaration (int num, symbol *first, symbol *second)
{
unsigned i = 0;
- /* User token numbers are not assigned during the parsing, but in a
- second step, via a traversal of the symbol table sorted on tag.
-
- However, error messages make more sense if we keep the first
- declaration first. */
- if (location_cmp (first->location, second->location) > 0)
- {
- symbol* tmp = first;
- first = second;
- second = tmp;
- }
+ symbols_sort (&first, &second);
complain_indent (&second->location, complaint, &i,
_("user token number %d redeclaration for %s"),
num, second->tag);
diff --git a/tests/input.at b/tests/input.at
index 969e53fc..205342bd 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -654,50 +654,118 @@ AT_CLEANUP
AT_SETUP([Incompatible Aliases])
-AT_DATA([input.y],
-[[%token foo "foo"
+m4_pushdef([AT_TEST],
+[AT_DATA([input.y], [$1])
+AT_BISON_CHECK([-fcaret input.y], [1], [], [$2])
+])
-%type foo
-%printer {bar} foo
-%destructor {bar} foo
-%left foo
-
-%type "foo"
-%printer {baz} "foo"
-%destructor {baz} "foo"
-%left "foo"
+# Use the string-alias first to check the order between "first
+# declaration" and second.
+AT_TEST([[%token foo "foo"
+%type "foo"
+%type foo
%%
exp: foo;
+]],
+[[input.y:3.7-11: error: %type redeclaration for foo
+ %type foo
+ ^^^^^
+input.y:2.7-11: previous declaration
+ %type "foo"
+ ^^^^^
]])
-AT_BISON_CHECK([-fcaret input.y], [1], [],
-[[input.y:8.7-11: error: %type redeclaration for "foo"
- %type "foo"
- ^^^^^
-input.y:3.7-11: previous declaration
- %type foo
- ^^^^^
-input.y:9.10-14: error: %printer redeclaration for "foo"
- %printer {baz} "foo"
+AT_TEST([[%token foo "foo"
+%printer {bar} "foo"
+%printer {baz} foo
+%%
+exp: foo;
+]],
+[[input.y:3.10-14: error: %printer redeclaration for foo
+ %printer {baz} foo
^^^^^
-input.y:4.10-14: previous declaration
- %printer {bar} foo
+input.y:2.10-14: previous declaration
+ %printer {bar} "foo"
^^^^^
-input.y:10.13-17: error: %destructor redeclaration for "foo"
- %destructor {baz} "foo"
+]])
+
+AT_TEST([[%token foo "foo"
+%destructor {bar} "foo"
+%destructor {baz} foo
+%%
+exp: foo;
+]],
+[[input.y:3.13-17: error: %destructor redeclaration for foo
+ %destructor {baz} foo
^^^^^
-input.y:5.13-17: previous declaration
- %destructor {bar} foo
+input.y:2.13-17: previous declaration
+ %destructor {bar} "foo"
^^^^^
-input.y:11.1-5: error: %left redeclaration for "foo"
- %left "foo"
+]])
+
+AT_TEST([[%token foo "foo"
+%left "foo"
+%left foo
+%%
+exp: foo;
+]],
+[[input.y:3.1-5: error: %left redeclaration for foo
+ %left foo
^^^^^
-input.y:6.1-5: previous declaration
- %left foo
+input.y:2.1-5: previous declaration
+ %left "foo"
^^^^^
]])
+# This time, declare the alias after its use.
+
+# Precedence/associativity.
+## FIXME: AT_TEST([[%left "foo"
+## FIXME: %left foo
+## FIXME: %token foo "foo"
+## FIXME: %%
+## FIXME: exp: foo;
+## FIXME: ]],
+## FIXME: [[input.y:2.1-5: error: %left redeclaration for foo
+## FIXME: %left foo
+## FIXME: ^^^^^
+## FIXME: input.y:1.1-5: previous declaration
+## FIXME: %left "foo"
+## FIXME: ^^^^^
+## FIXME: ]])
+
+## FIXME: # Printer.
+## FIXME: AT_TEST([[%printer {} "foo"
+## FIXME: %printer {} foo
+## FIXME: %token foo "foo"
+## FIXME: %%
+## FIXME: exp: foo;
+## FIXME: ]],
+## FIXME: [[input.y:2.10-11: error: %printer redeclaration for foo
+## FIXME: %printer {} foo
+## FIXME: ^^
+## FIXME: input.y:1.10-11: previous declaration
+## FIXME: %printer {} "foo"
+## FIXME: ^^
+## FIXME: ]])
+
+## FIXME: # Destructor.
+## FIXME: AT_TEST([[%destructor {} "foo"
+## FIXME: %destructor {} foo
+## FIXME: %token foo "foo"
+## FIXME: %%
+## FIXME: exp: foo;
+## FIXME: ]],
+## FIXME: [[input.y:2.13-14: error: %destructor redeclaration for foo
+## FIXME: %destructor {} foo
+## FIXME: ^^
+## FIXME: input.y:1.13-14: previous declaration
+## FIXME: %destructor {} "foo"
+## FIXME: ^^
+## FIXME: ]])
+
+m4_popdef([AT_TEST])
AT_CLEANUP