m4: Improved m4wrap

1 
1 17.5 Solution for 'm4wrap'
1 ==========================
1 
1 The replacement 'm4wrap' versions presented above, designed to guarantee
1 FIFO or LIFO order regardless of the underlying M4 implementation, share
1 a bug when dealing with wrapped text that looks like parameter
1 expansion.  Note how the invocation of 'm4wrapN' interprets these
1 parameters, while using the builtin preserves them for their intended
1 use.
1 
1      $ m4 -I examples
1      include(`wraplifo.m4')
1      =>
1      m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
1      ')
1      =>
1      builtin(`m4wrap', ``'define(`bar', ``$0:'-$1-$*-$#-')bar(`a', `b')
1      ')
1      =>
1      ^D
1      =>bar:-a-a,b-2-
1      =>m4wrap0:---0-
1 
1    Additionally, the computation of '_m4wrap_level' and creation of
1 multiple 'm4wrapN' placeholders in the original examples is more
1 expensive in time and memory than strictly necessary.  Notice how the
1 improved version grabs the wrapped text via 'defn' to avoid parameter
1 expansion, then undefines '_m4wrap_text', before stripping a level of
1 quotes with '_arg1' to expand the text.  That way, each level of
1 wrapping reuses the single placeholder, which starts each nesting level
1 in an undefined state.
1 
1    Finally, it is worth emulating the GNU M4 extension of saving all
1 arguments to 'm4wrap', separated by a space, rather than saving just the
1 first argument.  This is done with the 'join' macro documented
1 previously (⇒Shift).  The improved LIFO example is shipped as
1 'm4-1.4.18/examples/wraplifo2.m4', and can easily be converted to a FIFO
1 solution by swapping the adjacent invocations of 'joinall' and 'defn'.
1 
1      $ m4 -I examples
1      include(`wraplifo2.m4')
1      =>
1      undivert(`wraplifo2.m4')dnl
1      =>dnl Redefine m4wrap to have LIFO semantics, improved example.
1      =>include(`join.m4')dnl
1      =>define(`_m4wrap', defn(`m4wrap'))dnl
1      =>define(`_arg1', `$1')dnl
1      =>define(`m4wrap',
1      =>`ifdef(`_$0_text',
1      =>       `define(`_$0_text', joinall(` ', $@)defn(`_$0_text'))',
1      =>       `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl
1      =>define(`_$0_text', joinall(` ', $@))')')dnl
1      m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
1      ')
1      =>
1      m4wrap(`lifo text
1      m4wrap(`nested', `', `$@
1      ')')
1      =>
1      ^D
1      =>lifo text
1      =>foo:-a-a,b-2-
1      =>nested  $@
1