This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU M4 source repository".
http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=86f05e746830963af686d61d746a68205abeadf8 The branch, branch-1_4 has been updated via 86f05e746830963af686d61d746a68205abeadf8 (commit) from 08d5b5e080e2ff7e6808cd32956031e03a467095 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 86f05e746830963af686d61d746a68205abeadf8 Author: Eric Blake <[EMAIL PROTECTED]> Date: Wed Oct 31 08:50:30 2007 -0600 Test more corner cases. * doc/m4.texinfo (Changecom, Pseudo Arguments): Beef up tests. (Improved foreach): Document alternate foreachq style. * examples/foreachq3.m4: New file. * examples/loop.m4: New file. * examples/Makefile.am (EXTRA_DIST): Distribute them. Signed-off-by: Eric Blake <[EMAIL PROTECTED]> ----------------------------------------------------------------------- Summary of changes: ChangeLog | 9 +++++ doc/m4.texinfo | 85 +++++++++++++++++++++++++++++++++++++++++++----- examples/Makefile.am | 2 + examples/foreachq3.m4 | 10 ++++++ examples/loop.m4 | 17 ++++++++++ 5 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 examples/foreachq3.m4 create mode 100644 examples/loop.m4 diff --git a/ChangeLog b/ChangeLog index 737a6ec..a25c84d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-10-31 Eric Blake <[EMAIL PROTECTED]> + + Test more corner cases. + * doc/m4.texinfo (Changecom, Pseudo Arguments): Beef up tests. + (Improved foreach): Document alternate foreachq style. + * examples/foreachq3.m4: New file. + * examples/loop.m4: New file. + * examples/Makefile.am (EXTRA_DIST): Distribute them. + 2007-10-28 Eric Blake <[EMAIL PROTECTED]> More test coverage for autoconf usage patterns. diff --git a/doc/m4.texinfo b/doc/m4.texinfo index d7c8140..42c5438 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -1942,11 +1942,17 @@ foo) @comment levels. @example -define(`echo', `$@')dnl +define(`echo', `$@@')dnl len((echo(`01234567890123456789', `01234567890123456789')echo(`98765432109876543210', `98765432109876543210'))) @result{}84 +define(`argn', `$#')dnl +define(`echo1', `-$@@-')define(`echo2', `,$@@,')dnl +echo1(`1', `2', `3') argn(echo1(`1', `2', `3')) [EMAIL PROTECTED],2,3- 3 +echo2(`1', `2', `3') argn(echo2(`1', `2', `3')) [EMAIL PROTECTED],1,2,3, 5 @end example @end ignore @@ -3801,26 +3807,32 @@ implementations, it is a good idea to avoid @samp{(}, @samp{,}, and @samp{)} as the first character in @var{start}. @example -define(`echo', `$#:$@@:') +define(`echo', `$#:$*:$@@:') @result{} define(`hi', `HI') @result{} changecom(`(',`)') @result{} echo(hi) [EMAIL PROTECTED]::(hi) [EMAIL PROTECTED]:::(hi) changecom @result{} changecom(`((', `))') @result{} echo(hi) [EMAIL PROTECTED]:HI: [EMAIL PROTECTED]:HI:HI: echo((hi)) [EMAIL PROTECTED]::((hi)) [EMAIL PROTECTED]:::((hi)) changecom(`,', `)') @result{} echo(hi,hi)bye) [EMAIL PROTECTED]:HI,hi)bye: [EMAIL PROTECTED]:HI,hi)bye:HI,hi)bye: +changecom [EMAIL PROTECTED] +echo(hi,`,`'hi',hi) [EMAIL PROTECTED]:HI,,HI,HI:HI,,`'hi,HI: +echo(hi,`,`'hi',hi`'changecom(`,,', `hi')) [EMAIL PROTECTED]:HI,,`'hi,HI:HI,,`'hi,HI: @end example It is an error if the end of file occurs within a comment. @@ -6803,7 +6815,60 @@ Contrast the use of @[EMAIL PROTECTED], which quotes the first list element, with @[EMAIL PROTECTED] of the earlier implementation that returned the first list element directly. -For a different approach, the improved version of @code{foreach}, +The astute m4 programmer might notice that the solution above still uses +more memory, and thus more time, than strictly necessary. Note that [EMAIL PROTECTED], which contains an arbitrarily long quoted list, is expanded +and rescanned three times per iteration of @code{_foreachq}. +Furthermore, every iteration of the algorithm effectively unboxes then +reboxes the list, which costs a couple of macro invocations. It is +possible to rewrite the algorithm for a bit more speed by swapping the +order of the arguments to @code{_foreachq} in order to operate on an +unboxed list in the first place, and by using the fixed-length @samp{$#} +instead of an arbitrary length list as the key to end recursion. This +alternative approach is available as [EMAIL PROTECTED]@value{VERSION}/@/examples/@/foreach3.m4}: + [EMAIL PROTECTED] +$ @kbd{m4 -I examples} +include(`foreachq3.m4') [EMAIL PROTECTED] +undivert(`foreachq3.m4')dnl [EMAIL PROTECTED](`-1') [EMAIL PROTECTED] foreachq(x, `item_1, item_2, ..., item_n', stmt) [EMAIL PROTECTED] quoted list, alternate improved version [EMAIL PROTECTED](`foreachq', [EMAIL PROTECTED](`$1')_$0(`$1', `$3'ifelse(`$2', `', `', [EMAIL PROTECTED] `, $2'))popdef(`$1')') [EMAIL PROTECTED](`_foreachq', `ifelse(`$#', `2', `', [EMAIL PROTECTED] `define(`$1', `$3')$2`'$0(`$1', `$2'ifelse(`$#', `3', `', [EMAIL PROTECTED] `, shift(shift(shift($@@)))'))')') [EMAIL PROTECTED]'dnl +traceon(`shift')debugmode(`aq') [EMAIL PROTECTED] +foreachq(`x', ``1', `2', `3', `4'', `x +')dnl [EMAIL PROTECTED] [EMAIL PROTECTED]: -4- shift(`x', `x [EMAIL PROTECTED]', `1', `2', `3', `4') [EMAIL PROTECTED]: -3- shift(`x [EMAIL PROTECTED]', `1', `2', `3', `4') [EMAIL PROTECTED]: -2- shift(`1', `2', `3', `4') [EMAIL PROTECTED] [EMAIL PROTECTED]: -4- shift(`x', `x [EMAIL PROTECTED]', `2', `3', `4') [EMAIL PROTECTED]: -3- shift(`x [EMAIL PROTECTED]', `2', `3', `4') [EMAIL PROTECTED]: -2- shift(`2', `3', `4') [EMAIL PROTECTED] [EMAIL PROTECTED]: -4- shift(`x', `x [EMAIL PROTECTED]', `3', `4') [EMAIL PROTECTED]: -3- shift(`x [EMAIL PROTECTED]', `3', `4') [EMAIL PROTECTED]: -2- shift(`3', `4') [EMAIL PROTECTED] [EMAIL PROTECTED] example + +For yet another approach, the improved version of @code{foreach}, available in @[EMAIL PROTECTED]/@/examples/@/foreach2.m4}, simply overquotes the arguments to @[EMAIL PROTECTED] to begin with, using @code{dquote_elt}. Then @[EMAIL PROTECTED] can just use @@ -6846,9 +6911,11 @@ In summary, recursion over list elements is trickier than it appeared at first glance, but provides a powerful idiom within @code{m4} processing. As a final demonstration, both list styles are now able to handle several scenarios that would wreak havoc on the original -implementations. This points out one other difference between the two +implementations. This points out one other difference between the list styles. @code{foreach} evaluates unquoted list elements only once, -in preparation for calling @[EMAIL PROTECTED] But @code{foreachq} +in preparation for calling @[EMAIL PROTECTED], similary for [EMAIL PROTECTED] as provided by @file{foreachq3.m4}. But [EMAIL PROTECTED], as provided by @file{foreachq2.m4}, evaluates unquoted list elements twice while visiting the first list element, once in @[EMAIL PROTECTED] and once in @[EMAIL PROTECTED] When deciding which list style to use, one must take into account whether diff --git a/examples/Makefile.am b/examples/Makefile.am index e7672f9..b1ef68a 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -33,6 +33,7 @@ foreach.m4 \ foreach2.m4 \ foreachq.m4 \ foreachq2.m4 \ +foreachq3.m4 \ forloop.m4 \ forloop2.m4 \ fstab.m4 \ @@ -41,6 +42,7 @@ incl-test.m4 \ incl.m4 \ include.m4 \ indir.m4 \ +loop.m4 \ misc.m4 \ multiquotes.m4 \ patsubst.m4 \ diff --git a/examples/foreachq3.m4 b/examples/foreachq3.m4 new file mode 100644 index 0000000..beab455 --- /dev/null +++ b/examples/foreachq3.m4 @@ -0,0 +1,10 @@ +divert(`-1') +# foreachq(x, `item_1, item_2, ..., item_n', stmt) +# quoted list, alternate improved version +define(`foreachq', +`pushdef(`$1')_$0(`$1', `$3'ifelse(`$2', `', `', + `, $2'))popdef(`$1')') +define(`_foreachq', `ifelse(`$#', `2', `', + `define(`$1', `$3')$2`'$0(`$1', `$2'ifelse(`$#', `3', `', + `, shift(shift(shift($@)))'))')') +divert`'dnl diff --git a/examples/loop.m4 b/examples/loop.m4 new file mode 100644 index 0000000..31761c9 --- /dev/null +++ b/examples/loop.m4 @@ -0,0 +1,17 @@ +dnl Stress test for recursion algorithms. Usage: +dnl m4 -Ipath/to/examples [-Doptions] loop.m4 +dnl Options include: +dnl -Dalt - test with foreachq3 instead of foreachq2 +dnl -Dlimit=<num> - set upper limit of sequence to <num>, default 1000 +dnl -Dverbose - print the sequence to the screen, rather than discarding +dnl -Ddebug[=<code>] - execute <code> after forloop but before foreach +dnl -Dsleep=<num> - sleep for <num> seconds before exit, to allow time +dnl to examine peak process memory usage +include(`forloop2.m4')dnl +include(`quote.m4')dnl +include(ifdef(`alt', ``foreachq3.m4'', ``foreachq2.m4''))dnl +ifdef(`limit', `', `define(`limit', `1000')')dnl +ifdef(`verbose', `', `divert(`-1')')dnl +ifdef(`debug', `', `define(`debug')')dnl +foreachq(`i', dquote(1forloop(`i', `2', limit, `,i'))debug, ` i') +ifdef(`sleep',`syscmd(`echo done>/dev/tty;sleep 'sleep)')dnl hooks/post-receive -- GNU M4 source repository
