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