I was creating a command with what I am going to call a "list parameter", to allow the entry of up to ten libraries. While writing the Command Processing Program, CPP, I encountered something I could not find a good description of how to handle. Therefore, I am writing this post to give you a good example of how I did it.
I am not going to go into too much detail on how to create commands and their parameters as I covered many of the basics in two earlier posts: Creating your own commands, part 1 and Creating your own commands, part 2.
My example command, MYCMD, has just one parameter, which will be the list of up to ten libraries. The source for the command is as follows:
01 CMD PROMPT('List of libraries')
02 PARM KWD(LIBRARY) TYPE(*NAME) MIN(1) MAX(10) +
03 PROMPT('Libraries')
|
Line 2 and 3: The command parameter LIBRARY has a number of keywords:
- KWD: The keyword name for the parameter
- TYPE: It is a name type parameter, which means it is equivalent of ten long character
- MIN: The minimum number of entries that must be given
- MAX: The maximum number of allowed entries
- PROMPT: The description that appears on the screen
To create the command I use the Create Command, CRTCMD:
01 CRTCMD CMD(MYLIB/MYCMD) + 02 PGM(MYCMDCPP) + 03 SRCFILE(DEVSRC) |
Line 1: I want the command to be called MYCMD and for it to be in my library MYLIB.
Line 2: The command processing program will be called MYCMDCPP, and as I have not given a library name when the command it is executed it will "look" for MYCMDCPP in the job's library list.
Line 3: I keep all of my source code, regardless of type, in one source file: DEVSRC.
All of the other parameters I leave them as their defaults.
One thing I like about the way commands work is that I can give the CPP's name when creating the command, but it does not have to exist at the time I create the command.
Once created I can test the command by entering the follow at any command line:
MYCMD |
I can either press the Enter key or F4 to see the command's parameter:
List of libraries (MYCMD)
Type choices, press Enter.
Libraries . . . . . . . . . . . Name
+ for more values
|
If I want to display more than just the two entry fields I put a "+" in either one shown, and press Enter. This will show the number of fields as there is in the list, of ten:
Specify More Values for Parameter LIBRARY
Type choices, press Enter.
Libraries . . . . . . . . . . . LIBRARY1 Name
LIBRARY2
LIBRARY3
|
I am showing the library names I entered too. I deliberately did not enter the name consecutively, to demonstrate how the command handles the values entered when I press the Enter key:
List of libraries (MYCMD)
Type choices, press Enter.
Libraries . . . . . . . . . . . > LIBRARY1 Name
> LIBRARY2
+ for more values > LIBRARY3
|
The command has consolidated the list of libraries, removing the blank values.
I am going to show the CPP, MYCMDCPP, in three parts to explain what is happens.
The first part is:
01 **free 02 ctl-opt main(Main) option(*srcstmt) ; 03 dcl-proc Main ; 04 dcl-pi *n ; 05 LibraryInfo char(104) const ; 06 end-pi ; |
Line 2: I am using a Main procedure to eliminate the RPG cycle being included in the program, making it "linear". I was including the Source statement option to make error diagnosis and debugging easier.
Line 3: Start of the Main procedure.
Lines 4 – 6: The procedure interface for the Main procedure. This is a long string of all the values entered into the command's parameter. If I add a debug breakpoint after this line and check the contents of the variable LibraryInfo I see the following:
....5...10...15...20...25...30...35...40...45...50...55...60
1 ' ?LIBRARY1 LIBRARY2 LIBRARY3 PGM005V MYLIB QSQLTEMP'
61 '1 QTEMP PGM005V ? ?*SRCMBRTXT '
|
The first two positions appear to contain some kind of a hexadecimal value. The third to 34th positions contain the libraries I entered. And the rest is just "rubbish". How can I know how libraries I have without reading the rubbish? As "PGM005V" could be the name of a library I entered (it is not a library).
I could not find a description of what those first two bytes contained. I had an idea it would be the number of values entered, in this case 3 as a hexadecimal value.
Onto the second part of the program:
07 dcl-ds Libraries ; 08 NbrLibs bindec(2) ; 09 *n char(10) ; 10 *n char(10) ; 11 *n char(10) ; 12 *n char(10) ; 13 *n char(10) ; 14 *n char(10) ; 15 *n char(10) ; 16 *n char(10) ; 17 *n char(10) ; 18 *n char(10) ; 19 Libs char(10) dim(10) pos(3) ; 20 end-ds ; 21 dcl-s Counter uns(3) ; 22 Libraries = LibraryInfo ; |
Lines 7 – 20: I am going to use this data structure to break apart the input parameter into its constituent parts.
Line 7: The data structure is not qualified, therefore, all the subfields' names are not prefixed with the data structure's name.
Line 8: A binary decimal value does not contain a pack character, as a packed type variable does. If this is the area that contains the number of values passed it would be stored as:
00 03 |
As the first two bytes are define as binary decimal this would give me a number of 3.
Lines 9 – 18: These ten subfields are all defined as character ten. I have not given them names as the individual subfields will not be used.
Line 19: I have defined an array to overlay the prior ten subfields. I will be using this array for the library names.
Line 21: This variable will be used as a counter later in the program.
Line 22: I move the input parameter passed to this program to the data structure.
If I add a debug breakpoint after line 22 and display the contents of the data structure this is what I see:
> EVAL Libraries NBRLIBS OF LIBRARIES = 03. OF LIBRARIES = 'LIBRARY1 ' OF LIBRARIES = 'LIBRARY2 ' OF LIBRARIES = 'LIBRARY3 ' OF LIBRARIES = 'PGM005V ' OF LIBRARIES = 'MYLIB ' OF LIBRARIES = 'QSQLTEMP1 ' OF LIBRARIES = 'QTEMP ' OF LIBRARIES = 'PGM005V ' OF LIBRARIES = ' ? ?*SRCMB' OF LIBRARIES = 'RTXT ' LIBS OF LIBRARIES(1) = 'LIBRARY1 ' LIBS OF LIBRARIES(2) = 'LIBRARY2 ' LIBS OF LIBRARIES(3) = 'LIBRARY3 ' LIBS OF LIBRARIES(4) = 'PGM005V ' LIBS OF LIBRARIES(5) = 'MYLIB ' LIBS OF LIBRARIES(6) = 'QSQLTEMP1 ' LIBS OF LIBRARIES(7) = 'QTEMP ' LIBS OF LIBRARIES(8) = 'PGMG005V ' LIBS OF LIBRARIES(9) = ' ? ?*SRCMB' LIBS OF LIBRARIES(10) = 'RTXT ' |
As I assumed the first two bytes contain the number of libraries passed. I can now use this subfield later in the program to control the number of results I fetch from the array.
As I did not give the subfields names the next group of subfields look weird without them. But these show what was passed to this program as library names.
Lastly the contents of the array Libs is shown. Thanks to the NbrLibs subfield I know I only need the data from the first three elements.
Finally the third, and final, part of the CPP program:
23 for Counter = 1 to NbrLibs ; 24 dsply Libs(Counter) ; 25 endfor ; 26 return ; 27 end-proc ; |
Lines 23 – 25: This For-group will be performed the number times found in the binary decimal subfield from the data structure. In this example it will be performed three times.
Line 24: Each time the For-group is performed the value in the array element is displayed. If I look at the job log after the program has completed I see:
DSPLY LIBRARY1 DSPLY LIBRARY2 DSPLY LIBRARY3 |
I did test with other numbers of libraries to make sure that the first two bytes of the received parameter command does contain the number of libraries that were entered.
I think this an efficient program as if you exclude the definition for the data structure the rest of the program is only thirteen lines long. And I think it makes a good example of how to handle the list parameters from commands.
This article was written for IBM i 7.6, and should work for some earlier releases too.




No comments:
Post a Comment
To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.
Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.