blob: 8cabb3f3ac8e0a7dead259cfba3795c9e1dccfea [file]
# -*- Autoconf -*-
# Recursive implementations of M4sugar functions that iterate over $@.
# Copyright (C) 2008-2017, 2020-2026 Free Software Foundation, Inc.
#
# This file is part of Autoconf. 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.
#
# Under Section 7 of GPL version 3, you are granted additional
# permissions described in the Autoconf Configure Script Exception,
# version 3.0, as published by the Free Software Foundation.
#
# You should have received a copy of the GNU General Public License
# and a copy of the Autoconf Configure Script Exception along with
# this program; see the files COPYINGv3 and COPYING.EXCEPTION
# respectively. If not, see <https://www.gnu.org/licenses/>.
# The macros in this file are efficient in GNU M4 1.6 but quadratically
# expensive in GNU M4 1.4. See foreach.m4 for a detailed explanation.
#
# Every macro in this file is also defined in foreach.m4.
# Please take care to keep the implementations in sync.
#
# m4sugar.m4 selects which implementation to use based on the presence
# or absence of the macro __m4_version__, which was introduced in M4 1.6.x.
# _m4_foreach(PRE, POST, IGNORED, ARG...)
# ---------------------------------------
# Form the common basis of the m4_foreach and m4_map macros. For each
# ARG, expand PRE[ARG]POST[]. The IGNORED argument makes recursion
# easier, and must be supplied rather than implicit.
m4_define([_m4_foreach],
[m4_if([$#], [3], [],
[$1[$4]$2[]$0([$1], [$2], m4_shift3($@))])])
# m4_case(SWITCH, VAL1, IF-VAL1, VAL2, IF-VAL2, ..., DEFAULT)
# -----------------------------------------------------------
# Shorthand for m4_if(SWITCH, VAL1, IF-VAL1,
# SWITCH, VAL2, IF-VAL2, ..., DEFAULT).
m4_define([m4_case],
[m4_if([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
[$1], [$2], [$3],
[$0([$1], m4_shift3($@))])])
# m4_bmatch(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
# -----------------------------------------------------
# Match SWITCH against each of the REs. Expand to the VAL
# corresponding to the first RE that matched. (Stops evaluating
# when a match is found.)
m4_define([m4_bmatch],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
[$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
[$#], 2, [$2],
[m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shift3($@))],
[$3])])])
# _m4_cond(TEST1, VAL1, IF-VAL1, TEST2, VAL2, IF-VAL2, ..., [DEFAULT])
# -------------------------------------------------------------------
# Similar to m4_if, except that each TEST is expanded only if no previous
# TESTs matched. This is more efficient when the TESTs are expensive.
#
# Caller guarantees 3*n or 3*n + 1 arguments, 1 <= n.
m4_define([_m4_cond],
[m4_if(($1), [($2)], [$3],
[$#], [3], [],
[$#], [4], [$4],
[$0(m4_shift3($@))])])
# _m4_bpatsubsts(STRING, RE1, SUBST1, RE2, SUBST2, ...)
# ----------------------------------------------------
# m4 equivalent of
#
# $_ = "[$STRING]";
# s/RE1/SUBST1/g;
# s/RE2/SUBST2/g;
# ...
# $_ = substr $_, 1, -1;
#
# m4_bpatsubsts already validated an odd number of arguments.
m4_define([_m4_bpatsubsts],
[m4_if([$#], 2, [$1],
[$0(m4_builtin([patsubst], [[$1]], [$2], [$3]),
m4_shift3($@))])])
# _m4_shiftn(N, ...)
# ------------------
# Returns ... shifted N times. Does not do any validation of N.
#
# Autoconf does not use this macro, because it is inherently slower than
# calling the common cases of m4_shift2 or m4_shift3 directly. But it
# might as well be fast for other clients, such as Libtool. One way to
# do this is to expand $@ only once in _m4_shiftn (otherwise, for long
# lists, the expansion of m4_if takes twice as much memory as what the
# list itself occupies, only to throw away the unused branch). The end
# result is strictly equivalent to
# m4_if([$1], 1, [m4_shift(,m4_shift(m4_shift($@)))],
# [_m4_shiftn(m4_decr([$1]), m4_shift(m4_shift($@)))])
# but with the final 'm4_shift(m4_shift($@)))' shared between the two
# paths. The first leg uses a no-op m4_shift(,$@) to balance out the ().
m4_define([_m4_shiftn],
[m4_if([$1], 1, [m4_shift(],
[$0(m4_decr([$1])]), m4_shift(m4_shift($@)))])
# m4_do(...)
# ----------
# Expands to the expansion of each argument, in sequence, expanding an
# empty quoted string after each one (thus, m4_do([m4_], [fatal([oops])])
# will *not* invoke m4_fatal). Useful for splitting macro definitions
# across many lines for readability.
m4_define([m4_do],
[m4_if([$#], 0, [],
[$#], 1, [$1[]],
[$1[]$0(m4_shift($@))])])
# m4_dquote_elt(ARGS)
# ------------------
# Return ARGS as an unquoted list of double-quoted arguments.
m4_define([m4_dquote_elt],
[m4_if([$#], [0], [],
[$#], [1], [[[$1]]],
[[[$1]],$0(m4_shift($@))])])
# m4_reverse(ARGS)
# ----------------
# Output ARGS in reverse order.
m4_define([m4_reverse],
[m4_if([$#], [0], [], [$#], [1], [[$1]],
[$0(m4_shift($@)), [$1]])])
# m4_map_args_pair(EXPRESSION, [END-EXPR = EXPRESSION], ARG...)
# -------------------------------------------------------------
# Perform a pairwise grouping of consecutive ARGs, by expanding
# EXPRESSION([ARG1], [ARG2]). If there are an odd number of ARGs, the
# final argument is expanded with END-EXPR([ARGn]).
m4_define([m4_map_args_pair],
[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
[$#], [1], [m4_fatal([$0: too few arguments: $#: $1])],
[$#], [2], [],
[$#], [3], [m4_default([$2], [$1])([$3])[]],
[$#], [4], [$1([$3], [$4])[]],
[$1([$3], [$4])[]$0([$1], [$2], m4_shift(m4_shift3($@)))])])
# m4_join(SEP, ARG1, ARG2...)
# ---------------------------
# Produce ARG1SEPARG2...SEPARGn. Avoid back-to-back SEP when a given ARG
# is the empty string. No expansion is performed on SEP or ARGs.
#
#
# Since the number of arguments to join can be arbitrarily long, we
# want to avoid having more than one $@ in the macro definition;
# otherwise, the expansion would require twice the memory of the already
# long list. Hence, m4_join merely looks for the first non-empty element,
# and outputs just that element; while _m4_join looks for all non-empty
# elements, and outputs them following a separator. The final trick to
# note is that we decide between recursing with $0 or _$0 based on the
# nested m4_if ending with '_'.
m4_define([m4_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift2($@))])])
m4_define([_m4_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift2($@))])])
# m4_joinall(SEP, ARG1, ARG2...)
# ------------------------------
# Produce ARG1SEPARG2...SEPARGn. An empty ARG results in back-to-back SEP.
# No expansion is performed on SEP or ARGs.
m4_define([m4_joinall],
[[$2]_$0([$1], m4_shift($@))])
m4_define([_m4_joinall],
[m4_if([$#], [2], [], [[$1$3]$0([$1], m4_shift2($@))])])
# _m4_list_cmp_raw(A, B)
# ----------------------
# Compare the two lists of integer expressions A and B, which are
# safe to expand multiple times.
#
# Rather than face the overhead of m4_case, we use a helper function whose
# expansion includes the name of the macro to invoke on the tail, either
# m4_ignore or m4_unquote. This is particularly useful when comparing
# long lists, since less text is being expanded for deciding when to end
# recursion. The recursion is between a pair of macros that alternate
# which list is trimmed by one element; this is more efficient than
# calling m4_cdr on both lists from a single macro.
m4_define([_m4_list_cmp_raw],
[m4_if([$1], [$2], [0], [_m4_list_cmp_1([$1], $2)])])
m4_define([_m4_list_cmp],
[m4_if([$1], [], [0m4_ignore], [$2], [0], [m4_unquote], [$2m4_ignore])])
m4_define([_m4_list_cmp_1],
[_m4_list_cmp_2([$2], [m4_shift2($@)], $1)])
m4_define([_m4_list_cmp_2],
[_m4_list_cmp([$1$3], m4_cmp([$3+0], [$1+0]))(
[_m4_list_cmp_1(m4_dquote(m4_shift3($@)), $2)])])
# _m4_minmax(METHOD, ARG1, ARG2...)
# ---------------------------------
# Common recursion code for m4_max and m4_min. METHOD must be _m4_max
# or _m4_min, and there must be at least two arguments to combine.
#
# Please keep foreach.m4 in sync with any adjustments made here.
m4_define([_m4_minmax],
[m4_if([$#], [3], [$1([$2], [$3])],
[$0([$1], $1([$2], [$3]), m4_shift3($@))])])
# _m4_set_add_all_clean(SET, VALUE...)
# _m4_set_add_all_check(SET, VALUE...)
# -----------------------------
# Recursion helpers for m4_set_add_all; the check variant is slower
# but handles the case where an element has previously been removed
# but not pruned.
m4_define([_m4_set_add_all_clean],
[m4_if([$#], [2], [],
[_m4_set_add_clean([$1], [$3], [-], [])$0([$1], m4_shift2($@))])])
m4_define([_m4_set_add_all_check],
[m4_if([$#], [2], [],
[_m4_set_add([$1], [$3], [-], [])$0([$1], m4_shift2($@))])])