[Top][All Lists]
[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}
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/11
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/11
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/12
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/13
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/13
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/16
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/16
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/16
- Changes to m4/doc/m4.texinfo,v [branch-1_4],
Eric Blake <=
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/20
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/20
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/23
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/25
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/26
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/29
- Changes to m4/doc/m4.texinfo,v [branch-1_4], Eric Blake, 2006/10/31