From 92f34215fcf5e13206f7632ea832b48ce4dca702 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 13 Oct 2008 15:37:31 -0600 Subject: [PATCH] Add m4_set_map. * lib/m4sugar/m4sugar.m4 (m4_set_foreach): New macro. * tests/m4sugar.at (m4@&t@_set): Enhance test. * doc/autoconf.texi (Set manipulation Macros) : Document it. * NEWS: Likewise. Signed-off-by: Eric Blake --- ChangeLog | 7 +++++++ NEWS | 2 +- doc/autoconf.texi | 14 +++++++++++++- lib/m4sugar/m4sugar.m4 | 15 ++++++++++++++- tests/m4sugar.at | 12 ++++++++++-- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 988018fe..45a04343 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2008-10-17 Eric Blake + Add m4_set_map. + * lib/m4sugar/m4sugar.m4 (m4_set_foreach): New macro. + * tests/m4sugar.at (m4@&t@_set): Enhance test. + * doc/autoconf.texi (Set manipulation Macros) : + Document it. + * NEWS: Likewise. + Document m4_map_args. * lib/m4sugar/m4sugar.m4 (m4_transform, m4_transform_pair): Rename... diff --git a/NEWS b/NEWS index 664425cd..1ba23cc5 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,7 @@ GNU Autoconf NEWS - User visible changes. ** Configure scripts now use shell functions. ** The following m4sugar macros are new: - m4_default_quoted m4_map_args m4_map_args_pair + m4_default_quoted m4_map_args m4_map_args_pair m4_set_map ** The following documented m4sh macros are new: AS_LINENO_PREPARE AS_ME_PREPARE AS_VAR_COPY diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 9573034e..d539329e 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -11751,6 +11751,17 @@ m4_set_empty([b], [0], [m4_count(m4_set_list([b]))]) @end example @end defmac +@defmac m4_set_map (@var{set}, @var{action}) +@msindex{set_map} +For each element in the set @var{set}, expand @var{action} with a single +argument of the set element. Behavior is unspecified if @var{action} +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 passed as an argument. This macro is faster than the +corresponding +@code{m4_map_args([@var{action}]m4_set_listc([@var{set}]))}. +@end defmac + @defmac m4_set_remove (@var{set}, @var{value}, @ovar{if-present}, @ @ovar{if-absent}) @msindex{set_remove} @@ -11758,7 +11769,8 @@ If @var{value} is an element in the set @var{set}, then remove it and expand @var{if-present}. Otherwise expand @var{if-absent}. This macro operates in constant time so that multiple removals will scale linearly rather than quadratically; but when used outside of -@code{m4_set_foreach}, it leaves memory occupied until the set is later +@code{m4_set_foreach} or @code{m4_set_map}, it leaves memory occupied +until the set is later compacted by @code{m4_set_contents} or @code{m4_set_list}. Several other set operations are then less efficient between the time of element removal and subsequent memory compaction, but still maintain their diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index fa01ec6a..2d50230d 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -2717,6 +2717,19 @@ m4_define([m4_set_listc], [_m4_set_contents_1])([$1])_m4_set_contents_2([$1], [,_m4_defn([_m4_set_($1)])])]) +# m4_set_map(SET, ACTION) +# ----------------------- +# For each element of SET, expand ACTION with a single argument of the +# current element. ACTION should not recursively list SET's contents, +# add elements to SET, nor delete any element from SET except the one +# passed as an argument. The order that the elements are visited in +# is not guaranteed. This is faster than the corresponding +# m4_map_args([ACTION]m4_set_listc([SET])) +m4_define([m4_set_map], +[m4_ifdef([_m4_set_cleanup($1)], + [_m4_set_contents_1c], [_m4_set_contents_1])([$1])_m4_set_contents_2([$1], + [$2(_m4_defn([_m4_set_($1)]))])]) + # m4_set_remove(SET, VALUE, [IF-PRESENT], [IF-ABSENT]) # ---------------------------------------------------- # If VALUE is an element of SET, delete it and expand IF-PRESENT. @@ -2726,7 +2739,7 @@ m4_define([m4_set_listc], # # Optimize if the element being removed is the most recently added, # since defining _m4_set_cleanup($1) slows down so many other macros. -# In particular, this plays well with m4_set_foreach. +# In particular, this plays well with m4_set_foreach and m4_set_map. m4_define([m4_set_remove], [m4_set_contains([$1], [$2], [_m4_set_size([$1], [m4_decr])m4_if(_m4_defn([_m4_set([$1])]), [$2], diff --git a/tests/m4sugar.at b/tests/m4sugar.at index 72b78432..d6f40a7a 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -1136,7 +1136,8 @@ AT_SETUP([m4@&t@_set]) AT_KEYWORDS([m4@&t@_set_add m4@&t@_set_add_all m4@&t@_set_contains m4@&t@_set_contents m4@&t@_set_delete m4@&t@_set_difference m4@&t@_set_dump m4@&t@_set_empty m4@&t@_set_foreach m4@&t@_set_intersection m4@&t@_set_list -m4@&t@_set_listc m4@&t@_set_remove m4@&t@_set_size m4@&t@_set_union]) +m4@&t@_set_listc m4@&t@_set_map m4@&t@_set_remove m4@&t@_set_size +m4@&t@_set_union]) # Simple tests AT_CHECK_M4SUGAR_TEXT([[m4_set_contains([a], [1], [yes], [no]) @@ -1161,6 +1162,8 @@ m4_set_difference([a], [b]) m4_set_difference([b], [a]) m4_set_intersection([a], [b]) m4_set_union([a], [b]) +m4_define([printodd], [m4_if(m4_eval([$1 & 1]), [1], [:$1])])dnl +m4_set_map([a], [printodd]) m4_set_foreach([a], [i], [m4_if(m4_eval(i & 1), [1], [m4_set_remove([a], i)])]) m4_set_list([a]) m4_set_add([a], []) @@ -1196,6 +1199,7 @@ yes ,,4 ,3 ,1,2,3,,4 +:1:3 2 @@ -1259,11 +1263,15 @@ m4_len(m4_set_contents([a])) m4_len(m4_set_foreach([b], [b], [m4_if(m4_eval(b & 1), [1], [m4_set_remove([b], b, [-])])])) m4_set_size([b]) +m4_define([prune3x], [m4_if(m4_eval([$1 % 3]), [0], + [m4_set_remove([a], [$1], [-])])])dnl +m4_len(m4_set_map([a], [prune3x])) m4_count(m4_shift(m4_set_intersection([a], [b]))) ]], [[38894 5000 5000 -5000 +3333 +3334 ]]) AT_CLEANUP -- 2.47.2