プログラムで起きていることを状況に応じてメッセージで伝えることは重要です。特に、エラーが起きてオペレーターの操作や判断を必要する場合、適切なメッセージはシステムの運用面で大きな利益をもたらします。どのような時にどのようなメッセージを出すかは、プログラムのロジック同様にデザイナーの腕の見せ所でもあります。MVSには、コンソールへメッセージを出したり、オペレーターからの操作や応答を受け取るためのAPIも用意されています。これらは、コンソールを操作するオペレーターとプログラムの間の通信機能でもあります。
コンソールへメッセージを出力する
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 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTO 'MYP001I ENQ ERROR' INFORM ENQ ERROR WTO 'MYP001I AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+ CDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDE' : : ENQ (QNAME,RNAME,E,L'RNAME,STEP),RET=USE CVD RF,DOUBLE EDIT RETCD IN WTO MESSAGE UNPK MSGPARM1+4+15(2),DOUBLE I OI MSGPARM1+4+16,C'0' V WTO MF=(E,MSGPARM1) INFORM ENQ ERROR WITH RC SPACE , ENQ (QNAME,RNAME,E,L'RNAME,STEP),RET=USE SLR RE,RE CLEAR WORKREG IC RE,3(,RF) LOAD ENQ ERROR CODE CVD RE,DOUBLE EDIT RETCD IN WTO MESSAGE UNPK MSGPARM1+4+15(2),DOUBLE I OI MSGPARM1+4+16,C'0' V WTO MF=(E,MSGPARM1) INFORM ENQ ERROR WITH RC : : DOUBLE DC D'0' DOUBLE WORD WORKAREA QNAME DC CL8'MYPROG' TEST ENQ QNAME RNAME DC C'TESTENQ1' TEST ENQ RNAME ******** ----0----+----1----+----2----+----3 MSGPARM1 WTO 'MYP001I ENQ RC=??', WTO LIST FORM PARAMETER + MF=L |
WTOマクロは、コンソールへメッセージを出力します。メインフレームのアセンブラープログラマーに「初めて使ったOSのマクロは何ですか?」とアンケートを取れば、恐らく1位少なくとも3位内には入るであろうという位ポピュラーなマクロです。
使い方もいたって簡単で、マクロ名に続いて出したいメッセージテキストを”で囲めばOKです。テキストが長くて1行に書ききれない時は、71桁目まで目一杯書いて72桁目に何か文字を置き、次の行の16桁目から続けます。16桁目が空白でもそのまま空白文字として扱われます。
上記サンプルの中盤以降の2例は、メッセージ・テキストの中の文字を変更して出力したい場合に用いられる方法の1つです。実務では、固定のメッセージ・テキストだけでなくメッセージの中にプログラムの処理によって内容が変わる値などを埋め込みたいことがよくあります。このような場合は、リスト形式と実行形式のWTOマクロを組み合わせます。再入可能プログラムでは、モジュール内のWTOパラメーターを直接変更できないので、モジュール外の作業域に一旦コピーしてそちら側を修正して使用します。
このサンプルは、わざと同じENQを2回出し、それぞれのENQサービスの復帰コードをメッセージ中の「RC=??」の??部分に埋め込んでコンソールに出力するものです。単にENQ ERRORと出すよりも実用的です。オペレーターやプログラムの実行者は、復帰コードの値がわからなければ対処のしようがありません。サンプルでは、簡単にするために10進数に変換していますが、16進文字への変換ならマニュアルのコード表示と一致するのでさらにわかりやすくなります。
メッセージ・テキストは、WTOパラメーターの+4バイト目から始まります。アセンブルしてマクロの展開形を見ればすぐにわかります。本来ならば、OSマクロの中を直接変位を指定して場所をポイントするのは決していいことではないのですが、WTOのような基本的なマクロはその内容が変わることは現実的にありませんし、サンプルの方法は古典的ではありますが、昔から多くのプログラムで行われている言わば標準的・伝統的な方法です。
可変長のメッセージテキストを出力する
1 2 3 4 5 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTO TEXT=MSGLENG USE WTO WITH NEW FORMAT : MSGLENG DC AL2(L'MSGTEXT) MSG LENGTH AND TEXT MSGTEXT DC C'MYP002I VARIABLE LENGTH MESSAGE' |
可変長のメッセージ・テキストを出力する例です。TEXTパラメーターでコンソールへ出力するメッセージテキストの格納アドレスを指定します。メッセージ領域の先頭2バイトはメッセージ・テキストの長さです。メッセージ長フィールドの長さは含みません。長さに続いてメッセージ・テキストを格納します。TEXTパラメーターを使用すれば、長さもテキスト自体もプログラムの動作内容に応じて変更ができます。但し、WTOマクロにおけるTEXTパラメーターは最初からあったものではなく、後になってから追加されたもので古いプログラムでは使われていないことも多いです。その場合は、下記に示すようにリスト形式と実行形式を組み合わせて、WTOパラメーター・リスト内を直接直すようなコーディングがなされました。(前述のサンプル同様)
1 2 3 4 5 6 7 8 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTO MF=(E,WTOPARM) USE WTO WITH OLD FORMAT : WTOPARM DS 0F DC AL2(4+L'MSGTEXT) WTO PARAMETER LENGTH DC XL2'0000' MCSFLAGS MSGTEXT DC C'MYP002I VARIABLE LENGTH MESSAGE' : |
1 2 3 4 5 6 7 8 9 10 11 12 |
WTO PARAMETER LIST(OLD FASHION STYLE) +-------------+ +00| TEXT LENGTH | include 'TEXT LENGTH' and 'MCSFLAGS' field length. +-------------+ +02| MCSFLAGS | by MCSFLAG parameter +-------------+------------//-------------+ +04| MESSAGE TEXT | +-------------+------------//-------------+ +nn| DESC CODE | by DESC parameter +-------------+ +nn| ROUTE CODE | by ROUTCDE parameter +-------------+ |
メッセージテキストを”記号で囲む、従来からあるWTOパラメーターは上図のフォーマットになっています。先頭2バイトに、メッセージ・テキスト長に4を加えた値を設定します。DESCまたはROUTCDEパラメーターを指定した場合、メッセージ・テキストの後ろに設定されますが、その長さは先頭のレングス・フィールドには含まれません。パラメーターは、ワード境界に合わせます。
メッセージの種類と宛先を指定する
1 2 3 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTO 'MYP002I THIS MESSAGE HAS DESC CODE=6',DESC=(6) WTO 'MYP002I THIS MESSAGE HAS ROUTE CODE=2',ROUTCDE=(2) |
メッセージの種類や宛先を指定することもできます。DESCパラメーターは、メッセージの種類(性質)を表します。アプリケーション・プログラムでは省略されることが多いですが、一般のプログラムが指定するなら6または7でいいでしょう。OSの出口ルーチンなど、重大なエラーを検出してオペレーターにメッセージで伝えるような時、スクロールされてメッセージが流れないようにするにはDESCコードとして11を指定します。DESCコード11を指定した場合、WTOマクロ完了時にGR1に返されるメッセージ識別番号を保存します。この識別番号を使えば、DOMマクロによってメッセージを削除することが可能です。DESCコード11のメッセージは、プログラムがDOMマクロを使うかオペレーターがコンソール操作(K C,A,idコマンド)するまでは消されることはありません。
ROUTCDEパラメーターは、メッセージの宛先を表します。こちらも省略されることが多いですが、一般プログラムが指定するなら2がいいでしょう。SYSLOGの3~9桁目が、メッセージのROUTE CODEを示します。16進表記ですが左端ビットからROUTE1、2、3、4、5、6、…、28となっています。ここを見て、他のソフトウェア製品などがどのようなROUTCDEを使っているかを参考にするのも1つの方法です。FFFFFFFFとなっていたらROUTCDEは省略されています。
DESCとROUTCDEのコードそのものの詳細な解説は「z/OS MVS宛先コードおよび記述子コード」のマニュアルに記載されています。
SYSLOGへメッセージを出力する
1 2 3 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- WTL 'MYP002I SYSLOG MESSAGE' WTO 'MYP002I SYSLOG MESSAGE',MCSFLAG=HRDCPY |
コンソールへの表示は不要だがSYSLOGには残したいという場合は、WTLマクロをWTOマクロの代わりに使うことができます。なお、今日のz/OSではWTLマクロに代わりMCSFLAG=HRDCPYを指定したWTOマクロによる方法が推奨されています。
MCSFLAG=HRDCPY指定のWTOを使った場合、SDSFのLOG機能などの仮想コンソール・プログラムにはメッセージが表示されることがあります。これは、その仮想コンソール機能が純粋にコンソールとしてではなくSYSLOGをベースにメッセージを表示しているからです。本当にコンソールには出ていないかを確認するには、実コンソールを見て下さい。