Merge branch 'maint'

* maint:
  c++: shorten the assertions that check whether tokens are correct
  c++: don't glue functions together
  lalr1.cc: YY_ASSERT should use api.prefix
  c++: don't use YY_ASSERT at all if parse.assert is disabled
  c++: style: follow the Bison m4 quoting pattern
  yacc.c: provide the Bison version as an integral macro
  regen
  style: make conversion of version string to int public
  %require: accept version numbers with three parts ("3.7.4")
  yacc.c: fix #definition of YYEMPTY
  gnulib: update
  doc: fix incorrect section title
  doc: minor grammar fixes in counterexamples section
This commit is contained in:
Akim Demaille
2020-11-13 07:01:19 +01:00
21 changed files with 314 additions and 165 deletions

27
NEWS
View File

@@ -54,6 +54,33 @@ GNU Bison NEWS
The Java skeleton (lalr1.java) now supports LAC, via the %define variable The Java skeleton (lalr1.java) now supports LAC, via the %define variable
parse.lac. parse.lac.
* Noteworthy changes in release ?.? (????-??-??) [?]
** Bug fixes
*** Bug fixes in yacc.c
In Yacc mode, all the tokens are defined twice: once as an enum, and then
as a macro. YYEMPTY was missing its macro.
*** Bug fixes in lalr1.cc
The lalr1.cc skeleton used to emit internal assertions (using YY_ASSERT)
even when the `parse.assert` %define variable is not enabled. It no
longer does.
The private internal macro YY_ASSERT now obeys the `api.prefix` %define
variable.
When there is a very large number of tokens, some assertions could be long
enough to hit arbitrary limits in Visual C++. They have been rewritten to
work around this limitation.
** Changes
The YYBISON macro in generated "regular C parsers" (from the "yacc.c"
skeleton) used to be defined to 1. It is now defined to the version of
Bison as an integer (e.g., 30704 for version 3.7.4).
* Noteworthy changes in release 3.7.3 (2020-10-13) [stable] * Noteworthy changes in release 3.7.3 (2020-10-13) [stable]

View File

@@ -49,7 +49,7 @@ m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))])
# b4_generated_by # b4_generated_by
# --------------- # ---------------
m4_define([b4_generated_by], m4_define([b4_generated_by],
[b4_comment([A Bison parser, made by GNU Bison b4_version.]) [b4_comment([A Bison parser, made by GNU Bison b4_version_string.])
]) ])
# b4_copyright(TITLE, [YEARS]) # b4_copyright(TITLE, [YEARS])
@@ -651,11 +651,11 @@ m4_define([_b4_type_action],
])]) ])])
# b4_type_foreach(MACRO) # b4_type_foreach(MACRO, [SEP])
# ---------------------- # -----------------------------
# Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set. # Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set.
m4_define([b4_type_foreach], m4_define([b4_type_foreach],
[m4_map([$1], m4_defn([b4_type_names]))]) [m4_map_sep([$1], [$2], m4_defn([b4_type_names]))])

View File

@@ -320,8 +320,9 @@ m4_define([b4_symbol_type_define],
/// Copy constructor. /// Copy constructor.
basic_symbol (const basic_symbol& that);]b4_variant_if([[ basic_symbol (const basic_symbol& that);]b4_variant_if([[
/// Constructor for valueless symbols, and symbols from each type. /// Constructors for typed symbols.
]b4_type_foreach([b4_basic_symbol_constructor_define])], [[ ]b4_type_foreach([b4_basic_symbol_constructor_define], [
])], [[
/// Constructor for valueless symbols. /// Constructor for valueless symbols.
basic_symbol (typename Base::kind_type t]b4_locations_if([, basic_symbol (typename Base::kind_type t]b4_locations_if([,
YY_MOVE_REF (location_type) l])[); YY_MOVE_REF (location_type) l])[);

View File

@@ -58,11 +58,11 @@ m4_define([b4_cpp_guard_close],
# b4_pull_flag if they use the values of the %define variables api.pure or # b4_pull_flag if they use the values of the %define variables api.pure or
# api.push-pull. # api.push-pull.
m4_define([b4_identification], m4_define([b4_identification],
[[/* Identify Bison output. */ [[/* Identify Bison output, and Bison version. */
#define YYBISON 1 #define YYBISON ]b4_version[
/* Bison version. */ /* Bison version string. */
#define YYBISON_VERSION "]b4_version[" #define YYBISON_VERSION "]b4_version_string["
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[ #define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
@@ -520,10 +520,11 @@ m4_define([b4_token_define],
# ---------------- # ----------------
# Output the definition of the tokens. # Output the definition of the tokens.
m4_define([b4_token_defines], m4_define([b4_token_defines],
[b4_any_token_visible_if([/* Token kinds. */ [[/* Token kinds. */
m4_join([ #define ]b4_symbol([-2], [id])[ -2
]m4_join([
], b4_symbol_map([b4_token_define])) ], b4_symbol_map([b4_token_define]))
])]) ])
# b4_token_enum(TOKEN-NUM) # b4_token_enum(TOKEN-NUM)

View File

@@ -122,12 +122,12 @@ m4_define([b4_location_type_if],
# b4_identification # b4_identification
# ----------------- # -----------------
m4_define([b4_identification], m4_define([b4_identification],
[/** Version number for the Bison executable that generated this parser. */ [[/** Version number for the Bison executable that generated this parser. */
public static immutable string yy_bison_version = "b4_version"; public static immutable string yy_bison_version = "]b4_version_string[";
/** Name of the skeleton that generated this parser. */ /** Name of the skeleton that generated this parser. */
public static immutable string yy_bison_skeleton = b4_skeleton; public static immutable string yy_bison_skeleton = ]b4_skeleton[;
]) ]])
## ------------ ## ## ------------ ##

View File

@@ -71,12 +71,12 @@ m4_define([b4_lexer_if],
# b4_identification # b4_identification
# ----------------- # -----------------
m4_define([b4_identification], m4_define([b4_identification],
[ /** Version number for the Bison executable that generated this parser. */ [[ /** Version number for the Bison executable that generated this parser. */
public static final String bisonVersion = "b4_version"; public static final String bisonVersion = "]b4_version_string[";
/** Name of the skeleton that generated this parser. */ /** Name of the skeleton that generated this parser. */
public static final String bisonSkeleton = b4_skeleton; public static final String bisonSkeleton = ]b4_skeleton[;
]) ]])
## ------------ ## ## ------------ ##

View File

@@ -22,8 +22,8 @@ m4_pushdef([b4_copyright_years],
# b4_position_file # b4_position_file
# ---------------- # ----------------
# Name of the file containing the position class, if we want this file. # Name of the file containing the position class, if we want this file.
b4_header_if([b4_required_version_if([302], [], b4_header_if([b4_required_version_if([30200], [],
[m4_define([b4_position_file], [position.hh])])])]) [m4_define([b4_position_file], [position.hh])])])])
# b4_location_file # b4_location_file

View File

@@ -19,8 +19,8 @@
# b4_stack_file # b4_stack_file
# ------------- # -------------
# Name of the file containing the stack class, if we want this file. # Name of the file containing the stack class, if we want this file.
b4_header_if([b4_required_version_if([302], [], b4_header_if([b4_required_version_if([30200], [],
[m4_define([b4_stack_file], [stack.hh])])]) [m4_define([b4_stack_file], [stack.hh])])])
# b4_stack_define # b4_stack_define

View File

@@ -20,6 +20,13 @@
## variant. ## ## variant. ##
## --------- ## ## --------- ##
# b4_assert
# ---------
# The name of YY_ASSERT.
m4_define([b4_assert],
[b4_api_PREFIX[]_ASSERT])
# b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS]) # b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS])
# ------------------------------------------------ # ------------------------------------------------
# Run some ACTION ("build", or "destroy") on YYVAL of symbol type # Run some ACTION ("build", or "destroy") on YYVAL of symbol type
@@ -71,12 +78,12 @@ m4_map([ b4_symbol_tag_comment], [$@])dnl
# ------------------- # -------------------
# The needed includes for variants support. # The needed includes for variants support.
m4_define([b4_variant_includes], m4_define([b4_variant_includes],
[b4_parse_assert_if([[#include <typeinfo>]])[ [b4_parse_assert_if([[#include <typeinfo>
#ifndef YY_ASSERT #ifndef ]b4_assert[
# include <cassert> # include <cassert>
# define YY_ASSERT assert # define ]b4_assert[ assert
#endif #endif
]]) ]])])
@@ -110,8 +117,8 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([ semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([
: yytypeid_ (&typeid (T))])[ : yytypeid_ (&typeid (T))])[
{ {]b4_parse_assert_if([[
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);]])[
new (yyas_<T> ()) T (YY_MOVE (t)); new (yyas_<T> ()) T (YY_MOVE (t));
} }
@@ -125,7 +132,7 @@ m4_define([b4_value_type_declare],
/// Destruction, allowed only if empty. /// Destruction, allowed only if empty.
~semantic_type () YY_NOEXCEPT ~semantic_type () YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
])[} ])[}
# if 201103L <= YY_CPLUSPLUS # if 201103L <= YY_CPLUSPLUS
@@ -133,10 +140,10 @@ m4_define([b4_value_type_declare],
template <typename T, typename... U> template <typename T, typename... U>
T& T&
emplace (U&&... u) emplace (U&&... u)
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (std::forward <U>(u)...); return *new (yyas_<T> ()) T (std::forward <U>(u)...);
} }
# else # else
@@ -144,10 +151,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
emplace () emplace ()
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (); return *new (yyas_<T> ()) T ();
} }
@@ -155,10 +162,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
emplace (const T& t) emplace (const T& t)
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (!yytypeid_); ]b4_assert[ (!yytypeid_);
YY_ASSERT (sizeof (T) <= size); ]b4_assert[ (sizeof (T) <= size);
yytypeid_ = & typeid (T);])[ yytypeid_ = & typeid (T);]])[
return *new (yyas_<T> ()) T (t); return *new (yyas_<T> ()) T (t);
} }
# endif # endif
@@ -185,10 +192,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
T& T&
as () YY_NOEXCEPT as () YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == typeid (T)); ]b4_assert[ (*yytypeid_ == typeid (T));
YY_ASSERT (sizeof (T) <= size);])[ ]b4_assert[ (sizeof (T) <= size);]])[
return *yyas_<T> (); return *yyas_<T> ();
} }
@@ -196,10 +203,10 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
const T& const T&
as () const YY_NOEXCEPT as () const YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == typeid (T)); ]b4_assert[ (*yytypeid_ == typeid (T));
YY_ASSERT (sizeof (T) <= size);])[ ]b4_assert[ (sizeof (T) <= size);]])[
return *yyas_<T> (); return *yyas_<T> ();
} }
@@ -214,9 +221,9 @@ m4_define([b4_value_type_declare],
template <typename T> template <typename T>
void void
swap (self_type& that) YY_NOEXCEPT swap (self_type& that) YY_NOEXCEPT
{]b4_parse_assert_if([ {]b4_parse_assert_if([[
YY_ASSERT (yytypeid_); ]b4_assert[ (yytypeid_);
YY_ASSERT (*yytypeid_ == *that.yytypeid_);])[ ]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[
std::swap (as<T> (), that.as<T> ()); std::swap (as<T> (), that.as<T> ());
} }
@@ -388,11 +395,67 @@ m4_define([_b4_token_maker_define],
])]) ])])
m4_define([_b4_type_clause], # b4_token_kind(SYMBOL-NUM)
[b4_symbol_if([$1], [is_token], # -------------------------
[b4_symbol_if([$1], [has_id], # Some tokens don't have an ID.
[tok == token::b4_symbol([$1], [id])], m4_define([b4_token_kind],
[tok == b4_symbol([$1], [code])])])]) [b4_symbol_if([$1], [has_id],
[token::b4_symbol([$1], [id])],
[b4_symbol([$1], [code])])])
# _b4_tok_in(SYMBOL-NUM, ...)
# ---------------------------
# See b4_tok_in below. The SYMBOL-NUMs... are tokens only.
#
# We iterate over the tokens to group them by "range" of token numbers (not
# symbols numbers!).
#
# b4_fst is the start of that range.
# b4_prev is the previous value.
# b4_val is the current value.
# If b4_val is the successor of b4_prev in token numbers, update the latter,
# otherwise emit the code for range b4_fst .. b4_prev.
# $1 is also used as a terminator in the foreach, but it will not be printed.
#
m4_define([_b4_tok_in],
[m4_pushdef([b4_prev], [$1])dnl
m4_pushdef([b4_fst], [$1])dnl
m4_pushdef([b4_sep], [])dnl
m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)),
[m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [],
[b4_sep[]m4_if(b4_fst, b4_prev,
[tok == b4_token_kind(b4_fst)],
[(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl
m4_define([b4_fst], b4_val)dnl
m4_define([b4_sep], [
|| ])])dnl
m4_define([b4_prev], b4_val)])dnl
m4_popdef([b4_sep])dnl
m4_popdef([b4_fst])dnl
m4_popdef([b4_prev])dnl
])
# _b4_filter_tokens(SYMBOL-NUM, ...)
# ----------------------------------
# Expand as the list of tokens amongst SYMBOL-NUM.
m4_define([_b4_filter_tokens],
[m4_pushdef([b4_sep])dnl
m4_foreach([b4_val], [$@],
[b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl
m4_popdef([b4_sep])dnl
])
# b4_tok_in(SYMBOL-NUM, ...)
# ---------------------------
# A C++ conditional that checks that `tok` is a member of this list of symbol
# numbers.
m4_define([b4_tok_in],
[_$0(_b4_filter_tokens($@))])
# _b4_token_constructor_define(SYMBOL-NUM...) # _b4_token_constructor_define(SYMBOL-NUM...)
@@ -410,9 +473,6 @@ m4_define([_b4_token_constructor_define],
: super_type(]b4_join([token_type (tok)], : super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [std::move (v)]), b4_symbol_if([$1], [has_type], [std::move (v)]),
b4_locations_if([std::move (l)]))[) b4_locations_if([std::move (l)]))[)
{
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#else #else
symbol_type (]b4_join( symbol_type (]b4_join(
[int tok], [int tok],
@@ -422,10 +482,10 @@ m4_define([_b4_token_constructor_define],
: super_type(]b4_join([token_type (tok)], : super_type(]b4_join([token_type (tok)],
b4_symbol_if([$1], [has_type], [v]), b4_symbol_if([$1], [has_type], [v]),
b4_locations_if([l]))[) b4_locations_if([l]))[)
{
YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[);
}
#endif #endif
{]b4_parse_assert_if([[
]b4_assert[ (]b4_tok_in($@)[);
]])[}
]])]) ]])])

View File

@@ -15837,6 +15837,12 @@ Macro to discard a value from the parser stack and fake a lookahead
token. @xref{Action Features}. token. @xref{Action Features}.
@end deffn @end deffn
@deffn {Macro} YYBISON
The version of Bison as an integer, for instance 30704 for version 3.7.4.
Defined in @file{yacc.c} only. Before version 3.7.4, @code{YYBISON} was
defined to 1.
@end deffn
@deffn {Variable} yychar @deffn {Variable} yychar
External integer variable that contains the integer value of the External integer variable that contains the integer value of the
lookahead token. (In a pure parser, it is a local variable within lookahead token. (In a pure parser, it is a local variable within

2
gnulib

Submodule gnulib updated: 160d5e7d9a...839ed059f4

View File

@@ -103,6 +103,8 @@ src_bison_SOURCES = \
src/state.h \ src/state.h \
src/state-item.c \ src/state-item.c \
src/state-item.h \ src/state-item.h \
src/strversion.c \
src/strversion.h \
src/symlist.c \ src/symlist.c \
src/symlist.h \ src/symlist.h \
src/symtab.c \ src/symtab.c \

View File

@@ -127,9 +127,6 @@ muscle_init (void)
muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle, muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
hash_compare_muscles, muscle_entry_free); hash_compare_muscles, muscle_entry_free);
/* Version and input file. */
MUSCLE_INSERT_STRING ("version", VERSION);
} }

View File

@@ -42,6 +42,7 @@
#include "scan-skel.h" #include "scan-skel.h"
#include "symtab.h" #include "symtab.h"
#include "tables.h" #include "tables.h"
#include "strversion.h"
static struct obstack format_obstack; static struct obstack format_obstack;
@@ -829,6 +830,9 @@ prepare (void)
char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL"); char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
/* Versions. */
MUSCLE_INSERT_STRING ("version_string", VERSION);
MUSCLE_INSERT_INT ("version", strversion_to_int (VERSION));
MUSCLE_INSERT_INT ("required_version", required_version); MUSCLE_INSERT_INT ("required_version", required_version);
/* Flags. */ /* Flags. */

View File

@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.7.2.67-44c6. */ /* A Bison parser, made by GNU Bison 3.7.3.118-d0ea7-dirty. */
/* Bison implementation for Yacc-like parsers in C /* Bison implementation for Yacc-like parsers in C
@@ -45,11 +45,11 @@
define necessary library symbols; they are noted "INFRINGES ON define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */ USER NAME SPACE" below. */
/* Identify Bison output. */ /* Identify Bison output, and Bison version. */
#define YYBISON 1 #define YYBISON 30703
/* Bison version. */ /* Bison version string. */
#define YYBISON_VERSION "3.7.2.67-44c6" #define YYBISON_VERSION "3.7.3.118-d0ea7-dirty"
/* Skeleton name. */ /* Skeleton name. */
#define YYSKELETON_NAME "yacc.c" #define YYSKELETON_NAME "yacc.c"
@@ -220,8 +220,6 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
#include "system.h" #include "system.h"
#include <c-ctype.h> #include <c-ctype.h>
#include <errno.h>
#include <intprops.h>
#include <quotearg.h> #include <quotearg.h>
#include <vasnprintf.h> #include <vasnprintf.h>
#include <xmemdup0.h> #include <xmemdup0.h>
@@ -235,6 +233,7 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
#include "reader.h" #include "reader.h"
#include "scan-code.h" #include "scan-code.h"
#include "scan-gram.h" #include "scan-gram.h"
#include "strversion.h"
/* Pretend to be at least that version, to check features published /* Pretend to be at least that version, to check features published
in that version while developping it. */ in that version while developping it. */
@@ -647,19 +646,19 @@ union yyalloc
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] = static const yytype_int16 yyrline[] =
{ {
0, 311, 311, 320, 321, 325, 326, 332, 336, 341, 0, 310, 310, 319, 320, 324, 325, 331, 335, 340,
342, 343, 344, 345, 346, 351, 356, 357, 358, 359, 341, 342, 343, 344, 345, 350, 355, 356, 357, 358,
360, 361, 361, 362, 363, 364, 365, 366, 367, 368, 359, 360, 360, 361, 362, 363, 364, 365, 366, 367,
369, 373, 374, 383, 384, 388, 399, 403, 407, 415, 368, 372, 373, 382, 383, 387, 398, 402, 406, 414,
425, 426, 436, 437, 443, 456, 456, 461, 461, 466, 424, 425, 435, 436, 442, 455, 455, 460, 460, 465,
466, 471, 481, 482, 483, 484, 489, 490, 494, 495, 465, 470, 480, 481, 482, 483, 488, 489, 493, 494,
500, 501, 505, 506, 510, 511, 512, 525, 534, 538, 499, 500, 504, 505, 509, 510, 511, 524, 533, 537,
542, 550, 551, 555, 568, 569, 574, 575, 576, 594, 541, 549, 550, 554, 567, 568, 573, 574, 575, 593,
598, 602, 610, 612, 617, 624, 634, 638, 642, 650, 597, 601, 609, 611, 616, 623, 633, 637, 641, 649,
656, 669, 670, 676, 677, 678, 685, 685, 693, 694, 655, 668, 669, 675, 676, 677, 684, 684, 692, 693,
695, 700, 703, 705, 707, 709, 711, 713, 715, 717, 694, 699, 702, 704, 706, 708, 710, 712, 714, 716,
719, 724, 725, 734, 758, 759, 760, 761, 773, 775, 718, 723, 724, 733, 757, 758, 759, 760, 772, 774,
799, 804, 805, 810, 818, 819 798, 803, 804, 809, 817, 818
}; };
#endif #endif
@@ -3063,41 +3062,11 @@ handle_pure_parser (location const *loc, char const *directive)
} }
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
errors.
Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0": 300. */
static int
str_to_version (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 100, &res))
return -1;
++cp;
char *cp1 = NULL;
long minor = strtol (cp, &cp1, 10);
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|| ! (0 <= minor && minor < 100)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
IGNORE_TYPE_LIMITS_END
return res;
}
static void static void
handle_require (location const *loc, char const *version_quoted) handle_require (location const *loc, char const *version_quoted)
{ {
char *version = unquote (version_quoted); char *version = unquote (version_quoted);
required_version = str_to_version (version); required_version = strversion_to_int (version);
if (required_version == -1) if (required_version == -1)
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),

View File

@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.7.2.67-44c6. */ /* A Bison parser, made by GNU Bison 3.7.3.118-d0ea7-dirty. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C

View File

@@ -42,8 +42,6 @@
#include "system.h" #include "system.h"
#include <c-ctype.h> #include <c-ctype.h>
#include <errno.h>
#include <intprops.h>
#include <quotearg.h> #include <quotearg.h>
#include <vasnprintf.h> #include <vasnprintf.h>
#include <xmemdup0.h> #include <xmemdup0.h>
@@ -57,6 +55,7 @@
#include "reader.h" #include "reader.h"
#include "scan-code.h" #include "scan-code.h"
#include "scan-gram.h" #include "scan-gram.h"
#include "strversion.h"
/* Pretend to be at least that version, to check features published /* Pretend to be at least that version, to check features published
in that version while developping it. */ in that version while developping it. */
@@ -1053,41 +1052,11 @@ handle_pure_parser (location const *loc, char const *directive)
} }
/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on
errors.
Changes of behavior are only on minor version changes, so "3.0.5"
is the same as "3.0": 300. */
static int
str_to_version (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 100, &res))
return -1;
++cp;
char *cp1 = NULL;
long minor = strtol (cp, &cp1, 10);
if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.')
|| ! (0 <= minor && minor < 100)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
IGNORE_TYPE_LIMITS_END
return res;
}
static void static void
handle_require (location const *loc, char const *version_quoted) handle_require (location const *loc, char const *version_quoted)
{ {
char *version = unquote (version_quoted); char *version = unquote (version_quoted);
required_version = str_to_version (version); required_version = strversion_to_int (version);
if (required_version == -1) if (required_version == -1)
{ {
complain (loc, complaint, _("invalid version requirement: %s"), complain (loc, complaint, _("invalid version requirement: %s"),

67
src/strversion.c Normal file
View File

@@ -0,0 +1,67 @@
/* Convert version string to int.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
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 3 of the License, 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/>. */
#include <config.h>
#include "system.h"
#include "strversion.h"
#include <errno.h>
#include <intprops.h>
int
strversion_to_int (char const *version)
{
IGNORE_TYPE_LIMITS_BEGIN
int res = 0;
errno = 0;
char *cp = NULL;
{
long major = strtol (version, &cp, 10);
if (errno || cp == version || *cp != '.' || major < 0
|| INT_MULTIPLY_WRAPV (major, 10000, &res))
return -1;
}
{
++cp;
char *prev = cp;
long minor = strtol (cp, &cp, 10);
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|| ! (0 <= minor && minor < 100)
|| INT_MULTIPLY_WRAPV (minor, 100, &minor)
|| INT_ADD_WRAPV (minor, res, &res))
return -1;
}
if (*cp == '.')
{
++cp;
char *prev = cp;
long micro = strtol (cp, &cp, 10);
if (errno || cp == prev || (*cp != '\0' && *cp != '.')
|| ! (0 <= micro && micro < 100)
|| INT_ADD_WRAPV (micro, res, &res))
return -1;
}
IGNORE_TYPE_LIMITS_END
return res;
}

28
src/strversion.h Normal file
View File

@@ -0,0 +1,28 @@
/* Convert version string to int.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
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 3 of the License, 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/>. */
#ifndef STRVERSION_H_
# define STRVERSION_H_
/* Convert VERSION into an int (MAJOR * 10000 + MINOR * 100 + MICRO).
E.g., "3.7.4" => 30704, "3.8" => 30800.
Return -1 on errors. */
int strversion_to_int (char const *version);
#endif

View File

@@ -203,17 +203,20 @@ AT_SETUP([Several parsers])
# Generate and compile to *.o. Make sure there is no (allowed) YY* # Generate and compile to *.o. Make sure there is no (allowed) YY*
# nor yy* identifiers in the header after applying api.prefix. Check # nor yy* identifiers in the header after applying api.prefix. Check
# that headers can be compiled by a C++ compiler. # that headers can be compiled by a C++ compiler.
#
# They should all use parse.assert to make sure that we don't even
# conflict of YY_ASSERT.
m4_pushdef([AT_TEST], m4_pushdef([AT_TEST],
[AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} $2]) [AT_BISON_OPTION_PUSHDEFS([%define api.prefix {$1_} %define parse.assert $2])
AT_DATA_GRAMMAR([$1.y], AT_DATA_GRAMMAR([$1.y],
[[%define api.prefix {$1_} [[%define api.prefix {$1_}
%define parse.assert
$2 $2
%define parse.error verbose %define parse.error verbose
%union ]AT_VARIANT_IF([],
{ [%union {int integer;}])[
int integer;
} %code {
%{
#include <stdio.h> /* printf. */ #include <stdio.h> /* printf. */
]AT_PUSH_IF([[ ]AT_PUSH_IF([[
#if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__) #if defined __GNUC__ && (7 == __GNUC__ || 9 == __GNUC__)
@@ -222,8 +225,10 @@ $2
]])[ ]])[
]AT_YYERROR_DECLARE[ ]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[ ]AT_YYLEX_DECLARE[
%} }
%% %%
exp: exp:
'x' '1' { printf ("x1\n"); } 'x' '1' { printf ("x1\n"); }
| 'x' '2' { printf ("x2\n"); } | 'x' '2' { printf ("x2\n"); }
@@ -234,9 +239,12 @@ exp:
| 'x' '7' { printf ("x7\n"); } | 'x' '7' { printf ("x7\n"); }
| 'x' '8' { printf ("x8\n"); } | 'x' '8' { printf ("x8\n"); }
| 'x' '9' { printf ("x9\n"); } | 'x' '9' { printf ("x9\n"); }
| 'x' 'a' { printf ("xa\n"); }
| 'x' 'b' { printf ("xb\n"); }
; ;
%% %%
]AT_YYERROR_DEFINE[ ]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE(["$1"])[ ]AT_YYLEX_DEFINE(["$1"])[
]]) ]])
@@ -269,6 +277,8 @@ extern "C"
#endif #endif
#include "x5.hh" #include "x5.hh"
#include "x9.hh" #include "x9.hh"
#include "xa.hh"
#include "xb.hh"
#define RUN(S) \ #define RUN(S) \
do { \ do { \
@@ -291,6 +301,10 @@ main (void)
RUN(x8_parse()); RUN(x8_parse());
x9_::parser p9; x9_::parser p9;
RUN(p9.parse()); RUN(p9.parse());
xa_::parser pa;
RUN(pa.parse());
xb_::parser pb;
RUN(pb.parse());
return 0; return 0;
} }
]])# main.cc ]])# main.cc
@@ -303,7 +317,9 @@ AT_TEST([x5], [%locations %debug %language "c++"])
AT_TEST([x6], [%define api.pure]) AT_TEST([x6], [%define api.pure])
AT_TEST([x7], [%define api.push-pull both]) AT_TEST([x7], [%define api.push-pull both])
AT_TEST([x8], [%define api.pure %define api.push-pull both]) AT_TEST([x8], [%define api.pure %define api.push-pull both])
AT_TEST([x9], [%locations %code requires {#include "location.hh"} %define api.location.type {x5_::location} %debug %language "c++"]) AT_TEST([x9], [%locations %code requires {#include "location.hh"} %define api.location.type {::x5_::location} %debug %language "c++"])
AT_TEST([xa], [%locations %code requires {#include "location.hh"} %define api.location.type {::x5_::location} %language "c++" %define api.value.type variant])
AT_TEST([xb], [%locations %define api.location.file none %language "c++" %define api.value.type variant])
#AT_TEST([x5], [%locations %language "c++" %glr-parser]) #AT_TEST([x5], [%locations %language "c++" %glr-parser])
# Check that api.prefix works properly: # Check that api.prefix works properly:
@@ -339,6 +355,8 @@ AT_PERL_CHECK([[-n -0777 -e '
|YY_NULLPTR |YY_NULLPTR
|YY_RVREF |YY_RVREF
|YY_\w+_INCLUDED |YY_\w+_INCLUDED
|FILE\ \*yyo # Function argument.
|const\ yylocp # Function argument.
)\b}{}gx; )\b}{}gx;
while (/^(.*YY.*)$/gm) while (/^(.*YY.*)$/gm)
{ {
@@ -356,7 +374,7 @@ AT_PERL_CHECK([[-n -0777 -e '
# Do this late, so that other checks have been performed. # Do this late, so that other checks have been performed.
AT_SKIP_IF_CANNOT_LINK_C_AND_CXX AT_SKIP_IF_CANNOT_LINK_C_AND_CXX
AT_COMPILE_CXX([parser], [[x[1-9].o -DCC_IS_CXX=$CC_IS_CXX main.cc]]) AT_COMPILE_CXX([parser], [[x[1-9a-b].o -DCC_IS_CXX=$CC_IS_CXX main.cc]])
AT_PARSER_CHECK([parser], [0], [[expout]]) AT_PARSER_CHECK([parser], [0], [[expout]])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])

View File

@@ -366,7 +366,7 @@ AT_TOKEN_CTOR_IF(
[m4_pushdef([AT_LOC], [[(]AT_NAME_PREFIX[lloc)]]) [m4_pushdef([AT_LOC], [[(]AT_NAME_PREFIX[lloc)]])
m4_pushdef([AT_VAL], [[(]AT_NAME_PREFIX[lval)]]) m4_pushdef([AT_VAL], [[(]AT_NAME_PREFIX[lval)]])
m4_pushdef([AT_YYLEX_FORMALS], []) m4_pushdef([AT_YYLEX_FORMALS], [])
m4_pushdef([AT_YYLEX_RETURN], [yy::parser::symbol_type]) m4_pushdef([AT_YYLEX_RETURN], [AT_NAMESPACE::parser::symbol_type])
m4_pushdef([AT_YYLEX_ARGS], []) m4_pushdef([AT_YYLEX_ARGS], [])
m4_pushdef([AT_USE_LEX_ARGS], []) m4_pushdef([AT_USE_LEX_ARGS], [])
m4_pushdef([AT_YYLEX_PRE_FORMALS], []) m4_pushdef([AT_YYLEX_PRE_FORMALS], [])