diff options
Diffstat (limited to '')
-rw-r--r-- | m4/Makefile.in | 186 | ||||
-rw-r--r-- | m4/atconfig.m4 | 16 | ||||
-rw-r--r-- | m4/init.m4 | 37 | ||||
-rw-r--r-- | m4/m4.m4 | 17 | ||||
-rw-r--r-- | m4/missing.m4 | 70 | ||||
-rw-r--r-- | m4/sanity.m4 | 42 | ||||
-rw-r--r-- | m4sh.m4 | 731 | ||||
-rw-r--r-- | m4sugar.m4 | 1741 |
8 files changed, 2840 insertions, 0 deletions
diff --git a/m4/Makefile.in b/m4/Makefile.in new file mode 100644 index 0000000..c699503 --- /dev/null +++ b/m4/Makefile.in @@ -0,0 +1,186 @@ +# Copyright 2010-2012,2023 Thomas E. Dickey +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +EXPR = @EXPR@ +HELP2MAN = @HELP2MAN@ +M4 = @M4@ +PACKAGE = @PACKAGE@ +PACKAGE_NAME = @PACKAGE_NAME@ +PERL = @PERL@ +PERLSCRIPTS = @PERLSCRIPTS@ +VERSION = @VERSION@ + +EXTRA_DIST = \ +atconfig.m4 \ +init.m4 \ +m4.m4 \ +missing.m4 \ +sanity.m4 + +subdir = m4 +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && \ + CONFIG_HEADERS= CONFIG_LINKS= \ + CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status +uninstall-info-am: +tags: TAGS +TAGS: + + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + mkdir -p "$(distdir)/$$dir"; \ + fi; \ + if test -d $$d/$$file; then \ + cp -pR $$d/$$file $(distdir) \ + || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/m4/atconfig.m4 b/m4/atconfig.m4 new file mode 100644 index 0000000..79c7c72 --- /dev/null +++ b/m4/atconfig.m4 @@ -0,0 +1,16 @@ +## ----------------------## -*- Autoconf -*- +## Prepare for testing. ## +## ----------------------## + +#serial 3 + +# AT_CONFIG([AUTOTEST-PATH = .]) +# ------------------------------ +# Configure the test suite. +# +# AUTOTEST-PATH must help the test suite to find the executables, i.e., +# if the test suite is in `tests/' and the executables are in `src/', +# pass `../src'. If there are also executables in the source tree, use +# `../src:$top_srcdir/src'. +AC_DEFUN([AT_CONFIG], +[AC_SUBST([AUTOTEST_PATH], [m4_default([$1], [.])])]) diff --git a/m4/init.m4 b/m4/init.m4 new file mode 100644 index 0000000..22d9592 --- /dev/null +++ b/m4/init.m4 @@ -0,0 +1,37 @@ +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])]) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +# +ac_prog_editor=`echo $program_transform_name| sed -e 's/\\$\\$/$/g'` +# +ac_prog_actual=`echo autoconf|sed -e $ac_prog_editor` +AM_MISSING_PROG(AUTOCONF, $ac_prog_actual, $missing_dir) +# +ac_prog_actual=`echo autoheader|sed -e $ac_prog_editor` +AM_MISSING_PROG(AUTOHEADER, $ac_prog_actual, $missing_dir) +# +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) diff --git a/m4/m4.m4 b/m4/m4.m4 new file mode 100644 index 0000000..e48d690 --- /dev/null +++ b/m4/m4.m4 @@ -0,0 +1,17 @@ +# AC_PROG_GNU_M4 +# -------------- +# Check for GNU m4, at least 1.3 (supports frozen files). +AC_DEFUN([AC_PROG_GNU_M4], +[AC_PATH_PROGS(M4, gm4 gnum4 m4, m4) +AC_CACHE_CHECK(version of $M4, ac_cv_m4_version, +[ + ac_cv_m4_version=`$M4 --version | head -n 1 | sed -E -e 's/^.*[[ ]]([[1-9]][[0-9]]*\.)/\1/g' -e 's/[[^0-9.]]*$//' 2>/dev/null` + test -z "$ac_cv_m4_version" && ac_cv_m4_version=unknown +]) +AC_CACHE_CHECK(whether $M4 supports frozen files, ac_cv_prog_gnu_m4, +[ac_cv_prog_gnu_m4=no +if test x"$M4" != x; then + case `$M4 --help < /dev/null 2>&1` in + *reload-state*) ac_cv_prog_gnu_m4=yes ;; + esac +fi])]) diff --git a/m4/missing.m4 b/m4/missing.m4 new file mode 100644 index 0000000..091570d --- /dev/null +++ b/m4/missing.m4 @@ -0,0 +1,70 @@ +## --------------------------------------------------------- ## +## Fake the existence of programs that GNU maintainers use. ## +## --------------------------------------------------------- ## + +# serial 2 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_INSTALL_SH +# --------------------- +# Like AM_MISSING_PROG, but only looks for install-sh. +AC_DEFUN([AM_MISSING_INSTALL_SH], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +if test -z "$install_sh"; then + for install_sh in "$ac_aux_dir/install-sh" \ + "$ac_aux_dir/install.sh" \ + "${am_missing_run}${ac_auxdir}/install-sh"; + do + test -f "$install_sh" && break + done +fi +AC_SUBST(install_sh)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[test x"${MISSING+set}" = xset || + MISSING="\${SHELL} `CDPATH=:; cd $ac_aux_dir && pwd`/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + am_backtick='`' + AC_MSG_WARN([${am_backtick}missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to ${srcdir}/foo. In other projects, it is set to `.'. +# Of course, Automake must honor this variable whenever it call a tool +# from the auxiliary directory. The problem is that $srcdir (hence +# $ac_aux_dir) can be either an absolute path or a path relative to +# $top_srcdir or absolute, this depends on how configure is run. This +# is pretty annoying since it makes $ac_aux_dir quite unusable in +# subdirectories: on the top source directory, any form will work +# fine, but in subdirectories relative pat needs to be adapted. +# - calling $top_srcidr/$ac_aux_dir/missing would success if $srcdir is +# relative, but fail if $srcdir is absolute +# - conversely, calling $ax_aux_dir/missing would fail if $srcdir is +# absolute, and success on relative paths. +# +# Consequently, we define and use $am_aux_dir, the "always absolute" +# version of $ac_aux_dir. + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`CDPATH=:; cd $ac_aux_dir && pwd` +]) diff --git a/m4/sanity.m4 b/m4/sanity.m4 new file mode 100644 index 0000000..5cb5f27 --- /dev/null +++ b/m4/sanity.m4 @@ -0,0 +1,42 @@ +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + if test "[$]*" != "X $srcdir/configure conftest.file" \ + && test "[$]*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT([yes])]) @@ -0,0 +1,731 @@ +include(m4sugar.m4)# -*- Autoconf -*- +# This file is part of Autoconf. +# M4 sugar for common shell constructs. +# Requires GNU M4 and M4sugar. +#------------------------------------------------------------------------------ +# Copyright 2020-2021,2022 Thomas E. Dickey +# Copyright 2000, 2001 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the Free Software Foundation gives unlimited +# permission to copy, distribute and modify the configure scripts that +# are the output of Autoconf. You need not follow the terms of the GNU +# General Public License when using or distributing such scripts, even +# though portions of the text of Autoconf appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the Autoconf program. +# +# Certain portions of the Autoconf source text are designed to be copied +# (in certain cases, depending on the input) into the output of +# Autoconf. We call these the "data" portions. The rest of the Autoconf +# source text consists of comments plus executable code that decides which +# of the data portions to output in any given case. We call these +# comments and executable code the "non-data" portions. Autoconf never +# copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of Autoconf +# released by the Free Software Foundation. When you make and +# distribute a modified version of Autoconf, you may extend this special +# exception to the GPL to apply to your modified version as well, *unless* +# your modified version has the potential to copy into its output some +# of the text that was the non-data portion of the version that you started +# with. (In other words, unless your change moves or copies text from +# the non-data portions to the data portions.) If your modification has +# such potential, you must delete any notice of this special exception +# to the GPL from your modified version. +# +# Written by Akim Demaille, Pavel Roskin, Alexandre Oliva, Lars J. Aas +# and many other people. + + +## ------------------------- ## +## 1. Sanitizing the shell. ## +## ------------------------- ## + +# AS_SHELL_SANITIZE +# ----------------- +# Try to be as Bourne and/or POSIX as possible. +m4_defun([AS_SHELL_SANITIZE], +[# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Name of the executable. +dnl Moved here because the tests below can use AC_MSG_ERROR, which uses $as_me +as_me=`AS_BASENAME($[0])` + +_AS_EXPR_PREPARE +_AS_LN_S_PREPARE +_AS_TEST_PREPARE +_AS_UNSET_PREPARE +_AS_TR_PREPARE + +# NLS nuisances. +AS_UNSET([LANG], [C]) +AS_UNSET([LC_ALL], [C]) +AS_UNSET([LC_TIME], [C]) +AS_UNSET([LC_CTYPE], [C]) +AS_UNSET([LANGUAGE], [C]) +AS_UNSET([LC_COLLATE], [C]) +AS_UNSET([LC_NUMERIC], [C]) +AS_UNSET([LC_MESSAGES], [C]) + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +AS_UNSET([CDPATH], [:]) +]) + + +## ----------------------------- ## +## 2. Wrappers around builtins. ## +## ----------------------------- ## + +# This section is lexicographically sorted. + + +# AS_EXIT([EXIT-CODE = 1]) +# ------------------------ +# Exit and set exit code to EXIT-CODE in the way that it's seen +# within "trap 0". +# +# We cannot simply use "exit N" because some shells (zsh and Solaris sh) +# will not set $? to N while running the code set by "trap 0" +# So we set $? by executing "exit N" in the subshell and then exit. +# Other shells don't use `$?' as default for `exit', hence just repeating +# the exit value can only help improving portability. +m4_define([AS_EXIT], +[{ (exit m4_default([$1], 1)); exit m4_default([$1], 1); }]) + + +# AS_IF(TEST, [IF-TRUE], [IF-FALSE]) +# ---------------------------------- +# Expand into +# | if TEST; then +# | IF-TRUE +# | else +# | IF-FALSE +# | fi +# with simplifications is IF-TRUE and/or IF-FALSE is empty. +m4_define([AS_IF], +[m4_ifval([$2$3], +[if $1; then + m4_ifval([$2], [$2], :) +m4_ifvaln([$3], +[else + $3])dnl +fi +])dnl +])# AS_IF + + +# _AS_UNSET_PREPARE +# ----------------- +# AS_UNSET depends upon $as_unset: compute it. +m4_defun([_AS_UNSET_PREPARE], +[# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset="unset" +else + as_unset="false" +fi +]) + + +# AS_UNSET(VAR, [VALUE-IF-UNSET-NOT-SUPPORTED = `']) +# -------------------------------------------------- +# Try to unset the env VAR, otherwise set it to +# VALUE-IF-UNSET-NOT-SUPPORTED. `as_unset' must have been computed. +m4_defun([AS_UNSET], +[m4_require([_AS_UNSET_PREPARE])dnl +$as_unset $1 || test "${$1+set}" != set || { $1=$2; export $1; }]) + + + + + + +## ------------------------------------------ ## +## 3. Error and warnings at the shell level. ## +## ------------------------------------------ ## + +# If AS_MESSAGE_LOG_FD is defined, shell messages are duplicated there +# too. + + +# AS_ESCAPE(STRING, [CHARS = $"'\]) +# --------------------------------- +# Escape the CHARS in STRING. +m4_define([AS_ESCAPE], +[m4_patsubst([$1], + m4_ifval([$2], [[\([$2]\)]], [[\([\"$`]\)]]), + [\\\1])]) + + +# _AS_QUOTE_IFELSE(STRING, IF-MODERN-QUOTATION, IF-OLD-QUOTATION) +# --------------------------------------------------------------- +# Compatibility glue between the old AS_MSG suite which did not +# quote anything, and the modern suite which quotes the quotes. +# If STRING contains `\\' or `\$', it's modern. +# If STRING contains `\"' or `\`', it's old. +# Otherwise it's modern. +# We use two quotes in the pattern to keep highlighting tools at peace. +m4_define([_AS_QUOTE_IFELSE], +[m4_if(m4_regexp([$1], [\\[\\$]]), + [-1], [m4_if(m4_regexp([$1], [\\[`""]]), + [-1], [$2], + [$3])], + [$2])]) + + +# _AS_ECHO_UNQUOTED(STRING, [FD = AS_MESSAGE_FD]) +# ----------------------------------------------- +# Perform shell expansions on STRING and echo the string to FD. +m4_define([_AS_ECHO_UNQUOTED], +[echo "$1" >&m4_default([$2], [AS_MESSAGE_FD])]) + + +# _AS_QUOTE(STRING) +# ----------------- +# If there are quoted (via backslash) backquotes do nothing, else +# backslash all the quotes. +# FIXME: In a distant future (2.51 or +), this warning should be +# classified as `syntax'. It is classified as `obsolete' to ease +# the transition (for Libtool for instance). +m4_define([_AS_QUOTE], +[_AS_QUOTE_IFELSE([$1], + [AS_ESCAPE([$1], [`""])], + [m4_warn([obsolete], + [back quotes and double quotes should not be escaped in: $1])dnl +$1])]) + + +# _AS_ECHO(STRING, [FD = AS_MESSAGE_FD]) +# -------------------------------------- +# Protect STRING from backquote expansion, echo the result to FD. +m4_define([_AS_ECHO], +[_AS_ECHO_UNQUOTED([_AS_QUOTE([$1])], [$2])]) + + +# AS_MESSAGE(STRING, [FD = AS_MESSAGE_FD]) +# ---------------------------------------- +m4_define([AS_MESSAGE], +[m4_ifset([AS_MESSAGE_LOG_FD], + [{ _AS_ECHO([$as_me:__oline__: $1], [AS_MESSAGE_LOG_FD]) +_AS_ECHO([$as_me: $1], [$2]);}], + [_AS_ECHO([$as_me: $1], [$2])])[]dnl +]) + + +# AS_WARN(PROBLEM) +# ---------------- +m4_define([AS_WARN], +[AS_MESSAGE([WARNING: $1], [2])])# AS_WARN + + +# AS_ERROR(ERROR, [EXIT-STATUS = 1]) +# ---------------------------------- +m4_define([AS_ERROR], +[{ AS_MESSAGE([error: $1], [2]) + AS_EXIT([$2]); }[]dnl +])# AS_ERROR + + + +## -------------------------------------- ## +## 4. Portable versions of common tools. ## +## -------------------------------------- ## + +# This section is lexicographically sorted. + + +# AS_DIRNAME(PATHNAME) +# -------------------- +# Simulate running `dirname(1)' on PATHNAME, not all systems have it. +# This macro must be usable from inside ` `. +# +# Prefer expr to echo|sed, since expr is usually faster and it handles +# backslashes and newlines correctly. However, older expr +# implementations (e.g. SunOS 4 expr and Solaris 8 /usr/ucb/expr) have +# a silly length limit that causes expr to fail if the matched +# substring is longer than 120 bytes. So fall back on echo|sed if +# expr fails. +# +# FIXME: Please note the following m4_require is quite wrong: if the first +# occurrence of AS_DIRNAME_EXPR is in a backquoted expression, the +# shell will be lost. We might have to introduce diversions for +# setting up an M4sh script: required macros will then be expanded there. +m4_defun([AS_DIRNAME_EXPR], +[m4_require([_AS_EXPR_PREPARE])dnl +$as_expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \ + X[]$1 : 'X\(//\)[[^/]]' \| \ + X[]$1 : 'X\(//\)$' \| \ + X[]$1 : 'X\(/\)' \| \ + . : '\(.\)']) + +m4_defun([AS_DIRNAME_SED], +[echo X[]$1 | + sed ['/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q']]) + +m4_defun([AS_DIRNAME], +[AS_DIRNAME_EXPR([$1]) 2>/dev/null || +AS_DIRNAME_SED([$1])]) + + +# AS_BASENAME(PATHNAME) +# -------------------- +# Simulate running `basename(1)' on PATHNAME, not all systems have it. +# This macro must be usable from inside ` `. +m4_defun([AS_BASENAME], +[echo "$1" |sed 's,.*[[\\/]],,']) + +# AS_EXECUTABLE_P +# --------------- +# Check whether a file is executable. +m4_defun([AS_EXECUTABLE_P], +[m4_require([_AS_TEST_PREPARE])dnl +$as_executable_p $1[]dnl +])# AS_EXECUTABLE_P + + +# _AS_EXPR_PREPARE +# ---------------- +# Some expr work properly (i.e. compute and issue the right result), +# but exit with failure. When a fall back to expr (as in AS_DIRNAME) +# is provided, you get twice the result. Prevent this. +m4_defun([_AS_EXPR_PREPARE], +[if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr="expr" +else + as_expr="false" +fi +])# _AS_EXPR_PREPARE + + +# _AS_LN_S_PREPARE +# ---------------- +# Don't use conftest.sym to avoid filename issues on DJGPP, where this +# would yield conftest.sym.exe for DJGPP < 2.04. And don't use `conftest' +# as base name to avoid prohibiting concurrency (e.g., concurrent +# config.statuses). +m4_defun([_AS_LN_S_PREPARE], +[rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln' +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file +])# _AS_LN_S_PREPARE + + +# AS_LN_S(FILE, LINK) +# ------------------- +# FIXME: Should we add the glue code to handle properly relative symlinks +# simulated with `ln' or `cp'? +m4_defun([AS_LN_S], +[m4_require([_AS_LN_S_PREPARE])dnl +$as_ln_s $1 $2 +]) + + +# AS_MKDIR_P(PATH) +# ---------------- +# Emulate `mkdir -p' with plain `mkdir'. +# +# Don't set IFS to '\\/' (see the doc): you would end up with +# directories called foo\bar and foo?az and others depending upon the +# shell. +m4_define([AS_MKDIR_P], +[{ case $1 in + [[\\/]]* | ?:[[\\/]]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy=$1 +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$[@]"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || mkdir "$as_incr_dir" + ;; + esac +done; } +])# AS_MKDIR_P + + +# _AS_BROKEN_TEST_PREPARE +# ----------------------- +# FIXME: This does not work and breaks way too many things. +# +# Find out ahead of time whether we want test -x (preferred) or test -f +# to check whether a file is executable. +m4_defun([_AS_BROKEN_TEST_PREPARE], +[# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +@%:@! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +elif test -f conf$$.file >/dev/null 2>&1; then + as_executable_p="test -f" +else + AS_ERROR([cannot check whether a file is executable on this system]) +fi +rm -f conf$$.file +])# _AS_BROKEN_TEST_PREPARE + + +# _AS_TEST_PREPARE +# ---------------- +m4_defun([_AS_TEST_PREPARE], +[as_executable_p="test -f" +])# _AS_BROKEN_TEST_PREPARE + + + + + + +## ------------------ ## +## 5. Common idioms. ## +## ------------------ ## + +# This section is lexicographically sorted. + + +# AS_BOX(MESSAGE, [FRAME-CHARACTER = `=']) +# ---------------------------------------- +# Output MESSAGE, a single line text, framed with FRAME-CHARACTER (which +# must not be `/'). +m4_define([AS_BOX], +[AS_LITERAL_IF([$1], + [_AS_BOX_LITERAL($@)], + [_AS_BOX_INDIR($@)])]) + +# _AS_BOX_LITERAL(MESSAGE, [FRAME-CHARACTER = `=']) +# ------------------------------------------------- +m4_define([_AS_BOX_LITERAL], +[cat <<\_ASBOX +m4_patsubst([$1], [.], m4_if([$2], [], [[=]], [[$2]])) +$1 +m4_patsubst([$1], [.], m4_if([$2], [], [[=]], [[$2]])) +_ASBOX]) + +# _AS_BOX_INDIR(MESSAGE, [FRAME-CHARACTER = `=']) +# ----------------------------------------------- +m4_define([_AS_BOX_INDIR], +[sed 'h;s/./m4_default([$2], [=])/g;p;x;p;x' <<_ASBOX +$1 +_ASBOX]) + + +# AS_LITERAL_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL) +# ----------------------------------------------------- +# If EXPRESSION has shell indirections ($var or `expr`), expand +# IF-INDIR, else IF-NOT-INDIR. +# This is an *approximation*: for instance EXPRESSION = `\$' is +# definitely a literal, but will not be recognized as such. +m4_define([AS_LITERAL_IF], +[m4_if(m4_regexp([$1], [[`$]]), + -1, [$2], + [$3])]) + + +# AS_TMPDIR(PREFIX) +# ----------------- +# Create as safely as possible a temporary directory which name is +# inspired by PREFIX (should be 2-4 chars max), and set trap +# mechanisms to remove it. +m4_define([AS_TMPDIR], +[# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap 'AS_EXIT([1])' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: "${TMPDIR=/tmp}" +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/$1XXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/$1$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + AS_EXIT +}dnl +])# AS_TMPDIR + + +# AS_UNAME +# -------- +# Try to describe this machine. Meant for logs. +m4_define([AS_UNAME], +[{ +cat <<_ASUNAME +## ---------- ## +## Platform. ## +## ---------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +PATH = $PATH + +_ASUNAME +}]) + + + +## ------------------------------------ ## +## Common m4/sh character translation. ## +## ------------------------------------ ## + +# The point of this section is to provide high level macros comparable +# to m4's `translit' primitive, but m4/sh polymorphic. +# Transliteration of literal strings should be handled by m4, while +# shell variables' content will be translated at runtime (tr or sed). + + +# _AS_CR_PREPARE +# -------------- +# Output variables defining common character ranges. +# See m4_cr_letters etc. +m4_defun([_AS_CR_PREPARE], +[# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits +]) + + +# _AS_TR_SH_PREPARE +# ----------------- +m4_defun([_AS_TR_SH_PREPARE], +[m4_require([_AS_CR_PREPARE])dnl +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[[^_$as_cr_alnum]]%_%g" +]) + + +# AS_TR_SH(EXPRESSION) +# -------------------- +# Transform EXPRESSION into a valid shell variable name. +# sh/m4 polymorphic. +# Be sure to update the definition of `$as_tr_sh' if you change this. +m4_defun([AS_TR_SH], +[m4_require([_$0_PREPARE])dnl +AS_LITERAL_IF([$1], + [m4_patsubst(m4_translit([[$1]], [*+], [pp]), + [[^a-zA-Z0-9_]], [_])], + [`echo "$1" | $as_tr_sh`])]) + + +# _AS_TR_CPP_PREPARE +# ------------------ +m4_defun([_AS_TR_CPP_PREPARE], +[m4_require([_AS_CR_PREPARE])dnl +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[[^_$as_cr_alnum]]%_%g" +]) + + +# AS_TR_CPP(EXPRESSION) +# --------------------- +# Map EXPRESSION to an upper case string which is valid as rhs for a +# `#define'. sh/m4 polymorphic. Be sure to update the definition +# of `$as_tr_cpp' if you change this. +m4_defun([AS_TR_CPP], +[m4_require([_$0_PREPARE])dnl +AS_LITERAL_IF([$1], + [m4_patsubst(m4_translit([[$1]], + [*abcdefghijklmnopqrstuvwxyz], + [PABCDEFGHIJKLMNOPQRSTUVWXYZ]), + [[^A-Z0-9_]], [_])], + [`echo "$1" | $as_tr_cpp`])]) + + +# _AS_TR_PREPARE +# -------------- +m4_defun([_AS_TR_PREPARE], +[m4_require([_AS_TR_SH_PREPARE])dnl +m4_require([_AS_TR_CPP_PREPARE])dnl +]) + + + + +## --------------------------------------------------- ## +## Common m4/sh handling of variables (indirections). ## +## --------------------------------------------------- ## + + +# The purpose of this section is to provide a uniform API for +# reading/setting sh variables with or without indirection. +# Typically, one can write +# AS_VAR_SET(var, val) +# or +# AS_VAR_SET(as_$var, val) +# and expect the right thing to happen. + + +# AS_VAR_SET(VARIABLE, VALUE) +# --------------------------- +# Set the VALUE of the shell VARIABLE. +# If the variable contains indirections (e.g. `ac_cv_func_$ac_func') +# perform whenever possible at m4 level, otherwise sh level. +m4_define([AS_VAR_SET], +[AS_LITERAL_IF([$1], + [$1=$2], + [eval "$1=$2"])]) + + +# AS_VAR_GET(VARIABLE) +# -------------------- +# Get the value of the shell VARIABLE. +# Evaluates to $VARIABLE if there are no indirection in VARIABLE, +# else into the appropriate `eval' sequence. +m4_define([AS_VAR_GET], +[AS_LITERAL_IF([$1], + [$[]$1], + [`eval echo '${'"m4_patsubst($1, [[\\`]], [\\\&])"'}'`])]) + + +# AS_VAR_TEST_SET(VARIABLE) +# ------------------------- +# Expands into the `test' expression which is true if VARIABLE +# is set. Polymorphic. Should be dnl'ed. +m4_define([AS_VAR_TEST_SET], +[AS_LITERAL_IF([$1], + [test "${$1+set}" = set], + [eval "test \"\${$1+set}\" = set"])]) + + +# AS_VAR_SET_IF(VARIABLE, IF-TRUE, IF-FALSE) +# ------------------------------------------ +# Implement a shell `if-then-else' depending whether VARIABLE is set +# or not. Polymorphic. +m4_define([AS_VAR_SET_IF], +[AS_IF([AS_VAR_TEST_SET([$1])], [$2], [$3])]) + + +# AS_VAR_PUSHDEF and AS_VAR_POPDEF +# -------------------------------- +# + +# Sometimes we may have to handle literals (e.g. `stdlib.h'), while at +# other moments, the same code may have to get the value from a +# variable (e.g., `ac_header'). To have a uniform handling of both +# cases, when a new value is about to be processed, declare a local +# variable, e.g.: +# +# AS_VAR_PUSHDEF([header], [ac_cv_header_$1]) +# +# and then in the body of the macro, use `header' as is. It is of +# first importance to use `AS_VAR_*' to access this variable. Don't +# quote its name: it must be used right away by m4. +# +# If the value `$1' was a literal (e.g. `stdlib.h'), then `header' is +# in fact the value `ac_cv_header_stdlib_h'. If `$1' was indirect, +# then `header's value in m4 is in fact `$ac_header', the shell +# variable that holds all of the magic to get the expansion right. +# +# At the end of the block, free the variable with +# +# AS_VAR_POPDEF([header]) + + +# AS_VAR_PUSHDEF(VARNAME, VALUE) +# ------------------------------ +# Define the m4 macro VARNAME to an accessor to the shell variable +# named VALUE. VALUE does not need to be a valid shell variable name: +# the transliteration is handled here. To be dnl'ed. +m4_define([AS_VAR_PUSHDEF], +[AS_LITERAL_IF([$2], + [m4_pushdef([$1], [AS_TR_SH($2)])], + [as_$1=AS_TR_SH($2) +m4_pushdef([$1], [$as_[$1]])])]) + + +# AS_VAR_POPDEF(VARNAME) +# ---------------------- +# Free the shell variable accessor VARNAME. To be dnl'ed. +m4_define([AS_VAR_POPDEF], +[m4_popdef([$1])]) + + + +## ----------------- ## +## Setting M4sh up. ## +## ----------------- ## + + +# AS_INIT +# ------- +m4_define([AS_INIT], +[m4_init + +# Forbidden tokens and exceptions. +m4_pattern_forbid([^_?AS_]) +]) diff --git a/m4sugar.m4 b/m4sugar.m4 new file mode 100644 index 0000000..cebeb43 --- /dev/null +++ b/m4sugar.m4 @@ -0,0 +1,1741 @@ +divert(-1)# -*- Autoconf -*- +# vile:fk=utf-8 +# This file is part of Autoconf. +# Base M4 layer. +# Requires GNU M4. +# Copyright 2010,2023 Thomas E. Dickey +# Copyright 1999, 2000, 2001 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 2, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the Free Software Foundation gives unlimited +# permission to copy, distribute and modify the configure scripts that +# are the output of Autoconf. You need not follow the terms of the GNU +# General Public License when using or distributing such scripts, even +# though portions of the text of Autoconf appear in them. The GNU +# General Public License (GPL) does govern all other use of the material +# that constitutes the Autoconf program. +# +# Certain portions of the Autoconf source text are designed to be copied +# (in certain cases, depending on the input) into the output of +# Autoconf. We call these the "data" portions. The rest of the Autoconf +# source text consists of comments plus executable code that decides which +# of the data portions to output in any given case. We call these +# comments and executable code the "non-data" portions. Autoconf never +# copies any of the non-data portions into its output. +# +# This special exception to the GPL applies to versions of Autoconf +# released by the Free Software Foundation. When you make and +# distribute a modified version of Autoconf, you may extend this special +# exception to the GPL to apply to your modified version as well, *unless* +# your modified version has the potential to copy into its output some +# of the text that was the non-data portion of the version that you started +# with. (In other words, unless your change moves or copies text from +# the non-data portions to the data portions.) If your modification has +# such potential, you must delete any notice of this special exception +# to the GPL from your modified version. +# +# Written by Akim Demaille. +# + +# Set the quotes, whatever the current quoting system. +changequote() +changequote([, ]) + +# Some old m4's don't support m4exit. But they provide +# equivalent functionality by core dumping because of the +# long macros we define. +ifdef([__gnu__], , +[errprint(M4sugar requires GNU M4. Install it before installing M4sugar or +set the M4 environment variable to its path name.) +m4exit(2)]) + + +## ------------------------------- ## +## 1. Simulate --prefix-builtins. ## +## ------------------------------- ## + +# m4_define +# m4_defn +# m4_undefine +define([m4_define], defn([define])) +define([m4_defn], defn([defn])) +define([m4_undefine], defn([undefine])) + +m4_undefine([define]) +m4_undefine([defn]) +m4_undefine([undefine]) + + +# m4_copy(SRC, DST) +# ----------------- +# Define DST as the definition of SRC. +# What's the difference between: +# 1. m4_copy([from], [to]) +# 2. m4_define([from], [to($@)]) +# Well, obviously 1 is more expansive in space. Maybe 2 is more expansive +# in time, but because of the space cost of 1, it's not that obvious. +# Nevertheless, one huge difference is the handling of `$0'. If `from' +# uses `$0', then with 1, `to''s `$0' is `to', while it is `from' in 2. +# The user will certainly prefer see `from'. +m4_define([m4_copy], +[m4_define([$2], m4_defn([$1]))]) + + +# m4_rename(SRC, DST) +# ------------------- +# Rename the macro SRC as DST. +m4_define([m4_rename], +[m4_copy([$1], [$2])m4_undefine([$1])]) + + +# m4_rename_m4(MACRO-NAME) +# ------------------------ +# Rename MACRO-NAME as m4_MACRO-NAME. +m4_define([m4_rename_m4], +[m4_rename([$1], [m4_$1])]) + + +# m4_copy_unm4(m4_MACRO-NAME) +# --------------------------- +# Copy m4_MACRO-NAME as MACRO-NAME. +m4_define([m4_copy_unm4], +[m4_copy([$1], m4_patsubst([$1], [^m4_\(.*\)], [[\1]]))]) + + +# Some m4 internals have names colliding with tokens we might use. +# Rename them a` la `m4 --prefix-builtins'. +m4_rename_m4([builtin]) +m4_rename_m4([changecom]) +m4_rename_m4([changequote]) +m4_rename_m4([debugfile]) +m4_rename_m4([debugmode]) +m4_rename_m4([decr]) +m4_undefine([divert]) +m4_rename_m4([divnum]) +m4_rename_m4([dumpdef]) +m4_rename_m4([errprint]) +m4_rename_m4([esyscmd]) +m4_rename_m4([eval]) +m4_rename_m4([format]) +m4_rename_m4([ifdef]) +m4_rename([ifelse], [m4_if]) +m4_rename_m4([include]) +m4_rename_m4([incr]) +m4_rename_m4([index]) +m4_rename_m4([indir]) +m4_rename_m4([len]) +m4_rename([m4exit], [m4_exit]) +m4_rename([m4wrap], [m4_wrap]) +m4_rename_m4([maketemp]) +m4_rename_m4([patsubst]) +m4_undefine([popdef]) +m4_rename_m4([pushdef]) +m4_rename_m4([regexp]) +m4_rename_m4([shift]) +m4_rename_m4([sinclude]) +m4_rename_m4([substr]) +m4_rename_m4([symbols]) +m4_rename_m4([syscmd]) +m4_rename_m4([sysval]) +m4_rename_m4([traceoff]) +m4_rename_m4([traceon]) +m4_rename_m4([translit]) +m4_undefine([undivert]) + + +## ------------------- ## +## 2. Error messages. ## +## ------------------- ## + + +# m4_location +# ----------- +m4_define([m4_location], +[__file__:__line__]) + + +# m4_errprintn(MSG) +# ----------------- +# Same as `errprint', but with the missing end of line. +m4_define([m4_errprintn], +[m4_errprint([$1 +])]) + + +# m4_warning(MSG) +# --------------- +# Warn the user. +m4_define([m4_warning], +[m4_errprintn(m4_location[: warning: $1])]) + + +# m4_fatal(MSG, [EXIT-STATUS]) +# ---------------------------- +# Fatal the user. :) +m4_define([m4_fatal], +[m4_errprintn(m4_location[: error: $1])dnl +m4_expansion_stack_dump()dnl +m4_exit(m4_if([$2],, 1, [$2]))]) + + +# m4_assert(EXPRESSION, [EXIT-STATUS = 1]) +# ---------------------------------------- +# This macro ensures that EXPRESSION evaluates to true, and exits if +# EXPRESSION evaluates to false. +m4_define([m4_assert], +[m4_if(m4_eval([$1]), 0, + [m4_fatal([assert failed: $1], [$2])])]) + + +## ------------- ## +## 3. Warnings. ## +## ------------- ## + + +# m4_warning_ifelse(CATEGORY, IF-TRUE, IF-FALSE) +# ---------------------------------------------- +# If the CATEGORY of warnings is enabled, expand IF_TRUE otherwise +# IF-FALSE. +# +# The variable `m4_warnings' contains a comma separated list of +# warnings which order is the converse from the one specified by +# the user, i.e., if she specified `-W error,none,obsolete', +# `m4_warnings' is `obsolete,none,error'. We read it from left to +# right, and: +# - if none or noCATEGORY is met, run IF-FALSE +# - if all or CATEGORY is met, run IF-TRUE +# - if there is nothing left, run IF-FALSE. +m4_define([m4_warning_ifelse], +[_m4_warning_ifelse([$1], [$2], [$3], m4_warnings)]) + + +# _m4_warning_ifelse(CATEGORY, IF-TRUE, IF-FALSE, WARNING1, ...) +# -------------------------------------------------------------- +# Implementation of the loop described above. +m4_define([_m4_warning_ifelse], +[m4_case([$4], + [$1], [$2], + [all], [$2], + [], [$3], + [none], [$3], + [no-$1], [$3], + [$0([$1], [$2], [$3], m4_shiftn(4, $@))])]) + + +# _m4_warning_error_ifelse(IF-TRUE, IF-FALSE) +# ------------------------------------------- +# The same as m4_warning_ifelse, but scan for `error' only. +m4_define([_m4_warning_error_ifelse], +[__m4_warning_error_ifelse([$1], [$2], m4_warnings)]) + + +# __m4_warning_error_ifelse(IF-TRUE, IF-FALSE) +# -------------------------------------------- +# The same as _m4_warning_ifelse, but scan for `error' only. +m4_define([__m4_warning_error_ifelse], +[m4_case([$3], + [error], [$1], + [], [$2], + [no-error], [$2], + [$0([$1], [$2], m4_shiftn(3, $@))])]) + + + +# _m4_warn(MESSAGE) +# ----------------- +# Report MESSAGE as a warning, unless the user requested -W error, +# in which case report a fatal error. +m4_define([_m4_warn], +[_m4_warning_error_ifelse([m4_fatal([$1])], + [m4_warning([$1])])]) + + +# m4_warn(CATEGORY, MESSAGE) +# -------------------------- +# Report a MESSAGE to the autoconf user if the CATEGORY of warnings +# is requested (in fact, not disabled). +m4_define([m4_warn], +[m4_warning_ifelse([$1], [_m4_warn([$2])])]) + + + + +## ------------------- ## +## 4. File inclusion. ## +## ------------------- ## + + +# We also want to neutralize include (and sinclude for symmetry), +# but we want to extend them slightly: warn when a file is included +# several times. This is in general a dangerous operation because +# quite nobody quotes the first argument of m4_define. +# +# For instance in the following case: +# m4_define(foo, [bar]) +# then a second reading will turn into +# m4_define(bar, [bar]) +# which is certainly not what was meant. + +# m4_include_unique(FILE) +# ----------------------- +# Declare that the FILE was loading; and warn if it has already +# been included. +m4_define([m4_include_unique], +[m4_ifdef([m4_include($1)], + [m4_warn([syntax], [file `$1' included several times])])dnl +m4_define([m4_include($1)])]) + + +# m4_include(FILE) +# ---------------- +# As the builtin include, but warns against multiple inclusions. +m4_define([m4_include], +[m4_include_unique([$1])dnl +m4_builtin([include], [$1])]) + + +# m4_sinclude(FILE) +# ----------------- +# As the builtin sinclude, but warns against multiple inclusions. +m4_define([m4_sinclude], +[m4_include_unique([$1])dnl +m4_builtin([sinclude], [$1])]) + + + +## ------------------------------------ ## +## 5. Additional branching constructs. ## +## ------------------------------------ ## + +# Both `m4_ifval' and `m4_ifset' tests against the empty string. The +# difference is that `m4_ifset' is specialized on macros. +# +# In case of arguments of macros, eg $[1], it makes little difference. +# In the case of a macro `FOO', you don't want to check `m4_ifval(FOO, +# TRUE)', because if `FOO' expands with commas, there is a shifting of +# the arguments. So you want to run `m4_ifval([FOO])', but then you just +# compare the *string* `FOO' against `', which, of course fails. +# +# So you want a variation of `m4_ifset' that expects a macro name as $[1]. +# If this macro is both defined and defined to a non empty value, then +# it runs TRUE etc. + + +# m4_ifval(COND, [IF-TRUE], [IF-FALSE]) +# ------------------------------------- +# If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE. +# Comparable to m4_ifdef. +m4_define([m4_ifval], +[m4_if([$1], [], [$3], [$2])]) + + +# m4_n(TEXT) +# ---------- +# If TEXT is not empty, return TEXT and a new line, otherwise nothing. +m4_define([m4_n], +[m4_if([$1], + [], [], + [$1 +])]) + + +# m4_ifvaln(COND, [IF-TRUE], [IF-FALSE]) +# -------------------------------------- +# Same as `m4_ifval', but add an extra newline to IF-TRUE or IF-FALSE +# unless that argument is empty. +m4_define([m4_ifvaln], +[m4_if([$1], + [], [m4_n([$3])], + [m4_n([$2])])]) + + +# m4_ifset(MACRO, [IF-TRUE], [IF-FALSE]) +# -------------------------------------- +# If MACRO has no definition, or of its definition is the empty string, +# expand IF-FALSE, otherwise IF-TRUE. +m4_define([m4_ifset], +[m4_ifdef([$1], + [m4_if(m4_defn([$1]), [], [$3], [$2])], + [$3])]) + + +# m4_ifndef(NAME, [IF-NOT-DEFINED], [IF-DEFINED]) +# ----------------------------------------------- +m4_define([m4_ifndef], +[m4_ifdef([$1], [$3], [$2])]) + + +# m4_case(SWITCH, VAL1, IF-VAL1, VAL2, IF-VAL2, ..., DEFAULT) +# ----------------------------------------------------------- +# m4 equivalent of +# switch (SWITCH) +# { +# case VAL1: +# IF-VAL1; +# break; +# case VAL2: +# IF-VAL2; +# break; +# ... +# default: +# DEFAULT; +# break; +# }. +# All the values are optional, and the macro is robust to active +# symbols properly quoted. +m4_define([m4_case], +[m4_if([$#], 0, [], + [$#], 1, [], + [$#], 2, [$2], + [$1], [$2], [$3], + [m4_case([$1], m4_shiftn(3, $@))])]) + + +# m4_match(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT) +# ---------------------------------------------------- +# m4 equivalent of +# +# if (SWITCH =~ RE1) +# VAL1; +# elif (SWITCH =~ RE2) +# VAL2; +# elif ... +# ... +# else +# DEFAULT +# +# All the values are optional, and the macro is robust to active symbols +# properly quoted. +m4_define([m4_match], +[m4_if([$#], 0, [], + [$#], 1, [], + [$#], 2, [$2], + m4_regexp([$1], [$2]), -1, [m4_match([$1], m4_shiftn(3, $@))], + [$3])]) + + + +## ---------------------------------------- ## +## 6. Enhanced version of some primitives. ## +## ---------------------------------------- ## + +# m4_do(STRING, ...) +# ------------------ +# This macro invokes all its arguments (in sequence, of course). It is +# useful for making your macros more structured and readable by dropping +# unnecessary dnl's and have the macros indented properly. +m4_define([m4_do], +[m4_if($#, 0, [], + $#, 1, [$1], + [$1[]m4_do(m4_shift($@))])]) + + +# m4_default(EXP1, EXP2) +# ---------------------- +# Returns EXP1 if non empty, otherwise EXP2. +m4_define([m4_default], +[m4_ifval([$1], [$1], [$2])]) + + +# m4_defn(NAME) +# ------------- +# Unlike to the original, don't tolerate popping something which is +# undefined. +m4_define([m4_defn], +[m4_ifndef([$1], + [m4_fatal([$0: undefined macro: $1])])dnl +m4_builtin([defn], $@)]) + + +# _m4_dumpdefs_up(NAME) +# --------------------- +m4_define([_m4_dumpdefs_up], +[m4_ifdef([$1], + [m4_pushdef([_m4_dumpdefs], m4_defn([$1]))dnl +m4_dumpdef([$1])dnl +m4_popdef([$1])dnl +_m4_dumpdefs_up([$1])])]) + + +# _m4_dumpdefs_down(NAME) +# ----------------------- +m4_define([_m4_dumpdefs_down], +[m4_ifdef([_m4_dumpdefs], + [m4_pushdef([$1], m4_defn([_m4_dumpdefs]))dnl +m4_popdef([_m4_dumpdefs])dnl +_m4_dumpdefs_down([$1])])]) + + +# m4_dumpdefs(NAME) +# ----------------- +# Similar to `m4_dumpdef(NAME)', but if NAME was m4_pushdef'ed, display its +# value stack (most recent displayed first). +m4_define([m4_dumpdefs], +[_m4_dumpdefs_up([$1])dnl +_m4_dumpdefs_down([$1])]) + + +# m4_popdef(NAME) +# --------------- +# Unlike to the original, don't tolerate popping something which is +# undefined. +m4_define([m4_popdef], +[m4_ifndef([$1], + [m4_fatal([$0: undefined macro: $1])])dnl +m4_builtin([popdef], $@)]) + + +# m4_quote(STRING) +# ---------------- +# Return STRING quoted. +# +# It is important to realize the difference between `m4_quote(exp)' and +# `[exp]': in the first case you obtain the quoted *result* of the +# expansion of EXP, while in the latter you just obtain the string +# `exp'. +m4_define([m4_quote], [[$*]]) +m4_define([m4_dquote], [[[$*]]]) + + +# m4_noquote(STRING) +# ------------------ +# Return the result of ignoring all quotes in STRING and invoking the +# macros it contains. Amongst other things useful for enabling macro +# invocations inside strings with [] blocks (for instance regexps and +# help-strings). +m4_define([m4_noquote], +[m4_changequote(-=<{,}>=-)$1-=<{}>=-m4_changequote([,])]) + + +# m4_shiftn(N, ...) +# ----------------- +# Returns ... shifted N times. Useful for recursive "varargs" constructs. +m4_define([m4_shiftn], +[m4_assert(($1 >= 0) && ($# > $1))dnl +_m4_shiftn($@)]) + +m4_define([_m4_shiftn], +[m4_if([$1], 0, + [m4_shift($@)], + [_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])]) + + +# m4_undefine(NAME) +# ----------------- +# Unlike to the original, don't tolerate undefining something which is +# undefined. +m4_define([m4_undefine], +[m4_ifndef([$1], + [m4_fatal([$0: undefined macro: $1])])dnl +m4_builtin([undefine], $@)]) + + +## -------------------------- ## +## 7. Implementing m4 loops. ## +## -------------------------- ## + + +# m4_for(VARIABLE, FIRST, LAST, [STEP = +/-1], EXPRESSION) +# -------------------------------------------------------- +# Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO. +# Both limits are included, and bounds are checked for consistency. +m4_define([m4_for], +[m4_case(m4_sign(m4_eval($3 - $2)), + 1, [m4_assert(m4_sign(m4_default($4, 1)) == 1)], + -1, [m4_assert(m4_sign(m4_default($4, -1)) == -1)])dnl +m4_pushdef([$1], [$2])dnl +m4_if(m4_eval([$3 > $2]), 1, + [_m4_for([$1], [$3], m4_default([$4], 1), [$5])], + [_m4_for([$1], [$3], m4_default([$4], -1), [$5])])dnl +m4_popdef([$1])]) + + +# _m4_for(VARIABLE, FIRST, LAST, STEP, EXPRESSION) +# ------------------------------------------------ +# Core of the loop, no consistency checks. +m4_define([_m4_for], +[$4[]dnl +m4_if($1, [$2], [], + [m4_define([$1], m4_eval($1+[$3]))_m4_for([$1], [$2], [$3], [$4])])]) + + +# Implementing `foreach' loops in m4 is much more tricky than it may +# seem. Actually, the example of a `foreach' loop in the m4 +# documentation is wrong: it does not quote the arguments properly, +# which leads to undesired expansions. +# +# The example in the documentation is: +# +# | # foreach(VAR, (LIST), STMT) +# | m4_define([foreach], +# | [m4_pushdef([$1])_foreach([$1], [$2], [$3])m4_popdef([$1])]) +# | m4_define([_arg1], [$1]) +# | m4_define([_foreach], +# | [m4_if([$2], [()], , +# | [m4_define([$1], _arg1$2)$3[]_foreach([$1], +# | (shift$2), +# | [$3])])]) +# +# But then if you run +# +# | m4_define(a, 1) +# | m4_define(b, 2) +# | m4_define(c, 3) +# | foreach([f], [([a], [(b], [c)])], [echo f +# | ]) +# +# it gives +# +# => echo 1 +# => echo (2,3) +# +# which is not what is expected. +# +# Of course the problem is that many quotes are missing. So you add +# plenty of quotes at random places, until you reach the expected +# result. Alternatively, if you are a quoting wizard, you directly +# reach the following implementation (but if you really did, then +# apply to the maintenance of m4sugar!). +# +# | # foreach(VAR, (LIST), STMT) +# | m4_define([foreach], [m4_pushdef([$1])_foreach($@)m4_popdef([$1])]) +# | m4_define([_arg1], [[$1]]) +# | m4_define([_foreach], +# | [m4_if($2, [()], , +# | [m4_define([$1], [_arg1$2])$3[]_foreach([$1], +# | [(shift$2)], +# | [$3])])]) +# +# which this time answers +# +# => echo a +# => echo (b +# => echo c) +# +# Bingo! +# +# Well, not quite. +# +# With a better look, you realize that the parens are more a pain than +# a help: since anyway you need to quote properly the list, you end up +# with always using an outermost pair of parens and an outermost pair +# of quotes. Rejecting the parens both eases the implementation, and +# simplifies the use: +# +# | # foreach(VAR, (LIST), STMT) +# | m4_define([foreach], [m4_pushdef([$1])_foreach($@)m4_popdef([$1])]) +# | m4_define([_arg1], [$1]) +# | m4_define([_foreach], +# | [m4_if($2, [], , +# | [m4_define([$1], [_arg1($2)])$3[]_foreach([$1], +# | [shift($2)], +# | [$3])])]) +# +# +# Now, just replace the `$2' with `m4_quote($2)' in the outer `m4_if' +# to improve robustness, and you come up with a quite satisfactory +# implementation. + + +# m4_foreach(VARIABLE, LIST, EXPRESSION) +# -------------------------------------- +# +# Expand EXPRESSION assigning each value of the LIST to VARIABLE. +# LIST should have the form `item_1, item_2, ..., item_n', i.e. the +# whole list must *quoted*. Quote members too if you don't want them +# to be expanded. +# +# This macro is robust to active symbols: +# | m4_define(active, [ACT, IVE]) +# | m4_foreach(Var, [active, active], [-Var-]) +# => -ACT--IVE--ACT--IVE- +# +# | m4_foreach(Var, [[active], [active]], [-Var-]) +# => -ACT, IVE--ACT, IVE- +# +# | m4_foreach(Var, [[[active]], [[active]]], [-Var-]) +# => -active--active- +m4_define([m4_foreach], +[m4_pushdef([$1])_m4_foreach($@)m4_popdef([$1])]) + +# Low level macros used to define m4_foreach. +m4_define([m4_car], [$1]) +m4_define([_m4_foreach], +[m4_if(m4_quote($2), [], [], + [m4_define([$1], [m4_car($2)])$3[]_m4_foreach([$1], + [m4_shift($2)], + [$3])])]) + + + +## --------------------------- ## +## 8. More diversion support. ## +## --------------------------- ## + + +# _m4_divert(DIVERSION-NAME or NUMBER) +# ------------------------------------ +# If DIVERSION-NAME is the name of a diversion, return its number, +# otherwise if is a NUMBER return it. +m4_define([_m4_divert], +[m4_ifdef([_m4_divert($1)], + [m4_indir([_m4_divert($1)])], + [$1])]) + +# KILL is only used to suppress output. +m4_define([_m4_divert(KILL)], -1) + + +# m4_divert(DIVERSION-NAME) +# ------------------------- +# Change the diversion stream to DIVERSION-NAME. +m4_define([m4_divert], +[m4_define([m4_divert_stack], + m4_location[: $0: $1]m4_ifdef([m4_divert_stack], [ +m4_defn([m4_divert_stack])]))dnl +m4_builtin([divert], _m4_divert([$1]))dnl +]) + + +# m4_divert_push(DIVERSION-NAME) +# ------------------------------ +# Change the diversion stream to DIVERSION-NAME, while stacking old values. +m4_define([m4_divert_push], +[m4_pushdef([m4_divert_stack], + m4_location[: $0: $1]m4_ifdef([m4_divert_stack], [ +m4_defn([m4_divert_stack])]))dnl +m4_pushdef([_m4_divert_diversion], [$1])dnl +m4_builtin([divert], _m4_divert(_m4_divert_diversion))dnl +]) + + +# m4_divert_pop([DIVERSION-NAME]) +# ------------------------------- +# Change the diversion stream to its previous value, unstacking it. +# If specified, verify we left DIVERSION-NAME. +m4_define([m4_divert_pop], +[m4_ifval([$1], + [m4_if(_m4_divert([$1]), m4_divnum, [], + [m4_fatal([$0($1): unexpected current diversion: ]m4_divnum)])])dnl +m4_popdef([_m4_divert_diversion])dnl +dnl m4_ifndef([_m4_divert_diversion], +dnl [m4_fatal([too many m4_divert_pop])])dnl +m4_builtin([divert], + m4_ifdef([_m4_divert_diversion], + [_m4_divert(_m4_divert_diversion)], -1))dnl +m4_popdef([m4_divert_stack])dnl +]) + + +# m4_divert_text(DIVERSION-NAME, CONTENT) +# --------------------------------------- +# Output CONTENT into DIVERSION-NAME (which may be a number actually). +# An end of line is appended for free to CONTENT. +m4_define([m4_divert_text], +[m4_divert_push([$1])dnl +$2 +m4_divert_pop([$1])dnl +]) + + +# m4_divert_once(DIVERSION-NAME, CONTENT) +# --------------------------------------- +# Output once CONTENT into DIVERSION-NAME (which may be a number +# actually). An end of line is appended for free to CONTENT. +m4_define([m4_divert_once], +[m4_expand_once([m4_divert_text([$1], [$2])])]) + + +# m4_undivert(DIVERSION-NAME) +# --------------------------- +# Undivert DIVERSION-NAME. +m4_define([m4_undivert], +[m4_builtin([undivert], _m4_divert([$1]))]) + + + + +## -------------------------------------------- ## +## 8. Defining macros with bells and whistles. ## +## -------------------------------------------- ## + +# `m4_defun' is basically `m4_define' but it equips the macro with the +# needed machinery for `m4_require'. A macro must be m4_defun'd if +# either it is m4_require'd, or it m4_require's. +# +# Two things deserve attention and are detailed below: +# 1. Implementation of m4_require +# 2. Keeping track of the expansion stack +# +# 1. Implementation of m4_require +# =============================== +# +# Of course m4_defun AC_PROVIDE's the macro, so that a macro which has +# been expanded is not expanded again when m4_require'd, but the +# difficult part is the proper expansion of macros when they are +# m4_require'd. +# +# The implementation is based on two ideas, (i) using diversions to +# prepare the expansion of the macro and its dependencies (by François +# Pinard), and (ii) expand the most recently m4_require'd macros _after_ +# the previous macros (by Axel Thimm). +# +# +# The first idea: why using diversions? +# ------------------------------------- +# +# When a macro requires another, the other macro is expanded in new +# diversion, GROW. When the outer macro is fully expanded, we first +# undivert the most nested diversions (GROW - 1...), and finally +# undivert GROW. To understand why we need several diversions, +# consider the following example: +# +# | m4_defun([TEST1], [Test...REQUIRE([TEST2])1]) +# | m4_defun([TEST2], [Test...REQUIRE([TEST3])2]) +# | m4_defun([TEST3], [Test...3]) +# +# Because m4_require is not required to be first in the outer macros, we +# must keep the expansions of the various level of m4_require separated. +# Right before executing the epilogue of TEST1, we have: +# +# GROW - 2: Test...3 +# GROW - 1: Test...2 +# GROW: Test...1 +# BODY: +# +# Finally the epilogue of TEST1 undiverts GROW - 2, GROW - 1, and +# GROW into the regular flow, BODY. +# +# GROW - 2: +# GROW - 1: +# GROW: +# BODY: Test...3; Test...2; Test...1 +# +# (The semicolons are here for clarification, but of course are not +# emitted.) This is what Autoconf 2.0 (I think) to 2.13 (I'm sure) +# implement. +# +# +# The second idea: first required first out +# ----------------------------------------- +# +# The natural implementation of the idea above is buggy and produces +# very surprising results in some situations. Let's consider the +# following example to explain the bug: +# +# | m4_defun([TEST1], [REQUIRE([TEST2a])REQUIRE([TEST2b])]) +# | m4_defun([TEST2a], []) +# | m4_defun([TEST2b], [REQUIRE([TEST3])]) +# | m4_defun([TEST3], [REQUIRE([TEST2a])]) +# | +# | AC_INIT +# | TEST1 +# +# The dependencies between the macros are: +# +# 3 --- 2b +# / \ is m4_require'd by +# / \ left -------------------- right +# 2a ------------ 1 +# +# If you strictly apply the rules given in the previous section you get: +# +# GROW - 2: TEST3 +# GROW - 1: TEST2a; TEST2b +# GROW: TEST1 +# BODY: +# +# (TEST2a, although required by TEST3 is not expanded in GROW - 3 +# because is has already been expanded before in GROW - 1, so it has +# been AC_PROVIDE'd, so it is not expanded again) so when you undivert +# the stack of diversions, you get: +# +# GROW - 2: +# GROW - 1: +# GROW: +# BODY: TEST3; TEST2a; TEST2b; TEST1 +# +# i.e., TEST2a is expanded after TEST3 although the latter required the +# former. +# +# Starting from 2.50, uses an implementation provided by Axel Thimm. +# The idea is simple: the order in which macros are emitted must be the +# same as the one in which macro are expanded. (The bug above can +# indeed be described as: a macro has been AC_PROVIDE'd, but it is +# emitted after: the lack of correlation between emission and expansion +# order is guilty). +# +# How to do that? You keeping the stack of diversions to elaborate the +# macros, but each time a macro is fully expanded, emit it immediately. +# +# In the example above, when TEST2a is expanded, but it's epilogue is +# not run yet, you have: +# +# GROW - 2: +# GROW - 1: TEST2a +# GROW: Elaboration of TEST1 +# BODY: +# +# The epilogue of TEST2a emits it immediately: +# +# GROW - 2: +# GROW - 1: +# GROW: Elaboration of TEST1 +# BODY: TEST2a +# +# TEST2b then requires TEST3, so right before the epilogue of TEST3, you +# have: +# +# GROW - 2: TEST3 +# GROW - 1: Elaboration of TEST2b +# GROW: Elaboration of TEST1 +# BODY: TEST2a +# +# The epilogue of TEST3 emits it: +# +# GROW - 2: +# GROW - 1: Elaboration of TEST2b +# GROW: Elaboration of TEST1 +# BODY: TEST2a; TEST3 +# +# TEST2b is now completely expanded, and emitted: +# +# GROW - 2: +# GROW - 1: +# GROW: Elaboration of TEST1 +# BODY: TEST2a; TEST3; TEST2b +# +# and finally, TEST1 is finished and emitted: +# +# GROW - 2: +# GROW - 1: +# GROW: +# BODY: TEST2a; TEST3; TEST2b: TEST1 +# +# The idea, is simple, but the implementation is a bit evolved. If you +# are like me, you will want to see the actual functioning of this +# implementation to be convinced. The next section gives the full +# details. +# +# +# The Axel Thimm implementation at work +# ------------------------------------- +# +# We consider the macros above, and this configure.ac: +# +# AC_INIT +# TEST1 +# +# You should keep the definitions of _m4_defun_pro, _m4_defun_epi, and +# m4_require at hand to follow the steps. +# +# This implements tries not to assume that of the current diversion is +# BODY, so as soon as a macro (m4_defun'd) is expanded, we first +# record the current diversion under the name _m4_divert_dump (denoted +# DUMP below for short). This introduces an important difference with +# the previous versions of Autoconf: you cannot use m4_require if you +# were not inside an m4_defun'd macro, and especially, you cannot +# m4_require directly from the top level. +# +# We have not tried to simulate the old behavior (better yet, we +# diagnose it), because it is too dangerous: a macro m4_require'd from +# the top level is expanded before the body of `configure', i.e., before +# any other test was run. I let you imagine the result of requiring +# AC_STDC_HEADERS for instance, before AC_PROG_CC was actually run.... +# +# After AC_INIT was run, the current diversion is BODY. +# * AC_INIT was run +# DUMP: undefined +# diversion stack: BODY |- +# +# * TEST1 is expanded +# The prologue of TEST1 sets AC_DIVERSION_DUMP, which is the diversion +# where the current elaboration will be dumped, to the current +# diversion. It also m4_divert_push to GROW, where the full +# expansion of TEST1 and its dependencies will be elaborated. +# DUMP: BODY +# BODY: empty +# diversions: GROW, BODY |- +# +# * TEST1 requires TEST2a: prologue +# m4_require m4_divert_pushes another temporary diversion GROW - 1 (in +# fact, the diversion whose number is one less than the current +# diversion), and expands TEST2a in there. +# DUMP: BODY +# BODY: empty +# diversions: GROW-1, GROW, BODY |- +# +# * TEST2a is expanded. +# Its prologue pushes the current diversion again. +# DUMP: BODY +# BODY: empty +# diversions: GROW - 1, GROW - 1, GROW, BODY |- +# It is expanded in GROW - 1, and GROW - 1 is popped by the epilogue +# of TEST2a. +# DUMP: BODY +# BODY: nothing +# GROW - 1: TEST2a +# diversions: GROW - 1, GROW, BODY |- +# +# * TEST1 requires TEST2a: epilogue +# The content of the current diversion is appended to DUMP (and removed +# from the current diversion). A diversion is popped. +# DUMP: BODY +# BODY: TEST2a +# diversions: GROW, BODY |- +# +# * TEST1 requires TEST2b: prologue +# m4_require pushes GROW - 1 and expands TEST2b. +# DUMP: BODY +# BODY: TEST2a +# diversions: GROW - 1, GROW, BODY |- +# +# * TEST2b is expanded. +# Its prologue pushes the current diversion again. +# DUMP: BODY +# BODY: TEST2a +# diversions: GROW - 1, GROW - 1, GROW, BODY |- +# The body is expanded here. +# +# * TEST2b requires TEST3: prologue +# m4_require pushes GROW - 2 and expands TEST3. +# DUMP: BODY +# BODY: TEST2a +# diversions: GROW - 2, GROW - 1, GROW - 1, GROW, BODY |- +# +# * TEST3 is expanded. +# Its prologue pushes the current diversion again. +# DUMP: BODY +# BODY: TEST2a +# diversions: GROW-2, GROW-2, GROW-1, GROW-1, GROW, BODY |- +# TEST3 requires TEST2a, but TEST2a has already been AC_PROVIDE'd, so +# nothing happens. It's body is expanded here, and its epilogue pops a +# diversion. +# DUMP: BODY +# BODY: TEST2a +# GROW - 2: TEST3 +# diversions: GROW - 2, GROW - 1, GROW - 1, GROW, BODY |- +# +# * TEST2b requires TEST3: epilogue +# The current diversion is appended to DUMP, and a diversion is popped. +# DUMP: BODY +# BODY: TEST2a; TEST3 +# diversions: GROW - 1, GROW - 1, GROW, BODY |- +# The content of TEST2b is expanded here. +# DUMP: BODY +# BODY: TEST2a; TEST3 +# GROW - 1: TEST2b, +# diversions: GROW - 1, GROW - 1, GROW, BODY |- +# The epilogue of TEST2b pops a diversion. +# DUMP: BODY +# BODY: TEST2a; TEST3 +# GROW - 1: TEST2b, +# diversions: GROW - 1, GROW, BODY |- +# +# * TEST1 requires TEST2b: epilogue +# The current diversion is appended to DUMP, and a diversion is popped. +# DUMP: BODY +# BODY: TEST2a; TEST3; TEST2b +# diversions: GROW, BODY |- +# +# * TEST1 is expanded: epilogue +# TEST1's own content is in GROW, and it's epilogue pops a diversion. +# DUMP: BODY +# BODY: TEST2a; TEST3; TEST2b +# GROW: TEST1 +# diversions: BODY |- +# Here, the epilogue of TEST1 notices the elaboration is done because +# DUMP and the current diversion are the same, it then undiverts +# GROW by hand, and undefines DUMP. +# DUMP: undefined +# BODY: TEST2a; TEST3; TEST2b; TEST1 +# diversions: BODY |- +# +# +# 2. Keeping track of the expansion stack +# ======================================= +# +# When M4 expansion goes wrong it is often extremely hard to find the +# path amongst macros that drove to the failure. What is needed is +# the stack of macro `calls'. One could imagine that GNU M4 would +# maintain a stack of macro expansions, unfortunately it doesn't, so +# we do it by hand. This is of course extremely costly, but the help +# this stack provides is worth it. Nevertheless to limit the +# performance penalty this is implemented only for m4_defun'd macros, +# not for define'd macros. +# +# The scheme is simplistic: each time we enter an m4_defun'd macros, +# we prepend its name in m4_expansion_stack, and when we exit the +# macro, we remove it (thanks to pushdef/popdef). +# +# In addition, we want to use the expansion stack to detect circular +# m4_require dependencies. This means we need to browse the stack to +# check whether a macro being expanded is m4_require'd. For ease of +# implementation, and certainly for the benefit of performances, we +# don't browse the m4_expansion_stack, rather each time we expand a +# macro FOO we define _m4_expanding(FOO). Then m4_require(BAR) simply +# needs to check whether _m4_expanding(BAR) is defined to diagnose a +# circular dependency. +# +# To improve the diagnostic, in addition to keeping track of the stack +# of macro calls, m4_expansion_stack also records the m4_require +# stack. Note that therefore an m4_defun'd macro being required will +# appear twice in the stack: the first time because it is required, +# the second because it is expanded. We can avoid this, but it has +# two small drawbacks: (i) the implementation is slightly more +# complex, and (ii) it hides the difference between define'd macros +# (which don't appear in m4_expansion_stack) and m4_defun'd macros +# (which do). The more debugging information, the better. + + +# m4_expansion_stack_push(TEXT) +# ----------------------------- +m4_define([m4_expansion_stack_push], +[m4_pushdef([m4_expansion_stack], + [$1]m4_ifdef([m4_expansion_stack], [ +m4_defn([m4_expansion_stack])]))]) + + +# m4_expansion_stack_pop +# ---------------------- +# Dump the expansion stack. +m4_define([m4_expansion_stack_pop], +[m4_popdef([m4_expansion_stack])]) + + +# m4_expansion_stack_dump +# ----------------------- +# Dump the expansion stack. +m4_define([m4_expansion_stack_dump], +[m4_ifdef([m4_expansion_stack], + [m4_errprintn(m4_defn([m4_expansion_stack]))])dnl +m4_errprintn(m4_location[: the top level])]) + + +# _m4_divert(GROW) +# ---------------- +# This diversion is used by the m4_defun/m4_require machinery. It is +# important to keep room before GROW because for each nested +# AC_REQUIRE we use an additional diversion (i.e., two m4_require's +# will use GROW - 2. More than 3 levels has never seemed to be +# needed.) +# +# ... +# - GROW - 2 +# m4_require'd code, 2 level deep +# - GROW - 1 +# m4_require'd code, 1 level deep +# - GROW +# m4_defun'd macros are elaborated here. + +m4_define([_m4_divert(GROW)], 10000) + + +# _m4_defun_pro(MACRO-NAME) +# ------------------------- +# The prologue for Autoconf macros. +m4_define([_m4_defun_pro], +[m4_expansion_stack_push(m4_defn([m4_location($1)])[: $1 is expanded from...])dnl +m4_pushdef([_m4_expanding($1)])dnl +m4_ifdef([_m4_divert_dump], + [m4_divert_push(m4_defn([_m4_divert_diversion]))], + [m4_copy([_m4_divert_diversion], [_m4_divert_dump])dnl +m4_divert_push([GROW])])dnl +]) + + +# _m4_defun_epi(MACRO-NAME) +# ------------------------- +# The Epilogue for Autoconf macros. MACRO-NAME only helps tracing +# the PRO/EPI pairs. +m4_define([_m4_defun_epi], +[m4_divert_pop()dnl +m4_if(_m4_divert_dump, _m4_divert_diversion, + [m4_undivert([GROW])dnl +m4_undefine([_m4_divert_dump])])dnl +m4_expansion_stack_pop()dnl +m4_popdef([_m4_expanding($1)])dnl +m4_provide([$1])dnl +]) + + +# m4_defun(NAME, EXPANSION) +# ------------------------- +# Define a macro which automatically provides itself. Add machinery +# so the macro automatically switches expansion to the diversion +# stack if it is not already using it. In this case, once finished, +# it will bring back all the code accumulated in the diversion stack. +# This, combined with m4_require, achieves the topological ordering of +# macros. We don't use this macro to define some frequently called +# macros that are not involved in ordering constraints, to save m4 +# processing. +m4_define([m4_defun], +[m4_define([m4_location($1)], m4_location)dnl +m4_define([$1], + [_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])]) + + +# m4_defun_once(NAME, EXPANSION) +# ------------------------------ +# As m4_defun, but issues the EXPANSION only once, and warns if used +# several times. +m4_define([m4_defun_once], +[m4_define([m4_location($1)], m4_location)dnl +m4_define([$1], + [m4_provide_ifelse([$1], + [m4_warn([syntax], [$1 invoked multiple times])], + [_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])]) + + +# m4_pattern_forbid(ERE) +# ---------------------- +# Declare that no token matching the extended regular expression ERE +# should be seen in the output but if... +m4_define([m4_pattern_forbid], +[m4_file_append(m4_defn([m4_tmpdir])/forbidden.rx, [$1])]) + + +# m4_pattern_allow(ERE) +# --------------------- +# ... but if that token matches the extended regular expression ERE. +m4_define([m4_pattern_allow], +[m4_file_append(m4_defn([m4_tmpdir])/allowed.rx, [$1])]) + + +## ----------------------------- ## +## Dependencies between macros. ## +## ----------------------------- ## + + +# m4_before(THIS-MACRO-NAME, CALLED-MACRO-NAME) +# --------------------------------------------- +m4_define([m4_before], +[m4_provide_ifelse([$2], + [m4_warn([syntax], [$2 was called before $1])])]) + + +# m4_require(NAME-TO-CHECK, [BODY-TO-EXPAND = NAME-TO-CHECK]) +# ----------------------------------------------------------- +# If NAME-TO-CHECK has never been expanded (actually, if it is not +# m4_provide'd), expand BODY-TO-EXPAND *before* the current macro +# expansion. Once expanded, emit it in _m4_divert_dump. Keep track +# of the m4_require chain in m4_expansion_stack. +# +# The normal cases are: +# +# - NAME-TO-CHECK == BODY-TO-EXPAND +# Which you can use for regular macros with or without arguments, e.g., +# m4_require([AC_PROG_CC], [AC_PROG_CC]) +# m4_require([AC_CHECK_HEADERS(limits.h)], [AC_CHECK_HEADERS(limits.h)]) +# which is just the same as +# m4_require([AC_PROG_CC]) +# m4_require([AC_CHECK_HEADERS(limits.h)]) +# +# - BODY-TO-EXPAND == m4_indir([NAME-TO-CHECK]) +# In the case of macros with irregular names. For instance: +# m4_require([AC_LANG_COMPILER(C)], [indir([AC_LANG_COMPILER(C)])]) +# which means `if the macro named `AC_LANG_COMPILER(C)' (the parens are +# part of the name, it is not an argument) has not been run, then +# call it.' +# Had you used +# m4_require([AC_LANG_COMPILER(C)], [AC_LANG_COMPILER(C)]) +# then m4_require would have tried to expand `AC_LANG_COMPILER(C)', i.e., +# call the macro `AC_LANG_COMPILER' with `C' as argument. +# +# You could argue that `AC_LANG_COMPILER', when it receives an argument +# such as `C' should dispatch the call to `AC_LANG_COMPILER(C)'. But this +# `extension' prevents `AC_LANG_COMPILER' from having actual arguments that +# it passes to `AC_LANG_COMPILER(C)'. +m4_define([m4_require], +[m4_expansion_stack_push(m4_location[: $1 is required by...])dnl +m4_ifdef([_m4_expanding($1)], + [m4_fatal([$0: circular dependency of $1])])dnl +m4_ifndef([_m4_divert_dump], + [m4_fatal([$0: cannot be used outside of an m4_defun'd macro])])dnl +m4_provide_ifelse([$1], + [], + [m4_divert_push(m4_eval(m4_divnum - 1))dnl +m4_default([$2], [$1]) +m4_divert(m4_defn([_m4_divert_dump]))dnl +m4_undivert(m4_defn([_m4_divert_diversion]))dnl +m4_divert_pop(m4_defn([_m4_divert_dump]))])dnl +m4_provide_ifelse([$1], + [], + [m4_warn([syntax], + [$1 is m4_require'd but is not m4_defun'd])])dnl +m4_expansion_stack_pop()dnl +]) + + +# m4_expand_once(TEXT, [WITNESS = TEXT]) +# -------------------------------------- +# If TEXT has never been expanded, expand it *here*. Use WITNESS as +# as a memory that TEXT has already been expanded. +m4_define([m4_expand_once], +[m4_provide_ifelse(m4_ifval([$2], [[$2]], [[$1]]), + [], + [m4_provide(m4_ifval([$2], [[$2]], [[$1]]))[]$1])]) + + +# m4_provide(MACRO-NAME) +# ---------------------- +m4_define([m4_provide], +[m4_define([m4_provide($1)])]) + + +# m4_provide_ifelse(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED. +# The purpose of this macro is to provide the user with a means to +# check macros which are provided without letting her know how the +# information is coded. +m4_define([m4_provide_ifelse], +[m4_ifdef([m4_provide($1)], + [$2], [$3])]) + + +## -------------------- ## +## 9. Text processing. ## +## -------------------- ## + +# m4_cr_letters +# m4_cr_LETTERS +# m4_cr_Letters +# ------------- +m4_define([m4_cr_letters], [abcdefghijklmnopqrstuvwxyz]) +m4_define([m4_cr_LETTERS], [ABCDEFGHIJKLMNOPQRSTUVWXYZ]) +m4_define([m4_cr_Letters], +m4_defn([m4_cr_letters])dnl +m4_defn([m4_cr_LETTERS])dnl +) + +# m4_cr_digits +# ------------ +m4_define([m4_cr_digits], [0123456789]) + + +# m4_cr_symbols1 & m4_cr_symbols2 +# ------------------------------- +m4_define([m4_cr_symbols1], +m4_defn([m4_cr_Letters])dnl +_) + +m4_define([m4_cr_symbols2], +m4_defn([m4_cr_symbols1])dnl +m4_defn([m4_cr_digits])dnl +) + + +# m4_re_string +# ------------ +# Regexp for `[a-zA-Z_0-9]*' +m4_define([m4_re_string], +m4_dquote(m4_defn([m4_cr_symbols2]))dnl +[*]dnl +) + + +# m4_re_word +# ---------- +# Regexp for `[a-zA-Z_][a-zA-Z_0-9]*' +m4_define([m4_re_word], +m4_dquote(m4_defn([m4_cr_symbols1]))dnl +m4_defn([m4_re_string])dnl +) + +# m4_tolower(STRING) +# m4_toupper(STRING) +# ------------------ +# These macros lowercase and uppercase strings. +m4_define([m4_tolower], +[m4_translit([$1], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ], + [abcdefghijklmnopqrstuvwxyz])]) + +m4_define([m4_toupper], +[m4_translit([$1], + [abcdefghijklmnopqrstuvwxyz], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ])]) + + +# m4_split(STRING, [REGEXP]) +# -------------------------- +# +# Split STRING into an m4 list of quoted elements. The elements are +# quoted with [ and ]. Beginning spaces and end spaces *are kept*. +# Use m4_strip to remove them. +# +# REGEXP specifies where to split. Default is [\t ]+. +# +# Pay attention to the m4_changequotes. Inner m4_changequotes exist for +# obvious reasons (we want to insert square brackets). Outer +# m4_changequotes are needed because otherwise the m4 parser, when it +# sees the closing bracket we add to the result, believes it is the +# end of the body of the macro we define. +# +# Also, notice that $1 is quoted twice, since we want the result to +# be quoted. Then you should understand that the argument of +# patsubst is ``STRING'' (i.e., with additional `` and ''). +# +# This macro is safe on active symbols, i.e.: +# m4_define(active, ACTIVE) +# m4_split([active active ])end +# => [active], [active], []end + +m4_changequote(<<, >>) +m4_define(<<m4_split>>, +<<m4_changequote(``, '')dnl +[dnl Can't use m4_default here instead of m4_if, because m4_default uses +dnl [ and ] as quotes. +m4_patsubst(````$1'''', + m4_if(``$2'',, ``[ ]+'', ``$2''), + ``], ['')]dnl +m4_changequote([, ])>>) +m4_changequote([, ]) + + + +# m4_flatten(STRING) +# ------------------ +# If STRING contains end of lines, replace them with spaces. If there +# are backslashed end of lines, remove them. This macro is safe with +# active symbols. +# m4_define(active, ACTIVE) +# m4_flatten([active +# act\ +# ive])end +# => active activeend +m4_define([m4_flatten], +[m4_translit(m4_patsubst([[[$1]]], [\\ +]), [ +], [ ])]) + + +# m4_strip(STRING) +# ---------------- +# Expands into STRING with tabs and spaces singled out into a single +# space, and removing leading and trailing spaces. +# +# This macro is robust to active symbols. +# m4_define(active, ACTIVE) +# m4_strip([ active active ])end +# => active activeend +# +# This macro is fun! Because we want to preserve active symbols, STRING +# must be quoted for each evaluation, which explains there are 4 levels +# of brackets around $1 (don't forget that the result must be quoted +# too, hence one more quoting than applications). +# +# Then notice the patsubst of the middle: it is in charge of removing +# the leading space. Why not just `patsubst(..., [^ ])'? Because this +# macro will receive the output of the preceding patsubst, i.e. more or +# less [[STRING]]. So if there is a leading space in STRING, then it is +# the *third* character, since there are two leading `['; Equally for +# the outer patsubst. +m4_define([m4_strip], +[m4_patsubst(m4_patsubst(m4_patsubst([[[[$1]]]], + [[ ]+], [ ]), + [^\(..\) ], [\1]), + [ \(.\)$], [\1])]) + + +# m4_normalize(STRING) +# -------------------- +# Apply m4_flatten and m4_strip to STRING. +# +# The argument is quoted, so that the macro is robust to active symbols: +# +# m4_define(active, ACTIVE) +# m4_normalize([ act\ +# ive +# active ])end +# => active activeend + +m4_define([m4_normalize], +[m4_strip(m4_flatten([$1]))]) + + + +# m4_join(SEP, ARG1, ARG2...) +# --------------------------- +# Produce ARG1SEPARG2...SEPARGn. +m4_defun([m4_join], +[m4_case([$#], + [1], [], + [2], [[$2]], + [[$2][$1]m4_join([$1], m4_shift(m4_shift($@)))])]) + + + +# m4_append(MACRO-NAME, STRING) +# ----------------------------- +# Redefine MACRO-NAME to hold its former content plus STRING at the +# end. It is valid to use this macro with MACRO-NAME undefined. +# +# This macro is robust to active symbols. It can be used to grow +# strings. +# +# | m4_define(active, ACTIVE) +# | m4_append([sentence], [This is an]) +# | m4_append([sentence], [ active ]) +# | m4_append([sentence], [symbol.]) +# | sentence +# | m4_undefine([active])dnl +# | sentence +# => This is an ACTIVE symbol. +# => This is an active symbol. +# +# It can be used to define hooks. +# +# | m4_define(active, ACTIVE) +# | m4_append([hooks], [m4_define([act1], [act2])]) +# | m4_append([hooks], [m4_define([act2], [active])]) +# | m4_undefine([active]) +# | act1 +# | hooks +# | act1 +# => act1 +# => +# => active +m4_define([m4_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])])[$2])]) + + +# m4_list_append(MACRO-NAME, STRING) +# ---------------------------------- +# Same as `m4_append', but each element is separated by `, '. +m4_define([m4_list_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1]), ])[$2])]) + + +# m4_foreach_quoted(VARIABLE, LIST, EXPRESSION) +# --------------------------------------------- +# FIXME: This macro should not exists. Currently it's used only in +# m4_wrap, which needs to be rewritten. But it's godam hard. +m4_define([m4_foreach_quoted], +[m4_pushdef([$1], [])_m4_foreach_quoted($@)m4_popdef([$1])]) + +# Low level macros used to define m4_foreach. +m4_define([m4_car_quoted], [[$1]]) +m4_define([_m4_foreach_quoted], +[m4_if($2, [()], , + [m4_define([$1], [m4_car_quoted$2])$3[]_m4_foreach_quoted([$1], + [(m4_shift$2)], + [$3])])]) + + +# m4_text_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH]) +# ------------------------------------------------------- +# Expands into STRING wrapped to hold in WIDTH columns (default = 79). +# If prefix is set, each line is prefixed with it. If FIRST-PREFIX is +# specified, then the first line is prefixed with it. As a special +# case, if the length of the first prefix is greater than that of +# PREFIX, then FIRST-PREFIX will be left alone on the first line. +# +# Typical outputs are: +# +# m4_text_wrap([Short string */], [ ], [/* ], 20) +# => /* Short string */ +# +# m4_text_wrap([Much longer string */], [ ], [/* ], 20) +# => /* Much longer +# => string */ +# +# m4_text_wrap([Short doc.], [ ], [ --short ], 30) +# => --short Short doc. +# +# m4_text_wrap([Short doc.], [ ], [ --too-wide ], 30) +# => --too-wide +# => Short doc. +# +# m4_text_wrap([Super long documentation.], [ ], [ --too-wide ], 30) +# => --too-wide +# => Super long +# => documentation. +# +# FIXME: there is no checking of a longer PREFIX than WIDTH, but do +# we really want to bother with people trying each single corner +# of a software? +# +# This macro does not leave a trailing space behind the last word, +# what complicates it a bit. The algorithm is stupid simple: all the +# words are preceded by m4_Separator which is defined to empty for the +# first word, and then ` ' (single space) for all the others. +m4_define([m4_text_wrap], +[m4_pushdef([m4_Prefix], m4_default([$2], []))dnl +m4_pushdef([m4_Prefix1], m4_default([$3], [m4_Prefix]))dnl +m4_pushdef([m4_Width], m4_default([$4], 79))dnl +m4_pushdef([m4_Cursor], m4_len(m4_Prefix1))dnl +m4_pushdef([m4_Separator], [])dnl +m4_Prefix1[]dnl +m4_if(m4_eval(m4_Cursor > m4_len(m4_Prefix)), + 1, [m4_define([m4_Cursor], m4_len(m4_Prefix)) +m4_Prefix])[]dnl +m4_foreach_quoted([m4_Word], (m4_split(m4_normalize([$1]))), +[m4_define([m4_Cursor], m4_eval(m4_Cursor + len(m4_Word) + 1))dnl +dnl New line if too long, else insert a space unless it is the first +dnl of the words. +m4_if(m4_eval(m4_Cursor > m4_Width), + 1, [m4_define([m4_Cursor], + m4_eval(m4_len(m4_Prefix) + m4_len(m4_Word) + 1))] +m4_Prefix, + [m4_Separator])[]dnl +m4_Word[]dnl +m4_define([m4_Separator], [ ])])dnl +m4_popdef([m4_Separator])dnl +m4_popdef([m4_Cursor])dnl +m4_popdef([m4_Width])dnl +m4_popdef([m4_Prefix1])dnl +m4_popdef([m4_Prefix])dnl +]) + + + +## ----------------------- ## +## 10. Number processing. ## +## ----------------------- ## + +# m4_sign(A) +# ---------- +# +# The sign of the integer A. +m4_define([m4_sign], +[m4_match([$1], + [^-], -1, + [^0+], 0, + 1)]) + +# m4_cmp(A, B) +# ------------ +# +# Compare two integers. +# A < B -> -1 +# A = B -> 0 +# A > B -> 1 +m4_define([m4_cmp], +[m4_sign(m4_eval([$1 - $2]))]) + + +# m4_list_cmp(A, B) +# ----------------- +# +# Compare the two lists of integers A and B. For instance: +# m4_list_cmp((1, 0), (1)) -> 0 +# m4_list_cmp((1, 0), (1, 0)) -> 0 +# m4_list_cmp((1, 2), (1, 0)) -> 1 +# m4_list_cmp((1, 2, 3), (1, 2)) -> 1 +# m4_list_cmp((1, 2, -3), (1, 2)) -> -1 +# m4_list_cmp((1, 0), (1, 2)) -> -1 +# m4_list_cmp((1), (1, 2)) -> -1 +m4_define([m4_list_cmp], +[m4_if([$1$2], [()()], 0, + [$1], [()], [m4_list_cmp((0), [$2])], + [$2], [()], [m4_list_cmp([$1], (0))], + [m4_case(m4_cmp(m4_car$1, m4_car$2), + -1, -1, + 1, 1, + 0, [m4_list_cmp((m4_shift$1), (m4_shift$2))])])]) + + + +## ------------------------ ## +## 11. Version processing. ## +## ------------------------ ## + + +# m4_version_unletter(VERSION) +# ---------------------------- +# Normalize beta version numbers with letters to numbers only for comparison. +# +# Nl -> (N+1).-1.(l#) +# +#i.e., 2.14a -> 2.15.-1.1, 2.14b -> 2.15.-1.2, etc. +# This macro is absolutely not robust to active macro, it expects +# reasonable version numbers and is valid up to `z', no double letters. +m4_define([m4_version_unletter], +[m4_translit(m4_patsubst(m4_patsubst(m4_patsubst([$1], + [\([0-9]+\)\([abcdefghi]\)], + [m4_eval(\1 + 1).-1.\2]), + [\([0-9]+\)\([jklmnopqrs]\)], + [m4_eval(\1 + 1).-1.1\2]), + [\([0-9]+\)\([tuvwxyz]\)], + [m4_eval(\1 + 1).-1.2\2]), + [abcdefghijklmnopqrstuvwxyz], + [12345678901234567890123456])]) + + +# m4_version_compare(VERSION-1, VERSION-2) +# ---------------------------------------- +# Compare the two version numbers and expand into +# -1 if VERSION-1 < VERSION-2 +# 0 if = +# 1 if > +m4_define([m4_version_compare], +[m4_list_cmp((m4_split(m4_version_unletter([$1]), [\.])), + (m4_split(m4_version_unletter([$2]), [\.])))]) + + + +## ------------------- ## +## 12. File handling. ## +## ------------------- ## + + +# It is a real pity that M4 comes with no macros to bind a diversion +# to a file. So we have to deal without, which makes us a lot more +# fragile that we should. + + +# m4_file_append(FILE-NAME, CONTENT) +# ---------------------------------- +m4_define([m4_file_append], +[m4_syscmd([cat >>$1 <<_m4eof +$2 +_m4eof +]) +m4_if(m4_sysval, [0], [], + [m4_fatal([$0: cannot write: $1])])]) + + + +## ------------------------ ## +## 13. Setting M4sugar up. ## +## ------------------------ ## + + +# m4_init +# ------- +m4_define([m4_init], +[# We need a tmp directory. +m4_ifndef([m4_tmpdir], + [m4_define([m4_tmpdir], [/tmp])]) + +# M4sugar reserves `m4_[A-Za-z0-9_]*'. We'd need \b and +, +# but they are not portable. +m4_pattern_forbid([^m4_]) +m4_pattern_forbid([^dnl$]) + +# Check the divert push/pop perfect balance. +m4_wrap([m4_ifdef([_m4_divert_diversion], + [m4_fatal([$0: unbalanced m4_divert_push:] +m4_defn([m4_divert_stack]))])[]]) + +m4_divert_push([KILL]) +m4_wrap([m4_divert_pop([KILL])[]]) +]) |