-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Daniel Richard G. on 5/21/2007 1:43 AM: > In fact, it's a fairly simple patch. See attached for my stab at it. (Also, > there's a more straightforward test input file.) I did the two-arg > divert(), since that seems more natural than coming up with a new/separate > builtin for this. > > I think this fills a hole in the core m4 feature set---right now, as I > understand it, the only way to send text to a diversion is at the point > when the text is actually being written out. With this, you can send text > to a diversion in the same way that errprint() sends text to stderr: > immediately upon evaluation of the builtin. Without regard to the invoking > context.
Thanks again for the idea. And in the process of checking this in, I discovered a regression from a couple days ago in handling hand-crafted frozen files. Here's what I'm checking in to head. I'm porting the regression fix, but not the new feature, to the branch. 2007-05-31 Eric Blake <[EMAIL PROTECTED]> Add extension to divert builtin. * modules/m4.c (builtin_divert): Immediately divert second argument. * m4/output.c (m4_output_text): Allow 0 length. Fixes regression from two days ago. (m4_shipout_text): Short-circuit on zero length. * tests/freeze.at (loading format 2): Expand test to catch regression. Also check out-of-range version. * tests/builtins.at (divert): Expand test to check corner cases of extension. * NEWS: Document the extension. Reported by Daniel Richard G. - -- 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 iD8DBQFGXszC84KuGfSFAYARApeAAKDV+0R/8Xxr9rRqn454PGWSASqvrQCfdMJm yJJrW4hk+IlM9MxWjN8PlwY= =aDjR -----END PGP SIGNATURE-----
Index: NEWS =================================================================== RCS file: /sources/m4/m4/NEWS,v retrieving revision 1.42 diff -u -p -r1.42 NEWS --- NEWS 24 Mar 2007 21:29:41 -0000 1.42 +++ NEWS 31 May 2007 13:21:59 -0000 @@ -157,6 +157,11 @@ promoted to 2.0. information to the first line to show the definition of the macro being expanded. The 'e' flag has been updated to output non-text expansions. +*** The `divert' builtin now accepts an optional second argument of text + that is immediately placed on the new diversion, regardless of whether + the current expansion is nested within argument collection of another + macro. + *** The `dumpdef' builtin now always outputs to standard error, rather than the debug file specified by the `--debugfile' option or `debugfile' macro. Index: doc/m4.texinfo =================================================================== RCS file: /sources/m4/m4/doc/m4.texinfo,v retrieving revision 1.105 diff -u -p -r1.105 m4.texinfo --- doc/m4.texinfo 30 May 2007 13:36:58 -0000 1.105 +++ doc/m4.texinfo 31 May 2007 13:21:59 -0000 @@ -5008,11 +5008,17 @@ input file. @cindex files, diverting output to Output is diverted using @code{divert}: [EMAIL PROTECTED] {Builtin (m4)} divert (@dvar{number, 0}) [EMAIL PROTECTED] {Builtin (m4)} divert (@dvar{number, 0}, @ovar{text}) The current diversion is changed to @var{number}. If @var{number} is left out or empty, it is assumed to be zero. If @var{number} cannot be parsed, the diversion is unchanged. [EMAIL PROTECTED] @acronym{GNU} extensions +As a @acronym{GNU} extension, if optional @var{text} is supplied and [EMAIL PROTECTED] was valid, then @var{text} is immediately output to the +new diversion, regardless of whether the expansion of @code{divert} +occurred while collecting arguments for another macro. + The expansion of @code{divert} is void. @end deffn @@ -5076,6 +5082,44 @@ divert(`2')hello @result{}world @end example +The ability to immediately output extra text is a @acronym{GNU} +extension, but it can prove useful for ensuring that text goes to a +particular diversion no matter how many pending macro expansions are in +progress. For a demonstration of why this is useful, it is important to +understand in the example below why @samp{one} is output in diversion 2, +not diversion 1, while @samp{three} and @samp{five} both end up in the +correctly numbered diversion. The key point is that when @code{divert} +is executed unquoted as part of the argument collection of another +macro, the side effect takes place immediately, but the text @samp{one} +is not passed to any diversion until after the @samp{divert(`2')} and +the enclosing @code{echo} have also taken place. The example with [EMAIL PROTECTED] shows how following the quoting rule of thumb delays the +invocation of @code{divert} until it is not nested in any argument +collection context, while the example with @samp{five} shows the use of +the optional argument to speed up the output process. + [EMAIL PROTECTED] +define(`echo', `$1') [EMAIL PROTECTED] +echo(divert(`1')`one'divert(`2'))`'dnl +echo(`divert(`3')three`'divert(`4')')`'dnl +echo(divert(`5', `five')divert(`6'))`'dnl +divert [EMAIL PROTECTED] +undivert(`1') [EMAIL PROTECTED] +undivert(`2') [EMAIL PROTECTED] +undivert(`3') [EMAIL PROTECTED] +undivert(`4') [EMAIL PROTECTED] +undivert(`5') [EMAIL PROTECTED] +undivert(`6') [EMAIL PROTECTED] [EMAIL PROTECTED] example + Note that @code{divert} is an English word, but also an active macro without arguments. When processing plain text, the word might appear in normal text and be unintentionally swallowed as a macro invocation. One Index: m4/output.c =================================================================== RCS file: /sources/m4/m4/m4/output.c,v retrieving revision 1.44 diff -u -p -r1.44 output.c --- m4/output.c 28 May 2007 21:48:41 -0000 1.44 +++ m4/output.c 31 May 2007 13:21:59 -0000 @@ -423,6 +423,9 @@ m4_output_text (m4 *context, const char { size_t count; + if (!output_diversion || !length) + return; + if (!output_file && length > output_unused) make_room_for (context, length); @@ -470,7 +473,7 @@ m4_shipout_text (m4 *context, m4_obstack /* Do nothing if TEXT should be discarded. */ - if (output_diversion == NULL) + if (!output_diversion || !length) return; /* Output TEXT to a file, or in-memory diversion buffer. */ Index: modules/m4.c =================================================================== RCS file: /sources/m4/m4/modules/m4.c,v retrieving revision 1.109 diff -u -p -r1.109 m4.c --- modules/m4.c 24 May 2007 20:13:44 -0000 1.109 +++ modules/m4.c 31 May 2007 13:21:59 -0000 @@ -70,7 +70,7 @@ extern void m4_make_temp (m4 *contex BUILTIN (decr, false, true, true, 1, 1 ) \ BUILTIN (define, true, true, false, 1, 2 ) \ BUILTIN (defn, false, true, false, 1, -1 ) \ - BUILTIN (divert, false, false, false, 0, 1 ) \ + BUILTIN (divert, false, false, false, 0, 2 ) \ BUILTIN (divnum, false, false, false, 0, 0 ) \ BUILTIN (dnl, false, false, false, 0, 0 ) \ BUILTIN (dumpdef, false, false, false, 0, -1 ) \ @@ -578,11 +578,16 @@ M4BUILTIN_HANDLER (decr) M4BUILTIN_HANDLER (divert) { int i = 0; + const char *text; if (argc >= 2 && !m4_numeric_arg (context, argc, argv, 1, &i)) return; m4_make_diversion (context, i); + + text = M4ARG (2); + m4_shipout_text (context, NULL, text, strlen (text), + m4_get_current_line (context)); } /* Expand to the current diversion number. */ Index: tests/builtins.at =================================================================== RCS file: /sources/m4/m4/tests/builtins.at,v retrieving revision 1.40 diff -u -p -r1.40 builtins.at --- tests/builtins.at 12 Apr 2007 17:41:35 -0000 1.40 +++ tests/builtins.at 31 May 2007 13:21:59 -0000 @@ -177,6 +177,17 @@ AT_CHECK_M4([divert.m4], 0, Text diverted a second time. ]]) +dnl Test second divert argument, added for m4 2.0 +AT_DATA([in.m4], [[define(`echo',`$1')dnl +divert(`-1', `discarded without warning') +divert`'dnl +echo(` world'divert(divnum, `hello')) +]]) + +AT_CHECK_M4([-s in.m4], [0], [[#line 4 "in.m4" +hello world +]]) + AT_CLEANUP Index: tests/freeze.at =================================================================== RCS file: /sources/m4/m4/tests/freeze.at,v retrieving revision 1.11 diff -u -p -r1.11 freeze.at --- tests/freeze.at 28 May 2007 20:10:02 -0000 1.11 +++ tests/freeze.at 31 May 2007 13:21:59 -0000 @@ -163,6 +163,12 @@ M3 gnu F7,7,3 builtinbuiltingnu +# Text to negative diversion must not crash. Catches a regression +# introduced 2007-05-28 and fixed 2007-05-31. +D-1,5 +12345 +D0,0 + # Testing escape sequences T4,5 blah\t\477\040\X5C @@ -188,6 +194,13 @@ bar '7 \ ]]) +dnl We don't support anything larger than format 2; make sure of that... +AT_DATA([bogus.m4f], [[V3 +]]) +AT_CHECK_M4([-R bogus.m4f], [63], [], +[[m4: frozen file version 3 greater than max supported of 2 +]]) + AT_CLEANUP
_______________________________________________ M4-discuss mailing list M4-discuss@gnu.org http://lists.gnu.org/mailman/listinfo/m4-discuss