another regression test
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.patches |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 While working on porting stage 16 to head, I noticed that I wasn't really exercising recursive code with multi-character quoting. Ultimately, the speedup for linear speed on recursion only applies to single-character quoting (because with multi-character quoting, the parser can't bypass checking arguments, in case characters are concatenated together to form a quote delimiter), but I at least wanted to ensure it doesn't break with all the optimizations being added for single-character quotes. And in the process of adding that test, I had a hard time using the examples/forloop2.m4 file as is once I translated it to use different quoting, so I adjusted the example and added some documentation why. This patch applies to both the branch and head. - -- Don't work too hard, make some time for fun as well! Eric Blake [email protected] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFHt2Nt84KuGfSFAYARAsYPAKDAzuba1VfMq9gwyIB3Yllft0A+mQCeLagz rkGq4h8kfnJ79IPgS9Mu3DA= =NKMJ -----END PGP SIGNATURE----- _______________________________________________ M4-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/m4-patches
m4.patch319
(text/plain, 7.7 KB)
From 702a3fe3e8a61c0d4c6da09221559deeff43fabb Mon Sep 17 00:00:00 2001 From: Eric Blake <[email protected]> Date: Sat, 16 Feb 2008 14:39:41 -0700 Subject: [PATCH] Add regression test for multi-character quote recursion. * examples/foreach2.m4: Use $0 rather than spelling out name. * examples/foreachq2.m4: Likewise. * examples/forloop2.m4: Likewise. * examples/hanoi.m4: Likewise. * examples/trace.m4: Likewise. * doc/m4.texinfo (Improved forloop): Document advantage of $0. (Improved foreach): Adjust dump from file. Signed-off-by: Eric Blake <[email protected]> --- ChangeLog | 9 +++++++++ doc/m4.texinfo | 48 +++++++++++++++++++++++++++++++++++++++++++++--- examples/foreach2.m4 | 2 +- examples/foreachq2.m4 | 2 +- examples/forloop2.m4 | 2 +- examples/hanoi.m4 | 4 ++-- examples/trace.m4 | 4 ++-- 7 files changed, 61 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0baa3c1..76fcac3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2008-02-16 Eric Blake <[email protected]> + Add regression test for multi-character quote recursion. + * examples/foreach2.m4: Use $0 rather than spelling out name. + * examples/foreachq2.m4: Likewise. + * examples/forloop2.m4: Likewise. + * examples/hanoi.m4: Likewise. + * examples/trace.m4: Likewise. + * doc/m4.texinfo (Improved forloop): Document advantage of $0. + (Improved foreach): Adjust dump from file. + Stage 15: return argv refs back to collect_arguments. Collect an entire $@ reference at once rather than one argument at a time, outside of quotes (but inside quotes, $@ is still diff --git a/doc/m4.texinfo b/doc/m4.texinfo index 32cb0a9..6172277 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -6987,7 +6987,7 @@ undivert(`forloop2.m4')dnl @result{}# performs sanity check that FROM is larger than TO @result{}# allows complex numerical expressions in TO and FROM @result{}define(`forloop', `ifelse(eval(`($3) >= ($2)'), `1', -@result{} `pushdef(`$1', eval(`$2'))_forloop(`$1', +@result{} `pushdef(`$1', eval(`$2'))_$0(`$1', @result{} eval(`$3'), `$4')popdef(`$1')')') @result{}define(`_forloop', @result{} `$3`'ifelse(indir(`$1'), `$2', `', @@ -7006,6 +7006,48 @@ forloop(`i', `a', `b', `non-numeric bounds') @result{} @end example +One other change to notice is that the improved version used @samp{_$0} +rather than @samp{_foreach} to invoke the helper routine. In general, +this is a good practice to follow, because then the set of macros can be +uniformly transformed. The following example shows a transformation +that doubles the current quoting and appends a suffix @samp{2} to each +transformed macro. If @code{foreach} refers to the literal +@samp{_foreach}, then @code{foreach2} invokes @code{_foreach} instead of +the intended @code{_foreach2}, and the mixing of quoting paradigms leads +to an infinite recursion loop in this example. + +@comment options: -L9 +@comment status: 1 +@comment examples +@example +$ @kbd{m4 -d -L 9 -I examples} +define(`arg1', `$1')include(`forloop2.m4')include(`quote.m4') +@result{} +define(`double', `define(`$1'`2', + arg1(patsubst(dquote(defn(`$1')), `[`']', `\&\&')))') +@result{} +double(`forloop')double(`_forloop')defn(`forloop2') +@result{}ifelse(eval(``($3) >= ($2)''), ``1'', +@result{} ``pushdef(``$1'', eval(``$2''))_$0(``$1'', +@result{} eval(``$3''), ``$4'')popdef(``$1'')'') +forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)') +@result{} +changequote(`[', `]')changequote([``], ['']) +@result{} +forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'') +@result{} +changequote`'include(`forloop.m4') +@result{} +double(`forloop')double(`_forloop')defn(`forloop2') +@result{}pushdef(``$1'', ``$2'')_forloop($@@)popdef(``$1'') +forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)') +@result{} +changequote(`[', `]')changequote([``], ['']) +@result{} +forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'') +@error{}m4:stdin:12: recursion limit of 9 exceeded, use -L<N> to change it +@end 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 @@ -7068,7 +7110,7 @@ undivert(`foreachq2.m4')dnl @result{}divert(`-1') @result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt) @result{}# quoted list, improved version -@result{}define(`foreachq', `pushdef(`$1')_foreachq($@@)popdef(`$1')') +@result{}define(`foreachq', `pushdef(`$1')_$0($@@)popdef(`$1')') @result{}define(`_arg1q', ``$1'') @result{}define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@@))')') @result{}define(`_foreachq', `ifelse(`$2', `', `', @@ -7163,7 +7205,7 @@ undivert(`foreach2.m4')dnl @result{}divert(`-1') @result{}# foreach(x, (item_1, item_2, ..., item_n), stmt) @result{}# parenthesized list, improved version -@result{}define(`foreach', `pushdef(`$1')_foreach(`$1', +@result{}define(`foreach', `pushdef(`$1')_$0(`$1', @result{} (dquote(dquote_elt$2)), `$3')popdef(`$1')') @result{}define(`_arg1', `$1') @result{}define(`_foreach', `ifelse(`$2', `(`')', `', diff --git a/examples/foreach2.m4 b/examples/foreach2.m4 index 4acf0c2..74d00fb 100644 --- a/examples/foreach2.m4 +++ b/examples/foreach2.m4 @@ -2,7 +2,7 @@ include(`quote.m4')dnl divert(`-1') # foreach(x, (item_1, item_2, ..., item_n), stmt) # parenthesized list, improved version -define(`foreach', `pushdef(`$1')_foreach(`$1', +define(`foreach', `pushdef(`$1')_$0(`$1', (dquote(dquote_elt$2)), `$3')popdef(`$1')') define(`_arg1', `$1') define(`_foreach', `ifelse(`$2', `(`')', `', diff --git a/examples/foreachq2.m4 b/examples/foreachq2.m4 index 345ddfe..f57d3ed 100644 --- a/examples/foreachq2.m4 +++ b/examples/foreachq2.m4 @@ -2,7 +2,7 @@ include(`quote.m4')dnl divert(`-1') # foreachq(x, `item_1, item_2, ..., item_n', stmt) # quoted list, improved version -define(`foreachq', `pushdef(`$1')_foreachq($@)popdef(`$1')') +define(`foreachq', `pushdef(`$1')_$0($@)popdef(`$1')') define(`_arg1q', ``$1'') define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@))')') define(`_foreachq', `ifelse(`$2', `', `', diff --git a/examples/forloop2.m4 b/examples/forloop2.m4 index f1bdf0e..41e0e16 100644 --- a/examples/forloop2.m4 +++ b/examples/forloop2.m4 @@ -4,7 +4,7 @@ divert(`-1') # performs sanity check that FROM is larger than TO # allows complex numerical expressions in TO and FROM define(`forloop', `ifelse(eval(`($3) >= ($2)'), `1', - `pushdef(`$1', eval(`$2'))_forloop(`$1', + `pushdef(`$1', eval(`$2'))_$0(`$1', eval(`$3'), `$4')popdef(`$1')')') define(`_forloop', `$3`'ifelse(indir(`$1'), `$2', `', diff --git a/examples/hanoi.m4 b/examples/hanoi.m4 index c4a80fc..d290866 100644 --- a/examples/hanoi.m4 +++ b/examples/hanoi.m4 @@ -6,10 +6,10 @@ define(`move', `Move one disk from `$1' to `$2'. # _hanoi (cnt, from, to, aux) define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') +`$0(decr($1), $2, $4, $3)move($2, $3)$0(decr($1), $4, $3, $2)')') # hanoi (cnt) -define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') +define(`hanoi', `_$0(`$1', source, destination, auxilliary)') # traceon(`move', `_hanoi', `decr') divert`'dnl diff --git a/examples/trace.m4 b/examples/trace.m4 index a79dbcd..92ce981 100644 --- a/examples/trace.m4 +++ b/examples/trace.m4 @@ -6,10 +6,10 @@ define(`move', `Move one disk from `$1' to `$2'. # _hanoi (cnt, from, to, aux) define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') +`$0(decr($1), $2, $4, $3)move($2, $3)$0(decr($1), $4, $3, $2)')') # hanoi (cnt) -define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') +define(`hanoi', `_$0(`$1', source, destination, auxilliary)') divert`'dnl # Debugmode t -- 1.5.4