]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Add m4_argn.
authorEric Blake <ebb9@byu.net>
Wed, 22 Apr 2009 16:43:51 +0000 (10:43 -0600)
committerEric Blake <ebb9@byu.net>
Thu, 23 Apr 2009 02:51:28 +0000 (20:51 -0600)
* lib/m4sugar/m4sugar.m4 (m4_argn): New macro.
* NEWS: Document it.
* doc/autoconf.texi (Looping constructs) <m4_argn>: Likewise.
<m4_car, m4_cdr>: Improve documentation.
* tests/m4sugar.at (m4 lists): New test.

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

index 0d966d33e170fc8a75b694a67cdb3302ff79088e..8bc3ecd43047a28d7f5be0234df35f02f205e875 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-04-22  Eric Blake  <ebb9@byu.net>
+
+       Add m4_argn.
+       * lib/m4sugar/m4sugar.m4 (m4_argn): New macro.
+       * NEWS: Document it.
+       * doc/autoconf.texi (Looping constructs) <m4_argn>: Likewise.
+       <m4_car, m4_cdr>: Improve documentation.
+       * tests/m4sugar.at (m4 lists): New test.
+
 2009-04-22  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        Improve description of AC_PROG_CC_C89 and AC_PROG_CC_C99.
diff --git a/NEWS b/NEWS
index 60a6e20b0c12d90b713075672ab133fa9809a5aa..107a10c0c76fcd1911268f4b9ed856af02aa978d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,7 +19,8 @@ GNU Autoconf NEWS - User visible changes.
 ** The autotest macro AT_CHECK_NOESCAPE is now documented.
 
 ** The following documented m4sugar macros are new:
-   m4_default_nblank  m4_default_nblank_quoted  m4_ifblank  m4_ifnblank
+   m4_argn  m4_default_nblank  m4_default_nblank_quoted  m4_ifblank
+   m4_ifnblank
 
 * Major changes in Autoconf 2.63b (2009-03-31) [beta]
   Released by Eric Blake, based on git versions 2.63.*.
index 1256095a9d02e89c491eb6c4b7a2e88138b8119f..516e58df2130dfb1c7a290904cbe3ada331c356a 100644 (file)
@@ -11146,26 +11146,35 @@ m4_foreach([i], [list], [i])
 @result{}123
 @end example
 
-@defmac m4_car (@var{list})
+@defmac m4_argn (@var{n}, @ovar{arg}@dots{})
+@msindex{argn}
+Extracts argument @var{n} (larger than 0) from the remaining arguments.
+If there are too few arguments, the empty string is used.  For any
+@var{n} besides 1, this is more efficient than the similar
+@samp{m4_car(m4_shiftn([@var{n}], [], [@var{arg}@dots{}]))}.
+@end defmac
+
+@defmac m4_car (@var{arg}@dots{})
 @msindex{car}
-Expands to the quoted first element of the comma-separated quoted
-@var{list}.  Often used with @code{m4_cdr} to recursively iterate
+Expands to the quoted first @var{arg}.  Can be used with @code{m4_cdr}
+to recursively iterate
 through a list.  Generally, when using quoted lists of quoted elements,
 @code{m4_car} should be called without any extra quotes.
 @end defmac
 
-@defmac m4_cdr (@var{list})
+@defmac m4_cdr (@var{arg}@dots{})
 @msindex{cdr}
-Expands to a quoted list of all but the first element of the
-comma-separated quoted @var{list}, or the empty string if @var{list} had
-only one element.  Generally, when using quoted lists of quoted
-elements, @code{m4_cdr} should be called without any extra quotes.
+Expands to a quoted list of all but the first @var{arg}, or the empty
+string if there was only one argument.  Generally, when using quoted
+lists of quoted elements, @code{m4_cdr} should be called without any
+extra quotes.
 
 For example, this is a simple implementation of @code{m4_map}; note how
 each iteration checks for the end of recursion, then merely applies the
 first argument to the first element of the list, then repeats with the
 rest of the list.  (The actual implementation in M4sugar is a bit more
-involved, to gain some speed and share code with @code{m4_map_sep}).
+involved, to gain some speed and share code with @code{m4_map_sep}, and
+also to avoid expanding side effects in @samp{$2} twice).
 @example
 m4_define([m4_map], [m4_ifval([$2],
   [m4_apply([$1], m4_car($2))[]$0([$1], m4_cdr($2))])])dnl
index 420fd9985de8cddcb077966d5d608e2c82b1e9c1..f5a1f1c1af07cc3afb6ba485ceea35052ef1bc1f 100644 (file)
@@ -454,20 +454,35 @@ m4_define([m4_bmatch],
        [m4_if(m4_bregexp([$1], [$2]), -1, [$0([$1], m4_shift3($@))],
              [$3])])])
 
+# m4_argn(N, ARGS...)
+# -------------------
+# Extract argument N (greater than 0) from ARGS.  Example:
+#   m4_define([b], [B])
+#   m4_argn([2], [a], [b], [c]) => b
+#
+# Rather than using m4_car(m4_shiftn([$1], $@)), we exploit the fact that
+# GNU m4 can directly reference any argument, through an indirect macro.
+m4_define([m4_argn],
+[m4_assert([0 < $1])]dnl
+[m4_pushdef([_$0], [_m4_popdef([_$0])]m4_dquote([$]m4_incr([$1])))_$0($@)])
 
-# m4_car(LIST)
-# m4_cdr(LIST)
-# ------------
-# Manipulate m4 lists.
+
+# m4_car(ARGS...)
+# m4_cdr(ARGS...)
+# ---------------
+# Manipulate m4 lists.  m4_car returns the first argument.  m4_cdr
+# bundles all but the first argument into a quoted list.  These two
+# macros are generally used with list arguments, with quoting removed
+# to break the list into multiple m4 ARGS.
 m4_define([m4_car], [[$1]])
 m4_define([m4_cdr],
 [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
        [$#], 1, [],
        [m4_dquote(m4_shift($@))])])
 
-# _m4_cdr(LIST)
-# -------------
-# Like m4_cdr, except include a leading comma unless only one element
+# _m4_cdr(ARGS...)
+# ----------------
+# Like m4_cdr, except include a leading comma unless only one argument
 # remains.  Why?  Because comparing a large list against [] is more
 # expensive in expansion time than comparing the number of arguments; so
 # _m4_cdr can be used to reduce the number of arguments when it is time
index 2dd81dca85b26807b108b4d08dc684e18a0926b8..bf56c4dbacd2f42c440c7f5524c6c12e45ee698c 100644 (file)
@@ -786,6 +786,58 @@ AB
 AT_CLEANUP
 
 
+## ---------- ##
+## m4 lists.  ##
+## ---------- ##
+
+AT_SETUP([m4 lists])
+
+AT_KEYWORDS([m4@&t@_car m4@&t@_cdr m4@&t@_argn _m4@&t_cdr])
+
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_define([a], [A])m4_define([b], [B])m4_define([c], [C])
+m4_argn([1], [a], [b], [c])
+m4_argn([2], [a], [b], [c])
+m4_argn([3], [a], [b], [c])
+m4_argn([4], [a], [b], [c])
+m4_car([a], [b], [c])
+m4_cdr([a], [b], [c])
+m4_cdr([a], [b])
+m4_cdr([a])
+_m4_cdr([a], [b], [c])
+_m4_cdr([a], [b])
+_m4_cdr([a])
+m4_if(m4_cdr([], []), [[]], [good], [bad])
+m4_if(m4_cdr([]), [], [good], [bad])
+]], [[
+a
+b
+c
+
+a
+[b],[c]
+[b]
+
+, [b],[c]
+, [b]
+
+good
+good
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_argn([0], [a], [b], [c])
+]])
+AT_CHECK_M4SUGAR([-o-], [1], [],
+[[script.4s:2: error: assert failed: 0 < 0
+script.4s:2: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_CLEANUP
+
+
 ## ---------- ##
 ## m4_split.  ##
 ## ---------- ##