[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: document m4_foreach*/AC_FOREACH
From: |
Ralf Wildenhues |
Subject: |
Re: document m4_foreach*/AC_FOREACH |
Date: |
Thu, 16 Feb 2006 01:22:39 +0100 |
User-agent: |
Mutt/1.5.9i |
Hi Paul,
Thanks for the review!
* Paul Eggert wrote on Wed, Feb 15, 2006 at 06:03:30AM CET:
> Ralf Wildenhues <address@hidden> writes:
>
> > The following macros allow to implement loops in m4.
>
> Please remove "allow to", and change "m4" to "M4".
Done.
[ regarding m4_for ]
> > @var{step} may be @samp{+1}, or @samp{-1}.
>
> should mention that it defaults to +1
>
> > If it is given, it has to match the order of the limits.
>
> You can't iterate from 1 to 0 step +1?
Correct. Iterating from 1 to 0 step +1 will invoke an m4 assertion.
> If so, this should be mentioned; if not then the point needs
> clarification.
Your comment made me look again. First, I previously just misunderstood
the macro: step may actually be any integer, but needs to point in the
direction of (last - first). This is enforced by the macro. But also
the difference (last - first) had to be a multiple of step, otherwise m4
would iterate until you run out of memory. :-/
So here's an updated patch which rewrites m4_for to fix that, adds tests,
and the fixed and adjusted documentation, and a couple of typos found on
the way.
> Other than that, it looks good; please install.
I'll wait a couple of days before installing the patch below. It quotes
consistently. Its result should not depend on C89 inexact negative
integer division truncation mode. It may cause havoc if (last - first)
or (first - last) overflows though, but so does any code that uses
m4_cmp (and did the previous code). To be fixed next.
Cheers,
Ralf
* doc/autoconf.texi (Looping constructs): New node, to
document m4_for, m4_foreach, m4_foreach_w, and mention
obsolete AC_FOREACH.
(Obsolete Macros): Document AC_FOREACH.
* lib/m4sugar/m4sugar.m4 (_m4_for): Fix declaration comment.
* tests/m4sugar.at: New test for m4_for, m4_foreach, and
m4_foreach_w.
Index: doc/autoconf.texi
===================================================================
RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.949
diff -u -r1.949 autoconf.texi
--- doc/autoconf.texi 15 Feb 2006 07:00:29 -0000 1.949
+++ doc/autoconf.texi 16 Feb 2006 00:02:21 -0000
@@ -437,6 +437,7 @@
Programming in M4sugar
* Redefined M4 Macros:: M4 builtins changed in M4sugar
+* Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control
* Forbidden Patterns:: Catching unexpanded macros
@@ -8781,6 +8782,7 @@
@menu
* Redefined M4 Macros:: M4 builtins changed in M4sugar
+* Looping constructs:: Iteration in M4
* Evaluation Macros:: More quotation and evaluation control
* Forbidden Patterns:: Catching unexpanded macros
@end menu
@@ -8897,6 +8899,48 @@
to recover the behavior of the builtin.
@end defmac
+
+
address@hidden Looping constructs
address@hidden Looping constructs
+
+The following macros implement loops in M4.
+
address@hidden m4_for (@var{var}, @var{first}, @var{last}, @ovar{step},
@var{expression})
address@hidden
+Loop over the numeric values between @var{first} and @var{last}
+including bounds by increments of @var{step}. For each iteration,
+expand @var{expression} with the numeric value assigned to @var{var}.
+If @var{step} is omitted, it defaults to @samp{1} or @samp{-1} depending
+on the order of the limits. If given, @var{step} has to match this
+order.
address@hidden defmac
+
address@hidden m4_foreach (@var{var}, @var{list}, @var{expression})
address@hidden
+Loop over the comma-separated m4 list @var{list}, assigning each value
+to @var{var}, and expand @var{expression}. The following example will
+output two lines:
+
address@hidden
+m4_foreach([myvar], [[foo], [bar, baz]],
+ [echo myvar
+])
+
address@hidden example
address@hidden defmac
+
address@hidden m4_foreach_w (@var{var}, @var{list}, @var{expression})
address@hidden
+Loop over the whitespace-separated list @var{list}, assigning each value
+to @var{var}, and expand @var{expression}.
+
+The deprecated macro @code{AC_FOREACH} is an alias of
address@hidden
address@hidden defmac
+
+
+
@node Evaluation Macros
@subsection Evaluation Macros
@@ -14735,6 +14779,11 @@
@code{AC_PATH_XTRA}
@end defmac
address@hidden AC_FOREACH
address@hidden
address@hidden
address@hidden defmac
+
@defmac AC_FUNC_CHECK
@acindex{FUNC_CHECK}
@code{AC_CHECK_FUNC}
@@ -15955,7 +16004,7 @@
this scheme helps supporting more languages than plain C and C++.
@end itemize
-In addition to the change of syntax, the philosphy has changed too:
+In addition to the change of syntax, the philosophy has changed too:
while emphasis was put on speed at the expense of accuracy, today's
Autoconf promotes accuracy of the testing framework at, address@hidden, the
expense of speed.
Index: lib/m4sugar/m4sugar.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/m4sugar/m4sugar.m4,v
retrieving revision 2.96
diff -u -r2.96 m4sugar.m4
--- lib/m4sugar/m4sugar.m4 11 Jan 2006 08:05:55 -0000 2.96
+++ lib/m4sugar/m4sugar.m4 16 Feb 2006 00:02:21 -0000
@@ -568,21 +568,26 @@
# m4_for(VARIABLE, FIRST, LAST, [STEP = +/-1], EXPRESSION)
# --------------------------------------------------------
-# Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO.
-# Both limits are included, and bounds are checked for consistency.
+# Expand EXPRESSION defining VARIABLE to FROM, FROM + STEP, ..., up to
+# the last value in the interval [FIRST, LAST]. Both limits are
+# included, and STEP is checked for consistency, or set consistently.
m4_define([m4_for],
-[m4_case(m4_sign(m4_eval($3 - $2)),
- 1, [m4_assert(m4_sign(m4_default($4, 1)) == 1)],
- -1, [m4_assert(m4_sign(m4_default($4, -1)) == -1)])dnl
-m4_pushdef([$1], [$2])dnl
-m4_if(m4_eval([$3 > $2]), 1,
- [_m4_for([$1], [$3], m4_default([$4], 1), [$5])],
- [_m4_for([$1], [$3], m4_default([$4], -1), [$5])])dnl
+[m4_pushdef([$1], [$2])dnl
+m4_case(m4_cmp([$3], [$2]),
+ 1, [m4_pushdef([_m4_step], m4_default([$4], 1))dnl
+m4_assert(m4_sign(_m4_step) == 1)dnl
+_m4_for([$1], m4_eval(([$3 - $2]) / _m4_step * _m4_step + [$2]), _m4_step,
[$5])],
+ -1, [m4_pushdef([_m4_step], m4_default([$4], -1))dnl
+m4_assert(m4_sign(_m4_step) == -1)dnl
+_m4_for([$1], m4_eval(([$2 - $3]) / -(_m4_step) * _m4_step + [$2]), _m4_step,
[$5])],
+ 0, [m4_pushdef([_m4_step], [])dnl
+$5])[]dnl
+m4_popdef([_m4_step])dnl
m4_popdef([$1])])
-# _m4_for(VARIABLE, FIRST, LAST, STEP, EXPRESSION)
-# ------------------------------------------------
+# _m4_for(VARIABLE, LAST, STEP, EXPRESSION)
+# -----------------------------------------
# Core of the loop, no consistency checks.
m4_define([_m4_for],
[$4[]dnl
Index: tests/m4sugar.at
===================================================================
RCS file: /cvsroot/autoconf/autoconf/tests/m4sugar.at,v
retrieving revision 1.28
diff -u -r1.28 m4sugar.at
--- tests/m4sugar.at 14 May 2005 07:00:40 -0000 1.28
+++ tests/m4sugar.at 16 Feb 2006 00:02:21 -0000
@@ -2,7 +2,7 @@
AT_BANNER([M4sugar.])
-# Copyright (C) 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,8 +20,8 @@
# 02110-1301, USA.
-# AT_CHECK_M4SUGAR_TEXT(CODE, STDOUT, STDER)
-# ------------------------------------------
+# AT_CHECK_M4SUGAR_TEXT(CODE, STDOUT, STDERR)
+# -------------------------------------------
# Check that m4sugar CODE expands to STDOUT and emits STDERR.
m4_define([AT_CHECK_M4SUGAR_TEXT],
[
@@ -204,3 +204,79 @@
AT_CHECK_M4RE([m4_re_string], address@hidden)
AT_CLEANUP
+
+## ---------- ##
+## M4 Loops. ##
+## ---------- ##
+
+AT_SETUP([M4 loops])
+
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_define([myvar], [outer value])dnl
+m4_for([myvar], 1, 3, 1, [ myvar])
+m4_for([myvar], 1, 3, , [ myvar])
+m4_for([myvar], 3, 1,-1, [ myvar])
+m4_for([myvar], 3, 1, , [ myvar])
+m4_for([myvar], 1, 3, 2, [ myvar])
+m4_for([myvar], 3, 1,-2, [ myvar])
+m4_for([myvar],-1,-3,-2, [ myvar])
+m4_for([myvar],-3,-1, 2, [ myvar])
+dnl Make sure we recalculate the bounds correctly:
+m4_for([myvar], 1, 3, 3, [ myvar])
+m4_for([myvar], 1, 6, 3, [ myvar])
+m4_for([myvar],22,-7,-5, [ myvar])
+m4_for([myvar],-2,-7,-4, [ myvar])
+m4_for([myvar],-7,-2, 4, [ myvar])
+dnl Make sure we are not exposed to division truncation:
+m4_for([myvar], 2, 5, 2, [ myvar])
+m4_for([myvar],-5,-2, 2, [ myvar])
+m4_for([myvar], 5, 2,-2, [ myvar])
+m4_for([myvar],-2,-5,-2, [ myvar])
+dnl Make sure we do not divide by zero:
+m4_for([myvar], 1, 1, , [ myvar])
+m4_for([myvar], 1, 1,+2, [ myvar])
+m4_for([myvar], 1, 1,-2, [ myvar])
+m4_foreach([myvar], [[a], [b, c], [d], [e
+],[f]], [ myvar|])
+m4_foreach_w([myvar], [a b c, d,e f
+g], [ myvar|])
+myvar
+]],
+[[ 1 2 3
+ 1 2 3
+ 3 2 1
+ 3 2 1
+ 1 3
+ 3 1
+ -1 -3
+ -3 -1
+ 1
+ 1 4
+ 22 17 12 7 2 -3
+ -2 -6
+ -7 -3
+ 2 4
+ -5 -3
+ 5 3
+ -2 -4
+ 1
+ 1
+ 1
+ a| b, c| d| e
+| f|
+ a| b| c,| d,e| f| g|
+outer value
+]], [])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_divert_push([0])m4_wrap([m4_divert_pop([0])[]])dnl
+m4_for([myvar], 1, 3,-1, [ myvar])
+]])
+
+AT_CHECK_M4SUGAR([], 1, [],
+[[script.4s:3: error: assert failed: -1 == 1
+script.4s:3: the top level
+autom4te: m4 failed with exit status: 1
+]])
+AT_CLEANUP
- document m4_foreach*/AC_FOREACH, Ralf Wildenhues, 2006/02/14
- Re: document m4_foreach*/AC_FOREACH, Paul Eggert, 2006/02/15
- Re: document m4_foreach*/AC_FOREACH,
Ralf Wildenhues <=
- Re: document m4_foreach*/AC_FOREACH, Eric Blake, 2006/02/16
- Re: document m4_foreach*/AC_FOREACH, Ralf Wildenhues, 2006/02/16
- Re: document m4_foreach*/AC_FOREACH, Eric Blake, 2006/02/16
- Re: document m4_foreach*/AC_FOREACH, Ralf Wildenhues, 2006/02/17
- Re: document m4_foreach*/AC_FOREACH, Stepan Kasal, 2006/02/19
- Re: document m4_foreach*/AC_FOREACH, Ralf Wildenhues, 2006/02/19
- Re: document m4_foreach*/AC_FOREACH, Stepan Kasal, 2006/02/20
- Re: document m4_foreach*/AC_FOREACH, Ralf Wildenhues, 2006/02/20