m4: Indir

1 
1 5.7 Indirect call of macros
1 ===========================
1 
1 Any macro can be called indirectly with 'indir':
1 
1  -- Builtin: indir (NAME, [ARGS...])
1      Results in a call to the macro NAME, which is passed the rest of
1      the arguments ARGS.  If NAME is not defined, an error message is
1      printed, and the expansion is void.
1 
1      The macro 'indir' is recognized only with parameters.
1 
1    This can be used to call macros with computed or "invalid" names
1 ('define' allows such names to be defined):
1 
1      define(`$$internal$macro', `Internal macro (name `$0')')
1      =>
1      $$internal$macro
1      =>$$internal$macro
1      indir(`$$internal$macro')
1      =>Internal macro (name $$internal$macro)
1 
1    The point is, here, that larger macro packages can have private
1 macros defined, that will not be called by accident.  They can _only_ be
1 called through the builtin 'indir'.
1 
1    One other point to observe is that argument collection occurs before
1 'indir' invokes NAME, so if argument collection changes the value of
1 NAME, that will be reflected in the final expansion.  This is different
1 than the behavior when invoking macros directly, where the definition
1 that was in effect before argument collection is used.
1 
1      $ m4 -d
1      define(`f', `1')
1      =>
1      f(define(`f', `2'))
1      =>1
1      indir(`f', define(`f', `3'))
1      =>3
1      indir(`f', undefine(`f'))
1      error->m4:stdin:4: undefined macro `f'
1      =>
1 
1    When handed the result of 'defn' (⇒Defn) as one of its
1 arguments, 'indir' defers to the invoked NAME for whether a token
1 representing a builtin is recognized or flattened to the empty string.
1 
1      $ m4 -d
1      indir(defn(`defn'), `divnum')
1      error->m4:stdin:1: Warning: indir: invalid macro name ignored
1      =>
1      indir(`define', defn(`defn'), `divnum')
1      error->m4:stdin:2: Warning: define: invalid macro name ignored
1      =>
1      indir(`define', `foo', defn(`divnum'))
1      =>
1      foo
1      =>0
1      indir(`divert', defn(`foo'))
1      error->m4:stdin:5: empty string treated as 0 in builtin `divert'
1      =>
1