メニューボタン
IBMi海外記事2019.09.26

標識-新しい基礎知識

Jon Paris 著
トップイメージ図(標識)

標識の歴史は、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;
  • 名前付き定数を配列の添え字として使用して、名前と標識を関連付けることができますます。たとえば、次の例では、標識55をoverCreditLimit_55という名前に関連付けます。
  •     dcl-c  overCreditLimit_55  55;
           
        if *In(overCreditLimit_55);
          //    . . .
        EndIf;
  • 標識に論理式を割り当てることができます。たとえば、次の式は、テストのtrue/falseの結果に応じて標識55をオンまたはオフに設定します。
  •     *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プログラミングの基礎知識に関して、この記事シリーズで取り上げることを希望されるテーマがありましたら、お知らせください。

あわせて読みたい記事

PAGE TOP