A Generic Command Choice Validity Checker
October 6, 2004 Bruce Guetzkow
The code for this article is available for download.
In my previous article I created a generic program that you can use to display command parameter choices that are stored in a file: a command choice program. While that program is very useful, it is only part of the story. This time I’ll show you a procedure and service program that you can include in a validity checking program to ensure that parameter values entered are valid. With this second part, you will be able to validate parameter entries based on values stored in a file.
THE VALIDITY CHECKING PROGRAM
The sole purpose of a validity checking program is to make sure that all parameter entries for a command are valid. To use a VCP you must specify the name of the program on the VLDCKR parameter of the CRTCMD command. The VCP uses the same parameter list as the command processing program. Your VCP then determines if each parameter contains a valid entry. If an invalid entry is encountered, the VCP sends escape and diagnostic messages, which notify the system to prevent the command processing program from executing.
For parameters that do not use a command choice program, you can use simple “if” tests to determine whether an entry is valid:
IF COND(&PARM01 *NE 'A' AND &PARM01 *NE 'B') Send error messages if parm-01 is not an 'A' and not a 'B' ENDDO
Simple tests like these are fine when a parameter has specific, known values, but if the list of permissible values changes, the test must be modified and the program recompiled. If you want the flexibility to change permissible values without program modification, you should use a VCP.
CONTROL FILE
The VCP uses a file to store information about the command and keyword that are being validated. To be consistent with the command choice program, I use the CMDCHOICE file, since this file already has all of the information I need. If you created this file after reading the command choice program article, you don’t have to create it again. The source for the file is included again here for reference. You can use this VCP and the command choice program independent of each other if you wish, but they work best if used together.
File CMDCHOICE contains the following fields:
- CKCOMMAND–Command name
- CKLIB–Library containing value reference file
- CKKEYWORD–Command keyword
- CKFILE–Value reference file
- CKFIELD–Value reference field
- CKTEXT–Display text
This file is uniquely keyed by fields CKCOMMAND and CKKEYWORD. Fields CKLIB, CKFILE, and CKFIELD indicate the library, file, and field that contain the list of valid choices. We won’t need field CKTEXT for this service program, but it is needed for the command choice program.
VALIDITY CHECKER PROCEDURE
Let’s take a look at the source for the validity checking procedure. The module (CMDVLDCHK) consists of a single procedure: #vldcmdparm. This procedure has three required parameters:
- Command name (10 bytes)
- Command keyword (10 bytes)
- Entry value (up to 32 bytes)
The procedure returns an indicator value: *ON means that the entry value is valid.
The executable portion of this procedure begins by resetting the success indicator to *OFF. It then retrieves the command/keyword record from the control file to determine the name of the library, file, and field where the valid values are stored. Next I create an SQL statement that will attempt to retrieve the entry value indicated on our input parameter. This SQL statement is prepared, and a cursor is declared and opened. The first record matching the SQL statement is then fetched.
The next statement may look a little odd at first:
success_ind = (sqlstt = *zeros);
Let’s look at the right half of the statement: (sqlstt = *zeros). This is a Boolean statement, which evaluates to a true/false (*ON/*OFF) value. You may be more familiar with Booleans in the following context:
if sqlstt = *zeros;
In my statement, field success_ind will contain the value *ON if the Boolean is true, or *OFF if it is false. Here is another way I could have written this:
if sqlstt = *zeros; success_ind = *ON; else; success_ind = *OFF; endif;
I also could have left out the parentheses:
success_ind = sqlstt = *zeros;
I find this more difficult to read, but the compiler accepts this with no problems. The result of the statement turns indicator field success_ind to *ON if the entry value is valid, or *OFF if it is not valid.
The cursor is then closed, and the procedure returns an indicator to the caller indicating whether the value entered for the parameter is valid.
CREATING THE VCP
Now that I have a command choice validity checker, I need to create a VCP to validate all fields for this command. This program is unique for each command. Consider the following sample command (TEST):
CMD PROMPT('Test') PARM KWD(FILE) TYPE(FILE) MIN(1) PROMPT('File Name') PARM KWD(USERID) TYPE(*CHAR) LEN(10) RSTD(*NO) MIN(1) CHOICE(*PGM) CHOICEPGM(CMDCHOICE) PROMPT('User-ID') FILE: QUAL TYPE(*NAME) LEN(10) EXPR(*YES) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) SPCVAL((*LIBL) (*CURLIB)) EXPR(*YES) PROMPT('Library')
Suppose the purpose of the command processing program for this command is to send a message to the user specified, indicating the file name and current number of records in the file. A validity checking program could be used to make sure that the specified file exists and that the specified user is valid. Notice that the second parameter uses keywords CHOICE(*PGM) and CHOICEPGM(CMDCHOICE), indicating that valid entries will be displayed based on values stored in a file. This is our clue that we will need to use our new procedure to validate this value.
I have included a CLLE source member (TESTVCP) as a sample VCP. The program has two parameters, corresponding to the two keywords specified on the command above. The first parameter (FILE) is received as a 20-byte field containing the file name and the library name. The Change Variable (CHGVAR) command is used to split these parts into separate fields. Then the Check Object (CHKOBJ) command is used to determine if the file exists. If the command generates an escape message beginning with CPF98xx, an error has occurred. Message text is created, and the Send Program Message (SNDPGMMSG) command sends two messages. Message ID CPD0006 has been defined by IBM for use with validity checking programs. This message ID is used along with the text I specified to send a diagnostic message. You must prefix your message text with four zeros as the message ID expects a four-digit number as the first substitution variable. It is followed by sending CPF0002 as an escape message. The system then sends message ID CPF0001 to indicate that errors have occurred and processing stops, preventing the command processing program from executing with invalid information.
The second parameter must be validated, using the new #vldcmdparm procedure, because the list of valid values resides in a file. To validate the value, I first initialize fields &KEYWORD and &VALUE, then call procedure #vldcmdparm, passing the command name (field &COMMAND is initialized when it is declared), keyword, and parameter value. The procedure returns an indicator, which is *ON if the value is valid. From this point the logic is similar to what we did to check for a valid file. If the value was not valid, I create message text and send the diagnostic and escape messages.
For any command, this process is repeated for each command keyword. You can even validate dependent parameters. If, for example, parm-01 contains the value A, parm-05 must not contain a B. In this case you can test for valid values for each parameter individually and for parameter combinations as well.
PUTTING IT ALL TOGETHER
To make this all work, first compile the DDS for file CMDCHOICE (if you haven’t already done so):
CRTPF FILE(library/CMDCHOICE) SRCFILE(library/QDDSSRC) SRCMBR(CMDCHOICE)
Next, compile module CMDVLDCHK:
CRTSQLRPGI OBJ(library/CMDVLDCHK) SRCFILE(library/QRPGLESRC) SRCMBR(CMDVLDCHK) OBJTYPE(*MODULE)
Then create service program CMDVLDCHK:
CRTSRVPGM SRVPGM(library/CMDVLDCHK) MODULE(library/CMDVLDCHK) EXPORT(*ALL) ACTGRP(your-act-grp)
Create your VCP (assuming a CLLE module):
CRTCLMOD MODULE(library/your-vcp) SRCFILE(library/QCLLESRC) SRCMBR(your-vcp) CRTPGM PGM(library/your-vcp) MODULE(library/ your-vcp) BNDSRVPGM(library/CMDVLDCHK) ACTGRP(your-act-grp)
Be sure to update file CMDCHOICE with the values needed for each command and keyword and related library, file, and field. Also be sure to specify VLDCKR(library/your-vcp) with the CRTCMD command to associate the validity checking program to your command.
THE COMPLETE PACKAGE
With my previous article and this latest installment, you have the means to present a list of command keyword options stored in a file and validate that the value entered matches values in that file. Although you still need to create unique VCPs, the rest is ready to go.
Bruce Guetzkow has programmed on the AS/400 and iSeries since 1990, in manufacturing, distribution, and other industries. He is currently the IS director at United Credit Service in Elkhorn, Wisconsin. Click here to contact author.