Next: Improved cleardivert, Previous: Improved copy, Up: Answers [Contents][Index]
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 Shift). 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 $@
Next: Improved cleardivert, Previous: Improved copy, Up: Answers [Contents][Index]