Wednesday, May 22, 2019

Using Check BiFs in CL

check and check bifs in cl

It has been several been several months since I last wrote a post about CL programming, therefore, I thought it would be a good excuse to share something I was using in a CL program I wrote a couple or so weeks ago. I am sure many have used the Check, %CHECK, and the Check reverse, %CHECKR build in functions, BiFs, in RPG to check a character string for the first place a certain character(s) is not. In the CL program I was writing I needed the same functionality.

IBM has been adding BiFs to CL that are similar to the ones to be found in RPG. Fortunately there are %CHECK and %CHECKR BiFs in CL too. The general format of them is similar to the RPG equivalent:

%CHECK(<test values> <variable> <starting position>)

%CHECKR(<test values> <variable> <starting position>)

I found I could use these BiFs in my CL in two ways:

  1. Return the first position in the string where a character is not in the test values.
  2. Send a message to inform the user that the string contains an invalid character.

Let me jump into examples.

01  PGM

02  DCL VAR(&POS) TYPE(*UINT) LEN(2)
03  DCL VAR(&POS2) TYPE(*UINT) LEN(4)
04  DCL VAR(&VALUES1) TYPE(*CHAR) LEN(10) VALUE('0123456789')
05  DCL VAR(&VALUES2) TYPE(*CHAR) LEN(11) VALUE('0123456789 ')
06  DCL VAR(&VAR1) TYPE(*CHAR) LEN(15)

I wanted to show the variable declarations to explain what they are before I start showing the BiF examples.

Lines 2 and 3: If you have not seen the *UINT data type it defines the variable as an unsigned integer decimal variable.

Lines 3 and 4: This are the test values I will be using with the BiFs. They are different sizes as &VALUES2 contains the numbers 0 – 9 and the value blank, while &VALUE1 just contains 0 - 9. We will see later what difference this makes.

First example:

07  CHGVAR VAR(&VAR1) VALUE('123-456-789')
08  CHGVAR VAR(&POS) VALUE(%CHECK(&VALUES1 &VAR1))

After these two lines have executed the variable &POS will contain 4, as the hyphen is not in the list of values in &VALUES1.

I can modify this to return a message to the user:

09  IF COND(%CHECK(&VALUES1 &VAR1) *NE 0) +
         THEN(SNDPGMMSG MSG('Invalid character in string 1'))
10  ELSE CMD(SNDPGMMSG MSG('Characters in string 1 are valid'))

In this scenario as &VAR contains a character that is not in &VALUES, therefore, line 9 is executed and the message "Invalid character in string 1" is sent to the program message queue.

This next example shows the difference between using &VALUES1 and &VALUES2.

11  CHGVAR VAR(&VAR1) VALUE('123456789')
12  CHGVAR VAR(&POS) VALUE(%CHECK(&VALUES1 &VAR1))

13  CHGVAR VAR(&VAR1) VALUE('123456789')
14  CHGVAR VAR(&POS) VALUE(%CHECK(&VALUES2 &VAR1))

After line 12 is executed &POS = 10. Variable &VAR is 15 long, therefore, after the values 1 - 9 there are blanks. Blank is not in the list of values in &VALUES1.

After line 14 is executed &POS = 0, as blank is in the list of values in &VALUES2.

This is something to be mindful of when using these BiFs in both CL and RPG.

15  CHGVAR VAR(&VAR1) VALUE('X123456789')
16  CHGVAR VAR(&POS) VALUE(%CHECK(&VALUES2 &VAR1 2))

In this example &POS = 0, as the Check starts in the second position of the string which is after the "X" in the first position.

In all the previous examples I have used a variable to contain the list of test values. I can just as well put code the allowed values into the statement like:

17  CHGVAR VAR(&VAR1) VALUE('A B C D E F')        
18  CHGVAR VAR(&POS) VALUE(%CHECK('ABCDEF' &VAR1))
19  CHGVAR VAR(&POS) VALUE(%CHECKR(' ' &VAR1))

Line 18: &POS = 2 as that is the first place that the character in the string does not contain one of the values in the test values.

Line 19: As this is a Check reverse &POS = 11 as this is the first position, checking in reverse, that does not contain a blank.

I can use the %CHECKR to determine the length of the string:

20  IF COND(%CHECKR(' ' &VAR1) *LT 11) +
         THEN(SNDPGMMSG MSG('Character string is too short'))
21  ELSE CMD(SNDPGMMSG MSG('Character string is just right'))

In this case the message "Character string is just right" is sent to the program message queue as the first non-blank character is in the 11th position of &VAR1.

One thing the CL versions of %CHECK and %CHECKR, that the RPG equivalents cannot, is to directly check the Local Data Area:

22  CHGDTAARA DTAARA(*LDA (500 3)) VALUE('ABC')
23  CHGVAR VAR(&POS2) VALUE(%CHECK(' ' *LDA))
24  CHGVAR VAR(&POS2) VALUE(%CHECKR(' ' *LDA))

Line 23: &POS = 500.

Line 24: &POS = 502.

 

In my CL program I used these BiFs to determine the length of a string in a screen variable to determine if it was too short for the program's specifications.

 

You can learn more about this from the IBM website:

 

This article was written for IBM i 7.3, and should work for some earlier releases too.

No comments:

Post a Comment

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.