Prototyping and passing parameters in ILE RPG

The intent of this article is to explain prototype parameters and procedure interface specifications in a basic, straight-forward fashion. You probably already know that the ILE RPG programmer can not determine if a program passes parameters based simply by searching the source for a *ENTRY PLIST statement.

Prototyping is a more accommodating, extensible method for passing parameters but is more than just a replacement for *ENTRY PLIST. Prototyping adds functionality and flexibility.

First, the calling program will need prototype specifications coded. Naturally this is ideal situation to use a copy source member or "copy book" since the chances are good that you will want to reuse this prototype in other programs. A common example is to create a prototype for QCMDEXC and /copy it.

For a basic example, first look at the 'PR' specifications (the prototype looks similar to D spec data structures). These lines provide a place to specify a different name other than the actual program (by specifying EXTPGM) or procedure (using EXTPROC). This allows giving the program or procedure a more meaningful name.  In this example the actual program 'PRGXYZ1' can be referred to as "CustomerInquiry".  Next we need to define some parameters but keep in mind that at this point we are only concerned about the definition (type, size) of the field and not so concerned about the fields name:

   D CustomerInquiry  PR               EXTPGM('PRGXYZ1')
   D   parm1                         5 
   D   parm2                        12 


The prototype specifications must also be present in the called program. Since the prototype code is just duplicated remember; use the copy book! Additionally, 'PI' procedure interface specifications must be coded in the called program;

   D CustomerInquiry   PI
   D   CCompany                      5 
   D   CCustomer                    12 


The newly defined parameters can be used on CALL, CALLB, and CALLP statements;

  C          CALLP CustomerInquiry PARM(CCompany:CCustomer)

As you know the free format code would be similar but the opcode 'CALLP' is optional. CALLP is a call to a prototyped program or procedure.

/free
   CustomerInquiry (CCompany:CCustomer);
/end-free

Before prototypes were introduced parameters were passed "by reference" meaning a pointer is used instead of the actual field. Now there are options available that help you determine how the variables are to be handled. Of particular value, a parameter can be coded as a constant (Const) or "read-only" where the called program can not change the value in the field.

Here are some Options examples (but keep in mind the PR and PI parameter options must match);

   D CustomerInquiry  PR                EXTPGM('PRGXYZ1')
   D   parm1                        5   Const
   D   parm2                       12   Const

   D   parm3                       36   Const Options(*VarSize)
   D   parm4                            Like(OtherField)Value
   D   parm5                            LikeDS(MyDS) Options(*OMIT)
   D   parm6                        1   Const Options(*NOPASS)

The *OMIT option means that *OMIT can literally be used in the CALL statement instead of the parameter name and %parms will include these parms. The *NOPASS option means the parameter is optional but the field must either be the last field defined in the prototype or every field following this one must also be defined as *NOPASS. A field can be passed 'by value' (actual value) instead of 'by reference' (pointer) by using the Value option. Fields and arrays can be defined with LIKE and LIKEDS.

At times it is necessary to determine how many parameters are being passed and the built-in function (BIF) %parms can be used for this purpose. The older method of coding a system data structure SDS with the *PARMS field still works but is no longer necessary nor is it preferable going forward.

/free
   if %parms > 2 and %addr(parm3)<>*NULL
    parm3=%trimr(parm3)
   endif
/end-free

Obviously care must be used when defining parameters especially if they are used merged via a /copy statement. All programs that use the prototyped parameters and procedure interface specifications must be considered for compatibility with the parameter definitions.