No more hard-coding the source physical file or the library to run a REXX procedure. Use the Source File List (*SRCL) and Library List (*LIBL) to search for your REXX procedure.
If you have used REXX you probably have noticed that you must specify the name of the source physical file that contains the REXX procedure each time you run the Start REXX Procedure (STRREXPRC) command. If you have all your REXX procedures in the same source file, that's no problem. As soon as you start to diversify your REXX procedures in several libraries, you realize that IBM didn't give you the equivalent of *LIBL for your source files. In other words, there's no support for a source file list.
Yet, this would be a very useful concept. You should be able to provide a systemwide source file list, so that when you run STRREXPRC without specifying a source file name, the system would check the list sequentially until it finds the source member (or until it runs out without finding it, of course).
The CHGREXSRCL and RUN-REXPGM Commands
The Change REXX Source List (CHGREX-SRCL) and the Run REXX Program (RUN- REXPGM) commands solve this problem. The key to this support is a data area named REXX-SRCL which you can create in any of the libraries contained in the system portion of the library list.
Don't create this data area in any IBM-supplied library such as QSYS or QUSRSYS; you may lose it on the next release upgrade. You're better off using one of your own libraries. If the system portion of the library list doesn't contain any user libraries, you should create one for this specific purpose and add it to the system portion of the library list.
To perform this addition, run the Change System Value (CHGSYSVAL) command; the system value you want to change is QSYSLIBL. If you have V1R3 or later, you can use the Work with System Values (WRKSYSVAL) command, which will give you an interactive panel that simplifies the change.
Let's suppose you have a library called MISC in the system portion of the library list. Create data area REXXSRCL as follows:
CRTDTAARA DTAARA(MISC/REXXSRCL) + TYPE(*CHAR) + LEN(1000) + TEXT('REXX Source + File List') + AUT(*USE)
This data area will contain a systemwide list of source physical files (qualified to a library or *LIBL) that you can maintain with the CHGREXSRCL command. Be sure to specify AUT(*USE) when you create the data area-that will protect it from unauthorized maintenance.
Actually, the CHG-REXSRCL command (Figures 1a, 1b and 1c) can maintain two different source file lists: the system's or your job's. Your job's source file list is contained in data area QTEMP/REXXSRCL, which is created automatically the first time you run CHGREXSRCL or RUNREXPGM and contains a copy of the system's source file list. The system's source file list can only be maintained by a user with *ALLOBJ special authority.
To take advantage of the source file list, use the RUNREXPGM command (Figures 2a and 2b) to run a REXX program, instead of the IBM-supplied STRREXPRC command. If you specify SRCFILE(*SRCL), the source file list is activated and the system checks your job's source file list.
RUNREXPGM has three parameters:
PGM (Program): Enter the name of the REXX program; that is, the source member name.
SRCFILE (Source file): Enter the qualified name of the source physical file that contains the REXX member, or *SRCL (source file list).
PARM (Parameter string): Enter up to 3000 characters of parameter string values.
IBM's STRREXPRC contains two additional parameters-Command environment (CMDENV) and Exit program (EXITPGM)-which I did not include in my RUNREXPGM command because I wanted to keep RUNREXPGM short and simple. You can obviously improve on RUN-REXPGM by adding the two missing parameters.
Example of Use
Suppose you have REXX procedures scattered over the following source files: QGPL/QREXSRC, UTILITY/
SOURCE, OELIB/QRPGSRC and INVLIB/QPGMSRC. The first step is to change the system's source file list:
CHGREXSRCL TYPE(*SYS) + SRCL(QGPL/QREXSRC + UTILITY/SOURCE + OELIB/QRPGSRC + INVLIB/QPGMSRC)
Now you decide to run REXX program TESTREXX:
RUNREXPGM PGM(TESTREXX) + SRCF(*SRCL)
RUNREXPGM will check the four source files included in *SRCL and will execute the first TESTREXX it finds. If TESTREXX isn't there, it will return the following escape message:
REXX program TESTREXX not found in *SRCL.
Difference Between System & Job *SRCL
When you use the AS/400's library list support, you actually deal with three separate library lists: the system's system library list (contained in system value QSYSLIBL), the system's user library list (contained in system value QUSRLIBL) and the job's library list (contained in the job description). Every time you start a new job, the system creates the job's library list, which is made up of a copy of the QSYSLIBL and the QUSRLIBL (the JOBD library list may also be used). The job's library list is what *LIBL references. *LIBL never references the system's library lists directly.
This REXX source file list support is similar. The system's source file list is contained in data area REXX
SRCL (anywhere but QTEMP). Each time you start a new job and use either CHGREXSRCL or RUNREXPGM, the system creates the job's source file list in QTEMP, which is initially made up of the system source file list. Whenever you run the RUNREXPGM specifying SRCFILE(*SRCL), the system reads your job's source file list-never the system's list.
You can update the job source file list with the CHGREXSRCL command, specifying TYPE(*JOB) and listing the source files you want included. When you execute RUNREXPGM, the new job *SRCL will be used.
A Natural Concept
The source file list is to REXX programs what the library list is to objects- a natural concept. You don't have to wonder why IBM didn't include it with OS/400; with the utility commands I have presented, you've already got it.
Now you can begin programming in REXX fearlessly, without bothering to hard- code source file names or library names, because you have a source file list. Use it!
The REXX Source File List
Figure 1A Command CHGREXSRCL
CHGREXSRCL: CMD PROMPT('Change REXX Source File List') PARM KWD(TYPE) TYPE(*CHAR) LEN(4) RSTD(*YES) + DFT(*JOB) VALUES(*JOB *SYS) KEYPARM(*YES) + PROMPT('Type of source file list') PARM KWD(SRCL) TYPE(Q1) MAX(50) PROMPT('Source + file list') Q1: QUAL TYPE(*NAME) LEN(10) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL) (*CURLIB)) PROMPT('Library')
The REXX Source File List
Figure 1B CL program REX002CL
REX002CL: + PGM PARM(&TYPE &SRCL) DCL VAR(&COUNTER) TYPE(*DEC) LEN(5 0) DCL VAR(&LIST) TYPE(*CHAR) LEN(1000) DCL VAR(&RESULT) TYPE(*DEC) LEN(3 0) DCL VAR(&SPCAUT) TYPE(*CHAR) LEN(100) DCL VAR(&SRCL) TYPE(*CHAR) LEN(1002) DCL VAR(&TWO_BYTES) TYPE(*CHAR) LEN(2) DCL VAR(&TYPE) TYPE(*CHAR) LEN(4) /* Determine how many source files have been entered in the + &SRCL parameter. Do so by extracting the leading 2 bytes (in + binary) and converting them to decimal with QUSRTOOL's + CVTBINDEC command */ CHGVAR VAR(&TWO_BYTES) VALUE(%SST(&SRCL 1 2)) TAATOOL/CVTBINDEC FROMBIN(&TWO_BYTES) TODEC(&COUNTER) CHGVAR VAR(&COUNTER) VALUE(&COUNTER * 20) CHGVAR VAR(&LIST) VALUE(%SST(&SRCL 3 &COUNTER)) /* Process the *SYS source file list only if the user has + *ALLOBJ special authority */ IF COND(&TYPE *EQ '*SYS') THEN(DO) RTVUSRPRF USRPRF(*CURRENT) SPCAUT(&SPCAUT) CALL PGM(QCLSCAN) PARM(&SPCAUT X'100F' X'001F' '*ALLOBJ' + X'008F' '1' '1' ' ' &RESULT) IF COND(&RESULT *LE 0) THEN(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('You are not + authorized to CHGREXSRCL TYPE(*SYS)') MSGTYPE(*ESCAPE) RETURN ENDDO CHGDTAARA DTAARA(REXXSRCL *ALL) VALUE(&LIST) ENDDO /* Else, process the *JOB source file list */ ELSE CMD(DO) CHGDTAARA DTAARA(QTEMP/REXXSRCL *ALL) VALUE(&LIST) ENDDO ENDPGM
The REXX Source File List
Figure 1C CL program REX002CLA
REX002CLA: + PGM PARM(&CMDSPEC &TYPE &RTNSTRING) DCL VAR(&CMDSPEC) TYPE(*CHAR) LEN(20) DCL VAR(&LENGTH) TYPE(*CHAR) LEN(2) VALUE(X'03F0') DCL VAR(&LIST) TYPE(*CHAR) LEN(2000) DCL VAR(&POS) TYPE(*DEC) LEN(4 0) DCL VAR(&POSLIB) TYPE(*DEC) LEN(4 0) DCL VAR(&RTNLIB) TYPE(*CHAR) LEN(10) DCL VAR(&RTNSTRING) TYPE(*CHAR) LEN(5700) DCL VAR(&TYPE) TYPE(*CHAR) LEN(4) /* If necessary, make a copy of the *SYS source file list in + QTEMP. This will be considered the *JOB source file list. */ CHKOBJ OBJ(QTEMP/REXXSRCL) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(DO) RTVOBJD OBJ(REXXSRCL) OBJTYPE(*DTAARA) RTNLIB(&RTNLIB) CRTDUPOBJ OBJ(REXXSRCL) FROMLIB(&RTNLIB) OBJTYPE(*DTAARA) + TOLIB(QTEMP) NEWOBJ(REXXSRCL) ENDDO /* Retrieve the *SYS or *JOB source file list, as requested. + Keep in mind that the *JOB source file list is in QTEMP. */ IF COND(&TYPE *EQ '*SYS') THEN(DO) RTVDTAARA DTAARA(REXXSRCL *ALL) RTNVAR(&LIST) ENDDO ELSE CMD(DO) RTVDTAARA DTAARA(QTEMP/REXXSRCL *ALL) RTNVAR(&LIST) ENDDO /* Build the return string in &RTNSTRING so the command prompter + can show the names of the source files currently in the + source file list requested. The return string must begin + with a length (in binary, set to x'03F0' (1008 decimal), then + contain selective prompting for the parameters whose values + you want to show on the command prompter. In this case, the + SRCL parameter. */ CHGVAR VAR(&RTNSTRING) VALUE(&LENGTH *CAT '??SRCL(') CHGVAR VAR(&POS) VALUE(1) LOOP: + IF COND(%SST(&LIST &POS 10) *EQ ' ') THEN(GOTO CMDLBL(ENDLOOP)) CHGVAR VAR(&POSLIB) VALUE(&POS + 10) CHGVAR VAR(&RTNSTRING) VALUE(&RTNSTRING *BCAT %SST(&LIST &POSLIB + 10) *TCAT '/' *CAT %SST(&LIST &POS 10)) CHGVAR VAR(&POS) VALUE(&POS + 20) IF COND(&POS *LT 1000) THEN(GOTO CMDLBL(LOOP)) /* Close parenthesis for the SRCL parameter after all values + have been concatenated */ ENDLOOP: + CHGVAR VAR(&RTNSTRING) VALUE(&RTNSTRING *TCAT ')') ENDPGM
The REXX Source File List
Figure 2A Command RUNREXPGM
RUNREXPGM: CMD PROMPT('Run REXX Program') PARM KWD(PGM) TYPE(*NAME) LEN(10) MIN(1) + PROMPT('REXX program') PARM KWD(SRCFILE) TYPE(Q1) PROMPT('Source file') PARM KWD(PARM) TYPE(*CHAR) LEN(3000) DFT(*NONE) + PROMPT('Parameter string') Q1: QUAL TYPE(*NAME) LEN(10) DFT(*SRCL) SPCVAL((*SRCL)) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL)) PROMPT('Library')
The REXX Source File List
Figure 2B CL program REX003CL
REX003CL: + PGM PARM(&PGM &QSRCF &PARM) DCL VAR(&LIST) TYPE(*CHAR) LEN(1000) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) DCL VAR(&PARM) TYPE(*CHAR) LEN(3000) DCL VAR(&PGM) TYPE(*CHAR) LEN(10) DCL VAR(&POS) TYPE(*DEC) LEN(4 0) DCL VAR(&QSRCF) TYPE(*CHAR) LEN(20) DCL VAR(&RTNLIB) TYPE(*CHAR) LEN(10) DCL VAR(&SRCF) TYPE(*CHAR) LEN(10) DCL VAR(&SRCFLIB) TYPE(*CHAR) LEN(10) DCL VAR(&TESTF) TYPE(*CHAR) LEN(10) DCL VAR(&TESTFLIB) TYPE(*CHAR) LEN(10) MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) /* Break the qualified name of the source file */ CHGVAR VAR(&SRCF) VALUE(%SST(&QSRCF 1 10)) CHGVAR VAR(&SRCFLIB) VALUE(%SST(&QSRCF 11 10)) /* If *SRCL (source file list) support requested */ IF COND(&SRCF *EQ '*SRCL') THEN(DO) /* Copy the *SYS source file list as the *JOB source file + list, if the *JOB source file list doesn't exist yet. */ CHKOBJ OBJ(QTEMP/REXXSRCL) OBJTYPE(*DTAARA) MONMSG MSGID(CPF9801) EXEC(DO) RTVOBJD OBJ(REXXSRCL) OBJTYPE(*DTAARA) RTNLIB(&RTNLIB) CRTDUPOBJ OBJ(REXXSRCL) FROMLIB(&RTNLIB) OBJTYPE(*DTAARA) + TOLIB(QTEMP) NEWOBJ(REXXSRCL) ENDDO /* Retrieve the *JOB source file list and prepare for loop */ RTVDTAARA DTAARA(QTEMP/REXXSRCL) RTNVAR(&LIST) CHGVAR VAR(&POS) VALUE(1) LOOP: + IF COND(%SST(&LIST &POS 10) *EQ ' ') THEN(GOTO CMDLBL(ENDLOOP)) /* Determine if the REXX source member exists in the current + source file being examined (which is within the source + file list). If it doesn't exist, loop again; otherwise, + run the STRREXPRC using the source file and source file + library just checked. */ CHGVAR VAR(&TESTF) VALUE(%SST(&LIST &POS 10)) CHGVAR VAR(&POS) VALUE(&POS + 10) CHGVAR VAR(&TESTFLIB) VALUE(%SST(&LIST &POS 10)) CHGVAR VAR(&POS) VALUE(&POS + 10) CHKOBJ OBJ(&TESTFLIB/&TESTF) OBJTYPE(*FILE) MBR(&PGM) MONMSG MSGID(CPF0000) EXEC(DO) IF COND(&POS *LT 1000) THEN(GOTO CMDLBL(LOOP)) ENDDO STRREXPRC SRCMBR(&PGM) SRCFILE(&TESTFLIB/&TESTF) PARM(&PARM) /* End this program after running the REXX procedure */ RETURN /* Send *ESCAPE message if the REXX procedure wasn't found in + the source file list. */ ENDLOOP: + SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('REXX program' + *BCAT &PGM *BCAT 'not found in *SRCL') MSGTYPE(*ESCAPE) RETURN ENDDO /* If *SRCL support not requested, run the STRREXPRC command + straight */ ELSE CMD(DO) STRREXPRC SRCMBR(&PGM) SRCFILE(&SRCFLIB/&SRCF) PARM(&PARM) ENDDO RETURN /* Error trap */ ERROR: + RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + MSGFLIB(&MSGFLIB) SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) ENDPGM
LATEST COMMENTS
MC Press Online