Problem solve Get help with specific problems with your technologies, process and projects.

Taking advantage of CL advancements, starting with V5R3

Using the new CL programming tools released in V5R3 on the IBM System i has advantages: New looping methods, subroutines, and multiple file declarations. See examples of old versus new programs that ease and shorten programming commands.

Andrew Borts

When was the last time you wanted to write a subroutine in your CL program to cut down the amount of code you're writing? Or use a logic more complex then "IF/THEN/ELSE" within your CL program? When was the last time you wanted to loop through something without the use of GOTO's and IF's in the clunkiest use of code you've seen in a while. For me, it's daily. Who wants to clean up some code so our business rules and our code look related?

Starting in V5R3, there were significant changes to the organization of CL programming languages:

  • New looping methods
    • Until loop – DOUNTIL (ENDDO)
    • For loop – DOFOR (ENDDO)
    • While Loop – DOWHILE (ENDDO)
  • Logical end and restart of loops
    • ITERATE (same as RPG ITER)
    • LEAVE – (same as RPG LEAVE)
  • Multiple file declaration (V5R3)
    • RCVF for up to five files
    • Flow changes
    • SELECT when
  • Subroutines (V5R4)

Let me show you what you've been missing. In our old routines, we needed to group commands together using DO/ENDDO

             RCVF       OPNID(ID1)                  
/*           CPF0864     End of file detected for file &1 in &2.  */
             MONMSG     MSGID(CPF0864) EXEC(DO)     
             GOTO       CMDLBL(AGAIN)               

In a word: Yuck. What if this looked like this?

             DCLF       FILE(*LIBL/FILE1) OPNID(ID1)                
             DCL        VAR(&IMDONE) TYPE(*CHAR) LEN(1) VALUE('0')
             DOUNTIL    COND(&IMDONE *EQ '1')                       
             RCVF       OPNID(ID1)                                  
/*           CPF0864     End of file detected for file &1 in &2.  */
             MONMSG     MSGID(CPF0864) EXEC(LEAVE)                  
             CALL       PGM(MENEXT)                                 

Program flow is cleaned up. DOUNTIL checks the logic after the first iteration so we'll try and read the file, and leave the loop when the file is completed.

Controlling patterns using DOWHILE
You can control the patterns of your CL programs using DOWHILE as follows:

             DCLF       FILE(*LIBL/FILE1) OPNID(ID1)                      
             DCL        VAR(&FIL2FND) TYPE(*CHAR) LEN(1) VALUE('JHANCOCK')
             DCL        VAR(&FILEFND) TYPE(*CHAR) LEN(1) VALUE('1') 
             RTVOBJD    OBJ(&FILE2FND) OBJTYPE(*FILE)                     
             MONMSG     MSGID(CPF9801) EXEC(CHGVAR VAR(&FILE2FND) +       
             DOWHILE    COND(&FILEFND *EQ '1')                            
             RCVF       OPNID(ID1)                                        
             MONMSG     MSGID(CPF0864) EXEC(LEAVE)                        
             CALL       PGM(MENEXT)                                       

I'm never going to perform the loop unless JHANCOCK is found. Once I reach the end of file in all of these examples, I leave the loop. I can pop back up to the top of the loop if my logic requires me to start with, for example, the next record in the file.

Setting the number of loops
DOFOR is for looping a set amount of times, then falling out of the loop. Say if you need to do something 15 times:

             DOFOR      VAR(&CTR) FROM(1) TO(15) BY(1)               

The static values can be substituted for field names – from &FRM to &TO is a valid loop as well.

The examples I gave above also show how to uniquely identify up to five files – display or database files.

Using SELECT/WHEN/END/SELECT to clean up programs
So how many of our programs look like this?

             IF         COND(%SST(&FILENM 1 3) *EQ 'AAA') THEN(DO)
            GOTO       CMDLBL(LOOPTOP)                               
             ELSE       CMD(IF COND(%SST(&FILENM 1 3) *EQ 'BBB') +    
             GOTO       CMDLBL(ENDOFLOOP)                             

A little ugly. So we can clean it up:

             WHEN       COND(%SST(&FILENM 1 3) *EQ 'AAA') THEN(ITERATE)   
             WHEN       COND(%SST(&FILENM 1 3) *EQ 'BBB') THEN(LEAVE)     

The DO/ENDDO grouping of code above may be a bit exaggerated. But, you can see that using the SELECT/WHEN/ENDSELECT your code looks so much easier to understand.

Using CL subroutines
Subroutines clean up the code even more.

             WHEN       COND(%SST(&FILENM 1 3) *EQ 'AAA') +        
                          THEN(CALLSUBR SUBR(AAAFILE))             
             WHEN       COND(%SST(&FILENM 1 3) *EQ 'BBB') +        
                          THEN(CALLSUBR SUBR(BBBFILE))             
             SUBR       SUBR(AAAFILE)

You see that subroutine AAAFILE is called WHEN AAA is in the prefix of the field &FILENM. (%SST is the substring command.)

Using this technique, your code will clean up, and you'll be writing shorter and shorter CL programs in no time.

Dig Deeper on iSeries CL programming