Starting in IBM i 7.4 it is possible to use CL Built in Functions, BiF, in the parameters of CL's Call command. This becomes even easier when I use the additional parameters in the Parameter parameters of the CALL command.
Those of you who have seen example of my RPG code have seen examples where I have used BiFs in its Call operation code parameters. When I learned that there was now similar functionality in CL I became very curious what could I do with it.
I chosen a number of scenarios to write examples for, as these are things I have done many times with RPG's Call operation code.
- Remove leading blanks from a string when passed to another program.
- Convert character to numeric.
- Pass the length of a variable passed to the same program.
- Substring part of a larger string and passed that to the called program.
I am sure there are other scenarios that have sprung to your mind. These were just the ones that came to mine.
In all of the examples the calling program calls a CL program called TESTCL, which just produces a program dump. I can then look in the program dump's spool file, QPPGMDMP, to see how the passed value was interpreted by the called program.
My first scenario was to remove the leading blank characters from a string before I pass it to the called program.
01 DCL VAR(&CHAR) TYPE(*CHAR) LEN(30) 02 CHGVAR VAR(&CHAR) VALUE(' Text starts here') 03 CALL PGM(TESTCL) PARM((%TRIML(&CHAR))) |
The Calling program just has these three lines:
Line 1: Define the variable that will contain the string.
Line 2: Populate the variable with a string, with leading blank characters.
Line 3: Call TESTCL, using just one parameter. Within the definition of that parameter I have used the Trim leftmost characters BiF, %TRIML, to remove the leading blank characters.
The called program's source code looks like:
01 PGM PARM(&PARM_IN) 02 DCL VAR(&PARM_IN) TYPE(*CHAR) LEN(30) 03 DMPCLPGM |
Line 1: This program accepts one parameter from any program that calls it.
Line 2: Definition for this one parameter. This happens to be the same as the variable that is used as the parameter when this program is called.
Line 3: Generate the program dump.
When I look near the bottom of the spool file I can see the value in the &PARM_IN variable is what I expected.
Variable Type Length Value *....+....1....+....2....+ &PARM_IN *CHAR 30 'Text starts here ' +26 ' ' |
In my next example I want to convert a character representation of a number to a decimal value, and then pass it to the called program.
01 DCL VAR(&CHAR) TYPE(*CHAR) LEN(6) 02 CHGVAR VAR(&CHAR) VALUE('123.45') 03 CALL PGM(TESTCL) PARM(%DEC(&CHAR 5 2)) |
Line 1: I define the character variable to be six character long.
Line 2: I move a value to it.
Line 3: When I call TESTCL I use the Convert to decimal BiF, %DEC, to convert the value in &CHAR to a decimal value. The character variable has to be six characters to accommodate the decimal place. The decimal value assumes the decimal, therefore, it is only five characters.
01 PGM PARM(&PARM_IN) 02 DCL VAR(&PARM_IN) TYPE(*DEC) LEN(5 2) 03 DMPCLPGM |
This version of the called program, TESTCL, is as simple as the previous with just three lines of code.
Line 1: One parameter is passed to this program.
Line 2: The variable that is used for the parameter is defined as decimal date type, five long with two decimal places.
Line 3: I dump this program.
Looking in the program dump spool file the result contained in the variable was not as I expected.
Variable Type Length Value *....+....1....+....2....+ &PARM_IN *DEC 5 2 0 |
This must be due to the assumptions that the CL compiler makes with the parameter in the calling program. I am assuming as the variable is character, even though I have used the %DEC BiF, it is passed as character.
Fortunately with the enhancement to the Call command I can define the parameter as decimal within the command. This means the line 3 in the calling program becomes:
03 CALL PGM(TESTCL) PARM((%DEC(&CHAR 5 2) (*DEC 5 2))) |
Line 3: The (*DEC 5 2) means that the parameter is passed as decimal, five long, with two decimal places.
Making this change means that the value in the parameter variable is shown in the program dump as:
Variable Type Length Value *....+....1....+....2....+ &PARM_IN *DEC 5 2 123.45 |
Next example I want to pass two variables to the called program: a variable and its length:
01 DCL VAR(&CHAR) TYPE(*CHAR) LEN(15) 02 CHGVAR VAR(&CHAR) VALUE('Something') 03 CALL PGM(TESTCL) + 04 PARM((&CHAR) + 05 (%LEN(&CHAR) (*DEC 3 0))) |
Line 1: Definition for the variable.
Line 2: Putting a value in it.
Line 3 5: Calling TESTCL with two parameters. The first is the variable, the second uses the Length BiF, %LEN, to return the length of the variable, not the string contained within.
01 PGM PARM(&CHAR &PARM_IN) 02 DCL VAR(&CHAR) TYPE(*CHAR) LEN(15) 03 DCL VAR(&PARM_IN) TYPE(*DEC) LEN(3 0) 04 DMPCLPGM |
Line 1: Two parameters are passed to this program, see lines 3 - 5 of the calling program.
Lines 2 and 3: Definitions of the variables that will hold these passed parameters' values.
Line 3: Dump the program.
The dump's spool file contains the variables, and shows they contain the values I expected.
Variable Type Length Value *....+....1....+....2....+ &CHAR *CHAR 15 'Something ' &PARM_IN *DEC 3 0 15 |
I wanted to see if I could get the length of the string, not the variable, as the second parameter.
03 CALL PGM(TESTCL) + 04 PARM((&CHAR) + 05 (%LEN(%TRIM(&CHAR)) (*DEC 3 0))) |
I replaced lines 3 5 in the calling with the above. The change is in line 5, where I nest the %TRIM BiF within the %LEN. When I compiled this changed program it errored with the following:
500- CALL PGM(TESTCL) + 600 PARM((&CHAR) + 700 (%LEN(%TRIM(&CHAR)) (*DEC 3 0))) * CPD0181 30 Argument for built-in function %LEN not valid. |
It is a shame I cannot nest BiFs within one another in a passed parameter.
In the last scenario I want to use the Substring BiF. Rather than use the %SUBSTRING, I will be using %SST which is a synonym of the other.
01 DCL VAR(&CHAR) TYPE(*CHAR) LEN(26) 02 CHGVAR VAR(&CHAR) VALUE('ABCDEFGHIJKLMNOPQRSTUVWXYZ') 03 CALL PGM(TESTCL) PARM((%SST(&CHAR 5 5) (*CHAR 5))) |
Line 1: The variable is character and 26 long.
Line 2: Load it with all the letters of the alphabet.
Line 3: I am substring five characters, starting in the fifth position of the string.
The called program is very similar to the others I have shown.
01 PGM PARM(&PARM_IN) 02 DCL VAR(&PARM_IN) TYPE(*CHAR) LEN(5) 03 DMPCLPGM |
Line 2: The passed parameter is a five long character variable.
The dump's spool file shows what I would expect.
Variable Type Length Value *....+....1....+....2....+ &PARM_IN *CHAR 5 'EFGHI' |
I consider this a good improvement to the CL language. My only wish is that I could next BiFs within one another.
This article was written for IBM i 7.5, 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.