Defining PDM options can save a programmer many keystrokes, yet many programmers dont take advantage of this feature. Those who do typically define options that can be used from only one of the WRKxxxPDM displays. Heres how to define options that can work from all WRKxxxPDM displays and that also execute more than just a single command.
Have you ever written a program or system only to find that users were not using it? Or maybe they were using it, but not as you intended it to be used? Already, memories of such projects are filling your mind, but before you let your blood pressure start to rise, stop and consider that you may be guilty of the same thing. For example, what user- defined PDM options are you using these days? Dont tell me that IBM went to all that trouble to let you define your own options and youre not defining them!
If Ive figured correctly, you can define more than 1,000 PDM options. Since you can make an option do different things, depending on whether youre accessing it from the Work with Libraries in PDM (WRKLIBPDM), Work with Objects in PDM (WRKOBJPDM), or Work with Members in PDM (WRKMBRPDM) screens, in a sense, you can define even more.
In this article, Im going to show you how to define your own PDM options, but even more than that, Im going to show you how to define powerful PDM options.
The Basics
From any WRKxxxPDM screen, press F16. Youll see a list of user-defined options in a work-with panel. The list should not be empty, because IBM has already defined some options. The Work with User-Defined Options panel will allow you to create, change, and delete user-defined options.
If youd like to try this out, press F6 and create an option thats not already defined on your system. Ill use SF for this example; pick something else if that option is already taken. You can use a single letter or a letter followed by either a digit or another letter.
Type WRKSPLF in the command prompt. Press Enter twice. Youll be back to the WRK-xxxPDM screen that you left. Type SF (or whatever you named the option) in front
of an entry in the WRKxxxPDM display and press Enter. You should see the Work with Spool Files screen.
PDM Variables
Typing two characters instead of seven is nice, but thats not all you can do. PDM has the ability to insert certain data into the command string before passing it to the operating system for execution. These data are taken from the PDM environment and are represented by the two-character substitution variables shown in Figure 1. (If you have Application Development Manager/400, there are some three-character substitution variables you can use.)
Say you want an option to let you clear a physical file member. From the WRKMBRPDM display, press the F16 key to work with user-defined options. Press F6 to create a new option. Im going to name it Z1. (I would rather use CM, for Clear Member, but that ones already defined on my AS/400.) If option Z1 already exists on your system, call it something else.
In the command prompt, type clrpfm and press F4. In the Physical file prompt, key in &F. In the Library prompt, key in &L. In the member prompt, key in &N. Press Enter. Youll see the complete Clear Physical File Member (CLRPFM) command, filled in with PDM variables. Press Enter twice more to return to the Work with Members using PDM display.
If you want to test this out, create a dummy source member and populate it with a couple of dummy records. Then, key in Z1 (or whatever you called the new option) next to it and press Enter. The system will respond with an informational message telling you the member was cleared.
Typing in a two-character substitution variable is certainly easier than typing the complete Clear Physical File Member (CLRPFM) command. However, it wont work from the WRKOBJPDM display. It wont work from WRKLIBPDM either, but thats OK because it shouldnt. So, now Ill add a little power.
Whos Calling?
Figure 2 contains a CL program that runs correctly from any of the three PDM screens: WRKLIBPDM, WRKOBJPDM, or WRKMBRPDM. Ill call it PDMOPT. The To execute: instructions at the beginning of the program contain the command string youll need to put behind a PDM option to run the PDMOPT program.
PDMOPTs purpose is to send an error message to the users, informing them that the PDM option they selected is not allowed from the display from which they selected it. Notice that the program checks the &B PDM variable to determine from which display it was invoked, so the code includes separate areas for processing members, objects, or libraries. This program is not a finished product, but a template from which you can define a powerful PDM option.
Lets get back to the CLRPFM problem. I want it to run from WRKMBRPDM, so I need to change the portion of the program that processes members to run the CLRPFM command that I developed earlier. First, I make a copy of the PDMOPT program and call it PDMOPTZ1. (For the complete code for the PDMOPTZ1 program, go to our Web site at http://www.midrangecomputing.com/mc/ 98/12.) Ill modify this copy, not the template.
Figure 3 shows how I changed the code at the MEMBER label. First, I clear the file; then, I jump to the FWDMSG label to pass along the message that OS/400 sends in response. This system message should always tell the user that the file has been cleared.
However, Id also like this to run from the WRKOBJPDM display, provided that the object selected from the list is a physical file. Figure 4 shows the routine I wrote. It checks to make sure that the selected object is a physical file and sends appropriate error messages if it isnt. If the physical file has no members, the program informs the user. If the physical file has one member, the program clears the member. If the physical file has more than one member, the routine prompts for the name of the member to be cleared. I did
not change the program at the LIBRARY label, so the program continues to send an error message if the user uses option Z1 from the WRKLIBPDM display.
The only other task to be done is to define option Z1 to PDM. To do that, I use the command string shown in the To execute: box in Figure 2, changing the program name for PDMOPT to PDMOPTZ1. I could expand this even further (and I may do just that, one of these days.) For instance, I could allow this option to work against a logical file. If the item selected from the list were a logical file, I could clear the physical files its derived from. If the logical file had select or omit criteria, I could write code to delete just the records that it selects. Even OS/400 doesnt have a command to do things like this. The point is that you can make a user-defined option do most anything you want it to.
You Can Use Your Own File
User-defined PDM options are stored in a physical file called QAUOOPT, in library QGPL. If you prefer, you can create your own PDM options file. It must have a record length of 252 bytes. The OPTION field occupies the first two bytes, and the COMMAND field occupies the remaining 250. If you run the Display File Field Description (DSPFFD) command over QGPL/QAUOOPT, youll see the layout. The easiest way to create your own options file is to use the Create Duplicate Object (CRTDUPOBJ) command to copy QGPL/QAUOOPT.
You can press F18 from any of the WRKxxxPDM displays to change the name of the PDM options file to use. Once youre using your own file, you can define your own options without interfering with other PDM users.
A Few More Thoughts
I know youre eager to get started writing a power-PDM option, but first let me point out a few things to keep in mind.
The &C variable contains the user-defined option that was executed. If that option is a single character, that character will be right justified. You can pass it into a program either right- or left-justified. To right-adjust it, enclose &C in apostrophes. To left-adjust it, omit the apostrophes, as I have done in the CALL in the To execute: instructions in Figure
2.
The &X variable contains the selected items text description, enclosed within apostrophes. Trailing blanks are omitted. If that description is less than 32 characters long, the text is padded to a length of 32. If the description is 32 characters long or longer, the actual text is passed, whatever its length. This is consistent with the way CALL passes character literals to a program. If you want the length to be predictable, follow the &X variable with an apostrophe, 50 blanks, a nonblank character, and another apostrophe. If you do that, you can be assured youll receive 50 characters of good data. Again, see how I did it in Figure 2.
The &J variable is qualified. If you use it, be sure to put it in apostrophes. The CALL statement wont work if you dont.
Last, you may want to pass all substitution variables into each of your power-PDM options, as I have done in Figure 2, even though few (if any) programs will need all of them. If you pass all the variables, youll never have to modify the options definition when you decide you need another variable, and youll always be able to start a new option from the template in Figure 2.
Have a good time, make your PDM editing more productive, and let me hear of any exciting things you do with this technique.
Ted Holt is a senior technical editor for Midrange Computing. You can reach him at holt@ midrangecomputing.com.
Reference
AS/400 Programming Development Manager Users Guide and Reference (SC09- 1771-00, CD-ROM QBKAQK00)
Figure 1: The PDM substitution variables are the source of PDM power
/*===================================================================*/
/* To execute: */
/* */
/* CALL PGM(XXX/PDMOPT ) PARM('&A' '&B' &C '&D' + */
/* '&E' '&F' '&G' '&H' '&J' '&L' '&N' '&O' '&P' + */
/* '&R' '&S' '&T' '&U' '&V' '&W' + */
/* &X' ') */
/* */
/*===================================================================*/
/* To compile: */
/* */
/* CRTCLPGM PGM(XXX/PDMOPTxx) SRCFILE(XXX/QCLSRC) */
/* */
/*===================================================================*/
PGM PARM(&A &B &C &D &E &F &G &H &J &L &N &O +
&P &R &S &T &U &V &W &X)
DCL VAR(&A) TYPE(*CHAR) LEN(10)
DCL VAR(&B) TYPE(*CHAR) LEN(10)
DCL VAR(&C) TYPE(*CHAR) LEN(2)
DCL VAR(&D) TYPE(*CHAR) LEN(8)
DCL VAR(&E) TYPE(*CHAR) LEN(4)
DCL VAR(&F) TYPE(*CHAR) LEN(10)
DCL VAR(&G) TYPE(*CHAR) LEN(10)
DCL VAR(&H) TYPE(*CHAR) LEN(10)
DCL VAR(&J) TYPE(*CHAR) LEN(21)
DCL VAR(&L) TYPE(*CHAR) LEN(10)
DCL VAR(&N) TYPE(*CHAR) LEN(10)
DCL VAR(&O) TYPE(*CHAR) LEN(10)
DCL VAR(&P) TYPE(*CHAR) LEN(4)
DCL VAR(&R) TYPE(*CHAR) LEN(4)
DCL VAR(&S) TYPE(*CHAR) LEN(10)
DCL VAR(&T) TYPE(*CHAR) LEN(10)
DCL VAR(&U) TYPE(*CHAR) LEN(10)
DCL VAR(&V) TYPE(*CHAR) LEN(10)
DCL VAR(&W) TYPE(*CHAR) LEN(10)
DCL VAR(&X) TYPE(*CHAR) LEN(50)
DCL VAR(&SCREEN) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(256)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(FWDMSG))
IF (&B *EQ 'M') THEN(GOTO MEMBER)
IF (&B *EQ 'O') THEN(GOTO OBJECT)
GOTO LIBRARY
MEMBER:
CHGVAR VAR(&SCREEN) VALUE('WRKMBRPDM')
GOTO CMDLBL(WRONGSCRN)
RETURN
OBJECT:
CHGVAR VAR(&SCREEN) VALUE('WRKOBJPDM')
GOTO CMDLBL(WRONGSCRN)
RETURN
LIBRARY:
CHGVAR VAR(&SCREEN) VALUE('WRKLIBPDM')
GOTO CMDLBL(WRONGSCRN)
RETURN
WRONGSCRN:
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Option' +
*BCAT &C *BCAT 'is not valid from the' +
*BCAT &SCREEN *BCAT 'display') +
MSGTYPE(*ESCAPE)
FWDMSG:
RCVMSG MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +
SNDMSGFLIB(&MSGFLIB)
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA)
RETURN
ENDPGM
Figure 2: A skeletal CL program for defining PDM options
MEMBER:
CLRPFM FILE(&L/&F) MBR(&N)
GOTO FWDMSG
Figure 3: Executing the Z1 option from WRKMBRPDM clears the selected member
OBJECT:
IF COND(&T *NE '*FILE') THEN(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Object' +
*BCAT &L *TCAT '/' *CAT &N *BCAT 'type' +
*BCAT &T *BCAT 'is not a file') +
MSGTYPE(*ESCAPE)
ENDDO
RTVOBJD OBJ(&L/&N) OBJTYPE(&T) OBJATR(&OBJATR)
IF COND(%SST(&OBJATR 1 2) *NE 'PF') THEN(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('File' +
*BCAT &N *BCAT 'is not a physical file') +
MSGTYPE(*ESCAPE)
RETURN
ENDDO
RTVMBRD FILE(&L/&N) MBR(*FIRSTMBR) RTNMBR(&MBR_1_NAME)
MONMSG MSGID(CPF3019) EXEC(DO)
RCVMSG
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('File' +
*BCAT &N *BCAT 'has no members')
RETURN
ENDDO
RTVMBRD FILE(&L/&N) MBR(&MBR_1_NAME *NEXT)
MONMSG MSGID(CPF3049) EXEC(DO)
RCVMSG
CLRPFM FILE(&L/&N)
GOTO FWDMSG
ENDDO
?CLRPFM ?*FILE(&L/&N) ??MBR(*FIRST)
MONMSG MSGID(CPF6801) EXEC(RETURN)
GOTO FWDMSG
Figure 4: Executing option Z1 from WRKOBJPDM runs this routine
LATEST COMMENTS
MC Press Online