This topic discusses how to create an MI version of the CLCRTPG program that can be used to create MI programs. This program is called MICRTPG.
Because the CLCRTPG program is used to create the initial version of MICRTPG and CLCRTPG can support only as many as 2000 bytes of source in the &MIPGMSRC variable, MICRTPG is initially defined with a minimal set of function. Significant additions to the MICRTPG program can be made after it is used as a building block in the creation of MI programs.
In the initial design (see the program flow in Source for the CL03 program), there are four programs. The first program is a CL program (CL03) that does the following:
The MICRTPG program demonstrates how to do the following:
The overall program flow for creating the MICRTPG program appears as follows:
The source for CL03 follows:
/********************************************************************/ /********************************************************************/ /* */ /* Program Name: CL03 */ /* */ /* Programming Language: CL */ /* */ /* Description: Main driver program for initial version of */ /* MI program MICRTPG. This program creates a */ /* *USRSPC, calls CL04 to load MI source from */ /* a *SRC physical file into the *USRSPC, and */ /* then calls MICRTPG to create MI programs. */ /* */ /* Header Files Included: None */ /* */ /* */ /********************************************************************/ PGM PARM(&FILE &MBR) DCL VAR(&FILE) TYPE(*CHAR) LEN(10) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&SPCNAM) TYPE(*CHAR) LEN(20) + VALUE(' *CURLIB ') DCL VAR(&SPCEXTATR) TYPE(*CHAR) LEN(10) VALUE(' ') DCL VAR(&SPCSIZ) TYPE(*CHAR) LEN(4) + VALUE(X'00010000') DCL VAR(&SPCINTVAL) TYPE(*CHAR) LEN(1) VALUE(X'00') DCL VAR(&SPCSPCAUT) TYPE(*CHAR) LEN(10) + VALUE('*ALL') DCL VAR(&SPCTXTDSC) TYPE(*CHAR) LEN(50) VALUE(' ') DCL VAR(&SPCRPLOPT) TYPE(*CHAR) LEN(10) + VALUE('*YES') DCL VAR(&ERRCOD) TYPE(*CHAR) LEN(4) + VALUE(X'00000000') DCL VAR(&SPCDMN) TYPE(*CHAR) LEN(10) VALUE('*USER') DCL VAR(&BINOFFSET) TYPE(*CHAR) LEN(4) + VALUE(X'00000001') CHGVAR VAR(%SST(&SPCNAM 1 10)) VALUE(&MBR) CALL PGM(QUSCRTUS) PARM(&SPCNAM &SPCEXTATR + &SPCSIZ &SPCINTVAL &SPCSPCAUT &SPCTXTDSC + &SPCRPLOPT &ERRCOD &SPCDMN) OVRDBF FILE(MISRC) TOFILE(&FILE) MBR(&MBR) CALL PGM(CL04) PARM(&MBR &BINOFFSET) CALL PGM(MICRTPG) PARM(&MBR &BINOFFSET) ENDPGM
The source for CL04 follows:
/********************************************************************/ /********************************************************************/ /* */ /* Program Name: CL04 */ /* */ /* Programming Language: CL */ /* */ /* Description: Load a source physical file member into the */ /* *USRSPC named &MBR. */ /* */ /* */ /* Header Files Included: None */ /* */ /* */ /********************************************************************/ PGM PARM(&MBR &BINOFFSET) DCLF FILE(MISRC) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&BINOFFSET) TYPE(*CHAR) LEN(4) DCL VAR(&OFFSET) TYPE(*DEC) LEN(8 0) VALUE(1) DCL VAR(&LENGTH) TYPE(*CHAR) LEN(4) + VALUE(X'00000050') DCL VAR(&SPCNAM) TYPE(*CHAR) LEN(20) + VALUE(' *LIBL ') CHGVAR VAR(%SST(&SPCNAM 1 10)) VALUE(&MBR) LOOP: RCVF MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(DONE)) CALL PGM(QUSCHGUS) PARM(&SPCNAM &BINOFFSET + &LENGTH &SRCDTA '0') CHGVAR VAR(&OFFSET) VALUE(&OFFSET + 80) CHGVAR VAR(%BIN(&BINOFFSET)) VALUE(&OFFSET) GOTO CMDLBL(LOOP) DONE: ENDPGM
The source for CL05 follows:
/********************************************************************/ /********************************************************************/ /* */ /* Program Name: CL05 */ /* */ /* Programming Language: CL */ /* */ /* Description: Create an MI program using the QPRCRTPG API. */ /* */ /* */ /* Header Files Included: None */ /* */ /* */ /********************************************************************/ PGM PARM(&SRCMBR &MIPGMSRC &MIPGMSRCSZ) DCL VAR(&SRCMBR) TYPE(*CHAR) LEN(10) DCL VAR(&MIPGMSRC) TYPE(*CHAR) LEN(1) DCL VAR(&MIPGMSRCSZ) TYPE(*CHAR) LEN(4) DCL VAR(&PGMNAM) TYPE(*CHAR) LEN(20) + VALUE(' *CURLIB ') DCL VAR(&PGMTXT) TYPE(*CHAR) LEN(50) + VALUE(' ') DCL VAR(&PGMSRCF) TYPE(*CHAR) LEN(20) + VALUE('*NONE') DCL VAR(&PGMSRCM) TYPE(*CHAR) LEN(10) VALUE(' ') DCL VAR(&PGMSRCCHG) TYPE(*CHAR) LEN(13) VALUE(' ') DCL VAR(&PRTFNAM) TYPE(*CHAR) LEN(20) + VALUE('QSYSPRT *LIBL ') DCL VAR(&PRTSTRPAG) TYPE(*CHAR) LEN(4) + VALUE(X'00000001') DCL VAR(&PGMPUBAUT) TYPE(*CHAR) LEN(10) + VALUE('*ALL ') DCL VAR(&PGMOPTS) TYPE(*CHAR) LEN(22) + VALUE('*LIST *REPLACE ') DCL VAR(&NUMOPTS) TYPE(*CHAR) LEN(4) + VALUE(X'00000002') CHGVAR VAR(%SST(&PGMNAM 1 10)) VALUE(&SRCMBR) CALL PGM(QSYS/QPRCRTPG) PARM(&MIPGMSRC + &MIPGMSRCSZ &PGMNAM &PGMTXT &PGMSRCF + &PGMSRCM &PGMSRCCHG &PRTFNAM &PRTSTRPAG + &PGMPUBAUT &PGMOPTS &NUMOPTS) ENDPGM
The source for MICRTPG follows:
/********************************************************************/ /********************************************************************/ /* */ /* Program Name: MICRTPG */ /* */ /* Programming Language: MI */ /* */ /* Description: Initial version of MI program to create */ /* additional MI programs using the QPRCRTPG API. */ /* */ /* */ /* Header Files Included: None */ /* */ /* */ /********************************************************************/ ENTRY * (PARM_LIST) EXT; DCL SPCPTR MBR@ PARM; DCL SPCPTR BINOFFSET@ PARM; DCL OL PARM_LIST (MBR@, BINOFFSET@) PARM EXT; DCL DD MBR CHAR(10) BAS(MBR@); DCL DD BINOFFSET BIN(4) BAS(BINOFFSET@); DCL DD RSLVOBJ CHAR(34); DCL DD RSLVTYPE CHAR(1) DEF(RSLVOBJ) POS(1) INIT(X'19'); DCL DD RSLVSUBTYPE CHAR(1) DEF(RSLVOBJ) POS(2) INIT(X'34'); DCL DD RSLVNAME CHAR(30) DEF(RSLVOBJ) POS(3); DCL DD RSLVAUTH CHAR(2) DEF(RSLVOBJ) POS(33) INIT(X'0000'); DCL SYSPTR USRSPCOBJ; DCL SPCPTR USRSPC; DCL SYSPTR CL05 INIT("CL05", TYPE(PGM)); DCL OL CL05OL (MBR@, USRSPC, BINOFFSET@) ARG; CPYBLAP RSLVNAME, MBR, ' '; RSLVSP USRSPCOBJ, RSLVOBJ, *, *; SETSPPFP USRSPC, USRSPCOBJ; CALLX CL05, CL05OL, *; RTX *; PEND;
You will recognize some of these statements from the MI01 example, but others are new.
The following statements, which you have seen, for example, in MI01 program complete code example, define the entry point to this program and the parameters being passed on the call:
ENTRY * (PARM_LIST) EXT; DCL SPCPTR MBR@ PARM; DCL SPCPTR BINOFFSET@ PARM; DCL OL PARM_LIST (MBR@, BINOFFSET@) PARM EXT; DCL DD MBR CHAR(10) BAS(MBR@); DCL DD BINOFFSET BIN(4) BAS(BINOFFSET@);
The following, however, are new statements:
DCL DD RSLVOBJ CHAR(34); DCL DD RSLVTYPE CHAR(1) DEF(RSLVOBJ) POS(1) INIT(X'19'); DCL DD RSLVSUBTYPE CHAR(1) DEF(RSLVOBJ) POS(2) INIT(X'34'); DCL DD RSLVNAME CHAR(30) DEF(RSLVOBJ) POS(3); DCL DD RSLVAUTH CHAR(2) DEF(RSLVOBJ) POS(33) INIT(X'0000');
These statements declare a structure named RSLVOBJ that comprises four subelements defined within it. The subelements specify their position relative to the start of the structure RSLVOBJ. In the cases of the RSLVTYPE, RSLVSUBTYPE, and RSLVAUTH data elements, they initialize the associated storage.
The RSLVOBJ structure is used later in the program as an input to the resolve system pointer (RSLVSP) MI instruction. The RSLVSP instruction resolves (establishes addressability) to a user space (*USRSPC) (the X'1934' object type and subtype) named RSLVNAME (assigned from the source member name (MBR) data element). This user space is the one created in Source for the CL03 program. If you are interested in the details of this structure, see iSeries™ Machine Interface instructions under RSLVSP. For other valid object types and subtypes, see Object types.
DCL DD RSLVOBJ CHAR(34); DCL DD RSLVTYPE CHAR(1) DEF(RSLVOBJ) POS(1) INIT(X'19'); DCL DD RSLVSUBTYPE CHAR(1) DEF(RSLVOBJ) POS(2) INIT(X'34'); DCL DD RSLVNAME CHAR(30) DEF(RSLVOBJ) POS(3); DCL DD RSLVAUTH CHAR(2) DEF(RSLVOBJ) POS(33) INIT(X'0000');
The next statements declare a system pointer named USRSPCOBJ and a space pointer named USRSPC. USRSPCOBJ contains the address of the *USRSPC object after the execution of the RSLVSP instruction later in the instruction stream. USRSPC addresses the first byte of the *USRSPC:
DCL SYSPTR USRSPCOBJ; DCL SPCPTR USRSPC;
Because this program also uses the call external (CALLX) instruction to call the CL program CL05, define a system pointer for CL05:
DCL SYSPTR CL05 INIT("CL05", TYPE(PGM));
The preceding statement causes the QPRCRTPG API to initialize the system pointer CL05 to the name of the PGM CL05. The CL05 pointer is not set to the address of the CL05 object--this happens the first time the CL05 pointer is referred to in the instruction stream. If you review the declare statement in the QPRCRTPG API, notice that the context (CTX) argument uses the default. Using the context default (better known as library to most programmers) is equivalent to specifying *LIBL. *LIBL is referred to as the process name resolution list in the iSeries Machine Interface instructions.
Because this program calls the CL05 program (CALLX CL05) with parameters, it now defines an operand list CL05OL, which specifies the arguments to be passed on the CALLX:
DCL OL CL05OL (MBR@, USRSPC, BINOFFSET@) ARG;
When you get to the instruction stream of MICRTPG, copy the passed parameter MBR to the data structure element RSLVNAME. As RSLVNAME is defined as CHAR(30) and MBR is CHAR(10), the program uses the copy bytes left-justified with pad (CPYBLAP) instruction to set the rightmost 20 bytes of RSLVNAME to the value of the third argument (in this case, blanks):
CPYBLAP RSLVNAME, MBR, ' ';
Having established the *USRSPC name, use the RSLVSP instruction to get addressability to the object itself:
RSLVSP USRSPCOBJ, RSLVOBJ, *, *;
Then set the USRSPC space pointer to the first byte of the *USRSPC:
SETSPPFP USRSPC, USRSPCOBJ;
Now the program will call the CL05 program (CALLX CL05) and pass the address of the *USRSPC as a parameter (along with the member name, program name, and the size of the source stream). When you call CL05 with the operand list CL05OL, CL05 passes the actual space pointer USRSPC. CL05 does not pass a space pointer that refers to the space pointer USRSPC (as opposed to how MBR@ and BINOFFSET@ are passed to refer to MBR and BINOFFSET, respectively). This has the effect of having the CL05 program treat the *USRSPC storage as the parameter:
CALLX CL05, CL05OL, *;
Finally, as the program comes to an end, this is the return external instruction and pend directive for the initial version of MICRTPG:
RTX *; PEND;
To create MICRTPG, use the following CL commands:
DLTOVR MISRC OVRDBF MISRC MBR(MICRTPG) CALL CLCRTPG MICRTPG
Assuming a successful creation, the CLCRTPG program is not used again because of the MI base with which to work (for example, MICRTPG is used as a boot-strap for further compiler enhancement).