A Way to take the pain out of library list management
by Ernie Malaga
One of the drawbacks of library list management is that you cannot assign a name to a library list and store it as another object. If this were possible, you could create library lists for different tasks, giving them different names and placing them in libraries just like other objects. These library list objects could then be referenced by CL programs when it becomes necessary to change your library list.
As it is now, you can only use the Change Library List command (CHGLIBL); your library list comes from your job description object (*JOBD) every time you sign on. It is likely that your job description simply references system value QUSRLIBL (user library list) as the source for your library list.
The four commands I wrote take the pain out of managing library lists. The commands CRTLIBLOBJ, CHGLIBLOBJ, and DLTLIBLOBJ let you create, change, and delete library list objects, while the Set Library List command (SETLIBL) changes your job description by retrieving a given library list object.
In January, 1991, we published Ted Holt's article titled, "Using AS/400 Library Lists in Parallel Environments." If you have not done so already, you should read that article in order to understand the concept of the library list, and why it is so important.
What Do You Mean, Library List Objects?
Picture the following scenario. Your MIS department is understaffed, so each programmer is working on three separate projects. Because the projects are of diverse nature, each requires a different library list to compile, test, and debug the programs. Take note that during sign-on the system obtains the user's initial library list from the job description, and that the user cannot change the job description using the CHGJOB command. What is left? Using CHGLIBL each time the programmer goes from one project to another. The trouble with CHGLIBL is that it is an error-prone command; the user has to think too much and has to type too much.
The alternative is to create a separate library list object containing all the libraries needed for each project, giving them names. After this set-up process has been done once, the programmer must only run the SETLIBL command to change from one library list to another - quick, convenient, and less prone to error than CHGLIBL.
Or consider this other case. After changing the library list a dozen times (CHGLIBL, ADDLIBLE, RMVLIBLE, EDTLIBL), your library list will no longer be as it was when you signed on. How do you restore your library list? Is this possible? Yes it is, if you have created a library list object, named after yourself, using the CRTLIBLOBJ command. Anytime at all you can then use the SETLIBL command to reset the library list as it was when you signed on.
As a final example, if you find the same CHGLIBL statement in several CL programs (with the same set of libraries), you may wish to create a library list object and then change all occurrences of CHGLIBL with SETLIBL. You gain modularity in your programming, since the list of library names is stored in only one object (the library list object created with CRTLIBLOBJ). Should you need to add yet another library to the same group of libraries, you would not have to change all CL programs, then recompile them. All that would be necessary is to change the library list object with CHGLIBLOBJ.
The Library Object Commands
The Create Library List Object (CRTLIBLOBJ) command accepts a list of up to twenty-five libraries and assigns it a name and a fifty-character text. The library list "object" so created is actually a data area object. See the sample command prompt on 1.
The Create Library List Object (CRTLIBLOBJ) command accepts a list of up to twenty-five libraries and assigns it a name and a fifty-character text. The library list "object" so created is actually a data area object. See the sample command prompt on Figure 1.
The Change Library List Object (CHGLIBLOBJ) command changes the list of library names or the text assigned to the object, or both.
The Delete Library List Object (DLTLIBLOBJ) command deletes an existing library list object.
The Set Library List (SETLIBL) command actually changes your job's library list, matching the library list object that was referenced.
The xxxLIBLOBJ commands have the following parameters:
LIBL: Qualified name of the library list object being updated. The name is required, but the library defaults to LIBLLIB.
LIBS: List of libraries to make up the library list object. This list can contain a maximum of twenty-five library names. Not applicable to DLTLIBLOBJ.
TEXT: Text for the library list object, fifty characters maximum. Not applicable to DLTLIBLOBJ.
All commands use data area objects as library list objects. These objects can be in any library you wish, but the default library name is LIBLLIB (Library List Library), which should be created before running these commands. Optionally, you may change this default value and use one of your libraries for that purpose.
For a listing of the command sources, see2a, 2b, and 2c. 3a shows program LIBL001CL, the command's CPP. This program assumes the existence of command CVTBINDEC in your system. If it does not exist, you must create it from the source provided in Chapter 9 of the CL Programmer's Guide.
For a listing of the command sources, see Figures 2a, 2b, and 2c. Figure 3a shows program LIBL001CL, the command's CPP. This program assumes the existence of command CVTBINDEC in your system. If it does not exist, you must create it from the source provided in Chapter 9 of the CL Programmer's Guide.
Further, the CHGLIBLOBJ command takes advantage of a new feature of Release 3.0 (the prompt override program, or POP), which retrieves the current values of the library names when the command prompter is invoked. This program, LIBL003CL, is listed in 3b.
Further, the CHGLIBLOBJ command takes advantage of a new feature of Release 3.0 (the prompt override program, or POP), which retrieves the current values of the library names when the command prompter is invoked. This program, LIBL003CL, is listed in Figure 3b.
AS/400 shops still running under releases below 3.0 can use the CHGLIBLOBJ without the prompt override program. When executed, the CHGLIBLOBJ command will not show the names of the libraries contained in the library list object; it will be the responsibility of the user to type them all over.
The SETLIBL Command
The SETLIBL command has only one parameter: the qualified name of the library list object. The command source is listed in 4, while 5 shows program LIBL002CL, the CPP for this command.
The SETLIBL command has only one parameter: the qualified name of the library list object. The command source is listed in Figure 4, while Figure 5 shows program LIBL002CL, the CPP for this command.
Compiling the Commands
Compile CRTLIBLOBJ, DLTLIBLOBJ, and SETLIBL as follows:
CRTCMD CMD(xxx/CRTLIBLOBJ) + PGM(xxx/LIBL001CL) + SRCFILE(xxx/QCMDSRC)
CRTCMD CMD(xxx/DLTLIBLOBJ) + PGM(xxx/LIBL001CL) + SRCFILE(xxx/QCMDSRC)
CRTCMD CMD(xxx/SETLIBL) + PGM(xxx/LIBL002CL) + SRCFILE(xxx/QCMDSRC)
To create CHGLIBLOBJ, execute one of the following, depending on your OS/400 release level:
Releases 1.0, 1.2, and 2.0:
CRTCMD CMD(xxx/CHGLIBLOBJ) + PGM(xxx/LIBL001CL) + SRCFILE(xxx/QCMDSRC)
Release 3.0:
CRTCMD CMD(xxx/CHGLIBLOBJ) + PGM(xxx/LIBL001CL) + SRCFILE(xxx/QCMDSRC) + PMTOVRPGM(xxx/LIBL003CL)
What's Your Excuse?
Ted Holt showed you two months ago how to take advantage of the library list to run parallel or test environments on the AS/400. If you have put off using the technique because the library list baffled you, you must now come up with a better excuse: with the help of the four commands presented here, managing the library list is as simple as the proverbial piece of cake. ------------------------------------------------------------------------------- SIDEBAR
Our Library List Object utility uses new features of Release 3.0 of OS/400 that have brought a long-overdue improvement to the command prompter: the Prompt Override Program (POP). The POP is a program, written in any language, which can retrieve information and present it on the command prompter. This feature is now used in most CHGxxx commands, so that when the command prompter is invoked, it will show the current values, rather than *SAME, by default. Setting up POP for your favorite commands is a three-step process. First, you must determine what parameters are considered key parameters: this is not unlike determining which fields make up the key of a file -- you simply pick up the parameters that uniquely identify the item whose current values you want to bring up. Second, you must write the POP. Third, you must create the command indicating the name of the POP in the PMTOVRPGM parameter. Let's review this process step by step, using the CHGLIBLOBJ command presented in this article as an example.
1) Determine the key parameters. Which parameters uniquely identify the library list objects? Only one parameter: the qualified name of the library list object. Therefore, the CHGLIBLOBJ command indicates KEYPARM(*YES) for the LIBL parameter.
2) Write the POP. This is by far the hardest part; please refer to 3b as you read this sidebar. The POP receives, in its first parameter, the qualified name of the command that invoked it. In our case, this is CHGLIBLOBJ. This information is passed to the POP in case the same POP is invoked by several commands. Then the POP receives one parameter per key parameter from the command. Since the CHGLIBLOBJ command has one key parameter only, the POP receives only one parameter. Finally, the POP returns to the command prompter, in its last parameter, a selective prompt string.
2) Write the POP. This is by far the hardest part; please refer to Figure 3b as you read this sidebar. The POP receives, in its first parameter, the qualified name of the command that invoked it. In our case, this is CHGLIBLOBJ. This information is passed to the POP in case the same POP is invoked by several commands. Then the POP receives one parameter per key parameter from the command. Since the CHGLIBLOBJ command has one key parameter only, the POP receives only one parameter. Finally, the POP returns to the command prompter, in its last parameter, a selective prompt string.
This selective prompt string must include, in its first two bytes, the hexadecimal representation of the length of the string. The actual string follows. This hexadecimal representation can be built from a decimal variable or literal with the Convert Decimal to Binary (CVTDECBIN) command which, although not part of OS/400, is completely listed in page 6-37 of the CL Programmer's Guide. The string we need to pass back to the command prompter is:
??LIBS(all the library names) ??TEXT(text for library list object)
Since we must retrieve the component library names from the library list object (which is actually a data area object), and we have to perform many concatenations, CL is the language of choice for this POP. Also, RPG is ruled out since the last parameter of the POP must be a 5700-byte character string, and such long strings are not supported in RPG, unless extra steps are taken in the RPG program to process this string as a data structure. Building this return string is not complicated. The values are retrieved from the library list object with the Retrieve Data Area (RTVDTAARA) command, then concatenated together and placed in the last parameter. Before we do so, however, we use the CVTDECBIN to build the two-byte length indicator at the beginning of the return string; we can expect the return string to be less than four hundred bytes long, so that is the value we convert to hexadecimal.
3) Create the command. This is the easiest step, involving the execution of the CRTCMD with PMT OVRPGM (LIBL003CL).
For more information about POPs, please refer to the CL Programmer's Guide, pages 9-35 to 9-42. If you need help with selective prompt strings, see pages 6-14 to 6-16 of the same manual.
Treating Library Lists As Objects
Figure 1 Sample Command Prompt
Create Library List Object (CRTLIBLOBJ) Type choices, press Enter. Name of library list . . . . . . > WAYNE Name Library . . . . . . . . . . . LIBLLIB Name Libraries . . . . . . . . . . . > PROD Name > TEST > ACCTG > PERSONNEL > SCRATCH > TAATOOL > QGPL + for more values > QTEMP Text . . . . . . . . . . . . . . Wayne's library list Bottom F3=Exit F4=Prompt F5=Refresh F12=Cancel F13=How to use this display F24=More keys
Treating Library Lists As Objects
Figure 2A The CRTLIBLOBJ Command
CRTLIBLOBJ: CMD PROMPT('Create Library List Object') PARM KWD(LIBL) TYPE(Q1) MIN(1) PROMPT('Name of + library list') PARM KWD(LIBS) TYPE(*SNAME) LEN(10) MIN(1) + MAX(25) PROMPT('Libraries') PARM KWD(TEXT) TYPE(*CHAR) LEN(50) PROMPT('Text') PARM KWD(ACTION) TYPE(*CHAR) LEN(4) CONSTANT(*CRT) Q1: QUAL TYPE(*SNAME) LEN(10) MIN(1) QUAL TYPE(*SNAME) LEN(10) DFT(LIBLLIB) + PROMPT('Library')
Treating Library Lists As Objects
Figure 2B The CHGLIBLOBJ Command
CHGLIBLOBJ: CMD PROMPT('Change Library List Object') PARM KWD(LIBL) TYPE(Q1) MIN(1) KEYPARM(*YES) + PROMPT('Name of library list') PARM KWD(LIBS) TYPE(*SNAME) LEN(10) MIN(1) + MAX(25) PROMPT('Libraries') PARM KWD(TEXT) TYPE(*CHAR) LEN(50) PROMPT('Text') PARM KWD(ACTION) TYPE(*CHAR) LEN(4) CONSTANT(*CHG) Q1: QUAL TYPE(*SNAME) LEN(10) MIN(1) QUAL TYPE(*SNAME) LEN(10) DFT(LIBLLIB) + PROMPT('Library')
Treating Library Lists As Objects
Figure 2C The DLTLIBLOBJ Command
DLTLIBLOBJ: CMD PROMPT('Delete Library List Object') PARM KWD(LIBL) TYPE(Q1) MIN(1) PROMPT('Name of + library list') PARM KWD(LIBS) TYPE(*ZEROELEM) PARM KWD(TEXT) TYPE(*ZEROELEM) PARM KWD(ACTION) TYPE(*CHAR) LEN(4) CONSTANT(*DLT) Q1: QUAL TYPE(*SNAME) LEN(10) MIN(1) QUAL TYPE(*SNAME) LEN(10) DFT(LIBLLIB) + PROMPT('Library')
Treating Library Lists As Objects
Figure 3A The LIBL001CL CL Program
LIBL001CL: + PGM PARM(&QLL &LIBS &TEXT &ACTION) DCL VAR(&QLL) TYPE(*CHAR) LEN(20) DCL VAR(&LIBS) TYPE(*CHAR) LEN(252) DCL VAR(&TEXT) TYPE(*CHAR) LEN(50) DCL VAR(&ACTION) TYPE(*CHAR) LEN(4) DCL VAR(&LLOBJ) TYPE(*CHAR) LEN(10) DCL VAR(&LLLIB) TYPE(*CHAR) LEN(10) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&TWO_BYTES) TYPE(*CHAR) LEN(2) DCL VAR(&NBR_LIBS) TYPE(*DEC) LEN(5 0) DCL VAR(&COUNTER) TYPE(*DEC) LEN(2 0) DCL VAR(&OFFSET_1) TYPE(*DEC) LEN(3 0) DCL VAR(&OFFSET_2) TYPE(*DEC) LEN(3 0) DCL VAR(&ONE_LIB) TYPE(*CHAR) LEN(10) DCL VAR(&ERRORS) TYPE(*DEC) LEN(2 0) /* Break qualified name */ CHGVAR VAR(&LLOBJ) VALUE(%SST(&QLL 1 10)) CHGVAR VAR(&LLLIB) VALUE(%SST(&QLL 11 10)) /* Validate input */ CHKOBJ OBJ(&LLLIB) OBJTYPE(*LIB) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&MSGDTA) VALUE('Library' *BCAT &LLLIB *BCAT 'not + found') GOTO CMDLBL(ERROR) ENDDO /* Process *CRT action */ IF COND(&ACTION *EQ '*CRT') THEN(DO) CHKOBJ OBJ(&LLLIB/&LLOBJ) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(GOTO CMDLBL(CRT_OK)) CHGVAR VAR(&MSGDTA) VALUE('Library list' *BCAT &LLOBJ *BCAT + 'already exists in' *BCAT &LLLIB) GOTO CMDLBL(ERROR) CRT_OK: + CRTDTAARA DTAARA(&LLLIB/&LLOBJ) TYPE(*CHAR) LEN(250) + TEXT(&TEXT) AUT(*ALL) GOTO CMDLBL(CHG_OK) ENDDO ELSE CMD(DO) CHKOBJ OBJ(&LLLIB/&LLOBJ) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&MSGDTA) VALUE('Library list' *BCAT &LLOBJ + *BCAT 'not found in' *BCAT &LLLIB) GOTO CMDLBL(ERROR) ENDDO ENDDO /* Process *CHG action */ IF COND(&ACTION *EQ '*CHG') THEN(DO) CHGOBJD OBJ(&LLLIB/&LLOBJ) OBJTYPE(*DTAARA) TEXT(&TEXT) CHG_OK: + CHGVAR VAR(&TWO_BYTES) VALUE(%SST(&LIBS 1 2)) CVTBINDEC FROMBIN(&TWO_BYTES) TODEC(&NBR_LIBS) CHGVAR VAR(&ERRORS) VALUE(0) CHGVAR VAR(&COUNTER) VALUE(1) CHGVAR VAR(&OFFSET_1) VALUE(1) CHGVAR VAR(&OFFSET_2) VALUE(3) LOOP: + CHGVAR VAR(&ONE_LIB) VALUE(%SST(&LIBS &OFFSET_2 10)) CHGDTAARA DTAARA(&LLLIB/&LLOBJ (&OFFSET_1 10)) VALUE(&ONE_LIB) CHKOBJ OBJ(&ONE_LIB) OBJTYPE(*LIB) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&ERRORS) VALUE(&ERRORS + 1) CHGVAR VAR(&MSGDTA) VALUE('Component library' *BCAT + &ONE_LIB *BCAT 'not found') SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*DIAG) ENDDO CHGVAR VAR(&COUNTER) VALUE(&COUNTER + 1) CHGVAR VAR(&OFFSET_1) VALUE(&OFFSET_1 + 10) CHGVAR VAR(&OFFSET_2) VALUE(&OFFSET_2 + 10) IF COND(&COUNTER *LE &NBR_LIBS) THEN(GOTO CMDLBL(LOOP)) GOTO CMDLBL(ENDPGM) ENDDO /* Process *DLT action */ IF COND(&ACTION *EQ '*DLT') THEN(DO) DLTDTAARA DTAARA(&LLLIB/&LLOBJ) GOTO CMDLBL(ENDPGM) ENDDO /* Send error messages */ ERROR: + SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*DIAG) SNDPGMMSG MSGID(CPF0002) MSGF(QCPFMSG) MSGTYPE(*ESCAPE) /* End program */ ENDPGM: + IF COND(&ERRORS *GT 0) THEN(DO) CHGVAR VAR(&MSGDTA) VALUE('Library list updated, but errors + exist') SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*INFO) ENDDO ENDPGM
Treating Library Lists As Objects
Figure 3B The LIBL003CL Program
LIBL003CL: + PGM PARM(&QUALCMD &QUALLIBL &RTNSTRING) DCL VAR(&QUALCMD) TYPE(*CHAR) LEN(20) DCL VAR(&QUALLIBL) TYPE(*CHAR) LEN(20) DCL VAR(&RTNSTRING) TYPE(*CHAR) LEN(5700) DCL VAR(&LIBL) TYPE(*CHAR) LEN(10) DCL VAR(&LIBLLIB) TYPE(*CHAR) LEN(10) DCL VAR(&TWO_BYTES) TYPE(*CHAR) LEN(2) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&LIB01) TYPE(*CHAR) LEN(10) DCL VAR(&LIB02) TYPE(*CHAR) LEN(10) DCL VAR(&LIB03) TYPE(*CHAR) LEN(10) DCL VAR(&LIB04) TYPE(*CHAR) LEN(10) DCL VAR(&LIB05) TYPE(*CHAR) LEN(10) DCL VAR(&LIB06) TYPE(*CHAR) LEN(10) DCL VAR(&LIB07) TYPE(*CHAR) LEN(10) DCL VAR(&LIB08) TYPE(*CHAR) LEN(10) DCL VAR(&LIB09) TYPE(*CHAR) LEN(10) DCL VAR(&LIB10) TYPE(*CHAR) LEN(10) DCL VAR(&LIB11) TYPE(*CHAR) LEN(10) DCL VAR(&LIB12) TYPE(*CHAR) LEN(10) DCL VAR(&LIB13) TYPE(*CHAR) LEN(10) DCL VAR(&LIB14) TYPE(*CHAR) LEN(10) DCL VAR(&LIB15) TYPE(*CHAR) LEN(10) DCL VAR(&LIB16) TYPE(*CHAR) LEN(10) DCL VAR(&LIB17) TYPE(*CHAR) LEN(10) DCL VAR(&LIB18) TYPE(*CHAR) LEN(10) DCL VAR(&LIB19) TYPE(*CHAR) LEN(10) DCL VAR(&LIB20) TYPE(*CHAR) LEN(10) DCL VAR(&LIB21) TYPE(*CHAR) LEN(10) DCL VAR(&LIB22) TYPE(*CHAR) LEN(10) DCL VAR(&LIB23) TYPE(*CHAR) LEN(10) DCL VAR(&LIB24) TYPE(*CHAR) LEN(10) DCL VAR(&LIB25) TYPE(*CHAR) LEN(10) DCL VAR(&OLD_TEXT) TYPE(*CHAR) LEN(50) DCL VAR(&NEW_TEXT) TYPE(*CHAR) LEN(100) DCL VAR(&OLD_POS) TYPE(*DEC) LEN(3 0) DCL VAR(&NEW_POS) TYPE(*DEC) LEN(3 0) /* Break qualified name of library list object */ CHGVAR VAR(&LIBL) VALUE(%SST(&QUALLIBL 1 10)) CHGVAR VAR(&LIBLLIB) VALUE(%SST(&QUALLIBL 11 10)) /* Validate library list object */ CHKOBJ OBJ(&LIBLLIB/&LIBL) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(DO) CVTDECBIN FROMDEC(0) TOBIN(&TWO_BYTES) CHGVAR VAR(&RTNSTRING) VALUE(&TWO_BYTES) CHGVAR VAR(&MSGDTA) VALUE('Library list' *BCAT &LIBL *BCAT + 'not found in' *BCAT &LIBL) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*DIAG) SNDPGMMSG MSGID(CPF0011) MSGF(QCPFMSG) MSGTYPE(*ESCAPE) GOTO CMDLBL(ENDPGM) ENDDO /* Retrieve library names */ RTVDTAARA DTAARA(&LIBLLIB/&LIBL (1 10)) RTNVAR(&LIB01) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (11 10)) RTNVAR(&LIB02) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (21 10)) RTNVAR(&LIB03) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (31 10)) RTNVAR(&LIB04) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (41 10)) RTNVAR(&LIB05) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (51 10)) RTNVAR(&LIB06) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (61 10)) RTNVAR(&LIB07) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (71 10)) RTNVAR(&LIB08) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (81 10)) RTNVAR(&LIB09) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (91 10)) RTNVAR(&LIB10) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (101 10)) RTNVAR(&LIB11) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (111 10)) RTNVAR(&LIB12) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (121 10)) RTNVAR(&LIB13) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (131 10)) RTNVAR(&LIB14) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (141 10)) RTNVAR(&LIB15) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (151 10)) RTNVAR(&LIB16) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (161 10)) RTNVAR(&LIB17) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (171 10)) RTNVAR(&LIB18) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (181 10)) RTNVAR(&LIB19) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (191 10)) RTNVAR(&LIB20) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (201 10)) RTNVAR(&LIB21) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (211 10)) RTNVAR(&LIB22) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (221 10)) RTNVAR(&LIB23) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (231 10)) RTNVAR(&LIB24) RTVDTAARA DTAARA(&LIBLLIB/&LIBL (241 10)) RTNVAR(&LIB25) /* Retrieve library list description */ RTVOBJD OBJ(&LIBLLIB/&LIBL) OBJTYPE(*DTAARA) TEXT(&OLD_TEXT) /* Change all single apostrophes for double apostrophes */ CHGVAR VAR(&OLD_POS) VALUE(1) CHGVAR VAR(&NEW_POS) VALUE(1) LOOP: + IF COND(%SST(&OLD_TEXT &OLD_POS 1) *EQ '''') THEN(DO) CHGVAR VAR(%SST(&NEW_TEXT &NEW_POS 2)) VALUE('''''') CHGVAR VAR(&NEW_POS) VALUE(&NEW_POS + 2) ENDDO ELSE CMD(DO) CHGVAR VAR(%SST(&NEW_TEXT &NEW_POS 1)) VALUE(%SST(&OLD_TEXT + &OLD_POS 1)) CHGVAR VAR(&NEW_POS) VALUE(&NEW_POS + 1) ENDDO CHGVAR VAR(&OLD_POS) VALUE(&OLD_POS + 1) IF COND(&OLD_POS *LE 50) THEN(GOTO CMDLBL(LOOP)) /* Build the return string */ CVTDECBIN FROMDEC(400) TOBIN(&TWO_BYTES) CHGVAR VAR(&RTNSTRING) VALUE(&TWO_BYTES *CAT '??LIBS(' *CAT + &LIB01 *BCAT &LIB02 *BCAT &LIB03 *BCAT &LIB04 *BCAT &LIB05 + *BCAT &LIB06 *BCAT &LIB07 *BCAT &LIB08 *BCAT &LIB09 *BCAT + &LIB10 *BCAT &LIB11 *BCAT &LIB12 *BCAT &LIB13 *BCAT &LIB14 + *BCAT &LIB15 *BCAT &LIB16 *BCAT &LIB17 *BCAT &LIB18 *BCAT + &LIB19 *BCAT &LIB20 *BCAT &LIB21 *BCAT &LIB22 *BCAT &LIB23 + *BCAT &LIB24 *BCAT &LIB25 *TCAT ') ??TEXT(''' *CAT &NEW_TEXT + *TCAT ''')') ENDPGM: + ENDPGM
Treating Library Lists As Objects
Figure 4 The SETLIBL Command
SETLIBL: CMD PROMPT('Set Library List') PARM KWD(LIBL) TYPE(Q1) PROMPT('Library list') Q1: QUAL TYPE(*SNAME) LEN(10) MIN(1) QUAL TYPE(*SNAME) LEN(10) DFT(LIBLLIB) + PROMPT('Library')
Treating Library Lists As Objects
Figure 5 The LIBL002CL Program
LIBL002CL: + PGM PARM(&QLL) DCL VAR(&QLL) TYPE(*CHAR) LEN(20) DCL VAR(&LLOBJ) TYPE(*CHAR) LEN(10) DCL VAR(&LLLIB) TYPE(*CHAR) LEN(10) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&LIBS) TYPE(*CHAR) LEN(250) DCL VAR(&CMD) TYPE(*CHAR) LEN(300) DCL VAR(&OFFSET) TYPE(*DEC) LEN(3 0) DCL VAR(&LIBNAM) TYPE(*CHAR) LEN(10) DCL VAR(&ERRORS) TYPE(*DEC) LEN(2 0) /* Break qualified name */ CHGVAR VAR(&LLOBJ) VALUE(%SST(&QLL 1 10)) CHGVAR VAR(&LLLIB) VALUE(%SST(&QLL 11 10)) /* Validate input */ CHKOBJ OBJ(&LLLIB) OBJTYPE(*LIB) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&MSGDTA) VALUE('Library' *BCAT &LLLIB *BCAT 'not + found') GOTO CMDLBL(ERROR) ENDDO CHKOBJ OBJ(&LLLIB/&LLOBJ) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&MSGDTA) VALUE('Library list' *BCAT &LLOBJ *BCAT + 'not found in' *BCAT &LLLIB) GOTO CMDLBL(ERROR) ENDDO /* Set library list */ RTVDTAARA DTAARA(&LLLIB/&LLOBJ *ALL) RTNVAR(&LIBS) CHGVAR VAR(&CMD) VALUE('CHGLIBL LIBL(') CHGVAR VAR(&OFFSET) VALUE(1) CHGVAR VAR(&ERRORS) VALUE(0) LOOP: + CHGVAR VAR(&LIBNAM) VALUE(%SST(&LIBS &OFFSET 10)) IF COND(&LIBNAM *NE ' ') THEN(DO) CHKOBJ OBJ(&LIBNAM) OBJTYPE(*LIB) MONMSG MSGID(CPF9801) EXEC(DO) CHGVAR VAR(&ERRORS) VALUE(&ERRORS + 1) CHGVAR VAR(&MSGDTA) VALUE('Component library' *BCAT + &LIBNAM *BCAT 'not found') SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*DIAG) ENDDO CHGVAR VAR(&CMD) VALUE(&CMD *BCAT &LIBNAM) ENDDO CHGVAR VAR(&OFFSET) VALUE(&OFFSET + 10) IF COND(&OFFSET *LT 250) THEN(GOTO CMDLBL(LOOP)) ELSE CMD(DO) CHGVAR VAR(&CMD) VALUE(&CMD *TCAT ')') ENDDO IF COND(&ERRORS *EQ 0) THEN(DO) CALL PGM(QCMDEXC) PARM(&CMD 300) GOTO CMDLBL(ENDPGM) ENDDO ELSE CMD(DO) CHGVAR VAR(&MSGDTA) VALUE('Library list not set') ENDDO /* Send error messages */ ERROR: + SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*DIAG) SNDPGMMSG MSGID(CPF0002) MSGF(QCPFMSG) MSGTYPE(*ESCAPE) /* End program */ ENDPGM: + ENDPGM
LATEST COMMENTS
MC Press Online