Using %PARMS

In this example, a procedure FMTADDR has been changed several times to allow for a change in the address information for the employees of a company. FMTADDR is called by three different procedures. The procedures differ only in the number of parameters they use to process the employee information. That is, new requirements for the FMTADDR have arisen, and to support them, new parameters have been added. However, old procedures calling FMTADDR are still supported and do not have to be changed or recompiled.

The changes to the employee address can be summarized as follows:
  • Initially only the street name and number were required because all employees lived in the same city. Thus, the city and province could be supplied by default.
  • At a later point, the company expanded, and so the city information became variable for some company-wide applications.
  • Further expansion resulted in variable province information.

The procedure processes the information based on the number of parameters passed. The number may vary from 3 to 5. The number tells the program whether to provide default city or province values or both. Figure 1 shows the source for this procedure. Figure 2 shows the source for /COPY member containing the prototype.

The main logic of FMTADDR is as follows:
  1. Check to see how many parameters were passed by using %PARMS. This built-in function returns the number of passed parameters.
    • If the number is greater than 4, then the default province is replaced with the actual province supplied by the fifth parameter P_Province.
    • If the number is greater than 3, then the default city is replaced with the actual city supplied by the fourth parameter P_City.
  2. Correct the street number for printing using the subroutine GetStreet#.
  3. Concatenate the complete address.
  4. Return.
Figure 1. Source for procedure FMTADDR
      *=================================================================*
      * FMTADDR - format an address
      *
      * Interface parameters
      * 1. Address       character(70)
      * 2. Street number packed(5,0)
      * 3. Street name   character(20)
      * 4. City          character(15)   (some callers do not pass)
      * 5. Province      character(15)   (some callers do not pass)
      *=================================================================*
      * Pull in the prototype from the /COPY member
      /COPY  FMTADDRP
     DFmtAddr          PI
     D Address                       70
     D Street#                        5  0 CONST
     D Street                        20    CONST
     D P_City                        15    OPTIONS(*NOPASS) CONST
     D P_Province                    15    OPTIONS(*NOPASS) CONST
      *-----------------------------------------------------------------*
      * Default values for parameters that might not be passed.
      *-----------------------------------------------------------------*
     D City            S             15    INZ('Toronto')
     D Province        S             15    INZ('Ontario')
      *-----------------------------------------------------------------*
      * Check whether the province parameter was passed.  If it was,
      * replace the default with the parameter value.
      *-----------------------------------------------------------------*
     C                   IF        %PARMS > 4
     C                   EVAL      Province = P_Province
     C                   ENDIF
      *-----------------------------------------------------------------*
      * Check whether the city parameter was passed.  If it was,        *
      * replace the default with the parameter value.                   *
      *-----------------------------------------------------------------*
     C                   IF        %PARMS > 3
     C                   EVAL      City = P_City
     C                   ENDIF
      *-----------------------------------------------------------------*
      * Set 'CStreet#' to be character form of 'Street#'                *
      *-----------------------------------------------------------------*
     C                   EXSR      GetStreet#
      *-----------------------------------------------------------------*
      * Format the address as    Number Street, City, Province          *
      *-----------------------------------------------------------------*
     C           EVAL     ADDRESS = %TRIMR(CSTREET#) + ' ' +
     C                              %TRIMR(CITY) + ' ,' +
     C                              %TRIMR(PROVINCE)
     C                   RETURN
      *=================================================================*
      * SUBROUTINE: GetStreet#
      * Get the character form of the street number, left-adjusted      *
      * and padded on the right with blanks.                            *
      *=================================================================*
     C     GetStreet#    BEGSR
     C                   MOVEL     Street#       CStreet#         10
      *-----------------------------------------------------------------*
      * Find the first non-zero.                                        *
      *-----------------------------------------------------------------*
     C     '0'           CHECK     CStreet#      Non0              5 0
      *-----------------------------------------------------------------*
      * If there was a non-zero, substring the number starting at       *
      * non-zero.                                                       *
      *-----------------------------------------------------------------*
     C                   IF        Non0 > 0
     C                   SUBST(P)  CStreet#:Non0 CStreet#
      *-----------------------------------------------------------------*
      * If there was no non-zero, just use '0' as the street number.    *
      *-----------------------------------------------------------------*
     C                   ELSE
     C                   MOVEL(P)  '0'           CStreet#
     C                   ENDIF
     C                   ENDSR
Figure 2. Source for /COPY member with Prototype for Procedure FMTADDR
      *=================================================================*
      * Prototype for FMTADDR - format an address
      *=================================================================*
     DFmtAddr          PR
     D  addr                         70
     D  strno                         5  0 CONST
     D  st                           20    CONST
     D  cty                          15    OPTIONS(*NOPASS) CONST
     D  prov                         15    OPTIONS(*NOPASS) CONST

Figure 3 shows the source for the procedure PRTADDR. This procedure serves to illustrate the use of FMTADDR. For convenience, the three procedures which would each call FMTADDR are combined into this single procedure. Also, for the purposes of the example, the data is program-described.

Since PRTADDR is 'three procedures-in-one', it must define three different address data structures. Similarly, there are three parts in the calculation specifications, each one corresponding to programs at each stage. After printing the address, the procedure PRTADDR ends.

Figure 3. Source for procedure PRTADDR
      *=================================================================*
      * PRTADDR - Print an address
      *           Calls FmtAddr to format the address
      *=================================================================*
     FQSYSPRT   O    F   80        PRINTER
      *-----------------------------------------------------------------*
      * Prototype for FmtAddr
      *-----------------------------------------------------------------*
     DFmtAddr          PR
     D  addr                         70
     D  strno                         5  0
     D  st                           20
     D  cty                          15    OPTIONS(*NOPASS)
     D  prov                         15    OPTIONS(*NOPASS)
     DAddress          S             70
      *-----------------------------------------------------------------*
      * Stage1: Original address data structure.
      * Only street and number are variable information.
      *-----------------------------------------------------------------*
     D Stage1          DS
     D   Street#1                     5P 0 DIM(2) CTDATA
     D   StreetNam1                  20    DIM(2) ALT(Street#1)
      *-----------------------------------------------------------------*
      * Stage2: Revised address data structure as city information
      * now variable.
      *-----------------------------------------------------------------*
     D Stage2          DS
     D   Street#2                     5P 0 DIM(2) CTDATA
     D   Addr2                       35    DIM(2) ALT(Street#2)
     D     StreetNam2                20    OVERLAY(Addr2:1)
     D     City2                     15    OVERLAY(Addr2:21)
      *-----------------------------------------------------------------*
      * Stage3: Revised address data structure as provincial
      * information now variable.
      *-----------------------------------------------------------------*
     D Stage3          DS
     D   Street#3                     5P 0 DIM(2) CTDATA
     D   Addr3                       50    DIM(2) ALT(Street#3)
     D     StreetNam3                20    OVERLAY(Addr3:1)
     D     City3                     15    OVERLAY(Addr3:21)
     D     Province3                 15    OVERLAY(Addr3:36)
      *-----------------------------------------------------------------*
      * 'Program 1'- Use of FMTADDR before city parameter was added.
      *-----------------------------------------------------------------*
     C                   DO        2             X                 5 0
     C                   CALLP     FMTADDR (Address:Street#1(X):StreetNam1(X))
     C                   EXCEPT
     C                   ENDDO
      *-----------------------------------------------------------------*
      * 'Program 2'- Use of FMTADDR before province parameter was added.*
      *-----------------------------------------------------------------*
     C                   DO        2             X                 5 0
     C                   CALLP     FMTADDR (Address:Street#2(X):
     C                             StreetNam2(X):City2(X))
     C                   EXCEPT
     C                   ENDDO
      *-----------------------------------------------------------------*
      * 'Program 3' - Use of FMTADDR after province parameter was added.*
      *-----------------------------------------------------------------*
     C                   DO        2             X                 5 0
     C                   CALLP     FMTADDR (Address:Street#3(X):
     C                             StreetNam3(X):City3(X):Province3(X))
     C                   EXCEPT
     C                   ENDDO
     C                   SETON                                        LR
      *-----------------------------------------------------------------*
      * Print the address.                                              *
      *-----------------------------------------------------------------*
     OQSYSPRT   E
     O                       Address
**
00123Bumble Bee Drive
01243Hummingbird Lane
**
00003Cowslip Street      Toronto
01150Eglinton Avenue     North York
**
00012Jasper Avenue       Edmonton       Alberta
00027Avenue Road         Sudbury        Ontario
To create these programs, follow these steps:
  1. To create FMTADDR, using the source in Figure 1, type:
    CRTRPGMOD MODULE(MYLIB/FMTADDR)
  2. To create PRTADDR, using the source in Figure 3, type:
    CRTRPGMOD MODULE(MYLIB/PRTADDR)
  3. To create the program, PRTADDR, type:
    CRTPGM PGM(MYLIB/PRTADDR) MODULE(PRTADDR FMTADDR)
  4. Call PRTADDR. The output is shown below:
    123 Bumble Bee Drive, Toronto, Ontario
    1243 Hummingbird Lane, Toronto, Ontario
    3 Cowslip Street, Toronto, Ontario
    1150 Eglinton Avenue, North York, Ontario
    12 Jasper Avenue, Edmonton, Alberta
    27 Avenue Road, Sudbury, Ontario