In this section, we will delve into subroutines and procedures in Control Language (CL). Subroutines and procedures are essential for creating modular, reusable, and maintainable code. They allow you to break down complex tasks into smaller, manageable pieces.

What are Subroutines and Procedures?

  • Subroutines: A subroutine is a block of code that performs a specific task and can be called from different parts of a program. Subroutines help in reducing code duplication and improving readability.
  • Procedures: Procedures are similar to subroutines but are more formalized. They can accept parameters, return values, and are often used to encapsulate complex logic.

Defining a Subroutine

To define a subroutine in CL, you use the SUBR command. Here is a basic example:

PGM
    DCL VAR(&RESULT) TYPE(*DEC) LEN(5 0)
    CALLSUBR SUBR(MY_SUBROUTINE)
    SNDPGMMSG MSG('Result: ' *CAT &RESULT)
    ENDPGM

SUBR MY_SUBROUTINE
    DCL VAR(&A) TYPE(*DEC) LEN(5 0) VALUE(10)
    DCL VAR(&B) TYPE(*DEC) LEN(5 0) VALUE(20)
    CHGVAR VAR(&RESULT) VALUE(&A + &B)
    ENDSUBR

Explanation

  • PGM: Marks the beginning of the main program.
  • DCL: Declares a variable &RESULT to store the result.
  • CALLSUBR: Calls the subroutine MY_SUBROUTINE.
  • SNDPGMMSG: Sends a program message displaying the result.
  • ENDPGM: Marks the end of the main program.
  • SUBR: Defines the subroutine MY_SUBROUTINE.
  • CHGVAR: Changes the value of &RESULT to the sum of &A and &B.
  • ENDSUBR: Marks the end of the subroutine.

Defining a Procedure

Procedures in CL are defined using the PROC command. Here is an example:

PGM
    DCL VAR(&RESULT) TYPE(*DEC) LEN(5 0)
    CALLPROC PROC(MY_PROCEDURE) PARM(&RESULT)
    SNDPGMMSG MSG('Result: ' *CAT &RESULT)
    ENDPGM

PROC MY_PROCEDURE
    DCL VAR(&RESULT) TYPE(*DEC) LEN(5 0)
    DCL VAR(&A) TYPE(*DEC) LEN(5 0) VALUE(10)
    DCL VAR(&B) TYPE(*DEC) LEN(5 0) VALUE(20)
    CHGVAR VAR(&RESULT) VALUE(&A + &B)
    RETURN
ENDPROC

Explanation

  • PGM: Marks the beginning of the main program.
  • DCL: Declares a variable &RESULT to store the result.
  • CALLPROC: Calls the procedure MY_PROCEDURE and passes &RESULT as a parameter.
  • SNDPGMMSG: Sends a program message displaying the result.
  • ENDPGM: Marks the end of the main program.
  • PROC: Defines the procedure MY_PROCEDURE.
  • RETURN: Returns control to the calling program.
  • ENDPROC: Marks the end of the procedure.

Practical Exercise

Exercise 1: Create a Subroutine

  1. Write a CL program that defines a subroutine to calculate the factorial of a number.
  2. The main program should call the subroutine and display the result.
PGM
    DCL VAR(&NUMBER) TYPE(*DEC) LEN(5 0) VALUE(5)
    DCL VAR(&FACTORIAL) TYPE(*DEC) LEN(10 0)
    CALLSUBR SUBR(CALC_FACTORIAL)
    SNDPGMMSG MSG('Factorial: ' *CAT &FACTORIAL)
    ENDPGM

SUBR CALC_FACTORIAL
    DCL VAR(&I) TYPE(*DEC) LEN(5 0)
    DCL VAR(&RESULT) TYPE(*DEC) LEN(10 0) VALUE(1)
    FOR &I FROM(1) TO(&NUMBER) BY(1)
        CHGVAR VAR(&RESULT) VALUE(&RESULT * &I)
    ENDFOR
    CHGVAR VAR(&FACTORIAL) VALUE(&RESULT)
    ENDSUBR

Solution Explanation

  • FOR: Loop from 1 to the value of &NUMBER.
  • CHGVAR: Multiply &RESULT by the loop variable &I in each iteration.
  • ENDFOR: End of the loop.
  • CHGVAR: Assign the final result to &FACTORIAL.

Exercise 2: Create a Procedure

  1. Write a CL program that defines a procedure to check if a number is prime.
  2. The main program should call the procedure and display the result.
PGM
    DCL VAR(&NUMBER) TYPE(*DEC) LEN(5 0) VALUE(7)
    DCL VAR(&IS_PRIME) TYPE(*CHAR) LEN(3)
    CALLPROC PROC(CHECK_PRIME) PARM(&NUMBER &IS_PRIME)
    SNDPGMMSG MSG('Is Prime: ' *CAT &IS_PRIME)
    ENDPGM

PROC CHECK_PRIME
    DCL VAR(&NUMBER) TYPE(*DEC) LEN(5 0)
    DCL VAR(&IS_PRIME) TYPE(*CHAR) LEN(3)
    DCL VAR(&I) TYPE(*DEC) LEN(5 0)
    DCL VAR(&FLAG) TYPE(*CHAR) LEN(3) VALUE('YES')
    FOR &I FROM(2) TO(&NUMBER - 1) BY(1)
        IF COND(&NUMBER / &I * &I = &NUMBER) THEN(DO)
            CHGVAR VAR(&FLAG) VALUE('NO')
            LEAVE
        ENDDO
    ENDFOR
    CHGVAR VAR(&IS_PRIME) VALUE(&FLAG)
    RETURN
ENDPROC

Solution Explanation

  • FOR: Loop from 2 to &NUMBER - 1.
  • IF: Check if &NUMBER is divisible by &I.
  • CHGVAR: Set &FLAG to 'NO' if &NUMBER is not prime.
  • LEAVE: Exit the loop if a divisor is found.
  • CHGVAR: Assign the final result to &IS_PRIME.

Common Mistakes and Tips

  • Variable Scope: Ensure variables are declared in the correct scope. Variables declared inside a subroutine or procedure are local to that block.
  • Parameter Passing: When using procedures, ensure parameters are passed correctly and match the expected types and lengths.
  • Error Handling: Always include error handling to manage unexpected conditions gracefully.

Conclusion

In this section, we covered the basics of subroutines and procedures in CL. We learned how to define and call subroutines and procedures, and we practiced with exercises to reinforce these concepts. Understanding subroutines and procedures is crucial for writing modular and maintainable CL programs. In the next section, we will explore advanced file operations to further enhance your CL programming skills.

© Copyright 2024. All rights reserved