m4-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Changes to m4/doc/m4.texinfo,v [branch-1_4]


From: Eric Blake
Subject: Changes to m4/doc/m4.texinfo,v [branch-1_4]
Date: Thu, 19 Oct 2006 16:12:47 +0000

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.
 
address@hidden Loops
address@hidden Loops and recursion
address@hidden Shift
address@hidden 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:
+
address@hidden Composite quote (@dots{})
address@hidden Composite dquote (@dots{})
address@hidden 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
address@hidden, 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.
address@hidden deffn
+
+An actual implementation of these three macros is distributed as
address@hidden@value{VERSION}/@/examples/@/quote.m4} in this package.  First,
+let's examine their usage:
+
address@hidden
+include(`quote.m4')
address@hidden
+-quote-dquote-dquote_elt-
address@hidden
+-quote()-dquote()-dquote_elt()-
address@hidden'-`'-
+-quote(`1')-dquote(`1')-dquote_elt(`1')-
address@hidden'-`1'-
+-quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')-
address@hidden,2-`1',`2'-`1',`2'-
+define(`n', `$#')dnl
+-n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))-
address@hidden
+dquote(dquote_elt(`1', `2'))
address@hidden'',``2''
+dquote_elt(dquote(`1', `2'))
address@hidden',`2''
address@hidden 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
address@hidden 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.
+
address@hidden
+undivert(`quote.m4')dnl
address@hidden(`-1')
address@hidden quote(args) - convert args to single-quoted string
address@hidden(`quote', `ifelse(`$#', `0', `', ``$*'')')
address@hidden dquote(args) - convert args to quoted list of quoted strings
address@hidden(`dquote', ``$@@'')
address@hidden dquote_elt(args) - convert args to list of double-quoted strings
address@hidden(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
address@hidden                             ```$1'',$0(shift($@@))')')
address@hidden'dnl
address@hidden example
+
address@hidden Forloop
address@hidden 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},
address@hidden), 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
address@hidden, @pxref{Incr}), and recurses.
 
-Here is the actual implementation of @code{forloop}, distributed as
+Here is an actual implementation of @code{forloop}, distributed as
 @address@hidden/@/examples/@/forloop.m4} in this package:
 
 @example
-undivert(`forloop.m4')
+undivert(`forloop.m4')dnl
 @result{}divert(`-1')
address@hidden forloop(var, from, to, stmt)
address@hidden(`forloop',
address@hidden  `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', 
`$4')popdef(`$1')')
address@hidden forloop(var, from, to, stmt) - simple version
address@hidden(`forloop', `pushdef(`$1', `$2')_forloop($@@)popdef(`$1')')
 @result{}define(`_forloop',
address@hidden  `$4`'ifelse($1, `$3', ,
address@hidden    `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')')
address@hidden       `$4`'ifelse($1, `$3', `', `define(`$1', 
incr($1))$0($@@)')')
 @result{}divert`'dnl
address@hidden
 @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
address@hidden less than @var{end}, @var{end} not numeric, or
address@hidden not being a macro name.  See if you can improve these
+macros; or @pxref{Improved forloop, , Answers}).
+
address@hidden Foreach
address@hidden 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
 
address@hidden Improved forloop
address@hidden 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 @address@hidden/@/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}.
+
address@hidden
+undivert(`forloop2.m4')dnl
address@hidden(`-1')
address@hidden forloop(var, from, to, stmt) - improved version:
address@hidden   works even if VAR is not a strict macro name
address@hidden   performs sanity check that FROM is larger than TO
address@hidden   allows complex numerical expressions in TO and FROM
address@hidden(`forloop', `ifelse(eval(`($3) >= ($2)'), `1',
address@hidden  `pushdef(`$1', eval(`$2'))_forloop(`$1',
address@hidden    eval(`$3'), `$4')popdef(`$1')')')
address@hidden(`_forloop',
address@hidden  `$3`'ifelse(indir(`$1'), `$2', `',
address@hidden    `define(`$1', incr(indir(`$1')))$0($@@)')')
address@hidden'dnl
+include(`forloop2.m4')
address@hidden
+forloop(`i', `2', `1', `no iteration occurs')
address@hidden
+forloop(`', `1', `2', ` odd iterator name')
address@hidden odd iterator name odd iterator name
+forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
address@hidden 0xa 0xb 0xc
+forloop(`i', `a', `b', `non-numeric bounds')
address@hidden:stdin:6: bad expression in eval (bad input): (b) >= (a)
address@hidden
address@hidden 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.
+
address@hidden Improved foreach
address@hidden Solution for @code{foreach}
+
+FIXME - add content.
+
 @node Improved cleardivert
 @section Solution for @code{cleardivert}
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]