api.header.include: document it, and fix its default value

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
commit a53c6026cd367c75d5594e6e649ee1cdda93d5ae
Author: Akim Demaille <[email protected]>
Date:   Tue Jun 9 07:08:11 2020 +0200

    api.header.include: document it, and fix its default value
    
    While defining api.header.include worked as expected, its default
    value was incorrectly defined.  As a result, by default, the generated
    parsers still duplicated the content of the generated header instead
    of including it.
    
    * data/skeletons/yacc.c (api.header.include): Fix its default value.
    * tests/output.at: Check it.
    * doc/bison.texi (%define Summary): Document api.header.include.
    While at it, move the definition of api.namespace at the proper
    place.

diff --git a/NEWS b/NEWS
index 712b2b7a..1cec2252 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,26 @@ GNU Bison NEWS
   When installed to be relocatable (via configure --enable-relocatable),
   bison will now also look for a relocated m4.
 
+** Bug fixes
+
+*** Include the generated header (yacc.c)
+
+  Historically, when --defines was used, bison generated a header and pasted
+  an exact copy of it into the generated parser implementation file.  Since
+  Bison 3.4 it is possible to specify that the header should be `#include`d,
+  and how.  For instance
+
+    %define api.header.include {"parse.h"}
+
+  or
+
+    %define api.header.include {<parser/parse.h>}
+
+  Now api.header.include defaults to `"header-basename"`, as was intended in
+  Bison 3.4, where `header-basename` is the basename of the generated
+  header.  This is disabled when the generated header is `y.tab.h`, to
+  comply with Automake's ylwrap.
+
 ** New features
 
 *** File prefix mapping
diff --git a/TODO b/TODO
index 96459653..5d440169 100644
--- a/TODO
+++ b/TODO
@@ -15,16 +15,11 @@ list_get_end (gl_list_t list)
 ** Bistromathic
 - Hitting tab on a line with a syntax error is ugly
 
-- Be robust to existing ~/.inputrc
-
 - How about not evaluating incomplete lines when the text is not finished
   (as shells do).
 
 - Caret diagnostics
 
-** Doc
-*** api.header.include
-
 ** Questions
 *** Java
 - Should i18n be part of the Lexer?  Currently it's a static method of
@@ -54,9 +49,6 @@ enough.
 *** calc.at
 Stop hard-coding "Calc".  Adjust local.at (look for FIXME).
 
-** Counter example generation
-See https://github.com/akimd/bison/pull/15.
-
 ** Clean up
 Rename endtoken as eoftoken.
 
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index ffc02efd..a9c84a33 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -335,7 +335,7 @@ m4_define([b4_header_include_if],
                                    [$2])],
           [$2])])
 
-m4_if(b4_spec_header_file, [[y.tab.h]],
+m4_if(b4_spec_header_file, [y.tab.h], [],
       [b4_percent_define_default([[api.header.include]],
                                  [["@basename(]b4_spec_header_file[@)"]])])
 
diff --git a/doc/bison.texi b/doc/bison.texi
index 5a08fa92..c60897bc 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -5922,44 +5922,58 @@ Unaccepted @var{variable}s produce an error.  Some of the accepted
 @var{variable}s are described below.
 
 
-@c ================================================== api.namespace
-@deffn Directive {%define api.namespace} @{@var{namespace}@}
+@c ================================================== api.header.include
+@deffn Directive {%define api.header.include} @{"header.h"@}
+@deffnx Directive {%define api.header.include} @{<header.h>@}
 @itemize
-@item Languages(s): C++
+@item Languages(s): C (@file{yacc.c})
 
-@item Purpose: Specify the namespace for the parser class.
-For example, if you specify:
+@item Purpose: Specify how the generated parser should include the generated header.
 
-@example
-%define api.namespace @{foo::bar@}
-@end example
+Historically, when option @option{-D}/@option{--defines} was used,
+@command{bison} generated a header and pasted an exact copy of it into the
+generated parser implementation file.  Since Bison 3.6, it is
+@code{#include}d as @samp{"@var{basename}.h"}, instead of duplicated, unless
+@var{file} is @samp{y.tab}, see below.
 
-Bison uses @code{foo::bar} verbatim in references such as:
+The @code{api.header.include} variable allows to control how the generated
+parser @code{#include}s the generated header.  For instance:
 
 @example
-foo::bar::parser::semantic_type
+%define api.header.include @{"parse.h"@}
 @end example
 
-However, to open a namespace, Bison removes any leading @code{::} and then
-splits on any remaining occurrences:
+@noindent
+or
 
 @example
-namespace foo @{ namespace bar @{
-  class position;
-  class location;
-@} @}
+%define api.header.include @{<parser/parse.h>@}
 @end example
 
+Using @code{api.header.include} does not change the name of the generated
+header, only how it is included.
+
+To work around limitations of Automake's @command{ylwrap} (which runs
+@command{bison} with @option{--yacc}), @code{api.header.include} is
+@emph{not} predefined when the output file is @file{y.tab.c}.  Define it to
+avoid the duplication.
+
 @item Accepted Values:
-Any absolute or relative C++ namespace reference without a trailing
-@code{"::"}.  For example, @code{"foo"} or @code{"::foo::bar"}.
+An argument for @code{#include}.
 
 @item Default Value:
-@code{yy}, unless you used the obsolete @samp{%name-prefix "@var{prefix}"}
-directive.
+@samp{"@var{header-basename}"}, unless the header file is @file{y.tab.h},
+where @var{header-basename} is the name of the generated header, without
+directory part.  For instance with @command{bison -d calc/parse.y},
+@code{api.header.include} defaults to @samp{"parse.h"}, not
+@samp{"calc/parse.h"}.
+
+@item History:
+Introduced in Bison 3.4.  Defaults to @samp{"@var{basename}.h"} since Bison
+3.7, unless the header file is @file{y.tab.h}.
 @end itemize
 @end deffn
-@c api.namespace
+@c api.header.include
 
 
 @c ================================================== api.location.file
@@ -6043,6 +6057,46 @@ Introduced in Bison 2.7 for C++ and Java, in Bison 3.4 for C.
 @end deffn
 
 
+@c ================================================== api.namespace
+@deffn Directive {%define api.namespace} @{@var{namespace}@}
+@itemize
+@item Languages(s): C++
+
+@item Purpose: Specify the namespace for the parser class.
+For example, if you specify:
+
+@example
+%define api.namespace @{foo::bar@}
+@end example
+
+Bison uses @code{foo::bar} verbatim in references such as:
+
+@example
+foo::bar::parser::semantic_type
+@end example
+
+However, to open a namespace, Bison removes any leading @code{::} and then
+splits on any remaining occurrences:
+
+@example
+namespace foo @{ namespace bar @{
+  class position;
+  class location;
+@} @}
+@end example
+
+@item Accepted Values:
+Any absolute or relative C++ namespace reference without a trailing
+@code{"::"}.  For example, @code{"foo"} or @code{"::foo::bar"}.
+
+@item Default Value:
+@code{yy}, unless you used the obsolete @samp{%name-prefix "@var{prefix}"}
+directive.
+@end itemize
+@end deffn
+@c api.namespace
+
+
 @c ================================================== api.parser.class
 @deffn Directive {%define api.parser.class} @{@var{name}@}
 @itemize @bullet
diff --git a/tests/output.at b/tests/output.at
index 4e9a4409..11dcceb7 100644
--- a/tests/output.at
+++ b/tests/output.at
@@ -30,9 +30,10 @@ m4_define([AT_CHECK_FILES],
           [], [$1
 ])])
 
-# AT_CHECK_OUTPUT(INPUT-FILE, [DIRECTIVES], [FLAGS], EXPECTED-FILES, [STATUS],
-#                 [ADDITIONAL-TESTS], [PRE-TESTS])
-# -----------------------------------------------------------------------------
+# AT_CHECK_OUTPUT($1 = INPUT-FILE, $2 = [DIRECTIVES], $3 = [FLAGS],
+#                 $4 = EXPECTED-FILES, $5 = [STATUS],
+#                 $6 = [ADDITIONAL-TESTS], $7 = [PRE-TESTS])
+# -----------------------------------------------------------------
 m4_define([AT_CHECK_OUTPUT],
 [AT_SETUP([[Output files: ]$2 $3])[
 ]$7[
@@ -73,8 +74,19 @@ AT_CHECK_OUTPUT([foo.y], [], [-dv >&-],
                 [], [],
                 [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
 
+
+# Check how api.header.include.
 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.c],
-                [foo.c foo.h foo.output])
+                [foo.c foo.h foo.output], [],
+                [AT_CHECK([grep '#include "foo.h"' foo.c], [0], [ignore])])
+AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
+                [y.output y.tab.c y.tab.h], [],
+                [AT_CHECK([grep '#include "y.tab.h"' y.tab.c], [1], [ignore])])
+AT_CHECK_OUTPUT([foo.y], [%define api.header.include {"./foo.h"}], [-dv -y],
+                [y.output y.tab.c y.tab.h], [],
+                [AT_CHECK([grep '#include "./foo.h"' y.tab.c], [0], [ignore])])
+
+
 AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
                 [foo.output foo.tab.c foo.tab.h])
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.