Saturday, January 4, 2014

CL does DO.

CL does DO
Two of the Command Language, CL, commands added to IBM i (AS400) release 5.3 were theDOWHILE and DOUNTIL, and OS i (OS400) 6.1 brought us the DOFOR. I have always wanted DO commands as I have resented not being able to write "structure code" in CL as I had to use theGOTO command to create a loop.
I quickly adopted the DOWHILE into my programming, but I have been surprised that, despite bringing it to their attention, that only one of my colleagues uses it. Which is one of the reasons I wanted to create this post to make sure others are aware of them.
Prior to using these command if I wanted to read a file in a CL I had to do something like:
01         PGM
02
03         DCLF   FILE(QTEMP/WRKFILE) OPNID(A)
04
05  LOOP:  RCVF   OPNID(A)
06         MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ENDLOOP))
07
08         IF     COND(&A_STATUS *NE 'A') +
09                   THEN(GOTO CMDLBL(LOOP))
10
11  ENDLOOP:
12
13         ENDPGM
Why do I do that?   I always use the OPNID parameter on the Declare File,DCLF, command (line 3) to make it easier to understand which of the fields come from the file (see line 8).
Now my code can look like this:
010         PGM
02
03         DCL     VAR(&LOOP) TYPE(*LGL) VALUE('1')
04         DCLF    FILE(QTEMP/WRKFILE) OPNID(A)
05
06         DOWHILE COND(&LOOP)
07            RCVF OPNID(A)
08            MONMSG MSGID(CPF0000) EXEC(LEAVE)
09
10            IF COND(&A_STATUS *NE 'A') THEN(ITERATE)
11
12
13         ENDDO
14
15         ENDPGM
Notice that the DOWHILE is conditioned by the field &LOOP, which a Logic type field, and providing it is "on" it will loop.
This code shows two other new CL commands, ITERATE and LEAVE. I am sure you are fully familiar with them in RPGLE, but there is one extra feature they have in CL that I will mention at the bottom of this post.
Why do I do that?   I indent my code, which, in my opinion, makes it easier for someone else to read and understand.
If I need to perform a section of code a number of times I would have done something like this:
01              PGM
02
03         DCL    VAR(&COUNT) TYPE(*DEC) LEN(2 0) VALUE(1)
04
05 LOOP:
06
07
08         CHGVAR VAR(&COUNT) VALUE(&COUNT + 1)
09         IF     COND(&COUNT <= 10) +
10                   THEN(GOTO CMDLBL(LOOP))
11         ENDPGM
If I used the DOUNTIL command I can do this:
01         PGM
02
03         DCL    VAR(&COUNT) TYPE(*DEC) LEN(2 0) VALUE(1)
04                                                       
05         DOUNTIL COND(&COUNT > 10)              
06
07
08            CHGVAR VAR(&COUNT) VALUE(&COUNT + 1)
09         ENDDO
10
11         ENDPGM
With the introduction of the DOFOR I use it instead:
01         PGM
02
03         DCL     VAR(&COUNT) TYPE(*INT) LEN(2)
04
05         DOFOR   VAR(&COUNT) FROM(1) TO(10)
06
07
08         ENDDO
09
10         ENDPGM
Notice that te &COUNT field has to be defined as a integer, *INT.
The DOFOR works in the same way as the FOR operation code in RPGLE. It initializes the &COUNT field with the value of 1, FROM parameter. Each time it is executed it increments the &COUNT field by 1. When it reaches 10, parameterTO, it executes the DO one more time then leaves. If you want to increment&COUNT by more than one you can use the BY parameter to give the value by which it will be incremented.
Now what is that extra featrure I mentioned that the ITERATE and LEAVE has?
01            PGM
02
03            DCL      VAR(&LOOP) TYPE(*LGL) VALUE('1')
04            DCL      VAR(&COUNT) TYPE(*INT) LEN(2)
05            DCL      VAR(&FLG) TYPE(*CHAR) LEN(1)
06
07 LOOP1:     DOWHILE  COND(&LOOP)
08 LOOP2:        DOFOR    VAR(&COUNT) FROM(1) TO(10)
09
10                  IF   COND(&FLG = '2') +
11                          THEN(ITERATE CMDLBL(LOOP2))
12
13                  LEAVE   CMDLBL(LOOP1)
14               ENDDO
15            ENDDO
16
17            ENDPGM
Both ITERATE and LEAVE have the parameter CMDLBL. In the example below when the ITERATE is executed, on line 11, it iterates to the DO with that command label, in this case the first one, DOWHLE exiting the DOFOR. The LEAVE, on line 13, will leave both the DOFOR and DOWHILE.

I have tested this with program created from both CLP and CLLE source members, and it works in both.
You can learn more about the following commands from the IBM website:

No comments:

Post a Comment