【入門編】データ例外(S0C7)と固定小数点データ – PL/Iの基本構文とデータ制御実践ガイド

みなさん、こんにちは!IBMメインフレームの世界へようこそ。そして、レガシーシステムの心臓部であるPL/I(ピーエルワン)の学習、本当にお疲れ様です。

JavaやCOBOLといったモダン、あるいは少し先輩にあたる言語をバリバリ書いてきた方にとって、メインフレームの世界は、ときにおどろおどろしい「呪文」と「厳格すぎるルール」の連続に見えるかもしれません。特に、夜間バッチのログに突如として現れるあの恐怖の文字……「ABEND S0C7」。

画面の向こうで「うわ、またS0C7だ……今日はもう帰れないのか……」と冷や汗をかいた経験はありませんか?

でも、安心してくださいね。S0C7は決して正体の分からないモンスターではありません。その正体を知り、PL/Iがメモリ上でデータをどう扱っているのかさえ分かってしまえば、怖がる必要はまったくありません。今回は、固定小数点数(特にDECIMAL)とS0C7の切っても切れない関係について、一緒に優しく紐解いていきましょう!

—

1. JavaやCOBOLの感覚で挑むとハマる? PL/Iの「固定小数点数」の正体

Javaの `int` や `BigDecimal`、あるいはCOBOLの `PIC 9(5) COMP` などに慣れ親しんだ方にとって、PL/Iの数値データ定義は少し奇妙に映るかもしれません。

PL/Iでよく使われる固定小数点数には、主に以下の2つがあります。

  • FIXED BINARY(固定小数点二進数): コンピュータが一番大好きな「2進数」の世界。
  • FIXED DECIMAL(固定小数点十進数): 私たちが普段使う「10進数」を、メモリ上にそのまま詰め込む世界。

今回特に注目したいのは、後者の `FIXED DECIMAL`(パック10進数) です。

パック10進数ってなぁに?(コンビニのレシートの例え)

Javaの数値は、メモリ上で綺麗に32ビットや64ビットの塊として管理されます。しかし、メインフレームの起源である商用計算の世界では、「人間が読む10進数の桁数をそのまま正確に保ちたい!誤差なんて絶対に許されない!」という強いこだわりがありました。

そこで生まれたのがパック10進数(Packed Decimal)です。
イメージとしては、「1つのバイト(8ビット)を半分こ(4ビットずつ)にして、そこに0から9までの数字を2文字ギュッと詰め込む」という、お弁当箱のような仕組みです。

例えば、`DECLARE WS_AMT FIXED DECIMAL(5, 2);` という変数を宣言したとします。
これは「全体で5桁、そのうち小数点以下が2桁」という意味ですが、メモリ上では以下のように格納されます。

  • 1バイトに2桁の数字が入り、最後の半バイト(下位4ビット)には「符号(プラスかマイナスか)」を表すゾーン(C, D, Fなど)が入ります。

この「隙間なく綺麗に数字がパッキングされている」という点が、実は諸刃の剣なのです。

—

2. 恐ろしい「S0C7(データ例外)」はどうして起きるのか?

さて、本題の ABEND S0C7(System Completion Code 0C7:データ例外 / Data Exception) についてです。

CPUが計算をしようと、「よし、このメモリの場所にあるデータをパック10進数として計算するぞ!」と命令を実行したとき、そこに書かれていたデータが……

  • 文字コードのスペース(X’40’)だった!
  • うっかり混入した英字の「A」(X’C1’)だった!
  • ゾーン10進数(UNPACKED)のデータがそのまま紛れ込んでいた!

こんなふうに、「パックされているはずの場所に、正しい数字や符号以外のゴミ(不正な文字)が入っていた」とき、メインフレームのCPUは「ひゃあ!計算できないよ!」とパニックを起こして強制終了します。これがS0C7の正体です。

Javaで言えば `NumberFormatException` のようなものですが、メインフレームの場合は例外をキャッチし損ねると、バッチジョブ全体がその場で無慈悲にアベンド(異常終了)します。

—

3. 実践!PL/Iでのデータ定義と、不穏なコードの挙動

百聞は一見にしかず。実際にPL/Iでどのようにデータが扱われ、どういうシチュエーションで危ういのか、簡単なサンプルコードを見てみましょう。

—————————————————————-

  • PL/I サンプルプログラム:固定小数点数とデータ移動

—————————————————————-
S0C7_SAMPLE: PROC OPTIONS(MAIN);

/ 厳密な固定小数点十進数(パック10進数)の宣言 /
DCL WK_PRICE FIXED DECIMAL(7,2) INIT(0);
DCL WK_TAX FIXED DECIMAL(5,2) INIT(1.08);
DCL WK_TOTAL FIXED DECIMAL(9,2) INIT(0);

/ 外部から受け取った文字データ(空白やゴミが入る可能性がある) /
DCL RAW_INPUT CHAR(7) INIT(‘ ‘);

/ — シナリオ1:安全な計算 — /
WK_PRICE = 1234.56; 数値として正しく代入
WK_TOTAL = WK_PRICE WK_TAX;

PUT SKIP LIST (‘正常終了時の計算結果: ‘, WK_TOTAL);

/ — シナリオ2:危険な香り(S0C7の足音) — /

  • 外部ファイルから読み込んだつもりのRAW_INPUTが、
  • まだスペース(空白=’40’x)のままだとする。

/ 文字項目から数値項目への強引な代入(アンコンバート移動) /

  • ⚠️ここでPL/Iの暗黙の型変換が意図せず働くと危険!

WK_PRICE = RAW_INPUT;

/ この状態で計算をさせようとすると……ここで「ドカン!」(S0C7) /
WK_TOTAL = WK_PRICE WK_TAX;

END S0C7_SAMPLE;

ここがポイント!

PL/Iは非常に賢い言語(あるいは、お節介な言語)なので、異なるデータ型の間でもよしなに変換(代入)を行ってくれます。しかし、ファイルから読み込んだパディングされていない空白文字(CHAR型)を、そのまま `FIXED DECIMAL` に突っ込もうとすると、コンパイラや実行時は「文字を数値に直さなきゃ」と頑張りますが、中身がスペースでは変換しきれず、メモリ上には「不正なパックデータ」が生成されてしまいます。

そして、その不正なデータをCPUが演算器にロードした瞬間、S0C7 が炸裂するのです。

—

4. 現場で役立つ!S0C7を回避・解析するためのアプローチ

もし、あなたが保守現場で「S0C7が発生した!」というアラートを受け取ったら、どう動くべきでしょうか。プロとしてのスマートな解決ステップを授けましょう。

① SYSUDUMP または CEEDUMP を採取する

メインフレームの鉄則です。アベンドした瞬間のメモリダンプ(ストレージダンプ)を必ず採取してください。
ダンプの中に、どの変数が、どの命令(PSWアドレス)の実行時に不正な値を持っていたのかが、赤裸々に記録されています。

② 入力インターフェースを疑う(GURUN / 汚染データ)

S0C7の原因の9割は「外部から入ってきたデータの汚れ」です。

  • 前システムの移行時にブランクが混ざった
  • 画面からの入力チェックが漏れていて、半角スペースや特殊文字がDBやファイルに保存されてしまった

PL/I側で受け取る前に、「数値項目に置き換える前に、本当に数字だけが入っているか?」をチェックすることが最大の防御になります。

③ PL/Iのビルトイン関数(組み込み関数)を活用する

PL/Iには、データが数値として正しいかを判定する便利な関数や、安全に変換する仕組みがあります。例えば、`VALID`関数(処理系の仕様によりますが)や、文字から数値への変換時にエラーをトラップするオンユニット(ON-Unit)の活用です。

  • オン・ユニット(例外処理)の例

ON CONVERSION BEGIN;
PUT SKIP LIST (‘警告: 数値に変換できない不正なデータが検知されました!’);
WK_PRICE = 0; ゼロで安全にバイパスする等のリカバリ
END;

このように、PL/I伝統の `ON-Unit` を使えば、万が一不正なデータが来ても、プログラムがいきなりアベンドするのを防ぎ、優しくキャッチしてログに残すことができます。

—

おわりに:レガシーの仕様は、怖くない

Javaの例外処理に慣れていると、メインフレームのS0C7は「システム全体を巻き込む暴君」のように見えるかもしれません。
しかし、それはCPUが「おい、データが壊れていてこれ以上嘘の計算をしたくないから、ここで止まって安全性を守るよ!」と教えてくれているサインでもあります。

PL/Iの `FIXED DECIMAL` がメモリ上でどう並んでいるか、文字と数字の境界線で何が起きているのか。そのイメージさえ掴めば、S0C7は怖くありません。むしろ、「おっ、ここにゴミが混ざっているな」とピンセットで的確に取り除ける、名医のようなシステムアーキテクトに一歩近づけた証拠です。

ぜひ、恐れずにコードとメモリの対話を楽しんでくださいね。あなたのレガシーライフ、そしてマイグレーションの成功を心から応援しています!

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