autoconf-patches
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]