Creating an MI version of the CLCRTPG program
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:
- Creates a user space (*USRSPC) object of 64KB size to hold the MI source.
- Overrides the MISRC file to the appropriate source physical file and member (1).
- Calls a second CL program (CL04), which loads the selected MISRC member into the user space (*USRSPC) (2).
- Calls an MI program (MICRTPG) (3). The MICRTPG program calls CL program CL05 (4) and passes addressability to the *USRSPC, where CL05 then calls the QPRCRTPG API (5).
The MICRTPG program demonstrates how to perform the following operations:
- Define a structure.
- Initialize declared storage
- Use two different approaches to resolve a system pointer to an external object.
- Assign a space pointer to address a user space.
- Call a program and pass three parameters.
The overall program flow for creating the MICRTPG program appears as follows:

Source for the CL03 program
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
Source for the CL04 program
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
Source for the CL05 program
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
Source for the MICRTPG program
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;
Writing the MICRTPG program (by sections of code)
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@);
Declaring the structure
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 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. The RSLVNAME user space is 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 Resolve System Pointer (RSLVSP).
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');
Declaring pointers
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;Defining an external call
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 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;Calling the CL05 Program
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;Creating the MICRTPG program
To create MICRTPG, use the following CL commands:
DLTOVR MISRC
OVRDBF MISRC MBR(MICRTPG)
CALL CLCRTPG MICRTPGAssuming 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).