Creating an MI version of CLCRTPG

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.

Note: Read the Code license and disclaimer information for important legal information.

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:


Program flow for creating the MICRTPG program

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;

Understanding 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 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.

Note: In the declare (DCL) statement of RSLVOBJ, the leading blanks used to indent the subelements (for example, RSLVTYPE and RSLVSUBTYPE) are strictly to enhance the readability of the source. They are not a requirement of the QPRCRTPG API. In general, you can use strings of blanks of any length in the source of a program. Blanks, one or more, are simply used as delimiters in identifying tokens. The major exception is the INIT argument of a DCL statement where the number of blanks is important. For example, the previous declare statement could have been written as follows and other than readability, nothing would have been lost:
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 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, *, *;
Note: Similar to how the *USRSPC name was resolved, RSLVSP could be used with a type of X'02' and a subtype of X'01' to resolve a system pointer to the CL05 *PGM object. The two different approaches were used to demonstrate the different styles (RSLVSP is clearly more flexible) and also to stay within the 2000-byte limit of the program source size imposed by the CLCRTPG program.

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 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).

Related reference
Example: Writing an MI program
iSeries Machine Interface instructions
Internal object types
QPRCRTPG API