[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
document recent iteration functions
From: |
Eric Blake |
Subject: |
document recent iteration functions |
Date: |
Fri, 19 Dec 2008 21:16:08 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
As promised, here is my documentation patch that makes the m4_stack* and
various m4_*_sep macros public, because of the efficiency that they offer.
I've hammered these macros pretty well in autoconf, so I think the API is
pretty much settled now, except for the fact that this patch had to add an
argument to m4_map_args_w for consistency with the rest.
From: Eric Blake <address@hidden>
Date: Fri, 19 Dec 2008 14:06:46 -0700
Subject: [PATCH] Document some recently added macros.
* lib/m4sugar/m4sugar.m4 (m4_map_args_w): Add optional sep
parameter.
* doc/autoconf.texi (Looping constructs) <m4_map_args_sep>
<m4_map_args_w, m4_stack_foreach, m4_stack_foreach_sep>: Document
new macros.
(Set manipulation Macros) <m4_set_map_sep>: Likewise.
* tests/m4sugar.at (m4@&address@hidden, M4 loops): Enhance tests.
* NEWS: Document new macros.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 12 ++++++
NEWS | 4 ++-
doc/autoconf.texi | 89 ++++++++++++++++++++++++++++++++++++++++++++++--
lib/m4sugar/m4sugar.m4 | 45 ++++++++++++------------
tests/m4sugar.at | 9 +++--
5 files changed, 129 insertions(+), 30 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 369433c..e12309f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-12-19 Eric Blake <address@hidden>
+
+ Document some recently added macros.
+ * lib/m4sugar/m4sugar.m4 (m4_map_args_w): Add optional sep
+ parameter.
+ * doc/autoconf.texi (Looping constructs) <m4_map_args_sep>
+ <m4_map_args_w, m4_stack_foreach, m4_stack_foreach_sep>: Document
+ new macros.
+ (Set manipulation Macros) <m4_set_map_sep>: Likewise.
+ * tests/m4sugar.at (m4@&address@hidden, M4 loops): Enhance tests.
+ * NEWS: Document new macros.
+
2008-12-18 Eric Blake <address@hidden>
Fix separator in m4_stack_foreach_sep.
diff --git a/NEWS b/NEWS
index 30ac715..7eff140 100644
--- a/NEWS
+++ b/NEWS
@@ -27,7 +27,9 @@ GNU Autoconf NEWS - User visible changes.
** The following documented m4sugar macros are new:
m4_chomp m4_curry m4_default_quoted m4_esyscmd_s m4_map_args
- m4_map_args_pair m4_set_map
+ m4_map_args_pair m4_map_args_sep m4_map_args_w m4_set_map
+ m4_set_map_sep m4_stack_foreach m4_stack_foreach_lifo
+ m4_stack_foreach_sep m4_stack_foreach_sep_lifo
** The following m4sugar macros are documented now, but in some cases
with slightly different semantics than what the previous
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 1e211a1..2a2d4c7 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -11106,7 +11106,9 @@ Looping constructs
@defmac m4_foreach_w (@var{var}, @var{list}, @var{expression})
@msindex{foreach_w}
Loop over the white-space-separated list @var{list}, assigning each value
-to @var{var}, and expand @var{expression}.
+to @var{var}, and expand @var{expression}. If @var{var} is only
+referenced once in @var{expression}, it is more efficient to use
address@hidden
The deprecated macro @code{AC_FOREACH} is an alias of
@code{m4_foreach_w}.
@@ -11179,7 +11181,8 @@ Looping constructs
the list elements, the macro @code{m4_curry} can be used in @var{macro}
to supply the argument currying necessary to generate the desired
argument list. In the following example, @code{list_add_n} is more
-efficient than @code{list_add_x}.
+efficient than @code{list_add_x}. On the other hand, using
address@hidden can be even more efficient.
@example
m4_define([list], [[1], [2], [3]])dnl
@@ -11218,6 +11221,30 @@ Looping constructs
@end example
@end defmac
address@hidden m4_map_args_sep (@ovar{pre}, @ovar{post}, @ovar{sep},
@address@hidden)
address@hidden
+Expand the sequence @address@hidden@address@hidden for each
+argument, additionally expanding @var{sep} between arguments. One
+common use of this macro is constructing a macro call, where the opening
+and closing parentheses are split between @var{pre} and @var{post}; in
+particular, @code{m4_map_args(address@hidden, address@hidden)} is equivalent
+to @code{m4_map_args_sep(address@hidden(], [)], [], address@hidden)}. This
+macro provides the most efficient means for iterating over an arbitrary
+list of arguments, particularly when repeatedly constructing a macro
+call with more arguments than @var{arg}.
address@hidden defmac
+
address@hidden m4_map_args_w (@var{string}, @ovar{pre}, @ovar{post}, @ovar{sep})
address@hidden
+Expand the sequence @address@hidden@var{post}} for each word in
+the whitespace-separated @var{string}, additionally expanding @var{sep}
+between words. This macro provides the most efficient means for
+iterating over a whitespace-separated string. In particular,
address@hidden(address@hidden, address@hidden(], [)])} is more
+efficient than @code{m4_foreach_w([var], address@hidden,
address@hidden(m4_defn([var]))])}.
address@hidden defmac
+
@defmac m4_shiftn (@var{count}, @dots{})
@defmacx m4_shift2 (@dots{})
@defmacx m4_shift3 (@dots{})
@@ -11232,6 +11259,47 @@ Looping constructs
for two and three shifts, respectively.
@end defmac
address@hidden m4_stack_foreach (@var{macro}, @var{action})
address@hidden m4_stack_foreach_lifo (@var{macro}, @var{action})
address@hidden
address@hidden
+For each of the @code{m4_pushdef} definitions of @var{macro}, expand
address@hidden with the single argument of a definition of @var{macro}.
address@hidden starts with the oldest definition, while
address@hidden starts with the current definition.
address@hidden should not push or pop definitions of @var{macro}, nor is
+there any guarantee that the current definition of @var{macro} matches
+the argument that was passed to @var{action}. The macro @code{m4_curry}
+can be used if @var{action} needs more than one argument, although in
+that case it is more efficient to use @var{m4_stack_foreach_sep}.
+
+Due to technical limitations, there are a few low-level m4sugar
+functions, such as @code{m4_pushdef}, that cannot be used as the
address@hidden argument.
+
address@hidden
+m4_pushdef([a], [1])m4_pushdef([a], [2])dnl
+m4_stack_foreach([a], [ m4_incr])
address@hidden 2 3
+m4_stack_foreach_lifo([a], [ m4_curry([m4_substr], [abcd])])
address@hidden cd bcd
address@hidden example
address@hidden defmac
+
address@hidden m4_stack_foreach_sep (@var{macro}, @ovar{pre}, @ovar{post},
@ovar{sep})
address@hidden m4_stack_foreach_sep_lifo (@var{macro}, @ovar{pre}, @ovar{post},
@
+ @ovar{sep})
address@hidden
address@hidden
+Expand the sequence @address@hidden@var{post}} for each
address@hidden definition of @var{macro}, additionally expanding
address@hidden between definitions. @code{m4_stack_foreach_sep} visits the
+oldest definition first, while @code{m4_stack_foreach_sep_lifo} visits
+the current definition first. This macro provides the most efficient
+means for iterating over a pushdef stack. In particular,
address@hidden(address@hidden, address@hidden)} is short for
address@hidden(address@hidden, address@hidden(], [)])}.
address@hidden defmac
@node Evaluation Macros
@subsection Evaluation Macros
@@ -12071,7 +12139,22 @@ Set manipulation Macros
corresponding counterpart of
@code{m4_map_args(address@hidden(address@hidden))} or
@code{m4_set_foreach(address@hidden, [var],
address@hidden(m4_defn([var]))])}.
address@hidden(m4_defn([var]))])}. It is possible to use @code{m4_curry}
+if more than one argument is needed for @var{action}, although it is
+more efficient to use @code{m4_set_map_sep} in that case.
address@hidden defmac
+
address@hidden m4_set_map_sep (@var{set}, @ovar{pre}, @ovar{post}, @ovar{sep})
address@hidden
+For each element in the set @var{set}, expand
address@hidden@address@hidden, additionally expanding @var{sep}
+between elements. Behavior is unspecified if the expansion recursively
+lists the contents of @var{set} (although listing other sets
+is acceptable), or if it modifies the set in any way other than removing
+the element visited by the expansion. This macro provides the most
+efficient means for non-destructively visiting the elements of a set; in
+particular, @code(m4_set_map(address@hidden, address@hidden) is equivalent
+to @code{m4_set_map_sep(address@hidden, address@hidden(], [)])}.
@end defmac
@defmac m4_set_remove (@var{set}, @var{value}, @ovar{if-present}, @
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 6ca825f..05e357a 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -1145,9 +1145,9 @@ m4_define([m4_mapall],
[_m4_foreach([m4_apply([$1],], [)], [], $2)])])
-# m4_map_sep(MACRO, SEPARATOR, LIST)
-# m4_mapall_sep(MACRO, SEPARATOR, LIST)
-# -------------------------------------
+# m4_map_sep(MACRO, [SEPARATOR], LIST)
+# m4_mapall_sep(MACRO, [SEPARATOR], LIST)
+# ---------------------------------------
# Invoke MACRO($1), SEPARATOR, MACRO($2), ..., MACRO($N) where $1,
# $2... $N are the elements of LIST, and are in turn lists appropriate
# for m4_apply. SEPARATOR is expanded, in order to allow the creation
@@ -1207,8 +1207,8 @@ m4_define([m4_map_args_pair],
[$1([$3], [$4])[]$0([$1], [$2], m4_shift(m4_shift3($@)))])])
-# m4_map_args_sep(PRE, POST, SEP, ARG...)
-# ---------------------------------------
+# m4_map_args_sep([PRE], [POST], [SEP], ARG...)
+# ---------------------------------------------
# Expand PRE[ARG]POST for each argument, with SEP between arguments.
m4_define([m4_map_args_sep],
[m4_if([$#], [0], [m4_fatal([$0: too few arguments: $#])],
@@ -1219,11 +1219,12 @@ m4_define([m4_map_args_sep],
[$1[$4]$2[]_m4_foreach([$3[]$1], [$2], m4_shift3($@))])])
-# m4_map_args_w(STRING, [PRE], [POST])
-# ------------------------------------
+# m4_map_args_w(STRING, [PRE], [POST], [SEP])
+# -------------------------------------------
# Perform the expansion of PRE[word]POST[] for each word in STRING
# separated by whitespace. More efficient than:
# m4_foreach_w([var], [STRING], [PRE[]m4_defn([var])POST])
+# Additionally, expand SEP between words.
#
# As long as we have to use m4_bpatsubst to split the string, we might
# as well make it also apply PRE and POST; this avoids iteration
@@ -1234,9 +1235,9 @@ m4_define([m4_map_args_sep],
# empty elements and remove the extra layer of quoting.
m4_define([m4_map_args_w],
[_$0(_m4_split([ ]m4_flatten([$1])[ ], [[ ]+],
- m4_if(m4_index([$2$3], [\]), [-1], [[$3[]$2]],
- [m4_bpatsubst([[$3[]$2]], [\\], [\\\\])])),
- m4_len([[]$3]), m4_len([$2[]]))])
+ m4_if(m4_index([$2$3$4], [\]), [-1], [[$3[]$4[]$2]],
+ [m4_bpatsubst([[$3[]$4[]$2]], [\\], [\\\\])])),
+ m4_len([[]$3[]$4]), m4_len([$4[]$2[]]))])
m4_define([_m4_map_args_w],
[m4_substr([$1], [$2], m4_eval(m4_len([$1]) - [$2] - [$3]))])
@@ -1262,9 +1263,9 @@ m4_define([m4_stack_foreach_lifo],
[_m4_stack_reverse([$1], [m4_tmp-$1], [$2(_m4_defn([m4_tmp-$1]))])]dnl
[_m4_stack_reverse([m4_tmp-$1], [$1])])
-# m4_stack_foreach_sep(MACRO, PRE, POST, SEP)
-# m4_stack_foreach_sep_lifo(MACRO, PRE, POST, SEP)
-# ------------------------------------------------
+# m4_stack_foreach_sep(MACRO, [PRE], [POST], [SEP])
+# m4_stack_foreach_sep_lifo(MACRO, [PRE], [POST], [SEP])
+# ------------------------------------------------------
# Similar to m4_stack_foreach and m4_stack_foreach_lifo, in that every
# definition of a pushdef stack will be visited. But rather than
# passing the definition as a single argument to a macro, this variant
@@ -1280,8 +1281,8 @@ m4_define([m4_stack_foreach_sep_lifo],
[_m4_stack_reverse([m4_tmp-$1], [$1])])
-# _m4_stack_reverse(OLD, NEW, ACTION, SEP)
-# ----------------------------------------
+# _m4_stack_reverse(OLD, NEW, [ACTION], [SEP])
+# --------------------------------------------
# A recursive worker for pushdef stack manipulation. Destructively
# copy the OLD stack into the NEW, and expanding ACTION for each
# iteration. After the first iteration, SEP is promoted to the front
@@ -2793,8 +2794,8 @@ m4_define([m4_set_contents],
# _m4_set_contents_1(SET)
# _m4_set_contents_1c(SET)
-# _m4_set_contents_2(SET, PRE, POST, SEP)
-# ---------------------------------------
+# _m4_set_contents_2(SET, [PRE], [POST], [SEP])
+# ---------------------------------------------
# Expand to a list of quoted elements currently in the set, each
# surrounded by PRE and POST, and moving SEP in front of PRE on
# recursion. To avoid nesting limit restrictions, the algorithm must
@@ -2868,9 +2869,9 @@ m4_define([m4_set_dump],
[_m4_popdef([_m4_set_size($1)])])m4_ifdef([_m4_set_cleanup($1)],
[_$0_check], [_$0])([$1], [], [$2])])
-# _m4_set_dump(SET, SEP, PREP)
-# _m4_set_dump_check(SET, SEP, PREP)
-# ----------------------------------
+# _m4_set_dump(SET, [SEP], [PREP])
+# _m4_set_dump_check(SET, [SEP], [PREP])
+# --------------------------------------
# Print SEP and the current element, then delete the element and
# recurse with empty SEP changed to PREP. The check variant checks
# whether the element has been previously removed. Use _m4_defn and
@@ -2951,8 +2952,8 @@ m4_define([m4_set_listc],
m4_define([m4_set_map],
[m4_set_map_sep([$1], [$2(], [)])])
-# m4_set_map_sep(SET, PRE, POST, SEP)
-# -----------------------------------
+# m4_set_map_sep(SET, [PRE], [POST], [SEP])
+# -----------------------------------------
# For each element of SET, expand PRE[value]POST[], and expand SEP
# between elements.
m4_define([m4_set_map_sep],
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index a876588..4938027 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -60,8 +60,8 @@ m4_copy([abc], [foo])dnl
m4_stack_foreach([foo], [m4_n])
m4_stack_foreach_lifo([foo], [m4_n])
m4_stack_foreach_sep([abc], [ m4_index([abcdefghijkl],], [)])
-m4_define([colon], [:])dnl
-m4_stack_foreach_sep_lifo([abc], [<], [>], [colon])
+m4_define([colon], [:])m4_define([lt], [<])m4_define([gt], [>])dnl
+m4_stack_foreach_sep_lifo([abc], [lt], [gt], [colon])
m4_pushdef([xyz], [123])dnl
m4_pushdef([xyz], [456])dnl
m4_define([doit], [[$1](m4_stack_foreach_sep([xyz], [m4_dquote(], [)], [,]))
@@ -1029,7 +1029,8 @@ myvar
m4_map_args_w([a b c, d,e f
g], [ ], [|])
m4_map_args_w([a b], [\1], [/])
-m4_map_args_w([a b], [/], [\1])
+m4_define([dashes], [--])dnl
+m4_map_args_w([a b c], [/], [\1], [dashes])
dnl only one side effect expansion, prior to visiting list elements
m4_foreach([i], [[1], [2], [3]m4_errprintn([hi])], [m4_errprintn(i)])dnl
dnl shifting forms an important part of loops
@@ -1070,7 +1071,7 @@ m4_shiftn(3,1,2,3):m4_shiftn(3,1,2,3,4)
outer value
a| b| c,| d,e| f| g|
\1a/\1b/
-/a\1/b\1
+/a\1--/b\1--/c\1
::4
:4
]], [[hi
--
1.6.0.4
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- document recent iteration functions,
Eric Blake <=