[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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, whilestack_foreach_lifo
visits the current definition first. action should not modify or dereference macro. There are a few special macros, such asdefn
, which cannot be used as the macro parameter.
A sample implementation of these macros is distributed in the file ‘m4-1.4.17/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
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on September 29, 2013 using texi2html 5.0.