新命令ON-EXIT

V7R4 又は PTF適用済み V7R2以上 で使用可能な新命令 「**ON-EXIT**」。

「**ON-EXIT**」の特徴は、サブプロシージャ内が終了する際には ***”必ず実行される”*** という点。
これまで、辛かったのは、もし **MONITOR** していない例外が発生した場合がある場合は、*PSSR を定義したりで例外をキャッチしていたが、例外が例外を起こす悪夢や、発生元をSDSに頼るなど、処理が煩雑になりがち。
しかし、「**ON-EXIT**」 を使う事で、そのサブプロシージャの処理に準じた例外を等をハンドリング出来たり、中途半端な状況の顛末処理を必ず実行させる事が出来る。以下は、使用例。

```rpgle:QII0130R.rpgle
H DFTACTGRP(*NO) ACTGRP(*NEW)
F*- ---<< ファイル定義    >>-----*
FITEM      UF A E           K DISK
D*- ---<< 変数定義    >>-----*
D MSG             S             40A
C*- ***************************************************************
C*- *  ＫＬＩＳＴ                                                **
C*- ***************************************************************
C     ITEMKEY1      KLIST
C                   KFLD                    K@CODE            5 0           商品コード
C*- ***************************************************************
C*- *  メインロジック                                            **
C*- ***************************************************************
C                   Z-ADD     99999         K@CODE                          商品コード
C                   EVAL       MSG        = SUBPROC1()
C     MSG           DSPLY
C*
C                   Z-ADD     90000         K@CODE                          商品コード
C                   EVAL       MSG        = SUBPROC1()
C     MSG           DSPLY
C*
C                   SETON                                        LR
C                   RETURN
P*- ***************************************************************
P*- *  サブプロシージャ                                          **
P*- ***************************************************************
P SUBPROC1        B
D SUBPROC1        PI             1A
D*- ---<< 変数定義    >>-----*
D NOMON           S               N                                         監視外例外
C*
C* // サブロジック
C*
C                   MONITOR
C     ITEMKEY1      CHAIN     ITEMR                              90
C  N90              WRITE     ITEMR
C                   ON-ERROR  *ALL
C                   EVAL      MSG         = '[ERROR:*ALL]'
C                                         + %CHAR(%STATUS)
C                                         + '*ALL 監視エラー '
C     MSG           DSPLY
C                   RETURN                  'E'
C                   ENDMON
C*
C                   Z-ADD     *ZERO         W#ZERO            3 0
C     100           DIV       W#ZERO        W#ZERO
C*
C                   RETURN                  'S'
C*
C* // 必ずサブプロシージャで通過する終了処理
C                   ON-EXIT   NOMON
C  N90              UNLOCK    ITEM
C                   EVAL      MSG         = '[EXIT]'
C                                         + ' 全ての処理が通過する '
C                                         + %CHAR(NOMON)
C     MSG           DSPLY
C*
C*  監視外の例外が発生している場合
C                   IF        NOMON
C*      ログなど ...
C                   RETURN                  'E'
C                   ENDIF
P                 E
```

上記例では、監視外のゼロ除算を行うと`MSGW`になるが、`C：キャンセル`で応答した場合でも、「**ON-EXIT**」は必ず最後に実行される。以下スクリーンショット。
まだ、試していないが、マニュアルによると呼び出しスタックの上位がキャンセルされても、実行される様。これは、結構便利かも！
![2022-11-27_145516.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100029/f32a58d1-9dab-2d34-e157-4add87dd13fe.png)

注意点は
- サブプロシージャ限定であること。メインプロシージャでは使えない。
- DFTACTGRP(*YES) では使えない
- 幾つかのAPIが使えない。CEEDOD、CEEGSI、CEETSTA
- 幾つかの命令が使えない。BEGSR、DUMP、EXSR、GOTO、RESET、TAG

上記、以外もマニュアルには記載されていますが、割愛。例外監視していないエラーの場合`DUMP`は使えたら良かったのになぁーって感じです。