multistart: start more thorough testing

Akim Demaille <[email protected]>
Newsgroups gmane.comp.parsers.bison.patches
Message-ID <[email protected]>
Check multistart in calc.at.  That's the best place to test this across skeletons.

commit 9b18cac96bdad4a71b546a3c16ca4b7e25c0a657
Author: Akim Demaille <[email protected]>
Date:   Sun Sep 27 13:07:57 2020 +0200

    multistart: start more thorough testing
    
    * tests/local.at (AT_MULTISTART_IF): New.
    * tests/calc.at: Adjust to check multiple start symbols.
    * data/skeletons/yacc.c (yy_parse_impl): Fix.

diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 62f9f93c..c9d8161d 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -2182,7 +2182,8 @@ yypushreturn:]], [[
 ]b4_parse_error_bmatch([detailed\|verbose],
 [[  if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);]])[]m4_ifdef([b4_start_symbols], [[
-  yyimpl->yynerrs = yynerrs;]])[
+  if (yyimpl)
+    yyimpl->yynerrs = yynerrs;]])[
   return yyresult;
 }
 ]b4_push_if([b4_parse_state_variable_macros([b4_macro_undef])])[
diff --git a/tests/calc.at b/tests/calc.at
index 0da2bbeb..e44000a2 100644
--- a/tests/calc.at
+++ b/tests/calc.at
@@ -57,6 +57,8 @@ AT_LANG_DISPATCH([$0], $@)])
 # AT_CALC_MAIN(c).
 m4_define([AT_CALC_MAIN(c)],
 [[#include <assert.h>
+#include <stdlib.h> /* exit */
+#include <string.h> /* strcmp */
 #include <unistd.h>
 
 ]AT_CXX_IF([[
@@ -82,6 +84,18 @@ int global_count = 0;
 /* Total number of errors.  */
 int global_nerrs = 0;
 
+static FILE *
+open_file (const char *file)
+{
+  FILE *res = (file && *file && strcmp (file, "-")) ? fopen (file, "r") : stdin;
+  if (!res)
+    {
+      perror (file);
+      exit (3);
+    }
+  return res;
+}
+
 /* A C main function.  */
 int
 main (int argc, const char **argv)
@@ -89,7 +103,7 @@ main (int argc, const char **argv)
   semantic_value result = 0;
   int count = 0;
   int nerrs = 0;]])[
-  int status;
+  int status = 0;
 
   /* This used to be alarm (10), but that isn't enough time for a July
      1995 vintage DEC Alphastation 200 4/100 system, according to
@@ -98,21 +112,43 @@ main (int argc, const char **argv)
 
   alarm (200);
 
-  if (argc == 2)
-    input = fopen (argv[1], "r");
-  else
-    input = stdin;
-
-  if (!input)
-    {
-      perror (argv[1]);
-      return 3;
-    }
-
 ]AT_CXX_IF([], [AT_DEBUG_IF([  ]AT_NAME_PREFIX[debug = 1;])])[
-  status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
-  if (fclose (input))
-    perror ("fclose");]AT_PARAM_IF([[
+
+  {
+    int i;
+    for (i = 1; i < argc; ++i)
+      {
+]AT_MULTISTART_IF([[
+        if (!strcmp (argv[i], "--exp") && i+1 < argc)
+          {
+            input = open_file (argv[i+1]);
+            ignore_eol = 1;
+            ]AT_NAME_PREFIX[parse_exp_t res = ]AT_NAME_PREFIX[parse_exp ();
+            printf ("exp => %d (status: %d, errors: %d)\n",
+                    res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
+            status = res.yystatus;
+            ++i;
+          }
+        else if (!strcmp (argv[i], "--num") && i+1 < argc)
+          {
+            input = open_file (argv[i+1]);
+            ignore_eol = 1;
+            ]AT_NAME_PREFIX[parse_NUM_t res = ]AT_NAME_PREFIX[parse_NUM ();
+            printf ("NUM => %d (status: %d, errors: %d)\n",
+                    res.yystatus == 0 ? res.yyvalue : 0, res.yystatus, res.yynerrs);
+            status = res.yystatus;
+            ++i;
+          }
+        else]])[
+          {
+            input = open_file (argv[i]);
+            status = ]AT_NAME_PREFIX[parse (]AT_PARAM_IF([[&result, &count, &nerrs]])[);
+          }
+        if (input != stdin && fclose (input))
+          perror ("fclose");
+      }
+  }
+]AT_PARAM_IF([[
   assert (global_result == result); (void) result;
   assert (global_count  == count);  (void) count;
   assert (global_nerrs  == nerrs);  (void) nerrs;
@@ -196,13 +232,15 @@ read_integer (]AT_YYLEX_FORMALS[)
       AT_LOC_FIRST_LINE   = AT_LOC_LAST_LINE;
 ])[
     }
-  while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
+  while ((c = get_char (]AT_YYLEX_ARGS[)) == ' '
+         || c == '\t'
+         || (ignore_eol && c == '\n'));
 
   /* Process numbers.   */
   if (isdigit (c))
     {
       unget_char (]AT_YYLEX_PRE_ARGS[ c);
-      ]AT_VAL[.ival = read_integer (]AT_YYLEX_ARGS[);
+      ]AT_VAL[.]AT_VALUE_UNION_IF([NUM], [ival])[ = read_integer (]AT_YYLEX_ARGS[);
       return ]AT_CXX_IF([AT_NAMESPACE::parser::token::])[]AT_TOKEN_PREFIX[NUM;
     }
 
@@ -268,19 +306,22 @@ void location_print (FILE *o, Span s);
   typedef int semantic_value;
 }
 
-/* Exercise %union. */
+]AT_VALUE_UNION_IF([],
+[[/* Exercise %union. */
 %union
 {
   semantic_value ival;
-};
+};]])[
 %printer { ]AT_CXX_IF([[yyo << $$]],
-                      [[fprintf (yyo, "%d", $$)]])[; } <ival>;
+                      [[fprintf (yyo, "%d", $$)]])[; } <]AT_VALUE_UNION_IF([int], [ival])[>;
 
 %code provides
 {
   #include <stdio.h>
   /* The input.  */
   extern FILE *input;
+  /* Whether \n is a blank.  */
+  extern int ignore_eol;
   extern semantic_value global_result;
   extern int global_count;
   extern int global_nerrs;
@@ -293,6 +334,7 @@ void location_print (FILE *o, Span s);
   #define USE(Var)
 
   FILE *input;
+  int ignore_eol = 0;
   static int power (int base, int exponent);
 
   ]AT_YYERROR_DECLARE[
@@ -323,8 +365,8 @@ void location_print (FILE *o, Span s);
 
 /* Bison Declarations */
 %token CALC_EOF 0 ]AT_TOKEN_TRANSLATE_IF([_("end of input")], ["end of input"])[
-%token <ival> NUM   "number"
-%type  <ival> exp
+%token <]AT_VALUE_UNION_IF([int], [ival])[> NUM   "number"
+%type  <]AT_VALUE_UNION_IF([int], [ival])[> exp
 
 %nonassoc '='   /* comparison          */
 %left '-' '+'
@@ -654,7 +696,7 @@ input:
 
 line:
   EOL
-| exp EOL            { ]AT_PARAM_IF([*result = global_result = $1;], [USE ($1);])[ }
+| exp EOL            { ]AT_PARAM_IF([*result = global_result = $1;])[ }
 ;
 
 exp:
@@ -678,7 +720,7 @@ exp:
 | "-" exp  %prec NEG { $$ = -$2; }
 | exp "^" exp        { $$ = power ($1, $3); }
 | "(" exp ")"        { $$ = $2; }
-| "(" error ")"      { $$ = 1111; yyerrok; }
+| "(" error ")"      { $$ = 1111; }
 | "!"                { $$ = 0; return YYERROR; }
 | "-" error          { $$ = 0; return YYERROR; }
 ;
@@ -889,8 +931,8 @@ m4_define([AT_DATA_CALC_Y],
 ])
 
 
-# _AT_CHECK_CALC(BISON-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
-# ------------------------------------------------------------------
+# _AT_CHECK_CALC(CALC-OPTIONS, INPUT, [STDOUT], [NUM-STDERR-LINES])
+# -----------------------------------------------------------------
 # Run 'calc' on INPUT and expect no STDOUT nor STDERR.
 #
 # If BISON-OPTIONS contains '%debug' but not '%glr-parser', then
@@ -907,8 +949,8 @@ m4_define([_AT_CHECK_CALC],
 [$2
 ])
 AT_JAVA_IF(
-  [AT_JAVA_PARSER_CHECK([Calc < input], 0, [AT_PARAM_IF([m4_n([$3])])], [stderr])],
-  [AT_PARSER_CHECK([calc input],        0, [AT_PARAM_IF([m4_n([$3])])], [stderr])])
+  [AT_JAVA_PARSER_CHECK([Calc $1 < input], 0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])],
+  [AT_PARSER_CHECK([calc $1 input],        0, [m4_ifvaln(m4_quote($3), [$3])], [stderr])])
 AT_LANG_MATCH([c\|c++\|java],
   [AT_GLR_IF([],
     [AT_CHECK([grep -c -v 'Return for a new token:' stderr],
@@ -921,6 +963,7 @@ AT_LANG_MATCH([c\|c++\|java],
 #                      $4 = [STDOUT],
 #                      $5 = [NUM-STDERR-LINES],
 #                      $6 = [CUSTOM-ERROR-MESSAGE])
+#                      $7 = [CALC-OPTIONS])
 # ----------------------------------------------------------------------
 # Run 'calc' on INPUT, and expect a 'syntax error' message.
 #
@@ -937,14 +980,14 @@ AT_LANG_MATCH([c\|c++\|java],
 m4_define([_AT_CHECK_CALC_ERROR],
 [m4_bmatch([$3], [^/],
   [AT_JAVA_IF(
-    [AT_JAVA_PARSER_CHECK([Calc < $3], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
-    [AT_PARSER_CHECK([calc $3],        $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])],
+    [AT_JAVA_PARSER_CHECK([Calc $7 < $3], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
+    [AT_PARSER_CHECK([calc $7 $3],        $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])],
   [AT_DATA([[input]],
 [[$3
 ]])
   AT_JAVA_IF(
-    [AT_JAVA_PARSER_CHECK([Calc < input], $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])],
-    [AT_PARSER_CHECK([calc input],        $2, [AT_PARAM_IF([m4_n([$4])])], [stderr])])
+    [AT_JAVA_PARSER_CHECK([Calc $7 < input], $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])],
+    [AT_PARSER_CHECK([calc $7 input],        $2, [m4_ifvaln(m4_quote($4), [$4])], [stderr])])
 ])
 
 # Normalize the observed and expected error messages, depending upon the
@@ -1063,7 +1106,7 @@ AT_CHECK_SPACES([AT_JAVA_IF([Calc], [calc]).AT_LANG_EXT AT_HEADER_IF([AT_JAVA_IF
 # Test the precedences.
 # The Java traces do not show the clean up sequence at the end,
 # since it does not support %destructor.
-_AT_CHECK_CALC([$1],
+_AT_CHECK_CALC([],
 [[1 + 2 * 3 = 7
 1 + 2 * -3 = -5
 
@@ -1077,24 +1120,24 @@ _AT_CHECK_CALC([$1],
 
 2^2^3 = 256
 (2^2)^3 = 64]],
-[[final: 64 12 0]],
+[AT_PARAM_IF([final: 64 12 0])],
                [AT_JAVA_IF([1014], [1017])])
 
 # Some syntax errors.
 _AT_CHECK_CALC_ERROR([$1], [1], [1 2],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [15],
                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [1//2],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [20],
                      [AT_JAVA_IF([1.3-1.4], [1.3])[: syntax error on token ['/'] (expected: [number] ['-'] ['('] ['!'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [error],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [5],
                      [AT_JAVA_IF([1.1-1.2], [1.1])[: syntax error on token [invalid token] (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
 _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [30],
                      [AT_LAC_IF(
                        [AT_JAVA_IF([1.7-1.8], [1.7])[: syntax error on token ['='] (expected: ['-'] ['+'] ['*'] ['/'] ['^'] ['\n'])]],
@@ -1102,12 +1145,12 @@ _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3],
 _AT_CHECK_CALC_ERROR([$1], [1],
                      [
 +1],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [20],
                      [AT_JAVA_IF([2.1-2.2], [2.1])[: syntax error on token ['+'] (expected: ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ [number] ['-'] ['\n'] ['('] ['!'])]])
 # Exercise error messages with EOF: work on an empty file.
 _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
-                     [[final: 0 0 1]],
+                     [AT_PARAM_IF([final: 0 0 1])],
                      [4],
                      [[1.1: syntax error on token ]AT_TOKEN_TRANSLATE_IF([[[end of file]]], [[[end of input]]])[ (expected: [number] ['-'] ['\n'] ['('] ['!'])]])
 
@@ -1129,7 +1172,7 @@ _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null],
 #
 _AT_CHECK_CALC_ERROR([$1], [0],
                      [() + (1 + 1 + 1 +) + (* * *) + (1 * 2 * *) = 1],
-                     [[final: 4444 0 5]],
+                     [AT_PARAM_IF([final: 4444 0 5])],
                      [250],
 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
 ]AT_JAVA_IF([1.18-1.19], [1.18])[: syntax error on token [')'] (expected: [number] ['-'] ['('] ['!'])
@@ -1140,13 +1183,13 @@ _AT_CHECK_CALC_ERROR([$1], [0],
 # The same, but this time exercising explicitly triggered syntax errors.
 # POSIX says the lookahead causing the error should not be discarded.
 _AT_CHECK_CALC_ERROR([$1], [0], [(!) + (1 2) = 1],
-                     [[final: 2222 0 2]],
+                     [AT_PARAM_IF([final: 2222 0 2])],
                      [102],
 [AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
 ]AT_JAVA_IF([1.1-1.16], [1.1-15])[: error: 2222 != 1]])
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
-                     [[final: 2222 0 3]],
+                     [AT_PARAM_IF([final: 2222 0 3])],
                      [113],
 [AT_JAVA_IF([1.4-1.5], [1.4])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
 ]AT_JAVA_IF([1.12-1.13], [1.12])[: syntax error on token [number] (expected: ['='] ['-'] ['+'] ['*'] ['/'] ['^'] [')'])
@@ -1155,7 +1198,7 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(- *) + (1 2) = 1],
 # Check that yyerrok works properly: second error is not reported,
 # third and fourth are.  Parse status is successful.
 _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
-                     [[final: 3333 0 3]],
+                     [AT_PARAM_IF([final: 3333 0 3])],
                      [113],
 [AT_JAVA_IF([1.2-1.3], [1.2])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
 ]AT_JAVA_IF([1.10-1.11], [1.10])[: syntax error on token ['*'] (expected: [number] ['-'] ['('] ['!'])
@@ -1168,31 +1211,48 @@ _AT_CHECK_CALC_ERROR([$1], [0], [(* *) + (*) + (*)],
 # error-recovery without issuing a second error message.
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(#) + (#) = 2222],
-                     [[final: 2222 0 0]],
+                     [AT_PARAM_IF([final: 2222 0 0])],
                      [102],
 [[1.2: syntax error: invalid character: '#'
 1.8: syntax error: invalid character: '#']])
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + #) = 1111],
-                     [[final: 1111 0 0]],
+                     [AT_PARAM_IF([final: 1111 0 0])],
                      [102],
 [[1.6: syntax error: invalid character: '#']])
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(# + 1) = 1111],
-                     [[final: 1111 0 0]],
+                     [AT_PARAM_IF([final: 1111 0 0])],
                      [102],
 [[1.2: syntax error: invalid character: '#']])
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + # + 1) = 1111],
-                     [[final: 1111 0 0]],
+                     [AT_PARAM_IF([final: 1111 0 0])],
                      [102],
 [[1.6: syntax error: invalid character: '#']])
 
 _AT_CHECK_CALC_ERROR([$1], [0], [(1 + 1) / (1 - 1)],
-                     [[final: 2 0 1]],
+                     [AT_PARAM_IF([final: 2 0 1])],
                      [102],
 [AT_JAVA_IF([1.11-1.18], [1.11-17])[: error: null divisor]])
 
+# Multiple start symbols.
+AT_MULTISTART_IF([
+_AT_CHECK_CALC([--num], [[123]],
+               [[NUM => 123 (status: 0, errors: 0)]],
+               [AT_JAVA_IF([1014], [1017])])
+_AT_CHECK_CALC_ERROR([$1], [1], [1 + 2 * 3],
+                     [NUM => 0 (status: 1, errors: 1)],
+                     [102],
+                     [[1.3: syntax error, unexpected '+', expecting end of file]],
+                     [--num])
+
+_AT_CHECK_CALC([--exp], [[1 + 2 * 3]],
+               [[exp => 7 (status: 0, errors: 0)]],
+               [AT_JAVA_IF([1014], [1017])])
+])
+
+
 AT_BISON_OPTION_POPDEFS
 
 AT_CLEANUP
@@ -1246,13 +1306,18 @@ AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error detailed %deb
 AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error verbose %debug %locations %header %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
 AT_CHECK_CALC_LALR([%no-lines %define api.pure %define parse.error verbose %debug %locations %defines %define api.prefix {calc} %verbose %yacc %parse-param {semantic_value *result}{int *count}{int *nerrs}])
 
-
+# parse.error custom.
 AT_CHECK_CALC_LALR([%define parse.error custom])
 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc}])
 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs}])
 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs} %define api.push-pull both %define api.pure full])
 AT_CHECK_CALC_LALR([%define parse.error custom %locations %define api.prefix {calc} %parse-param {semantic_value *result}{int *count}{int *nerrs} %define api.push-pull both %define api.pure full %define parse.lac full])
 
+# multistart.
+AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union])
+AT_CHECK_CALC_LALR([%start input exp NUM %define api.value.type union %locations %define parse.error detailed])
+
+
 # ---------------- #
 # GLR Calculator.  #
 # ---------------- #
diff --git a/tests/local.at b/tests/local.at
index e07f0e51..b18bdf3b 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -222,6 +222,7 @@ m4_pushdef([AT_ERROR_VERBOSE_IF],
            [m4_bmatch([$3], [%define parse\.error verbose], [$1], [$2])])
 m4_pushdef([AT_ERROR_SIMPLE_IF],
            [AT_ERROR_CUSTOM_IF([$2], [AT_ERROR_DETAILED_IF([$2], [AT_ERROR_VERBOSE_IF([$2], [$1])], [$1])], [$1])])
+
 m4_pushdef([AT_CXX_IF],
 [m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])])
 m4_pushdef([AT_D_IF],
@@ -236,6 +237,7 @@ m4_pushdef([AT_LANG],
                                 [c])])])])
 m4_pushdef([AT_C_IF],
 [m4_if(AT_LANG, [c], [$1], [$2])])
+
 m4_pushdef([AT_GLR_IF],
 [m4_bmatch([$3], [%glr-parser\|%skeleton "glr.*"], [$1], [$2])])
 m4_pushdef([AT_LALR1_CC_IF],
@@ -245,6 +247,8 @@ m4_pushdef([AT_GLR_CC_IF],
 # Using yacc.c?
 m4_pushdef([AT_YACC_IF],
 [m4_bmatch([$3], [%language\|%glr-parser\|%skeleton], [$2], [$1])])
+
+
 m4_pushdef([AT_LAC_IF],
 [m4_bmatch([$3], [%define parse.lac full], [$1], [$2])])
 m4_pushdef([AT_LEXPARAM_IF],
@@ -256,6 +260,8 @@ m4_pushdef([AT_LOCATION_IF],
 # sure we can use a user type).
 m4_pushdef([AT_LOCATION_TYPE_SPAN_IF],
 [m4_bmatch([$3], [%define \(api\.location\.type\|location_type\) \{Span\}], [$1], [$2])])
+m4_pushdef([AT_MULTISTART_IF],
+[m4_bmatch([$3], [%start [_a-zA-Z]+ [_a-zA-Z]+], [$1], [$2])])
 m4_pushdef([AT_PARAM_IF],
 [m4_bmatch([$3], [%parse-param], [$1], [$2])])
 
@@ -281,6 +287,11 @@ m4_pushdef([AT_PURE_IF],
            [$2])])
 m4_pushdef([AT_PUSH_IF],
 [m4_bmatch([$3], [%define api.push-pull \(both\|pull\)], [$1], [$2])])
+# Whether we use %define api.value.type union
+m4_pushdef([AT_VALUE_UNION_IF],
+[m4_bmatch([$3], [%define api\.value\.type union], [$1], [$2])])
+
+
 # AT_NAME_PREFIX.
 m4_pushdef([AT_NAME_PREFIX],
 [m4_bmatch([$3], [\(%define api\.prefix\|%name-prefix\) .*],
@@ -395,6 +406,7 @@ AT_LOCATION_TYPE_SPAN_IF(
 
 AT_GLR_IF([AT_KEYWORDS([glr])])
 AT_PUSH_IF([AT_KEYWORDS([push])])
+AT_MULTISTART_IF([AT_KEYWORDS([multistart])])
 ])# _AT_BISON_OPTION_PUSHDEFS
 
 
@@ -428,10 +440,12 @@ m4_popdef([AT_NAME_PREFIX])
 m4_popdef([AT_LOCATION_TYPE_SPAN_IF])
 m4_popdef([AT_LOCATION_IF])
 m4_undefine([AT_PARSE_PARAMS])
+m4_popdef([AT_VALUE_UNION_IF])
 m4_popdef([AT_PUSH_IF])
 m4_popdef([AT_PURE_IF])
 m4_popdef([AT_PARSER_CLASS])
 m4_popdef([AT_PARAM_IF])
+m4_popdef([AT_MULTISTART_IF])
 m4_popdef([AT_LEXPARAM_IF])
 m4_popdef([AT_LAC_IF])
 m4_popdef([AT_YACC_IF])
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.