PL/Iの「編集文字」が語る、基幹システムの静かなる警告
メインフレームの保守やマイグレーションの現場で、長年PL/Iに触れていると、ふと忘れがちになるのが「数値から文字への変換」という何気ない処理の深淵です。特に `PIC ‘9’` と `PIC ‘Z’`。この二つの編集文字の使い分け一つで、システムの信頼性は大きく揺らぎます。
今日は、JavaやC#への移行を控えたテックリードの皆さんに、あえてこの「PL/Iの数値編集」という古典的かつ急所となるテーマを、実務的な視点から深掘りしてお伝えします。
—
1. ゼロサプレス(PIC ‘Z’)の陥穽とCONVERSION条件
多くのエンジニアが `PIC ‘Z9’` や `PIC ‘ZZZ9’` を使って数値を文字化しますが、ここには「数値がゼロの場合、すべてスペースになる」という仕様が潜んでいます。
DCL WORK_AMT FIXED DEC(5,0) INIT(0);
DCL DISP_AMT PIC ‘ZZZ9’;
/ WORK_AMTが0のとき、DISP_AMTは ‘ 0’ となるか ‘ ‘ となるか。
この微妙な挙動の差が、後続の帳票レイアウトを崩壊させる。 /
DISP_AMT = WORK_AMT;
現代の言語であれば、この程度の変換でアベンド(ABEND)することはありません。しかし、PL/Iのコンパイラは、型変換のルールを逸脱したデータ、例えばパック10進数(COMP-3)の中に不正な符号(X’0A’~X’0F’以外)が混入している場合、即座に `CONVERSION` 条件を発生させます。
移行プロジェクトで最も多い「謎のS0C7(データ例外)」は、実は移行先のJavaで `BigDecimal` に変換する際に検知されるケースが大半です。移行前に、この `CONVERSION` を意図的に発生させてデータを洗浄するバッチを作れるかどうかが、プロジェクトの成否を分ける分水嶺となります。
—
2. パックデシマルの「符号反転」という悪夢
実務で遭遇する最も恐ろしいケースは、DB2から取得したパック10進数(`PIC S9(7) COMP-3`)が、何らかの理由で符号ビットが破壊されている場合です。
CICSのオンライン処理や、古いEBCDIC環境からのデータ移行時、符号の `C`(正)や `D`(負)が正しく認識されず、変換時に `CONVERSION` 条件で落とされるか、あるいは計算結果が狂う。
/ 意図的に符号を破壊したダミーデータでのテスト /
DCL BAD_DATA CHAR(4) INIT(‘12345X’); / 最後のXが符号不正 /
DCL REAL_DATA FIXED DEC(7,0) DEF BAD_DATA;
/ ここで実行時にON CONVERSIONFILE文などで割り込めるかが
プロフェッショナルな設計の分かれ道。 /
ON CONVERSION BEGIN;
PUT SKIP LIST(‘データ変換エラーが発生しました。ログを詳細に出力します。’);
/ ここでダンプを取得し、ポインタを用いたメモリ解析へ繋げる /
CALL ABEND_HANDLER;
END;
—
3. ポインタによる動的メモリ操作とダンプ解析
基幹システムのアーキテクトであれば、`ADDR` 関数と `BASED` 変数を用いた構造体マッピングを避けては通れません。大規模なデータ変換処理を行う際、コンパイラ最適化(`OPTIMIZE(3)`など)を効かせると、変数の寿命が最適化され、ダンプ時に変数の値が参照できないことがあります。
- Tips: デバッグが必要なモジュールには一時的に `TEST` コンパイラオプションを付与し、最適化レベルを下げてください。
- 深層分析: ダンプ内で `PIC ‘9’` がどのようにメモリに展開されているか、`DUMP` コマンドで16進数を見れば、EBCDICの `F0`~`F9` が並んでいることが確認できます。これが `Z` 編集によってスペース(`40`)に置き換わるプロセスを理解することは、マイグレーション先で同じロジックを実装する際の「正当性証明」に不可欠です。
—
4. 移行を見据えたアーキテクチャの提言
JavaやC#へマイグレーションを行う際、PL/Iの `PIC` 編集の挙動を完全に再現しようとして `String.format` を多用するのは推奨しません。
結論として、以下の設計思想を推奨します。
1. バリデーション層の分離: PL/Iの変換ロジックをそのまま移行先に移植するのではなく、入力段階で「数値として妥当か」を判定するバリデーション専用のレイヤーを設けること。
2. 定数化された編集クラス: `PIC ‘Z9’` といった書式を、ビジネスロジック内に直接書かず、`Formatter` クラスとしてカプセル化すること。これにより、仕様変更や将来の言語刷新にも耐えうる保守性が担保されます。
PL/Iは古く、無骨な言語に見えます。しかし、その背後には「ハードウェアを直接叩く」というメインフレーム特有の緊張感と、それを制御するための緻密なルールが存在します。
もし、貴方の目の前で `CONVERSION` 条件が鳴り響いているなら、それはシステムが「データが汚れている」と警鐘を鳴らしている証拠です。その警告を無視せず、メモリの深層からデータを解き明かすこと。それこそが、時代を超えて基幹システムを守り抜く我々アーキテクトの矜持ではないでしょうか。
