第5章  DSPFも使えるの?
RPGプログラマーの為のC言語講座

DSPFをILE−Cで利用する場合には、ILE−Cの拡張関数群(_Rxxxxx)を使う必要があります。

次の関数が、ヘッダーファイル <recio.h> で定義されています。

    _Racquire           _Rclose            _Rcommit          _Rdelete
    _Rdevatr            _Rfeod             _Rfeov            _Rformat
    _Rindara            _Riofbk            _Rlocate          _Ropen
    _Ropnfbk            _Rpgmdev           _Rreadd           _Rreadf
    _Rreadindv          _Rreadk            _Rreadl           _Rreadn
    _Rreadnc            _Rreadp            _Rreads           _Rrelease
    _Rrlslck            _Rrollbck          _Rupdate          _Rupfb
    _Rwrite             _Rwrited           _Rwriterd         _Rwrread
    

RPGでは、F仕様書にWORKSTNファイルが定義してあれば、プログラムでは[ EXFMT SC01 ]の様に、いきなり画面のレコード様式を指定するだけでDSPFのI/Oが可能になります

Cを使う場合は、同じことを行うのに、もう少し面倒な手続きが必要になります。

    ファイルのオープン/クローズ

    表示するレコード様式の設定

    ZONE10進数とインテジャーの変換

などが追加で必要です。

まず、サンプルのRPGをみてください

     H            Y/                                    1               
     H*------------------------------------------------------------*    
     H* PROGRAM-ID    :    DSP1R                                   *    
     H* REMARKS       :    画面ファイルのプログラム              *    
     H* AUTHOR        :    Y.IDE                                   *    
     H* DATE-WRITEN   :    98/09/23                                *    
     H* VERSION       :    01.00 ORIGINAL                          *    
     H*------------------------------------------------------------*
     FDSP1FM  CF  E                    WORKSTN                          
     C                     Z-ADD1234567   DPBOTH                        
     C                     Z-ADD1234567   DPOUT                         
     C* 画面に表示                                                      
     C                     EXFMTSC01                                    
     C*                                                                 
     C                     SETON                     LR                 
     C                     RETRN                                       

[プログラムの解説]

画面ファイルにデータをセットして画面表示を行います。何らかの入力があるとプログラムは終了します。

使用しているDSPFのソースコード

     A                                      DSPSIZ(24 80 *DS3)
     A                                      CF03(03)
     A          R SC01
     A                                  4 16'数字'
     A                                  4 37'文字'
     A                                  6  5'INPUT :'
     A            DPIN           7Y 0I  6 14
     A            DPINA         20A  I  6 31
     A                                  8  5'OUTPUT :'
     A            DPOUT          7S 0O  8 14
     A            DPOUTA        20A  O  8 31
     A                                 10  5'BOTH :'
     A            DPBOTH         7Y 0B 10 14
     A            DPBTHA        20A  B 10 31

同じ処理をするプログラムCで作成しましょう。

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : DSP1C                                          */
/* REMARKS     :ディスプレイファイルI/O      
/* AUTHOR      : Y.Ide                                          */
/* DATE-WRITEN : 98/08/31                                       */
/* VERSION     : 01.00 ORIGINAL                                 */
/*--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

#pragma mapinc("SC01","CLAB/DSP1FM(*ALL)","both"," ","DSP","FM")
#include "SC01"

int main(void)
{
  _RFILE                            *dspf;
  _RIOFB_T                          *fb; 
  DSP_t                             sc01;
  int num = 1234567;

    if (( dspf = _Ropen("DSP1FM", "ar+" )) == NULL )
    {
        printf ("OPEN ERROR\n" );
        exit ( 1 );
    }
/*カウントアップと設定*/
    QXXITOZ(sc01.FM_SC01_o.DPOUT,  7, 0, num);
    QXXITOZ(sc01.FM_SC01_o.DPBOTH, 7, 0, num);
    memset(sc01.FM_SC01_o.DPOUTA,'X',20);
    memset(sc01.FM_SC01_o.DPBTHA,'X',20);

/*レコード様式を設定する*/
    _Rformat(dspf,"SC01" );

/* EXFMTに同じ*/
    fb = _Rwriterd(dspf, &sc01, sizeof(sc01) );

  _Rclose (dspf);
}

[プログラムの解説]

_Rformat(dspf,"SC01");の命令で、画面ファイルのレコード様式を設定してから、
_Rwriterd(dspf,&sc01,sizeof(sc01) );で画面の入出力を行っています。

画面様式の指定は、RPGでは不要の命令ですが、内部的には、レコード様式の選択が自動的に行われています。

RPG2(S/36など)では、O仕様書の最初にレコード様式名のコーディングをしていました。
たしかこんな感じだったと思います。

    O K4 "SC01"

次にサブファイルを使った例をみてみましょう

     H            Y/                                    1
     H*------------------------------------------------------------*
     H* PROGRAM-ID    :    SUB1R                                   *
     H* REMARKS       :   サブファイルのプログラム
     H* AUTHOR        :    Y.IDE                                   *
     H* DATE-WRITEN   :    98/09/22                                *
     H* VERSION       :    01.00 ORIGINAL                          *
     H*------------------------------------------------------------*
     FSUB1FM  CF  E                    WORKSTN
     F                                        RRN   KSFILE SC01
     C*サブファイルのクリア
     C                     SETON                     31
     C                     WRITESC01C
     C                     SETOF                     31
     C* 18レコードを出力
     C           1         DO   18        RRN     30
     C                     Z-ADDRRN       DPSEQ
     C                     Z-ADD1234567   DPBOTH
     C                     Z-ADD1234567   DPOUT
     C                     MOVE *ALL'X'   DPBTHA
     C                     MOVE *ALL'X'   DPOUTA
     C                     WRITESC01
     C                     ENDDO
     C*画面に表示
     C                     EXFMTSC01C
     C*
     C                     SETON                     LR
     C                     RETRN

[プログラムの解説]

サブファイルをクリアし、サブファイルにレコードを18件書き込み、画面表示を行います。何らかの入力があるとプログラムは終了します。

使用しているサブファイルのソースコード

DSPF SUB1FM

     A                                      DSPSIZ(24 80 *DS3)
     A                                      CF03(03)
     A          R SC01                      SFL
     A            DPSEQ          2  0O  5  4
     A            DPIN           7Y 0I  6  8
     A            DPBOTH         7Y 0B  6 32
     A            DPOUT          7S 0O  6 56
     A            DPINA         20A  I  7  8
     A            DPBTHA        20A  B  7 32
     A            DPOUTA        20A  O  7 56
     A          R SC01C                     SFLCTL(SC01)
     A                                      SFLDSP
     A                                      SFLDSPCTL
     A  30                                  SFLINZ
     A  31                                  SFLCLR
     A                                      SFLSIZ(0018)
     A                                      SFLPAG(0006)

同じ処理をするCプログラムを作成しましょう。

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : SUB1C                                          */
/* REMARKS     :サブファイルI/O
/* AUTHOR      : Y.Ide                                          */
/* DATE-WRITEN : 98/09/23                                       */
/* VERSION     : 01.00 ORIGINAL                                 */
/*--------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

#pragma mapinc("SC01","CLAB/SUB1FM(*ALL)","both"," ","DSP","FM")
#include "SC01"

int main(void)
{
  _RFILE                            *subf;
  _RIOFB_T                          *fb; /*オープンフィードバック*/
  DSP_t                             sc01;
  int num = 1234567;
  int x;

/*ファイルのオープン*/
    if (( subf = _Ropen("SUB1FM", "ar+" )) == NULL )
    {
        printf ("OPEN ERROR\n" );
        exit ( 1 );
    }
/*サブファイルのクリア*/
    _Rformat(subf,"SC01C" );
     sc01.FM_SC01C_o.IN31 = '1';
    _Rwrite(subf,&sc01.FM_SC01C_o,sizeof(sc01.FM_SC01C_o));

/* 18レコードを出力*/
  /*レコード様式を設定する*/
    _Rformat(subf,"SC01" );
  /*LOOP*/
  for(x=1 ; x <= 18 ; x++){
    QXXITOZ(sc01.FM_SC01_o.DPSEQ,   2, 0, x);
    QXXITOZ(sc01.FM_SC01_o.DPBOTH,  7, 0, num);
    QXXITOZ(sc01.FM_SC01_o.DPOUT,   7, 0, num);
    memset(sc01.FM_SC01_o.DPBTHA, 'X', sizeof(sc01.FM_SC01_o.DPBTHA));
    memset(sc01.FM_SC01_o.DPOUTA, 'X', sizeof(sc01.FM_SC01_o.DPOUTA));
    fb =  _Rwrited(subf,&sc01.FM_SC01_o, 56, x);
  }

/*画面を表示する*/
  /*レコード様式を設定する*/
    _Rformat(subf,"SC01C" );
       sc01.FM_SC01C_o.IN30 = '0';
       sc01.FM_SC01C_o.IN31 = '0';

  /* EXFMTと同じ*/
       fb = _Rwriterd(subf, &sc01.FM_SC01C_o, 2);

  _Rclose (subf);

}

[プログラムの解説]

サブファイルへの書き出しは、RRN(相対レコード番号)を使用する必要があるため、
_Rwrited命令を使用して書き出しを行っています。

    fb=_Rwrited(subf,&sc01.FM_SC01_o, 56, x);
    x に RRNの番号を指定します

注意

RPGでは、プログラムの開始時に各変数の初期化が行われるので、標識は初期値’0’になりますが、 Cではそのような初期化は行われません。よって標識の値に’0’が入っているかどうかは不定です。
上記、プログラムではIN30とIN31を明示的に’0’にセットしていますが、これは、必要な処理です

初期化は行われないことに注意しましょう!!

RPGとCの両者を比較すると、改めてRPGの生産性の高さを実感しますね。

DSPF使った処理は、特別な理由がない限り、RPGで作成するのが賢い選択と言えるでしょう。