Merge remote-tracking branch 'origin/maint'

* origin/maint:
  package: install the examples
  package: install README and the like in docdir
  diagnostics: fix the order of multiple declarations reports
  symbol: provide an easy means to compare them in source order

Conflicts:
  src/symtab.c
  tests/input.at

* tests/input.at: Comment out a test that master currently does not
pass (because of a728075710).
This commit is contained in:
Akim Demaille
2013-12-10 08:49:49 +01:00
10 changed files with 232 additions and 64 deletions

View File

@@ -24,8 +24,10 @@ SUBDIRS = po runtime-po .
aclocaldir = @aclocaldir@ aclocaldir = @aclocaldir@
aclocal_DATA = m4/bison-i18n.m4 aclocal_DATA = m4/bison-i18n.m4
EXTRA_DIST = .prev-version .version \ EXTRA_DIST = .prev-version .version cfg.mk PACKAGING \
cfg.mk ChangeLog-1998 ChangeLog-2012 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, ## 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 ## but also to run the tests. Of course, you ought to keep a sane

35
NEWS
View File

@@ -2,6 +2,41 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?] * 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] * Noteworthy changes in release 3.0.2 (2013-12-05) [stable]

View File

@@ -71,12 +71,15 @@ AC_CACHE_CHECK([whether pragma GCC diagnostic push works],
CFLAGS=$save_CFLAGS]) CFLAGS=$save_CFLAGS])
AC_ARG_ENABLE([gcc-warnings], 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 [case $enable_gcc_warnings in
yes|no) ;; yes|no) ;;
*) AC_MSG_ERROR([invalid value for --gcc-warnings: $enable_gcc_warnings]);; *) AC_MSG_ERROR([invalid value for --gcc-warnings: $enable_gcc_warnings]);;
esac], esac],
[enable_gcc_warnings=no]) [enable_gcc_warnings=no])
AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes])
if test "$enable_gcc_warnings" = yes; then if test "$enable_gcc_warnings" = yes; then
warn_common='-Wall-Wextra -Wno-sign-compare -Wcast-align -Wdocumentation warn_common='-Wall-Wextra -Wno-sign-compare -Wcast-align -Wdocumentation
-Wformat -Wpointer-arith -Wwrite-strings' -Wformat -Wpointer-arith -Wwrite-strings'

View File

@@ -27,11 +27,11 @@ SUFFIXES += .yy .stamp
$(AM_V_at)$(YACCCOMPILE) -o $*.cc $< $(AM_V_at)$(YACCCOMPILE) -o $*.cc $<
$(AM_V_at)mv -f $@.tmp $@ $(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 $@ || rm -f %D%/calc++-parser.stamp
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/calc++-parser.stamp @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/calc++-parser.stamp
CLEANFILES += \ CLEANFILES += \
$(calc_sources_generated) \ $(calcxx_sources_generated) \
%D%/calc++-parser.output \ %D%/calc++-parser.output \
%D%/calc++-parser.stamp \ %D%/calc++-parser.stamp \
%D%/calc++-scanner.cc %D%/calc++-scanner.cc
@@ -42,31 +42,31 @@ CLEANFILES += \
## -------------------- ## ## -------------------- ##
# Avoid using BUILT_SOURCES which is too global. # 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.cc \
%D%/calc++-driver.hh \ %D%/calc++-driver.hh \
%D%/calc++-scanner.ll \ %D%/calc++-scanner.ll \
%D%/calc++.cc %D%/calc++.cc
calc_extracted = \ calcxx_extracted = \
$(calc_sources_extracted) \ $(calcxx_sources_extracted) \
%D%/calc++-parser.yy %D%/calc++-parser.yy
extracted += $(calc_extracted) extracted += $(calcxx_extracted)
calc_sources_generated = \ calcxx_sources_generated = \
%D%/calc++-parser.cc \ %D%/calc++-parser.cc \
%D%/calc++-parser.hh \ %D%/calc++-parser.hh \
%D%/location.hh \ %D%/location.hh \
%D%/position.hh \ %D%/position.hh \
%D%/stack.hh %D%/stack.hh
calc_sources = \ calcxx_sources = \
$(calc_sources_extracted) \ $(calcxx_sources_extracted) \
$(calc_sources_generated) $(calcxx_sources_generated)
if FLEX_CXX_WORKS if FLEX_CXX_WORKS
check_PROGRAMS += %D%/calc++ check_PROGRAMS += %D%/calc++
nodist_%C%_calc___SOURCES = \ nodist_%C%_calc___SOURCES = \
$(calc_sources) $(calcxx_sources)
%C%_calc___CPPFLAGS = -I$(top_builddir)/%D% %C%_calc___CPPFLAGS = -I$(top_builddir)/%D%
%C%_calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS) %C%_calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS)
@@ -74,3 +74,11 @@ dist_TESTS += %D%/calc++.test
else else
EXTRA_DIST += %D%/calc++.test EXTRA_DIST += %D%/calc++.test
endif endif
## ------------ ##
## Installing. ##
## ------------ ##
calcxxdir = $(docdir)/examples/calc++
calcxx_DATA = $(calcxx_extracted)

View File

@@ -19,7 +19,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# 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: # Look for @example environments preceded with lines such as:
# #
@@ -35,6 +35,9 @@
use strict; use strict;
# Whether we generate synclines.
my $synclines = 0;
# normalize($block) # normalize($block)
# ----------------- # -----------------
# Remove Texinfo mark up. # Remove Texinfo mark up.
@@ -102,7 +105,7 @@ sub process ($)
{ {
# Bison supports synclines, but not Flex. # Bison supports synclines, but not Flex.
$input .= sprintf ("#line %s \"$in\"\n", $. + 1) $input .= sprintf ("#line %s \"$in\"\n", $. + 1)
if $file =~ /\.[chy]*$/; if $synclines && $file =~ /\.[chy]*$/;
next; next;
} }
elsif (/^\@end (small)?example$/) elsif (/^\@end (small)?example$/)
@@ -136,15 +139,19 @@ my @input;
my $seen_dash = 0; my $seen_dash = 0;
for my $arg (@ARGV) for my $arg (@ARGV)
{ {
if ($arg eq '--') if ($seen_dash)
{
$seen_dash = 1;
}
elsif ($seen_dash)
{ {
use File::Basename; use File::Basename;
$file_wanted{basename($arg)} = $arg; $file_wanted{basename($arg)} = $arg;
} }
elsif ($arg eq '--')
{
$seen_dash = 1;
}
elsif ($arg eq '--synclines')
{
$synclines = 1;
}
else else
{ {
push @input, $arg; push @input, $arg;

View File

@@ -25,7 +25,10 @@ AM_CXXFLAGS = \
doc = $(top_srcdir)/doc/bison.texi doc = $(top_srcdir)/doc/bison.texi
extexi = $(top_srcdir)/%D%/extexi 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 = extracted =
CLEANFILES += $(extracted) %D%/extracted.stamp CLEANFILES += $(extracted) %D%/extracted.stamp
%D%/extracted.stamp: $(doc) $(extexi) %D%/extracted.stamp: $(doc) $(extexi)

View File

@@ -30,3 +30,10 @@ nodist_%C%_mfcalc_SOURCES = $(mfcalc_sources)
%C%_mfcalc_CPPFLAGS = -I$(top_builddir)/%D% %C%_mfcalc_CPPFLAGS = -I$(top_builddir)/%D%
dist_TESTS += %D%/mfcalc.test dist_TESTS += %D%/mfcalc.test
## ------------ ##
## Installing. ##
## ------------ ##
mfcalcdir = $(docdir)/examples/mfcalc
mfcalc_DATA = $(mfcalc_extracted)

View File

@@ -30,3 +30,10 @@ nodist_%C%_rpcalc_SOURCES = $(rpcalc_sources)
%C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D% %C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D%
dist_TESTS += %D%/rpcalc.test dist_TESTS += %D%/rpcalc.test
## ------------ ##
## Installing. ##
## ------------ ##
rpcalcdir = $(docdir)/examples/rpcalc
rpcalc_DATA = $(rpcalc_extracted)

View File

@@ -138,6 +138,42 @@ symbol_free (void *ptr)
if (!sym->is_alias) if (!sym->is_alias)
sym_content_free (sym->content); sym_content_free (sym->content);
free (sym); 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 * char const *
@@ -250,6 +286,7 @@ symbol_redeclaration (symbol *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; unsigned i = 0;
locations_sort (&first, &second);
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
_("%s redeclaration for %s"), what, s->tag); _("%s redeclaration for %s"), what, s->tag);
i += SUB_INDENT; i += SUB_INDENT;
@@ -262,6 +299,7 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first,
location second) location second)
{ {
unsigned i = 0; unsigned i = 0;
locations_sort (&first, &second);
complain_indent (&second, complaint, &i, complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag); _("%s redeclaration for <%s>"), what, s->tag);
i += SUB_INDENT; i += SUB_INDENT;
@@ -570,17 +608,7 @@ static void
user_token_number_redeclaration (int num, symbol *first, symbol *second) user_token_number_redeclaration (int num, symbol *first, symbol *second)
{ {
unsigned i = 0; unsigned i = 0;
/* User token numbers are not assigned during the parsing, but in a symbols_sort (&first, &second);
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;
}
complain_indent (&second->location, complaint, &i, complain_indent (&second->location, complaint, &i,
_("user token number %d redeclaration for %s"), _("user token number %d redeclaration for %s"),
num, second->tag); num, second->tag);

View File

@@ -654,50 +654,118 @@ AT_CLEANUP
AT_SETUP([Incompatible Aliases]) AT_SETUP([Incompatible Aliases])
AT_DATA([input.y], m4_pushdef([AT_TEST],
[[%token foo "foo" [AT_DATA([input.y], [$1])
AT_BISON_CHECK([-fcaret input.y], [1], [], [$2])
])
%type <bar> foo # Use the string-alias first to check the order between "first
%printer {bar} foo # declaration" and second.
%destructor {bar} foo
%left foo
%type <baz> "foo"
%printer {baz} "foo"
%destructor {baz} "foo"
%left "foo"
AT_TEST([[%token foo "foo"
%type <bar> "foo"
%type <baz> foo
%% %%
exp: foo; exp: foo;
]],
[[input.y:3.7-11: error: %type redeclaration for foo
%type <baz> foo
^^^^^
input.y:2.7-11: previous declaration
%type <bar> "foo"
^^^^^
]]) ]])
AT_BISON_CHECK([-fcaret input.y], [1], [], AT_TEST([[%token foo "foo"
[[input.y:8.7-11: error: %type redeclaration for "foo" %printer {bar} "foo"
%type <baz> "foo" %printer {baz} foo
^^^^^ %%
input.y:3.7-11: previous declaration exp: foo;
%type <bar> foo ]],
^^^^^ [[input.y:3.10-14: error: %printer redeclaration for foo
input.y:9.10-14: error: %printer redeclaration for "foo" %printer {baz} foo
%printer {baz} "foo"
^^^^^ ^^^^^
input.y:4.10-14: previous declaration input.y:2.10-14: previous declaration
%printer {bar} foo %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 input.y:2.13-17: previous declaration
%destructor {bar} foo %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 input.y:2.1-5: previous declaration
%left foo %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 AT_CLEANUP