[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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. GNU
m4
tries to keep diversions in memory. However, there is a
limit to the overall memory usable by all diversions taken together
(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.
When creating the temporary file, m4
honors the value of the
environment variable TMPDIR
, and falls back to ‘/tmp’.
Thus, the amount of available disk space provides the only real limit on
the number and aggregate size of diversions.
Diversions make it possible to generate output in a different order than the input was read. It is possible to implement topological sorting dependencies. For example, GNU Autoconf makes use of diversions under the hood to ensure that the expansion of a prerequisite macro appears in the output prior to the expansion of a dependent macro, regardless of which order the two macros were invoked in the user’s input file.
10.1 Diverting output | ||
10.2 Undiverting output | ||
10.3 Diversion numbers | ||
10.4 Discarding diverted text |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Output is diverted using divert
:
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 precedes ') ⇒ ^D ⇒Wrapped TEXT precedes diverted text. |
If output is diverted to a negative 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 a common programming idiom in m4
for avoiding them.
divert(`-1') define(`foo', `Macro `foo'.') define(`bar', `Macro `bar'.') divert ⇒ |
Traditional implementations only supported ten diversions. But as a GNU extension, diversion numbers can be as large as positive integers will allow, rather than treating a multi-digit diversion number as a request to discard text.
divert(eval(`1<<28'))world divert(`2')hello ^D ⇒hello ⇒world |
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] | [ ? ] |
Diverted text can be undiverted explicitly using the builtin
undivert
:
Undiverts the numeric 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, diversions may contain non-numeric strings, which are treated as the names of files to copy into the output without expansion. A warning is issued if a file could not be opened.
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 ⇒ divert(`1')more divert(`2')undivert(`1')diverted text`'divert ⇒ undivert(`1') ⇒ undivert(`2') ⇒more ⇒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, assume
the file ‘foo’ contains:
$ cat foo bar |
then
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. It is possible to intermix files and diversion numbers.
divert(`1')diversion one divert(`2')undivert(`foo')dnl divert(`3')diversion three divert`'dnl undivert(`1', `2', `foo', `3')dnl ⇒diversion one ⇒bar ⇒bar ⇒diversion three |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The current diversion is tracked by the 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] | [ ? ] |
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:
Discard the contents of each of the listed numeric diversions.
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; or see section Answers).
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by root on March 13, 2013 using texi2html 1.82.