Everything you need to know about Modular RPG Programming! – Part II

In the previous post, the surface of modular programming was scratched. In this post, we will move on to the next set of concepts that need to be considered.

  1. Dynamic and Static Binding.
  2. CALL Operation.
  3. Procedures and Subprocedures.

Dynamic and Static Binding

Dynamic Binding – Dynamic binding is simply the method by which a program, if it calls another program, goes looking for the called program at run time (i.e dynamically). The binding happens at run time.

The CALLP operation is also dynamic. The disadvantage of dynamic calls are that, if a program calls another program many number of times dynamically, the binding takes time and ultimately results in performance issues.

When IBM introduced ILE,  Static Binding – An option to connect RPG modules before run time was also introduced. An RPG module can be created by using the CRTRPGMOD CL command. A number of modules that need to interact with each other can be created using this command and an executable *PGM command can be created using the CRTPGM CL command and specify the names of the modules as parameters. When the program runs, the binding is already done. So performance does not take a hit.

It needs to be noted that a *MODULE object cannot be executed.

Another Static binding method is through the usage of Service Programs (Object type: *SRVPGM). There are several advantages of using a Service Program. I will discuss more on Service Programs in detail in a later part. Now we move on to the CALL operation.

CALL Operation

CALL is an opcode that can be used only with fixed format calculation specification. It passes control to the program object specified in Factor 2. Factor 2 can contain a literal containing the Program name or it can contain  a field name or an array element.

To pass parameters to the called program, when using the CALL opcode, either the PLIST opcode can be used or the parameters can be specified just below the CALL operation.

* This is a sample of a calling program. Notice how the PARMs follow the
* CALL without a PLIST operation.
C       CALL            'Prog2'
C       PARM            FldA
C       PARM            FldB
C       PARM            FldC

The code snippet above shows Prog2 being called without making use of PLIST. The parameters to be passed are mentioned directly below the CALL.

* This is a sample of a calling program. The PARMs appear in a PLIST,
* which is referenced in the CALL operation. The effect is identical
* to that of the preceding example.
C  PlistA  PLIST
C          PARM      FldA
C          PARM      FldB
C          PARM      FldC
. . .
C CALL    'Prog2'    PlistA

As was the case with the earlier call, the variables are passed by reference and not by value. So if the called program changes the values of any of the variables passed as arguments, the changes reflect in the calling program also.

CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....
* Example showing how to pass FldA's value to Prog1 without
* the possibility of FldA's value being changed by Prog1
C                       CALL                                   'Prog1'
C                       PARM          FldA                FldX

The above snippet shows how you can pass a variable value(value of FldA – specified in Factor 1) to a program as a parameter and ensure that the called program does not modify the value of the variable in the caller. The address of variable FldX (result field) will be passed to the called program. Hence only FldX value will be modified in the caller program if the called program makes any changes.

FldA variable value will remain unchanged, regardless of what is done in Prog2.

Procedures and Subprocedures

This is one of my favorite topics! Somehow I find the Procedure and subprocedure feature introduced by IBM highly interesting.

So the first question is how to write a Procedure? The specification for denoting a procedure is ‘P’.

Explaining the syntax with a code snippet would be the easiest way to understand a subprocedure.

// Module contains subprocedure only; no main procedure

H NOMAIN
// Procedure prototype
D Celsius    PR      3 0
D                    3 0

// Begin subprocedure
P Celsius    B       EXPORT

// Procedure interface
D PI                 3 0
D Fahrenheit         3 0

// Here is where variables local to the subprocedure are defined.

D Temperature S      3 0
/FREE
   EVAL(H) Temperature = (5/9) * (Fahrenheit - 32);
   RETURN Temperature;
/END-FREE

// End subprocedure
P Celsius  E 

The things to note about the above code are:

  • The control specification mentions NOMAIN – which means this is a standalone subprocedure without any main procedure
  • Note there is no EXTPGM keyword here. The EXTPGM keyword is always associated with a dynamic call. It can be never used in Static Binding.
  • The next part is the beginning of the Procedure body. Procedure boundaries are marked by making use of the ‘P’ specification.
  • ‘B’ is used to mark the beginning of the Procedure body and Export allows the subprocedure to be called by other modules within the program. The EXPORT keyword is specified so that other associated modules can call this procedure.
  • The end of the procedure is marked by another P specification and in between comes the code or logic of the procedure

With this we wrap up the second part of this post. The remaining concepts will be covered in the next part.


Leave a comment