### 17.5 Solution for `m4wrap` ¶

The replacement `m4wrap` versions presented above, designed to guarantee FIFO or LIFO order regardless of the underlying M4 implementation, share a bug when dealing with wrapped text that looks like parameter expansion. Note how the invocation of `m4wrapn` interprets these parameters, while using the builtin preserves them for their intended use.

    $ m4 -I examples
    include(`wraplifo.m4')
    ⇒
    m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
    ')
    ⇒
    builtin(`m4wrap', ``'define(`bar', ``$0:'-$1-$*-$#-')bar(`a', `b')
    ')
    ⇒
    ^D
    ⇒bar:-a-a,b-2-
    ⇒m4wrap0:---0-

Additionally, the computation of `_m4wrap_level` and creation of multiple `m4wrapn` placeholders in the original examples is more expensive in time and memory than strictly necessary. Notice how the improved version grabs the wrapped text via `defn` to avoid parameter expansion, then undefines `_m4wrap_text`, before stripping a level of quotes with `_arg1` to expand the text. That way, each level of wrapping reuses the single placeholder, which starts each nesting level in an undefined state.

Finally, it is worth emulating the GNU M4 extension of saving all arguments to `m4wrap`, separated by a space, rather than saving just the first argument. This is done with the `join` macro documented previously (see Recursion in `m4`). The improved LIFO example is shipped as `m4-1.4.19/examples/wraplifo2.m4`, and can easily be converted to a FIFO solution by swapping the adjacent invocations of `joinall` and `defn`.

    $ m4 -I examples
    include(`wraplifo2.m4')
    ⇒
    undivert(`wraplifo2.m4')dnl
    ⇒dnl Redefine m4wrap to have LIFO semantics, improved example.
    ⇒include(`join.m4')dnl
    ⇒define(`_m4wrap', defn(`m4wrap'))dnl
    ⇒define(`_arg1', `$1')dnl
    ⇒define(`m4wrap',
    ⇒`ifdef(`_$0_text',
    ⇒       `define(`_$0_text', joinall(` ', $@)defn(`_$0_text'))',
    ⇒       `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl
    ⇒define(`_$0_text', joinall(` ', $@))')')dnl
    m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
    ')
    ⇒
    m4wrap(`lifo text
    m4wrap(`nested', `', `$@
    ')')
    ⇒
    ^D
    ⇒lifo text
    ⇒foo:-a-a,b-2-
    ⇒nested  $@