【入門編】ON CONVERSIONによるデータ変換エラーの捕捉 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといった他のプログラミング言語の経験がある方にとって、初めて目にするPL/I(ピーエルアイ)のソースコードは、少し独特で要塞のように頑丈に見えるかもしれませんね。

「変数の宣言方法がなんだか独特だな…」
「予約語がないってどういうこと?」

そんな風に面食らっている方もいらっしゃるでしょう。でも、大丈夫です。怖がる必要は全くありません。今回は、レガシーシステムの現場で最も頻出するトラブルの一つ「データ変換エラー(CONVERSION条件)」をテーマに、PL/Iの懐の深いエラーハンドリングの世界を一緒に優しく紐解いていきましょう。

バッチ処理の途中で「突然ジョブが異常終了した!」という夜中の呼び出しに怯える日々とは、今日でお別れです。

—

1. 他言語とはちょっと違う?PL/Iの識別子と「予約語を持たない」世界

JavaやCOBOLでは、「この単語は言語の命令だから変数名に使っちゃダメ!」という予約語(Reserved Words)がたくさんありますよね。

しかし、PL/Iの非常にユニークな(そして少しお茶目な)特徴として、「PL/Iには真の意味での予約語が存在しない」という仕様があります。

どういうことかと言うと、`IF` や `READ` といった命令語であっても、文脈から判断できるため、理屈上は変数名として使うことすらできてしまうのです。(※もちろん、ソースコードが読みにくくなるので絶対にやめましょうね!)

1
/ PL/Iの変数宣言の例:とっても自由度が高いんです /
DCL IF FIXED BIN(31); / 「IF」という名前の数値変数(良い子はマネしないでね) /
DCL TOTAL FIXED DEC(7,2); / 合計を格納する10進数変数 /

このように、データ型(属性)を `DCL`(DECLAREの略)の後にスッキリと記述するのがPL/I流です。他言語の経験者なら「あ、データ定義だな」とすぐに直感できるはずです。

—

2. 現場の悪夢:「文字が混ざった!」による変換エラー

基幹システムのバッチ処理で最も頭が痛い問題、それは「外部から連携されてきたマスタファイルや電文のデータが、実は汚れていた」というケースです。

例えば、数値を入れるべき領域(ゾーン10進数やパック10進数、あるいは数値文字型の領域)に、うっかりスペースや漢字、ゴミデータが混入していたとします。

これをそのまま計算や数値項目への代入に使おうとすると、ハードウェア側で「おいおい、計算できないよ!」と悲鳴を上げます。これが、PL/Iでいう CONVERSION条件(データ変換エラー) の発生です。

放置するとどうなるか?

もしこのエラーをそのまま放置(ハンドリングなし)していると、親切なOSやコンパイラは即座にジョブを「S0C7(あるいはそれに類するシステム異常終了)」で強制終了させ、夜中の運用オペレーターさんからあなたへ悲痛な電話がかかってくることになります……。

—

3. ON CONVERSION でエラーを優しく包み込む

ここで登場するのが、PL/Iの真骨頂であるONユニット(例外処理機構)です。
「もしデータ変換でエラーが起きたら、クラッシュさせるんじゃなくて、私がこう処理するから教えてね」と、プログラムにあらかじめ言い聞かせておくことができます。

実際のコードを見てみましょう。

1
CONV_TEST: PROC OPTIONS(MAIN);

/ 変数の宣言 /
DCL RAW_INPUT CHAR(5); / 外部から受け取った文字データ /
DCL NUM_VAL FIXED DEC(5); / 数値として扱いたい変数 /
DCL ERROR_FLAG BIT(1) INIT(‘0’B); / エラー検知フラグ /

/ ★ここがポイント!CONVERSIONエラーの監視をスタート /
ON CONVERSION BEGIN;
ERROR_FLAG = ‘1’; / エラーが起きたらフラグをONに /
NUM_VAL = 0; / 安全のため、とりあえずゼロで埋めておく /
PUT SKIP LIST(‘【警告】数値変換できない不正データ検知: ‘ || RAW_INPUT);
END;

/ テストデータの代入(わざと数値にならない文字を入れています) /
RAW_INPUT = ’12A45’;

/ ここで文字から数値への暗黙の変換が発生! /
NUM_VAL = RAW_INPUT;

/ エラー判定のチェック /
IF ERROR_FLAG THEN
PUT SKIP LIST(‘処理は継続しますが、スキップ処理またはログ保存が必要です。’);
ELSE
PUT SKIP LIST(‘正常な数値です。値は: ‘, NUM_VAL);
END;

END CONV_TEST;

このコードの優しいポイント

1. `ON CONVERSION BEGIN; … END;` というブロックで、変換エラーが起きたときの「避難経路」をあらかじめ用意しています。
2. エラーで即座にジョブが落ちるのを防ぎ、変数に安全なデフォルト値(今回は `0`)を代入して処理をスマートに継続させています。
3. 「どこがおかしかったのか」をログに出力できるため、後から調査するインフラ担当者や保守エンジニアにとっても非常に親切です。

—

4. 万が一ダンプ(SYSUDUMP)になってしまったときの解析手法

もし `ON` ユニットを書き忘れたり、想定外の例外でプログラムがアベンド(異常終了)してしまった場合、メインフレームの醍醐味(?)であるコアダンプ(SYSUDUMP / CEEDUMP)の解析が必要になります。

「英数字の羅列なんて読めないよ……」と怯える必要はありません。見るべきポイントは決まっています。

1. レジスタとPSW(プログラムステータスワード)の確認
ダンプリストの冒頭にあるPSWから、エラーが起まった正確なマシン語の命令アドレス(オフセット)を特定します。
2. コンパイラのリスト(LIST)との照合
PL/Iのコンパイルリストを出力しておき、「どのソース行の、どの代入文でその命令が生成されたか」を逆引きします。大抵の場合、`CHAR` 型から `FIXED` 型への代入を行っているアセンブラコード(CVT命令など)の周辺でスピンしています。
3. ワーキング・ストレージのダンプ(Storage Dump)
エラー当時の変数のメモリ領域を覗き込み、「あ、ここは `X’F1F2C1F4F5’`(EBCDICの ’12A45’)になってるから、アルファベットの ‘A’ (`C1`) が混ざって落ちたんだな」と原因を特定します。

—

まとめ

いかがでしたでしょうか?
PL/Iの `ON CONVERSION` は、一見すると古臭い構文に見えるかもしれませんが、「予期せぬ外部データの汚染から、基幹システムの巨大なバッチ処理を守り抜く」ための、先人たちの知恵が詰まった非常に強力な防壁です。

Javaの `try-catch` ブロックに少し似ている感覚で捉えていただければ、ぐっと親しみやすくなったのではないでしょうか。

レガシーシステムのマイグレーションや保守において、データエラーに直面したときは、ぜひ今回の `ON CONVERSION` を思い出して、優しく安全にエラーをハンドリングしてあげてくださいね。あなたのメインフレームライフが、少しでも快適で楽しいものになりますように!

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