Previous: Changeword, Up: Input Control


7.5 Saving text until end of input

It is possible to `save' some text until the end of the normal input has been seen. Text can be saved, to be read again by m4 when the normal input has been exhausted. This feature is normally used to initiate cleanup actions before normal exit, e.g., deleting temporary files.

To save input text, use the builtin m4wrap:

— Builtin: m4wrap (string, ...)

Stores string in a safe place, to be reread when end of input is reached. As a GNU extension, additional arguments are concatenated with a space to the string.

The expansion of m4wrap is void. The macro m4wrap is recognized only with parameters.

     define(`cleanup', `This is the `cleanup' action.
     ')
     =>
     m4wrap(`cleanup')
     =>
     This is the first and last normal input line.
     =>This is the first and last normal input line.
     ^D
     =>This is the cleanup action.

The saved input is only reread when the end of normal input is seen, and not if m4exit is used to exit m4.

It is safe to call m4wrap from saved text, but then the order in which the saved text is reread is undefined. If m4wrap is not used recursively, the saved pieces of text are reread in the opposite order in which they were saved (LIFO—last in, first out). However, this behavior is likely to change in a future release, to match POSIX, so you should not depend on this order.

Here is an example of implementing a factorial function using m4wrap:

     define(`f', `ifelse(`$1', `0', `Answer: 0!=1
     ', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1')
     ', `m4wrap(`f(decr(`$1'), `$2$1*')')')')
     =>
     f(`10')
     =>
     ^D
     =>Answer: 10*9*8*7*6*5*4*3*2*1=3628800

Invocations of m4wrap at the same recursion level are concatenated and rescanned as usual:

     define(`aa', `AA
     ')
     =>
     m4wrap(`a')m4wrap(`a')
     =>
     ^D
     =>AA

however, the transition between recursion levels behaves like an end of file condition between two input files.

     m4wrap(`m4wrap(`)')len(abc')
     =>
     ^D
     error-->m4: ERROR: end of file in argument list