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 である。
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(' 最適化 ')
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
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 コンパイラーを作成するのは相当、骨が折れることになるので
紹介することにした。