【入門編】STREAMファイルにおけるLINESIZEとPAGESIZEの制御と改行コードの扱い – PL/Iの基本構文とデータ制御実践ガイド

こんにちは!メインフレームの世界へようこそ。システムアーキテクトの私です。

JavaやCOBOLの経験がある方なら、基幹システムのバッチ処理で帳票やログを出力する際、画面やプリンタへのレイアウト制御に頭を悩ませた経験が一度はあるはずです。

さて、いざIBMメインフレームの世界に足を踏み入れ、PL/I(ピーエルワン)という言語に出会ったとき、多くのエンジニアが最初の関門で立ち止まります。それが今回取り上げる「STREAM(ストリーム)ファイルにおける `LINESIZE` と `PAGESIZE` の制御、そして改行コードの闇」です。

「COBOLみたいに `LINE ADVANCING` とか書かないのに、どうやって改行を制御しているの?」
「なんか勝手にレコードが途中で切れて次の行に行っちゃうんだけど……!」

大丈夫です。怖がる必要は全くありません。今回は、他言語の常識が少しだけ通用しないPL/Iのユニークな世界を、一緒に優しく紐解いていきましょう。

—

1. まずは心を穏やかに:PL/Iのファイル入出力(STREAM方式)とは?

JavaやC言語でファイルに文字を書き出すときは、明示的に `\n`(改行コード)を埋め込みますよね。COBOLでも、WRITE文で制御コードを意識することが多いでしょう。

しかし、PL/Iの STREAM出力(人間にとって読みやすい形式のストリーム入出力)は、まるでキャンバスに絵を描くように、データを「連続した文字の帯(ストリーム)」として扱います。

ここで登場するのが、ファイル(データセット)の性格を決める属性、`LINESIZE`(1行の長さ)と`PAGESIZE`(1ページの行数)です。これらはコンパイラやOSに対し、「この帳票はこういうフォーマットで出力してね」と伝えるための物理的なガイドラインになります。

家の廊下に例えてみましょう

想像してみてください。あなたは幅が「80センチ」しかない細長い廊下(これが `LINESIZE(80)` です)の壁に、ペンキで文字をずっと書き連ねていきます。
80センチの端まで来たら、ペンキ屋さんはどうするでしょうか? そう、勝手に次の行(次の段)に折り返しますよね。

PL/IのSTREAM出力も全く同じです。プログラム側がいくら長い文字列を `PUT`(出力)しようとも、`LINESIZE` で指定された限界に達した瞬間、システムが強制的に「はい、ここまで!改行ね!」とバツッとレコードを分割してしまうのです。

—

2. 予約語の罠と、コンパイラを悩ませる「キーワードの緩さ」

PL/Iの面白い(そして少し厄介な)特徴に、「文脈依存の予約語」があります。
Javaのように `class` や `public` といった厳格な予約語の壁が非常に低いため、うっかり変数名に使いそうな単語が、実はコンパイラへの指示(オプション)だったりします。

例えば、今回の主役である `LINESIZE` や `PAGESIZE` も、ファイルを開く `OPEN` ステートメントや、ファイル宣言時の `ENVIRONMENT`(ENV)オプションの中で指定します。

1
/ ファイルのOPEN時にLINESIZEを明示的に指定する例 /
OPEN FILE (PRINTER)
TITLE(‘SYSPRINT’)
LINESIZE(132) / 1行の最大長を132文字に設定 /
PAGESIZE(60); / 1ページの最大行数を60行に設定 /

もし、この設定を怠るとどうなるでしょうか?
システムデフォルトのサイズ(大抵は80文字など)が適用され、あなたが意図した美しい132桁のワイドな帳票が、勝手なところでポキポキと折られて出力されてしまうのです。「文字化けした?」「データが欠損した!」と慌てて夜中に飛び起きる原因の多くは、ここ直下にあります。

—

3. 実践!PL/Iコードで見る `LINESIZE` と `PAGESIZE` の挙動

百聞は一見にしかず。実際にどのようなコードで動かすのか、実務の現場を想定したサンプルを見てみましょう。大文字で書かれたレガシーな雰囲気が漂いますが、コメントを丁寧に添えたので安心してください。

1
/ ========================================================== /
/ プログラム名: SAMPLE01 /
/ 概要: STREAM出力におけるLINESIZE/PAGESIZEの制御サンプル /
/ ========================================================== /
SAMPLE01: PROC OPTIONS(MAIN);

/ ファイル(SYSPRINT)の宣言 /
/ STREAM出力、PRINT属性を付与することで改行やページ制御が有効になる /
DCL OUTFILE FILE STREAM OUTPUT PRINT;

/ 出力用ワーク変数 /
DCL W_LINE_DATA CHAR(200);

/ ファイルをオープンし、1行のサイズと1ページの行数を定義する /
/ ここの指定をサボると、デフォルトの狭い幅で強制改行されるので注意! /
OPEN FILE(OUTFILE)
LINESIZE(80) / 1行は80文字まで。これを超えると自動改行 /
PAGESIZE(5); / 1ページはたったの5行!すぐに改ページテストができる /

/ 1行目のデータ出力 /
W_LINE_DATA = ‘これはテスト出力の1行目です。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

/ 2行目のデータ出力 /
W_LINE_DATA = ‘こちらは2行目になります。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

/ 3行目、4行目、5行目と出力していくと… /
W_LINE_DATA = ‘3行目のデータです。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

W_LINE_DATA = ‘4行目のデータです。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

W_LINE_DATA = ‘5行目はページ最後の行です。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

/ PAGESIZE(5)を超えた状態でさらに出力するとどうなるか? /
/ プラットフォーム側の制御で、自動的に「フォームフィード(改ページ)」が挿入される /
W_LINE_DATA = ‘あふれた!これは6行目(次ページの1行目)です。’;
PUT FILE(OUTFILE) EDIT (W_LINE_DATA) (A(80));

/ ファイルをクローズ /
CLOSE FILE(OUTFILE);

RETURN;

END SAMPLE01;

ここがポイント!

上記のコードで `PRINT` 属性という強力な魔法を使っています。
この `PRINT` を指定したSTREAMファイルに対しては、PL/Iのランタイムライブラリがよしなに「改行コード」や「キャリッジコントロール(制御文字)」をレコードの先頭に自動付与してくれます。

JavaやC言語のように開発者が `\n` を文字列の中に意識して差し込む必要はありません。言語のランタイムが「おや、もう80文字だね」「おや、5行に達したから改ページコードを先頭に入れよう」と、裏側で気を利かせてファイルへ書き込んでくれるのです。

—

4. マイグレーションやバッチ改修時の「あるあるトラブル」

他言語からPL/Iの世界に飛び込んだエンジニアが、実務で一番ハマる罠をこっそりシェアしておきますね。

トラブル例:「ローカルPCのテスト環境と、メインフレームの本番で出力結果が違う!」

  • 原因:

コンパイラや実行環境(IBM Enterprise PL/Iなど)のバージョン、あるいはJCL(Job Control Language)側のDD文での `RECFM`(レコード形式)や `LRECL`(論理レコード長)の定義と、プログラム内の `LINESIZE` が食い違っているケースです。

  • 対策:

PL/Iの `LINESIZE` は、あくまで「プログラム側が認識している1行の幅」です。出力先のデータセットが持つ物理的な `LRECL` よりも大きな `LINESIZE` をプログラム内で指定してしまうと、レコードが途中でプツリと切り捨てられるか、JCL側でエラー(ABEND)になります。
「JCLのLRECL = PL/Iの LINESIZE」 これを一致させるのが、レガシーアーキテクトの鉄則です!

—

ペンキの例えを思い出してください。キャンバス(ファイル)の幅を正しく決めてあげれば、PL/Iはとても忠実に、そして美しくデータを並べてくれます。

最初は呪文のように見えるPLのオプション群も、仕様の背景にある「ハードウェアやプリンタ用紙の歴史」を知ることで、ぐっと身近で愛おしいものに変わっていきます。
バッチ改修やマイグレーションの現場でこの知識に直面したときは、「あ、あの時の廊下の話ね」と思い出し、一つずつ設定を確認してみてくださいね。あなたのレガシーシステムの旅を、心から応援しています!

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