View Full Version : A dangerous CL BUG that you should know about
01-01-1995, 02:00 AM
A colleague of mine was debugging a CL program that had corrupted parms. He told me the problem was in the operating system so I laughed and thought he was crazy until I ran my own tests and confirmed that OS/400 does scramble your parms under certain circumstances in CL. Here's the scenario PGM1 - has 3 paramaters PARM 1 - 50 Bytes *CHAR PARM 2 - 10 Bytes '1234567890' *CHAR PARM 3 - 10 Bytes 'A TEST xxx' *CHAR Do a CHGVAR of the 50 byte parm using the following: CHGVAR VAR(&PRM1) VALUE('THIS IS FILLING UP SOME') Then do a SBMJOB to another CL program passing these 3 parms. The called program will have PARM 1 corrupted and will contain the following Data " THIS IS FILLING UP SOME 1234567890 " As you can see, parm 2 got mashed into parm1. This goes against all I've learned regarding AS/400 parameter passing. Anyone else have this experience?
10-12-2000, 06:58 AM
Jim, What version of the OS are you running?
10-12-2000, 07:16 AM
Jim, I just tried this and my results were what I expected. What OS are you on? Here is the code I used: CL PROGRAM TEST alpha: pgm dcl &parm1 *char len(50) dcl &parm2 *char len(10) value('1234567890') dcl &parm3 *char len(10) value('A TEST XXX') chgvar &parm1 value('This is a test') call test2 parm(&parm1) omega: endpgm CL PROGRAM TEST2 alpha: pgm parm(&parm1) dcl &parm1 *char len(50) sndmsg &parm1 tousr(bmyrick) omega: endpgm -bret
10-12-2000, 07:19 AM
Sounds like the "feature" of when a parm is longer than 32 characters. "When you use the CALL command, character string constants of 32 bytes or less are always passed with a length of 32 bytes. If the string is longer than 32, you must specify the exact number of bytes, and pass exactly that number." This is documented in the CL Programming Manual and the AS/400 (Iseries 400) Knowledge Base. There is also discussion in this Forum on this topic. David
10-12-2000, 07:21 AM
Bret - Change your CALL of TEST2 to a SBMJOB CMD(CALL TEST2) and see what happens. . . Steve
10-12-2000, 07:31 AM
OS/400 has always had this bug. When you use SBMJOB when passing parms, if the length of any of the parms is greater than 32 bytes, and there are trailing blanks in the parm, you will get garbage. One way to get around this is to make the parm 1 byte longer than you need, and make it a non blank character. Then the called program can strip off the extra byte as follows: DCL &Parm50 (1) DCL &CHAR1 (1) value('X') DCL &PARM51 (51) CHGVAR(&PARM51) value(&PARM *CAT &PARM1) CALL PGMB(&PARM51) PgmB PGM parm(&PARM51) DCL &Parm50 (1) DCL &PARM51 (51) CHGVAR VAR(&PARM50) VALUE(%SST(&PARM51 1 50)) Ron
10-12-2000, 07:41 AM
Steve, Now were talking two different situations. SBMJOB has always had this "undocumented feature" we call a bug. When you send left justified text with trailing blanks, then the job will pass garbage tacked on to the end. I'm sure that there is some meaning to the garbage, but I don't need it, so I ignore it. A way to get around this is to: a) Right justify your data in the calling program; b) create the parm 1 byte longer than required and place an 'x' in the last position. Then strip the first X positions of the field out, in the called program. -bret
10-12-2000, 07:54 AM
Bret - I was just pointing out that your test and the problem as Jim described it were two different things . . . Jim specifically stated SBMJOB and your test performed a CALL . . . Thanks, Steve
10-12-2000, 08:09 AM
A way to get around this is to: a) Right justify your data in the calling program; b) create the parm 1 byte longer than required and place an 'x' in the last position. Then strip the first X positions of the field out, in the called program. Yes, this is how we got around the problem
10-12-2000, 08:11 AM
Steve, Oops! Really? I gotta go back and check that out. I missed it completely. -bret "I'm not nearsighted, I'm just blind" myrick
10-12-2000, 11:09 AM
OS/400 has always had the 'feature' of passing parms on a CALL command on a SBMJOB command at a fixed length of 32. The easiest way around this is to create a command over the program and use it instead of calling the program. So instead of doing this: SBMJOB CMD(CALL PGM(PGM1) PARM(&PARM1 &PARM2 &PARM3)) do SBMJOB CMD(CMD1 PARM1(&PARM1) PARM2(&PARM2) PARM3(&PARM3)) Good Luck. John Panzenhagen
10-13-2000, 11:18 AM
This is how I would do it, if I follow the thread question correctly... &cmd = 100 char (eg) *Parm = 33 (x) &Parm2 = 20 (y) &Parm3 = 10 (z) */ CHGVAR VAR(&CMD) VALUE('CALL program (' + *CAT '''' *CAT &parm *CAT '''' *CAT ' ' + *CAT '''' *CAT &Parm2 *CAT '''' *CAT ' ' *CAT '''' *CAT &parm3 *CAT '''' *CAT ')') SBMJOB JOB(&parms) JOBD(greg) + RQSDTA(&CMD) INLLIBL(*JOBD) OUTQ(*JOBD) It will work, but is a little fussy typing in first time.
Powered by vBulletin® Version 4.1.5 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.