【入門編】CICSにおけるEXEC CICS HANDLE CONDITIONによる例外制御 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといったモダン、あるいは少し前の業務系言語をバリバリ書いてきた方にとって、IBMメインフレームの世界、そしてそこで動く「PL/I(ピーエルアイ)」という言語は、どこか要塞のようそびえ立って見え、「なんだか難解で怖いな……」と感じるかもしれません。

でも、安心してくださいね。どんなに歴史のある巨大なシステムであっても、使われているルールは一つひとつ紐解いていけば、必ず「なるほど!」と腑に落ちるシンプルな仕組みでできています。

今回は、PL/Iの基本構文における「識別子の自由さ」に少し触れつつ、オンライン画面制御の王様であるCICS(キックス)の世界で避けて通れない「`EXEC CICS HANDLE CONDITION`による例外制御」について、一緒に優しく紐解いていきましょう!

—

1. ちょっと一息:PL/Iには「予約語」がないって本当?

JavaやCOBOLには、「この単語はシステムのものだから、変数名に使っちゃダメ!」という予約語(キーワード)がたくさんありますよね。例えば、COBOLで `DISPLAY` や `MOVE` を変数名にしようものなら、コンパイラに激怒されてしまいます。

ところが、PL/Iの非常にユニークで、初学者が驚くポイントの一つが「PL/Iには厳密な意味での予約語が存在しない」ということです。

どういうことかと言うと、PL/Iは文脈(コンテキスト)から「あ、ここではこれは命令文だな」「ここでは単なる変数名だな」と賢く判断してくれます。極端な話、`IF` という名前の変数を作ることすらできてしまうのです(もちろん、混乱を招くので絶対におすすめはしませんが!)。

この「柔軟すぎる」言語仕様は、識別子の命名規則にも表れており、最大31文字までのアルファベット、数字、そしてアンダースコア(`_`)を使って、自分にとって分かりやすい名前を自由につけることができます。

この「柔軟で懐の深い」PL/Iの空気感を感じていただいたところで、本題であるCICSの例外制御の世界へと飛び込んでみましょう。

—

2. CICSにおけるエラー処理の基本:HANDLE CONDITIONとは?

さて、舞台はCICS(Customer Information Control System)です。画面から飛んできたリクエストを受け、データベース(DB2やVSAMファイル)をゴリゴリ操作するオンラインプログラムの世界です。

JavaやC#なら、ファイルが見つからなかったり、重複レコードエラーが起きたりすると `try-catch` ブロックで例外(Exception)をスマートに捕捉しますよね。

しかし、CICSの世界(そしてそれを支えるPL/I)では、例外が起きたときの挙動はもう少し「レトロで直感的」です。その代表格が、`EXEC CICS HANDLE CONDITION` というコマンドになります。

例え話:自動ブレーキと「もしも」の時の連絡網

イメージしてみてください。あなたが巨大な遊園地のジェットコースター(CICSオンラインプログラム)を運転しています。
途中で「レールに異常あり(NOTFND:データが無いよ!)」や「同じ人が二重登録されちゃった(DUPREC:重複だよ!)」というトラブルが発生するかもしれません。

そんな時、何の手も打っていなければ、ジェットコースターは緊急停止し、お客様(エンドユーザー)を乗せたままアトラクション全体が強制終了(異常終了・ABEND)してしまいます。それは困りますよね。

そこで、出発する前にこう宣言しておくのです。
「もし『NOTFND(データ無し)』が起きたら、パニックにならずに『ERROR_ROUTINE』というサブルーチンに飛びなさい!」

これが、`HANDLE CONDITION` の正体です。プログラムのあらかじめ決めた場所で「もしこのエラーが起きたら、ここにジャンプしてね」という例外時のジャンプ先(連絡網)をあらかじめ登録しておく仕組みなのです。

—

3. 実践!PL/IとCICSで書く例外制御コード

百聞は一見にしかず。実際のPL/Iコードを見てみましょう。大文字で書かれた重厚な構文ですが、日本語コメントを追っていけば怖くありませんよ。

1
/ ========================================================== /
/ CICSオンラインプログラム:顧客情報参照処理 /
/ ========================================================== /
CUSTREAD: PROC OPTIONS(MAIN);

/ — 変数宣言(データ制御) — /
DCL W_CUST_ID CHAR(5); / 画面から入力された顧客ID /
DCL W_MSG CHAR(40); / 画面に返すメッセージ /

/ ====================================================== /
/ 1. 異常発生時のジャンプ先(コンディション)を登録する /
/ ====================================================== /

/ VSAMファイルからデータが見つからなかった場合の処理を指定 /
EXEC CICS HANDLE CONDITION
NOTFND(ERR_NOT_FOUND)
ERROR(ERR_GENERAL);

/ — 画面からの入力を受け取る(イメージ) — /
/ ※実際にはここで RECEIVE MAP などが入ります /
W_CUST_ID = ‘12345’;

/ ====================================================== /
/ 2. メインのファイル読み込み処理(VSAMのKSDSを読む) /
/ ====================================================== /
EXEC CICS READ FILE(‘CUSTFILE’)
INTO(W_CUST_ID)
RIDFLD(W_CUST_ID);

/ 通常時の処理(データが見つかった場合) /
W_MSG = ‘顧客データが正常に読み込まれました。’;
GOTO SEND_SCREEN;

/ ====================================================== /
/ 3. 例外処理セクション(HANDLE CONDITIONのジャンプ先) /
/ ====================================================== /

ERR_NOT_FOUND:
/ NOTFND(該当データなし)が発生したときにここに飛んでくる /
W_MSG = ‘指定された顧客IDは存在しません。’;
GOTO SEND_SCREEN;

ERR_GENERAL:
/ その他の予期せぬCICSエラーが発生した場合の逃げ道 /
W_MSG = ‘システムエラーが発生しました。管理者にお問い合わせください。’;
/ 落ちる前にログを仕込んだりする処理がここに入ります /
GOTO SEND_SCREEN;

/ ====================================================== /
/ 4. 画面への出力と終了 /
/ ====================================================== /
SEND_SCREEN:
/ ※本来はここで SEND MAP 等でメッセージを画面に出力します /

/ 最後に、設定したハンドル(例外捕捉)を無効化して終了 /
EXEC CICS IGNORE CONDITION NOTFND;

RETURN;

END CUSTREAD;

—

4. ここが現場の落とし穴!「HANDLE CONDITION」のスタックと有効範囲

さて、ここからがレグシーシステムを扱うプログラマとしての腕の見せ所、そしてハマりやすいポイントです。Javaの `try-catch` と大きく違う、CICS特有の「罠」についてお話します。

罠その1:HANDLEは「グローバル(引き継がれる)」に効く

`EXEC CICS HANDLE CONDITION` は、一度宣言すると、そのプログラムが実行している間、あるいは別のプログラムに処理(`LINK` や `XCTL`)を渡すまで、ずっと有効です。
つまり、プログラムのあちこちで気楽に宣言しまくると、「今どのエラーがどこに飛ぶようになっているのか」が分からなくなるスパゲッティ状態になりがちです。

罠その2:サブルーチン呼び出しにおけるスコープの意識

PL/Iの内部プロシージャ(サブルーチン)や、別のCICSプログラムへ制御を移したとき、古いハンドルの設定がそのまま残っていると、意図しない場所でエラーを拾ってしまい、無限ループや想定外のジャンプを引き起こすことがあります。

そのため、安全なプログラミングの鉄則として、

  • エラーをその場で個別に処理したいときは、コマンド単位で `NOHANDLE` オプションを使う
  • 別のプログラムを呼び出す前には、一度 `IGNORE CONDITION` や `PUSH HANDLE / POP HANDLE`(※)でハンドルの状態をきれいに整理・退避する

といった防衛策が必要になります。
(※ `PUSH HANDLE` / `POP HANDLE` は、現在の例外処理のスタックを一時的に保存・復元するCICSの便利な命令です)

—

5. おわりに:怖がらなくて大丈夫、PL/Iはあなたの味方です

いかがでしたでしょうか?
「予約語がない自由な文法を持つPL/I」と、「CICSという巨大なトランザクション基盤の中で動く例外制御(`HANDLE CONDITION`)」。
一見すると古めかしく、冷たいルールに見えるかもしれませんが、そこには「限られたリソースの中で、いかに確実にエラーをハンドリングするか」という先人たちの知恵と工夫がぎっしり詰まっています。

「もしエラーが起きたら、ここに逃げ込んでね」と優しく道案内をしてあげる感覚でコードを眺めてみると、PL/IやCICSの仕組みがぐっと身近に感じられるはずです。

レガシー移行や保守の現場でこのコードに出会ったとき、「あ、あの時のジェットコースターの例えね」と思い出して少しでも心が軽くなっていただければ幸いです。
それでは、快適なメインフレーム開発ライフを!

タイトルとURLをコピーしました