Create libm4.m4.

* Makefile.am: Adjusted for libm4.m4.

* acgeneral.m4 (m4_errprint, m4_warn, m4_fatal, m4_prefix,
m4_eval, m4_shift, m4_format, m4_include_unique, m4_include,
m4_sinclude, m4_quote, m4_split, m4_join, m4_strip, m4_append,
m4_list_append, ifval, ifset, m4_default, m4_case, m4_match,
m4_foreach): Moved from here, to...
* libm4.m4: here.
* acgeneral.m4 (AC_WRAP): Moved from here, to...
* libm4.m4 (m4_wrap): here.  All callers changed.

* acgeneral.m4: Don't include acversion.m4.
* autoconf.m4: Include libm4.m4 and acversion.m4.
* autoheader.m4: Likewise.
This commit is contained in:
Akim Demaille 2000-02-07 17:42:03 +00:00
parent b519547b61
commit 6b8dfc89ca
11 changed files with 587 additions and 968 deletions

View File

@ -1,3 +1,22 @@
2000-02-07 Akim Demaille <akim@epita.fr>
Create libm4.m4.
* Makefile.am: Adjusted for libm4.m4.
* acgeneral.m4 (m4_errprint, m4_warn, m4_fatal, m4_prefix,
m4_eval, m4_shift, m4_format, m4_include_unique, m4_include,
m4_sinclude, m4_quote, m4_split, m4_join, m4_strip, m4_append,
m4_list_append, ifval, ifset, m4_default, m4_case, m4_match,
m4_foreach): Moved from here, to...
* libm4.m4: here.
* acgeneral.m4 (AC_WRAP): Moved from here, to...
* libm4.m4 (m4_wrap): here. All callers changed.
* acgeneral.m4: Don't include acversion.m4.
* autoconf.m4: Include libm4.m4 and acversion.m4.
* autoheader.m4: Likewise.
2000-02-07 Akim Demaille <akim@epita.fr>
AC_CHECK_SIZEOF: Fix a bug, use standard default headers, and

View File

@ -1,7 +1,7 @@
## Process this file with automake to create Makefile.in.
## Makefile for Autoconf.
## Copyright (C) 1999 Free Software Foundation, Inc.
## Copyright (C) 1999, 2000 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
@ -38,7 +38,7 @@ EXTRA_SCRIPTS = autoscan
distpkgdataDATA = \
acfunctions acheaders acidentifiers acmakevars acprograms \
acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
libm4.m4 acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
nodistpkgdataDATA = autoconf.m4f autoheader.m4f acversion.m4
@ -95,13 +95,12 @@ editpl = sed -e 's,@''datadir''@,$(pkgdatadir),g' -e 's,@''PERL''@,$(PERL),g' \
.m4.m4f:
@case `$(M4) --help </dev/null 2>&1` in \
*reload-state*) echo freezing $*.m4; \
$(M4) -F $*.m4f -I${srcdir} ${srcdir}/$*.m4 ;; \
*traditional*) ;; \
*) echo Error: Autoconf requires GNU m4 1.1 or later; exit 1 ;; \
$(M4) -F $*.m4f -I$(srcdir) $(srcdir)/$*.m4 ;; \
*) echo Error: Autoconf requires GNU m4 1.4 or later; exit 1 ;; \
esac
autoconf.m4f: autoconf.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoconf.m4f: autoconf.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
# The documentation

View File

@ -81,7 +81,7 @@ EXTRA_SCRIPTS = autoscan
# s/nodistpackageDATA/nodist_pkgdata_DATA/
# and adapt dependencies once we use a more recent Automake
distpkgdataDATA = acfunctions acheaders acidentifiers acmakevars acprograms acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
distpkgdataDATA = acfunctions acheaders acidentifiers acmakevars acprograms libm4.m4 acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
nodistpkgdataDATA = autoconf.m4f autoheader.m4f acversion.m4
@ -605,13 +605,12 @@ install-data-hook: INSTALL.txt
.m4.m4f:
@case `$(M4) --help </dev/null 2>&1` in \
*reload-state*) echo freezing $*.m4; \
$(M4) -F $*.m4f -I${srcdir} ${srcdir}/$*.m4 ;; \
*traditional*) ;; \
*) echo Error: Autoconf requires GNU m4 1.1 or later; exit 1 ;; \
$(M4) -F $*.m4f -I$(srcdir) $(srcdir)/$*.m4 ;; \
*) echo Error: Autoconf requires GNU m4 1.4 or later; exit 1 ;; \
esac
autoconf.m4f: autoconf.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoconf.m4f: autoconf.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
# The documentation

View File

@ -49,399 +49,6 @@ dnl Written by David MacKenzie, with help from
dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
dnl Roland McGrath, Noah Friedman, david d zuhn, and many others.
dnl
divert(-1)dnl Throw away output until AC_INIT is called.
changequote([, ])
include(acversion.m4)
dnl Some old m4's don't support m4exit. But they provide
dnl equivalent functionality by core dumping because of the
dnl long macros we define.
ifdef([__gnu__], , [errprint(Autoconf requires GNU m4.
Install it before installing Autoconf or set the
M4 environment variable to its path name.
)m4exit(2)])
dnl m4_errprint(MSG)
dnl ----------------
dnl Same as `errprint', but reports the file and line.
define(m4_errprint, [errprint(__file__:__line__: [$1
])])
dnl m4_warn(MSG)
dnl ------------
dnl Warn the user.
define(m4_warn, [m4_errprint([warning: $1])])
dnl m4_fatal(MSG, [EXIT-STATUS])
dnl ----------------------------
dnl Fatal the user. :)
define(m4_fatal,
[m4_errprint([error: $1])dnl
m4exit(ifelse([$2],, 1, [$2]))])
dnl Some m4 internals have names colliding with tokens we might use.
dnl Rename them a` la `m4 --prefix-builtins'.
define([m4_prefix],
[define([m4_$1], defn([$1]))
undefine([$1])])
m4_prefix([eval])
m4_prefix([shift])
m4_prefix([format])
dnl We also want to neutralize include (and sinclude for symmetry),
dnl but we want to extend them slightly: warn when a file is included
dnl several times. This is in general a dangerous operation because
dnl quite nobody quotes the first argument of define.
dnl
dnl For instance in the following case:
dnl define(foo, [bar])
dnl then a second reading will turn into
dnl define(bar, [bar])
dnl which is certainly not what was meant.
dnl m4_include_unique(FILE)
dnl -----------------------
dnl Declare that the FILE was loading; and warn if it has already
dnl been included.
define(m4_include_unique,
[ifdef([m4_include($1)],
[m4_warn([file `$1' included several times])])dnl
define([m4_include($1)])])
dnl m4_include(FILE)
dnl ----------------
dnl As the builtin include, but warns against multiple inclusions.
define(m4_include,
[m4_include_unique([$1])dnl
builtin([include], [$1])])
dnl m4_sinclude(FILE)
dnl -----------------
dnl As the builtin sinclude, but warns against multiple inclusions.
define(m4_sinclude,
[m4_include_unique([$1])dnl
builtin([sinclude], [$1])])
dnl Neutralize include and sinclude.
undefine([include])
undefine([sinclude])
dnl ------------------------------------------------------------
dnl Text processing in m4.
dnl ------------------------------------------------------------
dnl m4_quote(STRING)
dnl ----------------
dnl Return STRING quoted.
dnl
dnl It is important to realize the difference between `quote(exp)' and
dnl `[exp]': in the first case you obtain the quoted *result* of the
dnl expansion of EXP, while in the latter you just obtain the string
dnl `exp'.
define([m4_quote], [[$@]])
dnl m4_split(STRING, [REGEXP])
dnl --------------------------
dnl Split STRING into an m4 list of quoted elements. The elements are
dnl quoted with [ and ]. Beginning spaces and end spaces *are kept*.
dnl Use m4_strip to remove them.
dnl
dnl REGEXP specifies where to split. Default is [\t ]+.
dnl
dnl Pay attention to the changequotes. Inner changequotes exist for
dnl obvious reasons (we want to insert square brackets). Outer
dnl changequotes are needed because otherwise the m4 parser, when it
dnl sees the closing bracket we add to the result, believes it is the
dnl end of the body of the macro we define.
dnl
dnl Also, notice that $1 is quoted twice, since we want the result to be
dnl quoted. Then you should understand that the argument of patsubst is
dnl ``STRING'' (i.e., with additional `` and '').
dnl
dnl This macro is safe on active symbols, i.e.:
dnl define(active, ACTIVE)
dnl m4_split([active active ])end
dnl => [active], [active], []end
changequote(<<, >>)
define(<<m4_split>>,
<<changequote(``, '')dnl
[dnl Can't use m4_default here instead of ifelse, because m4_default uses
dnl [ and ] as quotes.
patsubst(````$1'''',
ifelse(``$2'',, ``[ ]+'', ``$2''),
``], ['')]dnl
changequote([, ])>>)
changequote([, ])
dnl m4_join(STRING)
dnl ---------------
dnl If STRING contains end of lines, replace them with spaces. If there
dnl are backslashed end of lines, remove them. This macro is safe with
dnl active symbols.
dnl define(active, ACTIVE)
dnl m4_join([active
dnl act\
dnl ive])end
dnl => active activeend
define([m4_join],
[translit(patsubst([[[$1]]], [\\
]), [
], [ ])])
dnl m4_strip(STRING)
dnl ----------------
dnl Expands into STRING with tabs and spaces singled out into a single
dnl space, and removing leading and trailing spaces.
dnl
dnl This macro is robust to active symbols.
dnl define(active, ACTIVE)
dnl m4_strip([ active active ])end
dnl => active activeend
dnl
dnl This macro is fun! Because we want to preserve active symbols, STRING
dnl must be quoted for each evaluation, which explains there are 4 levels
dnl of brackets around $1 (don't forget that the result must be quoted
dnl too, hence one more quoting than applications).
dnl
dnl Then notice the patsubst of the middle: it is in charge of removing
dnl the leading space. Why not just `patsubst(..., [^ ])'? Because this
dnl macro will receive the output of the preceding patsubst, i.e. more or
dnl less [[STRING]]. So if there is a leading space in STRING, then it is
dnl the *third* character, since there are two leading `['; Equally for
dnl the outer patsubst.
define([m4_strip],
[patsubst(patsubst(patsubst([[[[$1]]]],
[[ ]+], [ ]),
[^\(..\) ], [\1]),
[ \(.\)$], [\1])])
dnl m4_append(MACRO-NAME, STRING)
dnl -----------------------------
dnl Redefine MACRO-NAME to hold its former content plus STRING at the
dnl end. It is valid to use this macro with MACRO-NAME undefined.
dnl
dnl This macro is robust to active symbols. It can be used to grow
dnl strings.
dnl
dnl | define(active, ACTIVE)
dnl | m4_append([sentence], [This is an])
dnl | m4_append([sentence], [ active ])
dnl | m4_append([sentence], [symbol.])
dnl | sentence
dnl | undefine([active])dnl
dnl | sentence
dnl => This is an ACTIVE symbol.
dnl => This is an active symbol.
dnl
dnl It can be used to define hooks.
dnl
dnl | define(active, ACTIVE)
dnl | m4_append([hooks], [define([act1], [act2])])
dnl | m4_append([hooks], [define([act2], [active])])
dnl | undefine([active])
dnl | act1
dnl | hooks
dnl | act1
dnl => act1
dnl =>
dnl => active
define(m4_append,
[define([$1],
ifdef([$1], [defn([$1])])[$2])])
dnl m4_list_append(MACRO-NAME, STRING)
dnl ----------------------------------
dnl Same as `m4_append', but each element is separated by `, '.
define(m4_list_append,
[define([$1],
ifdef([$1], [defn([$1]), ])[$2])])
dnl ------------------------------------------------------------
dnl Some additional m4 structural control.
dnl ------------------------------------------------------------
dnl Both `ifval' and `ifset' tests against the empty string. The
dnl difference is that `ifset' is specialized on macros.
dnl
dnl In case of arguments of macros, eg $[1], it makes little difference.
dnl In the case of a macro `FOO', you don't want to check `ifval(FOO,
dnl TRUE)', because if `FOO' expands with commas, there is a shifting of
dnl the arguments. So you want to run `ifval([FOO])', but then you just
dnl compare the *string* `FOO' against `', which, of course fails.
dnl
dnl So you want a variation of `ifset' that expects a macro name as $[1].
dnl If this macro is both defined and defined to a non empty value, then
dnl it runs TRUE etc.
dnl ifval(COND, IF-TRUE[, IF-FALSE])
dnl --------------------------------
dnl If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE.
dnl Comparable to ifdef.
define([ifval], [ifelse([$1],[],[$3],[$2])])
dnl ifset(MACRO, IF-TRUE[, IF-FALSE])
dnl --------------------------------
dnl If MACRO has no definition, or of its definition is the empty string,
dnl expand IF-FALSE, otherwise IF-TRUE.
define([ifset],
[ifdef([$1],
[ifelse(defn([$1]), [], [$3], [$2])],
[$3])])
dnl m4_default(EXP1, EXP2)
dnl ----------------------
dnl Returns EXP1 if non empty, otherwise EXP2.
define([m4_default], [ifval([$1], [$1], [$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.
define(m4_case,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
[$1], [$2], [$3],
[m4_case([$1], m4_shift(m4_shift(m4_shift($@))))])])
# 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.
define(m4_match,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
regexp([$1], [$2]), -1, [m4_match([$1],
m4_shift(m4_shift(m4_shift($@))))],
[$3])])
## --------------------- ##
## Implementing m4 loops ##
## --------------------- ##
# Implementing loops (`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(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach',
# | `pushdef(`$1', `')_foreach(`$1', `$2', `$3')popdef(`$1')')
# | define(`_arg1', `$1')
# | define(`_foreach',
# | `ifelse(`$2', `()', ,
# | `define(`$1', _arg1$2)$3`'_foreach(`$1', (shift$2), `$3')')')
#
# But then if you run
#
# | define(a, 1)
# | define(b, 2)
# | define(c, 3)
# | foreach(`f', `(`a', `(b', `c)')', `echo f
# | ')
#
# it gives
#
# => echo 1
# => echo (2,3)
#
# which is not what is expected.
#
# Once you understood this, you turn yourself into a quoting wizard,
# and come up with the following solution:
#
# | # foreach(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach', `pushdef(`$1', `')_foreach($@)popdef(`$1')')
# | define(`_arg1', ``$1'')
# | define(`_foreach',
# | `ifelse($2, `()', ,
# | `define(`$1', `_arg1$2')$3`'_foreach(`$1', `(shift$2)', `$3')')')
#
# which this time answers
#
# => echo a
# => echo (b
# => echo c)
#
# Bingo!
# m4_foreach(VARIABLE, LIST, EXPRESSION)
# --------------------------------------
# Expand EXPRESSION assigning to VARIABLE each value of the LIST
# (LIST should have the form `[(item_1, item_2, ..., item_n)]'),
# i.e. the whole list should be *quoted*. Quote members too if
# you don't want them to be expanded.
#
# This macro is robust to active symbols:
# define(active, ACTIVE)
# m4_foreach([Var], [([active], [b], [active])], [-Var-])end
# => -active--b--active-end
define(m4_foreach,
[pushdef([$1], [])_m4_foreach($@)popdef([$1])])
dnl Low level macros used to define m4_foreach
define(m4_car, [[$1]])
define(_m4_foreach,
[ifelse($2, [()], ,
[define([$1], [m4_car$2])$3[]_m4_foreach([$1],
[(m4_shift$2)],
[$3])])])
dnl ### Defining macros
@ -733,74 +340,9 @@ AC_DEFUN(AC_SPECIALIZE,
[indir([$1], m4_shift($@))])])
dnl ## --------------------------------- ##
dnl ## Helping macros to display strings ##
dnl ## --------------------------------- ##
dnl AC_WRAP(STRING [, PREFIX[, FIRST-PREFIX[, WIDTH]]]]))
dnl -----------------------------------------------------
dnl Expands into STRING wrapped to hold in WIDTH columns (default = 79).
dnl If prefix is set, each line is prefixed with it. If FIRST-PREFIX is
dnl specified, then the first line is prefixed with it. As a special
dnl case, if the length of the first prefix is greater than that of
dnl PREFIX, then FIRST-PREFIX will be left alone on the first line.
dnl
dnl Typical outputs are:
dnl
dnl AC_WRAP([Short string */], [ ], [/* ], 20)
dnl => /* Short string */
dnl
dnl AC_WRAP([Much longer string */], [ ], [/* ], 20)
dnl => /* Much longer
dnl => string */
dnl
dnl AC_WRAP([Short doc.], [ ], [ --short ], 30)
dnl => --short Short doc.
dnl
dnl AC_WRAP([Short doc.], [ ], [ --too-wide ], 30)
dnl => --too-wide
dnl => Short doc.
dnl
dnl AC_WRAP([Super long documentation.], [ ], [ --too-wide ], 30)
dnl => --too-wide
dnl => Super long
dnl => documentation.
dnl
dnl FIXME: there is no checking of a longer PREFIX than WIDTH, but do
dnl we really want to bother with people trying each single corner
dnl of a software?
dnl
dnl This macro does not leave a trailing space behind the last word,
dnl what complicates it a bit. The algorithm is stupid simple: all the
dnl words are preceded by AC_Separator which is defined to empty for the
dnl first word, and then ` ' (single space) for all the others.
define([AC_WRAP],
[pushdef([AC_Prefix], m4_default([$2], []))dnl
pushdef([AC_Prefix1], m4_default([$3], [AC_Prefix]))dnl
pushdef([AC_Width], m4_default([$4], 79))dnl
pushdef([AC_Cursor], len(AC_Prefix1))dnl
pushdef([AC_Separator], [])dnl
AC_Prefix1[]dnl
ifelse(m4_eval(AC_Cursor > len(AC_Prefix)),
1, [define([AC_Cursor], len(AC_Prefix))
AC_Prefix])[]dnl
AC_FOREACH([AC_Word], [$1],
[define([AC_Cursor], m4_eval(AC_Cursor + len(AC_Word) + 1))dnl
dnl New line if too long, else insert a space unless it is the first
dnl of the words.
ifelse(m4_eval(AC_Cursor > AC_Width),
1, [define([AC_Cursor], m4_eval(len(AC_Prefix) + len(AC_Word) + 1))]
AC_Prefix,
[AC_Separator])[]dnl
AC_Word[]dnl
define([AC_Separator], [ ])])dnl
popdef([AC_Separator])dnl
popdef([AC_Cursor])dnl
popdef([AC_Width])dnl
popdef([AC_Prefix1])dnl
popdef([AC_Prefix])dnl
])
## --------------------------------- ##
## Helping macros to display strings ##
## --------------------------------- ##
dnl AC_HELP_STRING(LHS, RHS[, COLUMN])
@ -847,7 +389,7 @@ dnl
define([AC_HELP_STRING],
[pushdef([AC_Prefix], m4_default([$3], [ ]))dnl
pushdef([AC_Prefix_Format], [ %-]m4_eval(len(AC_Prefix) - 3)[s ])dnl [ %-23s ]
AC_WRAP([$2], AC_Prefix, m4_format(AC_Prefix_Format, [$1]))dnl
m4_wrap([$2], AC_Prefix, m4_format(AC_Prefix_Format, [$1]))dnl
popdef([AC_Prefix_Format])dnl
popdef([AC_Prefix])dnl
])
@ -859,7 +401,7 @@ dnl AC_INIT_NOTICE
dnl --------------
AC_DEFUN(AC_INIT_NOTICE,
[# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using Autoconf version] AC_ACVERSION [
# Generated automatically using Autoconf version ]AC_ACVERSION[
# Copyright (C) 1992, 93, 94, 95, 96, 98, 1999 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
@ -3490,16 +3032,16 @@ dnl so uname gets run too.
# Files that config.status was made for.
ifset([AC_LIST_FILES], [config_files="\\
AC_WRAP(AC_LIST_FILES, [ ])"
m4_wrap(AC_LIST_FILES, [ ])"
])dnl
ifset([AC_LIST_HEADERS], [config_headers="\\
AC_WRAP(AC_LIST_HEADERS, [ ])"
m4_wrap(AC_LIST_HEADERS, [ ])"
])dnl
ifset([AC_LIST_LINKS], [config_links="\\
AC_WRAP(AC_LIST_LINKS, [ ])"
m4_wrap(AC_LIST_LINKS, [ ])"
])dnl
ifset([AC_LIST_COMMANDS], [config_commands="\\
AC_WRAP(AC_LIST_COMMANDS, [ ])"
m4_wrap(AC_LIST_COMMANDS, [ ])"
])dnl
ac_cs_usage="\\

View File

@ -20,9 +20,11 @@ dnl 02111-1307, USA.
dnl
dnl Written by David MacKenzie.
dnl
include(acgeneral.m4)dnl
builtin(include, acspecific.m4)dnl
builtin(include, acoldnames.m4)dnl
include(libm4.m4)dnl
m4_include(acversion.m4)dnl
m4_include(acgeneral.m4)dnl
m4_include(acspecific.m4)dnl
m4_include(acoldnames.m4)dnl
dnl Do not sinclude acsite.m4 here, because it may not be installed
dnl yet when Autoconf is frozen.
dnl Do not sinclude ./aclocal.m4 here, to prevent it from being frozen.

View File

@ -19,7 +19,9 @@ dnl 02111-1307, USA.
dnl
dnl Written by Roland McGrath.
dnl
include(acgeneral.m4)dnl
include(libm4.m4)dnl
m4_include(acversion.m4)dnl
m4_include(acgeneral.m4)dnl
m4_include(acspecific.m4)dnl
m4_include(acoldnames.m4)dnl
@ -111,7 +113,7 @@ dnl Issue an autoheader template for KEY, i.e., a comment composed
dnl of DESCRIPTION (properly wrapped), and then #undef KEY.
define([AH_TEMPLATE],
[AH_VERBATIM([$1],
AC_WRAP([$2 */], [ ], [/* ])[
m4_wrap([$2 */], [ ], [/* ])[
#undef $1])])

View File

@ -1,7 +1,7 @@
## Process this file with automake to create Makefile.in.
## Makefile for Autoconf.
## Copyright (C) 1999 Free Software Foundation, Inc.
## Copyright (C) 1999, 2000 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
@ -38,7 +38,7 @@ EXTRA_SCRIPTS = autoscan
distpkgdataDATA = \
acfunctions acheaders acidentifiers acmakevars acprograms \
acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
libm4.m4 acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
nodistpkgdataDATA = autoconf.m4f autoheader.m4f acversion.m4
@ -95,13 +95,12 @@ editpl = sed -e 's,@''datadir''@,$(pkgdatadir),g' -e 's,@''PERL''@,$(PERL),g' \
.m4.m4f:
@case `$(M4) --help </dev/null 2>&1` in \
*reload-state*) echo freezing $*.m4; \
$(M4) -F $*.m4f -I${srcdir} ${srcdir}/$*.m4 ;; \
*traditional*) ;; \
*) echo Error: Autoconf requires GNU m4 1.1 or later; exit 1 ;; \
$(M4) -F $*.m4f -I$(srcdir) $(srcdir)/$*.m4 ;; \
*) echo Error: Autoconf requires GNU m4 1.4 or later; exit 1 ;; \
esac
autoconf.m4f: autoconf.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoconf.m4f: autoconf.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
# The documentation

View File

@ -81,7 +81,7 @@ EXTRA_SCRIPTS = autoscan
# s/nodistpackageDATA/nodist_pkgdata_DATA/
# and adapt dependencies once we use a more recent Automake
distpkgdataDATA = acfunctions acheaders acidentifiers acmakevars acprograms acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
distpkgdataDATA = acfunctions acheaders acidentifiers acmakevars acprograms libm4.m4 acgeneral.m4 acoldnames.m4 acspecific.m4 autoconf.m4 autoheader.m4
nodistpkgdataDATA = autoconf.m4f autoheader.m4f acversion.m4
@ -605,13 +605,12 @@ install-data-hook: INSTALL.txt
.m4.m4f:
@case `$(M4) --help </dev/null 2>&1` in \
*reload-state*) echo freezing $*.m4; \
$(M4) -F $*.m4f -I${srcdir} ${srcdir}/$*.m4 ;; \
*traditional*) ;; \
*) echo Error: Autoconf requires GNU m4 1.1 or later; exit 1 ;; \
$(M4) -F $*.m4f -I$(srcdir) $(srcdir)/$*.m4 ;; \
*) echo Error: Autoconf requires GNU m4 1.4 or later; exit 1 ;; \
esac
autoconf.m4f: autoconf.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoconf.m4f: autoconf.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
autoheader.m4f: autoheader.m4 libm4.m4 acgeneral.m4 acspecific.m4 acoldnames.m4 acversion.m4
# The documentation

View File

@ -20,9 +20,11 @@ dnl 02111-1307, USA.
dnl
dnl Written by David MacKenzie.
dnl
include(acgeneral.m4)dnl
builtin(include, acspecific.m4)dnl
builtin(include, acoldnames.m4)dnl
include(libm4.m4)dnl
m4_include(acversion.m4)dnl
m4_include(acgeneral.m4)dnl
m4_include(acspecific.m4)dnl
m4_include(acoldnames.m4)dnl
dnl Do not sinclude acsite.m4 here, because it may not be installed
dnl yet when Autoconf is frozen.
dnl Do not sinclude ./aclocal.m4 here, to prevent it from being frozen.

View File

@ -49,399 +49,6 @@ dnl Written by David MacKenzie, with help from
dnl Franc,ois Pinard, Karl Berry, Richard Pixley, Ian Lance Taylor,
dnl Roland McGrath, Noah Friedman, david d zuhn, and many others.
dnl
divert(-1)dnl Throw away output until AC_INIT is called.
changequote([, ])
include(acversion.m4)
dnl Some old m4's don't support m4exit. But they provide
dnl equivalent functionality by core dumping because of the
dnl long macros we define.
ifdef([__gnu__], , [errprint(Autoconf requires GNU m4.
Install it before installing Autoconf or set the
M4 environment variable to its path name.
)m4exit(2)])
dnl m4_errprint(MSG)
dnl ----------------
dnl Same as `errprint', but reports the file and line.
define(m4_errprint, [errprint(__file__:__line__: [$1
])])
dnl m4_warn(MSG)
dnl ------------
dnl Warn the user.
define(m4_warn, [m4_errprint([warning: $1])])
dnl m4_fatal(MSG, [EXIT-STATUS])
dnl ----------------------------
dnl Fatal the user. :)
define(m4_fatal,
[m4_errprint([error: $1])dnl
m4exit(ifelse([$2],, 1, [$2]))])
dnl Some m4 internals have names colliding with tokens we might use.
dnl Rename them a` la `m4 --prefix-builtins'.
define([m4_prefix],
[define([m4_$1], defn([$1]))
undefine([$1])])
m4_prefix([eval])
m4_prefix([shift])
m4_prefix([format])
dnl We also want to neutralize include (and sinclude for symmetry),
dnl but we want to extend them slightly: warn when a file is included
dnl several times. This is in general a dangerous operation because
dnl quite nobody quotes the first argument of define.
dnl
dnl For instance in the following case:
dnl define(foo, [bar])
dnl then a second reading will turn into
dnl define(bar, [bar])
dnl which is certainly not what was meant.
dnl m4_include_unique(FILE)
dnl -----------------------
dnl Declare that the FILE was loading; and warn if it has already
dnl been included.
define(m4_include_unique,
[ifdef([m4_include($1)],
[m4_warn([file `$1' included several times])])dnl
define([m4_include($1)])])
dnl m4_include(FILE)
dnl ----------------
dnl As the builtin include, but warns against multiple inclusions.
define(m4_include,
[m4_include_unique([$1])dnl
builtin([include], [$1])])
dnl m4_sinclude(FILE)
dnl -----------------
dnl As the builtin sinclude, but warns against multiple inclusions.
define(m4_sinclude,
[m4_include_unique([$1])dnl
builtin([sinclude], [$1])])
dnl Neutralize include and sinclude.
undefine([include])
undefine([sinclude])
dnl ------------------------------------------------------------
dnl Text processing in m4.
dnl ------------------------------------------------------------
dnl m4_quote(STRING)
dnl ----------------
dnl Return STRING quoted.
dnl
dnl It is important to realize the difference between `quote(exp)' and
dnl `[exp]': in the first case you obtain the quoted *result* of the
dnl expansion of EXP, while in the latter you just obtain the string
dnl `exp'.
define([m4_quote], [[$@]])
dnl m4_split(STRING, [REGEXP])
dnl --------------------------
dnl Split STRING into an m4 list of quoted elements. The elements are
dnl quoted with [ and ]. Beginning spaces and end spaces *are kept*.
dnl Use m4_strip to remove them.
dnl
dnl REGEXP specifies where to split. Default is [\t ]+.
dnl
dnl Pay attention to the changequotes. Inner changequotes exist for
dnl obvious reasons (we want to insert square brackets). Outer
dnl changequotes are needed because otherwise the m4 parser, when it
dnl sees the closing bracket we add to the result, believes it is the
dnl end of the body of the macro we define.
dnl
dnl Also, notice that $1 is quoted twice, since we want the result to be
dnl quoted. Then you should understand that the argument of patsubst is
dnl ``STRING'' (i.e., with additional `` and '').
dnl
dnl This macro is safe on active symbols, i.e.:
dnl define(active, ACTIVE)
dnl m4_split([active active ])end
dnl => [active], [active], []end
changequote(<<, >>)
define(<<m4_split>>,
<<changequote(``, '')dnl
[dnl Can't use m4_default here instead of ifelse, because m4_default uses
dnl [ and ] as quotes.
patsubst(````$1'''',
ifelse(``$2'',, ``[ ]+'', ``$2''),
``], ['')]dnl
changequote([, ])>>)
changequote([, ])
dnl m4_join(STRING)
dnl ---------------
dnl If STRING contains end of lines, replace them with spaces. If there
dnl are backslashed end of lines, remove them. This macro is safe with
dnl active symbols.
dnl define(active, ACTIVE)
dnl m4_join([active
dnl act\
dnl ive])end
dnl => active activeend
define([m4_join],
[translit(patsubst([[[$1]]], [\\
]), [
], [ ])])
dnl m4_strip(STRING)
dnl ----------------
dnl Expands into STRING with tabs and spaces singled out into a single
dnl space, and removing leading and trailing spaces.
dnl
dnl This macro is robust to active symbols.
dnl define(active, ACTIVE)
dnl m4_strip([ active active ])end
dnl => active activeend
dnl
dnl This macro is fun! Because we want to preserve active symbols, STRING
dnl must be quoted for each evaluation, which explains there are 4 levels
dnl of brackets around $1 (don't forget that the result must be quoted
dnl too, hence one more quoting than applications).
dnl
dnl Then notice the patsubst of the middle: it is in charge of removing
dnl the leading space. Why not just `patsubst(..., [^ ])'? Because this
dnl macro will receive the output of the preceding patsubst, i.e. more or
dnl less [[STRING]]. So if there is a leading space in STRING, then it is
dnl the *third* character, since there are two leading `['; Equally for
dnl the outer patsubst.
define([m4_strip],
[patsubst(patsubst(patsubst([[[[$1]]]],
[[ ]+], [ ]),
[^\(..\) ], [\1]),
[ \(.\)$], [\1])])
dnl m4_append(MACRO-NAME, STRING)
dnl -----------------------------
dnl Redefine MACRO-NAME to hold its former content plus STRING at the
dnl end. It is valid to use this macro with MACRO-NAME undefined.
dnl
dnl This macro is robust to active symbols. It can be used to grow
dnl strings.
dnl
dnl | define(active, ACTIVE)
dnl | m4_append([sentence], [This is an])
dnl | m4_append([sentence], [ active ])
dnl | m4_append([sentence], [symbol.])
dnl | sentence
dnl | undefine([active])dnl
dnl | sentence
dnl => This is an ACTIVE symbol.
dnl => This is an active symbol.
dnl
dnl It can be used to define hooks.
dnl
dnl | define(active, ACTIVE)
dnl | m4_append([hooks], [define([act1], [act2])])
dnl | m4_append([hooks], [define([act2], [active])])
dnl | undefine([active])
dnl | act1
dnl | hooks
dnl | act1
dnl => act1
dnl =>
dnl => active
define(m4_append,
[define([$1],
ifdef([$1], [defn([$1])])[$2])])
dnl m4_list_append(MACRO-NAME, STRING)
dnl ----------------------------------
dnl Same as `m4_append', but each element is separated by `, '.
define(m4_list_append,
[define([$1],
ifdef([$1], [defn([$1]), ])[$2])])
dnl ------------------------------------------------------------
dnl Some additional m4 structural control.
dnl ------------------------------------------------------------
dnl Both `ifval' and `ifset' tests against the empty string. The
dnl difference is that `ifset' is specialized on macros.
dnl
dnl In case of arguments of macros, eg $[1], it makes little difference.
dnl In the case of a macro `FOO', you don't want to check `ifval(FOO,
dnl TRUE)', because if `FOO' expands with commas, there is a shifting of
dnl the arguments. So you want to run `ifval([FOO])', but then you just
dnl compare the *string* `FOO' against `', which, of course fails.
dnl
dnl So you want a variation of `ifset' that expects a macro name as $[1].
dnl If this macro is both defined and defined to a non empty value, then
dnl it runs TRUE etc.
dnl ifval(COND, IF-TRUE[, IF-FALSE])
dnl --------------------------------
dnl If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE.
dnl Comparable to ifdef.
define([ifval], [ifelse([$1],[],[$3],[$2])])
dnl ifset(MACRO, IF-TRUE[, IF-FALSE])
dnl --------------------------------
dnl If MACRO has no definition, or of its definition is the empty string,
dnl expand IF-FALSE, otherwise IF-TRUE.
define([ifset],
[ifdef([$1],
[ifelse(defn([$1]), [], [$3], [$2])],
[$3])])
dnl m4_default(EXP1, EXP2)
dnl ----------------------
dnl Returns EXP1 if non empty, otherwise EXP2.
define([m4_default], [ifval([$1], [$1], [$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.
define(m4_case,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
[$1], [$2], [$3],
[m4_case([$1], m4_shift(m4_shift(m4_shift($@))))])])
# 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.
define(m4_match,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
regexp([$1], [$2]), -1, [m4_match([$1],
m4_shift(m4_shift(m4_shift($@))))],
[$3])])
## --------------------- ##
## Implementing m4 loops ##
## --------------------- ##
# Implementing loops (`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(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach',
# | `pushdef(`$1', `')_foreach(`$1', `$2', `$3')popdef(`$1')')
# | define(`_arg1', `$1')
# | define(`_foreach',
# | `ifelse(`$2', `()', ,
# | `define(`$1', _arg1$2)$3`'_foreach(`$1', (shift$2), `$3')')')
#
# But then if you run
#
# | define(a, 1)
# | define(b, 2)
# | define(c, 3)
# | foreach(`f', `(`a', `(b', `c)')', `echo f
# | ')
#
# it gives
#
# => echo 1
# => echo (2,3)
#
# which is not what is expected.
#
# Once you understood this, you turn yourself into a quoting wizard,
# and come up with the following solution:
#
# | # foreach(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach', `pushdef(`$1', `')_foreach($@)popdef(`$1')')
# | define(`_arg1', ``$1'')
# | define(`_foreach',
# | `ifelse($2, `()', ,
# | `define(`$1', `_arg1$2')$3`'_foreach(`$1', `(shift$2)', `$3')')')
#
# which this time answers
#
# => echo a
# => echo (b
# => echo c)
#
# Bingo!
# m4_foreach(VARIABLE, LIST, EXPRESSION)
# --------------------------------------
# Expand EXPRESSION assigning to VARIABLE each value of the LIST
# (LIST should have the form `[(item_1, item_2, ..., item_n)]'),
# i.e. the whole list should be *quoted*. Quote members too if
# you don't want them to be expanded.
#
# This macro is robust to active symbols:
# define(active, ACTIVE)
# m4_foreach([Var], [([active], [b], [active])], [-Var-])end
# => -active--b--active-end
define(m4_foreach,
[pushdef([$1], [])_m4_foreach($@)popdef([$1])])
dnl Low level macros used to define m4_foreach
define(m4_car, [[$1]])
define(_m4_foreach,
[ifelse($2, [()], ,
[define([$1], [m4_car$2])$3[]_m4_foreach([$1],
[(m4_shift$2)],
[$3])])])
dnl ### Defining macros
@ -733,74 +340,9 @@ AC_DEFUN(AC_SPECIALIZE,
[indir([$1], m4_shift($@))])])
dnl ## --------------------------------- ##
dnl ## Helping macros to display strings ##
dnl ## --------------------------------- ##
dnl AC_WRAP(STRING [, PREFIX[, FIRST-PREFIX[, WIDTH]]]]))
dnl -----------------------------------------------------
dnl Expands into STRING wrapped to hold in WIDTH columns (default = 79).
dnl If prefix is set, each line is prefixed with it. If FIRST-PREFIX is
dnl specified, then the first line is prefixed with it. As a special
dnl case, if the length of the first prefix is greater than that of
dnl PREFIX, then FIRST-PREFIX will be left alone on the first line.
dnl
dnl Typical outputs are:
dnl
dnl AC_WRAP([Short string */], [ ], [/* ], 20)
dnl => /* Short string */
dnl
dnl AC_WRAP([Much longer string */], [ ], [/* ], 20)
dnl => /* Much longer
dnl => string */
dnl
dnl AC_WRAP([Short doc.], [ ], [ --short ], 30)
dnl => --short Short doc.
dnl
dnl AC_WRAP([Short doc.], [ ], [ --too-wide ], 30)
dnl => --too-wide
dnl => Short doc.
dnl
dnl AC_WRAP([Super long documentation.], [ ], [ --too-wide ], 30)
dnl => --too-wide
dnl => Super long
dnl => documentation.
dnl
dnl FIXME: there is no checking of a longer PREFIX than WIDTH, but do
dnl we really want to bother with people trying each single corner
dnl of a software?
dnl
dnl This macro does not leave a trailing space behind the last word,
dnl what complicates it a bit. The algorithm is stupid simple: all the
dnl words are preceded by AC_Separator which is defined to empty for the
dnl first word, and then ` ' (single space) for all the others.
define([AC_WRAP],
[pushdef([AC_Prefix], m4_default([$2], []))dnl
pushdef([AC_Prefix1], m4_default([$3], [AC_Prefix]))dnl
pushdef([AC_Width], m4_default([$4], 79))dnl
pushdef([AC_Cursor], len(AC_Prefix1))dnl
pushdef([AC_Separator], [])dnl
AC_Prefix1[]dnl
ifelse(m4_eval(AC_Cursor > len(AC_Prefix)),
1, [define([AC_Cursor], len(AC_Prefix))
AC_Prefix])[]dnl
AC_FOREACH([AC_Word], [$1],
[define([AC_Cursor], m4_eval(AC_Cursor + len(AC_Word) + 1))dnl
dnl New line if too long, else insert a space unless it is the first
dnl of the words.
ifelse(m4_eval(AC_Cursor > AC_Width),
1, [define([AC_Cursor], m4_eval(len(AC_Prefix) + len(AC_Word) + 1))]
AC_Prefix,
[AC_Separator])[]dnl
AC_Word[]dnl
define([AC_Separator], [ ])])dnl
popdef([AC_Separator])dnl
popdef([AC_Cursor])dnl
popdef([AC_Width])dnl
popdef([AC_Prefix1])dnl
popdef([AC_Prefix])dnl
])
## --------------------------------- ##
## Helping macros to display strings ##
## --------------------------------- ##
dnl AC_HELP_STRING(LHS, RHS[, COLUMN])
@ -847,7 +389,7 @@ dnl
define([AC_HELP_STRING],
[pushdef([AC_Prefix], m4_default([$3], [ ]))dnl
pushdef([AC_Prefix_Format], [ %-]m4_eval(len(AC_Prefix) - 3)[s ])dnl [ %-23s ]
AC_WRAP([$2], AC_Prefix, m4_format(AC_Prefix_Format, [$1]))dnl
m4_wrap([$2], AC_Prefix, m4_format(AC_Prefix_Format, [$1]))dnl
popdef([AC_Prefix_Format])dnl
popdef([AC_Prefix])dnl
])
@ -859,7 +401,7 @@ dnl AC_INIT_NOTICE
dnl --------------
AC_DEFUN(AC_INIT_NOTICE,
[# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using Autoconf version] AC_ACVERSION [
# Generated automatically using Autoconf version ]AC_ACVERSION[
# Copyright (C) 1992, 93, 94, 95, 96, 98, 1999 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
@ -3490,16 +3032,16 @@ dnl so uname gets run too.
# Files that config.status was made for.
ifset([AC_LIST_FILES], [config_files="\\
AC_WRAP(AC_LIST_FILES, [ ])"
m4_wrap(AC_LIST_FILES, [ ])"
])dnl
ifset([AC_LIST_HEADERS], [config_headers="\\
AC_WRAP(AC_LIST_HEADERS, [ ])"
m4_wrap(AC_LIST_HEADERS, [ ])"
])dnl
ifset([AC_LIST_LINKS], [config_links="\\
AC_WRAP(AC_LIST_LINKS, [ ])"
m4_wrap(AC_LIST_LINKS, [ ])"
])dnl
ifset([AC_LIST_COMMANDS], [config_commands="\\
AC_WRAP(AC_LIST_COMMANDS, [ ])"
m4_wrap(AC_LIST_COMMANDS, [ ])"
])dnl
ac_cs_usage="\\

514
libm4.m4 Normal file
View File

@ -0,0 +1,514 @@
divert(-1) -*- Autoconf -*-
# This file is part of Autoconf.
# Base m4 layer.
# Requires GNU m4.
# Copyright (C) 1999 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.
#
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(Autoconf requires GNU m4. Install it before installing Autoconf or
set the M4 environment variable to its path name.)
m4exit(2)])
## --------------------------------------------- ##
## Move some m4 builtins to a safer name space. ##
## --------------------------------------------- ##
# m4_errprint(MSG)
# ----------------
# Same as `errprint', but reports the file and line.
define(m4_errprint, [errprint(__file__:__line__: [$1
])])
# m4_warn(MSG)
# ------------
# Warn the user.
define(m4_warn, [m4_errprint([warning: $1])])
# m4_fatal(MSG, [EXIT-STATUS])
# ----------------------------
# Fatal the user. :)
define(m4_fatal,
[m4_errprint([error: $1])dnl
m4exit(ifelse([$2],, 1, [$2]))])
# Some m4 internals have names colliding with tokens we might use.
# Rename them a` la `m4 --prefix-builtins'.
define([m4_prefix],
[define([m4_$1], defn([$1]))
undefine([$1])])
m4_prefix([eval])
m4_prefix([shift])
m4_prefix([format])
# 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 define.
#
# For instance in the following case:
# define(foo, [bar])
# then a second reading will turn into
# 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.
define(m4_include_unique,
[ifdef([m4_include($1)],
[m4_warn([file `$1' included several times])])dnl
define([m4_include($1)])])
# m4_include(FILE)
# ----------------
# As the builtin include, but warns against multiple inclusions.
define(m4_include,
[m4_include_unique([$1])dnl
builtin([include], [$1])])
# m4_sinclude(FILE)
# -----------------
# As the builtin sinclude, but warns against multiple inclusions.
define(m4_sinclude,
[m4_include_unique([$1])dnl
builtin([sinclude], [$1])])
# Neutralize include and sinclude.
undefine([include])
undefine([sinclude])
## --------------------------------------- ##
## Some additional m4 structural control. ##
## --------------------------------------- ##
# Both `ifval' and `ifset' tests against the empty string. The
# difference is that `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 `ifval(FOO,
# TRUE)', because if `FOO' expands with commas, there is a shifting of
# the arguments. So you want to run `ifval([FOO])', but then you just
# compare the *string* `FOO' against `', which, of course fails.
#
# So you want a variation of `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.
# ifval(COND, IF-TRUE[, IF-FALSE])
# --------------------------------
# If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE.
# Comparable to ifdef.
define([ifval], [ifelse([$1],[],[$3],[$2])])
# 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.
define([ifset],
[ifdef([$1],
[ifelse(defn([$1]), [], [$3], [$2])],
[$3])])
# m4_default(EXP1, EXP2)
# ----------------------
# Returns EXP1 if non empty, otherwise EXP2.
define([m4_default], [ifval([$1], [$1], [$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.
define(m4_case,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
[$1], [$2], [$3],
[m4_case([$1], m4_shift(m4_shift(m4_shift($@))))])])
# 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.
define(m4_match,
[ifelse([$#], 0, [],
[$#], 1, [],
[$#], 2, [$2],
regexp([$1], [$2]), -1, [m4_match([$1],
m4_shift(m4_shift(m4_shift($@))))],
[$3])])
## --------------------- ##
## Implementing m4 loops ##
## --------------------- ##
# Implementing loops (`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(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach',
# | `pushdef(`$1', `')_foreach(`$1', `$2', `$3')popdef(`$1')')
# | define(`_arg1', `$1')
# | define(`_foreach',
# | `ifelse(`$2', `()', ,
# | `define(`$1', _arg1$2)$3`'_foreach(`$1', (shift$2), `$3')')')
#
# But then if you run
#
# | define(a, 1)
# | define(b, 2)
# | define(c, 3)
# | foreach(`f', `(`a', `(b', `c)')', `echo f
# | ')
#
# it gives
#
# => echo 1
# => echo (2,3)
#
# which is not what is expected.
#
# Once you understood this, you turn yourself into a quoting wizard,
# and come up with the following solution:
#
# | # foreach(x, (item_1, item_2, ..., item_n), stmt)
# | define(`foreach', `pushdef(`$1', `')_foreach($@)popdef(`$1')')
# | define(`_arg1', ``$1'')
# | define(`_foreach',
# | `ifelse($2, `()', ,
# | `define(`$1', `_arg1$2')$3`'_foreach(`$1', `(shift$2)', `$3')')')
#
# which this time answers
#
# => echo a
# => echo (b
# => echo c)
#
# Bingo!
# m4_foreach(VARIABLE, LIST, EXPRESSION)
# --------------------------------------
# Expand EXPRESSION assigning to VARIABLE each value of the LIST
# (LIST should have the form `[(item_1, item_2, ..., item_n)]'),
# i.e. the whole list should be *quoted*. Quote members too if
# you don't want them to be expanded.
#
# This macro is robust to active symbols:
# define(active, ACTIVE)
# m4_foreach([Var], [([active], [b], [active])], [-Var-])end
# => -active--b--active-end
define(m4_foreach,
[pushdef([$1], [])_m4_foreach($@)popdef([$1])])
# Low level macros used to define m4_foreach
define(m4_car, [[$1]])
define(_m4_foreach,
[ifelse($2, [()], ,
[define([$1], [m4_car$2])$3[]_m4_foreach([$1],
[(m4_shift$2)],
[$3])])])
## ----------------------- ##
## Text processing in m4. ##
## ----------------------- ##
# m4_quote(STRING)
# ----------------
# Return STRING quoted.
#
# It is important to realize the difference between `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'.
define([m4_quote], [[$@]])
# 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 changequotes. Inner changequotes exist for
# obvious reasons (we want to insert square brackets). Outer
# 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.:
# define(active, ACTIVE)
# m4_split([active active ])end
# => [active], [active], []end
changequote(<<, >>)
define(<<m4_split>>,
<<changequote(``, '')dnl
[dnl Can't use m4_default here instead of ifelse, because m4_default uses
dnl [ and ] as quotes.
patsubst(````$1'''',
ifelse(``$2'',, ``[ ]+'', ``$2''),
``], ['')]dnl
changequote([, ])>>)
changequote([, ])
# m4_join(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.
# define(active, ACTIVE)
# m4_join([active
# act\
# ive])end
# => active activeend
define([m4_join],
[translit(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.
# 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.
define([m4_strip],
[patsubst(patsubst(patsubst([[[[$1]]]],
[[ ]+], [ ]),
[^\(..\) ], [\1]),
[ \(.\)$], [\1])])
# 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.
#
# | define(active, ACTIVE)
# | m4_append([sentence], [This is an])
# | m4_append([sentence], [ active ])
# | m4_append([sentence], [symbol.])
# | sentence
# | undefine([active])dnl
# | sentence
# => This is an ACTIVE symbol.
# => This is an active symbol.
#
# It can be used to define hooks.
#
# | define(active, ACTIVE)
# | m4_append([hooks], [define([act1], [act2])])
# | m4_append([hooks], [define([act2], [active])])
# | undefine([active])
# | act1
# | hooks
# | act1
# => act1
# =>
# => active
define(m4_append,
[define([$1],
ifdef([$1], [defn([$1])])[$2])])
# m4_list_append(MACRO-NAME, STRING)
# ----------------------------------
# Same as `m4_append', but each element is separated by `, '.
define(m4_list_append,
[define([$1],
ifdef([$1], [defn([$1]), ])[$2])])
## --------------------------------- ##
## Helping macros to display strings ##
## --------------------------------- ##
# m4_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_wrap([Short string */], [ ], [/* ], 20)
# => /* Short string */
#
# m4_wrap([Much longer string */], [ ], [/* ], 20)
# => /* Much longer
# => string */
#
# m4_wrap([Short doc.], [ ], [ --short ], 30)
# => --short Short doc.
#
# m4_wrap([Short doc.], [ ], [ --too-wide ], 30)
# => --too-wide
# => Short doc.
#
# m4_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.
define([m4_wrap],
[pushdef([m4_Prefix], m4_default([$2], []))dnl
pushdef([m4_Prefix1], m4_default([$3], [m4_Prefix]))dnl
pushdef([m4_Width], m4_default([$4], 79))dnl
pushdef([m4_Cursor], len(m4_Prefix1))dnl
pushdef([m4_Separator], [])dnl
m4_Prefix1[]dnl
ifelse(m4_eval(m4_Cursor > len(m4_Prefix)),
1, [define([m4_Cursor], len(m4_Prefix))
m4_Prefix])[]dnl
m4_foreach([m4_Word], (m4_split(m4_strip(m4_join([$1])))),
[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.
ifelse(m4_eval(m4_Cursor > m4_Width),
1, [define([m4_Cursor], m4_eval(len(m4_Prefix) + len(m4_Word) + 1))]
m4_Prefix,
[m4_Separator])[]dnl
m4_Word[]dnl
define([m4_Separator], [ ])])dnl
popdef([m4_Separator])dnl
popdef([m4_Cursor])dnl
popdef([m4_Width])dnl
popdef([m4_Prefix1])dnl
popdef([m4_Prefix])dnl
])