summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-11-05 17:11:15 -0700
committerEric Blake <ebb9@byu.net>2008-11-05 20:04:49 -0700
commitb07a2b3d74f02078b409f70666853a353f95dd94 (patch)
tree877b7e240314654d4421027b5e6e9f453726cf29
parent4e009d522870613c74305ad49e6cc548133b6bab (diff)
downloadautoconf-b07a2b3d.tar.gz
Add m4_map_args_w.
* lib/m4sugar/m4sugar.m4 (m4_map_args_w): New macro, undocumented for now. (_m4_split): Allow user control over separator. (m4_split): Adjust caller. (m4_foreach_w, m4_append_uniq_w, _m4_text_wrap): Rewrite to use m4_map_args_w. * tests/m4sugar.at (m4@&t@_append): Augment test keywords. (M4 loops): Test new interface. Signed-off-by: Eric Blake <ebb9@byu.net>
-rw-r--r--ChangeLog10
-rw-r--r--lib/m4sugar/m4sugar.m461
-rw-r--r--tests/m4sugar.at10
3 files changed, 61 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 73e8095..e6686fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2008-11-05 Eric Blake <ebb9@byu.net>
+ Add m4_map_args_w.
+ * lib/m4sugar/m4sugar.m4 (m4_map_args_w): New macro, undocumented
+ for now.
+ (_m4_split): Allow user control over separator.
+ (m4_split): Adjust caller.
+ (m4_foreach_w, m4_append_uniq_w, _m4_text_wrap): Rewrite to use
+ m4_map_args_w.
+ * tests/m4sugar.at (m4@&t@_append): Augment test keywords.
+ (M4 loops): Test new interface.
+
Use m4_set_map_sep in more places.
* lib/m4sugar/m4sugar.m4 (m4_set_difference, m4_set_intersection)
(m4_set_union): Use m4_set_map_sep rather than m4_set_foreach.
diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4
index 5c2e1c8..2a0d7ce 100644
--- a/lib/m4sugar/m4sugar.m4
+++ b/lib/m4sugar/m4sugar.m4
@@ -1073,8 +1073,8 @@ m4_define([_m4_foreach],
# m4_foreach_w(VARIABLE, LIST, EXPRESSION)
# ----------------------------------------
-#
-# Like m4_foreach, but the list is whitespace separated.
+# Like m4_foreach, but the list is whitespace separated. Depending on
+# EXPRESSION, it may be more efficient to use m4_map_args_w.
#
# This macro is robust to active symbols:
# m4_foreach_w([Var], [ active
@@ -1082,8 +1082,11 @@ m4_define([_m4_foreach],
# ive ], [-Var-])end
# => -active--b--active-end
#
+# This used to use a slower implementation based on m4_foreach:
+# m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])
m4_define([m4_foreach_w],
-[m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])
+[m4_pushdef([$1])m4_map_args_w([$2],
+ [m4_define([$1],], [)$3])m4_popdef([$1])])
# m4_map(MACRO, LIST)
@@ -1181,6 +1184,29 @@ m4_define([m4_map_args_sep],
[$1[$4]$2[]_m4_foreach([$3[]$1], [$2], m4_shift3($@))])])
+# m4_map_args_w(STRING, [PRE], [POST])
+# ------------------------------------
+# 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])
+#
+# 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
+# altogether. But we must be careful of any \ in PRE or POST.
+# _m4_strip returns a quoted string, but that's okay, since it also
+# supplies an empty leading and trailing argument due to our
+# intentional whitespace around STRING. We use m4_substr to strip the
+# 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_define([_m4_map_args_w],
+[m4_substr([$1], [$2], m4_eval(m4_len([$1]) - [$2] - [$3]))])
+
+
# m4_stack_foreach(MACRO, FUNC)
# m4_stack_foreach_lifo(MACRO, FUNC)
# ----------------------------------
@@ -2024,7 +2050,6 @@ m4_define([m4_toupper],
# m4_split(STRING, [REGEXP])
# --------------------------
-#
# Split STRING into an m4 list of quoted elements. The elements are
# quoted with [ and ]. Beginning spaces and end spaces *are kept*.
# Use m4_strip to remove them.
@@ -2053,15 +2078,15 @@ m4_define([m4_toupper],
# so avoid unnecessary dnl inside the definition.
m4_define([m4_split],
[m4_if([$1], [], [],
- [$2], [ ], [m4_if(m4_index([$1], [ ]), [-1], [[[$1]]], [_$0($@)])],
- [$2], [], [_$0([$1], [[ ]+])],
- [_$0($@)])])
+ [$2], [ ], [m4_if(m4_index([$1], [ ]), [-1], [[[$1]]],
+ [_$0([$1], [$2], [, ])])],
+ [$2], [], [_$0([$1], [[ ]+], [, ])],
+ [_$0([$1], [$2], [, ])])])
m4_define([_m4_split],
[m4_changequote([-=<{(],[)}>=-])]dnl
[[m4_bpatsubst(-=<{(-=<{($1)}>=-)}>=-, -=<{($2)}>=-,
- -=<{(], [)}>=-)]m4_changequote([, ])])
-
+ -=<{(]$3[)}>=-)]m4_changequote([, ])])
# m4_flatten(STRING)
@@ -2267,8 +2292,7 @@ m4_define([_m4_append_uniq],
#
# Use _m4_defn for speed.
m4_define([m4_append_uniq_w],
-[m4_foreach_w([m4_Word], [$2],
- [_m4_append_uniq([$1], _m4_defn([m4_Word]), [ ])])])
+[m4_map_args_w([$2], [_m4_append_uniq([$1],], [, [ ])])])
# m4_text_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH])
@@ -2342,17 +2366,16 @@ dnl check if the cursor would exceed the wrap column
dnl if so, reset cursor, and insert newline and prefix
dnl if not, insert the separator (usually a space)
dnl either way, insert the word
-[[m4_foreach_w([m4_Word], [$1],
- [m4_define([m4_Cursor],
- m4_eval(m4_Cursor + m4_qlen(_m4_defn([m4_Word]))
- + 1))m4_if(m4_eval(m4_Cursor > ([$4])),
- [1], [m4_define([m4_Cursor],
- m4_eval(m4_Indent + m4_qlen(_m4_defn([m4_Word])) + 1))
-[$2]],
- [m4_Separator[]])_m4_defn([m4_Word])])]],
+[[m4_map_args_w([$1], [$0_word(], [, [$2], [$4])])]],
dnl finally, clean up the local variables
[[_m4_popdef([m4_Separator], [m4_Cursor], [m4_Indent])]]))
+m4_define([_m4_text_wrap_word],
+[m4_define([m4_Cursor], m4_eval(m4_Cursor + m4_qlen([$1]) + 1))]dnl
+[m4_if(m4_eval(m4_Cursor > ([$3])),
+ [1], [m4_define([m4_Cursor], m4_eval(m4_Indent + m4_qlen([$1]) + 1))
+[$2]],
+ [m4_Separator[]])[$1]])
# m4_text_box(MESSAGE, [FRAME-CHARACTER = `-'])
# ---------------------------------------------
diff --git a/tests/m4sugar.at b/tests/m4sugar.at
index c8b22eb..5a90493 100644
--- a/tests/m4sugar.at
+++ b/tests/m4sugar.at
@@ -546,6 +546,7 @@ AT_CLEANUP
## ----------- ##
AT_SETUP([m4@&t@_append])
+AT_KEYWORDS([m4@&t@_append_uniq m4@&t@_append_uniq_w])
AT_CHECK_M4SUGAR_TEXT(
[[m4_define([active], [ACTIVE])dnl
@@ -876,7 +877,7 @@ AT_CLEANUP
AT_SETUP([M4 loops])
-AT_KEYWORDS([m4@&t@_for m4@&t@_foreach m4@&t@_foreach_w])
+AT_KEYWORDS([m4@&t@_for m4@&t@_foreach m4@&t@_foreach_w m4@&t@_map_args_w])
AT_CHECK_M4SUGAR_TEXT([[dnl
m4_define([myvar], [outer value])dnl
@@ -921,6 +922,10 @@ m4_foreach([myvar], [[a], [b, c], [d], [e
m4_foreach_w([myvar], [a b c, d,e f
g], [ myvar|])
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])
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
@@ -959,6 +964,9 @@ m4_shiftn(3,1,2,3):m4_shiftn(3,1,2,3,4)
| f|
a| b| c,| d,e| f| g|
outer value
+ a| b| c,| d,e| f| g|
+\1a/\1b/
+/a\1/b\1
::4
:4
]], [[hi