ほとんどの場合、次の例(以前のものと同様)$ETRAPと$ZTRAPと同様の動作を持っています。 最も顕著な違いは、$ETRAPがアクティブな場合、$ECODEはMスタック・レベルの2番目のエラーがそのレベルからの即時の暗黙のQUITをトリガーするかどうかを判別することです。詳細は、 第8章: “固有の特殊変数” の$ECODEおよび$ETRAPのセクションを参照してください。$ETRAPがアクティブな時に処理フロー上の$ECODEの効果のために、$ZTRAP関連のコード内で$ECODEのメンテナンスを適切に含むために利点があるので、2つのメカニズムが合体されている時に物事がうまく動作します。 その他の違いは、いくつかの例で説明しています。
$ZTRAPがBREAKコマンドに設定され、エラーが発生している時は、GT.Mはダイレクトモードにプロセスを置きます。$ZTRAPのデフォルトは、BREAKコマンドです。プログラムを開発する際、$ZTRAP="BREAK" は、ダイレクトモードからエラーの原因を調査することができます。GT.Mのデバッグツールの詳細については、第4章: “ダイレクトモードでの操作とデバッグ” を参照してください。
例:
GTM>zprint ^EP1 EP1 WRITE !,"THIS IS "_$TEXT(+0) KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>do ^EP1 THIS IS EP1%GTM-E-UNDEF, Undefined local variable: A At M source location BAD^EP1 GTM>ZSHOW BAD^EP1 ($ZTRAP) (Direct mode) +1^GTM$DMOD (Direct mode) GTM>QUIT GTM>ZSHOW EP1+1^EP1 (Direct mode) +1^GTM$DMOD (Direct mode) GTM>
$ETRAP="" と $ZTRAP="B" がデフォルトなので、この例では明示的に$ETRAPまたは$ZTRAPのどちらかを設定していません。ルーチンが BAD^EP1でのエラーを検出すると、GT.Mはダイレクトモードを開始します。 ZSHOWは、最下部にダイレクトモードの基底フレームを、最上部に$ZTRAPが呼び出される表記でEP1を、持っていることをMスタックに表示します。プロンプトでQUITコマンドは、スタックからEP1を削除します。
ダイレクトモードへのアクセスからこのようなプロダクションイメージとしてプログラムを防止するために、$ETRAPまたは$ZTRAPへ "BREAK" 以外のアクションを割り当てます。次のセクションでは、$ETRAPまたは$ZTRAPのための様々な代替値を検討します。
ダイレクトモードへの不適切なアクセスを防ぐために、プロダクション コードからすべてのブレークポイントを除去します。もしコードにBREAKコマンドが含まれている場合、コマンドは、デバッグのためにオンになっている後置条件フラグの対象とすべきです。ZBREAKは、現在のプロセスだけに効果がある代替のデバッグツールとして提供され、そして、イメージのアクティベーションの期間中にのみ持続します。
GOTOコマンドは、ルーチン内で別の行へ、または、別のルーチンへ、恒久的に実行を移行するためにGT.Mに指示をします。エラーを調査するために停止することが望ましくない時には、他のいくつかのポイントで実行を継続する$ETRAPまたは$ZTRAPの中でGOTOコマンドを使用してください。
例:
GTM>ZPRINT ^EP2 EP2 WRITE !,"THIS IS "_$TEXT(+0) SET $ECODE="" ;this affects only $ETRAP SET $ETRAP="GOTO ET" ;this implicitly stacks $ZTRAP ;N $ZT S $ZT="GOTO ET" ;would give a similar result DO SUB1 WRITE !,"THIS IS THE END" QUIT SUB1 WRITE !,"THIS IS SUB1" DO SUB2 QUIT SUB2 WRITE !,"THIS IS SUB2" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET ;SET $ZTRAP="" ;if using $ZTRAP to prevent recursion WRITE !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR" WRITE !,"$STACK: ",$STACK WRITE !,"$STACK(-1): ",$STACK(-1) WRITE !,"$ZLEVEL: ",$ZLEVEL FOR I=$STACK(-1):-1:1 DO . WRITE !,"LEVEL: ",I . SET K=10 . FOR J="PLACE","MCODE","ECODE" DO . . WRITE ?K," ",J,": ",$STACK(I,J) . . SET K=K+20 WRITE !,$ZSTATUS,! ZSHOW "S" SET $ECODE="" ;this affects only $ETRAP QUIT GTM>do ^EP2 THIS IS EP2 THIS IS SUB1 THIS IS SUB2 CONTINUING WITH ERROR TRAP AFTER AN ERROR $STACK: 3 $STACK(-1): 3 $ZLEVEL: 4 LEVEL: 3 PLACE: BAD^EP2 MCODE: BAD WRITE A ECODE: ,M6,Z150373850, LEVEL: 2 PLACE: SUB1+1^EP2 MCODE: DO SUB2 ECODE: LEVEL: 1 PLACE: EP2+4^EP2 MCODE: DO SUB1 ECODE: 150373850,BAD^EP2,%GTM-E-UNDEF, Undefined local variable: A ET+12^EP2 SUB1+1^EP2 EP2+4^EP2 +1^GTM$DMOD (Direct mode) THIS IS THE END GTM>
このルーチンは、エラーが発生したときに、ETラベルへ実行を移行するGOTOコマンドを指定します。$ZLEVEL特殊変数は、Mのスタックレベルを示す整数が含まれています。
ZGOTOコマンドは、GOTOコマンドに似ていますが、しかし、ZGOTOは、プログラムスタックから複数のレベルの除去が可能になります。ZGOTOは、そのようなメニューとして、実行が特定の時点に戻すことを確認することができます。
例:
GTM>ZPRINT ^EP3 EP3 ; MENU WRITE !,"THIS IS MENU IN ",$TEXT(0) SET $ECODE="" ;this affects only $ETRAP SET $ETRAP="SET $ECODE="""" ZGOTO 2" ;N $ZT S $ZT="ZGOTO 2" ;would give a similar result DO SUB1 WRITE !,"`MENU' AFTER $ETRAP" WRITE !,"$STACK: ",$STACK WRITE !,"$ZLEVEL: ",$ZLEVEL QUIT SUB1 WRITE !,"THIS IS SUB1" DO SUB2 WRITE !,"THIS IS SKIPPED BY ZGOTO" QUIT SUB2 WRITE !,"THIS IS SUB2" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>do ^EP3 THIS IS MENU IN THIS IS SUB1 THIS IS SUB2 `MENU' AFTER $ETRAP $STACK: 1 $ZLEVEL: 2
このルーチンは、もしエラーが発生した場合に、LEVEL2への実行をリセットするためにGT.Mに指示をします。 すべての中間レベルを削除します。
一般的には、$ZLEVELに基づくZGOTOのコーディングレベルの情報は、前の例に示すように、"ハードコーディング"よりも堅牢な技術を提供します。
例:
GTM>ZPRINT ^EP4 EP4 WRITE !,"THIS IS "_$TEXT(+0) SET $ECODE="" ;this affects only $ETRAP DO MAIN WRITE !,"THIS IS ",$TEXT(+0)," AFTER THE ERROR" WRITE !,"$ZLEVEL: ",$ZLEVEL QUIT MAIN WRITE !,"THIS IS MAIN" WRITE !,"$ZLEVEL: ",$ZLEVEL SET $ETRAP="ZGOTO "_$ZLEVEL_":ET" ;N $ZT S $ZT="ZGOTO "_$ZLEVEL_":ET ;alternative DO SUB1 QUIT SUB1 WRITE !,"THIS IS SUB1" WRITE !,"$ZLEVEL: ",$ZLEVEL DO SUB2 QUIT SUB2 WRITE !,"THIS IS SUB2" WRITE !,"$ZLEVEL :",$ZLEVEL KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET ;SET $ZTRAP="" ;if using $ZTRAP to prevent recursion WRITE !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR" WRITE !,"$STACK: ",$STACK WRITE !,"$STACK(-1): ",$STACK(-1) WRITE !,"$ZLEVEL: ",$ZLEVEL FOR I=$STACK(-1):-1:1 DO . WRITE !,"LEVEL: ",I . SET K=10 . FOR J="PLACE","MCODE","ECODE" DO . . WRITE ?K," ",J,": ",$STACK(I,J) . . SET K=K+20 WRITE !,$ZSTATUS,! ZSHOW "S" SET $ECODE="" ;this affects only $ETRAP QUIT GTM>do ^EP4 THIS IS EP4 THIS IS MAIN $ZLEVEL: 3 THIS IS SUB1 $ZLEVEL: 4 THIS IS SUB2 $ZLEVEL :5 CONTINUING WITH ERROR TRAP AFTER AN ERROR $STACK: 2 $STACK(-1): 4 $ZLEVEL: 3 LEVEL: 4 PLACE: BAD^EP4 MCODE: BAD WRITE A ECODE: ,M6,Z150373850, LEVEL: 3 PLACE: SUB1+2^EP4 MCODE: DO SUB2 ECODE: LEVEL: 2 PLACE: MAIN+4^EP4 MCODE: DO SUB1 ECODE: LEVEL: 1 PLACE: EP4+2^EP4 MCODE: DO MAIN ECODE: 150373850,BAD^EP4,%GTM-E-UNDEF, Undefined local variable: A ET+12^EP4 EP4+2^EP4 +1^GTM$DMOD (Direct mode) THIS IS EP4 AFTER THE ERROR $ZLEVEL: 2 GTM>
このルーチンは、現在のレベルを指定しているZGOTOに、$ETRAPまたは$ZTRAPを設定します。 ルーチンがラベルBADでエラーを検出したとき、GT.Mは、$ETRAP(または$ZTRAP)が確立された場所のレベルで、ラベルETに制御を切り替えます。実行のこの時点で、ETは、指定されたレベルのプログラム スタック エントリとして、SUB1+2^EP4を置き換えます。すなわち $ZLEVEL=3 。 QUITコマンドは、$ZLEVEL=2のレベルに制御を戻します。
コマンドNEW $ETRAPまたはNEW $ZTRAPはそれぞれ$ETRAPまたは$ZTRAPの現在の値を積み重ね、$ZTRAPの場合は値を空文字列に設定します。通常は、SET $ETRAP or $ZTRAP は、直ちに、NEW $ETRAP or $ZTRAPに従います。GT.Mが、$ETRAPまたは$ZTRAPがNEWされていたレベルを離れるQUITコマンドに遭遇する時 、GT.Mは、NEWコマンドの後にISVに設定された任意の値を削除し、ISVがNEWに以前保持していた値を復元します。NEW $ETRAP または $ZTRAPは、ルーチンのネストに対応するエラーハンドラの構築を可能にします。 SET $ETRAPまたは$ ZTRAPは、空文字列の値をまだ持っていない場合、他の変数を暗黙的にNEWします。(上の別記のように)そのようなインターリーブすることは、$ZTRAPハンドラが$ECODEに適切に対処することが必要にもかかわらず、これは異なるレベルで$ETRAPと $ZTRAPのインタリーブが可能になります。
例:
GTM>ZPRINT ^EP5 EP5 WRITE !,"THIS IS "_$TEXT(+0) SET $ECODE="";this affects only $ETRAP WRITE !,"STARTING $ETRAP: ",$ETRAP WRITE !,"STARTING $ZTRAP: ",$ZTRAP DO SUB1 WRITE !,"ENDING $ETRAP: ",$ETRAP WRITE !,"ENDING $ZTRAP: ",$ZTRAP QUIT MAIN WRITE !,"THIS IS MAIN" WRITE !,"$ZLEVEL: ",$ZLEVEL DO SUB1 QUIT SUB1 WRITE !,"THIS IS SUB1" NEW $ETRAP SET $ETRAP="GOTO ET1" ;NEW $ZTRAP SET $ZTRAP="GOTO ET1" ;alternative WRITE !,"$ETRAP FOR SUB1: ",$ETRAP KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET1 WRITE !,"ERROR TRAP 1" WRITE !,"$ETRAP AFTER THE TRAP: ",$ETRAP WRITE !,"$ZTRAP AFTER THE TRAP: ",$ZTRAP SET $ECODE="";this affects only $ETRAP QUIT GTM>do ^EP5 THIS IS EP5 STARTING $ETRAP: STARTING $ZTRAP: B THIS IS SUB1 $ETRAP FOR SUB1: GOTO ET1 ERROR TRAP 1 $ETRAP AFTER THE TRAP: GOTO ET1 $ZTRAP AFTER THE TRAP: ENDING $ETRAP: ENDING $ZTRAP: B GTM>
SUB1で、このルーチンは、$ETRAPをNEWし、そして、暗黙的に$ZTRAPをNEWする値をそれに割り当てます。 ルーチンがSUB1レベルでエラーを検出する時、GT.Mは、$ETRAPまたは$ZTRAPの値を変更せずに、ラベルET1に制御を移行します。 ルーチンが、ルーチンET1でQUITコマンドに遭遇する時、GT.Mは、その呼び出されたET1をDOした後のコマンドに制御を移行し、それらがNEWとSETの前に保持されている値に$ETRAPまたは$ZTRAPを復元します。
注意 | |
---|---|
もしET1への移行がスタックレベルを減少させるZGOTOで実現されていた場合、トラップの後で、$ETRAPが空の文字列の値を持つ必要があり、そして、$ZTRAPが "B" になる必要があります。 |
DOコマンドで設定される$ETRAPまたは$ZTRAPは、それがエラーを検出した時に、これのまたは別のルーチン内で一時的に別の行へ実行を移行するためにGT.Mへ指示します。 DOの範囲内でQUITコマンドは、$ETRAPまたは$ZTRAPによって指定されたコードに戻す制御を移行します。 ISVのコードは、明示的または暗黙的なQUITのために終了する時に、$ETRAPと$ZTRAPの動作は異なります。 $ETRAPがコントロール内にある時に、エラーが発生した時点でのレベルが削除され、起動しているレベルに制御が戻ります。 $ZTRAPのコードが含まれている場合、実行がエラーのある行の先頭でピックアップします。DOコマンドがエラーを含む行の再実行が許可されるので、$ZTRAP内でのDOコマンドは、オペレータが解決すると思われるI/Oエラーのために、通常、使用されます。
例:
GTM>ZPRINT ^EP6 EP6 WRITE !,"THIS IS "_$TEXT(+0) NEW NEW $ZTRAP SET $ZTRAP="DO ET" SET (CB,CE)=0 BAD SET CB=CB+1 WRITE A SET CE=CE+1 WRITE !,"AFTER SUCCESSFUL EXECUTION OF BAD:",! SET A="A IS NOT DEFINED" ZWRITE QUIT ET W !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR",! ZWRITE SET A="A IS NOW DEFINED" GTM>do ^EP6 THIS IS EP6 CONTINUING WITH ERROR TRAP AFTER AN ERROR CB=1 CE=0 A IS NOW DEFINED AFTER SUCCESSFUL EXECUTION OF BAD: A="A IS NOT DEFINED" CB=2 CE=1 GTM>
この例では、DOコマンドに$ZTRAPをセットします。 ルーチンがラベルBADで行の途中でエラーに遭遇する時、GT.MはラベルETへ制御を移行します。 ルーチン ETからQUITした後に、GT.Mは、ラベルBADの行の先頭に制御を戻します。
例:
GTM>ZPRINT ^EP6A EP6A WRITE !,"THIS IS "_$TEXT(+0) NEW NEW $ETRAP SET $ETRAP="GOTO ET" SET (CB,CE)=0 BAD SET CB=CB+1 WRITE A SET CE=CE+1 WRITE !,"AFTER SUCCESSFUL EXECUTION OF BAD:",! ZWRITE QUIT ET W !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR",! ZWRITE SET A="A IS NOW DEFINED" SET RETRY=$STACK($STACK,"PLACE") SET $ECODE="" GOTO @RETRY GTM>DO ^EP6A THIS IS EP6A CONTINUING WITH ERROR TRAP AFTER AN ERROR CB=1 CE=0 A IS NOW DEFINED AFTER SUCCESSFUL EXECUTION OF BAD: A="A IS NOW DEFINED" CB=2 CE=1 RETRY="BAD^EP6A" GTM>
このルーチンは、制御の無条件移行がない時に、$ZTRAPのデフォルトで発生するオリジナルの実行ストリームの再開(リザンプション)と同じ種類を実行するように、$ETRAPを処理をどのようにコーディングする方法の例です。
もし$ETRAPと$ZTRAPの両方がエラーに遭遇している際に空の文字列に設定されている場合、現在のレベルは破棄され、エラーは呼び出しレベルで再発行されます。既に最低のMスタックレベルの時には、GT.Mはルーチンの実行を終了し、シェルレベルまで制御を戻します。もし$ZTRAPが排他的に使用されている場合は、$ZTRAP="" は、下位レベルに関連付けられている $ZTRAP のNEWされた値のアンスタックを抑制します。$ETRAPの値が常にアンスタックされ、しかし、もし最下位レベルの$ETRAPが空の文字列(GT.M起動時にデフォルトである)である場合に、$ZTRAPと同様にGT.Mは同じ終了を実行します。 ISVの空の両方でこれらの終了は、GT.Mがエラーを検出した時に、ステータスメッセージを表示してシェルに戻るためのメカニズムを提供します。
例:
GTM>ZPRINT ^EP7 EP7 WRITE !,"THIS IS ",$TEXT(+0) SET $ECODE="";this only affects $ETRAP SET $ETRAP="",$ZTRAP="" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>do ^EP7 THIS IS EP7 %GTM-E-UNDEF, Undefined local variable: A %GTM-I-RTSLOC, At M source location BAD^EP7 $
GT.Mは、Mエラーを説明するメッセージを発行し、シェルに制御を開放します。
$ZTRAPによって指定されたアクションが$ZTRAPの値を変更する前に別のランタイムエラーの結果を生じさせる時には、スタックオーバーフローがGT.Mイメージを終了するまで、ルーチンは繰り返し$ZTRAPを呼び出すでしょう。エラー処理の開始時で SET $ZTRAP="" することは、無限ループのこのタイプが発生しないことを保証します。 $ETRAPは暗黙的にQUITが続いているので、再帰する傾向にはありません。$ETRAPは再帰に耐性がある一方で、同じレベル内のGOTOまたはZGOTOが暗黙のQUITを回避できるので、それは完全に免疫がありません。すべてのレベルでエラーが適切に扱われている前に、もし$ECODEが不適切にクリアされている場合は、1つ以上のスタックレベルでのエラーを含む$ETRAPのエラー処理も再帰的に引き起こすことができます。
例:
GTM>ZPRINT ^EP8 EP8 WRITE !,"THIS IS ",$TEXT(+0) NEW $ZTRAP SET $ZTRAP="DO ET" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET WRITE 2/0 QUIT GTM>DO ^EP8 THIS IS EP8 %GTM-E-STACKCRIT, Stack space critical %GTM-E-ERRWZTRAP, Error while processing $ZTRAP GTM>
ルーチンがラベルBADでエラーに遭遇する時、GT.MはラベルETへ制御を移行します。 ルーチンがラベルETでエラーを検出するき、スタックオーバーフロー状態がGT.Mイメージを終了するまで、再帰的にETを行います。
プログラムがエラー処理ルーチンに入ると直ぐ SET $ZTRAPは="" コマンドは、"無限" 再帰のこのタイプを防ぎます。
GTM>zprint ^EP8A EP8A WRITE !,"THIS IS ",$TEXT(+0) SET $ECODE="" SET $ZTRAP="",$ETRAP="DO ET" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET WRITE !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR" ZSHOW "S" WRITE !,"HERE COMES AN ERROR IN THE TRAP CODE" WRITE 2/0 QUIT GTM>DO ^EP8A THIS IS EP8A CONTINUING WITH ERROR TRAP AFTER AN ERRORET+1^EP8A BAD^EP8A ($ZTRAP) +1^GTM$DMOD (Direct mode) HERE COMES AN ERROR IN THE TRAP CODE %GTM-E-DIVZERO, Attempt to divide by zero GTM>
これは、この状況で$ETRAPの動作がより適切な方法を示しています。故意に排他的な$ETRAPを使用するとき、このステップは、等式の外で$ZTRAPを取り、初期化の一部でなければなりません。$ZTRAP("B") の初期値がアンスタックされる時に、最も低いレベルでの $ZTRAP="" は、ダイレクトモードに戻っての実行を防ぐことに、注意してください。
例:
GTM>ZPRINT ^EP9 EP9 WRITE !,"THIS IS ",$TEXT(+0) SET $ZTRAP="DO ET" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT ET SET $ZT="" WRITE !,"THIS IS THE ERROR TRAP" ERROR WRITE !,"HERE COMES AN ERROR IN THE ERROR TRAP" WRITE 2/0 QUIT GTM>DO ^EP9 THIS IS EP9 THIS IS THE ERROR TRAP HERE COMES AN ERROR IN THE ERROR TRAP %GTM-E-DIVZERO, Attempt to divide by zero %GTM-I-RTSLOC, At M source location ERROR+1^EP9 $
このルーチンは、プログラムがエラーハンドラに入るとすぐに、$ZTRAPの値にnullをセットします。 エラーがエラーハンドラ内で発生したときに、これはプログラムの終了を保証します。
QUIT, HALT, ZHALTコマンドも、$ETRAPまたは$ZTRAPの便利なアクションとして提供されます。
QUITコマンドは、その呼び出しレベルでの実行を終了します。
例:
GTM>zprint ^EP10 EP10 WRITE !,"THIS IS ",$TEXT(+0) SET $ECODE="";this affects only $ETRAP S $ET="S $EC="""" Q" ;this implicitly stacks $ZTRAP ;N $ZT S $ZT="QUIT" ;would give a similar result DO SUB1 QUIT SUB1 WRITE !,"THIS IS SUB1" DO SUB2 WRITE !,"THIS IS SUB1 AFTER THE ERROR WAS 'IGNORED'" QUIT SUB2 WRITE !,"THIS IS SUB2" KILL A BAD WRITE A WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>do ^EP10 THIS IS EP10 THIS IS SUB1 THIS IS SUB2 THIS IS SUB1 AFTER THE ERROR WAS 'IGNORED' GTM>
このルーチンは、QUITコマンドに、$ETRAPまたは$ZTRAPをセットします。 ルーチンがラベルBADでエラーに遭遇する時、GT.Mはアクティブなエラーを扱う ISV を実行します。QUITコマンドは、SUB2の実行を終了し、SUB1に戻って実行を移行します。 WRITEは$ZSTATUS特殊変数を使用してエラーメッセージを表示します。デフォルトの動作は、$ETRAPのコードが完了した後に、QUITすることなので、現在のレベルで取りうるアクションが何もない場合、このテクニックは、$ETRAP="" の意味論を避けるために、プレースホルダとして主に$ETRAPとともに利用されます。$ZTRAPで、デフォルトの動作がエラーを発生させたその行の開始時に実行を再開するためには、QUITはプレースホルダ以上のものです。
HALTコマンドは、ルーチンの実行を終了し、シェルのレベルに制御を戻します。 SET $ETRAP="HALT" または $ZTRAP="HALT" は、"HALT" コードがシェルに戻るエラー状態コードを通過しないことを除いて、空の文字列にISVを設定するのと似ています。 HALTの後、$? には、ゼロ(0)が含まれています。contains zero (0).
ZHALTはHALTのように動作しますが、GT.MはOSシェルに戻って引き継ぎます。UNIXシェルは通常、戻りコードを1バイトに制限するので、ZHALT引数の値を切り捨てる可能性があります。
例:
GTM>ZPRINT ^EP11 EP11 WRITE !,"THIS IS ",$TEXT(+0) SET $ECODE="";this affects only $ETRAP SET $ETRAP="HALT";this implicitly stacks $ZTRAP ;SET $ZTRAP="HALT";would give a similar result KILL A BAD WRITE !,A WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>DO ^EP11 THIS IS EP11 $
エラー処理オプションの概要 | |
---|---|
エラー処理の特徴 |
説明と可能な使用法 |
$ETRAP="BREAK" $ZTRAP="BREAK" |
エラーに遭遇した際に、エラーの性質を決定するためにインタラクティブなデバッギングを可能にするダイレクトモードに戻ります。 |
$ETRAP="GOTO.." $ZTRAP="GOTO.." |
エラーが発生した際に制御を移行し、エラー後の実行の継続を可能にします。エラーを記録したり報告するエラー処理ルーチンを使用してください。 |
$ETRAP="ZGOTO.." $ZTRAP="ZGOTO.." |
GOTOに似ていますが、追加的にスタックからのレベルの移動が可能になります。特定のポイントへリカバリを可能にするメニューなどに使用します。 |
NEW $ETRAP NEW $ZTRAP |
NEW $ETRAPは古い値をスタックしますが、現在の値は変更しません。NEW $ZTRAPは古い値をスタックし、現在の値を空の文字列に設定します。通常は、SET $ETRAP または SET $ZTRAP が続きます。 与えられたレベルからQUITした後、GT.Mは、NEWする前に保持する値を復元します。アプリケーション内の異なるレベルでのエラー処理の異なるメソッドを有効にするために使用します。 |
$ETRAP="DO..." |
エラーが発生した際に、別のラベルに一時的に実行を移します。 DOから復帰した後、GT.Mは、エラーが発生した時のスタックレベルからQUITします。 制御がネストされたレベル以下で、呼び出し側のコードに、または、トラップハンドラに返すかどうかは、$ECODEの値に依存します。 |
$ZTRAP="DO..." |
エラーが発生した際に、別のラベルに一時的に実行を移します。 GT.MがDOから戻り$ZTRAPのアクションを完了すると、実行はエラーを含む行の先頭で続行し、エラーを含む行全体を再実行します。オペレータは、エラー状態を修正するために介入することができるI/Oデバイスのエラーで使用してください。 |
$ZTRAP="" |
ステータスコードでshellに戻り、実行を終了します。もしエラー処理ルーチンでSETする場合は、無限ループを防ぎます。 ダイレクトモードへのアクセスを防ぎます。 呼び出し側のshell が $? をテストする必要があるときに、プロダクションコードで使用します。 |
$ETRAP="SET $ECODE=""""" $ZTRAP="QUIT" |
エラーが発生した際にそのレベルで実行を終了し、直後に続く呼び出しのポイントで呼び出しレベルに戻ります。 特定のレベルでエラーを無視し実行を継続するために使用します。 |
$ZTRAP="HALT" |
正常終了が発生したかのようにシェルlに戻ります。 ダイレクトモードへのアクセスを避けます。呼び出し側のシェルがGT.Mプロセスの終了ステータスを調べる必要がない場合に、プロダクションコードで使用してください。 |
もし $ZTRAPに無効なソースコードが含まれている場合は、GT.Mはエラーメッセージを表示し、ダイレクトモードにプロセスを置きます。
もし$ZTRAPによって指定されたアクションが$ZTRAPの値を変更する前に別のランタイムエラーの結果を生じさせる場合、スタックオーバーフローがGT.Mイメージを終了するまで、繰り返し$ZTRAPを呼び出すループになることがあります。 $ZTRAPを単純にキープし、例外処理をデバッグするために特別な注意を払ってください。
注意 | |
---|---|
$ETRAPコード内のエラーは、暗黙の TROLLBACK:$TLEVEL QUIT:$QUIT "" QUIT をトリガします。 |
GT.Mは、エラー状態に関する情報を調べて記録するための多くの標準機能と拡張機能が用意されています。
拡張機能は次のとおりです:
ZSHOW
ZWRITE
$ECODE
$STACK
$STACK()
$ZSTATUS
$ZJOBEXAM()
$ZLEVEL
ZSHOWコマンドは、現在のM環境に関する情報を表示します。ZSHOWの引数は、出力情報の1つ以上のタイプを選択するコードを含む式を含むことができます。
A:自動再リンク(auto-relink)情報を選択
B:ZBREAK情報を選択
C:ロードされた外部呼び出しパッケージとそのルーチンのリストを提供します。ZSHOW "C" は、アクセス可能であるがプロセスによってアクセスされていないパッケージを報告しません。
D:オープンデバイスの情報を選択
G:グローバル統計の情報を選択
I:固有の特殊変数を選択
L:プロセスが保持しているロックを選択
R:ルーチンのハッシュでMスタックを選択
S:Mスタックを選択
V:ローカル変数を選択
*:Aを除くすべての可能なZSHOW情報を選択
引数なしのZSHOWが、現デバイス上でMスタックを表示します。開始から現在の実行レベルまでプログラムのスタックをリスト表示します。
ZWRITEコマンドは、定義済みの変数の現在値を表示します。 ZWRITEは、変数のコンテキストを調べたり保存するためのツールを提供します。 ZWRITEとZSHOWは、現在のローカル変数のみを表示することができます。新しいコマンドで保護されているローカル変数状態や呼び出されたフォーマルリストの外観は表示できません。WRITEは、現在のグローバル変数も表示します。
$ECODE特殊変数には、Mの標準と、ユーザ定義と、GT.Mの特定のエラーコードが含まれています
$STACK特殊変数には、Mの実行スタックの深さの中の現在のレベルが含まれています。
$STACK() 関数は、実行環境のアスペクト(様相)を記述する文字列を返します。
$ZLEVEL特殊変数は、DOとXECUTEコマンドのネストレベルを示す整数値を保持します。 $ZLEVELは、常に、そのコンテキストで ZSHOW "S" の発行で表示されるレベルの整数カウント数が入っています。
$ZJOBEXAM() 関数は、プロセス・コンテキストのダンプを格納したファイルへのフルパスを示す文字列を返します。
$ZSTATUS特殊変数は、実行中のエラー状態コードと最後のエラー状態の場所を記録します。
I/O操作では、GT.Mは、$ZAと$ZBと$ZEOF特殊変数を使用します。 $ZAは、現デバイス上の最後の読み取りによって決定されたステータスが含まれています。
記録の保持を簡素化するために、アプリケーションは、エラーに関する情報を記録するエラー処理ルーチンに、$ZTRAPをセットできます。 次のセクションでは、これを行うルーチンERR.mの例を紹介します。
GTM>ZPRINT ^ERR ERR0;;RECORD CONTECT OF AN ERROR ; RECORD SET $ZTRAP="GOTO OPEN" ZSHOW "*":^ERR($J,$H) GOTO LOOPT;$H might change LOOPV ZSHOW "V":^ERR($J,$H,"VL",$ZLEVEL) LOOPT IF $ZLEVEL>1 ZGOTO $ZLEVEL-1:LOOPV STACK SET $ZTRAP="GOTO WARN" SET %ERRVH=$H;can cause error if memory low SET ^ERR($J,%ERRVH,"$STACK")=$STACK SET ^ERR($J,%ERRVH,"$STACK",-1)=$STACK(-1) FOR %ERRVI=$STACK(-1):-1:1 DO . SET %ERRVK="" . FOR %ERRVJ="PLACE","MCODE","ECODE" DO . . SET %ERRVK=%ERRVK_$STACK(%ERRVI,%ERRVJ)_"|~|" . SET ^ERR($J,%ERRVH,"$STACK",%ERRVI)=%ERRVK GOTO WARN OPEN SET $ZTRAP="GOTO OPEN1" SET %ERRIO=$IO,%ERRZA=$ZA,%ERRZB=$ZB,%ERRZE=$ZEOF SET %ERRVF="REC.ERR" SET %ERRVF=$ZDATE($H,"YEARMMDD2460SS")_"_"_$J_".ERR" OPEN %ERRVF:NEWVERSION USE %ERRVF S $ZT="S $ZT="" G WARN"" U $P:(NOCENA:CTRAP="""") G STAC" ZSHOW "*" KILL %ERRVF,%ERRIO,%ERRZA,%ERRZB,%ERRZE GOTO LOOPU LOOPF WRITE !,"LOCAL VARIABLES FOR ZLEVEL: ",$ZLEVEL,! ZWRITE LOOPU IF $ZLEVEL>1 ZGOTO $ZLEVEL-1:LOOPF WRITE ! STAC SET $ZTRAP="GOTO WARN" WRITE !,"PROGRAM STACK: ",! WRITE !,"$STACK: ",$STACK,! WRITE !,"$STACK(-1): ",$STACK(-1),! FOR %ERRVI=$STACK(-1):-1:1 DO . WRITE !,"LEVEL: ",%ERRVI . SET %ERRVK=10 . FOR %ERRVJ="PLACE","MCODE","ECODE" DO .. W ?%ERRVK,"",%ERRVJ,":",$STACK(%ERRVI,%ERRVJ) .. SET %ERRVK=%ERRVK+20 CLOSE $IO WARN SET $ZTRAP="GOTO FATAL" IF $P=$I SET %ERRIO=$IO,%ERRZA,%ERRZB=$ZB,%ERRZE=$ZEOF USE $P:(NOCENABLE:CTRAP="":EXCEPTION="") WRITE !,"YOU HAVE ENCOUNTERED AN ERROR" WRITE !,"PLEASE NOTIFY JOAN Q SUPPORT PERSON",! FATAL SET $ZTRAP="" ZM +$P($ST($ST(-1),"ECODE"),"Z",2)
エラーのさまざまなフォールバックアクションのイベントで取られているように、ルーチンは値の順序に$ZTRAPをセットします。もしSTACKCRITのエラーが発生した場合、GT.Mは、エラー処理のための少量のスペースを作ります。しかし、もしエラーハンドラがネスティングルーチンまたはローカル変数の操作によりかなり大量のスペースを使い果たしている場合、エラーハンドラは、別のSTACKCRITエラーを引き起こすことがあります。このケースでは、無限ループになるエラー処理が可能で、したがって、各エラーが完了し閉じるルーチンに移動するように、このルーチンは $ZTRAPを変更します。
最初それは、グローバル ^ERRでコンテキスト情報を格納しようとします。LOOPVからLOOPTまでのコードは、ZSHOWコマンドを使用して呼び出しレベルを記録します。この手法は、アプリケーションプログラムが各レベルのローカル変数を定義またはNEWするような状況に対応します。コードは、$ZLEVELの値が1(1)より大きい各インスタンスのループのパススルーを実行します。各パスに対して、ERR.M は、ZGOTOで$ZLEVELの値をデクリメントします。$ZLEVELの値が1つ(1)に到達すると、STACKラベルの時点とそれ以降のコードは、$STACK()関数で利用可能なエラーのコンテキストを格納します。
もしこの情報のいずれかを格納について問題がある場合、^ERRは、現在のデフォルト作業ディレクトリにファイル内のコンテキスト情報を格納しようとします。もしファイルを使用する場合、それはするために(OPENラベルの時点)、I/O操作に関するレコード情報、エラー時点で現デバイス上で、エラーハンドラはログファイルを開く前にデバイス固有のI/O特殊変数$IO、$ZA、$ZB、$ZEOF の値をローカル変数にSETします。
ルーチンは、日付とプロセスの$JOBで構成される名前のログファイルをOPENします。NEWVERSION デバイスパラメータは、ファイルの新しいバージョンを作成するためにGT.Mに指示します。LOOPF-LOOPUのコードは、上述したものと類似の方法で、ZWRITEコマンドを使用して呼び出しレベルを記録します。もしファイルに書き込もうとしてエラーが発生する場合は、$ZTRAPは、プリンシプルデバイスをUSEし、ユーザターミナル上で最小限のエラーコンテキストを提供しようとする中で、STACラベルに制御を移行します。STACラベルの位置とそれに続くコードは、$STACK()関数で利用可能なエラーのコンテキストを記録します。
ラベルWARNで、ルーチンは、エラーが発生したことと通知を、ユーザに通知を試みます。
ラベルFATALで、ZMESSAGEコマンドがエラーを再び知らせます。(適切な設定で)$ETRAPと$ZTRAPが現在nullであるために、GT.Mはホストのシェルへプロセスの制御をリリースします。この例では、ユーザはダイレクトモードへのアクセス権をけっして持ちません。
例:
GTM>zprint ^EP13 EP13 WRITE !,"THIS IS ",$TEXT(+0) SET $ZTRAP="GOTO NODB" KILL ^ERR NODB SET $ECODE="";this affects only $ETRAP ;S $ET="GOTO ^ERR";this implicitly stacks $ZTRAP N $ZT S $ZT="GOTO ^ERR" ;gives similar result DO SUB1 WRITE !,"THIS IS THE END" QUIT SUB1 WRITE !,"THIS IS SUB1" NEW SET (A,B,C)=$ZLEVEL DO SUB2 QUIT SUB2 WRITE !,"THIS IS SUB2" NEW SET (B,C,D)=$ZLEVEL DO SUB3 QUIT SUB3 WRITE !,"THIS IS SUB3" NEW SET (A,C,D)=$ZLEVEL DO BAD BAD NEW (A) SET B="BAD" WRITE 1/0 WRITE !,"THIS IS NOT DISPLAYED" QUIT GTM>do ^EP13 THIS IS EP13 THIS IS SUB1 THIS IS SUB2 THIS IS SUB3 PROGRAM STACK: $STACK: 5 $STACK(-1): 5 LEVEL: 5 PLACE:BAD+2^EP13 MCODE: WRITE 1/0 ECODE:,M9,Z150373210, LEVEL: 4 PLACE:SUB3+3^EP13 MCODE: DO BAD ECODE: LEVEL: 3 PLACE:SUB2+3^EP13 MCODE: DO SUB3 ECODE: LEVEL: 2 PLACE:SUB1+3^EP13 MCODE: DO SUB2 ECODE: LEVEL: 1 PLACE:NODB+3^EP13 MCODE: DO SUB1 ECODE: YOU HAVE ENCOUNTERED AN ERROR PLEASE NOTIFY JOAN Q SUPPORT PERSON %GTM-E-DIVZERO, Attempt to divide by zero %GTM-I-RTSLOC, At M source location FATAL+1^ERR
例 EP13は、$ZTRAP="GOTO ^ERR" のセットにより、エラー記録用のルーチンを使用します。ルーチンがラベルBADでエラーに遭遇する時、GT.MはラベルERRへ制御を移行します。 その後、Afterwards .ERR ファイルには次のようななようがあります:
GTM>zwrite ^ERR ^ERR(4806,"62364,27842","D",1)="/dev/pts/8 OPEN TERMINAL NOPAST NOESCA NOREADS T YPE WIDTH=80 LENG=22 EDIT " ^ERR(4806,"62364,27842","G",0)="GLD:*,REG:*,SET:68,KIL:3,GET:0,DTA:0,ORD:0,ZPR:0 ,QRY:0,LKS:0,LKF:0,CTN:0,DRD:3,DWT:0,NTW:68,NTR:6,NBW:71,NBR:154,NR0:0 ,NR1:0,NR2:0,NR3:0,TTW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3 :0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0" ^ERR(4806,"62364,27842","G",1)="GLD:/home/jdoe/.fis-gtm/V5.4-002B_x86/g/gtm.gld ,REG:DEFAULT,SET:69,KIL:4,GET:0,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0,CT N:69,DRD:3,DWT:0,NTW:69,NTR:7,NBW:72,NBR:160,NR0:0,NR1:0,NR2:0,NR3:0,T TW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0 ,TC2:0,TC3:0,TC4:0,ZTR:0" ^ERR(4806,"62364,27842","I",1)="$DEVICE=""""" ^ERR(4806,"62364,27842","I",2)="$ECODE="",M9,Z150373210,""" ^ERR(4806,"62364,27842","I",3)="$ESTACK=5" ^ERR(4806,"62364,27842","I",4)="$ETRAP=""""" ^ERR(4806,"62364,27842","I",5)="$HOROLOG=""62364,27842""" ^ERR(4806,"62364,27842","I",6)="$IO=""/dev/pts/8""" ^ERR(4806,"62364,27842","I",7)="$JOB=4806" ^ERR(4806,"62364,27842","I",8)="$KEY=""""" ^ERR(4806,"62364,27842","I",9)="$PRINCIPAL=""/dev/pts/8""" ^ERR(4806,"62364,27842","I",10)="$QUIT=0" ^ERR(4806,"62364,27842","I",11)="$REFERENCE=""^ERR(4806,""""62364,27842"""","""" I"""",10)""" ^ERR(4806,"62364,27842","I",12)="$STACK=5" ^ERR(4806,"62364,27842","I",13)="$STORAGE=2147483647" ^ERR(4806,"62364,27842","I",14)="$SYSTEM=""47,gtm_sysid""" ^ERR(4806,"62364,27842","I",15)="$TEST=1" ^ERR(4806,"62364,27842","I",16)="$TLEVEL=0" ^ERR(4806,"62364,27842","I",17)="$TRESTART=0" ^ERR(4806,"62364,27842","I",18)="$X=12" ^ERR(4806,"62364,27842","I",19)="$Y=21" ^ERR(4806,"62364,27842","I",20)="$ZA=0" ^ERR(4806,"62364,27842","I",21)="$ZALLOCSTOR=893732" ^ERR(4806,"62364,27842","I",22)="$ZB=""""" ^ERR(4806,"62364,27842","I",23)="$ZCHSET=""M""" ^ERR(4806,"62364,27842","I",24)="$ZCMDLINE=""""" ^ERR(4806,"62364,27842","I",25)="$ZCOMPILE=""""" ^ERR(4806,"62364,27842","I",26)="$ZCSTATUS=0" ^ERR(4806,"62364,27842","I",27)="$ZDATEFORM=0" ^ERR(4806,"62364,27842","I",28)="$ZDIRECTORY=""/home/jdoe/""" ^ERR(4806,"62364,27842","I",29)="$ZEDITOR=0" ^ERR(4806,"62364,27842","I",30)="$ZEOF=0" ^ERR(4806,"62364,27842","I",31)="$ZERROR=""Unprocessed $ZERROR, see $ZSTATUS""" ^ERR(4806,"62364,27842","I",32)="$ZGBLDIR=""/home/jdoe/.fis-gtm/V5.4-002B_x86/g /gtm.gld""" ^ERR(4806,"62364,27842","I",33)="$ZININTERRUPT=0" ^ERR(4806,"62364,27842","I",34)="$ZINTERRUPT=""IF $ZJOBEXAM()""" ^ERR(4806,"62364,27842","I",35)="$ZIO=""/dev/pts/8""" ^ERR(4806,"62364,27842","I",36)="$ZJOB=0" ^ERR(4806,"62364,27842","I",37)="$ZLEVEL=6" ^ERR(4806,"62364,27842","I",38)="$ZMAXTPTIME=0" ^ERR(4806,"62364,27842","I",39)="$ZMODE=""INTERACTIVE""" ^ERR(4806,"62364,27842","I",40)="$ZPATNUMERIC=""M""" ^ERR(4806,"62364,27842","I",41)="$ZPOSITION=""RECORD+1^ERR""" ^ERR(4806,"62364,27842","I",42)="$ZPROCESS=""""" ^ERR(4806,"62364,27842","I",43)="$ZPROMPT=""GTM>""" ^ERR(4806,"62364,27842","I",44)="$ZQUIT=0" ^ERR(4806,"62364,27842","I",45)="$ZREALSTOR=898568" ^ERR(4806,"62364,27842","I",46)="$ZROUTINES=""/home/jdoe/.fis-gtm/V5.4-002B_x86 /o(/home/jdoe/.fis-gtm/V5.4-002B_x86/r /home/jdoe/.fis-gtm/r) /usr/l ib/fis-gtm/V5.4-002B_x86""" ^ERR(4806,"62364,27842","I",47)="$ZSOURCE=""""" ^ERR(4806,"62364,27842","I",48)="$ZSTATUS=""150373210,BAD+2^EP13,%GTM-E-DIVZERO, Attempt to divide by zero""" ^ERR(4806,"62364,27842","I",49)="$ZSTEP=""B""" ^ERR(4806,"62364,27842","I",50)="$ZSYSTEM=0" ^ERR(4806,"62364,27842","I",51)="$ZTNAME=""""" ^ERR(4806,"62364,27842","I",52)="$ZTDATA=0" ^ERR(4806,"62364,27842","I",53)="$ZTEXIT=""""" ^ERR(4806,"62364,27842","I",54)="$ZTLEVEL=0" ^ERR(4806,"62364,27842","I",55)="$ZTOLDVAL=""""" ^ERR(4806,"62364,27842","I",56)="$ZTRAP=""GOTO OPEN""" ^ERR(4806,"62364,27842","I",57)="$ZTRIGGEROP=""""" ^ERR(4806,"62364,27842","I",58)="$ZTSLATE=""""" ^ERR(4806,"62364,27842","I",59)="$ZTUPDATE=""""" ^ERR(4806,"62364,27842","I",60)="$ZTVALUE=""""" ^ERR(4806,"62364,27842","I",61)="$ZTWORMHOLE=""""" ^ERR(4806,"62364,27842","I",62)="$ZUSEDSTOR=893732" ^ERR(4806,"62364,27842","I",63)="$ZVERSION=""GT.M V5.4-002B Linux x86""" ^ERR(4806,"62364,27842","I",64)="$ZYERROR=""""" ^ERR(4806,"62364,27842","L",0)="MLG:0,MLT:0" ^ERR(4806,"62364,27842","S",1)="RECORD+1^ERR" ^ERR(4806,"62364,27842","S",2)="SUB3+3^EP13" ^ERR(4806,"62364,27842","S",3)="SUB2+3^EP13" ^ERR(4806,"62364,27842","S",4)="SUB1+3^EP13" ^ERR(4806,"62364,27842","S",5)="NODB+3^EP13" ^ERR(4806,"62364,27842","S",6)="+1^GTM$DMOD (Direct mode) " ^ERR(4806,"62364,27842","V",1)="A=5 ;*" ^ERR(4806,"62364,27842","V",2)="B=""BAD""" File contents: $DEVICE="" $ECODE=",M9,Z150373210,M6,Z150373850," $ESTACK=5 $ETRAP="" $HOROLOG="62364,27842" $IO="20110930074402_4806.ERR" $JOB=4806 $KEY="" $PRINCIPAL="/dev/pts/8" $QUIT=0 $REFERENCE="^ERR(4806,""62364,27842"",""S"",6)" $STACK=5 $STORAGE=2147483647 $SYSTEM="47,gtm_sysid" $TEST=1 $TLEVEL=0 $TRESTART=0 $X=0 $Y=18 $ZA=0 $ZALLOCSTOR=895460 $ZB="" $ZCHSET="M" $ZCMDLINE="" $ZCOMPILE="" $ZCSTATUS=0 $ZDATEFORM=0 $ZDIRECTORY="/home/jdoe/" $ZEDITOR=0 $ZEOF=1 $ZERROR="Unprocessed $ZERROR, see $ZSTATUS" $ZGBLDIR="/home/jdoe/.fis-gtm/V5.4-002B_x86/g/gtm.gld" $ZININTERRUPT=0 $ZINTERRUPT="IF $ZJOBEXAM()" $ZIO="20110930074402_4806.ERR" $ZJOB=0 $ZLEVEL=6 $ZMAXTPTIME=0 $ZMODE="INTERACTIVE" $ZPATNUMERIC="M" $ZPOSITION="OPEN+7^ERR" $ZPROCESS="" $ZPROMPT="GTM>" $ZQUIT=0 $ZREALSTOR=898568 -------------------- Extra lines removed --------------------