【テクニカル・上級編】CHARACTER VARYING型の内部構造と長さ制御 – PL/Iの基本構文とデータ制御実践ガイド

鉄壁のメインフレームを支えるPL/I:VARYING文字列と「2バイトの罠」を解き明かす

メインフレームの現場で何十年と生き抜いてきた諸君なら、一度は目にしたことがあるはずだ。S0C4やS0C7のダンプを抱えて夜中に頭を抱えるあの瞬間、実はその背後で「PL/Iの可変長文字列」が牙を剥いていた……という事態を。

今日は、JavaやC#へのマイグレーションを控えたアーキテクト諸君、あるいは今まさにCOBOLとPL/Iが混在する巨大なバッチシステムを保守している猛者たちに向けて、PL/Iの`CHARACTER VARYING`の深淵に触れていこう。

1. VARYING型の構造:2バイトの「小さな支配者」

PL/Iの`CHARACTER(n) VARYING`は、一見すると扱いやすい現代的な文字列型に見える。だが、その内部構造を理解せずして、ポインタ操作や外部インターフェースとの連携を語ることはできない。

この型は、宣言した最大長(n)に加えて、先頭の2バイトに「現在保持している実データの長さ」を格納するハーフワード(FIXED BIN(15))を持っている。つまり、`DCL STR CHAR(10) VARYING;` と宣言した瞬間、メモリ上には合計12バイトの領域が確保されるわけだ。

なぜこれが「移行」で鬼門になるのか

Javaの`String`やC#の`string`は、これらとは全く異なるメモリ管理を行う。特に、JNI経由でデータを渡す際や、VSAMファイルを読み込む際に、この「先頭2バイトの長さ情報」を正しくハンドリングしていないと、データがオフセットして読み込まれ、文字化けや致命的なアベンドを誘発する。

2. SUBSTR関数の裏側とポインタの危うい関係

PL/Iの`SUBSTR`は万能だが、VARYING型に対して行う際は注意が必要だ。

/i
DCL STR CHAR(20) VARYING INIT(‘MAINFRAME’);
DCL PTR PTR;
DCL 1 STR_STRUCT BASED(PTR),
2 LEN FIXED BIN(15),
2 DATA CHAR(20);

/ アドレッシングによる直接操作の例 /
PTR = ADDR(STR);
/ 慎重に扱わないと長さ情報(LEN)を破壊するリスクがある /
SUBSTR(STR_STRUCT.DATA, 1, 3) = ‘IBM’;

このように、ベース変数(BASED変数)を使って直接メモリを操作する際、うっかり`LEN`を更新し忘れるとどうなるか。コンパイラは何も文句を言わない。しかし、その後の処理で`PUT LIST(STR);`を実行した瞬間、メモリ上のゴミがそのまま出力されるか、あるいは境界外アクセスでS0C4が飛んでくる。

3. アベンド解析の現場:ダンプから読み解く「真実」

もし諸君がABENDダンプを眺めることになったら、まず確認すべきはレジスタに格納されたアドレスと、VARYING変数の先頭2バイトだ。

  • パックデシマルとの混在: かつてあった事例だが、外部から受け取ったパックデシマル(COMP-3)の符号(通常は0x0Cや0x0D)を、PL/Iの可変長文字列として誤解釈して読み込み、長さ情報部分に0x000Cが入ってしまったケースがある。これに気づかず`SUBSTR`をかけようとすれば、当然ながらシステムは異常終了する。
  • ダンプの読み方: ダンプリスト上で該当アドレスの最初の2バイトが`00 05`であれば、その文字列の長さは「5」だ。それ以降のバイト列が期待値と合致しているか、16進ダンプを指で追いかける根気強さが、アーキテクトには求められる。

4. マイグレーションを成功させる「守り」の設計

JavaやC#への移行を行う際、最も避けるべきは「PL/Iの挙動を安易にエミュレートしようとすること」だ。

1. データ構造の正規化: `VARYING`の先頭2バイトをそのまま保持するクラスを作るのではなく、マイグレーション先では「長さ情報」と「バッファ」を明確に分離したオブジェクトモデルを再設計すべきだ。
2. DB2連携のエッジケース: `VARCHAR`型のカラムをPL/Iで受け取る際、indicator変数(標識変数)の存在を忘れてはならない。PL/I側で`CHARACTER VARYING`として受け取るのか、それともポインタ越しにSQLCAを解析するのか。この設計判断が、移行後のバッチ処理の堅牢性を左右する。

結び:技術の継承という責務

PL/Iは、C言語のような自由度と、COBOLのような堅牢なビジネスロジック処理を併せ持つ、実に「大人」の言語だ。その仕様の隅々には、IBMの先人たちが何十年もかけて蓄積してきた最適化の知恵が詰まっている。

「古い言語だから」と切り捨てるのは簡単だ。だが、その内部構造を理解し、現代の言語体系へ正しく翻訳することこそが、我々システムアーキテクトに課せられた使命ではないだろうか。

次に諸君がダンプと向き合うとき、この「2バイトの存在」が、諸君のデバッグを少しでも楽にしてくれることを願っている。何か特定のコンパイラオプション(`OPT(3)`など)による最適化の罠について深掘りしたい場合は、またいつでも聞いてくれ。現場の知見は、マニュアルの行間にあるものだ。

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