標識-新しい基礎知識
標識の歴史は、RPGの最も初期のバージョンより前どころか、はるか昔のタビュレーティング マシンの時代まで遡ります。定義のしかたによっては、さらに昔ということにもなるかもしれません。しかし、紛れのない事実は、*INnnや*INLRという意味の標識は、昔のタビュレーター ボード プログラムを翻訳する手段としてRPG言語に追加されたということです。
そうした初期の時代以降、RPGは大きく成長してきましたが、今でも多くの人々が旧式の番号付き標識を使用してコードを書いています。LRはどうでしょうか。ともあれ、何だか逃れられなくなっているような気もしてしまうのですが、RPGプログラムで番号付き標識を使用する必要性がなくなってから、実はかなりの年月が経っているのです。実際、名前付き標識がこの言語に初めて導入されたのはV4R2です。もちろん、プログラム記述レポート ファイルを使用する場合は、O-仕様書で番号付き標識を使用するしかありませんが、演算では選ぶことができます。
2012年に、この記事のオリジナル バージョンを記して以降、RPGは完全なフリーフォーム データ宣言の導入という、大きな変化を経験しています。「Classic」シリーズとして改訂する記事を選ぶ際、そのことがこの記事を選ぶ決め手となりました。
以前、「An Indicator By Any Other Name」という記事で、標識に関するいくつかの基礎知識について記しました。おさらいの意味で、ぜひともその記事を確認してみてください。本記事では、その記事では扱わなかった点を取り上げます。
- 標識は配列として扱うことができます。つまり、*In55と*In(55)は同じ標識を参照します。
- コンパイラーは、標識(名前付きまたはそれ以外も)がブール式であり、それ自体をテストできることを認識します。たとえば、以下の例はどちらも、標識55の使い方として完全に有効です。
If *In(55);
// . . .
Endif;
If Not *In55;
// . . .
EndIf;
dcl-c overCreditLimit_55 55;
if *In(overCreditLimit_55);
// . . .
EndIf;
*In(overCreditLimit) =
( orderTotal + currentBalance ) > creditLimit;
次のステップへ進む
標識*In01-*In99は、メモリー内の一連のバイト、連続バイトであるに過ぎません。そのため、99個(または使用している数だけ)の標識すべてに名前を付けたい場合は、標識配列を、自分で設計したデータ構造にマッピングすることで、それを行うことができます。次のコード例に、基本的な考え方が示されています。ポインターが気になるかもしれませんが、心配は要りません。このように使用すれば、ポインターについて何も行う必要はありません。コンパイラーがすべての処理を行ってくれます。例を示します。
dcl-s pIndicators Pointer Inz(%Addr(*In));
dcl-ds indicators Based(pIndicators);
newPage_01 ind Pos(1)
endOfFile_02 ind Pos(2);
//
errorFlags char(3) Pos(55);
overCreditLimit_55 ind Pos(55);
invalidCustomer_56 ind Pos(56);
badPartNumber_57 ind Pos(57);
end-ds;
最初にポインターを定義し、次に標識データ構造を定義したことに注目してください。このようにすれば、/Copyメンバーに基本セットアップを組み込んでから(必要な場合)、アプリケーション固有の定義をデータ構造に追加するということが簡単に行えるようになります。
次の例もフィールド(errorFlags)を定義しますが、これにより、一群のエラー標識を非常に簡単にオンまたはオンに切り替えることができます。
errorFlags = *Off;
この目的でMOVEAを使用する古い手法は使ったことがありませんが、こうする方がはるかに良いと思います。同じような手法を、サブファイルの標識で使用することができます。サブファイルを表示または消去するには、特定のオン/オフの組み合わせが必要です。このケースでは、適切な「0」および「1」のパターンを持つ名前付き定数を使用して、必要な設定を実現します。以下に例を示します。
dcl-ds DisplayIndicators Based(pIndicators);
// Input request indicators
exit_3 ind Pos(3);
sortPrCode_5 ind Pos(5);
sortDesc_6 ind Pos(6);
// Output control indicators
sflControls_90_92 char(3) Pos(90);
// Individual indicators shown for reference - not used in code
sflDspCtl_90 ind Pos(90);
sflClear_91 ind Pos(91);
sflDsp_92 ind Pos(92);
end-ds;
// Constants to set subfile operations
dcl-c clearSfl '010';
dcl-c displaySfl '101';
このようにしてから、標識をセットアップしてサブファイルを消去または表示できるようにすれば、あとは1行コーディングするだけです。MOVEAとは異なり、非常に分かりやすいのではないでしょうか。たとえば、
sflControls_90_92 = ClearSfl;
sflControls_90_92 = DisplaySfl;
実のところ、私が標識に古い文字スタイルの表現を使用するのはこのケースくらいです。
INDDS: 標識に名前を付けるための組み込みの手法
V4R2の頃、標識名はDDSで直接サポートされていなかったため、RPGコンパイラー チームは、RPG独自の実装を考え出す必要があると考えました。そうして生まれたのがINDDSです。INDDSはINDicator Data Structure(標識データ構造)の略であり、標識に名前付きデータ構造を使用するファイルのF-仕様書に追加するだけです。INDDSについては、注目すべき重要なポイントがいくつかあります:。
- ファイルにINDDSを使用すると、そのファイルによって使用される標識と標準の*INシリーズとの間の関連はなくなります。デバイスは指定されたデータ構造で定義された標識のみを使用します。
- ファイルごとに固有のデータ構造を指定することができます。また、1つのデータ構造を複数のファイルで共有することもできます。
- INDDSは、INDARA(Indicator Area:標識域)キーワードで定義されるファイルにのみ指定できます。何年かすればこの制限がなくなると思っていましたが、あまり期待しなかったのは幸いです。
- このキーワードを何の問題もなく使用できるように、表示装置ファイルを変更することができます。ただし、INDARAファイルでは、レコード フォーマットのCLEARまたはRESETは、標識に影響するのではなく、データ フィールドのみに影響することに留意してください。
- INDDSキーワードによって識別される標識配列の長さは、常に99バイトです。POSキーワードを使用すると、簡単に標識番号を名前にマッピングできます。
それでは、シンプルな表示装置ファイルを見てみましょう。前の例で使用した同じエラー標識が使用されています。ファイル宣言と標識データ構造は、次のようにしてコーディングされます。
dcl-f DispFile WORKSTN(*EXT) USAGE(*INPUT:*OUTPUT)
INDDS(dispIndicators);
dcl-ds dispIndicators;
//
errorFlags char(3) Pos(55);
overCreditLimit_55 ind Pos(55);
invalidCustomer_56 ind Pos(56);
badPartNumber_57 ind Pos(57);
end-ds;
これは、標識を処理する手法として、一番すっきりしたやり方だと私には思えます。また、通常の標識の99までの制限が邪魔な場合に非常に有用です。たとえば、複数のファイルで標識のいくつかを共有する必要があるとします。けれども、99個を超える標識を使用できるようにするために、同じデータ構造をファイルに共有させたくないとします。そのような場合は、EVAL-CORR(Evaluate Corresponding)を使用すると、かなりうまく処理できます。
たとえば、表示装置ファイル データ構造の関連部分を複製し、新しいデータ構造定義にQUALIFIEDキーワードを追加するだけです。次いで、マッチしている標識の状態を一方のデータ構造から他方のデータ構造へコピーするのであれば、EVAL-CORRを使用してそれらを適切な方向にコピーするだけです。
次の例では、この手法と、よりシンプルなオプションの両方が示されています。後者は、表示装置ファイル エラー標識と、O-仕様書によって印刷のために使用される標識が、1つのフィールドにグループ化されることを利用しています。
dcl-ds printIndicators Qualified Based(pIndicators);
// Print specific indicators
newPage_01 ind Pos(1);
endOfFile_02 ind Pos(2);
// indicators common with display file
errorFlags char(3) Pos(55);
overCreditLimit_55 ind Pos(55);
invalidCustomer_56 ind Pos(56);
badPartNumber_57 ind Pos(57);
end-ds;
// Copy all common indicators from display file to print
Eval_Corr printIndicators = dispIndicators;
// Or just set print indicators from display file settings
printIndicators.errorFlags = errorFlags;
個々の標識の名前を変えないことが重要です。変更してしまうと機能しません。この命令コードの「corresponding」の部分の意味は、そういうことです。コピーされるのは、名前がマッチしていて、データ型が適合するフィールドのみです。
この記事が、最新の標識の使用法についての理解をアップデートするのに役立つことができたのだとすれば幸いです。モダンRPGプログラミングの基礎知識に関して、この記事シリーズで取り上げることを希望されるテーマがありましたら、お知らせください。