File: m4.info, Node: Improved m4wrap, Next: Improved cleardivert, Prev: Improved copy, Up: Answers 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 (*note Shift::). The improved LIFO example is shipped as ‘m4-1.4.20/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 $@