-*- Autoconf -*- # C M4 Macros for Bison. # Copyright (C) 2002, 2004-2012 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 . ## ---------------- ## ## Identification. ## ## ---------------- ## # b4_comment_(TEXT, OPEN, CONTINUE, END) # ------------------------------------- # Put TEXT in comment. Avoid trailing spaces: don't indent empty lines. # Avoid adding indentation to the first line, as the indentation comes # from OPEN. That's why we don't patsubst([$1], [^\(.\)], [ \1]). # # Prefix all the output lines with PREFIX. m4_define([b4_comment_], [$2[]m4_bpatsubst([$1], [ \(.\)], [ $3\1])$4]) # b4_c_comment(TEXT, [PREFIX]) # ---------------------------- # Put TEXT in comment. Avoid trailing spaces: don't indent empty lines. # Avoid adding indentation to the first line, as the indentation comes # from "/*". That's why we don't patsubst([$1], [^\(.\)], [ \1]). # # Prefix all the output lines with PREFIX. m4_define([b4_c_comment], [b4_comment_([$1], [$2/* ], [$2 ], [$2 */])]) # b4_comment(TEXT, [PREFIX]) # -------------------------- # By default, C comments. m4_define([b4_comment], [b4_c_comment($@)]) # 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])[ /* Using locations. */ #define YYLSP_NEEDED ]b4_locations_if([1], [0])[ ]]) ## ---------------- ## ## Default values. ## ## ---------------- ## # If the %union is not named, its name is YYSTYPE. m4_define_default([b4_union_name], [YYSTYPE]) # If the %name-prefix is not given, it is yy. m4_define_default([b4_prefix], [yy]) ## ------------------------ ## ## Pure/impure interfaces. ## ## ------------------------ ## # b4_user_args # ------------ m4_define([b4_user_args], [m4_ifset([b4_parse_param], [, b4_c_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 the smallest int type able to handle numbers ranging from # MIN to MAX (included). m4_define([b4_int_type], [m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char], b4_ints_in($@, [-128], [127]), [1], [signed char], b4_ints_in($@, [0], [65535]), [1], [unsigned short int], b4_ints_in($@, [-32768], [32767]), [1], [short int], m4_eval([0 <= $1]), [1], [unsigned int], [int])]) # b4_int_type_for(NAME) # --------------------- # Return the smallest 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) # -------------------------------------------- # 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. YYID must be defined as an identity # function that suppresses warnings about constant conditions. m4_define([b4_table_value_equals], [m4_if(m4_eval($3 < m4_indir([b4_]$1[_min]) || m4_indir([b4_]$1[_max]) < $3), [1], [[YYID (0)]], [[((]$2[) == (]$3[))]])]) ## ---------## ## Values. ## ## ---------## # b4_null_define # -------------- # Portability issues: define a YY_NULL appropriate for the current # language (C, C++98, or C++11). m4_define([b4_null_define], [# ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULL nullptr # else # define YY_NULL 0 # endif # endif[]dnl ]) # b4_null # ------- # Return a null pointer constant. m4_define([b4_null], [YY_NULL]) # b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT) # ------------------------------------------------------------- # Define "yy" which contents is CONTENT. m4_define([b4_integral_parser_table_define], [m4_ifvaln([$3], [b4_c_comment([$3], [ ])])dnl static const b4_int_type_for([$2]) yy$1[[]] = { $2 };dnl ]) ## ------------------------- ## ## Assigning token numbers. ## ## ------------------------- ## # b4_token_define(TOKEN-NAME, TOKEN-NUMBER) # ----------------------------------------- # Output the definition of this token as #define. m4_define([b4_token_define], [#define b4_percent_define_get([api.tokens.prefix])$1 $2 ]) # b4_token_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER) # ------------------------------------------------------- # Output the definition of the tokens (if there are) as #defines. m4_define([b4_token_defines], [m4_if([$#$1], [1], [], [/* Tokens. */ m4_map([b4_token_define], [$@])]) ]) # b4_token_enum(TOKEN-NAME, TOKEN-NUMBER) # --------------------------------------- # Output the definition of this token as an enum. m4_define([b4_token_enum], [b4_percent_define_get([api.tokens.prefix])$1 = $2]) # b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER) # ----------------------------------------------------- # Output the definition of the tokens (if there are) as enums. m4_define([b4_token_enums], [m4_if([$#$1], [1], [], [/* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { m4_map_sep([ b4_token_enum], [, ], [$@]) }; #endif ])]) # b4_token_enums_defines(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER) # ------------------------------------------------------------- # 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, [TYPE]) # ---------------------------- # Given a semantic value VAL ($$, $1 etc.), extract its value of type # TYPE if TYPE is given, otherwise just return VAL. The result can be # used safetly, it is put in parens to avoid nasty precedence issues. # TYPE is *not* put in braces, provide some if needed. m4_define([b4_symbol_value], [($1[]m4_ifval([$2], [.$2]))]) ## --------------------------------------------- ## ## Defining C functions in both K&R and ANSI-C. ## ## --------------------------------------------- ## # b4_modern_c # ----------- # A predicate useful in #if to determine whether C is ancient or modern. # # If __STDC__ is defined, the compiler is modern. IBM xlc 7.0 when run # as 'cc' doesn't define __STDC__ (or __STDC_VERSION__) for pedantic # reasons, but it defines __C99__FUNC__ so check that as well. # Microsoft C normally doesn't define these macros, but it defines _MSC_VER. # Consider a C++ compiler to be modern if it defines __cplusplus. # m4_define([b4_c_modern], [[(defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER)]]) # b4_c_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...) # ---------------------------------------------------------- # Declare the function NAME. m4_define([b4_c_function_def], [#if b4_c_modern b4_c_ansi_function_def($@) #else $2 $1 (b4_c_knr_formal_names(m4_shift2($@))) b4_c_knr_formal_decls(m4_shift2($@)) #endif[]dnl ]) # b4_c_ansi_function_def(NAME, RETURN-VALUE, [DECL1, NAME1], ...) # --------------------------------------------------------------- # Declare the function NAME in ANSI. m4_define([b4_c_ansi_function_def], [$2 $1 (b4_c_ansi_formals(m4_shift2($@)))[]dnl ]) # b4_c_ansi_formals([DECL1, NAME1], ...) # -------------------------------------- # Output the arguments ANSI-C definition. m4_define([b4_c_ansi_formals], [m4_if([$#], [0], [void], [$#$1], [1], [void], [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])]) m4_define([b4_c_ansi_formal], [$1]) # b4_c_knr_formal_names([DECL1, NAME1], ...) # ------------------------------------------ # Output the argument names. m4_define([b4_c_knr_formal_names], [m4_map_sep([b4_c_knr_formal_name], [, ], [$@])]) m4_define([b4_c_knr_formal_name], [$2]) # b4_c_knr_formal_decls([DECL1, NAME1], ...) # ------------------------------------------ # Output the K&R argument declarations. m4_define([b4_c_knr_formal_decls], [m4_map_sep([b4_c_knr_formal_decl], [ ], [$@])]) m4_define([b4_c_knr_formal_decl], [ $1;]) ## ------------------------------------------------------------ ## ## Declaring (prototyping) C functions in both K&R and ANSI-C. ## ## ------------------------------------------------------------ ## # b4_c_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...) # ----------------------------------------------------------- # Declare the function NAME. m4_define([b4_c_function_decl], [#if b4_c_modern b4_c_ansi_function_decl($@) #else $2 $1 (); #endif[]dnl ]) # b4_c_ansi_function_decl(NAME, RETURN-VALUE, [DECL1, NAME1], ...) # ---------------------------------------------------------------- # Declare the function NAME. m4_define([b4_c_ansi_function_decl], [$2 $1 (b4_c_ansi_formals(m4_shift2($@)));[]dnl ]) ## --------------------- ## ## Calling C functions. ## ## --------------------- ## # b4_c_function_call(NAME, RETURN-VALUE, [DECL1, NAME1], ...) # ----------------------------------------------------------- # Call the function NAME with arguments NAME1, NAME2 etc. m4_define([b4_c_function_call], [$1 (b4_c_args(m4_shift2($@)))[]dnl ]) # b4_c_args([DECL1, NAME1], ...) # ------------------------------ # Output the arguments NAME1, NAME2... m4_define([b4_c_args], [m4_map_sep([b4_c_arg], [, ], [$@])]) m4_define([b4_c_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@]) break;]) # b4_predicate_case(LABEL, CONDITIONS) # ------------------------------------ m4_define([b4_predicate_case], [ case $1: if (! ($2)) YYERROR; b4_syncline([@oline@], [@ofile@]) break;]) # b4_yydestruct_generate(FUNCTION-DECLARATOR) # ------------------------------------------- # Generate the "yydestruct" function, which declaration is issued using # FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C # or "b4_c_function_def" for K&R. m4_define_default([b4_yydestruct_generate], [[/*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ ]$1([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); switch (yytype) { ]b4_symbol_foreach([b4_symbol_destructor])dnl [ default: break; } }]dnl ]) # b4_yy_symbol_print_generate(FUNCTION-DECLARATOR) # ------------------------------------------------ # Generate the "yy_symbol_print" function, which declaration is issued using # FUNCTION-DECLARATOR, which may be "b4_c_ansi_function_def" for ISO C # or "b4_c_function_def" for K&R. m4_define_default([b4_yy_symbol_print_generate], [[ /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ ]$1([yy_symbol_value_print], [static void], [[FILE *yyoutput], [yyoutput]], [[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 *yyo = yyoutput; ]b4_parse_param_use([yyo], [yylocationp])dnl [ if (!yyvaluep) return;] dnl glr.c does not feature yytoknum. m4_if(b4_skeleton, ["yacc.c"], [[# ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif ]])dnl [ switch (yytype) { ]b4_symbol_foreach([b4_symbol_printer])dnl [ default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ ]$1([yy_symbol_print], [static void], [[FILE *yyoutput], [yyoutput]], [[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]))[ { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); ]b4_locations_if([ YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); ])dnl [ yy_symbol_value_print (yyoutput, yytype, yyvaluep]dnl b4_locations_if([, yylocationp])[]b4_user_args[); YYFPRINTF (yyoutput, ")"); }]dnl ])