Purpose

.-,--------------.
V |
>>-CALL--+-name----+------------+-+------------+--;------------><
| '-expression-' |
+-OFF--+-ERROR---+--------------------+
| +-FAILURE-+ |
| '-HALT----' |
'-ON--+-ERROR---+--+----------------+-'
+-FAILURE-+ '-NAME--trapname-'
'-HALT----'
CALL calls a routine (if you specify
name) or controls the trapping of certain conditions
(if you specify ON or OFF).
To control trapping, you specify
OFF or ON and the condition you want to trap. OFF turns off the specified
condition trap. ON turns on the specified condition trap. All information
on condition traps is contained in Conditions and Condition Traps.
To call a routine, a literal string or symbol that
is taken as a constant, specify
name. The
name must be a symbol, which is treated literally,
or a literal string. The routine called can be:
- An internal routine
- A function or subroutine that is in the same program as the CALL
instruction or function call that calls it.
- A built-in routine
- A function (which may be called as a subroutine) that is defined
as part of the REXX language.
- An external routine
- A function or subroutine that is neither built-in nor
in the same program as the CALL instruction or function call that
calls it.
If
name is a string (that
is, you specify
name in quotation marks),
the search for internal routines is bypassed, and only a built-in
function or an external routine is called. Note that the names of
built-in functions (and generally the names of external routines,
too) are in uppercase; therefore the name in the literal string should
also be in uppercase.
The called routine can optionally return
a result, and when it does, the CALL instruction is functionally identical
with the clause:

.-,--------------.
V |
>>-result=name--(----+------------+-+--)--;--------------------><
'-expression-'
If the called routine does not return a result, you
get an error if you call it as a function (as previously shown).
VM supports specifying up to 20 expressions, separated by
commas. The expressions are evaluated in
order from left to right and form the argument strings during execution
of the routine. Any ARG or PARSE ARG instruction or ARG built-in function
in the called routine accesses these strings rather than any previously
active in the calling program, until control returns to the CALL instruction.
You can omit expressions, if appropriate, by including extra commas.
The CALL then causes a branch to the routine called
name, using exactly the same mechanism as function
calls, see
Functions. The search order
is in the section on functions but briefly is as follows:
- Internal routines:
- These are sequences of instructions inside the same program, starting
at the label that matches name in the CALL
instruction. If you specify the routine name in quotation marks, then
an internal routine is not considered for that search order. You can
use SIGNAL and CALL together to call an internal routine whose name
was determined at the time of execution; this is known as a multi-way call (see SIGNAL). The RETURN instruction completes the execution of an internal
routine.
- Built-in routines:
- These are routines built into the language processor for providing
various functions. They always return a string that is the result
of the routine. (See Built-in Functions.)
- External routines:
- Users can write or use routines that are external to the language
processor and the calling program. External routines must be coded
in REXX. If the CALL instruction calls an external routine written
in REXX as a subroutine, you can retrieve any argument strings with
the ARG or PARSE ARG instructions or the ARG built-in function.
During execution of an internal routine,
all variables previously known are generally accessible. However,
the PROCEDURE instruction can set up a local variables environment
to protect the subroutine and caller from each other. The EXPOSE option
on the PROCEDURE instruction can expose selected variables to a routine.
Calling an external program as a subroutine is similar to calling
an internal routine. The external routine, however, is an implicit
PROCEDURE in that all the caller's variables are always hidden. The
status of internal values (NUMERIC settings, and so forth) start with
their defaults (rather than inheriting those of the caller). In addition,
you can use EXIT to return from the routine.
When control reaches an internal routine, the line number of
the CALL instruction is available in the variable SIGL (in the caller's
variable environment). This may be used as a debug aid, as it is,
therefore, possible to find out how control reached a routine. Note
that if the internal routine uses the PROCEDURE instruction, then
it needs to EXPOSE SIGL to get access to the line number of the CALL.
Eventually the subroutine should process a RETURN instruction,
and at that point control returns to the clause following the original
CALL. If the RETURN instruction specified an expression, the variable
RESULT is set to the value of that expression. Otherwise, the variable
RESULT is dropped (becomes uninitialized).
An internal routine
can include calls to other internal routines, as well as recursive calls to itself.
- Example:
-
/* Recursive subroutine execution... */
arg z
call factorial z
say z'! =' result
exit
factorial: procedure /* Calculate factorial by */
arg n /* recursive invocation. */
if n=0 then return 1
call factorial n-1
return result * n
During internal subroutine (and function) execution, all
important pieces of information are automatically saved and then restored
upon return from the routine. These are:
- The status of DO loops and other structures: Executing
a SIGNAL while within a subroutine is safe because DO loops, and so
forth, that were active when the subroutine was called are not ended.
(But those currently active within the subroutine are ended.)
- Trace action: After a subroutine is debugged, you can insert
a TRACE Off at the beginning of it, and this does not affect the tracing
of the caller. Conversely, if you simply wish to debug a subroutine,
you can insert a TRACE Results at the start and tracing is automatically
restored to the conditions at entry (for example, Off) upon return.
Similarly, ? (interactive debug) and ! (command inhibition) are saved across routines.
- NUMERIC settings: The DIGITS, FUZZ, and FORM of arithmetic
operations (in section NUMERIC)
are saved and then restored on return. A subroutine can, therefore,
set the precision, and so forth, that it needs to use without affecting
the caller.
- ADDRESS settings: The current and previous destinations for commands (see section ADDRESS) are saved and then restored on
return.
- Condition traps: (CALL ON and SIGNAL ON) are saved and
then restored on return. This means that CALL ON, CALL OFF, SIGNAL
ON, and SIGNAL OFF can be used in a subroutine without affecting the
conditions the caller set up.
- Condition information: This information describes the state
and origin of the current trapped condition. The CONDITION built-in
function returns this information. See section CONDITION.
- Elapsed-time clocks: A subroutine inherits the elapsed-time
clock from its caller (see section TIME), but because the time clock is saved across routine calls, a subroutine
or internal function can independently restart and use the clock without
affecting its caller. For the same reason, a clock started within
an internal routine is not available to the caller.
- OPTIONS settings: ETMODE and EXMODE are saved and then
restored on return. For more information, see section OPTIONS.
Implementation maximum: The total nesting of control structures, which
includes internal routine calls, is dependent upon available storage.