Prototyped Calls

To call a subprocedure, you must use a prototyped call. You can also call any program or procedure that is written in any language in this way. A prototyped call is one where the call interface is checked at compile time through the use of a prototype. A prototype is a definition of the call interface. It includes the following information:
  • Whether the call is bound (procedure) or dynamic (program)
  • How to find the program or procedure (the external name)
  • The number and nature of the parameters
  • Which parameters must be passed, and which are optionally passed
  • Whether operational descriptors are passed (for a procedure)
  • The data type of the return value, if any (for a procedure)

The prototype is used by the compiler to call the program or procedure correctly, and to ensure that the caller passes the correct parameters. Figure 1 shows a prototype for a procedure FmtCust, which formats various fields of a record into readable form. It has two output parameters.

Figure 1. Prototype for FmtCust Procedure
      // Prototype for procedure FmtCust  (Note the PR on definition
      // specification.)  It has two output parameters.
     D FmtCust         PR
     D  Name                        100A
     D  Address                     100A

To format an address, the application calls a procedure FmtAddr. FmtAddr has several input parameters, and returns a varying character field. Figure 2 shows the prototype for FmtAddr.

Figure 2. Prototype for FmtAddr Procedure
      //---------------------------------------------------------
      // FmtAddr - procedure to produce an address in the form
      //---------------------------------------------------------
     D FmtAddr         PR           100A     VARYING
     D   streetNum                   10I 0   CONST
     D   streetName                  50A     CONST
     D   city                        20A     CONST
     D   state                       15A     CONST
     D   zip                          5P 0   CONST

If the procedure is coded in the same module as the call, specifying the prototype is optional. If the prototype is not specified, the compiler will generate the prototype from the procedure interface. However, if the procedure is exported and it is also called from another RPG module or program, a prototype should be specified in a copy file, and the copy file should be copied into both the calling module and the module that is exporting the procedure.

If the program or procedure is prototyped, you call it with CALLP or within an expression if you want to use the return value. You pass parameters in a list that follows the name of the prototype, for example, name (parm1 : parm2 : …).

Figure 3 shows a call to FmtCust. Note that the names of the output parameters, shown above in Figure 1, do not match those in the call statement. The parameter names in a prototype are for documentation purposes only. The prototype serves to describe the attributes of the call interface. The actual definition of call parameters takes place inside the procedure itself.

Figure 3. Calling the FmtCust Procedure
     C                   CALLP     FmtCust(RPTNAME : RPTADDR)
Using prototyped calls you can call (with the same syntax):
  • Programs that are on the system at run time
  • Exported procedures in other modules or service programs that are bound in the same program or service program
  • Subprocedures in the same module

FmtCust calls FmtAddr to format the address. Because FmtCust wants to use the return value, the call to FmtAddr is made in an expression. Figure 4 shows the call.

Figure 4. Calling the FmtAddr Procedure
        //--------------------------------------------------------------
        // Call the FmtAddr procedure to handle the address
        //--------------------------------------------------------------
        Address = FmtAddress (STREETNUM : STREETNAME :
                              CITY : STATE : ZIP);
The use of procedures to return values, as in the above figure, allows you to write any user-defined function you require. In addition, the use of a prototyped call interface enables a number of options for parameter passing.
  • Prototyped parameters can be passed in several ways: by reference, by value (for procedures only), or by read-only reference. The default method for RPG is to pass by reference. However, passing by value or by read-only reference gives you more options for passing parameters.
  • If the prototype indicates that it is allowed for a given parameter, you may be able to do one or more of the following:
    • Pass *OMIT
    • Leave out a parameter entirely
    • Pass a shorter parameter than is specified (for character and graphic parameters, and for array parameters)