<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="Compile an MI program" />
<meta name="abstract" content="To compile an MI program, use the Create Program (QPRCRTPG) API." />
<meta name="description" content="To compile an MI program, use the Create Program (QPRCRTPG) API." />
<meta name="DC.Relation" scheme="URI" content="MIpgmg.htm" />
<meta name="DC.Relation" scheme="URI" content="../apis/qprcrtpg.htm" />
<meta name="DC.Relation" scheme="URI" content="../rzatk/mitoc.htm" />
<meta name="DC.Relation" scheme="URI" content="MIcrever.htm" />
<meta name="DC.Relation" scheme="URI" content="MIcrepro.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="MIcompprog" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Compile an MI program</title>
</head>
<body id="MIcompprog"><a name="MIcompprog"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Compile an MI program</h1>
<div><p>To compile an MI program, use the Create Program (QPRCRTPG) API. </p>
<div class="section"><div class="note"><span class="notetitle">Note:</span> Read the <a href="codedisclaimer.htm">Code license and disclaimer information</a> for important
legal information.</div>
<p>If you enter the source into a source physical
file, you can now compile the source and create an MI program. </p>
<div class="note"><span class="notetitle">Note:</span> The
QPRCRTPG API assumes that the source statements presented to it are in code
page 37. See iSeries™ Machine
Interface instructions for the specific code points required to build MI programs.</div>
</div>
<div class="section"><h4 class="sectiontitle">Use CLCRTPG to create an MI program</h4><p>Assume that
the source is in a member named MI01 in the source file MISRC, which is created
with a default record length (RCDLEN) of 92. The following CLCRTPG CL program
can be used to create an MI program called MI01. (An MI program to call the
Create Program (QPRCRTPG) API is developed in Creating an MI version of CLCRTPG.)</p>
<div class="note"><span class="notetitle">Note:</span> All
non-MI source examples are provided in CL, because CL is the one language
(other than REXX) that is standard on all systems. Other high-level languages
(HLLs) could be used in place of the CL programs (and in many cases would
have been easier).</div>
<p>The following program reads a source file member
into a program variable (&amp;MIPGMSRC) and then does a CALL to the QPRCRTPG
API. This program has many limitations (the major limitation is a program
variable-size limit of 2000 bytes for the source), but provides for a reasonably
simple MI program creation scenario.</p>
<div class="note"><span class="notetitle">Note:</span> By using the code examples,
you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
<pre>/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: CLCRTPG                                        */
/*                                                                  */
/*     Programming Language: CL                                     */
/*                                                                  */
/*     Description: Create an MI program using the QPRCRTPG API.    */
/*                                                                  */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
             PGM        PARM(&amp;SRCMBR)
             DCLF       FILE(MISRC)
             DCL        VAR(&amp;SRCMBR) TYPE(*CHAR) LEN(10)
             DCL        VAR(&amp;MIPGMSRC) TYPE(*CHAR) LEN(2000)
             DCL        VAR(&amp;MIPGMSRCSZ) TYPE(*CHAR) LEN(4)
             DCL        VAR(&amp;OFFSET) TYPE(*DEC) LEN(5 0) VALUE(1)
             DCL        VAR(&amp;PGMNAM) TYPE(*CHAR) LEN(20) +
                          VALUE('          *CURLIB   ')
             DCL        VAR(&amp;PGMTXT) TYPE(*CHAR) LEN(50) +
                          VALUE('Compare two packed arguments and +
                          return larger')
             DCL        VAR(&amp;PGMSRCF) TYPE(*CHAR) LEN(20) +
                          VALUE('*NONE')
             DCL        VAR(&amp;PGMSRCM) TYPE(*CHAR) LEN(10) VALUE(' ')
             DCL        VAR(&amp;PGMSRCCHG) TYPE(*CHAR) LEN(13) VALUE(' ')
             DCL        VAR(&amp;PRTFNAM) TYPE(*CHAR) LEN(20) +
                          VALUE('QSYSPRT   *LIBL     ')
             DCL        VAR(&amp;PRTSTRPAG) TYPE(*CHAR) LEN(4) +
                          VALUE(X'00000001')
             DCL        VAR(&amp;PGMPUBAUT) TYPE(*CHAR) LEN(10) +
                          VALUE('*ALL      ')
             DCL        VAR(&amp;PGMOPTS) TYPE(*CHAR) LEN(22) +
                          VALUE('*LIST      *REPLACE   ')
             DCL        VAR(&amp;NUMOPTS) TYPE(*CHAR) LEN(4) +
                          VALUE(X'00000002')
 LOOP:       RCVF
             MONMSG     MSGID(CPF0864) EXEC(GOTO CMDLBL(CRTPGM))
             CHGVAR     VAR(%SST(&amp;MIPGMSRC &amp;OFFSET 80)) VALUE(&amp;SRCDTA)
             CHGVAR     VAR(&amp;OFFSET) VALUE(&amp;OFFSET + 80)
             GOTO       CMDLBL(LOOP)
 CRTPGM:     CHGVAR     VAR(%SST(&amp;PGMNAM 1 10)) VALUE(&amp;SRCMBR)
             CHGVAR     VAR(%BIN(&amp;MIPGMSRCSZ)) VALUE(&amp;OFFSET)
             CALL       PGM(QSYS/QPRCRTPG) PARM(&amp;MIPGMSRC +
                          &amp;MIPGMSRCSZ &amp;PGMNAM &amp;PGMTXT &amp;PGMSRCF +
                          &amp;PGMSRCM &amp;PGMSRCCHG &amp;PRTFNAM &amp;PRTSTRPAG +
                          &amp;PGMPUBAUT &amp;PGMOPTS &amp;NUMOPTS)
             ENDPGM</pre>
</div>
<div class="section" id="MIcompprog__miexample"><a name="MIcompprog__miexample"><!-- --></a><h4 class="sectiontitle">Create the MI example program</h4><p>After
creating the CL program (assumed to be called CLCRTPG), the following statements
create the previous MI program MI01:</p>
<pre>DLTOVR MISRC
OVRDBF MISRC MBR(MI01)
CALL CLCRTPG MI01</pre>
<div class="note"><span class="notetitle">Note:</span> If the creation of MI01 fails, you should closely compare
your source to that shown in this chapter. In general, consider the QPRCRTPG
error messages that refer to "probable compiler error" as referring to your
input source and not that the QPRCRTPG API itself is in error. (QPRCRTPG assumes
its input is probably from a high-level language (HLL) compiler.)</div>
<p>Further,
if the error message is CPF6399 (Identifier not declared), you can get an
object definition table (ODT) listing by adding *XREF to the option template
parameter (variable &amp;PGMOPTS in the CLCRTPG program) when calling the
QPRCRTPG API. Add *XREF to the existing *LIST and *REPLACE options, and change
the number of option template entries parameter (variable &amp;NUMOPTS) to
3.</p>
</div>
<div class="section"><h4 class="sectiontitle">Test MI01</h4><div class="p">In this topic, assume that MI01 was successfully
created.<div class="note"><span class="notetitle">Note:</span> By using the code examples, you agree to the terms of the <a href="codedisclaimer.htm">Code license and disclaimer information</a>.</div>
</div>
<pre>/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: CL01                                           */
/*                                                                  */
/*     Programming Language: CL                                     */
/*                                                                  */
/*     Description: Test the MI program MI01.                       */
/*                                                                  */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
             PGM        PARM(&amp;ARG1 &amp;ARG2)
             DCL        VAR(&amp;ARG1) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;ARG2) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;RESULT) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;MSG) TYPE(*CHAR) LEN(20)
             DCL        VAR(&amp;USR) TYPE(*CHAR) LEN(10)
             RTVJOBA    USER(&amp;USR)
             CALL       PGM(MI01) PARM(&amp;ARG1 &amp;ARG2 &amp;RESULT)
             CHGVAR     VAR(&amp;MSG) VALUE(&amp;RESULT)
             SNDMSG     MSG(&amp;MSG) TOUSR(&amp;USR)
             ENDPGM</pre>
<p>The following statement calls the CL01 program:</p>
<pre>CALL CL01 (-5    6)</pre>
<p>This
test should cause a message to be sent to your user message queue with the
following value:</p>
<pre>00000000000006.00000</pre>
</div>
<div class="section"><h4 class="sectiontitle">Debug the MI program</h4><p>The MI program (MI01) that
you created is a standard *PGM object on the iSeries system. As you would expect,
you can call MI01 from other high-level languages. You can delete MI01 with
the Delete Program (DLTPGM) command, save and restore MI01 using the standard
save (SAV) and restore (RST) commands, and so on.</p>
<p>You can also debug
it using the standard debugger on the system. To debug it, you need to look
at the listing produced by the QPRCRTPG API to determine the MI instruction
number. Then use that number with the Add Breakpoint (ADDBKP) CL command.
For example, when creating MI01 in the previous exercise, the following listing
was generated by QPRCRTPG:</p>

<div class="tablenoborder"><table cellpadding="4" cellspacing="0" summary="" frame="border" border="1" rules="all"><tbody><tr><td valign="top"> <pre>5763SS1 V3R1M0 940909                                Generated Output                                 08/08/94 09:46:36  Page     1
  SEQ <span class="uicontrol">(1)</span>INST Offset    Generated Code     *... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 6 ... ... 7 ... ... 8
 00001                                             ENTRY * (PARM_LIST) EXT                                               ;
 00002                                             DCL SPCPTR ARG1@ PARM                                                 ;
 00003                                             DCL SPCPTR ARG2@ PARM                                                 ;
 00004                                             DCL SPCPTR RESULT@ PARM                                               ;
 00005                                             DCL OL PARM_LIST (ARG1@, ARG2@, RESULT@) PARM EXT                     ;
 00006                                             DCL DD ARG1 PKD(15,5) BAS(ARG1@)                                      ;
 00007                                             DCL DD ARG2 PKD(15,5) BAS(ARG2@)                                      ;
 00008                                             DCL DD RESULT PKD(15,5) BAS(RESULT@)                                  ;
 00009  0001 000004  3C46 2000 0006 0007           CMPNV(B) ARG1,ARG2 / LO(ITS2)                                         ;
                     0009
 00010  0002 00000E  1042 0008 0006                CPYNV RESULT,ARG1                                                     ;
 00011  0003 000014  1011 000A                     B RETURN                                                              ;
 00012  0004 000018  3042 0008 0007       ITS2:    CPYNV RESULT,ARG2                                                     ;
 00013  0005 00001E  22A1 0000  <span class="uicontrol">(2)</span>        RETURN:  RTX *                                                                ;
 00014  0006 000022  0260                          PEND                                                                  ;
 5763SS1 V3R1M0 940909                                Generated Output                                 08/08/94 09:46:36  Page     2
  MSGID    ODT   ODT Name                                          Semantics and ODT Syntax Diagnostics
 5763SS1 V3R1M0 940909                                Generated Output                                 08/08/94 09:46:36  Page     3
   MSGID   MI Instruction Stream Semantic Diagnostics
</pre>
 </td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="section"><h4 class="sectiontitle">Set breakpoints in the MI program</h4><p>To view the value
of RESULT at label RETURN, you first determine that RETURN corresponds to
MI instruction (<span class="uicontrol">(1)</span>) 0005 (<span class="uicontrol">(2)</span>)
and enter the following CL commands:</p>
<pre>STRDBG PGM(MI01)
ADDBKP STMT('/0005') PGMVAR((RESULT ()))
CALL CL01 (-5    6)</pre>
<p>The following display is shown:</p>
<pre>+--------------------------------------------------------------------------------+
|                                                                                |
|                               Display Breakpoint                               |
|                                                                                |
|  Statement/Instruction . . . . . . . . . : /0005                               |
|  Program . . . . . . . . . . . . . . . . : MI01                                |
|  Recursion level . . . . . . . . . . . . : 1                                   |
|  Start position  . . . . . . . . . . . . : 1                                   |
|  Format  . . . . . . . . . . . . . . . . : *CHAR                               |
|  Length  . . . . . . . . . . . . . . . . : *DCL                                |
|                                                                                |
|  Variable  . . . . . . . . . . . . . . . : RESULT                              |
|    Type  . . . . . . . . . . . . . . . . :   PACKED                            |
|    Length  . . . . . . . . . . . . . . . :   15 5                              |
|   '          6.00000'                                                          |
|                                                                                |
+--------------------------------------------------------------------------------+</pre>
<p>Breakpoints also can be set with a directive statement. Given
that the MI01 program is able to be debugged and a break directive was not
used, the purpose for which you use the directive may not be obvious. As mentioned
in <a href="#MIcompprog__miexample">Create the MI example program</a>, many expected users of the
QPRCRTPG API are compilers of HLLs. The break (BRK) directive allows users
of the QPRCRTPG API to associate an HLL statement identifier with a generated
MI instruction. For example, assume that MI01 was developed to be an implementation
of a fictional HLL language statement such as:</p>
<pre>RESULT = MAX(ARG1, ARG2)</pre>
<p>This
assigns the MAX (defined as the largest argument) of ARG1 or ARG2 to RESULT.
Also assume that an HLL programmer had written a program called HLLEXAMPLE
with the following statements:</p>
<pre>00001  RESULT = MAX(ARG1, ARG2)
00002  EXIT</pre>
<p>By using break (BRK) directives, the QPRCRTPG user
or compiler could associate the HLL statements with the generated MI instructions
in the following way.</p>
<pre>/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: MI01                                           */
/*                                                                  */
/*     Programming Language: MI                                     */
/*                                                                  */
/*     Description: Demonstrate how to associate HLL statement      */
/*                  identifiers with MI instructions using BRK      */
/*                  directives.                                     */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
ENTRY * (PARM_LIST) EXT;
DCL     SPCPTR      ARG1@      PARM;
DCL     SPCPTR      ARG2@      PARM;
DCL     SPCPTR      RESULT@    PARM;
DCL     OL          PARM_LIST
                   (ARG1@,
                    ARG2@,
                    RESULT@)
                    PARM       EXT;
DCL     DD          ARG1       PKD(15,5)     BAS(ARG1@);
DCL     DD          ARG2       PKD(15,5)     BAS(ARG2@);
DCL     DD          RESULT     PKD(15,5)     BAS(RESULT@);
BRK "00001";
        CMPNV(B)    ARG1,ARG2  / LO(ITS2);
        CPYNV       RESULT,ARG1;
        B           RETURN;
ITS2:   CPYNV       RESULT,ARG2;
BRK "00002";
RETURN: RTX         *;
        PEND;</pre>
<p>This allows the HLL programmer to use the following to debug
the HLL program by using the statement identifiers of the HLL:</p>
<pre>STRDBG PGM(HLLEXAMPLE)
ADDBKP STMT(00002) PGMVAR((RESULT ()))</pre>
<p>The following display
shows that the HLL statement 00002 has been equated with MI instruction 0005
due to the use of BRK directives:</p>
<pre>+--------------------------------------------------------------------------------+
|                                                                                |
|                                                                                |
|                                                                                |
|                               Display Breakpoint                               |
|                                                                                |
|  Statement/Instruction . . . . . . . . . : 00002 /0005                         |
|  Program . . . . . . . . . . . . . . . . : HLLEXAMPLE                          |
|  Recursion level . . . . . . . . . . . . : 1                                   |
|  Start position  . . . . . . . . . . . . : 1                                   |
|  Format  . . . . . . . . . . . . . . . . : *CHAR                               |
|  Length  . . . . . . . . . . . . . . . . : *DCL                                |
|                                                                                |
|  Variable  . . . . . . . . . . . . . . . : RESULT                              |
|    Type  . . . . . . . . . . . . . . . . :   PACKED                            |
|    Length  . . . . . . . . . . . . . . . :   15 5                              |
|   '          6.00000'                                                          |
|                                                                                |
+--------------------------------------------------------------------------------+
</pre>
</div>
<div class="section"><h4 class="sectiontitle">Handle exceptions in the MI program</h4><p>As coded, the
MI01 program works fine when it is passed packed decimal parameters. But when
the MI01 program is passed other data types, such as in CALL CL01 (abc 6),
exceptions occur. To handle these exceptions, additional statements could
be added to MI01 so that:</p>
<ul><li>A 1-character return code parameter returns a status where <samp class="codeph">0</samp> indicates
no error and <samp class="codeph">1</samp> indicates an error occurred.</li>
<li>An exception description is defined to handle MCH1202 decimal data errors.</li>
</ul>
<p>Add the following statements to MI01:</p>
<ol><li>Declare a fourth space parameter to receive the return code parameter: <pre>DCL     SPCPTR      RC@        PARM;</pre>
</li>
<li>Update the operand list directive for PARM_LIST: <pre>DCL     OL          PARM_LIST
                   (ARG1@,
                    ARG2@,
                    RESULT@,
                    RC@)              /* the new parameter  */
                    PARM       EXT;</pre>
</li>
<li>Declare the storage addressed by RC@ as a 1-byte character data element: <pre>DCL     DD          RC         CHAR(1)       BAS(RC@);</pre>
</li>
<li>Declare an exception handler for MCH1202. With this exception description,
all occurrences of MCH1202 will cause an immediate (IMD) branch to label M1202. <pre>DCL     EXCM        DATAERROR  EXCID(H'0C02') BP (M1202) IMD;</pre>
<div class="note"><span class="notetitle">Note:</span> The EXCID is the hexadecimal representation of the message identifier
string 1202 where 12 = X'0C' and 02 = X'02'. While most MCH errors follow
this relationship of message ID string to hexadecimal EXCID, you should always
refer to the iSeries Machine
Interface instructions to determine what specific exception IDs may be signaled
by a given MI statement.</div>
</li>
<li>Because label M1202 is being used to indicate an error, set the return
code to <samp class="codeph">1</samp> by using copy bytes left-justified and then end: <pre>M1202:  CPYBLA      RC,'1';
        RTX         *;
        PEND;</pre>
<p>A more complete example of how to handle exceptions is provided
in Handling exceptions in the MICRTPG2 program.</p>
</li>
<li>Because the non-M1202 path indicates that no error was detected, update
the normal return path: <pre>RETURN: CPYBLA      RC,'0';</pre>
</li>
<li>Because M1202 was appended to the end of the MI01 source, remove the original
MI01 PEND directive.</li>
</ol>
<p>The an updated view of the MI01 program is as follows:</p>
<pre>/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: MI01                                           */
/*                                                                  */
/*     Programming Language: MI                                     */
/*                                                                  */
/*     Description: Enhanced version of MI program MI01 that        */
/*                  demonstrates enabling an exception monitor.     */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
ENTRY * (PARM_LIST) EXT;
DCL     SPCPTR      ARG1@      PARM;
DCL     SPCPTR      ARG2@      PARM;
DCL     SPCPTR      RESULT@    PARM;
DCL     SPCPTR      RC@        PARM;
DCL     OL          PARM_LIST
                   (ARG1@,
                    ARG2@,
                    RESULT@,
                    RC@)
                    PARM       EXT;
DCL     DD          ARG1       PKD(15,5)     BAS(ARG1@);
DCL     DD          ARG2       PKD(15,5)     BAS(ARG2@);
DCL     DD          RESULT     PKD(15,5)     BAS(RESULT@);
DCL     DD          RC         CHAR(1)       BAS(RC@);
DCL     EXCM        DATAERROR  EXCID(H'0C02') BP (M1202) IMD;
        CMPNV(B)    ARG1,ARG2  / LO(ITS2);
        CPYNV       RESULT,ARG1;
        B           RETURN;
ITS2:   CPYNV       RESULT,ARG2;
RETURN: CPYBLA      RC,'0';
        RTX         *;
M1202:  CPYBLA      RC,'1';
        RTX         *;
        PEND;</pre>
<p>The following example updates CL01 to support the new return
code parameter:</p>
<pre>/********************************************************************/
/********************************************************************/
/*                                                                  */
/*     Program Name: CL01                                           */
/*                                                                  */
/*     Programming Language: CL                                     */
/*                                                                  */
/*     Description: Enhanced version of CL program CL01 that        */
/*                  demonstrates the use of enhanced MI01.          */
/*                                                                  */
/*     Header Files Included: None                                  */
/*                                                                  */
/*                                                                  */
/********************************************************************/
             PGM        PARM(&amp;ARG1 &amp;ARG2)
             DCL        VAR(&amp;ARG1) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;ARG2) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;RESULT) TYPE(*DEC) LEN(15 5)
             DCL        VAR(&amp;RC) TYPE(*CHAR) LEN(1)
             DCL        VAR(&amp;MSG) TYPE(*CHAR) LEN(20)
             DCL        VAR(&amp;USR) TYPE(*CHAR) LEN(10)
             RTVJOBA    USER(&amp;USR)
             CALL       PGM(MI01) PARM(&amp;ARG1 &amp;ARG2 &amp;RESULT &amp;RC)
             IF         COND(&amp;RC = '0') +
               THEN(CHGVAR     VAR(&amp;MSG) VALUE(&amp;RESULT))
             ELSE +
               CHGVAR     VAR(&amp;MSG) VALUE('ERROR FOUND')
             SNDMSG     MSG(&amp;MSG) TOUSR(&amp;USR)
             ENDPGM</pre>
<p>After recompiling the MI01 program and the CL01 program, CALL
CL01 (abc 6) now results in the following message (not the previous MCH1202):</p>
<pre>ERROR FOUND</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="MIpgmg.htm" title="Provides information about creating machine interface (MI) programs.">Machine interface programming</a></div>
</div>
<div class="relref"><strong>Related reference</strong><br />
<div><a href="../apis/qprcrtpg.htm">Create Program (QPRCRTPG)</a></div>
<div><a href="../rzatk/mitoc.htm">iSeries Machine Interface instructions</a></div>
<div><a href="MIcrever.htm">Creating an MI version of CLCRTPG</a></div>
<div><a href="MIcrepro.htm" title="This topic shows how to create the MICRTPG2 program and how to handle exceptions in the MICRTPG2 program.">Create the MICRTPG2 program</a></div>
</div>
</div>
</body>
</html>