The Subroutine (SUBR) command is used in a CL procedure, along with the End Subroutine (ENDSUBR) command, to delimit the group of commands that define a subroutine.
The name of the subroutine, as used by the CALLSUBR command, is defined by the SUBR parameter on the Subroutine (SUBR) command.
The first Subroutine (SUBR) command that is encountered in a procedure also marks the end of the mainline of that procedure. All commands from this point forward, with the exception of the ENDPGM command, must be contained within a subroutine, in other words, between Subroutine (SUBR) and End Subroutine (ENDSUBR) commands. The Subroutine (SUBR) and End Subroutine (ENDSUBR) commands must be matched pairs, and subroutines cannot be nested; in other words, no SUBR SUBR - ENDSUBR ENDSUBR nesting of subroutines is allowed.
Both the ENDSUBR and RTNSUBR commands can be used to exit a subroutine, and when processed, control is returned to the command immediately following the Call Subroutine (CALLSUBR) command that called the subroutine. Both commands have an optional RTNVAL parameter, which can be anything that can be stored in a CL variable of TYPE(*INT) and LEN(4). If no RTNVAL parameter is defined on the Return Subroutine (RTNSUBR) or End Subroutine (ENDSUBR) command, a value of zero is returned.
For an example of the general structure of a CL procedure which contains a subroutine, see the following:
PGM DCLPRCOPT SUBRSTACK(25) DCL VAR(&RTNVAR) TYPE(*INT) LEN(4) : CALLSUBR SUBR(SUBR1) RTNVAL(&RTNVAR) : SUBR SUBR(SUBR1) : RTNSUBR RTNVAL(-1) : ENDSUBR ENDPGM
In this example, the Declare Processing Options (DCLPRCOPT) command was used to specify the size of the subroutine stack to be 25. The variable &RTNVAR is used to contain the return value from the subroutine. The Call Subroutine (CALLSUBR) command will transfer control to the subroutine SUBR1, as defined by the SUBR command. If the Return Subroutine (RTNSUBR) command is run, the value of &RTNVAR will be -1, if the End Subroutine (ENDSUBR) command is run, &RTNVAR will equal 0. If no RTNVAL parameter was defined on the Call Subroutine (CALLSUBR) command, the return value from the subroutine would be ignored.