mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
* data/skeletons/c.m4 (b4_c99_int_type_define): Reorder to put the signed types first, since they’re simpler and this keeps similar code closer. For signed types, don’t bother checking whether the type promotes to int since the type must be signed anyway. For unsigned types, protect a test like ‘UCHAR_MAX <= INT_MAX’ with ‘!defined __UINT_LEAST8_MAX__’, as otherwise the logic is wrong for oddball platforms; and once we do that, there should no need for ‘defined INT_MAX’ so remove that.
970 lines
28 KiB
Plaintext
970 lines
28 KiB
Plaintext
-*- Autoconf -*-
|
|
|
|
# C M4 Macros for Bison.
|
|
|
|
# Copyright (C) 2002, 2004-2015, 2018-2019 Free Software Foundation,
|
|
# Inc.
|
|
|
|
# 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/>.
|
|
|
|
m4_include(b4_skeletonsdir/[c-like.m4])
|
|
|
|
# b4_tocpp(STRING)
|
|
# ----------------
|
|
# Convert STRING into a valid C macro name.
|
|
m4_define([b4_tocpp],
|
|
[m4_toupper(m4_bpatsubst(m4_quote($1), [[^a-zA-Z0-9]+], [_]))])
|
|
|
|
|
|
# b4_cpp_guard(FILE)
|
|
# ------------------
|
|
# A valid C macro name to use as a CPP header guard for FILE.
|
|
m4_define([b4_cpp_guard],
|
|
[[YY_]b4_tocpp(m4_defn([b4_prefix])/[$1])[_INCLUDED]])
|
|
|
|
|
|
# b4_cpp_guard_open(FILE)
|
|
# b4_cpp_guard_close(FILE)
|
|
# ------------------------
|
|
# If FILE does not expand to nothing, open/close CPP inclusion guards for FILE.
|
|
m4_define([b4_cpp_guard_open],
|
|
[m4_ifval(m4_quote($1),
|
|
[#ifndef b4_cpp_guard([$1])
|
|
# define b4_cpp_guard([$1])])])
|
|
|
|
m4_define([b4_cpp_guard_close],
|
|
[m4_ifval(m4_quote($1),
|
|
[#endif b4_comment([!b4_cpp_guard([$1])])])])
|
|
|
|
|
|
## ---------------- ##
|
|
## Identification. ##
|
|
## ---------------- ##
|
|
|
|
# b4_identification
|
|
# -----------------
|
|
# Depends on individual skeletons to define b4_pure_flag, b4_push_flag, or
|
|
# b4_pull_flag if they use the values of the %define variables api.pure or
|
|
# api.push-pull.
|
|
m4_define([b4_identification],
|
|
[[/* Identify Bison output. */
|
|
#define YYBISON 1
|
|
|
|
/* Bison version. */
|
|
#define YYBISON_VERSION "]b4_version["
|
|
|
|
/* Skeleton name. */
|
|
#define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[
|
|
|
|
/* Pure parsers. */
|
|
#define YYPURE ]b4_pure_flag])[]m4_ifdef([b4_push_flag], [[
|
|
|
|
/* Push parsers. */
|
|
#define YYPUSH ]b4_push_flag])[]m4_ifdef([b4_pull_flag], [[
|
|
|
|
/* Pull parsers. */
|
|
#define YYPULL ]b4_pull_flag])[
|
|
]])
|
|
|
|
|
|
## ---------------- ##
|
|
## Default values. ##
|
|
## ---------------- ##
|
|
|
|
# b4_api_prefix, b4_api_PREFIX
|
|
# ----------------------------
|
|
# Corresponds to %define api.prefix
|
|
b4_percent_define_default([[api.prefix]], [[yy]])
|
|
m4_define([b4_api_prefix],
|
|
[b4_percent_define_get([[api.prefix]])])
|
|
m4_define([b4_api_PREFIX],
|
|
[m4_toupper(b4_api_prefix)])
|
|
|
|
|
|
# b4_prefix
|
|
# ---------
|
|
# If the %name-prefix is not given, it is api.prefix.
|
|
m4_define_default([b4_prefix], [b4_api_prefix])
|
|
|
|
# If the %union is not named, its name is YYSTYPE.
|
|
b4_percent_define_default([[api.value.union.name]],
|
|
[b4_api_PREFIX[][STYPE]])
|
|
|
|
|
|
## ------------------------ ##
|
|
## Pure/impure interfaces. ##
|
|
## ------------------------ ##
|
|
|
|
# b4_lex_formals
|
|
# --------------
|
|
# All the yylex formal arguments.
|
|
# b4_lex_param arrives quoted twice, but we want to keep only one level.
|
|
m4_define([b4_lex_formals],
|
|
[b4_pure_if([[[[YYSTYPE *yylvalp]], [[&yylval]]][]dnl
|
|
b4_locations_if([, [[YYLTYPE *yyllocp], [&yylloc]]])])dnl
|
|
m4_ifdef([b4_lex_param], [, ]b4_lex_param)])
|
|
|
|
|
|
# b4_lex
|
|
# ------
|
|
# Call yylex.
|
|
m4_define([b4_lex],
|
|
[b4_function_call([yylex], [int], b4_lex_formals)])
|
|
|
|
|
|
# b4_user_args
|
|
# ------------
|
|
m4_define([b4_user_args],
|
|
[m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])])
|
|
|
|
|
|
# b4_parse_param
|
|
# --------------
|
|
# If defined, b4_parse_param arrives double quoted, but below we prefer
|
|
# it to be single quoted.
|
|
m4_define([b4_parse_param],
|
|
b4_parse_param)
|
|
|
|
|
|
# b4_parse_param_for(DECL, FORMAL, BODY)
|
|
# ---------------------------------------
|
|
# Iterate over the user parameters, binding the declaration to DECL,
|
|
# the formal name to FORMAL, and evaluating the BODY.
|
|
m4_define([b4_parse_param_for],
|
|
[m4_foreach([$1_$2], m4_defn([b4_parse_param]),
|
|
[m4_pushdef([$1], m4_unquote(m4_car($1_$2)))dnl
|
|
m4_pushdef([$2], m4_shift($1_$2))dnl
|
|
$3[]dnl
|
|
m4_popdef([$2])dnl
|
|
m4_popdef([$1])dnl
|
|
])])
|
|
|
|
# b4_parse_param_use([VAL], [LOC])
|
|
# --------------------------------
|
|
# 'YYUSE' VAL, LOC if locations are enabled, and all the parse-params.
|
|
m4_define([b4_parse_param_use],
|
|
[m4_ifvaln([$1], [ YYUSE ([$1]);])dnl
|
|
b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl
|
|
b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal);
|
|
])dnl
|
|
])
|
|
|
|
|
|
## ------------ ##
|
|
## Data Types. ##
|
|
## ------------ ##
|
|
|
|
# b4_int_type(MIN, MAX)
|
|
# ---------------------
|
|
# Return a narrow int type able to handle integers ranging from MIN
|
|
# to MAX (included) in portable C code. Assume MIN and MAX fall in
|
|
# 'int' range.
|
|
m4_define([b4_int_type],
|
|
[m4_if(b4_ints_in($@, [-127], [127]), [1], [signed char],
|
|
b4_ints_in($@, [0], [255]), [1], [unsigned char],
|
|
|
|
b4_ints_in($@, [-32767], [32767]), [1], [short],
|
|
b4_ints_in($@, [0], [65535]), [1], [unsigned short],
|
|
|
|
[int])])
|
|
|
|
# b4_c99_int_type(MIN, MAX)
|
|
# -------------------------
|
|
# Like b4_int_type, but for C99.
|
|
# b4_c99_int_type_define replaces b4_int_type with this.
|
|
m4_define([b4_c99_int_type],
|
|
[m4_if(b4_ints_in($@, [-127], [127]), [1], [yytype_int8],
|
|
b4_ints_in($@, [0], [255]), [1], [yytype_uint8],
|
|
|
|
b4_ints_in($@, [-32767], [32767]), [1], [yytype_int16],
|
|
b4_ints_in($@, [0], [65535]), [1], [yytype_uint16],
|
|
|
|
[int])])
|
|
|
|
# b4_c99_int_type_define
|
|
# ----------------------
|
|
# Define private types suitable for holding small integers in C99 or later.
|
|
m4_define([b4_c99_int_type_define],
|
|
[m4_copy_force([b4_c99_int_type], [b4_int_type])dnl
|
|
[/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
|
|
<limits.h> and (if available) <stdint.h> are included
|
|
so that the code can choose integer types of a good width. */
|
|
|
|
#ifndef __PTRDIFF_MAX__
|
|
# ifndef INT_MAX
|
|
# include <limits.h> /* INFRINGES ON USER NAME SPACE */
|
|
# endif
|
|
# ifndef PTRDIFF_MAX
|
|
# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
|
|
# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/* Narrow types that promote to a signed type and that can represent a
|
|
signed or unsigned integer of at least N bits. In tables they can
|
|
save space and decrease cache pressure. Promoting to a signed type
|
|
helps avoid bugs in integer arithmetic. */
|
|
|
|
#ifdef __INT_LEAST8_MAX__
|
|
typedef __INT_LEAST8_TYPE__ yytype_int8;
|
|
#elif defined INT_LEAST8_MAX
|
|
typedef int_least8_t yytype_int8;
|
|
#else
|
|
typedef signed char yytype_int8;
|
|
#endif
|
|
|
|
#ifdef __INT_LEAST16_MAX__
|
|
typedef __INT_LEAST16_TYPE__ yytype_int16;
|
|
#elif defined INT_LEAST16_MAX
|
|
typedef int_least16_t yytype_int16;
|
|
#else
|
|
typedef short yytype_int16;
|
|
#endif
|
|
|
|
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
|
|
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
|
|
#elif (!defined __UINT_LEAST8_MAX__ && defined UINT_LEAST8_MAX \
|
|
&& UINT_LEAST8_MAX <= INT_MAX)
|
|
typedef uint_least8_t yytype_uint8;
|
|
#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
|
|
typedef unsigned char yytype_uint8;
|
|
#else
|
|
typedef short yytype_uint8;
|
|
#endif
|
|
|
|
#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
|
|
typedef __UINT_LEAST16_TYPE__ yytype_uint16;
|
|
#elif (!defined __UINT_LEAST16_MAX__ && defined UINT_LEAST16_MAX \
|
|
&& UINT_LEAST16_MAX <= INT_MAX)
|
|
typedef uint_least16_t yytype_uint16;
|
|
#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
|
|
typedef unsigned short yytype_uint16;
|
|
#else
|
|
typedef int yytype_uint16;
|
|
#endif]])
|
|
|
|
|
|
# b4_int_type_for(NAME)
|
|
# ---------------------
|
|
# Return a narrow int type able to handle numbers ranging from
|
|
# 'NAME_min' to 'NAME_max' (included).
|
|
m4_define([b4_int_type_for],
|
|
[b4_int_type($1_min, $1_max)])
|
|
|
|
|
|
# b4_table_value_equals(TABLE, VALUE, LITERAL, SYMBOL)
|
|
# ----------------------------------------------------
|
|
# Without inducing a comparison warning from the compiler, check if the
|
|
# literal value LITERAL equals VALUE from table TABLE, which must have
|
|
# TABLE_min and TABLE_max defined. SYMBOL denotes
|
|
m4_define([b4_table_value_equals],
|
|
[m4_if(m4_eval($3 < m4_indir([b4_]$1[_min])
|
|
|| m4_indir([b4_]$1[_max]) < $3), [1],
|
|
[[0]],
|
|
[(($2) == $4)])])
|
|
|
|
|
|
## ----------------- ##
|
|
## Compiler issues. ##
|
|
## ----------------- ##
|
|
|
|
# b4_attribute_define([noreturn])
|
|
# -------------------------------
|
|
# Provide portable compiler "attributes". If "noreturn" is passed, define
|
|
# _Noreturn.
|
|
m4_define([b4_attribute_define],
|
|
[[#ifndef YY_ATTRIBUTE
|
|
# if (defined __GNUC__ \
|
|
&& (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
|
|
|| defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
|
|
# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
|
|
# else
|
|
# define YY_ATTRIBUTE(Spec) /* empty */
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef YY_ATTRIBUTE_PURE
|
|
# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
|
|
#endif
|
|
|
|
#ifndef YY_ATTRIBUTE_UNUSED
|
|
# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
|
|
#endif
|
|
|
|
]m4_bmatch([$1], [\bnoreturn\b], [[/* The _Noreturn keyword of C11. */
|
|
]dnl This is an exact copy of lib/_Noreturn.h.
|
|
[#ifndef _Noreturn
|
|
# if (defined __cplusplus \
|
|
&& ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
|
|
|| (defined _MSC_VER && 1900 <= _MSC_VER)))
|
|
# define _Noreturn [[noreturn]]
|
|
# elif ((!defined __cplusplus || defined __clang__) \
|
|
&& (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
|
|
|| 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
|
|
/* _Noreturn works as-is. */
|
|
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
|
|
# define _Noreturn __attribute__ ((__noreturn__))
|
|
# elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
|
|
# define _Noreturn __declspec (noreturn)
|
|
# else
|
|
# define _Noreturn
|
|
# endif
|
|
#endif
|
|
|
|
]])[/* Suppress unused-variable warnings by "using" E. */
|
|
#if ! defined lint || defined __GNUC__
|
|
# define YYUSE(E) ((void) (E))
|
|
#else
|
|
# define YYUSE(E) /* empty */
|
|
#endif
|
|
|
|
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
|
|
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
|
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
|
|
_Pragma ("GCC diagnostic push") \
|
|
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
|
|
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
|
|
_Pragma ("GCC diagnostic pop")
|
|
#else
|
|
# define YY_INITIAL_VALUE(Value) Value
|
|
#endif
|
|
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
|
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
|
|
#endif
|
|
#ifndef YY_INITIAL_VALUE
|
|
# define YY_INITIAL_VALUE(Value) /* Nothing. */
|
|
#endif
|
|
]])
|
|
|
|
|
|
# b4_null_define
|
|
# --------------
|
|
# Portability issues: define a YY_NULLPTR appropriate for the current
|
|
# language (C, C++98, or C++11).
|
|
#
|
|
# In C++ pre C++11 it is standard practice to use 0 (not NULL) for the
|
|
# null pointer. In C, prefer ((void*)0) to avoid having to include stdlib.h.
|
|
m4_define([b4_null_define],
|
|
[# ifndef YY_NULLPTR
|
|
# if defined __cplusplus
|
|
# if 201103L <= __cplusplus
|
|
# define YY_NULLPTR nullptr
|
|
# else
|
|
# define YY_NULLPTR 0
|
|
# endif
|
|
# else
|
|
# define YY_NULLPTR ((void*)0)
|
|
# endif
|
|
# endif[]dnl
|
|
])
|
|
|
|
|
|
# b4_null
|
|
# -------
|
|
# Return a null pointer constant.
|
|
m4_define([b4_null], [YY_NULLPTR])
|
|
|
|
|
|
|
|
## ---------##
|
|
## Values. ##
|
|
## ---------##
|
|
|
|
# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
|
|
# -------------------------------------------------------------
|
|
# Define "yy<TABLE-NAME>" whose contents is CONTENT.
|
|
m4_define([b4_integral_parser_table_define],
|
|
[m4_ifvaln([$3], [b4_comment([$3], [ ])])dnl
|
|
static const b4_int_type_for([$2]) yy$1[[]] =
|
|
{
|
|
$2
|
|
};dnl
|
|
])
|
|
|
|
|
|
## ------------------------- ##
|
|
## Assigning token numbers. ##
|
|
## ------------------------- ##
|
|
|
|
# b4_token_define(TOKEN-NUM)
|
|
# --------------------------
|
|
# Output the definition of this token as #define.
|
|
m4_define([b4_token_define],
|
|
[b4_token_format([#define %s %s], [$1])])
|
|
|
|
# b4_token_defines
|
|
# ----------------
|
|
# Output the definition of the tokens.
|
|
m4_define([b4_token_defines],
|
|
[b4_any_token_visible_if([/* Tokens. */
|
|
m4_join([
|
|
], b4_symbol_map([b4_token_define]))
|
|
])])
|
|
|
|
|
|
# b4_token_enum(TOKEN-NUM)
|
|
# ------------------------
|
|
# Output the definition of this token as an enum.
|
|
m4_define([b4_token_enum],
|
|
[b4_token_format([%s = %s], [$1])])
|
|
|
|
|
|
# b4_token_enums
|
|
# --------------
|
|
# Output the definition of the tokens (if there are) as enums.
|
|
m4_define([b4_token_enums],
|
|
[b4_any_token_visible_if([[/* Token type. */
|
|
#ifndef ]b4_api_PREFIX[TOKENTYPE
|
|
# define ]b4_api_PREFIX[TOKENTYPE
|
|
enum ]b4_api_prefix[tokentype
|
|
{
|
|
]m4_join([,
|
|
],
|
|
b4_symbol_map([b4_token_enum]))[
|
|
};
|
|
#endif
|
|
]])])
|
|
|
|
|
|
# b4_token_enums_defines
|
|
# ----------------------
|
|
# Output the definition of the tokens (if there are any) as enums and,
|
|
# if POSIX Yacc is enabled, as #defines.
|
|
m4_define([b4_token_enums_defines],
|
|
[b4_token_enums[]b4_yacc_if([b4_token_defines])])
|
|
|
|
|
|
## ----------------- ##
|
|
## Semantic Values. ##
|
|
## ----------------- ##
|
|
|
|
|
|
# b4_symbol_value(VAL, [SYMBOL-NUM], [TYPE-TAG])
|
|
# ----------------------------------------------
|
|
# See README.
|
|
m4_define([b4_symbol_value],
|
|
[m4_ifval([$3],
|
|
[($1.$3)],
|
|
[m4_ifval([$2],
|
|
[b4_symbol_if([$2], [has_type],
|
|
[($1.b4_symbol([$2], [type]))],
|
|
[$1])],
|
|
[$1])])])
|
|
|
|
|
|
## ---------------------- ##
|
|
## Defining C functions. ##
|
|
## ---------------------- ##
|
|
|
|
|
|
# b4_function_define(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
|
|
# -----------------------------------------------------------
|
|
# Declare the function NAME in C.
|
|
m4_define([b4_function_define],
|
|
[$2
|
|
$1 (b4_formals(m4_shift2($@)))[]dnl
|
|
])
|
|
|
|
|
|
# b4_formals([DECL1, NAME1], ...)
|
|
# -------------------------------
|
|
# The formal arguments of a C function definition.
|
|
m4_define([b4_formals],
|
|
[m4_if([$#], [0], [void],
|
|
[$#$1], [1], [void],
|
|
[m4_map_sep([b4_formal], [, ], [$@])])])
|
|
|
|
m4_define([b4_formal],
|
|
[$1])
|
|
|
|
|
|
|
|
## ----------------------- ##
|
|
## Declaring C functions. ##
|
|
## ----------------------- ##
|
|
|
|
|
|
# b4_function_declare(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
|
|
# ------------------------------------------------------------
|
|
# Declare the function NAME.
|
|
m4_define([b4_function_declare],
|
|
[$2 $1 (b4_formals(m4_shift2($@)));[]dnl
|
|
])
|
|
|
|
|
|
|
|
|
|
## --------------------- ##
|
|
## Calling C functions. ##
|
|
## --------------------- ##
|
|
|
|
|
|
# b4_function_call(NAME, RETURN-VALUE, [DECL1, NAME1], ...)
|
|
# -----------------------------------------------------------
|
|
# Call the function NAME with arguments NAME1, NAME2 etc.
|
|
m4_define([b4_function_call],
|
|
[$1 (b4_args(m4_shift2($@)))[]dnl
|
|
])
|
|
|
|
|
|
# b4_args([DECL1, NAME1], ...)
|
|
# ----------------------------
|
|
# Output the arguments NAME1, NAME2...
|
|
m4_define([b4_args],
|
|
[m4_map_sep([b4_arg], [, ], [$@])])
|
|
|
|
m4_define([b4_arg],
|
|
[$2])
|
|
|
|
|
|
## ----------- ##
|
|
## Synclines. ##
|
|
## ----------- ##
|
|
|
|
# b4_sync_start(LINE, FILE)
|
|
# -------------------------
|
|
m4_define([b4_sync_start], [[#]line $1 $2])
|
|
|
|
|
|
## -------------- ##
|
|
## User actions. ##
|
|
## -------------- ##
|
|
|
|
# b4_case(LABEL, STATEMENTS)
|
|
# --------------------------
|
|
m4_define([b4_case],
|
|
[ case $1:
|
|
$2
|
|
b4_syncline([@oline@], [@ofile@])dnl
|
|
break;])
|
|
|
|
|
|
# b4_predicate_case(LABEL, CONDITIONS)
|
|
# ------------------------------------
|
|
m4_define([b4_predicate_case],
|
|
[ case $1:
|
|
if (! (
|
|
$2)) YYERROR;
|
|
b4_syncline([@oline@], [@ofile@])dnl
|
|
break;])
|
|
|
|
|
|
# b4_yydestruct_define
|
|
# --------------------
|
|
# Define the "yydestruct" function.
|
|
m4_define_default([b4_yydestruct_define],
|
|
[[/*-----------------------------------------------.
|
|
| Release the memory associated to this symbol. |
|
|
`-----------------------------------------------*/
|
|
|
|
]b4_function_define([yydestruct],
|
|
[static void],
|
|
[[const char *yymsg], [yymsg]],
|
|
[[int yytype], [yytype]],
|
|
[[YYSTYPE *yyvaluep], [yyvaluep]][]dnl
|
|
b4_locations_if( [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
|
|
m4_ifset([b4_parse_param], [, b4_parse_param]))[
|
|
{
|
|
]b4_parse_param_use([yyvaluep], [yylocationp])dnl
|
|
[ if (!yymsg)
|
|
yymsg = "Deleting";
|
|
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
|
|
|
|
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
|
]b4_symbol_actions([destructor])[
|
|
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
|
}]dnl
|
|
])
|
|
|
|
|
|
# b4_yy_symbol_print_define
|
|
# -------------------------
|
|
# Define the "yy_symbol_print" function.
|
|
m4_define_default([b4_yy_symbol_print_define],
|
|
[[
|
|
/*-----------------------------------.
|
|
| Print this symbol's value on YYO. |
|
|
`-----------------------------------*/
|
|
|
|
]b4_function_define([yy_symbol_value_print],
|
|
[static void],
|
|
[[FILE *yyo], [yyo]],
|
|
[[int yytype], [yytype]],
|
|
[[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
|
|
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
|
|
m4_ifset([b4_parse_param], [, b4_parse_param]))[
|
|
{
|
|
FILE *yyoutput = yyo;
|
|
]b4_parse_param_use([yyoutput], [yylocationp])dnl
|
|
[ if (!yyvaluep)
|
|
return;]
|
|
dnl glr.c does not feature yytoknum.
|
|
m4_if(b4_skeleton, ["yacc.c"],
|
|
[[# ifdef YYPRINT
|
|
if (yytype < YYNTOKENS)
|
|
YYPRINT (yyo, yytoknum[yytype], *yyvaluep);
|
|
# endif
|
|
]])dnl
|
|
b4_percent_code_get([[pre-printer]])dnl
|
|
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
|
b4_symbol_actions([printer])
|
|
YY_IGNORE_MAYBE_UNINITIALIZED_END
|
|
b4_percent_code_get([[post-printer]])dnl
|
|
[}
|
|
|
|
|
|
/*---------------------------.
|
|
| Print this symbol on YYO. |
|
|
`---------------------------*/
|
|
|
|
]b4_function_define([yy_symbol_print],
|
|
[static void],
|
|
[[FILE *yyo], [yyo]],
|
|
[[int yytype], [yytype]],
|
|
[[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
|
|
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
|
|
m4_ifset([b4_parse_param], [, b4_parse_param]))[
|
|
{
|
|
YYFPRINTF (yyo, "%s %s (",
|
|
yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
|
|
|
|
]b4_locations_if([ YY_LOCATION_PRINT (yyo, *yylocationp);
|
|
YYFPRINTF (yyo, ": ");
|
|
])dnl
|
|
[ yy_symbol_value_print (yyo, yytype, yyvaluep]dnl
|
|
b4_locations_if([, yylocationp])[]b4_user_args[);
|
|
YYFPRINTF (yyo, ")");
|
|
}]dnl
|
|
])
|
|
|
|
|
|
## ---------------- ##
|
|
## api.value.type. ##
|
|
## ---------------- ##
|
|
|
|
|
|
# ---------------------- #
|
|
# api.value.type=union. #
|
|
# ---------------------- #
|
|
|
|
# b4_symbol_type_register(SYMBOL-NUM)
|
|
# -----------------------------------
|
|
# Symbol SYMBOL-NUM has a type (for variant) instead of a type-tag.
|
|
# Extend the definition of %union's body (b4_union_members) with a
|
|
# field of that type, and extend the symbol's "type" field to point to
|
|
# the field name, instead of the type name.
|
|
m4_define([b4_symbol_type_register],
|
|
[m4_define([b4_symbol($1, type_tag)],
|
|
[b4_symbol_if([$1], [has_id],
|
|
[b4_symbol([$1], [id])],
|
|
[yytype_[]b4_symbol([$1], [number])])])dnl
|
|
m4_append([b4_union_members],
|
|
m4_expand([
|
|
b4_symbol_tag_comment([$1])dnl
|
|
b4_symbol([$1], [type]) b4_symbol([$1], [type_tag]);]))
|
|
])
|
|
|
|
|
|
# b4_type_define_tag(SYMBOL1-NUM, ...)
|
|
# ------------------------------------
|
|
# For the batch of symbols SYMBOL1-NUM... (which all have the same
|
|
# type), enhance the %union definition for each of them, and set
|
|
# there "type" field to the field tag name, instead of the type name.
|
|
m4_define([b4_type_define_tag],
|
|
[b4_symbol_if([$1], [has_type],
|
|
[m4_map([b4_symbol_type_register], [$@])])
|
|
])
|
|
|
|
|
|
# b4_symbol_value_union(VAL, SYMBOL-NUM, [TYPE])
|
|
# ----------------------------------------------
|
|
# Same of b4_symbol_value, but when api.value.type=union.
|
|
m4_define([b4_symbol_value_union],
|
|
[m4_ifval([$3],
|
|
[(*($3*)(&$1))],
|
|
[m4_ifval([$2],
|
|
[b4_symbol_if([$2], [has_type],
|
|
[($1.b4_symbol([$2], [type_tag]))],
|
|
[$1])],
|
|
[$1])])])
|
|
|
|
|
|
# b4_value_type_setup_union
|
|
# -------------------------
|
|
# Setup support for api.value.type=union. Symbols are defined with a
|
|
# type instead of a union member name: build the corresponding union,
|
|
# and give the symbols their tag.
|
|
m4_define([b4_value_type_setup_union],
|
|
[m4_define([b4_union_members])
|
|
b4_type_foreach([b4_type_define_tag])
|
|
m4_copy_force([b4_symbol_value_union], [b4_symbol_value])
|
|
])
|
|
|
|
|
|
# -------------------------- #
|
|
# api.value.type = variant. #
|
|
# -------------------------- #
|
|
|
|
# b4_value_type_setup_variant
|
|
# ---------------------------
|
|
# Setup support for api.value.type=variant. By default, fail, specialized
|
|
# by other skeletons.
|
|
m4_define([b4_value_type_setup_variant],
|
|
[b4_complain_at(b4_percent_define_get_loc([[api.value.type]]),
|
|
[['%s' does not support '%s']],
|
|
[b4_skeleton],
|
|
[%define api.value.type variant])])
|
|
|
|
|
|
# _b4_value_type_setup_keyword
|
|
# ----------------------------
|
|
# api.value.type is defined with a keyword/string syntax. Check if
|
|
# that is properly defined, and prepare its use.
|
|
m4_define([_b4_value_type_setup_keyword],
|
|
[b4_percent_define_check_values([[[[api.value.type]],
|
|
[[none]],
|
|
[[union]],
|
|
[[union-directive]],
|
|
[[variant]],
|
|
[[yystype]]]])dnl
|
|
m4_case(b4_percent_define_get([[api.value.type]]),
|
|
[union], [b4_value_type_setup_union],
|
|
[variant], [b4_value_type_setup_variant])])
|
|
|
|
|
|
# b4_value_type_setup
|
|
# -------------------
|
|
# Check if api.value.type is properly defined, and possibly prepare
|
|
# its use.
|
|
b4_define_silent([b4_value_type_setup],
|
|
[# Define default value.
|
|
b4_percent_define_ifdef([[api.value.type]], [],
|
|
[# %union => api.value.type=union-directive
|
|
m4_ifdef([b4_union_members],
|
|
[m4_define([b4_percent_define_kind(api.value.type)], [keyword])
|
|
m4_define([b4_percent_define(api.value.type)], [union-directive])],
|
|
[# no tag seen => api.value.type={int}
|
|
m4_if(b4_tag_seen_flag, 0,
|
|
[m4_define([b4_percent_define_kind(api.value.type)], [code])
|
|
m4_define([b4_percent_define(api.value.type)], [int])],
|
|
[# otherwise api.value.type=yystype
|
|
m4_define([b4_percent_define_kind(api.value.type)], [keyword])
|
|
m4_define([b4_percent_define(api.value.type)], [yystype])])])])
|
|
|
|
# Set up.
|
|
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
|
|
[keyword\|string], [_b4_value_type_setup_keyword])
|
|
])
|
|
|
|
|
|
## -------------- ##
|
|
## Declarations. ##
|
|
## -------------- ##
|
|
|
|
|
|
# b4_value_type_define
|
|
# --------------------
|
|
m4_define([b4_value_type_define],
|
|
[b4_value_type_setup[]dnl
|
|
/* Value type. */
|
|
m4_bmatch(b4_percent_define_get_kind([[api.value.type]]),
|
|
[code],
|
|
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
|
typedef ]b4_percent_define_get([[api.value.type]])[ ]b4_api_PREFIX[STYPE;
|
|
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
|
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
|
#endif
|
|
]],
|
|
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
|
|
[union\|union-directive],
|
|
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined ]b4_api_PREFIX[STYPE_IS_DECLARED
|
|
]b4_percent_define_get_syncline([[api.value.union.name]])dnl
|
|
[union ]b4_percent_define_get([[api.value.union.name]])[
|
|
{
|
|
]b4_user_union_members[
|
|
};
|
|
]b4_percent_define_get_syncline([[api.value.union.name]])dnl
|
|
[typedef union ]b4_percent_define_get([[api.value.union.name]])[ ]b4_api_PREFIX[STYPE;
|
|
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
|
|
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
|
|
#endif
|
|
]])])])
|
|
|
|
|
|
# b4_location_type_define
|
|
# -----------------------
|
|
m4_define([b4_location_type_define],
|
|
[[/* Location type. */
|
|
]b4_percent_define_ifdef([[api.location.type]],
|
|
[[typedef ]b4_percent_define_get([[api.location.type]])[ ]b4_api_PREFIX[LTYPE;
|
|
]],
|
|
[[#if ! defined ]b4_api_PREFIX[LTYPE && ! defined ]b4_api_PREFIX[LTYPE_IS_DECLARED
|
|
typedef struct ]b4_api_PREFIX[LTYPE ]b4_api_PREFIX[LTYPE;
|
|
struct ]b4_api_PREFIX[LTYPE
|
|
{
|
|
int first_line;
|
|
int first_column;
|
|
int last_line;
|
|
int last_column;
|
|
};
|
|
# define ]b4_api_PREFIX[LTYPE_IS_DECLARED 1
|
|
# define ]b4_api_PREFIX[LTYPE_IS_TRIVIAL 1
|
|
#endif
|
|
]])])
|
|
|
|
|
|
# b4_declare_yylstype
|
|
# -------------------
|
|
# Declarations that might either go into the header (if --defines) or
|
|
# in the parser body. Declare YYSTYPE/YYLTYPE, and yylval/yylloc.
|
|
m4_define([b4_declare_yylstype],
|
|
[b4_value_type_define[]b4_locations_if([
|
|
b4_location_type_define])
|
|
|
|
b4_pure_if([], [[extern ]b4_api_PREFIX[STYPE ]b4_prefix[lval;
|
|
]b4_locations_if([[extern ]b4_api_PREFIX[LTYPE ]b4_prefix[lloc;]])])[]dnl
|
|
])
|
|
|
|
|
|
# b4_YYDEBUG_define
|
|
# -----------------
|
|
m4_define([b4_YYDEBUG_define],
|
|
[[/* Debug traces. */
|
|
]m4_if(b4_api_prefix, [yy],
|
|
[[#ifndef YYDEBUG
|
|
# define YYDEBUG ]b4_parse_trace_if([1], [0])[
|
|
#endif]],
|
|
[[#ifndef ]b4_api_PREFIX[DEBUG
|
|
# if defined YYDEBUG
|
|
#if YYDEBUG
|
|
# define ]b4_api_PREFIX[DEBUG 1
|
|
# else
|
|
# define ]b4_api_PREFIX[DEBUG 0
|
|
# endif
|
|
# else /* ! defined YYDEBUG */
|
|
# define ]b4_api_PREFIX[DEBUG ]b4_parse_trace_if([1], [0])[
|
|
# endif /* ! defined YYDEBUG */
|
|
#endif /* ! defined ]b4_api_PREFIX[DEBUG */]])[]dnl
|
|
])
|
|
|
|
# b4_declare_yydebug
|
|
# ------------------
|
|
m4_define([b4_declare_yydebug],
|
|
[b4_YYDEBUG_define[
|
|
#if ]b4_api_PREFIX[DEBUG
|
|
extern int ]b4_prefix[debug;
|
|
#endif][]dnl
|
|
])
|
|
|
|
# b4_yylloc_default_define
|
|
# ------------------------
|
|
# Define YYLLOC_DEFAULT.
|
|
m4_define([b4_yylloc_default_define],
|
|
[[/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
|
|
If N is 0, then set CURRENT to the empty location which ends
|
|
the previous symbol: RHS[0] (always defined). */
|
|
|
|
#ifndef YYLLOC_DEFAULT
|
|
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
|
do \
|
|
if (N) \
|
|
{ \
|
|
(Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
|
|
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
|
|
(Current).last_line = YYRHSLOC (Rhs, N).last_line; \
|
|
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \
|
|
} \
|
|
else \
|
|
{ \
|
|
(Current).first_line = (Current).last_line = \
|
|
YYRHSLOC (Rhs, 0).last_line; \
|
|
(Current).first_column = (Current).last_column = \
|
|
YYRHSLOC (Rhs, 0).last_column; \
|
|
} \
|
|
while (0)
|
|
#endif
|
|
]])
|
|
|
|
# b4_yy_location_print_define
|
|
# ---------------------------
|
|
# Define YY_LOCATION_PRINT.
|
|
m4_define([b4_yy_location_print_define],
|
|
[b4_locations_if([[
|
|
/* YY_LOCATION_PRINT -- Print the location on the stream.
|
|
This macro was not mandated originally: define only if we know
|
|
we won't break user code: when these are the locations we know. */
|
|
|
|
#ifndef YY_LOCATION_PRINT
|
|
# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
|
|
|
|
/* Print *YYLOCP on YYO. Private, do not rely on its existence. */
|
|
|
|
YY_ATTRIBUTE_UNUSED
|
|
]b4_function_define([yy_location_print_],
|
|
[static int],
|
|
[[FILE *yyo], [yyo]],
|
|
[[YYLTYPE const * const yylocp], [yylocp]])[
|
|
{
|
|
int res = 0;
|
|
int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
|
|
if (0 <= yylocp->first_line)
|
|
{
|
|
res += YYFPRINTF (yyo, "%d", yylocp->first_line);
|
|
if (0 <= yylocp->first_column)
|
|
res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
|
|
}
|
|
if (0 <= yylocp->last_line)
|
|
{
|
|
if (yylocp->first_line < yylocp->last_line)
|
|
{
|
|
res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
|
|
if (0 <= end_col)
|
|
res += YYFPRINTF (yyo, ".%d", end_col);
|
|
}
|
|
else if (0 <= end_col && yylocp->first_column < end_col)
|
|
res += YYFPRINTF (yyo, "-%d", end_col);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
# define YY_LOCATION_PRINT(File, Loc) \
|
|
yy_location_print_ (File, &(Loc))
|
|
|
|
# else
|
|
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
|
|
# endif
|
|
#endif]],
|
|
[[/* This macro is provided for backward compatibility. */
|
|
#ifndef YY_LOCATION_PRINT
|
|
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
|
|
#endif]])
|
|
])
|
|
|
|
# b4_yyloc_default
|
|
# ----------------
|
|
# Expand to a possible default value for yylloc.
|
|
m4_define([b4_yyloc_default],
|
|
[[
|
|
# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
|
|
= { ]m4_join([, ],
|
|
m4_defn([b4_location_initial_line]),
|
|
m4_defn([b4_location_initial_column]),
|
|
m4_defn([b4_location_initial_line]),
|
|
m4_defn([b4_location_initial_column]))[ }
|
|
# endif
|
|
]])
|