[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Add and document AS_VAR_COPY, speed up configure
From: |
Eric Blake |
Subject: |
Add and document AS_VAR_COPY, speed up configure |
Date: |
Fri, 17 Oct 2008 11:43:51 -0600 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.17) Gecko/20080914 Thunderbird/2.0.0.17 Mnenhy/0.7.5.666 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I'm planning on committing this to savannah later today, unless someone
reviews it sooner.
$ git pull http://repo.or.cz/w/autoconf/ericb.git master
The driving factor behind this patch is that I wanted to fix what is
already present in the AS_VAR family before adding AS_VAR_APPEND. I took
to heart the FIXME related to AS_VAR_GET (that API is lousy, because it
handles trailing newlines inconsistently, and because it forks more than
necessary). I deprecated it, and replaced it with a new API:
# AC_VAR_COPY(dest, src)
# ----------------------
# Copy the contents of the polymorphic shell variable SRC and assign them
# as the contents of the polymorphic shell variable DEST.
#
# When it is desirable to access an indirect variable within a shell ""
# context, use AC_VAR_COPY to first copy the contents into a temporary
# literal shell variable.
As a result of moving away from AS_VAR_GET, coreutils' configure now has a
noticeable drop in the number of ``, leading to faster configure execution
on cygwin. And since the new API doesn't have the bug with trailing
newline, I figured it was finally time to document the AS_VAR family.
Adding a test case exposed and fixed a flaw in the AC_VAR_PUSHDEF logic
(since AS_LITERAL_IF _must_ expand its argument, the definition of the
temporary macro must _not_ contain any attempts to manipulate diversions;
so the AS_REQUIRE must be hoisted to the top level before using AS_TR_SH).
This is a series of three patches:
Eric Blake (3):
Add AS_VAR_COPY.
Test AS_VAR interfaces.
Document AS_VAR interfaces.
- --
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkj4ztcACgkQ84KuGfSFAYBgeQCgxuBH0H4DFxrVzosEUFGikjF3
1OAAnjz6B+qkWbVqeV7hwY5evvH6gQOY
=+oCm
-----END PGP SIGNATURE-----
>From 66b449ba0b237461b8b70e67ab2ca1ea4547b65f Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 16 Oct 2008 21:29:09 -0600
Subject: [PATCH] Add AS_VAR_COPY.
* lib/m4sugar/m4sh.m4 (AS_VAR_COPY): New macro.
(AS_VAR_GET): Reduce output to one line.
(AS_VAR_IF): Use it, instead of the broken AS_VAR_GET.
* lib/autoconf/general.m4 (AC_CACHE_CHECK): Likewise.
* lib/autoconf/libs.m4 (AC_SEARCH_LIBS): Likewise.
* lib/autotest/general.m4 (_AT_FINISH): Likewise.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 10 ++++++++
lib/autoconf/general.m4 | 2 +-
lib/autoconf/libs.m4 | 2 +-
lib/autotest/general.m4 | 2 +-
lib/m4sugar/m4sh.m4 | 59 +++++++++++++++++++++++++++-------------------
5 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1ba9686..348cdec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-10-17 Eric Blake <address@hidden>
+
+ Add AS_VAR_COPY.
+ * lib/m4sugar/m4sh.m4 (AS_VAR_COPY): New macro.
+ (AS_VAR_GET): Reduce output to one line.
+ (AS_VAR_IF): Use it, instead of the broken AS_VAR_GET.
+ * lib/autoconf/general.m4 (AC_CACHE_CHECK): Likewise.
+ * lib/autoconf/libs.m4 (AC_SEARCH_LIBS): Likewise.
+ * lib/autotest/general.m4 (_AT_FINISH): Likewise.
+
2008-10-16 Eric Blake <address@hidden>
Allow comments before functions emitted by m4sh.
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index beb3104..8c858c4 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -1990,7 +1990,7 @@ m4_defun([AC_CACHE_CHECK],
AC_CACHE_VAL([$2], [$3])dnl
AS_LITERAL_IF([$2],
[AC_MSG_RESULT([$$2])],
- [ac_res=AS_VAR_GET([$2])
+ [AS_VAR_COPY([ac_res], [$2])
AC_MSG_RESULT([$ac_res])])dnl
])
diff --git a/lib/autoconf/libs.m4 b/lib/autoconf/libs.m4
index 4e62040..03258f0 100644
--- a/lib/autoconf/libs.m4
+++ b/lib/autoconf/libs.m4
@@ -84,7 +84,7 @@ done
AS_VAR_SET_IF([ac_Search], , [AS_VAR_SET([ac_Search], [no])])dnl
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS])
-ac_res=AS_VAR_GET([ac_Search])
+AS_VAR_COPY([ac_res], [ac_Search])
AS_IF([test "$ac_res" != no],
[test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$3],
diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index f7ded36..9e7df68 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -774,7 +774,7 @@ if test -n "$at_top_srcdir"; then
builddir=../..
for at_dir_var in srcdir top_srcdir top_build_prefix
do
- at_val=AS_VAR_GET([at_$at_dir_var])
+ AS_VAR_COPY([at_val], [at_$at_dir_var])
case $at_val in
[[\\/$]]* | ?:[[\\/]]* ) at_prefix= ;;
*) at_prefix=../../ ;;
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index c387864..bd5c9c4 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1515,9 +1515,9 @@ esac[]dnl
-## ------------------------------------ ##
-## Common m4/sh character translation. ##
-## ------------------------------------ ##
+## --------------------------------------- ##
+## 6. 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.
@@ -1608,9 +1608,9 @@ AS_REQUIRE([_AS_TR_CPP_PREPARE])dnl
-## --------------------------------------------------- ##
-## Common m4/sh handling of variables (indirections). ##
-## --------------------------------------------------- ##
+## ------------------------------------------------------ ##
+## 7. Common m4/sh handling of variables (indirections). ##
+## ------------------------------------------------------ ##
# The purpose of this section is to provide a uniform API for
@@ -1619,18 +1619,18 @@ AS_REQUIRE([_AS_TR_CPP_PREPARE])dnl
# AS_VAR_SET(var, val)
# or
# AS_VAR_SET(as_$var, val)
-# and expect the right thing to happen.
+# and expect the right thing to happen. In the descriptions below,
+# a literal name matches the regex [a-zA-Z_][a-zA-Z0-9_]*, an
+# indirect name is a shell expression that produces a literal name
+# when passed through eval, and a polymorphic name is either type.
-# 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=AS_ESCAPE([$2])"])])
+# AS_VAR_COPY(DEST, SOURCE)
+# -------------------------
+# Set the polymorphic shell variable DEST to the contents of the polymorphic
+# shell variable SOURCE.
+m4_define([AS_VAR_COPY],
+[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])
# AS_VAR_GET(VARIABLE)
@@ -1638,13 +1638,24 @@ m4_define([AS_VAR_SET],
# Get the value of the shell VARIABLE.
# Evaluates to $VARIABLE if there are no indirection in VARIABLE,
# else into the appropriate `eval' sequence.
-# FIXME: This mishandles values that end in newlines.
-# Fixing this will require changing the API.
+# This macro is deprecated because it sometimes mishandles trailing newlines;
+# use AS_VAR_COPY instead.
m4_define([AS_VAR_GET],
[AS_LITERAL_IF([$1],
[$$1],
- [`eval 'as_val=${'m4_bpatsubst([$1], [[\\`]], [\\\&])'}
- AS_ECHO(["$as_val"])'`])])
+ [`eval 'as_val=${'m4_bpatsubst([$1], [[\\`]], [\\\&])'};dnl
+AS_ECHO(["$as_val"])'`])])
+
+
+# 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=AS_ESCAPE([$2])"])])
# AS_VAR_TEST_SET(VARIABLE)
@@ -1672,7 +1683,7 @@ m4_define([AS_VAR_SET_IF],
m4_define([AS_VAR_IF],
[AS_LITERAL_IF([$1],
[AS_IF([test "x$$1" = x""$2], [$3], [$4])],
- [as_val=AS_VAR_GET([$1])
+ [AS_VAR_COPY([as_val], [$1])
AS_IF([test "x$as_val" = x""$2], [$3], [$4])])])
@@ -1721,9 +1732,9 @@ m4_define([AS_VAR_POPDEF],
[m4_popdef([$1])])
-## ----------------- ##
-## Setting M4sh up. ##
-## ----------------- ##
+## -------------------- ##
+## 8. Setting M4sh up. ##
+## -------------------- ##
# AS_INIT_GENERATED
--
1.6.0.2
>From 10638f2b9a1e1d78ee57ae90a4a7f93e9ed8818d Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 17 Oct 2008 07:31:06 -0600
Subject: [PATCH] Test AS_VAR interfaces.
* tests/m4sh.at (AS@&address@hidden): New test.
* lib/m4sugar/m4sh.m4 (AS_VAR_PUSHDEF): Force expansion of
_AS_TR_SH_PREPARE at top level, rather than argument collection.
(AS_TR_SH): Support command substitution.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 6 +++
lib/m4sugar/m4sh.m4 | 12 +++++-
tests/m4sh.at | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 348cdec..128ba5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2008-10-17 Eric Blake <address@hidden>
+ Test AS_VAR interfaces.
+ * tests/m4sh.at (AS@&address@hidden): New test.
+ * lib/m4sugar/m4sh.m4 (AS_VAR_PUSHDEF): Force expansion of
+ _AS_TR_SH_PREPARE at top level, rather than argument collection.
+ (AS_TR_SH): Support command substitution.
+
Add AS_VAR_COPY.
* lib/m4sugar/m4sh.m4 (AS_VAR_COPY): New macro.
(AS_VAR_GET): Reduce output to one line.
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index bd5c9c4..ed4de6a 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1569,7 +1569,8 @@ AS_LITERAL_IF([$1],
m4_dquote(m4_dquote(m4_defn([m4_cr_not_symbols2])))[[,
[pp[]]]]dnl
m4_dquote(m4_dquote(m4_for(,1,255,,[[_]])))[[)],
- [`AS_ECHO(["$1"]) | $as_tr_sh`])])
+ [`AS_ECHO(["m4_bpatsubst(m4_dquote(m4_expand([$1])),
+ [[\\`]], [\\\&])"]) | $as_tr_sh`])])
# _AS_TR_CPP_PREPARE
@@ -1718,8 +1719,15 @@ m4_define([AS_VAR_IF],
# 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.
+#
+# AS_TR_SH attempts to play with diversions if _AS_TR_SH_PREPARE has
+# not been expanded. However, users are expected to do subsequent
+# calls that trigger AS_LITERAL_IF([VARNAME]), and that macro performs
+# expansion inside an argument collection context, where diversions
+# don't work. Therefore, we must require the preparation ourselves.
m4_define([AS_VAR_PUSHDEF],
-[AS_LITERAL_IF([$2],
+[AS_REQUIRE([_AS_TR_SH_PREPARE])dnl
+AS_LITERAL_IF([$2],
[m4_pushdef([$1], [AS_TR_SH($2)])],
[as_$1=AS_TR_SH($2)
m4_pushdef([$1], [$as_[$1]])])])
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 4951fd9..eb869a7 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -884,6 +884,102 @@ ok 7
AT_CLEANUP
+## ---------- ##
+## AS_VAR_*. ##
+## ---------- ##
+
+AT_SETUP([AS@&address@hidden)
+AT_KEYWORDS([m4sh AS@&address@hidden AS@&address@hidden AS@&address@hidden
+AS@&address@hidden AS@&address@hidden AS@&address@hidden AS@&address@hidden
+AS@&address@hidden)
+
+AT_DATA_M4SH([script.as], [[dnl
+AS_INIT
+# Literals.
+dnl AS_VAR_SET_IF also covers AS_VAR_TEST_SET
+AS_VAR_SET_IF([foo], [echo oops], [echo ok])
+AS_VAR_SET([foo], ['\a "weird" `value` with; $fun '\''characters
+']) # 'font-lock
+AS_VAR_COPY([bar], [foo])
+echo "$bar-"
+echo "AS_VAR_GET([foo])-"
+AS_VAR_SET_IF([foo], [echo ok], [echo oops])
+AS_VAR_IF([foo], [string], [echo oops], [echo ok])
+AS_VAR_PUSHDEF([tmp], [foo])
+AS_VAR_IF([tmp], ['\a "weird" `value` with; $fun '\''characters
+'], [echo ok], [echo oops]) # 'font-lock
+AS_VAR_POPDEF([tmp])
+m4_ifdef([tmp], [echo oops])
+
+# Indirects via shell vars.
+echo '===='
+num=1
+AS_VAR_SET_IF([foo$num], [echo oops], [echo ok])
+AS_VAR_SET([foo$num], ['\a "weird" `value` with; $fun '\''characters
+']) # 'font-lock
+AS_VAR_COPY([bar], [foo$num])
+num=2
+AS_VAR_COPY([foo$num], [bar])
+echo "$foo2-"
+echo "AS_VAR_GET([foo$num])-"
+AS_VAR_SET_IF([foo$num], [echo ok], [echo oops])
+AS_VAR_IF([foo$num], [string], [echo oops], [echo ok])
+AS_VAR_PUSHDEF([tmp], [foo$num])
+AS_VAR_IF([tmp], ['\a "weird" `value` with; $fun '\''characters
+'], [echo ok], [echo oops]) # 'font-lock
+AS_VAR_POPDEF([tmp])
+m4_ifdef([tmp], [echo oops])
+
+# Indirects via command substitution.
+echo '===='
+AS_VAR_SET_IF([`echo foo3`], [echo oops], [echo ok])
+AS_VAR_SET([`echo foo3`], ['\a "weird" `value` with; $fun '\''characters
+']) # 'font-lock
+AS_VAR_COPY([bar], [`echo foo3`])
+num=2
+AS_VAR_COPY([`echo foo4`], [bar])
+echo "$foo4-"
+echo "AS_VAR_GET([`echo foo4`])-"
+AS_VAR_SET_IF([`echo foo4`], [echo ok], [echo oops])
+AS_VAR_IF([`echo foo4`], [string], [echo oops], [echo ok])
+AS_VAR_PUSHDEF([tmp], [`echo foo4`])
+AS_VAR_IF([tmp], ['\a "weird" `value` with; $fun '\''characters
+'], [echo ok], [echo oops]) # 'font-lock
+AS_VAR_POPDEF([tmp])
+m4_ifdef([tmp], [echo oops])
+:
+]])
+
+AT_CHECK_M4SH
+AT_CHECK([./script], [], [[ok
+\a "weird" `value` with; $fun 'characters
+-
+\a "weird" `value` with; $fun 'characters
+-
+ok
+ok
+ok
+====
+ok
+\a "weird" `value` with; $fun 'characters
+-
+\a "weird" `value` with; $fun 'characters-
+ok
+ok
+ok
+====
+ok
+\a "weird" `value` with; $fun 'characters
+-
+\a "weird" `value` with; $fun 'characters-
+ok
+ok
+ok
+]])
+
+AT_CLEANUP
+
+
## ----------------- ##
## AS_INIT cleanup. ##
## ----------------- ##
--
1.6.0.2
>From f04f6b137d4c0c1002d1f96753e55c073dd9179f Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 17 Oct 2008 10:36:18 -0600
Subject: [PATCH] Document AS_VAR interfaces.
* doc/autoconf.texi (Programming in M4sh): M4sh is now prime-time.
(Polymorphic Variables): New node.
* NEWS: Update accordingly.
* lib/m4sugar/m4sh.m4: Sort AS_VAR macros.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 6 ++
NEWS | 8 +++
doc/autoconf.texi | 146 +++++++++++++++++++++++++++++++++++++++++++++++++--
lib/m4sugar/m4sh.m4 | 71 ++++++++++++-------------
4 files changed, 191 insertions(+), 40 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 128ba5b..9728f78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2008-10-17 Eric Blake <address@hidden>
+ Document AS_VAR interfaces.
+ * doc/autoconf.texi (Programming in M4sh): M4sh is now prime-time.
+ (Polymorphic Variables): New node.
+ * NEWS: Update accordingly.
+ * lib/m4sugar/m4sh.m4: Sort AS_VAR macros.
+
Test AS_VAR interfaces.
* tests/m4sh.at (AS@&address@hidden): New test.
* lib/m4sugar/m4sh.m4 (AS_VAR_PUSHDEF): Force expansion of
diff --git a/NEWS b/NEWS
index 2f7914a..90e49ce 100644
--- a/NEWS
+++ b/NEWS
@@ -18,11 +18,19 @@ GNU Autoconf NEWS - User visible changes.
** The following documented m4sh macros are new:
AS_LINENO_PREPARE
AS_ME_PREPARE
+ AS_VAR_COPY
** The following m4sh macros are documented now:
AS_ECHO
AS_ECHO_N
+ AS_LITERAL_IF
AS_UNSET
+ AS_VAR_IF
+ AS_VAR_POPDEF
+ AS_VAR_PUSHDEF
+ AS_VAR_SET
+ AS_VAR_SET_IF
+ AS_VAR_TEST_SET
AS_VERSION_COMPARE
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 43227a6..2ac048e 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -433,6 +433,7 @@ Top
Programming in M4sh
* Common Shell Constructs:: Portability layer for common shell constructs
+* Polymorphic Variables:: Support for indirect variable names
* Initialization Macros:: Macros to establish a sane shell environment
* File Descriptor Macros:: File descriptor macros for input and output
@@ -11797,9 +11798,6 @@ Programming in M4sh
@end enumerate
@end quotation
-
-For the time being, it is not mature enough to be widely used.
-
M4sh reserves the M4 macro namespace @samp{^_AS_} for internal use, and
the namespace @samp{^AS_} for M4sh macros. It also reserves the shell
and environment variable namespace @samp{^as_}, and the here-doc
@@ -11809,6 +11807,7 @@ Programming in M4sh
@menu
* Common Shell Constructs:: Portability layer for common shell constructs
+* Polymorphic Variables:: Support for indirect variable names
* Initialization Macros:: Macros to establish a sane shell environment
* File Descriptor Macros:: File descriptor macros for input and output
@end menu
@@ -11932,7 +11931,8 @@ Common Shell Constructs
@defmac AS_UNSET (@var{var})
@asindex{UNSET}
Unsets the shell variable @var{var}, working around bugs in older
-shells (@pxref{Limitations of Builtins, , Limitations of Shell Builtins}).
+shells (@pxref{Limitations of Builtins, , Limitations of Shell
+Builtins}). @var{var} can be a literal or indirect variable name.
@end defmac
@defmac AS_VERSION_COMPARE (@var{version-1}, @var{version-2}, @
@@ -11947,6 +11947,144 @@ Common Shell Constructs
The @acronym{GNU} C Library}).
@end defmac
address@hidden Polymorphic Variables
address@hidden Support for indirect variable names
address@hidden variable name indirection
address@hidden polymorphic variable name
address@hidden indirection, variable name
+
+Often times, it is convenient to write a macro that will emit shell code
+operating on a shell variable. The simplest case is when the variable
+name is known. But a more powerful idiom is writing shell code that can
+work through an indirection, where another variable or command
+substitution produces the name of the variable to actually manipulate.
+M4sh supports the notion of polymorphic shell variables, making it easy
+to write a macro that can deal with either literal or indirect variable
+names and output shell code appropriate to both use cases. Behavior is
+undefined if expansion of an indirect variable does not result in a
+literal variable name. These macros are often followed with @code{dnl},
+to avoid excess newlines in the output.
+
address@hidden AS_LITERAL_IF (@var{expression}, @ovar{if-literal},
@ovar{if-not})
address@hidden
+If the expansion of @var{expression} is definitely a shell literal,
+expand @var{if-literal}. If the expansion of @var{expression} looks
+like it might contain shell indirections (such as @code{$var} or
address@hidden), then @var{if-not} is expanded. The implementation is
+somewhat conservative (for example, @samp{'[$]'} is a single-quoted
+shell literal, but causes @var{if-not} to be expanded), in order to
+offer speed to the common case of deciding whether a variable name is
+literal or indirect, but can be used even in contexts unrelated to
+variable names.
address@hidden defmac
+
address@hidden AS_VAR_COPY (@var{dest}, @var{source})
address@hidden
+Emit shell code to assign the contents of the polymorphic shell variable
address@hidden to the polymorphic shell variable @var{dest}. For example,
+executing this m4sh snippet will output @samp{bar hi}:
+
address@hidden
+foo=bar bar=hi
+AS_VAR_COPY([a], [foo])
+AS_VAR_COPY([b], [$foo])
+echo "$a $b"
address@hidden example
+
+When it is necessary to access the contents of an indirect variable
+inside a shell double-quoted context, the recommended idiom is to first
+copy the contents into a temporary literal shell variable.
+
address@hidden
+for header in stdint_h inttypes_h ; do
+ AS_VAR_COPY([var], [ac_cv_header_$header])
+ echo "$header detected: $var"
+done
address@hidden smallexample
address@hidden defmac
+
address@hidden AS_VAR_GET is intentionally undocumented; it can't handle
address@hidden trailing newlines uniformly, and forks too much.
+
address@hidden AS_VAR_IF (@var{var}, @ovar{value}, @ovar{if-match},
@ovar{if-diff})
address@hidden
+Output a shell conditional statement. If the contents of the
+polymorphic shell variable @var{var} equal to the string @var{value},
+execute @var{if-match}; otherwise execute @var{if-diff}. Avoids shell
+bugs if an interrupt signal arrives while a command substitution in
address@hidden is being expanded.
address@hidden defmac
+
address@hidden AS_VAR_PUSHDEF (@var{m4-name}, @var{value})
address@hidden AS_VAR_POPDEF (@var{m4-name})
address@hidden
address@hidden
address@hidden composing variable names
address@hidden variable names, composing
+A common m4sh idiom involves composing shell variable names from an m4
+argument (for example, writing a macro that uses a cache variable).
address@hidden can be an arbitrary string, which will be transliterated
+into a valid shell name by @code{AS_TR_SH}. In order to access the
+composed variable name based on @var{value}, it easier to declare a
+temporary m4 macro @var{m4-name} with @code{AS_VAR_PUSHDEF}, then use
+that macro as the argument to subsequent @code{AS_VAR} macros as a
+polymorphic variable name, and finally free the temporary macro with
address@hidden
+
+Here is an involved example, that shows the power of writing macros that
+can handle composed shell variable names:
+
address@hidden
+m4_define([MY_CHECK_HEADER],
+[AS_VAR_PUSHDEF([my_Header], [ac_cv_header_$1])dnl
+AS_VAR_IF([my_Header], [yes], [echo "header $1 available"])dnl
+AS_VAR_POPDEF([my_Header])dnl
+])
+MY_CHECK_HEADER([stdint.h])
+for header in inttypes.h stdlib.h ; do
+ MY_CHECK_HEADER([$header])
+done
address@hidden example
+
+In the above example, @code{MY_CHECK_HEADER} can operate on polymorphic
+variable names. In the first invocation, the m4 argument is
address@hidden, which transliterates into a literal @code{stdint_h}.
+As a result, the temporary macro @code{my_Header} expands to the literal
+shell name @samp{ac_cv_header_stdint_h}. In the second invocation, the
+m4 argument to @code{MY_CHECK_HEADER} is @code{$header}, and the
+temporary macro @code{my_Header} expands to the indirect shell name
address@hidden During the shell execution of the for loop, when
address@hidden contains @samp{inttypes.h}, then @samp{$as_my_Header}
+contains @samp{ac_cv_header_inttypes_h}. If this script is then run on a
+platform where all three headers have been previously detected, the
+output of the script will include:
+
address@hidden
+header stdint.h detected
+header inttypes.h detected
+header stdlib.h detected
address@hidden smallexample
address@hidden defmac
+
address@hidden AS_VAR_SET (@var{var}, @ovar{value})
address@hidden
+Emit shell code to assign the contents of the polymorphic shell variable
address@hidden to the shell expansion of @var{value}.
address@hidden defmac
+
address@hidden AS_VAR_SET_IF (@var{var}, @ovar{if-set}, @ovar{if-undef})
address@hidden
+Emit a shell conditional statement, which executes @var{if-set} if the
+polymorphic shell variable @code{var} is set to any value, and
address@hidden otherwise.
address@hidden defmac
+
address@hidden AS_VAR_TEST_SET (@var{var})
address@hidden
+Emit a shell statement that results in a successful exit status only if
+the polymorphic shell variable @code{var} is set.
address@hidden defmac
+
@node Initialization Macros
@section Initialization Macros
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index ed4de6a..5a48b0d 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1648,35 +1648,6 @@ m4_define([AS_VAR_GET],
AS_ECHO(["$as_val"])'`])])
-# 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=AS_ESCAPE([$2])"])])
-
-
-# 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],
- [{ as_var=$1; eval "test \"\${$as_var+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_IF(VARIABLE, VALUE, IF-TRUE, IF-FALSE)
# ---------------------------------------------
# Implement a shell `if test $VARIABLE = VALUE; then-else'.
@@ -1701,8 +1672,7 @@ m4_define([AS_VAR_IF],
# 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.
+# first importance to use `AS_VAR_*' to access this variable.
#
# 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,
@@ -1714,6 +1684,13 @@ m4_define([AS_VAR_IF],
# AS_VAR_POPDEF([header])
+# AS_VAR_POPDEF(VARNAME)
+# ----------------------
+# Free the shell variable accessor VARNAME. To be dnl'ed.
+m4_define([AS_VAR_POPDEF],
+[m4_popdef([$1])])
+
+
# AS_VAR_PUSHDEF(VARNAME, VALUE)
# ------------------------------
# Define the m4 macro VARNAME to an accessor to the shell variable
@@ -1733,11 +1710,33 @@ AS_LITERAL_IF([$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])])
+# 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=AS_ESCAPE([$2])"])])
+
+
+# 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_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],
+ [{ as_var=$1; eval "test \"\${$as_var+set}\" = set"; }])])
## -------------------- ##
--
1.6.0.2
- Add and document AS_VAR_COPY, speed up configure,
Eric Blake <=