[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: |
Fri, 17 Feb 2006 18:02:15 +0100 |
User-agent: |
Mutt/1.5.11 |
Hi Eric,
* Eric Blake wrote on Thu, Feb 16, 2006 at 10:08:12PM CET:
> According to Ralf Wildenhues on 2/16/2006 1:58 PM:
> >>m4_for([myvar], 1, 1, 0, [ myvar])
> >
> > Yes, good idea. Below is an additional patchlet for the first and third
> > case. The second isn't m4_assert'ed at the moment: the body is expanded
> > once, with myvar set to 1.
> Either way, the
> testsuite needs to explicitly test the chosen behavior, so that we cannot
> accidentally regress in the future (even though we never anticipate a user
> coding up m4_for([myval], 1, 1, 0, [ myval]), we can't be too careful).
Good idea.
Below is an updated patch, which combines the previous version and
tests all three of your cases, and also makes sure that it works
with arguments that themselves are arithmetic expressions (as opposed
to plain integers). I also changed it so that it does not incur
integer overflow any more.
Who would've thought a simple for-loop was so involved? Guess for
each simple programming concept there is a language in which it is
difficult to realize. ;-)
OK to apply?
Side note: m4_cmp and m4_sign need similar fixes, if they are to be
used more widely.
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.
(m4_for): Fix to never loop (almost) endlessly, work correctly
with arithmetic expressions in arguments, a step of zero or
non-integer multiple of the interval, and avoid integer
overflow.
* 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 17 Feb 2006 16:42:17 -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 17 Feb 2006 16:42:17 -0000
@@ -571,19 +571,24 @@
# Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO.
# Both limits are included, and bounds are checked for consistency.
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], m4_eval([$2]))dnl
+m4_if(m4_eval(([$3]) > $1), 1,
+[m4_pushdef([_m4_step], m4_eval(m4_default([$4], 1)))dnl
+m4_assert(_m4_step > 0)dnl
+_m4_for([$1], m4_eval((([$3]) - $1) / _m4_step * _m4_step + $1), _m4_step,
[$5])],
+ m4_eval(([$3]) < $1), 1,
+[m4_pushdef([_m4_step], m4_eval(m4_default([$4], -1)))dnl
+m4_assert(_m4_step < 0)dnl
+_m4_for([$1], m4_eval(($1 - ([$3])) / -(_m4_step) * _m4_step + $1), _m4_step,
[$5])],
+ [m4_pushdef(_m4_step,[])dnl
+$5])[]dnl
+m4_popdef([_m4_step])dnl
m4_popdef([$1])])
-# _m4_for(VARIABLE, FIRST, LAST, STEP, EXPRESSION)
-# ------------------------------------------------
-# Core of the loop, no consistency checks.
+# _m4_for(VARIABLE, LAST, STEP, EXPRESSION)
+# -----------------------------------------
+# Core of the loop, no consistency checks, all arguments are plain numbers.
m4_define([_m4_for],
[$4[]dnl
m4_if($1, [$2], [],
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 17 Feb 2006 16:42:17 -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,117 @@
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])
+dnl Make sure we do not loop endlessly
+m4_for([myval], 1, 1, 0, [ myval])
+dnl Make sure to properly parenthesize
+m4_for([myvar], 3-5, -2+8, , [ myvar])
+m4_for([myvar], -2+8, 3-5, , [ myvar])
+m4_for([myvar], 8, 16, 3 * 2, [ myvar])
+m4_for([myvar], 8, 16, -3 * -2, [ myvar])
+m4_for([myvar], [2<<2], [2<<3], [-3 * (-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
+ 1
+ -2 -1 0 1 2 3 4 5 6
+ 6 5 4 3 2 1 0 -1 -2
+ 8 14
+ 8 14
+ 8 14
+ 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 > 0
+script.4s:3: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_divert_push([0])m4_wrap([m4_divert_pop([0])[]])dnl
+m4_for([myvar], 1, 2, 0, [ myvar])
+]])
+
+AT_CHECK_M4SUGAR([], 1, [],
+[[script.4s:3: error: assert failed: 0 > 0
+script.4s:3: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_divert_push([0])m4_wrap([m4_divert_pop([0])[]])dnl
+m4_for([myvar], 2, 1, 0, [ myvar])
+]])
+
+AT_CHECK_M4SUGAR([], 1, [],
+[[script.4s:3: error: assert failed: 0 < 0
+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, 2006/02/15
- 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 <=
- 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