CVSROOT:        /sources/m4
Module name:    m4
Changes by:     Eric Blake <ericb>      06/09/05 13:25:24

Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- doc/m4.texinfo      31 Aug 2006 03:21:35 -0000      1.39
+++ doc/m4.texinfo      5 Sep 2006 13:25:24 -0000       1.40
@@ -124,7 +124,7 @@
 * File Inclusion::              File inclusion
 * Diversions::                  Diverting and undiverting output
 
-* Modules::                     Extending m4 with dynamic runtime modules
+* Modules::                     Extending M4 with dynamic runtime modules
 
 * Text handling::               Macros for text handling
 * Arithmetic::                  Macros for doing arithmetic
@@ -132,8 +132,7 @@
 * Miscellaneous::               Miscellaneous builtin macros
 * Frozen files::                Fast loading of frozen state
 
-* Compatibility::               Compatibility with other versions of m4
-* Experiments::                 Experimental features in GNU M4
+* Compatibility::               Compatibility with other versions of @code{m4}
 * Answers::                     Correct version of some examples
 * Copying This Manual::         How to make copies of this manual
 * Indices::                     Indices of concepts and macros
@@ -152,11 +151,11 @@
 Lexical and syntactic conventions
 
 * Names::                       Macro names
-* Quoted strings::              Quoting input to m4
-* Comments::                    Comments in m4 input
+* Quoted strings::              Quoting input to @code{m4}
+* Comments::                    Comments in @code{m4} input
 * Other tokens::                Other kinds of input tokens
-* Input processing::            How m4 copies input to output
-* Regular expression syntax::   How m4 interprets regular expressions
+* Input processing::            How @code{m4} copies input to output
+* Regular expression syntax::   How @code{m4} interprets regular expressions
 
 How to invoke macros
 
@@ -170,7 +169,7 @@
 
 * Define::                      Defining a new macro
 * Arguments::                   Arguments to macros
-* Pseudo Arguments::            Pseudo arguments to macros
+* Pseudo Arguments::            Special arguments to macros
 * Undefine::                    Deleting a macro
 * Defn::                        Renaming macros
 * Pushdef::                     Temporarily redefining macros
@@ -178,14 +177,15 @@
 
 * Indir::                       Indirect call of macros
 * Builtin::                     Indirect call of builtins
-
 * Symbols::                     Getting the defined macro names
 
 Conditionals, loops, and recursion
 
 * 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
 
@@ -201,7 +201,7 @@
 * Changecom::                   Changing the comment delimiters
 * Changeresyntax::              Changing the regular expression syntax
 * Changesyntax::                Changing the lexical structure of the input
-* M4wrap::                      Saving input until end of input
+* M4wrap::                      Saving text until end of input
 
 File inclusion
 
@@ -215,7 +215,7 @@
 * Divnum::                      Diversion numbers
 * Cleardiv::                    Discarding diverted text
 
-Extending m4 with dynamic runtime modules
+Extending M4 with dynamic runtime modules
 
 * Listing Modules::             Listing loaded modules
 * Load::                        Loading additional modules
@@ -238,19 +238,19 @@
 * Eval::                        Evaluating integer expressions
 * Mpeval::                      Multiple precision arithmetic
 
-Running shell commands
+Macros for running shell commands
 
 * Platform macros::             Determining the platform
 * Syscmd::                      Executing simple commands
 * Esyscmd::                     Reading the output of commands
 * Sysval::                      Exit status
-* Maketemp::                    Making names for temporary files
+* Maketemp::                    Making temporary files
 
 Miscellaneous builtin macros
 
 * Errprint::                    Printing error messages
 * Location::                    Printing current location
-* M4exit::                      Exiting from m4
+* M4exit::                      Exiting from @code{m4}
 * Syncoutput::                  Turning on and off sync lines
 
 Fast loading of frozen state
@@ -263,15 +263,16 @@
 
 * Extensions::                  Extensions in @acronym{GNU} M4
 * Incompatibilities::           Other incompatibilities
+* Experiments::                 Experimental features in @acronym{GNU} M4
 
-Copying This Manual
+How to make copies of this manual
 
 * GNU Free Documentation License::  License for copying this manual
 
-Indices
+Indices of concepts and macros
 
 * Concept index::               Index for many concepts
-* Macro index::                 Index for all m4 macros
+* Macro index::                 Index for all @code{m4} macros
 
 @end detailmenu
 @end menu
@@ -811,15 +812,15 @@
 
 @menu
 * Names::                       Macro names
-* Quoted strings::              Quoting input to m4
-* Comments::                    Comments in m4 input
+* Quoted strings::              Quoting input to @code{m4}
+* Comments::                    Comments in @code{m4} input
 * Other tokens::                Other kinds of input tokens
-* Input processing::            How m4 copies input to output
-* Regular expression syntax::   How m4 interprets regular expressions
+* Input processing::            How @code{m4} copies input to output
+* Regular expression syntax::   How @code{m4} interprets regular expressions
 @end menu
 
 @node Names
[EMAIL PROTECTED] Names
[EMAIL PROTECTED] Macro names
 
 @cindex names
 A name is any sequence of letters, digits, and the character @kbd{_}
@@ -835,7 +836,7 @@
 @xref{Changesyntax}, for more information.
 
 @node Quoted strings
[EMAIL PROTECTED] Quoted strings
[EMAIL PROTECTED] Quoting input to @code{m4}
 
 @cindex quoted string
 A quoted string is a sequence of characters surrounded by quote
@@ -864,7 +865,7 @@
 (@pxref{Changesyntax}).
 
 @node Comments
[EMAIL PROTECTED] Comments
[EMAIL PROTECTED] Comments in @code{m4} input
 
 @cindex comments
 Comments in @code{m4} are normally delimited by the characters @samp{#}
@@ -900,7 +901,7 @@
 @code{changesyntax} (@pxref{Changesyntax}).
 
 @node Other tokens
[EMAIL PROTECTED] Other tokens
[EMAIL PROTECTED] Other kinds of input tokens
 
 Any character, that is neither a part of a name, nor of a quoted string,
 nor a comment, is a token by itself.  When not in the context of macro
@@ -912,7 +913,7 @@
 can be adjusted with @code{changesyntax} (@pxref{Changesyntax}).
 
 @node Input processing
[EMAIL PROTECTED] Input Processing
[EMAIL PROTECTED] How @code{m4} copies input to output
 
 As @code{m4} reads the input token by token, it will copy each token
 directly to the output immediately.
@@ -968,7 +969,7 @@
 all the input has been consumed.
 
 @node Regular expression syntax
[EMAIL PROTECTED] Regular Expression Syntax
[EMAIL PROTECTED] How @code{m4} interprets regular expressions
 
 There are several contexts where @code{m4} parses an argument as a
 regular expression.  This section describes the various flavors of
@@ -1253,14 +1254,15 @@
 
 It is an error if the end of file occurs while collecting arguments.
 
[EMAIL PROTECTED] status: 1
 @example
 define(
 ^D
[EMAIL PROTECTED]:stdin:1: ERROR: end of file in argument list
[EMAIL PROTECTED]:stdin:1: end of file in argument list
 @end example
 
 @node Quoting Arguments
[EMAIL PROTECTED] Quoting macro arguments
[EMAIL PROTECTED] On Quoting Arguments to macros
 
 @cindex quoted macro arguments
 @cindex macros, quoted arguments to
@@ -1335,7 +1337,7 @@
 @menu
 * Define::                      Defining a new macro
 * Arguments::                   Arguments to macros
-* Pseudo Arguments::            Pseudo arguments to macros
+* Pseudo Arguments::            Special arguments to macros
 * Undefine::                    Deleting a macro
 * Defn::                        Renaming macros
 * Pushdef::                     Temporarily redefining macros
@@ -1343,7 +1345,6 @@
 
 * Indir::                       Indirect call of macros
 * Builtin::                     Indirect call of builtins
-
 * Symbols::                     Getting the defined macro names
 @end menu
 
@@ -1780,11 +1781,14 @@
 @end example
 
 Using @code{defn} to generate special tokens for builtin macros outside
-of expected contexts can sometimes trigger warnings.
+of expected contexts can sometimes trigger warnings.  But most of the
+time, such tokens are silently converted to the empty string.
 
 @example
+defn(`defn')
[EMAIL PROTECTED]
 define(defn(`divnum'), `cannot redefine a builtin token')
[EMAIL PROTECTED]:stdin:1: Warning: define: invalid macro name ignored
[EMAIL PROTECTED]:stdin:2: Warning: define: invalid macro name ignored
 @result{}
 divnum
 @result{}0
@@ -2003,6 +2007,25 @@
 defined, that will not be called by accident.  They can @emph{only} be
 called through the builtin @code{indir}.
 
+One other point to observe is that argument collection occurs before
[EMAIL PROTECTED] invokes @var{name}, so if argument collection changes the
+value of @var{name}, that will be reflected in the final expansion.
+This is different than the behavior when invoking macros directly,
+where the definition that was in effect before argument collection is
+used.
+
[EMAIL PROTECTED]
+define(`f', `1')
[EMAIL PROTECTED]
+f(define(`f', `2'))
[EMAIL PROTECTED]
+indir(`f', define(`f', `3'))
[EMAIL PROTECTED]
+indir(`f', undefine(`f'))
[EMAIL PROTECTED]:stdin:4: Warning: indir: undefined macro `f'
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
 @node Builtin
 @section Indirect call of builtins
 
@@ -2124,11 +2147,13 @@
 @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
[EMAIL PROTECTED] Testing macro definitions
[EMAIL PROTECTED] Testing if a macro is defined
 
 @cindex conditionals
 There are two different builtin conditionals in @code{m4}.  The first is
@@ -2156,7 +2181,7 @@
 @end example
 
 @node Ifelse
[EMAIL PROTECTED] Comparing strings
[EMAIL PROTECTED] If-else construct, or multibranch
 
 @cindex comparing strings
 The other conditional, @code{ifelse}, is much more powerful.  It can be
@@ -2164,13 +2189,30 @@
 as a multibranch, depending on the number of arguments supplied:
 
 @deffn {Builtin (m4)} ifelse (@var{comment})
[EMAIL PROTECTED] {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, 
@var{equal}, @w{opt @var{not-equal})}
[EMAIL PROTECTED] {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, 
@var{equal}, @dots{})
[EMAIL PROTECTED] {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, 
@var{equal}, @
+  @ovar{not-equal})
[EMAIL PROTECTED] {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, 
@var{equal-1}, @
+  @var{string-3}, @var{string-4}, @var{equal-2}, @dots{})
 Used with only one argument, the @code{ifelse} simply discards it and
-produces no output.  This is a common @code{m4} idiom for introducing a
+produces no output.
+
+If called with three or four arguments, @code{ifelse} expands into
[EMAIL PROTECTED], if @var{string-1} and @var{string-2} are equal (character
+for character), otherwise it expands to @var{not-equal}.  A final fifth
+argument is ignored, after triggering a warning.
+
+If called with six or more arguments, and @var{string-1} and
[EMAIL PROTECTED] are equal, @code{ifelse} expands into @var{equal-1},
+otherwise the first three arguments are discarded and the processing
+starts again.
+
+The macro @code{ifelse} is recognized only with parameters.
[EMAIL PROTECTED] deffn
+
+Using only one argument is a common @code{m4} idiom for introducing a
 block comment, as an alternative to repeatedly using @code{dnl}.  This
-special usage is recognized by GNU @code{m4}, so that in this case, the
-warning about missing arguments is never triggered.
+special usage is recognized by @acronym{GNU} @code{m4}, so that in this
+case, the warning about missing arguments is never triggered.
 
 @example
 ifelse(`some comments')
@@ -2180,43 +2222,64 @@
 @result{}
 @end example
 
-If called with three or four arguments, @code{ifelse} expands into
[EMAIL PROTECTED], if @var{string-1} and @var{string-2} are equal (character
-for character), otherwise it expands to @var{not-equal}.
+Using three or four arguments provides decision points.
 
 @example
 ifelse(`foo', `bar', `true')
 @result{}
 ifelse(`foo', `foo', `true')
 @result{}true
-ifelse(`foo', `bar', `true', `false')
[EMAIL PROTECTED]
-ifelse(`foo', `foo', `true', `false')
+define(`foo', `bar')
[EMAIL PROTECTED]
+ifelse(foo, `bar', `true', `false')
 @result{}true
+ifelse(foo, `foo', `true', `false')
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
+Notice how the first argument was used unquoted; it is common to compare
+the expansion of a macro with a string.  With this macro, you can now
+reproduce the behavior of many of the builtins, where the macro is
+recognized only with arguments.
+
[EMAIL PROTECTED]
+define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')')
[EMAIL PROTECTED]
+foo
[EMAIL PROTECTED]
+foo()
[EMAIL PROTECTED]:1
+foo(`a', `b', `c')
[EMAIL PROTECTED]:3
 @end example
 
 @cindex multibranches
 However, @code{ifelse} can take more than four arguments.  If given more
 than four arguments, @code{ifelse} works like a @code{case} or @code{switch}
 statement in traditional programming languages.  If @var{string-1} and
[EMAIL PROTECTED] are equal, @code{ifelse} expands into @var{equal}, otherwise
[EMAIL PROTECTED] are equal, @code{ifelse} expands into @var{equal-1}, otherwise
 the procedure is repeated with the first three arguments discarded.  This
 calls for an example:
 
 @example
+ifelse(`foo', `bar', `third', `gnu', `gnats')
[EMAIL PROTECTED]:stdin:1: Warning: ifelse: extra arguments ignored: 5 > 4
[EMAIL PROTECTED]
+ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth')
[EMAIL PROTECTED]
 ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh')
 @result{}seventh
+ifelse(`foo', `bar', `3', `gnu', `gnats', `6', `7', `8')
[EMAIL PROTECTED]:stdin:4: Warning: ifelse: extra arguments ignored: 8 > 7
[EMAIL PROTECTED]
 @end example
 
-The macro @code{ifelse} is recognized only with parameters.
[EMAIL PROTECTED] deffn
-
 Naturally, the normal case will be slightly more advanced than these
 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
@@ -2231,9 +2294,12 @@
 There is a builtin macro, @code{shift}, which can, among other things,
 be used for iterating through the actual arguments to a macro:
 
[EMAIL PROTECTED] {Builtin (m4)} shift (@dots{})
[EMAIL PROTECTED] takes any number of arguments, and expands to all but the 
first
-argument, separated by commas, with each argument quoted.
[EMAIL PROTECTED] {Builtin (m4)} shift (@var{arg1}, @dots{})
+Takes any number of arguments, and expands to all its arguments except
[EMAIL PROTECTED], separated by commas, with each argument quoted.
+
+The macro @code{shift} is recognized only with parameters.
[EMAIL PROTECTED] deffn
 
 @example
 shift
@@ -2243,10 +2309,14 @@
 shift(`foo', `bar', `baz')
 @result{}bar,baz
 @end example
+
+An example of the use of @code{shift} is this macro:
+
[EMAIL PROTECTED] Composite reverse (@dots{})
+Takes any number of arguments, and reverse their order.
 @end deffn
 
-An example of the use of @code{shift} is this macro, which reverses the
-order of its arguments:
+It is implemented as:
 
 @example
 define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'',
@@ -2261,14 +2331,66 @@
 @end example
 
 While not a very interesting macro, it does show how simple loops can be
-made with @code{shift}, @code{ifelse} and recursion.
+made with @code{shift}, @code{ifelse} and recursion.  It also shows
+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 quoting.  With @code{quote}, only one
+level of quoting is added, effectively removing whitespace after commas
+and turning the arguments into a string.  With @code{dquote}, 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
+
+Here is an implementation, along with an example usage.
+
[EMAIL PROTECTED] FIXME - these macros are worth reusing in other examples;
[EMAIL PROTECTED] factor them into examples/quote.m4.
[EMAIL PROTECTED]
+define(`quote', `ifelse(`$#', `0', `', ``$*'')')dnl
+define(`dquote', ``$@@'')dnl
+define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
+                             ```$1'',dquote_elt(shift($@@))')')dnl
+-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'-
+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.
+
[EMAIL PROTECTED] Forloop
[EMAIL PROTECTED] Iteration by counting
 
[EMAIL PROTECTED] forloops
[EMAIL PROTECTED] for loops
 @cindex loops, counting
 @cindex counting loops
-Here is an example of a loop macro that implements a simple forloop.  It
-can, for example, be used for simple counting:
+Here is an example of a loop macro that implements a simple for loop.
[EMAIL PROTECTED] FIXME - this section still needs some work done
+
[EMAIL PROTECTED] Composite forloop (@var{iterator}, @var{start}, @var{end}, 
@var{text})
+Takes the name in @var{iterator}, which must be a valid macro name, and
+successively assign it each integer value from @var{start} to @var{end},
+inclusive.  For each assignment to @var{iterator}, append @var{text} to
+the expansion of the @code{forloop}.  @var{text} may refer to
[EMAIL PROTECTED]  Any definition of @var{iterator} prior to this
+invocation is restored.
[EMAIL PROTECTED] deffn
 
+It can, for example, be used for simple counting:
+
[EMAIL PROTECTED] FIXME - include(`forloop.m4')
 @comment ignore
 @example
 forloop(`i', 1, 8, `i ')
@@ -2325,12 +2447,69 @@
 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.
 
[EMAIL PROTECTED] FIXME - it would be nice to introduce foreach here, and even
[EMAIL PROTECTED] give an example like this for finding defined macros that meet
[EMAIL PROTECTED] a certain pattern (see examples/foreach.m4):
[EMAIL PROTECTED] define(`quote', ``$@'')
[EMAIL PROTECTED] foreach(`macro', (quote(symbols)),
[EMAIL PROTECTED]         `regexp(macro, `.*_.*', ``\&',')')
[EMAIL PROTECTED] Foreach
[EMAIL PROTECTED] Iteration by list contents
+
[EMAIL PROTECTED] for each loops
[EMAIL PROTECTED] loops, list iteration
[EMAIL PROTECTED] iterating over lists
+Here is an example of a loop macro that implements list iteration.
[EMAIL PROTECTED] FIXME - this section still needs some work done
+
[EMAIL PROTECTED] Composite foreach (@var{iterator}, @var{paren-list}, 
@var{text})
+Takes the name in @var{iterator}, which must be a valid macro name, and
+successively assign it each value from @var{paren-list}.
[EMAIL PROTECTED] is a comma-separated list of elements surrounded by
+parentheses.  For each assignment to @var{iterator}, append @var{text}
+to the expansion of @code{foreach}.  @var{text} may refer to
[EMAIL PROTECTED]  Any definition of @var{iterator} prior to this
+invocation is restored.
[EMAIL PROTECTED] deffn
+
+As an example, this displays each word in a list inside of a sentence.
+
[EMAIL PROTECTED] FIXME - include(`foreach.m4')
[EMAIL PROTECTED] ignore
[EMAIL PROTECTED]
+foreach(`x', `(foo, bar, foobar)', `Word was: x
+')
[EMAIL PROTECTED] was: foo
[EMAIL PROTECTED] was: bar
[EMAIL PROTECTED] was: foobar
[EMAIL PROTECTED] example
+
+The implementation of the @code{foreach} macro is a bit more involved;
+it is a wrapper around two helper macros.  First, @code{_arg1} is needed
+to grab the first element of a list.  Second, @code{_foreach} implements
+the recursion, successively walking through the original list.
+
+Here is an actual implementation of @code{forloop}, followed by a
+demonstration of using it to filter out a list of symbols that contain
[EMAIL PROTECTED]
+
[EMAIL PROTECTED] FIXME - include(foreach.m4),include(quote.m4)
[EMAIL PROTECTED]
+define(`foreach', `pushdef(`$1')_foreach($@@)popdef(`$1')')dnl
+define(`_arg1', ``$1'')dnl
+define(`_foreach',
+       `ifelse($2, `()', ,
+               `define(`$1',
+                       `_arg1$2')$3`'_foreach(`$1', `(shift$2)',
+                                              `$3')')')dnl
+define(`dquote', ``$@@'')
[EMAIL PROTECTED]
+foreach(`macro', (dquote(symbols)), `regexp(macro, `.*if.*', ``\&',')')
[EMAIL PROTECTED],ifelse,shift,
[EMAIL PROTECTED] example
+
+The example had to use a helper @code{quote} to ensure that the output
+from @code{symbols} was double quoted; without it, the macro would have
+gone into an infinite loop thanks to macros being reinvoked during the
+rescanning.  Choosing @samp{()} as the list delimiters made this
+example rather awkward in terms of proper quoting.  (A different
+implementation can be acheived by changing @var{list} from a
+parenthesized list to a quoted list; try reimplementing @code{foreach}
+with these semantics yourself, then check @pxref{Answers}).
 
 @node Debugging
 @chapter How to debug macros and input
@@ -2534,7 +2713,7 @@
 * Changecom::                   Changing the comment delimiters
 * Changeresyntax::              Changing the regular expression syntax
 * Changesyntax::                Changing the lexical structure of the input
-* M4wrap::                      Saving input until end of input
+* M4wrap::                      Saving text until end of input
 @end menu
 
 @node Dnl
@@ -2630,7 +2809,7 @@
 the quoting mechanism.
 
 @node Changecom
[EMAIL PROTECTED] Changing comment delimiters
[EMAIL PROTECTED] Changing the comment delimiters
 
 @cindex changing comment delimiters
 @cindex comment delimiters, changing
@@ -3101,7 +3280,7 @@
 
 
 @node M4wrap
[EMAIL PROTECTED] Saving input
[EMAIL PROTECTED] Saving text until end of input
 
 @cindex saving input
 @cindex input, saving
@@ -3473,7 +3652,7 @@
 should try to see if you can find it and correct it.   @xref{Answers}.)
 
 @node Modules
[EMAIL PROTECTED] Runtime Dynamic Modules
[EMAIL PROTECTED] Extending M4 with dynamic runtime modules
 
 @cindex modules
 @sc{gnu} m4-1.4.x had a monolithic architecture.  All of its
@@ -3979,7 +4158,7 @@
 
 
 @node Format
[EMAIL PROTECTED] Formatted output
[EMAIL PROTECTED] Formatting strings (printf-like)
 
 @cindex formatted output
 @cindex output, formatted
@@ -4006,7 +4185,7 @@
 @result{}5000
 @end example
 
-Using the @code{forloop} macro defined in @xref{Loops}, this
+Using the @code{forloop} macro defined in @xref{Forloop}, this
 example shows how @code{format} can be used to produce tabular output.
 
 @comment ignore
@@ -4074,7 +4253,7 @@
 @end deffn
 
 @node Eval
[EMAIL PROTECTED] Evaluating integer or rational expressions
[EMAIL PROTECTED] Evaluating integer expressions
 
 @cindex integer expression evaluation
 @cindex evaluation, of integer expressions
@@ -4213,7 +4392,7 @@
 @end deffn
 
 @node Shell commands
[EMAIL PROTECTED] Running shell commands
[EMAIL PROTECTED] Macros for running shell commands
 
 @cindex executing shell commands
 @cindex running shell commands
@@ -4227,8 +4406,8 @@
 * Platform macros::             Determining the platform
 * Syscmd::                      Executing simple commands
 * Esyscmd::                     Reading the output of commands
-* Sysval::                      Exit codes
-* Maketemp::                    Making names for temporary files
+* Sysval::                      Exit status
+* Maketemp::                    Making temporary files
 @end menu
 
 @node Platform macros
@@ -4299,7 +4478,7 @@
 @end deffn
 
 @node Sysval
[EMAIL PROTECTED] Exit codes
[EMAIL PROTECTED] Exit status
 
 @cindex exit code from shell commands
 @cindex shell commands, exit code from
@@ -4323,7 +4502,7 @@
 @end example
 
 @node Maketemp
[EMAIL PROTECTED] Making names for temporary files
[EMAIL PROTECTED] Making temporary files
 
 @cindex temporary file names
 @cindex files, names of temporary
@@ -4357,7 +4536,7 @@
 @menu
 * Errprint::                    Printing error messages
 * Location::                    Printing current location
-* M4exit::                      Exiting from m4
+* M4exit::                      Exiting from @code{m4}
 * Syncoutput::                  Turning on and off sync lines
 @end menu
 
@@ -4433,7 +4612,7 @@
 (@pxref{M4wrap}) is not reread.
 
 @node Syncoutput
[EMAIL PROTECTED] Turning sync lines on and off within @code{m4}
[EMAIL PROTECTED] Turning on and off sync lines
 
 @cindex Toggling sync lines within @code{m4}
 @deffn {Builtin (gnu)} syncoutput (@var{truth})
@@ -4661,12 +4840,13 @@
 is made to summarize these here.
 
 @menu
-* Extensions::                  Extensions in GNU m4
+* Extensions::                  Extensions in @acronym{GNU} M4
 * Incompatibilities::           Other incompatibilities
+* Experiments::                 Experimental features in @acronym{GNU} M4
 @end menu
 
 @node Extensions
[EMAIL PROTECTED] Extensions in GNU @code{m4}
[EMAIL PROTECTED] Extensions in @acronym{GNU} M4
 
 @cindex GNU extensions
 @cindex @acronym{POSIX}
@@ -4835,7 +5015,7 @@
 
 
 @node  Experiments
[EMAIL PROTECTED] Experimental features in GNU M4
[EMAIL PROTECTED] Experimental features in @acronym{GNU} M4
 
 Certain features of GNU @code{m4} are experimental.
 
@@ -4877,6 +5057,82 @@
 Some of the examples in this manuals are buggy.  Correctly working
 macros are presented here.
 
+The @code{foreach} macro (@pxref{Foreach}) as presented required the
+user to use parentheses to delineate the list.  This approach is
+quadratic, because the entire list is propagated through each recursion,
+with additional invocations of the shift macro added on each iteration:
+
[EMAIL PROTECTED] FIXME - include(foreach.m4),include(quote.m4)
[EMAIL PROTECTED] options: -d-V
[EMAIL PROTECTED]
+define(`foreach', `pushdef(`$1')_foreach($@@)popdef(`$1')')dnl
+define(`_arg1', ``$1'')dnl
+define(`_foreach',
+       `ifelse($2, `()', ,
+               `define(`$1',
+                       `_arg1$2')$3`'_foreach(`$1', `(shift$2)',
+                                              `$3')')')dnl
+define(`dquote', ``$@'')
[EMAIL PROTECTED]
+foreach(`macro', (dquote(symbols)), `regexp(macro, `shift', `\&')')
[EMAIL PROTECTED]
+traceon(`shift')
[EMAIL PROTECTED]
+foreach(`a', `(1,2,3)', `a
+')
[EMAIL PROTECTED]
[EMAIL PROTECTED]: -2- shift
[EMAIL PROTECTED]: -2- shift
[EMAIL PROTECTED]
[EMAIL PROTECTED]: -3- shift
[EMAIL PROTECTED]: -2- shift
[EMAIL PROTECTED]: -3- shift
[EMAIL PROTECTED]: -2- shift
[EMAIL PROTECTED]
[EMAIL PROTECTED]: -4- shift
[EMAIL PROTECTED]: -3- shift
[EMAIL PROTECTED]: -2- shift
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
+An alternative implementation takes a quoted list, with semantics that
+the list is expanded once before iteration, and has the benefit that
+each iteration operates on a shorter list, giving linear performance on
+long lists.  Another way of viewing these semantics is that the
+outermost quotes delineates the list, then each element of the list must
+be quoted as though the list delimiters were not present.  Notice the
+difference when iterating over @code{symbols}; we must use
[EMAIL PROTECTED] instead of @code{dquote} to get the necessary quoting.
+
[EMAIL PROTECTED] FIXME - include(foreach.m4),include(quote.m4)
[EMAIL PROTECTED] options: -d-V
[EMAIL PROTECTED]
+define(`foreach', `pushdef(`$1')_foreach($@@)popdef(`$1')')dnl
+define(`_arg1', ``$1'')dnl
+define(`quote', `ifelse(`$#', `0', `', ``$*'')')dnl
+define(`dquote', ``$@@'')dnl
+define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
+                             ```$1'',dquote_elt(shift($@@))')')dnl
+define(`_rest', `ifelse(`$#', `1', , `dquote(shift($@@))')')dnl
+define(`_foreach',
+       `ifelse(quote($2), , ,
+               `define(`$1',
+                       `_arg1($2)')$3`'_foreach(`$1', _rest($2),
+                                                `$3')')')dnl
+foreach(`macro', `dquote_elt(symbols)', `regexp(macro, `shift', `\&')')
[EMAIL PROTECTED]
+traceon(`shift')
[EMAIL PROTECTED]
+foreach(`a', ``1',`2',`3'', `a
+')
[EMAIL PROTECTED]
[EMAIL PROTECTED]: -3- shift
[EMAIL PROTECTED]
[EMAIL PROTECTED]: -3- shift
[EMAIL PROTECTED]
[EMAIL PROTECTED]
[EMAIL PROTECTED] example
+
 The @code{cleardivert} macro (@pxref{Cleardiv}) cannot, as it stands, be
 called without arguments to clear all pending diversions.  A macro that
 achieves that as well is:
@@ -4895,7 +5151,7 @@
 @c ========================================================== Appendices
 
 @node Copying This Manual
[EMAIL PROTECTED] Copying This Manual
[EMAIL PROTECTED] How to make copies of this manual
 @cindex License
 
 @menu
@@ -4905,20 +5161,20 @@
 @include fdl.texi
 
 @node Indices
[EMAIL PROTECTED] Indices
[EMAIL PROTECTED] Indices of concepts and macros
 
 @menu
 * Concept index::               Index for many concepts
-* Macro index::                 Index for all m4 macros
+* Macro index::                 Index for all @code{m4} macros
 @end menu
 
 @node Concept index
[EMAIL PROTECTED] Concept index
[EMAIL PROTECTED] Index for many concepts
 
 @printindex cp
 
 @node Macro index
[EMAIL PROTECTED] Macro index
[EMAIL PROTECTED] Index for all @code{m4} macros
 
 References are exclusively to the places where a builtin is introduced
 the first time.


Reply via email to