[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9. Diverting and undiverting output

Diversions are a way of temporarily saving output. The output of m4 can at any time be diverted to a temporary file, and be reinserted into the output stream, undiverted, again at a later time.

Numbered diversions are counted from 0 upwards, diversion number 0 being the normal output stream. The number of simultaneous diversions is limited mainly by the memory used to describe them, because GNU m4 tries to keep diversions in memory. However, there is a limit to the overall memory usable by all diversions taken altogether (512K, currently). When this maximum is about to be exceeded, a temporary file is opened to receive the contents of the biggest diversion still in memory, freeing this memory for other diversions. So, it is theoretically possible that the number of diversions be limited by the number of available file descriptors.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.1 Diverting output

Output is diverted using divert:

Builtin: divert ([number = `'])

The current diversion is changed to number. If number is left out or empty, it is assumed to be zero. If number cannot be parsed, the diversion is unchanged.

The expansion of divert is void.

When all the m4 input will have been processed, all existing diversions are automatically undiverted, in numerical order.

 
divert(`1')
This text is diverted.
divert
⇒
This text is not diverted.
⇒This text is not diverted.
^D
⇒
⇒This text is diverted.

Several calls of divert with the same argument do not overwrite the previous diverted text, but append to it. Diversions are printed after any wrapped text is expanded.

 
define(`text', `TEXT')
⇒
divert(`1')`diverted text.'
divert
⇒
m4wrap(`Wrapped text preceeds ')
⇒
^D
⇒Wrapped TEXT preceeds diverted text.

If output is diverted to a non-existent diversion, it is simply discarded. This can be used to suppress unwanted output. A common example of unwanted output is the trailing newlines after macro definitions. Here is how to avoid them.

 
divert(`-1')
define(`foo', `Macro `foo'.')
define(`bar', `Macro `bar'.')
divert
⇒

This is a common programming idiom in m4.

Note that 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 way to avoid this is to use the `-P' option to rename all builtins (see section Invoking m4). Another is to write a wrapper that requires a parameter to be recognized.

 
We decided to divert the stream for irrigation.
⇒We decided to  the stream for irrigation.
define(`divert', `ifelse(`$#', `0', ``$0'', `builtin(`$0', $@)')')
⇒
divert(-1)
Ignored text.
divert(0)
⇒
We decided to divert the stream for irrigation.
⇒We decided to divert the stream for irrigation.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 Undiverting output

Diverted text can be undiverted explicitly using the builtin undivert:

Builtin: undivert ([number]…)

Undiverts the diversions given by the arguments, in the order given. If no arguments are supplied, all diversions are undiverted, in numerical order. As a GNU extension, if number is not numeric, treat it as a file name instead.

The expansion of undivert is void.

 
divert(`1')
This text is diverted.
divert
⇒
This text is not diverted.
⇒This text is not diverted.
undivert(`1')
⇒
⇒This text is diverted.
⇒

Notice the last two blank lines. One of them comes from the newline following undivert, the other from the newline that followed the divert! A diversion often starts with a blank line like this.

When diverted text is undiverted, it is not reread by m4, but rather copied directly to the current output, and it is therefore not an error to undivert into a diversion. Undiverting the empty string is the same as specifying diversion 0; in either case nothing happens since the output has already been flushed.

 
divert(`1')diverted text
divert
⇒
undivert()
⇒
undivert(`0')
⇒
undivert
⇒diverted text
⇒

When a diversion has been undiverted, the diverted text is discarded, and it is not possible to bring back diverted text more than once.

 
divert(`1')
This text is diverted first.
divert(`0')undivert(`1')dnl
⇒
⇒This text is diverted first.
undivert(`1')
⇒
divert(`1')
This text is also diverted but not appended.
divert(`0')undivert(`1')dnl
⇒
⇒This text is also diverted but not appended.

Attempts to undivert the current diversion are silently ignored. Thus, when the current diversion is not 0, the current diversion does not get rearranged among the other diversions.

 
divert(`1')one
divert(`2')two
divert(`3')three
divert(`2')undivert`'dnl
divert`'undivert`'dnl
⇒two
⇒one
⇒three

GNU m4 allows named files to be undiverted. Given a non-numeric argument, the contents of the file named will be copied, uninterpreted, to the current output. This complements the builtin include (see section Including named files). To illustrate the difference, the file `examples/foo' contains the word `bar':

 
define(`bar', `BAR')
⇒
undivert(`foo')
⇒bar
⇒
include(`foo')
⇒BAR
⇒

If the file is not found (or cannot be read), an error message is issued, and the expansion is void.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.3 Diversion numbers

The current diversion is tracked by the builtin divnum:

Builtin: divnum

Expands to the number of the current diversion.

 
Initial divnum
⇒Initial 0
divert(`1')
Diversion one: divnum
divert(`2')
Diversion two: divnum
^D
⇒
⇒Diversion one: 1
⇒
⇒Diversion two: 2

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.4 Discarding diverted text

Often it is not known, when output is diverted, whether the diverted text is actually needed. Since all non-empty diversion are brought back on the main output stream when the end of input is seen, a method of discarding a diversion is needed. If all diversions should be discarded, the easiest is to end the input to m4 with `divert(`-1')' followed by an explicit `undivert':

 
divert(`1')
Diversion one: divnum
divert(`2')
Diversion two: divnum
divert(`-1')
undivert
^D

No output is produced at all.

Clearing selected diversions can be done with the following macro:

Composite: cleardivert ([diversion]…)

Discard the contents of each listed diversion.

 
define(`cleardivert',
`pushdef(`_n', divnum)divert(`-1')undivert($@)divert(_n)popdef(`_n')')
⇒

It is called just like undivert, but the effect is to clear the diversions, given by the arguments. (This macro has a nasty bug! You should try to see if you can find it and correct it. see section Correct version of some examples)


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by System Administrator on September, 23 2007 using texi2html 1.70.