List parameters are a useful feature found in many OS/400 commands. These types of parameters allow you to enter multiple values into a single parameter. For example, when you prompt the Save Object (SAVOBJ) command, the Object (OBJ) parameter initially provides two entry fields. Keying a plus sign (+) into either entry, causes the system to expand the entry field list allowing up to 300 objects to be entered. If you enter three objects, the OBJ parameter might look like this:
OBJ(OBJECTA OBJECTB OBJECTC)
The example you have just seen is called a simple list. However, in another type of list called a list within a list, each entry contains two or more values. For example the Send Net File (SNDNETF) command has a parameter called User ID (TOUSRID). Each TOUSRID value is made up of two elements: the user ID and the address. If you wish to send a file to two user IDs, the TOUSRID parameter might look like this:
TOUSRID((USERA ADDRA) (USERB ADDRB))
The command-definition language allows you to create your own commands which contain simple list and list within list parameters. You accomplish this with a Parameter Definition (PARM) statement with a Maximum values allowed (MAX) value greater than one. A list within a list also requires the use of Element Definition (ELEM) statements.
The command definition for a list parameter is not difficult to code. However, processing the list in a command-processing program (CPP) is not so easy because the CPP receives the entire list as a single variable. This variable contains a two-byte, binary prefix indicating the number of entries in the list. List within list parameters are even more difficult to deal with because each inner list has an additional 2-byte binary prefix indicating the number of inner list entries.
The Extract List (EXTLST) command in QUSRTOOL simplifies the task of processing both simple and list within list parameters in a CL program.
Specify the CL program variable that contains the list to be processed. This must be defined as a character variable and can be up to 2,000 bytes long.
Specify the length of each element for a simple list, or the combined lengths of the elements in a multiple list. Valid values range from 1 to 100.
Specify the CL program variable that is to contain the extracted list element. This must be defined as a 100-byte character variable. For a simple list, this contains the current list element, left justified. For a list within a list, use the substring function to extract each element.
Specify the current element number being processed. This must be defined as a five-digit decimal variable with no decimal positions. Set the value to zero to return the first element from the list. Upon execution, this value is automatically incremented by one for each element returned. When the last element is returned, the value is set to -1.
Specify whether the list is a simple list or a list within a list.
*NO: The list is a simple list.
*YES: The list is a list within a list (referred to as a multiple list by this
To see how this tool works, let's look at an example. The following statement shows the command definition of a simple list parameter:
PARM KWD(LIST) TYPE(*CHAR) + LEN(10) MAX(50) + PROMPT('List')
This parameter allows you to specify up to 50 entries. Each entry can be up to 10 characters in length. 1 contains the CL program to process this parameter using the EXTLST command.
This parameter allows you to specify up to 50 entries. Each entry can be up to 10 characters in length. Figure 1 contains the CL program to process this parameter using the EXTLST command.
Two variable definitions used as parameters by the EXTLST command require special considerations. The &LIST variable is defined as a character variable with a length of 502. The length is calculated by multiplying the LEN parameter times the MAX parameter and adding the two-byte binary prefix-in this case, (10 x 50) + 2 = 502. The &ENTRY variable is defined as a character variable with a length of 10, to match the length (LEN) of the LIST parameter of the command.
Now let's look at the program logic. The EXTLST command is processed in a loop. The command specifies the name of the list variable, the number of elements in the list, the return variable for the element, and the current number variable. When an element is retrieved from the list, EXTLST automatically increments &CURNBR. When all the elements have been processed, EXTLST returns a value of - 1 in the &CURNBR variable.
After the EXTLST command executes, the program checks the &CURNBR variable. If its value is greater than zero, the value of the list element is returned in the &ELEMENT variable. Since &ELEMENT is a 100-byte variable but the elements in the list are only 10 bytes each, the program must extract the first 10 positions into the &ENTRY variable using the substring (%SST) function. At this point, the &ENTRY variable contains the value of one element in the list. Place your code to process the value in the &ENTRY variable here-inside the loop. The program then branches back to EXTLST command to repeat the loop until you've exhausted the entries in the list.
You have just seen an example of how to process a simple list using the EXTLST command. You can also process lists within lists by specifying *YES for the Multiple List (MULTILIST) parameter of the EXTLST command. For an example of this, refer to the source member EXTLST in file QATTINFO in library QUSRTOOL.
Robin Klima is a senior technical editor for Midrange Computing.
This tool is documented in Midrange Computing's QUSRTOOL Command Reference. The manual contains explanations and syntax diagrams for more than 300 obscure yet useful tools.
The Extract List (EXTLST) Command
Figure 1 Example of EXTLST Command
PGM PARM(&LIST) DCL VAR(&LIST) TYPE(*CHAR) LEN(502) DCL VAR(&ENTRY) TYPE(*CHAR) LEN(10) DCL VAR(&CURNBR) TYPE(*DEC) LEN(5 0) DCL VAR(&ELEMENT) TYPE(*CHAR) LEN(100) LOOP: EXTLST LIST(&LIST) ELMLEN(10) ELEMENT(&ELEMENT) + CURNBR(&CURNBR) IF COND(&CURNBR *GT 0) THEN(DO) CHGVAR VAR(&ENTRY) VALUE(%SST(&ELEMENT 1 10)) /* . */ /* . Code to process the &ENTRY variable */ /* . */ GOTO CMDLBL(LOOP) ENDDO ENDPGM