[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Changes to m4/doc/m4.texinfo,v
From: |
Eric Blake |
Subject: |
Changes to m4/doc/m4.texinfo,v |
Date: |
Tue, 05 Sep 2006 13:25:25 +0000 |
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
address@hidden Names
address@hidden 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
address@hidden Quoted strings
address@hidden 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
address@hidden Comments
address@hidden 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
address@hidden Other tokens
address@hidden 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
address@hidden Input Processing
address@hidden 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
address@hidden Regular Expression Syntax
address@hidden 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.
address@hidden status: 1
@example
define(
^D
address@hidden:stdin:1: ERROR: end of file in argument list
address@hidden:stdin:1: end of file in argument list
@end example
@node Quoting Arguments
address@hidden Quoting macro arguments
address@hidden 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')
address@hidden
define(defn(`divnum'), `cannot redefine a builtin token')
address@hidden:stdin:1: Warning: define: invalid macro name ignored
address@hidden: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
address@hidden 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.
+
address@hidden
+define(`f', `1')
address@hidden
+f(define(`f', `2'))
address@hidden
+indir(`f', define(`f', `3'))
address@hidden
+indir(`f', undefine(`f'))
address@hidden:stdin:4: Warning: indir: undefined macro `f'
address@hidden
address@hidden 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
address@hidden Testing macro definitions
address@hidden 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
address@hidden Comparing strings
address@hidden 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})
address@hidden {Builtin (m4)} ifelse (@var{string-1}, @var{string-2},
@var{equal}, @w{opt @var{not-equal})}
address@hidden {Builtin (m4)} ifelse (@var{string-1}, @var{string-2},
@var{equal}, @dots{})
address@hidden {Builtin (m4)} ifelse (@var{string-1}, @var{string-2},
@var{equal}, @
+ @ovar{not-equal})
address@hidden {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
address@hidden, 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
address@hidden 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.
address@hidden 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
address@hidden, 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')
address@hidden
-ifelse(`foo', `foo', `true', `false')
+define(`foo', `bar')
address@hidden
+ifelse(foo, `bar', `true', `false')
@result{}true
+ifelse(foo, `foo', `true', `false')
address@hidden
address@hidden 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.
+
address@hidden
+define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')')
address@hidden
+foo
address@hidden
+foo()
address@hidden:1
+foo(`a', `b', `c')
address@hidden: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
address@hidden are equal, @code{ifelse} expands into @var{equal}, otherwise
address@hidden 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')
address@hidden:stdin:1: Warning: ifelse: extra arguments ignored: 5 > 4
address@hidden
+ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth')
address@hidden
ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh')
@result{}seventh
+ifelse(`foo', `bar', `3', `gnu', `gnats', `6', `7', `8')
address@hidden:stdin:4: Warning: ifelse: extra arguments ignored: 8 > 7
address@hidden
@end example
-The macro @code{ifelse} is recognized only with parameters.
address@hidden 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.
address@hidden Loops
address@hidden Loops and recursion
address@hidden Shift
address@hidden 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:
address@hidden {Builtin (m4)} shift (@dots{})
address@hidden takes any number of arguments, and expands to all but the first
-argument, separated by commas, with each argument quoted.
address@hidden {Builtin (m4)} shift (@var{arg1}, @dots{})
+Takes any number of arguments, and expands to all its arguments except
address@hidden, separated by commas, with each argument quoted.
+
+The macro @code{shift} is recognized only with parameters.
address@hidden 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:
+
address@hidden 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:
+
address@hidden Composite quote (@dots{})
address@hidden Composite dquote (@dots{})
address@hidden 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.
address@hidden deffn
+
+Here is an implementation, along with an example usage.
+
address@hidden FIXME - these macros are worth reusing in other examples;
address@hidden factor them into examples/quote.m4.
address@hidden
+define(`quote', `ifelse(`$#', `0', `', ``$*'')')dnl
+define(`dquote', ``$@@'')dnl
+define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
+ ```$1'',dquote_elt(shift($@@))')')dnl
+-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'-
+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.
+
address@hidden Forloop
address@hidden Iteration by counting
address@hidden forloops
address@hidden 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.
address@hidden FIXME - this section still needs some work done
+
address@hidden 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
address@hidden Any definition of @var{iterator} prior to this
+invocation is restored.
address@hidden deffn
+It can, for example, be used for simple counting:
+
address@hidden 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.
address@hidden FIXME - it would be nice to introduce foreach here, and even
address@hidden give an example like this for finding defined macros that meet
address@hidden a certain pattern (see examples/foreach.m4):
address@hidden define(`quote', ``$@'')
address@hidden foreach(`macro', (quote(symbols)),
address@hidden `regexp(macro, `.*_.*', ``\&',')')
address@hidden Foreach
address@hidden Iteration by list contents
+
address@hidden for each loops
address@hidden loops, list iteration
address@hidden iterating over lists
+Here is an example of a loop macro that implements list iteration.
address@hidden FIXME - this section still needs some work done
+
address@hidden 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}.
address@hidden 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
address@hidden Any definition of @var{iterator} prior to this
+invocation is restored.
address@hidden deffn
+
+As an example, this displays each word in a list inside of a sentence.
+
address@hidden FIXME - include(`foreach.m4')
address@hidden ignore
address@hidden
+foreach(`x', `(foo, bar, foobar)', `Word was: x
+')
address@hidden was: foo
address@hidden was: bar
address@hidden was: foobar
address@hidden 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
address@hidden
+
address@hidden FIXME - include(foreach.m4),include(quote.m4)
address@hidden
+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', ``$@@'')
address@hidden
+foreach(`macro', (dquote(symbols)), `regexp(macro, `.*if.*', ``\&',')')
address@hidden,ifelse,shift,
address@hidden 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
address@hidden Changing comment delimiters
address@hidden Changing the comment delimiters
@cindex changing comment delimiters
@cindex comment delimiters, changing
@@ -3101,7 +3280,7 @@
@node M4wrap
address@hidden Saving input
address@hidden 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
address@hidden Runtime Dynamic Modules
address@hidden 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
address@hidden Formatted output
address@hidden 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
address@hidden Evaluating integer or rational expressions
address@hidden Evaluating integer expressions
@cindex integer expression evaluation
@cindex evaluation, of integer expressions
@@ -4213,7 +4392,7 @@
@end deffn
@node Shell commands
address@hidden Running shell commands
address@hidden 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
address@hidden Exit codes
address@hidden Exit status
@cindex exit code from shell commands
@cindex shell commands, exit code from
@@ -4323,7 +4502,7 @@
@end example
@node Maketemp
address@hidden Making names for temporary files
address@hidden 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
address@hidden Turning sync lines on and off within @code{m4}
address@hidden 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
address@hidden Extensions in GNU @code{m4}
address@hidden Extensions in @acronym{GNU} M4
@cindex GNU extensions
@cindex @acronym{POSIX}
@@ -4835,7 +5015,7 @@
@node Experiments
address@hidden Experimental features in GNU M4
address@hidden 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:
+
address@hidden FIXME - include(foreach.m4),include(quote.m4)
address@hidden options: -d-V
address@hidden
+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', ``$@'')
address@hidden
+foreach(`macro', (dquote(symbols)), `regexp(macro, `shift', `\&')')
address@hidden
+traceon(`shift')
address@hidden
+foreach(`a', `(1,2,3)', `a
+')
address@hidden
address@hidden: -2- shift
address@hidden: -2- shift
address@hidden
address@hidden: -3- shift
address@hidden: -2- shift
address@hidden: -3- shift
address@hidden: -2- shift
address@hidden
address@hidden: -4- shift
address@hidden: -3- shift
address@hidden: -2- shift
address@hidden
address@hidden 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
address@hidden instead of @code{dquote} to get the necessary quoting.
+
address@hidden FIXME - include(foreach.m4),include(quote.m4)
address@hidden options: -d-V
address@hidden
+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', `\&')')
address@hidden
+traceon(`shift')
address@hidden
+foreach(`a', ``1',`2',`3'', `a
+')
address@hidden
address@hidden: -3- shift
address@hidden
address@hidden: -3- shift
address@hidden
address@hidden
address@hidden 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
address@hidden Copying This Manual
address@hidden How to make copies of this manual
@cindex License
@menu
@@ -4905,20 +5161,20 @@
@include fdl.texi
@node Indices
address@hidden Indices
address@hidden 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
address@hidden Concept index
address@hidden Index for many concepts
@printindex cp
@node Macro index
address@hidden Macro index
address@hidden Index for all @code{m4} macros
References are exclusively to the places where a builtin is introduced
the first time.
- Changes to m4/doc/m4.texinfo,v,
Eric Blake <=
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/05
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/05
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/07
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/14
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/18
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/19
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/19
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/20
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/20
- Changes to m4/doc/m4.texinfo,v, Eric Blake, 2006/09/21