m4: Improved copy

 
 17.4 Solution for 'copy'
 ========================
 
 The macro 'copy' presented above is unable to handle builtin tokens with
 M4 1.4.x, because it tries to pass the builtin token through the macro
 'curry', where it is silently flattened to an empty string (⇒
 Composition).  Rather than using the problematic 'curry' to work
 around the limitation that 'stack_foreach' expects to invoke a macro
 that takes exactly one argument, we can write a new macro that lets us
 form the exact two-argument 'pushdef' call sequence needed, so that we
 are no longer passing a builtin token through a text macro.
 
  -- Composite: stack_foreach_sep (MACRO, PRE, POST, SEP)
  -- Composite: stack_foreach_sep_lifo (MACRO, PRE, POST, SEP)
      For each of the 'pushdef' definitions associated with MACRO, expand
      the sequence 'PRE`'definition`'POST'.  Additionally, expand SEP
      between definitions.  'stack_foreach_sep' visits the oldest
      definition first, while 'stack_foreach_sep_lifo' visits the current
      definition first.  The expansion may dereference MACRO, but should
      not modify it.  There are a few special macros, such as 'defn',
      which cannot be used as the MACRO parameter.
 
    Note that 'stack_foreach(`MACRO', `ACTION')' is equivalent to
 'stack_foreach_sep(`MACRO', `ACTION(', `)')'.  By supplying explicit
 parentheses, split among the PRE and POST arguments to
 'stack_foreach_sep', it is now possible to construct macro calls with
 more than one argument, without passing builtin tokens through a macro
 call.  It is likewise possible to directly reference the stack
 definitions without a macro call, by leaving PRE and POST empty.  Thus,
 in addition to fixing 'copy' on builtin tokens, it also executes with
 fewer macro invocations.
 
    The new macro also adds a separator that is only output after the
 first iteration of the helper '_stack_reverse_sep', implemented by
 prepending the original SEP to PRE and omitting a SEP argument in
 subsequent iterations.  Note that the empty string that separates SEP
 from PRE is provided as part of the fourth argument when originally
 calling '_stack_reverse_sep', and not by writing '$4`'$3' as the third
 argument in the recursive call; while the other approach would give the
 same output, it does so at the expense of increasing the argument size
 on each iteration of '_stack_reverse_sep', which results in quadratic
 instead of linear execution time.  The improved stack walking macros are
 available in 'm4-1.4.18/examples/stack_sep.m4':
 
      $ m4 -I examples
      include(`stack_sep.m4')
      =>
      define(`copy', `ifdef(`$2', `errprint(`$2 already defined
      ')m4exit(`1')',
         `stack_foreach_sep(`$1', `pushdef(`$2',', `)')')')dnl
      pushdef(`a', `1')pushdef(`a', defn(`divnum'))
      =>
      copy(`a', `b')
      =>
      b
      =>0
      popdef(`b')
      =>
      b
      =>1
      pushdef(`c', `1')pushdef(`c', `2')
      =>
      stack_foreach_sep_lifo(`c', `', `', `, ')
      =>2, 1
      undivert(`stack_sep.m4')dnl
      =>divert(`-1')
      =># stack_foreach_sep(macro, pre, post, sep)
      =># Invoke PRE`'defn`'POST with a single argument of each definition
      =># from the definition stack of MACRO, starting with the oldest, and
      =># separated by SEP between definitions.
      =>define(`stack_foreach_sep',
      =>`_stack_reverse_sep(`$1', `tmp-$1')'dnl
      =>`_stack_reverse_sep(`tmp-$1', `$1', `$2`'defn(`$1')$3', `$4`'')')
      =># stack_foreach_sep_lifo(macro, pre, post, sep)
      =># Like stack_foreach_sep, but starting with the newest definition.
      =>define(`stack_foreach_sep_lifo',
      =>`_stack_reverse_sep(`$1', `tmp-$1', `$2`'defn(`$1')$3', `$4`'')'dnl
      =>`_stack_reverse_sep(`tmp-$1', `$1')')
      =>define(`_stack_reverse_sep',
      =>`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0(
      =>  `$1', `$2', `$4$3')')')
      =>divert`'dnl