Tools

19. MI コンパイラー

MI (Machine Interface) とはマシンインターフェース言語であり、ほとんど機械語に近い。
MI 関数は C/400 からの利用することができるが、直接、MI プログラムを作成することができる。
我々が良く知るRPG もコンパイラーによって MI の集合として作成されているのである。
それでは MI は何のために必要となるのであろうか ?
実は MI を使えば Systemi5 のオブジェクトを直接、読み取ることができる。
多くはオブジェクトを読み取ってユーザー・スペースに保管して、それを上位の高級言語(RPG,
COBOL,C/400 ...) で処理するという具合である。

もちろん MI 言語のためのコンパイラーも OS400 にも用意されている。
API のマニュアルで「プログラムおよび CLPコマンド API」 には「QPRCRTPG:プログラムの作成」
というAPI があるが、何ための API であるのか不思議に思った人も少なくはないであろう。
実はこれが MI 言語のコンパイラーである。
しかし OS400 には CRTMIPGM というコマンドは存在していない。
IBM は API:QPRCRTPG を使って自分でコンパイラーを作りなさい、という訳である。

筆者もあるオブジェクトのソースを取り出すために(別に不正なことをしているわけではないが)
ある MI を入手したのだが、これが正しく動作しないのに気づいた。
そこで MI ソースを修正してコンパイルということになるが、確か MI コンパイラーの自作が必要で
あることを思い出した。
手元の AS/400 の中をいくつか探してみると、正しく動作する MI コンパイラーを過去に作成して
いるようなので、ここに紹介しよう。
コマンド名は CRTMIPGM である。

【 CMD : CRTMIPGM 】
 CRTMIPGM:   CMD        PROMPT(' MIプログラムの作成 ')                
 PGM:        PARM       KWD(PGM) TYPE(QUAL1) MIN(1) PGM(*YES) +         
                          PROMPT(' プログラム ')                        
 SRCFILE:    PARM       KWD(SRCFILE) TYPE(QUAL2) FILE(*UNSPFD) +        
                          PROMPT(' 原始ファイル ')                      
 SRCMBR:     PARM       KWD(SRCMBR) TYPE(*NAME) LEN(10) DFT(*PGM) +     
                          SPCVAL((*PGM)) PROMPT(' 原始メンバー ')       
 TEXT:       PARM       KWD(TEXT) TYPE(*CHAR) LEN(50) +                 
                          DFT(*SRCMBRTXT) +                             
                          PROMPT(' テキスト '' 記述 ''')                
 AUT:        PARM       KWD(AUT) TYPE(*CHAR) LEN(10) RSTD(*YES) +       
                          DFT(*LIBCRTAUT) VALUES(*LIBCRTAUT *ALL +      
                          *CHANGE *USE *EXCLUDE) +                      
                          SPCVAL((*LIBCRTAUT) (*CHANGE) (*ALL) +        
                          (*EXCLUDE) (*USE)) PROMPT(' 権限 ')           
 OPTION:     PARM       KWD(OPTION) TYPE(LIST1) +                       
                          PROMPT(' 生成オプション ')                    
 QUAL1:      QUAL       TYPE(*NAME) LEN(10) MIN(1)                      
             QUAL       TYPE(*NAME) LEN(10) DFT(*CURLIB) +              
                          SPCVAL((*CURLIB)) PROMPT(' ライブラリー ')    
 QUAL2:      QUAL       TYPE(*NAME) LEN(10) DFT(QMISRC) SPCVAL((*NONE)) 
             QUAL       TYPE(*NAME) LEN(10) DFT(*LIBL) +                
                          SPCVAL((*LIBL) (*CURLIB)) +                   
                          PROMPT(' ライブラリー ')                      
 LIST1:      ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*GEN) +      
                          VALUES(*GEN *NOGEN) +                         
                          PROMPT(' プログラムの生成 ')                  
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*REPLACE) +  
                          VALUES(*REPLACE *NOREPLACE) +                 
                          PROMPT(' プログラムの置換え ')                
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*LIST) +     
                          VALUES(*LIST *NOLIST) +                       
                          PROMPT(' リストの生成 ')                      
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*XREF) +     
                          VALUES(*XREF *NOXREF) +                       
                          PROMPT(' 相互参照表の作成 ')                  
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*ATR) +      
                          VALUES(*ATR *NOATR) +                         
                          PROMPT(' 合計リストの作成 ')                  
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*USER) +     
                          VALUES(*USER *ADOPT *OWNER) +                 
                          PROMPT(' ユーザー・プロフィール ')           
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*ADPAUT) +  
                          VALUES(*ADPAUT *NOADPAUT) +                  
                          PROMPT(' 借用権限の使用 ')                   
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*SUBSCR) +  
                          VALUES(*SUBSCR *NOSUBSCR *UNCON) +           
                          PROMPT(' 配列の制約 ')                       
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*SUBSTR) +  
                          VALUES(*SUBSTR *NOSUBSTR) +                  
                          PROMPT(' ストリングの制約 ')                 
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*CLRPSSA) + 
                          VALUES(*CLRPSSA *NOCLRPSSA) +                
                          PROMPT(' 静的記憶域の初期設定 ')             
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*CLRPASA) + 
                          VALUES(*CLRPASA *NOCLRPASA) +                
                          PROMPT(' 自動記憶域の初期設定 ')             
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) +               
                          DFT(*NOIGNDEC) VALUES(*NOIGNDEC *IGNDEC) +   
                          PROMPT(' 10進数データ・エラーの無視 ')     
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) +               
                          DFT(*NOIGNBIN) VALUES(*NOIGNBIN *IGNBIN) +   
                          PROMPT(' 2進数 データ・サイズ・エラー の無視 ')    
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) +             
                          DFT(*NOOVERLAP) VALUES(*NOOVERLAP +        
                          *OVERLAP) +                                
                          PROMPT(' 一致オペランドのサポート ')       
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*NODUP) + 
                          VALUES(*NODUP *DUP) +                      
                          PROMPT(' 重複宣言の許可 ')                 
             ELEM       TYPE(*CHAR) LEN(11) RSTD(*YES) DFT(*OPT) +   
                          VALUES(*OPT *NOOPT) PROMPT(' 最適化 ')     
【 CLP : CRTMIPGMCL 】
             PGM        PARM(&PGMOBJ &SRCFILLIB &SRCMBR &TEXT &AUT +    
                          &LIST)                                        
/*---------------------------------------------------------*/           
/*    CRTMIPGM   :   MIプログラムの作成                  */           
/*---------------------------------------------------------*/           
             DCL        VAR(&PGMOBJ) TYPE(*CHAR) LEN(20)                
             DCL        VAR(&PGM) TYPE(*CHAR) LEN(10)                   
             DCL        VAR(&OBJLIB) TYPE(*CHAR) LEN(10)                
             DCL        VAR(&SRCFILLIB) TYPE(*CHAR) LEN(20)             
             DCL        VAR(&SRCFIL) TYPE(*CHAR) LEN(10)                
             DCL        VAR(&SRCLIB) TYPE(*CHAR) LEN(10)                
             DCL        VAR(&SRCMBR) TYPE(*CHAR) LEN(10)                
             DCL        VAR(&TEXT) TYPE(*CHAR) LEN(50)                  
             DCL        VAR(&WTEXT) TYPE(*CHAR) LEN(50)                 
             DCL        VAR(&AUT) TYPE(*CHAR) LEN(10)                   
             DCL        VAR(&LIST) TYPE(*CHAR) LEN(178)                 
             DCL        VAR(&SRCCHGDATE) TYPE(*CHAR) LEN(13)            
             DCL        VAR(&WCHG) TYPE(*CHAR) LEN(13)                  
             DCL        VAR(&ERRID) TYPE(*CHAR) LEN(7)                  
             DCL        VAR(&ERRBYT) TYPE(*DEC) LEN(9 0)                
             DCL        VAR(&ERRLEN) TYPE(*CHAR) LEN(4) +               
                          VALUE(X'00000000') /* 2 進数  */              
             DCL        VAR(&ERRDTA) TYPE(*CHAR) LEN(256)               
             DCL        VAR(&APIERR) TYPE(*CHAR) LEN(272) /* 2 進数  */ 
             DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)                  
             DCL        VAR(&MSGF) TYPE(*CHAR) LEN(10)                  
             DCL        VAR(&MSG) TYPE(*CHAR) LEN(80)                   
             DCL        VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)               
             DCL        VAR(&MSGDTA) TYPE(*CHAR) LEN(100)               
             DCL        VAR(&ERRORSW) TYPE(*LGL)                        
             MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(STDERR1))       
                                                                        
             CHGVAR     VAR(&PGM)    VALUE(%SST(&PGMOBJ 01 10))         
             CHGVAR     VAR(&OBJLIB) VALUE(%SST(&PGMOBJ 11 10))         
             CHGVAR     VAR(&SRCFIL) VALUE(%SST(&SRCFILLIB 01 10))      
             CHGVAR     VAR(&SRCLIB) VALUE(%SST(&SRCFILLIB 11 10))      
             IF         COND(&SRCMBR *EQ '*PGM      ') THEN(DO)         
             CHGVAR     VAR(&SRCMBR) VALUE(&PGM)                        
             ENDDO                                                      
             RTVMBRD    FILE(&SRCLIB/&SRCFIL) MBR(&SRCMBR) +            
                          SRCCHGDATE(&WCHG) TEXT(&WTEXT)                
             IF         COND(%SST(&TEXT 1 10) *EQ '*SRCMBRTXT') +     
                          THEN(DO)                                    
             CHGVAR     VAR(&TEXT) VALUE(&WTEXT)                      
             ENDDO                                                    
             OVRDBF     FILE(SRCFILE) TOFILE(&SRCLIB/&SRCFIL) +       
                          MBR(&SRCMBR) SECURE(*YES)                   
             CALL       PGM(QUATTRO/CRTMIPGMR) PARM(&PGMOBJ &TEXT +   
                          &WCHG &AUT &LIST &APIERR)                   
             DLTOVR     *ALL                                          
             CHGVAR     VAR(&ERRLEN) VALUE(%SST(&APIERR 5 4))         
             CHGVAR     VAR(&ERRID)  VALUE(%SST(&APIERR 9 7))         
             CHGVAR     VAR(&ERRDTA) VALUE(%SST(&APIERR 17 256))      
             CHGVAR     VAR(&ERRBYT) VALUE(%BIN(&ERRLEN))             
                                                                      
             IF         COND(&ERRBYT = 0) THEN(DO)                    
             SNDPGMMSG  MSGID(CPF9897) MSGF(QSYS/QCPFMSG) +           
                          MSGDTA(' MIプログラム ' || &PGM |< +      
                          ' がライブラリー ' || &OBJLIB |< +          
                          ' に作成された。 ') MSGTYPE(*COMP)          
             ENDDO                                                    
             ELSE       CMD(DO)                                       
             IF         COND(&ERRID *EQ '*******') THEN(DO)           
             SNDPGMMSG  MSGID(CPF9897) MSGF(QSYS/QCPFMSG) +           
                          MSGDTA(' 原始メンバーのレコード数が 9999+   
                           を越えている。 ') MSGTYPE(*ESCAPE)         
             ENDDO                                                    
             ELSE       CMD(DO)                                       
             IF         COND(&ERRID *EQ '*NOPEND') THEN(DO)           
             SNDPGMMSG  MSGID(CPF9897) MSGF(QSYS/QCPFMSG) +           
                          MSGDTA(' 最後のステートメント PEND; が見つ +
                           からない。MIコンパイルは行なわれません + 
                           。 ') MSGTYPE(*ESCAPE)                     
             ENDDO                                                    
             ELSE       CMD(DO)                                       
             SNDPGMMSG  MSGID(&ERRID) MSGF(QSYS/QCPFMSG) +            
                          MSGDTA(%SST(&ERRDTA 1 &ERRBYT)) +           
                          MSGTYPE(*ESCAPE)                            
             ENDDO                                                    
             ENDDO                                                    
             ENDDO                                                    
             RETURN                                                   
                                                                      
 STDERR1:    IF         COND(&ERRORSW) THEN(SNDPGMMSG MSGID(CPF9999) +  
                          MSGF(QSYS/QCPFMSG) MSGTYPE(*ESCAPE))          
             CHGVAR     VAR(&ERRORSW) VALUE('1')                        
 STDERR2:    RCVMSG     MSGTYPE(*DIAG) MSGDTA(&MSGDTA) MSGID(&MSGID) +  
                          MSGF(&MSGF) MSGFLIB(&MSGFLIB)                 
             IF         COND(&MSGID *EQ '       ') THEN(GOTO +          
                          CMDLBL(STDERR3))                              
             SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +            
                          MSGDTA(&MSGDTA) MSGTYPE(*DIAG)                
             GOTO       CMDLBL(STDERR2)                                 
 STDERR3:    RCVMSG     MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) +  
                          MSGF(&MSGF) MSGFLIB(&MSGFLIB)                 
             SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +            
                          MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE)              
 END:        ENDPGM
【 RPG : CRTMIPGMR 】
     H            Y/                                    1                        
     F******** MIプログラムの作成 ***********************************          
     FSRCFILE IP  F      92            DISK         KINFDS INFDSF                
     FQPRINT  O   F     132     OF     PRINTER                        UC         
     F*****************************************************************          
     E                    MIR      9999 80               MI BFR                  
     E                    OPR        16 11               OPTION LIST             
     E                    T1R     1   1 22               TITLE 1                 
     E                    T2R     1   1 41               TITLE 2                 
     E                    O1R     1   8 46               OPTION 1                
     E                    O2R     1  16 46               OPTION 2                
     ISRCFILE AA  01                                                             
     I                                        1  12 WRES                         
     I                                       13  92 SRCDTA                       
     IINFDSF      DS                                                             
     I                                       83 102 SRCFLB                       
     I                                       83  92 WSFIL                        
     I                                       93 102 WSLIB                        
     I                                      129 138 SRCMBR                       
     I                                    B 156 1590WRNBR                        
     ISPCBIN      DS                                                             
     I                                    B   1   40MILEN                        
     I I            2                     B   5   80PRPAG                        
     I                                    B   9  120OPLEN                   
     IDSOPT       DS                            178                         
     I                                    B   1   20WOPLN                   
     I                                        3 178 WOPT                    
     I                                        3 178 OPR                     
     IPGMOBJ      DS                                                        
     I                                        1  10 PGM                     
     I                                       11  20 OBJLIB                  
     ISRCCHG      DS                                                        
     I                                        2   70CRTDAT                  
     I                                        8  130CRTTIM                  
     IAPIERR      DS                                                        
     I                                    B   1   40ERRBYT                  
     I                                    B   5   80ERRLEN                  
     I                                        9  15 ERRID                   
     I                                       16  16 ERRRES                  
     I                                       17 272 ERRDTA                  
     I* LIB名付きPGM名                                              * 
     I              'QPRINT    QGPL      'C         PRTFIL                  
     C*----------------------------------------------------+                
     C*  他の プログラム からの CALL---パラメーター の受取         *                
     C*----------------------------------------------------+                
     C           *ENTRY    PLIST                           |                
     C                     PARM           PGMOBJ           |プログラム         
     C                     PARM           TEXT   50        |テキスト                
     C                     PARM           SRCCHG           |SRCCHGDATTIM        
     C                     PARM           AUT    10        |AUT                 
     C           DSOPT     PARM           OPTION178        |OPTION LIST         
     C                     PARM           APIERR           |APIERR              
     C*----------------------------------------------------+                    
     C*                                                                         
     C                     ADD  1         N       40                            
     C                     MOVE SRCDTA    MIR,N                                 
     CLR                   EXSR CREATE                                          
     C******************************************************                    
     C           *INZSR    BEGSR                                                
     C******************************************************                    
     CSR                   Z-ADD10        ERRLEN                                
     CSR         WRNBR     IFGT 9999                       OVRFLW               
     CSR                   Z-ADD22        ERRLEN                                
     CSR                   MOVE '*******' ERRID                                 
     CSR                   MOVEL'OVRFLW'  ERRDTA                                
     CSR                   EXSR PRINT                                           
     C*----------------------------------------------------+                    
     C                     EXCPT@ERROR                     |                    
     C*----------------------------------------------------+                    
     CSR                   CLOSEQPRINT                                          
     CSR                   SETON                     LR                         
     CSR                   RETRN                                             
     CSR                   END                             OVRFLW            
     CSR         WRNBR     MULT 80        MILEN                              
     CSR         INZEND    ENDSR                                             
     C******************************************************                 
     C           CREATE    BEGSR                                             
     C******************************************************                 
     CSR                   EXSR PRINT                                        
     CSR         'PEND;'   SCAN SRCDTA:1  N              50                  
     CSR         *IN50     IFEQ *OFF                       NOT PEND          
     CSR                   Z-ADD22        ERRLEN                             
     CSR                   MOVE '*NOPEND' ERRID                              
     CSR                   MOVEL'NOPEND'  ERRDTA                             
     C*----------------------------------------------------+                 
     C                     EXCPT@ENDER                     |                 
     C*----------------------------------------------------+                 
     CSR                   CLOSEQPRINT                                       
     CSR                   ELSE                            NOT PEND          
     CSR                   CLOSEQPRINT                                       
     CSR                   Z-ADDWOPLN     OPLEN                              
     CSR                   Z-ADD272       ERRBYT                             
     CSR                   Z-ADD2         PRPAG                              
     C*----------------------------------------------------+                 
     C                     CALL 'QPRCRTPG'                 |                 
     C                     PARM           MIR              |               
     C                     PARM           MILEN            |               
     C                     PARM           PGMOBJ           |               
     C                     PARM           TEXT             |               
     C                     PARM           SRCFLB           |               
     C                     PARM           SRCMBR           |               
     C                     PARM           SRCCHG           |               
     C                     PARM PRTFIL    PRFIL  20        |               
     C                     PARM           PRPAG            |               
     C                     PARM           AUT              |               
     C                     PARM           WOPT             |               
     C                     PARM           OPLEN            |               
     C                     PARM           APIERR           |               
     C*----------------------------------------------------+               
     CSR                   END                             NOT PEND        
     CSR         CRTEND    ENDSR                                           
     C******************************************************               
     C           PRINT     BEGSR                                           
     C******************************************************               
     CSR                   TIME           TIME    60                       
     CSR                   OPEN QPRINT                                     
     C*----------------------------------------------------+               
     C                     EXCPT@HEAD                      |               
     C*----------------------------------------------------+               
     CSR         1         DO   16        N                N=1-16     
     C*----------------------------------------------------+          
     C                     EXCPT@DETAL                     |          
     C*----------------------------------------------------+          
     CSR                   END                             N=1-16     
     CSR                   ENDSR                                      
     OQPRINT  E  201           @HEAD                                  
     O                                      'CRTMIPGM 941220'         
     O                         T1R,1     77                           
     O                         UDATE Y  110                           
     O                         TIME     119 '0 :  :  '                
     O                                  127 ' ページ '                
     O                         PAGE     131                           
     O        E  103           @HEAD                                  
     O                         O1R,1                                  
     O                         PGM                                    
     O        E  104           @HEAD                                  
     O                         O1R,2                                  
     O                         WSLIB   +  2                           
     O        E  105           @HEAD                                  
     O                         O1R,3                                  
     O                         WSFIL                                  
     O        E  106           @HEAD                                  
     O                         O1R,4                                  
     O                         WSLIB   +  2                              
     O        E  107           @HEAD                                     
     O                         O1R,5                                     
     O                         SRCMBR                                    
     O        E  108           @HEAD                                     
     O                         O1R,6                                     
     O                         CRTDATY                                   
     O                         CRTTIM  +  2 '0 :  :  '                   
     O        E  109           @HEAD                                     
     O                         O1R,7                                     
     O                         AUT                                       
     O        E  110           @HEAD                                     
     O                         O1R,8                                     
     O                         TEXT                                      
     O        E  112           @HEAD                                     
     O                         T2R,1                                     
     O        E  1             @DETAL                                    
     O                         O2R,N                                     
     O                         OPR,N                                     
     O        E 11             @ERROR                                    
     O                                      '** 原始レコード数が '       
     O                         WRNBR 4                                   
     O                                      ' のためにエラー '           
     O        E 11             @ENDER                                    
     O                                      ' 最後のステートメントに '   
     O                                      'PEND; がない。 '            
** T1R                                                                   
CRTMIPGM コマンド入力                                                    
** T2R                                                                   
 オプション・テンプレート・パラメーター :                                
** O1R                                                                   
 プログラム . . . . . . . . . . . . . . . :                              
   ライブラリー . . . . . . . . . . . . . :                              
 原始ファイル . . . . . . . . . . . . . . :                              
   ライブラリー . . . . . . . . . . . . . :                              
 原始メンバー . . . . . . . . . . . . . . :                              
 最終変更原始メンバー . . . . . . . . . . :                              
 権限 . . . . . . . . . . . . . . . . . . :                              
 テキスト . . . . . . . . . . . . . . . . :                              
** O2R                                                                   
   プログラム・オブジェクトの作成 . . . . :                              
   プログラムの置換え . . . . . . . . . . :                              
   リストの生成 . . . . . . . . . . . . . :                              
   相互参照表の作成 . . . . . . . . . . . :                              
   合計リストの作成 . . . . . . . . . . . :                              
   ユーザー・プロフィール . . . . . . . . :                              
   借用権限の使用 . . . . . . . . . . . . :                              
   配列の制約 . . . . . . . . . . . . . . :                              
   ストリングの制約 . . . . . . . . . . . :    
   静的記憶域の初期設定 . . . . . . . . . :    
   自動記憶域の初期設定 . . . . . . . . . :    
   10進数データ・エラーの無視 . . . . . :    
   2進数データ・サイズ・エラーの無視 . . :    
   一致オペランドのサポート . . . . . . . :    
   重複宣言の許可 . . . . . . . . . . . . :    
   最適化 . . . . . . . . . . . . . . . . :    
【 解説 】

良くこんなものを作ったものだと我ながら感心してしまうのだが、長い日の経過後、
今日、役に立ったのである。
かと言って、いまさら MI コンパイラーを作成するのは相当、骨が折れることになるので
紹介することにした。