Anyone who has programmed on IBM i has experienced this frustration. I want to call a CL program from a command line. I type:
CALL CL_PGM ('A' 12) |
And I am presented with the following error:
MCH1202 received by procedure CL_PGM. (C D I R) |
For the beginner this is cryptic. When I drill down into the job log I can see what really happened:
> CALL CL_PGM('A' 12) Decimal data error. Function check. MCH1202 unmonitored by CL_PGM at statement 0000000700 instruction X'0000'. MCH1202 received by procedure CL_PGM. (C D I R) MCH1202 received by procedure CL_PGM. (C D I R) |
Why is what I passed to the program causing a decimal error?
When I pass a number like this to a CL program it has to be in hexadecimal, as a number is of a decimal data typed (packed). If I pass a hex value as the number:
CALL CL_PGM('A' x'00012F') |
It does not error, but it is not an easy way to call a program. Over the years many developers have made up their minds to only passed character values between programs so that they did not have to deal with this issue.
In IBM i 7.5 there is a solution, which I cannot find in the documentation for IBM i 7.4 TR6. The Call command, CALL, has been changed.
Before I go into examples of this change let me show you the source for my CL program. This is the same program I used above:
01 PGM PARM(&FIRST &SECOND) 02 DCL VAR(&FIRST) TYPE(*CHAR) LEN(1) 03 DCL VAR(&SECOND) TYPE(*DEC) LEN(5 0) 04 CHGVAR VAR(&FIRST) VALUE(&FIRST) 05 CHGVAR VAR(&SECOND) VALUE(&SECOND) 06 ENDPGM |
Line 1: Two parameters are passed to this program.
Lines 2: The first parameter is character.
Line 3: The second is decimal.
Lines 4 and 5: If you do not use the passed parameter it will not error, if it has an invalid data type.
When I am in a partition with an older release and I prompt the Call command I am presented with the following:
Call Program (CALL) Type choices, press Enter. Program . . . . . . . . . . . . > SOMETHING Name Library . . . . . . . . . . . *LIBL Name, *LIBL, *CURLIB Parameters: Parameter . . . . . . . . . . + for more values |
I am sure you are familiar with this screen. I can enter the values of the parameters I want to pass to my program.
With IBM i 7.5 there are extra parameters:
Call Program (CALL) Type choices, press Enter. Program . . . . . . . . . . . . > SOMETHING Name Library . . . . . . . . . . . > *LIBL Name, *LIBL, *CURLIB Parameters: Parameter . . . . . . . . . . Type and length of parameter: Type . . . . . . . . . . . . . *DFT *DFT, *DEC, *CHAR, *LGL... Length . . . . . . . . . . . . Number Decimal positions . . . . . . Number + for more values |
These allow me to enter the (data) type of the value, its length, and if it is numeric the number of decimal positions.
The allowed (data) types are:
Type | Description | Maximum length |
*DFT | Old rules apply. Character or decimal. | Char = 32 bytes Dec = 15,5 |
*CHAR | Character | 32,767 bytes |
*DEC | Decimal | 24,8 |
*INT | Signed binary integer | 8 bytes |
*UINT | Unsigned binary integer | 8 bytes |
*LGL | Logical, only '0' or '1' | 1 |
*FLT | Binary floating point | 8 bytes |
These parameters are optional. If I do not use them then *DFT is assumed.
How would I use these new parameters to call my program?
CALL PGM(CL_PGM) PARM(('A' (*CHAR 1)) (12 (*DEC 5 0))) |
As the first parameter is a single character I could just:
CALL PGM(CL_PGM) PARM(('A' (12 (*DEC 5 0))) |
If I increase the length of the character, first, parameter the program does not error:
CALL PGM(CL_PGM) PARM(('A' (*CHAR 2)) (12 (*DEC 5 0))) |
If I increase the size of the decimal, second, parameter it does error.
CALL PGM(CL_PGM) PARM(('A' (12 (*DEC 6 0))) |
If I add a decimal position to the decimal position:
CALL PGM(CL_PGM) PARM(('A' (12 (*DEC 5 1))) |
And I check the result in debug I get an expected result:
&SECOND = 00120. |
I can also use this within one CL program to call another program:
01 PGM 02 CALL PGM(CL_PGM) PARM(('B' (*CHAR 1)) (100 (*DEC 5 0))) 03 ENDPGM |
I am very pleased with this as I can now call CL programs from the command line when testing without fear of it erroring due to a decimal error.
You can learn more about the changes to the Call command from the IBM website here.
This article was written for IBM i 7.5 only.
This is fantastic news.. still recalled the error which is a real pain in those days. Finally IBM settled this. Thanks for sharing Simon..
ReplyDeleteLooks good. We will socialise this when we go to 7.5. Thanks big heaps
ReplyDeleteHow about SBMJOB?
ReplyDeleteIt used to have problems when submitting numeric values. Did tih change improved it?
Work with the SBMJOB command:
DeleteSBMJOB CMD(CALL PGM(EGA007CLC) PARM(('A' (*CHAR 1))(123 (*DEC 5 0)))) JOB(TEST)
If I add a decimal position to the decimal position:
ReplyDeleteCALL PGM(CL_PGM) PARM(('A' (12 (*DEC 5 1)))
And I check the result in debug I get an expected result:
&SECOND = 00120.
Who, in this case, i don’t get
&SECOND = 0012.0 ?
The decimal place is assumed, therefore, in a 5,1 variable 00120 is 12 with 0 decimal value.
Deletethanks Simon, a little late for me but it's good IBM guys did it this time
ReplyDeleteI found a great use for this that has nothing to do with decimals. We have struggled for years with the problems related to a long CHAR entry parameter on a CL. Testing yesterday, I looked at the failed job log and saw the email address was garbled hex. I remembered this article and Bingo! It worked fine. Many thanks.
ReplyDeleteCALL PGM(MYLIB/CLPGMC)
PARM((EMAILADDRESS@SERVER.COM (*CHAR 50)))