]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Add AS_VAR_APPEND.
authorEric Blake <ebb9@byu.net>
Mon, 20 Oct 2008 11:50:01 +0000 (05:50 -0600)
committerEric Blake <ebb9@byu.net>
Tue, 21 Oct 2008 21:03:17 +0000 (15:03 -0600)
* lib/m4sugar/m4sh.m4 (_AS_VAR_APPEND_PREPARE)
(_AS_VAR_APPEND_WORKS, AS_VAR_APPEND): New macros.
(AS_PREPARE, _AS_PREPARE): Emit preparation.
* tests/m4sh.at (AS@&t@_VAR_APPEND): New test.
* doc/autoconf.texi (Polymorphic Variables) <AS_VAR_APPEND>:
Document new macro.
<AS_VAR_SET>: Mention ramification of `""` rules.
* NEWS: Mention new macro.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
NEWS
doc/autoconf.texi
lib/m4sugar/m4sh.m4
tests/m4sh.at

index f98b7086443e898541a4b8ad4a7cc5e27322521e..d845609cd373bddaf40103a40097cf5cac43eff3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-10-21  Eric Blake  <ebb9@byu.net>
+
+       Add AS_VAR_APPEND.
+       * lib/m4sugar/m4sh.m4 (_AS_VAR_APPEND_PREPARE)
+       (_AS_VAR_APPEND_WORKS, AS_VAR_APPEND): New macros.
+       (AS_PREPARE, _AS_PREPARE): Emit preparation.
+       * tests/m4sh.at (AS@&t@_VAR_APPEND): New test.
+       * doc/autoconf.texi (Polymorphic Variables) <AS_VAR_APPEND>:
+       Document new macro.
+       <AS_VAR_SET>: Mention ramification of `""` rules.
+       * NEWS: Mention new macro.
+
 2008-10-21  Paolo Bonzini  <bonzini@gnu.org>
        and Eric Blake  <ebb9@byu.net>
 
diff --git a/NEWS b/NEWS
index 147639b39cd6af68fc89df6df6dc1fa254cc3c40..4ac8e8adc28f0214e974186c2ae09b5e2e70bf2c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,7 +17,7 @@ GNU Autoconf NEWS - User visible changes.
    m4_set_map
 
 ** The following documented m4sh macros are new:
-   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_VAR_COPY
+   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_VAR_APPEND  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
index eed40c56ab478df34154ac8e380376b9f9c461bb..25a733788b72962424fc4198b3bb6b51e11bc3ec 100644 (file)
@@ -12070,6 +12070,31 @@ echo "$tmp"])])
 @end example
 @end defmac
 
+@defmac AS_VAR_APPEND (@var{var}, @var{text})
+@asindex{APPEND}
+Emit shell code to append the shell expansion of @var{text} to the end
+of the current contents of the polymorphic shell variable @var{var},
+taking advantage of shells that provide the @samp{+=} extension for more
+efficient scaling.
+
+For situations where the final contents of @var{var} are relatively
+short (less than 256 bytes), it is more efficient to use the simpler
+code sequence of @code{@var{var}=$@{@var{var}@}@var{text}} (or its
+polymorphic equivalent of @code{AS_VAR_COPY([tmp], [@var{var}])} and
+@code{AS_VAR_SET([@var{var}], ["$tmp"@var{text}])}).  But in the case
+when the script will be repeatedly appending text into @code{var},
+issues of scaling start to become apparent.  A naive implementation
+requires execution time linear to the length of the current contents of
+@var{var} as well as the length of @var{text} for a single append, for
+an overall quadratic scaling with multiple appends.  This macro takes
+advantage of shells which provide the extension
+@code{@var{var}+=@var{text}}, which can provide amortized constant time
+for a single append, for an overall linear scaling with multiple
+appends.  Note that unlike @code{AS_VAR_SET}, this macro requires that
+@var{text} be quoted properly to avoid field splitting and file name
+expansion.
+@end defmac
+
 @defmac AS_VAR_COPY (@var{dest}, @var{source})
 @asindex{VAR_COPY}
 Emit shell code to assign the contents of the polymorphic shell variable
@@ -12163,7 +12188,10 @@ header stdlib.h detected
 @defmac AS_VAR_SET (@var{var}, @ovar{value})
 @asindex{VAR_SET}
 Emit shell code to assign the contents of the polymorphic shell variable
-@var{var} to the shell expansion of @var{value}.
+@var{var} to the shell expansion of @var{value}.  @var{value} is not
+subject to field splitting or file name expansion, so if command
+substitution is used, it may be done with @samp{`""`} rather than using
+an intermediate variable (@pxref{Shell Substitutions}).
 @end defmac
 
 @defmac AS_VAR_SET_IF (@var{var}, @ovar{if-set}, @ovar{if-undef})
index 9ef15f5704a3766a6b33ddb2df0f0acb7c4e7e39..10537eb0c12a4a72510abccd4729e99eeffa9804 100644 (file)
@@ -280,6 +280,7 @@ _AS_TEST_PREPARE
 _AS_TR_CPP_PREPARE
 _AS_TR_SH_PREPARE
 _AS_UNSET_PREPARE
+_AS_VAR_APPEND_PREPARE
 m4_popdef([AS_REQUIRE])dnl
 ])
 
@@ -303,6 +304,7 @@ AS_REQUIRE([_AS_TEST_PREPARE])
 AS_REQUIRE([_AS_TR_CPP_PREPARE])
 AS_REQUIRE([_AS_TR_SH_PREPARE])
 AS_REQUIRE([_AS_UNSET_PREPARE])
+AS_REQUIRE([_AS_VAR_APPEND_PREPARE], [], [M4SH-INIT-FN])
 m4_divert_pop[]dnl
 ])
 
@@ -1637,6 +1639,52 @@ AS_REQUIRE([_AS_TR_CPP_PREPARE])dnl
 # when passed through eval, and a polymorphic name is either type.
 
 
+# _AS_VAR_APPEND_PREPARE
+# ----------------------
+# Define as_func_append to the optimum definition for the current
+# shell (bash and zsh provide the += assignment operator to avoid
+# quadratic append growth over repeated appends).
+m4_defun([_AS_VAR_APPEND_PREPARE],
+[AS_FUNCTION_DESCRIBE([as_func_append], [VAR VALUE],
+[Append the text in VALUE to the end of the definition contained in
+VAR.  Take advantage of any shell optimizations that allow amortized
+linear growth over repeated appends, instead of the typical quadratic
+growth present in naive implementations.])
+AS_IF([_AS_RUN(["AS_ESCAPE([_AS_VAR_APPEND_WORKS])"])],
+[eval 'as_func_append ()
+  {
+    eval $[]1+=\$[]2
+  }'],
+[as_func_append ()
+  {
+    eval $[]1=\$$[]1\$[]2
+  }]) # as_func_append
+])
+
+
+# _AS_VAR_APPEND_WORKS
+# --------------------
+# Output a shell test to discover whether += works.
+m4_define([_AS_VAR_APPEND_WORKS],
+[as_var=1; as_var+=2; test x$as_var = x12])
+
+
+# AS_VAR_APPEND(VAR, VALUE)
+# -------------------------
+# Append the shell expansion of VALUE to the end of the existing
+# contents of the polymorphic shell variable VAR, taking advantage of
+# any shell optimizations that allow repeated appends to result in
+# amortized linear scaling rather than quadratic behavior.  This macro
+# is not worth the overhead unless the expected final size of the
+# contents of VAR outweigh the typical VALUE size of repeated appends.
+# Note that unlike AS_VAR_SET, VALUE must be properly quoted to avoid
+# field splitting and file name expansion.
+m4_define([AS_VAR_APPEND],
+[_AS_DETECT_SUGGESTED([_AS_VAR_APPEND_WORKS])dnl
+AS_REQUIRE([_AS_VAR_APPEND_PREPARE], [], [M4SH-INIT-FN])dnl
+as_func_append $1 $2])
+
+
 # AS_VAR_COPY(DEST, SOURCE)
 # -------------------------
 # Set the polymorphic shell variable DEST to the contents of the polymorphic
@@ -1724,7 +1772,8 @@ m4_pushdef([$1], [$as_[$1]])])])
 # AS_VAR_SET(VARIABLE, VALUE)
 # ---------------------------
 # Set the contents of the polymorphic shell VARIABLE to the shell
-# expansion of VALUE.
+# expansion of VALUE.  VALUE is immune to field splitting and file
+# name expansion.
 m4_define([AS_VAR_SET],
 [AS_LITERAL_IF([$1],
               [$1=$2],
index b0ddafdeb789ffeed1eab759937a9ab7bb9478c1..6ea6358594a619d72a79871c7ac8809a2e065180 100644 (file)
@@ -926,7 +926,7 @@ AT_CLEANUP
 ## AS_VAR_*.  ##
 ## ---------- ##
 
-AT_SETUP([AS@&t@_VAR])
+AT_SETUP([AS@&t@_VAR basics])
 AT_KEYWORDS([m4sh AS@&t@_VAR_COPY AS@&t@_VAR_SET AS@&t@_VAR_GET])
 AT_KEYWORDS([AS@&t@_VAR_TEST_SET AS@&t@_VAR_SET_IF AS@&t@_VAR_IF])
 AT_KEYWORDS([AS@&t@_VAR_PUSHDEF AS@&t@_VAR_POPDEF])
@@ -1018,6 +1018,41 @@ ok
 AT_CLEANUP
 
 
+## --------------- ##
+## AS_VAR_APPEND.  ##
+## --------------- ##
+
+AT_SETUP([AS@&t@_VAR_APPEND])
+AT_KEYWORDS([m4sh AS@&t@_VAR])
+
+AT_DATA_M4SH([script.as], [[dnl
+AS_INIT
+# Literals.
+AS_VAR_APPEND([foo], ["hello,  "])
+AS_VAR_APPEND([foo], [world])
+echo "$foo"
+# Indirects via shell vars.
+num=1
+AS_VAR_APPEND([foo$num], ['hello,  '])
+AS_VAR_APPEND([foo$num], [`echo "world"`])
+echo "$foo1"
+# Indirects via command substitution.
+h=hello w=',  world'
+AS_VAR_APPEND([`echo foo2`], [${h}])
+AS_VAR_APPEND([`echo foo2`], ["$w"])
+echo "$foo2"
+]])
+
+AT_CHECK_M4SH
+AT_CHECK([./script], [],
+[[hello,  world
+hello,  world
+hello,  world
+]])
+
+AT_CLEANUP
+
+
 ## ----------------- ##
 ## AS_INIT cleanup.  ##
 ## ----------------- ##