Macros can invoke other macros within the same macro file; a macro can also invoke a macro from another macro file if the invocation takes place in literal text, that is, not within a control expression. A macro can invoke itself directly or indirectly (an invoked macro can invoke the macro that invoked it); the number of nested invocations is limited to 10 to prevent infinite recursion.
Within each macro, you can specify parameters that must be passed to the macro when it is invoked by another. You must specify named variables enclosed in parentheses after the macro name in the first line of the macro, as shown in this example:
<# macroName (count, total) #>
Additional parameters can be passed as well. Parameters can be local variables, environmental variables, literals, or operations. The invoking macro passes local variables by reference to the invoked macro. Passing parameters has no effect on the invoking macro unless the parameter is a local variable that is changed by the invoked macro. When the invoked macro completes execution, the local variable assumes the new value for the invoking macro.
The invoked macro can use the param[ n ] expression to access parameters passed to it, where n is the number of the parameter passed. This is useful if optional parameters can be passed to a macro or if the same iterative algorithm needs to process the parameters.
Use the expression param[0] to return the total number of parameters passed to the macro. Use the return keyword to halt execution of the invoked macro and resume execution of the invoking macro. Use the exit keyword to halt execution of all macros.
Example 1
The following sample macro demonstrates macro invocation:
<# invoking_examples #>
<# //---------------------------------------- #>
<# name := env.getline("What is your first name? ") #>
! First, <#name#>, we will invoke the if_examples and
! the while_examples macros...
<# tmpl.if_examples; tmpl.while_examples #>
! Hey <#name#>, have you noticed that your name backwards is:
!<# eman:= ""; tmpl.reversestring(name, eman); eman; "\n"#>
<# tmpl.argumentlist("a", "b", "c")#>
<# endtmpl #>
<# argumentlist #>
<# if param[0] = 0; return; endif #>
! argumentList() was called with the following arguments:
<# while ++i <= param[0]#>
! <#param[i];"\n"#>
<# endwhile #>
<# endtmpl #>
<# reversestring (string, gnirts) #>
<# i := 0 + string; // i is now equal to the number of characters in string. #>
<# while --i >= 0; gnirts := gnirts $ substr(string, i, 1); endwhile #>
<# endtmpl #>
Example 2
The following macro in file macro1.mac invokes a macro from within another file, macro2.mac:
<# callAnotherMacro #> <# localVar := 5 #> macro macro2.mac macroName2 <# localVar #> string1 <# endtmpl #>
This macro passes the value of localVar to macroName2. The value of localVar remains at 5 for callAnotherMacro, regardless of any operations upon that variable in the second macro. In other words, an invoked macro in another file cannot return any values to the invoking macro.
The output of callAnotherMacro looks like this:
host1# macro verbose macro1.mac callAnotherMacro host1#!Macro 'callAnotherMacro' in the file 'macro1.mac' starting execution (Id: 55) macro macro2.mac macroName2 5 string1 !Macro 'macroName2' in the file 'macro2.mac' starting execution !Macro 'macroName2' in the file 'macro2.mac' ending execution host1#!Macro 'callAnotherMacro' in the file 'macro1.mac' ending execution (Id: 55)
The invoked macro cannot invoke a third macro from another file. Only a single level of invocation is supported.