The CASE structure is used to control sections of the program. CASE offers greater readability than IF-THEN-ELSE when a high level of nesting is required or when the control structure is controlling several dozen lines of code. This is, in part, due to the inherent nature of CASE to separate the logic from the processes.

RPG supports both in-line and subroutine forms of CASE. The CASxx operation performs subroutines while the SELECT-WHEN-OTHER operations perform in-line code. The Boolean operators for CASxx and WHEN operations are the same as those listed in Table 8.3. The CASE operations are considered choice constructs. Figure 8.11 shows the logic flow for the CASE structure.

click to expand
Figure 8.11: The two forms of CASE.

The primary difference between the two forms of CASE (shown in Figure 8.11) is that the logic flow illustrated to the right includes a default process and the logic flow to the left has no default process.

In Example 8.6, the WHEN operations, like the IF-ELSE-ENDIF operations, can be difficult to distinguish from the other operations. This can force the programmer to interpret each line of code (i.e., the process) even if all that is needed is to check the logic (i.e., choice) of the program.

Example 8.6: In-line CASE using SELECT/WHENxx/OTHER.

start example
     C                   Select
     C                   When      FieldA = FieldB
     C                   Eval      Answer = 'A = B'
     C                   Add       A             B
     C                   Div       Cost          MARKUP
     C                   When      FieldA > FieldB
     C                   Eval      Answer = 'A > B'
     C                   Sub       A             B
     C                   Div       Cost          PRICE
     C                   When      FieldA < FieldB
     C                   Eval      Answer = 'A < B'
     C                   Eval      MarkUp = Price - Cost
     C                   If        MarkUp  0
     C                   Div       MarkUp        PRICE
     C                   endIf
     C                   When      FieldA  FieldB
      *                        *** This WHEN block would never run
     C                   Eval      Answer = 'A B'
     C                   Add       MarkUp       YTDProfit
     C                   endSl
end example

Complex or multiple conditions, such as those illustrated in Example 8.6, are necessary from time to time. In-line CASE statements can add power to the application. When the in-line CASE gets too complex, however, its power tends to be offset by complexity. At this point, it is important to consider using the CASxx operation or a WHEN-EXSR operation set.

The form of CASE shown in Example 8.7 can provide an alternative to the standard in-line form of CASE (i.e., SELECT-WHEN-OTHER-ENDSL) logic. This form takes advantage of the SELECT-WHEN constructs while placing the process within subroutines or subprocedures.

Example 8.7: The SELECT-WHEN-EXSR-CALLP form of case.

start example

click to expand

end example

The traditional form of CASE, using the CASxx operation, was often used in place of the technique illustrated in Example 8.7. Example 8.7 contains the much simpler CASxx structure. The logic flow of the program is the same as in Example 8.6. Example 8.8, however, allows the programmer to concentrate on the logic (i.e., choice) of the program.

Example 8.8: The subroutine CASxx operation.

start example
     C     FieldA        casEQ     FieldB        Equal
     C     FieldA        casGT     FieldB        Greater
     C     FieldA        casLT     FieldB        LessThan
     C     FieldA        casNE     FieldB        NotEqual
     C                   endCS
end example

In Example 8.9, the field named FUNCT (Function) is compared to the literal 'DELETE' on line 1. The CASEQ operation is used to test for the equal condition. If the test is true (i.e., FUNCT equals 'DELETE'), the subroutine DELETERCD (Delete a Record) is performed.

Example 8.9: A basic CASE structure.

start example
 0001 C     Funct         casEQ     'DELETE'      DeleteRcd
 0002 C                   endCS
     C*.....the program continues...

 0003 Csr   DeleteRcd     BEGSR
 0004 C     Index         Delete    CUSTMAST                             56
 0005 Csr                 endSR
end example

Upon completion of the subroutine DLTRCD, control returns to the END statement associated with the CASE structure (line 2 in Example 8.9). The next successive operation is performed as the program continues.

Successive CASE Operations

As mentioned earlier, CASE is the preferred control structure for choice constructs. Successive CASE structures are easy to read and understand. They support top-down program design by allowing the programmer to concentrate on the logic of the program (i.e., the logic modules) until the detail (i.e., the function modules) must be written. See Figure 8.13, for example, if the design of a routine calls for the type of code shown in Figure 8.12.

start figure

   PROMPT the workstation operator for the FUNCTION request.
   READ the Operator's RESPONSE.
   PARSE the Operator's RESPONSE.
   BUILD the requested FUNCTION.
   IF FUNCTION equals 'DELETE' then
      Perform the DELETE-RECORD routine.
   ELSE, IF FUNCTION equals 'UPDATE' then
      Perform the UPDATE-RECORD routine.
   ELSE, IF FUNCTION equals 'ADDNEW' then
      Perform the ADD-RECORD routine.
   ELSE, IF FUNCTION equals 'SEARCH' then
      Perform the SEARCH routine.
   ELSE, IF FUNCTION equals 'EXIT' then
      Perform the END-PROGRAM routine.
   ELSE, perform the DEFAULT handler.

end figure

Figure 8.12: Successive CASE operations sample code.

The RPG code that supports the design shown in Figure 8.12 is featured in Figure 8.13.

start figure

 0001 C                   Dou       Funct = 'EXIT'
      * Prompt the workstation operator for a response.
 0002 C                   Exsr      Prompt
      * Parse (interpret) the Operator's response.
 0003 C                   EXSR      Parse
      * Finish up the PARSE by converting the request to FUNCT.
 0004 C                   EXSR      BuildFunct
     ** Select the subroutine when the relationship is met.
 0005 C                   SELECT
 0006 C                   When      Funct = 'DELETE'
 0007 C                   CallP     DeleteRcd
 0008 C                   When      Funct = 'UPDATE'
 0009 C                   CallP     UpdateRcd
 0010 C                   When      Funct = 'ADDNEW'
 0011 C                   CallP     AddRcd
 0012 C                   When      Funct = 'SEARCH'
 0013 C                   CallP     SearchFile
 0014 C                   When      Funct = 'EXIT'
 0015 C                   CallP     EndProc
 0016 C                   Other
 0017 C                   Exsr      DefaultRtn
 0018 C                   endSL
 0019 C                   endDo

end figure

Figure 8.13: CASE-controlled logic module.

As shown in Figure 8.13, the CASE structure makes this logic control module easy to read and comprehend. On the other hand, if an IF-THEN-ELSE structure is used, it could lead to a much more complex module.

Upon entry into the CASE structure, the relationship between the field FUNCT and the constant 'DELETE' is performed. If the relationship is true, the subroutine DLTRCD is performed. Upon completion of the subroutine DLTRCD, control passes to the END statement associated with the CASE structure.

If the relationship test on line 6 is false, control passes to the WHEN operation on line 6. If that relationship test is true, the subroutine UPDRCD is performed. Upon completion of the subroutine, control passes to the CASE structure ENDSL statement on line 18.

This process is repeated for each CASE structure in this CASE group. If none of the CASE comparisons are true, the "catch all" OTHER (otherwise) operation on line 16 performs the subroutine DFTRTN.

Compare and Branch Operations

The CABxx (Compare and Branch) operation is unique to the RPG language. It differs from the CASxx operation in that the CASxx operation performs a subroutine and returns to the same point in the program. The CABxx operation branches to a label and does not return.

The CABxx operation supports the complete set of Boolean operators listed in Table 8.3. When the relationship test is true, a branch to the label specified in the result field is performed. When the relationship test is false, the program continues with the next successive instruction following the CABxx operation. If resulting indicators are specified, they are set on accordingly—regardless of the Boolean operator used with the operation.

Other RPG operations are required to provide a target for the CABxx operation. The TAG and ENDSR operation provide this function. Table 8.4 lists the RPG operations that support branching.

Table 8.4: RPG Branching Operations




Compare and branch.


Go to (i.e., branch to) a label identified by a TAG or ENDSR operation.


End subroutine. Factor 1 can contain a label that can be used as the target of a CABxx or GOTO operation.


Label. Factor 1 contains a label that can be used as the target of a CABxx or GOTO operation.


Iterate a DO loop. Branch to the top of the DO loop for the next iteration.


Exit a DO loop. Branch to the corresponding ENDDO statement of a DO loop.


Exit subroutine. Branch to the ENDSR statement of the current subroutine.

The CABxx operation should be used primarily as an escape clause in order to branch to an exit routine or to the end of a subroutine or program. Never use CABxx or GOTO to exit a subroutine. Branching to a label on the ENDSR operation is acceptable, however.

The GOTO operation should be avoided as much as possible. Actually, many programming shops have standards and conventions that prohibit the use of GOTO. The GOTO operation is an unconditional branch to another location of the RPG program.

The ENDSR and TAG operations are declarative operations that identify a label to the RPG program. A label is the target of a CABxx or GOTO operation. The content of factor 1 is used as the label of the TAG operation.

The ITER (iterate) operation causes control of a DO loop (DO, DOW, or DOU) to be transferred to the top of the DO loop. The next iteration of the DO loop is evoked. Condition the ITER operation, when necessary, with an IF statement.

The LEAVE operation causes control of a DO loop (DO, DOW, or DOU) to be terminated. In other words, the program branches to the corresponding ENDDO statement. This operation can be considered an "Exit DO Loop" operation. Condition the LEAVE operation, when necessary, with an IF statement.

The LEAVESR operation causes a branch to the ENDSR operation for the current subroutine. This, in turn, causes the subroutine to return.