### 6.6 Working with definition stacks ¶

Thanks to `pushdef`, manipulation of a stack is an intrinsic operation in `m4`. Normally, only the topmost definition in a stack is important, but sometimes, it is desirable to manipulate the entire definition stack.

Composite: stack_foreach (macro, action) ¶
Composite: stack_foreach_lifo (macro, action) ¶

  For each of the `pushdef` definitions associated with macro, invoke the macro action with a single argument of that definition. `stack_foreach` visits the oldest definition first, while `stack_foreach_lifo` visits the current definition first. action should not modify or dereference macro. There are a few special macros, such as `defn`, which cannot be used as the macro parameter.

A sample implementation of these macros is distributed in the file `m4-1.4.19/examples/stack.m4`.

    $ m4 -I examples
    include(`stack.m4')
    ⇒
    pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3')
    ⇒
    define(`show', ``$1'
    ')
    ⇒
    stack_foreach(`a', `show')dnl
    ⇒1
    ⇒2
    ⇒3
    stack_foreach_lifo(`a', `show')dnl
    ⇒3
    ⇒2
    ⇒1

Now for the implementation. Note the definition of a helper macro, `_stack_reverse`, which destructively swaps the contents of one stack of definitions into the reverse order in the temporary macro ‘`tmp-$1`’. By calling the helper twice, the original order is restored back into the macro ‘`$1`’; since the operation is destructive, this explains why ‘`$1`’ must not be modified or dereferenced during the traversal. The caller can then inject additional code to pass the definition currently being visited to ‘`$2`’. The choice of helper names is intentional; since ‘`-`’ is not valid as part of a macro name, there is no risk of conflict with a valid macro name, and the code is guaranteed to use `defn` where necessary. Finally, note that any macro used in the traversal of a `pushdef` stack, such as `pushdef` or `defn`, cannot be handled by `stack_foreach`, since the macro would temporarily be undefined during the algorithm.

    $ m4 -I examples
    undivert(`stack.m4')dnl
    ⇒divert(`-1')
    ⇒# stack_foreach(macro, action)
    ⇒# Invoke ACTION with a single argument of each definition
    ⇒# from the definition stack of MACRO, starting with the oldest.
    ⇒define(`stack_foreach',
    ⇒`_stack_reverse(`$1', `tmp-$1')'dnl
    ⇒`_stack_reverse(`tmp-$1', `$1', `$2(defn(`$1'))')')
    ⇒# stack_foreach_lifo(macro, action)
    ⇒# Invoke ACTION with a single argument of each definition
    ⇒# from the definition stack of MACRO, starting with the newest.
    ⇒define(`stack_foreach_lifo',
    ⇒`_stack_reverse(`$1', `tmp-$1', `$2(defn(`$1'))')'dnl
    ⇒`_stack_reverse(`tmp-$1', `$1')')
    ⇒define(`_stack_reverse',
    ⇒`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0($@)')')
    ⇒divert`'dnl