一般的には、1つのメッセージが1つのWTOマクロによって出力されますが、オペレータ・コマンドの処理結果など、プログラムの処理結果を複数のメッセージで構成して出力したいこともよくあります。出したいメッセージが10行分あるなら、テキスト内容を変えてWTOマクロを10回出せば実現できます。しかし、この方法ではコンソール上の個々のメッセージの間に他のジョブのメッセージが割り込んで表示されてしまう場合もあります。これを防ぐためには、1つのWTOで複数のメッセージを出すか、メッセージ毎にWTOを発行するものの連続したメッセージ群であることをOSに示すことで、メッセージとメッセージの間に他のジョブのメッセージを割り込ませないようにします。
OSのDisplayコマンドの表示結果のようなメッセージ出力を行う場合は、複数行メッセージのためのWTO機能を利用します。予め出力するメッセージ行数が決まっているなら前者(複数メッセージを1つのWTOで出力)、処理の内容によって行数が可変になるような場合は後者(複数WTOだが連続したメッセージ群として出力)の方法を使うといいでしょう。ただし、コネクティングWTOと呼ばれる後者の方法はAPF許可されたプログラムでなければなりません。
一度に複数のメッセージをコンソールに出力する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTO MF=(E,CMDRESLT) SHOW COMMAND PROCESSING RESULT : : : CMDRESLT WTO ('DATA LINE,MESSAGE-1',D), + ('DATA LINE,MESSAGE-2',D), + ('DATA LINE,MESSAGE-3',DE), + MCSFLAG=(RESP), + ROUTCDE=2,DESC=5,MF=L WTO TEXT=((MSG1,D), SHOW COMMAND PROCESSING RESULT + (MSG2,D),(MSG3,DE)), + MCSFLAG=(RESP), + ROUTCDE=2,DESC=5 : : : MSG1 DC AL2(L'MSG1TXT) MSG1TXT DC C'DATA LINE,MESSAGE-1' MSG2 DC AL2(L'MSG2TXT) MSG2TXT DC C'DATA LINE,MESSAGE-2' MSG3 DC AL2(L'MSG3TXT) MSG3TXT DC C'DATA LINE,MESSAGE-3' |
最初の例は、複数行WTOマクロの古典的なコーディングです。1つのWTOで複数のメッセージをコンソールに出力できます。リスト形式のWTOマクロを組み合わせてますので、メッセージ・テキストはプログラムで修正することができます。テキスト長は増やせないので、予め空白を埋めるなりして必要な最大長で定義しておきます。2番目の例は、現在のz/OS(MVS)で利用可能なメッセージ・テキストをマクロの外に記述する方法です。
上記の最初の例で、リスト形式のWTOマクロを以下のように書くとWTOは失敗することがあります。
1 2 3 4 |
CMDRESLT DS 0H WTO ('DATA LINE,MESSAGE-1',D), + : : |
実行形式のWTOマクロではラベル名CMDRESLTを指定しますが、CMDRESLTはDS 0Hによってハーフワード境界に調整されます。しかし、続くMF=L指定のWTOマクロの展開内でパラメーター・リストの先頭がフルワード境界に調整されるため、ラベル名の位置と実際のWTOパラメーターが場合によっては2バイトずれてしまいます。ずれた場合は正しいパラメーターリストを指さなくなるので、実行形式のWTOマクロは失敗します。マクロそのものの使い方は誤っていないため、デバッグしてもなかなか原因が掴めません。実際の復帰コードは4となりますが、マニュアルでは行数が0あるいはメッセージ長が0などと説明されており、実際のコーディングと合わないため「なんで??」となってしまいます。
一般的には、機械命令はDS 0Hで境界調整するのでついこのようなラベルをコーディングしがちですが、マクロ命令の多く(特にリスト形式)はフルワード境界に調整されますから知っておくといいでしょう。わかってしまえばつまらない原因のバグですが、わかりにくい例でもあります。マクロ命令にラベルを付ける場合は、DS 0Hで追記するのではなくマクロ命令そのものにラベルを付けます。
複数のメッセージを連結してコンソールに出力する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- L R0,CIBXCNID LOAD CONSOLE ID ST R0,CMDCONID SAVE IT : コマンドが入力されたコンソールIDは : CIBXから得ることができる。 : SLR R0,R0 CLEAR GR0 WTO TEXT=((TITLE,)), SHOW TITLE(CONTROL LINE) + CONSID=CMDCONID, + MF=(E,WTOPARMC) ST R1,WTOTOKEN SAVE CONNECTING WTO TOKEN SLR R0,R0 CLEAR GR0 WTO TEXT=((MIDASHI,)), SHOW MIDASHI(LABEL LINE) + CONNECT=WTOTOKEN, + MF=(E,WTOPARML) : : LA R2,MSG1 LOAD MESSAGE TEXT FIELD SLR R0,R0 CLEAR GR0 WTO TEXT=(((2),)), SHOW COMMAND PROCESSING RESULT + CONNECT=WTOTOKEN, + MF=(E,WTOPARMD) : : 処理しながら必要なメッセージを出力していく。 (MSG1,MSG2,MSG3...) : : SLR R0,R0 CLEAR GR0 WTO CONNECT=WTOTOKEN, INDICATE END OF WTO OUTPUTTING + MF=(E,WTOPARME) : : : TITLE DC AL2(L'TITLTXT) TITLTXT DC C'CNTL LINE,TITLE' MIDASHI DC AL2(L'MIDSTXT) MIDSTXT DC C'LABEL LINE,MIDASHI' MSG1 DC AL2(L'MSG1TXT) MSG1TXT DC C'DATA LINE,MESSAGE-1' MSG2 DC AL2(L'MSG2TXT) MSG2TXT DC C'DATA LINE,MESSAGE-2' MSG3 DC AL2(L'MSG3TXT) MSG3TXT DC C'DATA LINE,MESSAGE-3' : WTOPARMC WTO TEXT=((,C)),CONSID=, WTO PLIST MODEL(TYPE=C) LEN=35 + MCSFLAG=(RESP), + DESC=(5,8,9),AREAID=Z,MF=L WTOPARML WTO TEXT=((,L)),CONNECT=, WTO PLIST MODEL(TYPE=L) LEN=71 + MF=L SPACE , WTOPARMD WTO TEXT=((,D)),CONNECT=, WTO PLIST MODEL(TYPE=D) LEN=71 + MF=L SPACE , WTOPARME WTO TEXT=((,E)),CONNECT=, WTO PLIST MODEL(TYPE=E) LEN=0 + MF=L |
通常のWTO同様に、1つのWTOで1つのメッセージを出力するものの、各々のメッセージはひとまとまりの複数行メッセージとして扱われるコネクティングWTOです。AREAIDパラメーターで、コンソール上の表示域を指定できます。サンプルでは、一般メッセージが表示されるスクロール領域を出力するためAREAIDに’Z’を指定していますが、OSのDisplayコマンド同様に表示域(K△Aコマンドで設定するAREA域)に出力する場合は、AREAIDに’A’を指定し、DESCコードに最低でも(8,9)を指定します。表示域(AREA=A)に出力すれば、メッセージのスクロールは K D,F コマンドで制御できるようになります。制御行(C)とラベル行(L)はスクロールされないので、固定表示させたいタイトルや見出しに利用できます。なお、APF許可されていないプログラムでコネクティングWTOを使うと、2回目以降の連結されたWTOはSD23でABENDします。
システム系の制御プログラムの場合、コネクティングWTOの方が応用範囲が広いので便利です。行数が固定された場合でも、処理内容やデータによって行数が変わる場合のどちらでも対応できます。なお、コネクティングWTOを使う場合、出力する上限の行数を決めてそれを超えたらデータ行の出力を打ち切るべきです(例えば、多くても100行しか出さないなど)。ひとつのプログラムで大量のコネクティングWTOを使うとコンソール資源を占有してしまいますし、万一WTO出力を伴うループを起こしてしまったらコンソール・バッファはあっという間に枯渇してしまいます。要所要所にフェイル・セーフとなるようなチェック処理を入れるのは制御プログラミングの基本でもあります。