CVSROOT:        /sources/m4
Module name:    m4
Branch:         branch-1_4
Changes by:     Eric Blake <ericb>      06/10/19 16:12:46

Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.88
retrieving revision 1.1.1.1.2.89
diff -u -b -r1.1.1.1.2.88 -r1.1.1.1.2.89
--- doc/m4.texinfo      16 Oct 2006 13:15:32 -0000      1.1.1.1.2.88
+++ doc/m4.texinfo      19 Oct 2006 16:12:46 -0000      1.1.1.1.2.89
@@ -190,7 +190,9 @@
 
 * Ifdef::                       Testing if a macro is defined
 * Ifelse::                      If-else construct, or multibranch
-* Loops::                       Loops and recursion in m4
+* Shift::                       Recursion in @code{m4}
+* Forloop::                     Iteration by counting
+* Foreach::                     Iteration by list contents
 
 How to debug macros and input
 
@@ -262,6 +264,8 @@
 Correct version of some examples
 
 * Improved exch::               Solution for @code{exch}
+* Improved forloop::            Solution for @code{forloop}
+* Improved foreach::            Solution for @code{foreach}
 * Improved cleardivert::        Solution for @code{cleardivert}
 * Improved fatal_error::        Solution for @code{fatal_error}
 
@@ -1913,7 +1917,9 @@
 @menu
 * Ifdef::                       Testing if a macro is defined
 * Ifelse::                      If-else construct, or multibranch
-* Loops::                       Loops and recursion in m4
+* Shift::                       Recursion in @code{m4}
+* Forloop::                     Iteration by counting
+* Foreach::                     Iteration by list contents
 @end menu
 
 @node Ifdef
@@ -2042,8 +2048,8 @@
 examples.  A common use of @code{ifelse} is in macros implementing loops
 of various kinds.
 
[EMAIL PROTECTED] Loops
[EMAIL PROTECTED] Loops and recursion
[EMAIL PROTECTED] Shift
[EMAIL PROTECTED] Recursion in @code{m4}
 
 @cindex recursive macros
 @cindex macros, recursive
@@ -2077,7 +2083,7 @@
 An example of the use of @code{shift} is this macro:
 
 @deffn Composite reverse (@dots{})
-Takes any number of arguments, and reverse their order.
+Takes any number of arguments, and reverses their order.
 @end deffn
 
 It is implemented as:
@@ -2096,7 +2102,70 @@
 
 While not a very interesting macro, it does show how simple loops can be
 made with @code{shift}, @code{ifelse} and recursion.  It also shows
-that @code{shift} is usually used with @samp{$@@}.
+that @code{shift} is usually used with @samp{$@@}.  Sometimes, a
+recursive algorithm requires adding quotes to each element:
+
[EMAIL PROTECTED] Composite quote (@dots{})
[EMAIL PROTECTED] Composite dquote (@dots{})
[EMAIL PROTECTED] Composite dquote_elt (@dots{})
+Takes any number of arguments, and adds quoting.  With @code{quote},
+only one level of quoting is added, effectively removing whitespace
+after commas and turning multiple arguments into a single string.  With
[EMAIL PROTECTED], two levels of quoting are added, one around each element,
+and one around the list.  And with @code{dquote_elt}, two levels of
+quoting are added around each element.
[EMAIL PROTECTED] deffn
+
+An actual implementation of these three macros is distributed as
[EMAIL PROTECTED]@value{VERSION}/@/examples/@/quote.m4} in this package.  First,
+let's examine their usage:
+
[EMAIL PROTECTED]
+include(`quote.m4')
[EMAIL PROTECTED]
+-quote-dquote-dquote_elt-
[EMAIL PROTECTED]
+-quote()-dquote()-dquote_elt()-
[EMAIL PROTECTED]'-`'-
+-quote(`1')-dquote(`1')-dquote_elt(`1')-
[EMAIL PROTECTED]'-`1'-
+-quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')-
[EMAIL PROTECTED],2-`1',`2'-`1',`2'-
+define(`n', `$#')dnl
+-n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))-
[EMAIL PROTECTED]
+dquote(dquote_elt(`1', `2'))
[EMAIL PROTECTED]'',``2''
+dquote_elt(dquote(`1', `2'))
[EMAIL PROTECTED]',`2''
[EMAIL PROTECTED] example
+
+The last two lines show that when given two arguments, @code{dquote}
+results in one string, while @code{dquote_elt} results in two.  Now,
+examine the implementation.  Note that @code{quote} and
[EMAIL PROTECTED] make decisions based on their number of arguments, so
+that when called without arguments, they result in nothing instead of a
+quoted empty string; this is so that it is possible to distinquish
+between no arguments and an empty first argument.  @code{dquote}, on the
+other hand, results in a string no matter what, since it is still
+possible to tell whether it was invoked without arguments based on the
+resulting string.
+
[EMAIL PROTECTED]
+undivert(`quote.m4')dnl
[EMAIL PROTECTED](`-1')
[EMAIL PROTECTED] quote(args) - convert args to single-quoted string
[EMAIL PROTECTED](`quote', `ifelse(`$#', `0', `', ``$*'')')
[EMAIL PROTECTED] dquote(args) - convert args to quoted list of quoted strings
[EMAIL PROTECTED](`dquote', ``$@@'')
[EMAIL PROTECTED] dquote_elt(args) - convert args to list of double-quoted 
strings
[EMAIL PROTECTED](`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
[EMAIL PROTECTED]                             ```$1'',$0(shift($@@))')')
[EMAIL PROTECTED]'dnl
[EMAIL PROTECTED] example
+
[EMAIL PROTECTED] Forloop
[EMAIL PROTECTED] Iteration by counting
 
 @cindex for loops
 @cindex loops, counting
@@ -2142,35 +2211,36 @@
 the first argument.
 
 The macro @code{_forloop} expands the fourth argument once, and tests
-to see if it is finished.  If it has not finished, it increments
-the iteration variable (using the predefined macro @code{incr},
[EMAIL PROTECTED]), and recurses.
+to see if the iterator has reached the final value.  If it has not
+finished, it increments the iterator (using the predefined macro
[EMAIL PROTECTED], @pxref{Incr}), and recurses.
 
-Here is the actual implementation of @code{forloop}, distributed as
+Here is an actual implementation of @code{forloop}, distributed as
 @[EMAIL PROTECTED]/@/examples/@/forloop.m4} in this package:
 
 @example
-undivert(`forloop.m4')
+undivert(`forloop.m4')dnl
 @result{}divert(`-1')
[EMAIL PROTECTED] forloop(var, from, to, stmt)
[EMAIL PROTECTED](`forloop',
[EMAIL PROTECTED]  `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', 
`$4')popdef(`$1')')
[EMAIL PROTECTED] forloop(var, from, to, stmt) - simple version
[EMAIL PROTECTED](`forloop', `pushdef(`$1', `$2')_forloop($@@)popdef(`$1')')
 @result{}define(`_forloop',
[EMAIL PROTECTED]  `$4`'ifelse($1, `$3', ,
[EMAIL PROTECTED]    `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
[EMAIL PROTECTED]       `$4`'ifelse($1, `$3', `', `define(`$1', 
incr($1))$0($@@)')')
 @result{}divert`'dnl
[EMAIL PROTECTED]
 @end example
 
-Notice the careful use of quotes.  Only three macro arguments are
+Notice the careful use of quotes.  Certain macro arguments are left
 unquoted, each for its own reason.  Try to find out @emph{why} these
-three arguments are left unquoted, and see what happens if they are
-quoted.
+arguments are left unquoted, and see what happens if they are quoted.
+(As presented, these two macros are useful but not very robust for
+general use.  They lack even basic error handling for cases like
[EMAIL PROTECTED] less than @var{end}, @var{end} not numeric, or
[EMAIL PROTECTED] not being a macro name.  See if you can improve these
+macros; or @pxref{Improved forloop, , Answers}).
+
[EMAIL PROTECTED] Foreach
[EMAIL PROTECTED] Iteration by list contents
 
-Now, even though these two macros are useful, they are still not robust
-enough for general use. They lack even basic error handling of cases
-like start value less than final value, and the first argument not being
-a name.  Correcting these errors are left as an exercise to the reader.
+FIXME - Fill out this section.
 
 @node Debugging
 @chapter How to debug macros and input
@@ -3952,7 +4022,7 @@
 @result{}300
 @end example
 
-Using the @code{forloop} macro defined earlier (@pxref{Loops}), this
+Using the @code{forloop} macro defined earlier (@pxref{Forloop}), this
 example shows how @code{format} can be used to produce tabular output.
 
 @example
@@ -5202,6 +5272,8 @@
 
 @menu
 * Improved exch::               Solution for @code{exch}
+* Improved forloop::            Solution for @code{forloop}
+* Improved foreach::            Solution for @code{foreach}
 * Improved cleardivert::        Solution for @code{cleardivert}
 * Improved fatal_error::        Solution for @code{fatal_error}
 @end menu
@@ -5224,6 +5296,54 @@
 @result{}expansion text
 @end example
 
[EMAIL PROTECTED] Improved forloop
[EMAIL PROTECTED] Solution for @code{forloop}
+
+The @code{forloop} macro (@pxref{Forloop}) as presented earlier can go
+into an infinite loop if given an iterator that is not parsed as a macro
+name.  It does not do any sanity checking on its numeric bounds, and
+only permits decimal numbers for bounds.  Here is an improved version,
+shipped as @[EMAIL PROTECTED]/@/examples/@/forloop2.m4}; this
+version also optimizes based on the fact that the starting bound does
+not need to be passed to the helper @code{_forloop}.
+
[EMAIL PROTECTED]
+undivert(`forloop2.m4')dnl
[EMAIL PROTECTED](`-1')
[EMAIL PROTECTED] forloop(var, from, to, stmt) - improved version:
[EMAIL PROTECTED]   works even if VAR is not a strict macro name
[EMAIL PROTECTED]   performs sanity check that FROM is larger than TO
[EMAIL PROTECTED]   allows complex numerical expressions in TO and FROM
[EMAIL PROTECTED](`forloop', `ifelse(eval(`($3) >= ($2)'), `1',
[EMAIL PROTECTED]  `pushdef(`$1', eval(`$2'))_forloop(`$1',
[EMAIL PROTECTED]    eval(`$3'), `$4')popdef(`$1')')')
[EMAIL PROTECTED](`_forloop',
[EMAIL PROTECTED]  `$3`'ifelse(indir(`$1'), `$2', `',
[EMAIL PROTECTED]    `define(`$1', incr(indir(`$1')))$0($@@)')')
[EMAIL PROTECTED]'dnl
+include(`forloop2.m4')
[EMAIL PROTECTED]
+forloop(`i', `2', `1', `no iteration occurs')
[EMAIL PROTECTED]
+forloop(`', `1', `2', ` odd iterator name')
[EMAIL PROTECTED] odd iterator name odd iterator name
+forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
[EMAIL PROTECTED] 0xa 0xb 0xc
+forloop(`i', `a', `b', `non-numeric bounds')
[EMAIL PROTECTED]:stdin:6: bad expression in eval (bad input): (b) >= (a)
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
+Of course, it is possible to make even more improvements, such as
+adding an optional step argument, or allowing iteration through
+descending sequences.  @acronym{GNU} Autoconf provides some of these
+additional bells and whistles in its @code{m4_for} macro.
+
[EMAIL PROTECTED] Improved foreach
[EMAIL PROTECTED] Solution for @code{foreach}
+
+FIXME - add content.
+
 @node Improved cleardivert
 @section Solution for @code{cleardivert}
 


Reply via email to