TSO-ISPF JCL COBOL VSAM DB2 CICS Tools Articles Job Portal Forum Quiz Interview Q&A

Rexx Subroutines


After completing this chapter, you will be able to explain how to write and apply subroutines.


Subroutines are similar to functions which are invoked to perform a specific task. When a subroutine execution is completed successfully, the control returns back to the instruction that follows the subroutine call.

In many ways subroutines and functions are similar except the way in which they are called and the way values are returned back.

Following are the characteristics of a subroutine:

  • A Subroutine may or may not receive arguments.

  • A Subroutine may or may not return any values.

  • Unlike functions, CALL statements are used to invoke subroutines. CALL statement should be followed by subroutine name which is optionally followed by arguments. Similar to functions, a maximum of 20 arguments can be passed to subroutine.

    CALL SUBR ARG1 ARG2

In the earlier call, SUBR is the subroutine being called and ARG1 & ARG2 denote the arguments passed to the subroutine.

  • Once the necessary instructions are executed in the subroutine, RETURN statements are used to transfer the control back to the calling module.

  • In the calling exec, the value returned by a subroutine will be received in a special variable called RESULT.

Subroutines can be broadly classified as internal and external subroutines.


Internal Subroutines:

Internal subroutines are coded within the current exec, marked by a label and used only by that exec. As internal subroutines generally appear after the main part of the exec, when you have an internal subroutine, it is important to end the main part of the exec with the EXIT instruction.

Example:

/* REXX */
CALL INTSUBR
EXIT 0

INTSUBR:
SAY 'YOU ARE INSIDE INTERNAL SUBROUTINE'
RETURN

Note:

Issuing a CALL to internal label names for subroutines and functions that are greater than eight characters, may have unintended results. Label names will be truncated to eight characters


External Subroutines:

External subroutine is a program or an exec in a member of a partitioned data set that can be called by one or more execs.

Whenever a CALL statement is encountered in REXX, internal labels will be searched first. If no internal labels match the subroutine name, it will be treated as an external subroutine and the subroutine will be picked up from the partitioned dataset allocated to DDnames SYSEXEC or SYSPROC. The order of search will be SYSEXEC followed by SYSPROC.


Passing Arguments across Subroutine / Function Calls:

An internal routine can share variables with its caller. As a result, commonly shared variables can be used to pass information between calling exec and internal routine. Arguments can also be used to pass information to and from an internal routine.

However, external routines, however, cannot share the same variables, and information must pass between them through arguments or some other external way, such as data stack.

Note:

Here routine refers to both subroutines and functions

Call by Variable:

When an exec and its internal routine share the same variables, the value of a variable is what was last assigned, regardless of whether the assignment was in the main part of the exec or in the internal routine.

In the following example, the value of ANS is assigned in the subroutine and displayed in the main part of the exec. The variables NUM1, NUM2, and ANS are shared across internal subroutine and the calling exec.

Example of passing information in a variable

/*******************************REXX *********************************/
/* This exec receives a calculated value from an internal subroutine */
/* displays that value.                                              */
/*********************************************************************/

/* CALL AS INTERNAL SUBROUTINE */
NUM1 = 5
NUM2 = 10
CALL ANS_SUBR
SAY ANS	      /* DISPLAYS 15 */
NUM1 = 5
NUM2 = 12

/* CALL AS INTERNAL USER-DEFINED FUNCTION */
X=ANS_SUBR()
SAY ANS      /* DISPLAYS 17 */


ANS_SUBR:
ANS = NUM1 + NUM2

RETURN 0
/* ENABLE ANS_SUBR TO BE CALLED AS FUNCTION DUMMY VALUE IS RETURNED */

Call by Arguments:

Arguments can be used to pass information to both internal and external subroutines / functions. As mentioned earlier, maximum of 20 arguments can be passed to the subroutines functions.

For example, a call statement passing arguments can be visualized as

CALL SUBR ARG1 ARG2 ARG3.

Here arguments ARG1, ARG2 and ARG3 are passed to the subroutine SUBR.

Similarly, a function passing arguments can be visualized as

X = FUNC(ARG1, ARG2, ARG3)

Here arguments ARG1, ARG2 and ARG3 are passed to the function FUNC.

The subroutines can receive the arguments passed from the calling exec using ARG or PARSE ARG instruction, where the arguments can be delimited by commas or spaces.

ARG ARG1 ARG2 ARG3

The names of the arguments on the CALL and the ARG instructions do not have to be same as the information is not passed by name but by value.

CALL SUBR ARG1 ARG2 ARG3.

The names of the arguments on the CALL and the ARG instructions do not have to be same as the information is not passed by name but by value.

In the subroutine / function values are returned to the calling exec using RETURN statement. Although a subroutine can receive up to 20 arguments, it can specify only one expression on the RETURN instruction.

For example, 'RETURN ans' statement returns the value 'ans' to the calling exec.

Receive parameters from Function / Subroutines:

The value returned due to a function call substitutes the function call itself.

For example,

X = MAX(1,2,3) + 2;

Here the in-built function MAX will return a value of 3, which will be substituted in the above statement as

X = 3 + 2;

Thus X will be assigned a value of 5.

Whereas, in case of subroutines the value returned from a subroutine will be available in a special variable called RESULT.

Example of receiving value from a subroutine:

/*******************************REXX *********************************/
/* This exec receives the maximum value between two numbers	         */
/* from a subroutine and displays that value.                        */
/*********************************************************************/

/* CALL AS INTERNAL SUBROUTINE */
NUM1 = 5
NUM2 = 2
CALL PERSUBR NUM1 NUM2
SAY 'PERIMETER IS : ' RESULT    /* DISPLAYED AS 20 */
EXIT 0

/* CALL AS INTERNAL USER-DEFINED FUNCTION */
PERSUBR:
ARG LEN WID
PER = 2*(LEN+WID)
RETURN PER

Summary:

  • A Subroutine is used as a common structure when the sequence of instructions is repeatedly used in a main program, which results in ease of use and understanding.

  • The subroutines are broadly classified as internal and external subroutines.

  • Internal subroutines are coded with in the current exec and external subroutines are coded outside the exec and are accessible by other execs as well.

  • Internal subroutines can share the variables used by main exec where as external subroutines cannot.

  • Both external and internal subroutines can receive the information through arguments.


If you have any doubts or queries related to this chapter, get them clarified from our Mainframe experts on ibmmainframer Community!

Are you looking for Job Change? Job Portal