The RUN Utility: Call a Program with Correctly Formatted Parameters
November 1, 2006 Ted Holt
Note: The source code for article can be downloaded here
One complaint I hear from time to time concerns the way CL’s CALL command formats literal values that are used as parameters. I have a utility that I use when testing programs that overcomes this problem. It allows me to call a program and ensures that the parameters are formatted as they should be.
First, let’s be sure we all understand the problem. When you use the CL CALL command to begin execution of a program, CL makes some assumptions about literal parameters. CL assumes that numeric values are 15-digit packed-decimal numbers with five decimal positions. Character literals of 32 characters or less are assumed to be 32 characters in length, and the value is padded with trailing blanks if necessary. A character literal of 33 bytes or more is assumed to be the length of the literal, which may not completely fill the parameter. These rules apply when the CALL command runs from a command line, is executed through QCMDEXC, is executed within a CL procedure (program or module), or executed in the CMD or RQSDTA parameters of the Submit Job (SBMJOB) command.
Common ways to get around this limitation are:
These are all fine, I suppose. Each has its advantages and disadvantages. I hate options one through three because they are workarounds. Option four is clumsy, but I have used it many times. Option five is elegant, but I don’t like to write a command unless I’ll need the command in the production environment.
I came up with another alternative that works well for me. I wrote a command that will call a program with literal parameters that fit the definition in the called program. I call my command RUN, because that’s the shortest word I could think of that seemed appropriate. (DO and GO were already taken.)
Suppose I wish to call program MYPGM, passing it three parameters:
Here’s how it’s done:
RUN PGM(MYPGM) PARM(('I like cheese a whole lot!' *CHAR (64)) + (3.14 *DEC (7 2)) (12345678901 *DEC (11)))
If I prefer to run in batch, that’s OK, too.
SBMJOB CMD(RUN PGM(MYPGM) PARM(('I like cheese a whole lot!' *CHAR (64)) (3.14 *DEC (7 2)) (12345678901 *DEC (11)))) JOB(MYJOB)
I know that looks messy, but I prompt the command and fill in the blanks, which is no big deal.
The RUN utility consists of two objects–the RUN command and RPG program RUNRG. The latter object is created from two modules–RUNRG and Cletus the Codeslinger’s ASSERT, which was published in Four Hundred Guru. (See Programming with Assertions for more on that.) I have included revised source for ASSERT in the downloadable code that accompanies this article.
The RUN command has two parameters, which are the same as those defined to the CALL command. The first is the qualified name of the program to be called. The second is a list of parameters. Each element of the list consists of the parameter’s value, the data type (*CHAR or *DEC), and the length. The length is a single number for character parameters. For decimal parameters you may specify one or two length values to indicate number of digits and decimal places. If you specify only one length value for a decimal value, the number is assumed to have zero decimal positions.
Before you can create the RUN utility, you will have to load the following source members in a library of your choosing.
To create the utility, first create the command, then the two modules, and finally bind the two modules into a program.
CRTCMD CMD(RUN) PGM(RUNRG) CRTRPGMOD MODULE(somelib/ASSERT) + SRCFILE(QRPGLESRC) SRCMBR(ASSERT) CRTRPGMOD MODULE(somelib/RUNRG) + SRCFILE(QRPGLESRC) SRCMBR(RUNRG) CRTPGM PGM(somelib/RUNRG) + MODULE(RUNRG ASSERT) ACTGRP(*CALLER)
Let me emphasize that for me, this is just a way to test programs that would normally be called from other programs. I have never used RUN in a production environment, nor do I plan to. I have not thoroughly tested all the error-handling logic, although I feel it would probably kick in if it had to. If you install RUN, please keep this disclaimer in mind.