PL/Iの「見えない落とし穴」:FIXED BINARYの精度とON FIXEDOVERFLOWの真実
現場の諸君、今日もメインフレームの迷宮で格闘していることだろう。
PL/Iという言語は、一見するとCOBOLよりも自由度が高く、C言語のような柔軟性を持っているように見える。だが、この「自由さ」は時に、保守担当者を地獄へ突き落とす罠にもなり得る。
今回は、我々が日常的に扱う `FIXED BINARY`、いわゆる「バイナリ整数」の内部表現と、境界を超えた時に発生する「あいつ」――`ON FIXEDOVERFLOW`の挙動について、実務的な視点で深掘りしよう。
—
1. なぜ「予約語」がないのか? その功罪
まず大前提として、PL/Iには「予約語(Reserved Words)」が存在しない。これはつまり、`IF` や `THEN` といったキーワードさえも変数名として使えてしまうということだ。
「変数名に `IF` を使うやつなんていないだろう?」と思うかもしれないが、レガシーなソースコードの世界は地獄の釜の蓋が開いている。この仕様はパーサーを非常に複雑にし、コンパイラが「これは変数か? 命令か?」を文脈(Context)から必死に推測していることを忘れてはならない。
この「文脈依存」という性質は、計算精度においても同様の注意を要するのだ。
—
2. FIXED BINARY(15) と (31) のメモリの現実
`FIXED BINARY(15)` と `(31)`。この二つの違いを「単なる数字の大きさ」だと思っていないか?
- FIXED BINARY(15): 2バイト(ハーフワード)で表現される。符号付きのため、扱える範囲は -32,768 ~ 32,767 だ。
- FIXED BINARY(31): 4バイト(フルワード)で表現される。範囲は -2,147,483,648 ~ 2,147,483,647。
内部表現の肝は、「左詰め」ではなく「ワード境界(Alignment)」にある。特にVSAMファイルやストラクチャのマップ(`DEFINED` 属性を使った再定義など)を扱う際、コンパイラは効率のためにパディングを挿入する。この「見えない隙間」を理解していないと、データ構造のダンプを見た時にパニックに陥ることになる。
—
3. ON FIXEDOVERFLOW:沈黙の破壊者を止めるには
計算結果が型の上限を超えたとき、PL/Iのデフォルトの挙動は「計算を続行し、値を切り捨てて警告なし」という、実務上もっとも恐ろしい選択肢をとることがある。ここで登場するのが `ON FIXEDOVERFLOW` ブロックだ。
これを使えば、オーバーフローが発生した瞬間に制御を奪い、ログを出力したり、異常終了(ABEND)を意図的に引き起こしてデータ破損を防ぐことができる。
実践的な実装例
1
/ ———————————————————– /
/ FIXEDOVERFLOWの制御とバイナリ演算のサンプル /
/ ———————————————————– /
TEST_CALC: PROC OPTIONS(MAIN);
DCL V_COUNT_15 FIXED BIN(15) INIT(30000);
DCL V_RESULT_15 FIXED BIN(15);
DCL V_ERROR_FLG BIT(1) INIT(‘0’B);
/ 割り込みハンドラの定義 /
ON FIXEDOVERFLOW
BEGIN;
DISPLAY(‘!!! OVERFLOW OCCURRED !!!’);
V_ERROR_FLG = ‘1’B;
GOTO ERROR_EXIT;
END;
/ 15ビットの上限(32767)を超える演算を実行 /
V_RESULT_15 = V_COUNT_15 + 5000;
DISPLAY(‘CALCULATION FINISHED: ‘ || TRIM(V_RESULT_15));
RETURN;
ERROR_EXIT:
DISPLAY(‘PROGRAM TERMINATED ABNORMALLY DUE TO OVERFLOW’);
/ 必要に応じてダンプ出力やABEND処理を記述 /
END TEST_CALC;
—
4. 現場で生き残るためのテクニック
1. BUILTIN関数の活用:
`FIXED BIN` の演算を行う際は、`BINARYVALUE` や `FIXED` 関数を意識的に使うこと。特に、型が異なる変数同士の演算は、コンパイラが裏で一時的な変換を行う。これが予期せぬオーバーフローの温床となる。
2. VSAMアクセス時のアライメント:
VSAMやフラットファイルを読み込む際、`ALIGNED` 属性と `UNALIGNED` 属性を厳密に使い分けること。`UNALIGNED` を指定するとメモリ効率は上がるが、演算速度がわずかに低下する。しかし、外部インターフェースとの整合性が最優先だ。
3. ONユニットの範囲:
`ON` ユニットは動的にスタックされる。不用意に広範囲で宣言すると、意図しない場所で古いエラーハンドラが呼び出されることがある。`REVERT` 文を使って、必要なブロックを抜ける前に必ずハンドラを解除する習慣をつけるのが、ベテランの作法だ。
最後に
「動いているから大丈夫」という考えは、メインフレームの世界では最も危険な思考だ。
`FIXED BINARY` の精度は、単なるスペックではない。それは君たちが書いたロジックが、何年先も、何億件ものデータに対して「正しくあり続ける」ための約束事だ。
次回のバッチ改修では、`ON FIXEDOVERFLOW` が各モジュールで正しく設定されているか、一度 `grep` して確認してみるといい。きっと、冷や汗をかくような発見があるはずだ。健闘を祈る。
