【入門編】SUBSTR組み込み関数の左辺値としての利用と内部オフセット計算 – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといった他のモダンな言語や基幹言語の経験がある方にとって、初めてPL/I(ピーエルワン)のコードを見たとき、「なんだか独特な書き方だな…」と少し身構えてしまうかもしれませんよね。

特に、PL/IにはC言語のような厳密な「予約語(キーワード)」の概念が薄く、`IF`や`READ`といった命令ですさえ、文脈によってはただの「変数名」として使えてしまうという、懐の深さ(あるいはカオスさ)を持っています。初めて知ったときは「コンパイラはどうやって判別してるの!?」と冷や汗をかいたものです。

でも、安心してください。一つずつ紐解いていけば、PL/Iは非常に論理的で、ハードウェアの動きに忠実な美しい言語です。

今回は、そんなPL/Iの数あるユニークな機能の中でも、レガシーシステムのバッチ改修やデータ移行の現場でひそかに(そして強力に)活躍する、「SUBSTR組み込み関数の左辺値利用と、その裏側で行われるメモリの秘密」について、優しく丁寧に解説していきますね。

1. 他言語からの挑戦者たちが驚く、PL/Iの柔軟すぎる命名規則

JavaやCOBOLでは、`IF`や`SELECT`といった言語仕様上の重要なキーワードは「予約語」とされ、変数名として使うことはご法度ですよね。

しかし、PL/Iの世界では、キーワードは「コンテキスト(文脈)依存」です。例えば、以下のようなコードを書くことも理論上は可能です(良い子は真似しないでくださいね)。

1
IF = 10; / “IF”という名前の変数に10を代入している…? /

コンパイラは、前後の文脈から「あ、ここでは条件分岐のIFじゃなくて、変数としてのIFだな」と空気を読んで解釈します。この柔軟性ゆえに、古いメインフレームのプログラムを解析していると、思わず頭を抱えたくなるようなトリッキーな変数名に出会うことがありますが、それもまたレガシーシステムの醍醐味(?)です。

そんな懐の深いPL/Iにおいて、文字(文字列)を自在に切り貼りするための代表格が `SUBSTR`(サブストリング)組み込み関数 です。

2. SUBSTR関数って、右側(値)に置くだけじゃないの?

文字列の一部を切り出すとき、みなさんはどのように書きますか?
Javaの `substring()` や、COBOLの `MOVE WS-FULL(1:5) TO WS-PART` のようなイメージを持っていると、次のようなコードを見たときにきっと二度見することでしょう。

1
/ 住所データの中から、市町村名の一部を直接書き換える例 /
SUBSTR(CUSTOMER_ADDRESS, 10, 5) = ‘中央区’;

なんと、`SUBSTR`関数が代入文の「左辺」にいるのです!

「えっ、関数に戻り値を代入するなんてできるの?」
「C言語のポインタ操作みたいで難しそう…」

そう思われるのも無理はありません。JavaやCOBOLに慣れ親しんだ方ほど、この書き方は魔法のように見えるはずです。でも大丈夫。裏側の仕組みを知れば、怖さはスッと消えていきますよ。

3. メモリの「どこを・どう書き換えるか」の正体

この `SUBSTR(CUSTOMER_ADDRESS, 10, 5) = ‘中央区’;` というコードが実行されるとき、コンピュータのメモリ(ストレージ)上では何が起きているのでしょうか?

イメージしてみてください。
メインフレームのメモリ上には、`CUSTOMER_ADDRESS` という名前の箱が、例えば「50バイト分の連続した領域」としてガッチリ確保されています。

COBOLであれば、領域の一部を書き換えるために、わざわざワークエリアを用意して再定義(REDEFINES)したり、部分参照を駆使したりと、少し手数が要りますよね。

しかしPL/Iの `SUBSTR` を左辺に置いた場合、コンパイラは次のようなスマートな仕事を裏で行ってくれます。

1. オフセットの計算: 変数 `CUSTOMER_ADDRESS` の先頭アドレスを基準にして、「開始位置(10バイト目)」がどこにあるかをズレ(オフセット)として瞬時に計算します。
2. 長さの特定: そこから「何バイト分(5バイト)」を対象にするかを確定します。
3. 直接上書き(ダイレクト・ポインティング): 新たな値(’中央区’)を、メモリ上のそのピンポイントの場所に直接流し込みます。

つまり、変数全体を一旦別のものに作り直すのではなく、「メモリの特定の部屋の、特定の引き出しだけをパカッと開けて中身を入れ替える」ようなダイナミックな処理を、たった1行で安全に行っているのです。

4. コンパイラが裏で用意する「記述子(Descriptor)」の働き

ここで、少しだけアーキテクトらしいディープな話をさせてください。

PL/Iがなぜこのような柔軟な文字列操作を効率よく行えるかというと、コンパイラが変数と一緒に「記述子(Descriptor)」という隠れたメタデータ(情報の情報)を管理しているからです。

PL/Iの文字列型(`CHARACTER`型)には、主に以下の2種類があります。

  • VARYING属性: 文字列の実際の長さが変動するタイプ(C言語の動的文字列やJavaのStringに近い)
  • NON-VARYING属性: 宣言された長さが固定のタイプ(COBOLの固定長項目に近い)

`SUBSTR` を左辺に使うとき、コンパイラは対象となる変数が固定長なのか可変長なのか、現在の長さはいくつなのかを記述子から即座に読み取り、メモリのアドレス計算を最適化しています。

実務のマイグレーションやバッチ改修でこの記述子を意識するシーンは多くありませんが、「PL/Iのコンパイラは、私たちが書いた簡潔なコードの裏で、メモリの番人として緻密なアドレス計算をしてくれているんだな」と想像できるようになると、コードを読む視点がグッと深まります。

5. 実務で役立つ!安全なSUBSTR左辺値利用のサンプルコード

それでは、実際に動かすことができるPL/Iのサンプルコードを見てみましょう。
電文や固定長ファイル(フラットファイル)の電文レイアウトをゴニョゴニョと加工する、メインフレーム現場ではおなじみのパターンです。

1
——————————————————————

  • プログラム名: CUSTMOD
  • 概要: 顧客マスターの固定長レコードの一部をSUBSTR左辺値で更新する

——————————————————————
CUSTMOD: PROC OPTIONS(MAIN);

/ 80バイトの固定長レコード領域を宣言 /
DCL MASTER_RECORD CHARACTER(80) INIT(‘ ‘);

/ 作業用のフラグ /
DCL 1 W_WORK_AREA,
5 W_ERR_FLG CHARACTER(1) INIT(‘0’);

—————————————————————-
— 1. テスト用に初期データをセットする(本来はファイルから読み込む)
—————————————————————-
MASTER_RECORD = ‘00123山田 太郎 東京都千代田区1-1 ‘;

—————————————————————-
— 2. SUBSTRを左辺に使って、名前の後ろのスペース部分をピンポイント修正
—————————————————————-
/ 氏名フィールド(6文字目から15バイト)を「山田 次郎」に上書き /
SUBSTR(MASTER_RECORD, 6, 15) = ‘山田 次郎 ‘;

—————————————————————-
— 3. 住所の番地部分(50文字目から5バイト)を書き換える
—————————————————————-
SUBSTR(MASTER_RECORD, 50, 5) = ‘2-2-2’;

—————————————————————-
— 4. 結果を出力する
—————————————————————-
PUT SKIP LIST(‘更新結果レコード: ‘ || MASTER_RECORD);

END CUSTMOD;

このコードのポイント

  • `MASTER_RECORD` という一つの長い文字列(80バイト)に対し、`SUBSTR` を左辺に使うことで、不要な文字列結合や複雑な切り出し処理を書くことなく、ダイレクトに特定の位置を書き換えています。
  • コボラーの皆さんならお馴染みの「レコードレイアウトの一部分だけパッチを当てる」ような処理が、PL/Iでは非常にエレガントに記述できることがお分かりいただけると思います。

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

初めてPL/Iの `SUBSTR` の左辺値利用を見たときは、「なんて直感に反する書き方なんだろう」と驚いたかもしれません。しかし、その裏側にあるのは「限られたメモリ領域をいかに効率よく、無駄なオーバーヘッドなしに操作するか」という、メインフレーム全盛期からのエンジニアたちの知恵と工夫の結晶です。

「予約語がない」「関数を左辺に置く」といった一見奇妙に見える仕様も、仕組みを一つずつ紐解いていけば、どれも理にかなった合理的なルールであることが分かります。

レガシーシステムの移行や改修は、一見すると黒魔術のように思えるかもしれませんが、怖がる必要はまったくありません。いつでも足元を固めて、一歩ずつコードと対話していけば、必ず味方になってくれます。

あなたのメインフレーム・ライフが、少しでも楽しく、自信に満ちたものになりますように。それではまた次回の技術解説でお会いしましょう!

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