ILE-RPG(その1)
次ページ へ 目 次 へ


ILE−RPGの最大の特長はバインドと呼ばれる、スタティック・リンク方式にあります。
この方式は、従来のダイナミック・リンク方式に比べ、リンクの際のオーバーヘッドが
軽減され、処理効率が大幅に向上します。
このページでは、従来のRPG(RPG-V)との相違点を中心に、
ILE−RPG(RPG-W)について紹介します。




サンプル

まず、RPG−VからRPG−Wへ、CVTRPGSRCコマンドで変換をしたサンプルを紹介します。

RPG−W
     H*---------------------------------------------------------------
     H* ID   : LM420
     H* NAME :担当者別得意先一覧
     H*---------------------------------------------------------------
     H DATEDIT(*YMD-)
     F*---------------------------------------------------------------
     F*得意先マスターファイル
     FM420      IF   E           K DISK
     F*得意先一覧
     FLM420P    O    E             PRINTER OFLIND(*IN30)
     C*---------------------------------------------------------------
     C*初期処理
     C                   SETON                                        30
     C                   READ      M420R                                  99
     C*本処理
+----C     *IN99         DOWEQ     *OFF
|    C                   MOVEL     TKCDNO        P1TKCD                         得意先Y
|    C                   MOVEL     TKNMKJ        P1NMKJ                         得意先名
|    C                   MOVEL     TKNMKN        P1NMKN                         得意先カナ
|    C                   MOVEL     TKTEL         P1TEL                          TEL
|    C                   MOVEL     TKSLNO        P1SLNO                         担当営業Y
|    C                   MOVEL     TKURJS        P1URJS                         売上実績額
|+---C     *IN30         IFEQ      *ON
||   C                   WRITE     HDR01
||   C                   SETOFF                                       30
|+---C                   ENDIF
|    C                   WRITE     DTL01
|    C*
|    C                   READ      M420R                                  99
+----C                   ENDDO
     C*終了処理
     C                   SETON                                        LR
     C                   RETURN

RPG−V
     **---------------------------------------------------------------
     ** ID   : LM420
     ** NAME :担当者別得意先一覧
     **---------------------------------------------------------------
     H            Y-
     F*---------------------------------------------------------------
     F*得意先マスターファイル
     FM420    IF  E           K        DISK
     F*得意先一覧
     FLM420P  O   E             30     PRINTER
     C*---------------------------------------------------------------
     C*初期処理
     C                     SETON                     30
     C                     READ M420R                    99
     C*本処理
+----C           *IN99     DOWEQ*OFF
|    C                     MOVELTKCDNO    P1TKCD           得意先Y
|    C                     MOVELTKNMKJ    P1NMKJ           得意先名
|    C                     MOVELTKNMKN    P1NMKN           得意先カナ
|    C                     MOVELTKTEL     P1TEL            TEL
|    C                     MOVELTKSLNO    P1SLNO           担当営業Y
|    C                     MOVELTKURJS    P1URJS           売上実績額
|+---C           *IN30     IFEQ *ON
||   C                     WRITEHDR01
||   C                     SETOF                     30
|+---C                     ENDIF
|    C                     WRITEDTL01
|    C*
|    C                     READ M420R                    99
+----C                     ENDDO
     C*終了処理
     C                     SETON                     LR
     C                     RETRN


ソースレコード様式の相違点

RPG-Vでは1行80バイトですが、RPG-Wでは1行100バイトに拡張されています。
フィールド名の長さは、最大14桁まで拡張されています。


各仕様書と仕様書コード

仕様書はファイル補足仕様書(E,L)が廃止され、定義仕様書(D)、プロシージャー仕様書(P)が
新しく設けられています。対応は次のとおりです。

RPG−III RPG−IV
D,I
D,I
なし


制御仕様書(仕様書コード:H)

固定カラム様式からキーワード・パラメータ記述の様式に改定されています。
例えば、日付編集様式がYMDで、その仕切り文字が/のとき、次のようになります。

....+... 1 ...+... 2 ...+... 3 ...+... 4...+... 5 ...+... 6 ...+... 7 ...+. 
H DATEDIT(*YMD/)


ファイル仕様書(仕様書コード:F)

カラム様式のレイアウトが、改定されています。

カラム 項目
6桁 仕様書コード(F)
7〜16桁目 ファイル名
ファイル名は従来の8桁から10桁に拡張されています。
17桁 ファイル・タイプ
I : 入力ファイル
O : 出力ファイル
U : 更新ファイル
C : 入出力共用ファイル
18桁 ブランク :出力ファイル
P : プライマリーファイル
S : セカンダリーファイル
R : レコードアクセスファイル
T : 配列またはテーブルファイル
F : 全手順ファイル
22桁 ファイル形式
F : プログラム記述ファイル
E : 外部記述ファイル
23〜27桁 レコード長。プログラム記述の場合。
29〜33桁 キーの長さ。プログラム記述の場合。
34桁目 レコード・アドレス・タイプ
ブランク 相対レコード番号(RRN)を使用して処理。
K キー値を使用してファイルを処理。
36〜42桁 装置
PRINTER
DISK
WORKSTN
SEQ


定義仕様書(仕様書コード:D)

カラム 項目
7〜21桁 変数名、配列名または構造名
24〜25桁 定義タイプ(C、DS、PI,PR,S)
26〜32桁 開始位置(FROM)
32〜39桁 終了位置(TO)または長さ
40桁 データタイプ
41〜42桁 少数点以下の桁数
44〜80桁 キーワードパラメータ

従来のファイル補足仕様で行っていた、配列/テーブルの定義や入力仕様書におけるデータ構造(DS)は
この部分で定義します。44桁から後に、自由形式のパラメータ記述ができるようになっています。
データのタイプとしては、アドレスを扱うポインター変数が新しく登場しています。


配列

配列の定義は、定義タイプは’S’とし、キーワードパラメータDIMで、要素数とともに定義します。
コンパイル時にデータをローディングするときは、パラメータCTDATAを与えます。
レコードあたりのデータ件数は、パラメータPERRCDで与えます。
以下に例を示します。
....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+. 
     D LDAY            S              2  0 DIM(12) CTDATA PERRCD(12)      

この例は、コンパイル時配列で、名称はLDAY、長さ2、少数点以下0のゾーン10進数データタイプで、
要素数は12です。データは1行あたり12個となっています。


データ構造

データ構造は、定義タイプ’DS’で構造名を定義し、所属要素(データ構造サブフィールド)を
それに引き続く行で、定義タイプ、ブランクで定義します。
所属要素の位置取りは開始位置、終了位置を指定する方法と、その要素の長さを指定する方法の
2種類が可能です。
要素の長さを指定する場合は、「終了位置」に指定し、開始位置はブランクにします。
データタイプには次のようなものがあります。(一部のみ紹介です)
コード タイプ
ブランク 文字列
ゾーン10進数
パック10進数
2進数
ポインター


初期値はキーワード・パラメータ INZで与えます。
以下に例を示します。
 ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     DFLD444           DS                                              
     D FLD01                          6                                
     D FLD02                         12    INZ('111111111122')         
     D FLD03                          4                                
     D AAA01                          1                                
     D AAA22                          5                                
     D BBB11                          5S 0                             

基底付きデータ構造

基底付きデータ構造は、基底として与えられたポインター(アドレス)によって、割当てられる場所が変わるデータ構造です。
アセンブラーのDSECTに相当します。
次に示すのは、基底付きの構造の例です。
 ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7
     DBASED1           DS                  BASED(PTR)                 
     D CCC11                          6                               
     D CCC22                         12                               

上の例で、PTRはアドレスの入るポインター変数です。関数%ADDRによって基底アドレスの取得ができます。
ポインターはデータまたはデータ構造の有り場所を示すデータです。大きさは16バイトです。
世間では64ビットアドレスが最新ですが、ASでは大分前から128ビットアドレスになっています。
このポインターは権限のないプログラムが操作するとオールゼロになるようです。(ウィルス対策か?)
基底付き変数をあやつって、システムの奥の院まで侵入なんてことはできないようです。

RPG-Wでは%ADDRなどいくつかの新しい関数が使用できるようになっています。


独立変数

独立変数とは、構造に属していない単独の変数をいいます。COBOLでいえば、77項目に相当します。
定義タイプを’S’(スカラー)として、長さ、データタイプ、小数以下の桁数を指定して定義します。
初期値を与える場合は、キーワードINZで指定します。
以下に例を示します。いずれも5桁のパック10進数を定義しています。



 ....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
      D I               S              5P 0 INZ(0)                      
      D J               S              5P 0                             
      D K               S              5P 0                             
      D L               S              5P 0                             
      D M               S              5P 0                             
      D N               S              5P 0                             


可変長変数

可変長変数は長さの変わる文字列のための変数です。
定義はVARYING属性をつけて、次の例のようにします。

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     D VAR1            S             20A   VARYING                      
     D VAR2            S             30A   VARYING                    
                             

楽屋裏では、2バイトの長さ情報+文字列の形でサポートしています。


可変長レコードのサポート

可変長レコードは、次のようにしてサポートできます。

  1)可変長レコードのファイル定義

   DDSでは定義できません。SQLのCREATE TABLEコマンドを使って定義します。

  CREATE TABLE QTEMP/FILE1 (FLD01 VARCHAR (80 )
   NOT NULL WITH DEFAULT)


   この例では、1レコード1フィールドの可変長レコード(最大長80バイト)のファイルが定義されます。

  2)プログラムでは、最大長80バイトの可変長フィールドを、1個だけからなる構造体を定義して
   利用します。

以下に例を示します。

... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
H DATEDIT(*YMD-)                      
FFILE1     O    F   82        DISK                                         
 *                                                                         
D FILE1R          DS                                                       
D VAR1                          80A   VARYING                              
 *                                                                         
C                   MOVEL     *ALL'A'       C10A             10           
C                   MOVEL     *ALL'B'       C20A             20         
C                   MOVEL     *ALL'C'       C30A             30         
C                   EVAL      VAR1= C10A                                  
C                   WRITE     FILE1         FILE1R                         
C                   EVAL      VAR1= C20A                                  
C                   WRITE     FILE1         FILE1R                         
C                   EVAL      VAR1= C30A                                  
C                   WRITE     FILE1         FILE1R                         
 *                                                                         
C                   SETON                                        LR        
C                   RETURN             

注:
 1)ファイル仕様書ではレコード長を80+2(=82)バイトで記述していることに注意してください。
 2)レコードの構造体は最大長80バイトのVARYING属性の1フィールドの構造を定義しています。
 3)変数VAR1にはEVAL命令でセットしていることに注意してください。
   MOVELで値をセットすると、最初のMOVELでその長さが固定されてしまいます。
   EVALであれば、長さの可変長属性が保たれます。

上記プログラムの実行結果は次のようになります。

                   物理ファイル・メンバー表示
 ファイル . . . : FILE1 ライブラリー . : QTEMP
 メンバー . . . : FILE1 レコード . . . : 1
 制御 . . . . . . 桁 . . . . . . : 1
 検索 . . . . . .
 * . . . + . . . . 1 . . . . + . . . . 2 . . . . + . . . . 3 . . . . . .
 
000AC1C1 C1C1C1C1 C1C1C1C1 40404040 40404040 40404040 40404040 40404040 40404040
 
0014C2C2 C2C2C2C2 C2C2C2C2 C2C2C2C2 C2C2C2C2 C2C24040 40404040 40404040 40404040
 
001EC3C3 C3C3C3C3 C3C3C3C3 C3C3C3C3 C3C3C3C3 C3C3C3C3 C3C3C3C3 C3C3C3C3 40404040
              ****** データの終わり ******
先頭の2バイト(赤)が長さ情報となっていることに注意して下さい。


演算仕様書(仕様書コード:C)

様式の拡張

項目2の様式が2種類になっています。

RPGVからの拡張の様式

カラム様式の改訂に加え、さらに拡張様式で、「式」の記述ができるようになっています。
「式」とは評価(計算)をしたとき、最終的にある値を表わすものをいいます。

.....CL0N01FACTOR1+++++++OPCODE&EXTFACTOR2+++++++RESULT++++++++LEN++D+H 
     C                   Z-ADD     P@YMD         W@YMD                  
     C     W@YY          DIV       04            W                      
     C                   MVR                     R                      


RPGW項目2の拡張様式

項目2が拡張されて、式を記述できるようになっています。
 .....CL0N01FACTOR1+++++++OPCODE&EXTEXTENDED-FACTOR2++++++++++++++++++++
      C                   IF        AA =  BB OR  CC > DD                
      C                   EVAL      A = B**2  + C                       

フィールド名は14桁まで拡張されています。結果のフィールドも同様です。
添え字は、RPG−IIIでは

変数名,X

の形でしたが、RPG-IVでは

変数名(X)

の形になっています。
拡張された14桁のうち、10桁までは変数用にし、4桁分は添え字に使うことをおすすめします。


組込関数

式の記述に呼応して、各種の組込み関数が用意されています。
一部を紹介します。
関数名 機能
%SUBST 文字列の切出し
%CHAR 文字列への変換
%SCAN 文字列の検索
%ADDR アドレスポインターの取得


命令

命令も拡張されています。いくつかを紹介します。
命令 機能
ALLOC メモリーの獲得(汎用機でのGETMAINマクロ相当)
CALLB バインド済みプロシージャー呼び出し
CALLP プロトタイププロシージャー/プログラムの呼び出し。
DOW WHILE型の繰返し
DOU UNTIL型の繰返し
EVAL 式の評価と割付。COBOLのCOMPUTE命令。


プロシージャーとサブ・プロシージャー

従来のRPGでのプログラムが、プロシージャーとサブ・プロシージャーの2タイプに別れています。
プロシージャーは従来のプログラムに相当し、RPGサイクルや実行のために必要なメモリーなどの
資源を準備するためのコードが付加されています。

サブ・プロシージャーは、呼び出され専門のプログラムといえます。
サブ・プロシージャーにはRPG独特のサイクルの部分はありません。
プロシージャーの一般構造は次のようになります。
プロシージャー 制御仕様書
ファイル仕様書
定義仕様書
入力仕様書
演算仕様書
サブ・プロシージャー プロシージャー仕様書の始め
定義仕様書
演算仕様書
プロシージャー仕様書の終り
データ コンパイル時配列へのローディングデータ 仕様書コードなし

プロシージャー仕様書の始めから、同じく終りまでが、サブ・プロシージャーで、それ以外がメイン・プロシージャーです。


サブ・プロシージャー

サブ・プロシージャーは、メインプログラムの中に含まれるサブ・ルーチンで、開始のプロシージャー仕様書と
終了のプロシージャー仕様書で区切られます。
開始のプロシージャー仕様書は仕様書コード’P’で、24桁目が’B’、終了は同じく’E’です。
以下にサブ・プロシージャーを含むプログラムのサンプルを示します。
サブ・プロシージャーは複数あってもよいし、また、まったくなくてもかまいません。
なお、EXSRで呼び出す従来の内部サブルーチンも当然使用できます。
呼出使用で効率が一番よいのは内部サブルーチン、ついでサブ・プロジージャー、従来の(OPM)プログラムです。

以下に例を示します。

サンプル

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     H DATEDIT(*YMD-)                                                  
     D*----------------------------------------------------------------
     D  YMD1           S              6S 0                             
     D  YMD1A          S              8S 0                             
     D SUBY2K          PR                                              
     C     *ENTRY        PLIST                                         
     C                   PARM                    YMD1C             6   
     C                   MOVE      YMD1C         YMD1                  
     C                   CALLP     SUBY2K                              
     C     YMD1A         DSPLY                                         
     C                   SETON                                        LR
     C                   RETURN                                        
     P*. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     P* ここからサブプロシージャー
     P SUBY2K          B                                               
     C*                                                                
     C     YMD1          IFGT      700000                              
     C                   EVAL      YMD1A = YMD1+ 19000000              
     C                   ELSE                                          
     C                   EVAL      YMD1A = YMD1+ 20000000              
     C                   ENDIF                                         
     C                   RETURN                                                        
     P                 E

このサブプロシージャーでは、外側で定義した変数をそのままサブ・プロシージャーで使用し、
1900年代か2000年代かを判断しています。

サブ・プロシージャーの内部で、改めて定義仕様書(D仕様書)により変数の定義することもできます。
この場合、内部で定義した変数はそのサブ・プロシージャー内だけで、通用します。
(これは、PL/I のサブ・プロシージャーの場合と同じです。)


パラメータの受け渡し

外側で定義した変数を共用する方法のほかに、パラメータを定義してそれを介してデータを授受することも
できます。このためには、呼び出し側は、定義仕様書でプロトタイプと呼ばれる、受渡し情報を定義します。
プロトタイプの定義タイプは’PR’です。パラメータの形式情報は、その直後に続けて定義します。
例えば、SUBY2Kという名のサブ・プロシージャーで6S0、8S0(ゾーン10進数)のパラメータを受渡しする
場合のプロトタイプは次のようになります。

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     D SUBY2K          PR                                              
     D                                6S 0                             
     D                                8S 0                             

受取り側は対応するパラメータプロシージャ・インターフェイス(PI)を定義します。
パラメータプロシージャ・インターフェイスは、定義タイプ’PI’として定義し、それにつづけて
各パラメータを定義します。
上記呼び出しを受ける場合のパラメータ・インターフェイスは次のようになります。

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     D SUBY2K          PI                                              
     D  YMD2                          6S 0                             
     D  YMD2A                         8S 0                             

サンプル・プログラム

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     D* パラメータを使用してのプロシージャー呼び出し。                 
     H DATEDIT(*YMD-)                                                  
     D*================================================================
     D* プロトタイプの指定                                             
     D* 呼び出されるプログラムは 6S0 8S0 のパラメータを要求            
     D SUBY2K          PR                                              
     D                                6S 0                             
     D                                8S 0                             
     D*----------------------------------------------------------------
     D  YMD1           S              6S 0                             
     D  YMD1A          S              8S 0                             
     C*================================================================
     C     *ENTRY        PLIST                                         
     C                   PARM                    YMD1                  
     C*                                                                
     C                   CALLP     SUBY2K (YMD1:YMD1A)                 
     C*                                     6S0  8S0                   
     C     YMD1A         DSPLY                                         
     C     YMD2A         DSPLY                                         
     C                   SETON                                        LR
     C                   RETURN                                        
     P*================================================================
     P* ここからサブ・プロシージャー                                   
     P SUBY2K          B                                               
     D* パラメータインターフェイス                                     
     D SUBY2K          PI                                              
     D  YMD2                          6S 0                             
     D  YMD2A                         8S 0                             
     C*                                                                
     C     YMD2          IFGT      700000                              
     C                   EVAL      YMD2A = YMD2+ 19000000              
     C                   ELSE                                          
     C                   EVAL      YMD2A = YMD2+ 20000000              
     C                   ENDIF                                         
     C                   EVAL      YMD1  = YMD1                        
     C                   RETURN                                        
     P                 E                                               



スタティック・リンク

従来、外部プログラムを呼出し利用する場合は、ダイナミック(動的)リンクで、行っていました。
ILEの体系では、実行プログラム・オブジェクトの前に、プログラム・モジュールを作成し、
これをバインドして実行プログラム・オブジェクトを作成するようになっています。
すなわち、コンパイラーの役目はプログラム・モジュールを作成するところまでです。

バインドでは、どのコンパイラーが作り出したプログラム・モジュールも特別に区別すること
なく、実行プログラム・オブジェクトに組込まれます。これがILE(統合化言語環境)といわれる
ゆえんです。いわば、裏方の環境は激変していますが、表側からは激変というほどのことは
ありません。
スタティック・リンクにすると、ダイナミック・リンクの際に行っていた、SYSてMのいくつかの作業が
バインド時に行わなわれ、実行時に必要なくなるので、処理の効率がよくなります。

汎用機では当初から、コンパイル+リンクの形でスタティック・リンクが行われており、むしろ
ダイナミック・リンクは、どちらかというと例外的でした。AS/400では逆にダイナミック・リンクが
メインでしたが、ILEによってダイナミック・リンクのオーバーヘッドを取り除き、効率を高めようとする
ねらいと思われます。実測では約100倍となっています。

AS/400と汎用機の対応は次のようになります。
AS/400 汎用機
コンパイル コンパイル
プログラム・モジュール オブジェクト
バインド リンク・エディット
実行プログラム・オブジェクト ロードモ・ジュール


ILE−RPGのパフォーマンス

ある本に外部CALL命令を利用してのプログラム呼出しは莫大な「費用」がかかるので、・・・
という記述を見て、RPG-IIIによる外部CALL命令を使用した場合と、RPG-IVによるプロシージャー呼出しの
差を比較してみました。結果は下記のとおりで思わぬ大差がつきました。
LR(ラストレコード)標識をオフにしないでリターンさせるテクで、RPG−IIIをチューンナップした場合も
比較のためにあげています。

下はRPG-IVのプログラムの例です。呼出したプログラムからの戻りの値を出力したり、表示
したりはしていません。RPG-IIIも同様のプログラムでCALLによる外部プログラム呼出し
の個所が異なるだけです。(ソース省略)

200,000件の呼出しの結果は次のとおりです。ページアウトの影響をできるだけさけるため、
いずれも2回RUNして、2回目の値をとっています。時間の計測はそれほど正確ではありません。

RPG-III(SETON LRあり) 約45秒
RPG-III(SETON LRなし) 約6秒
RPG-IV 約1秒(もっと少ないかもしれません。)

マシンはAS/400−170,OSはV4.3.0です。


テストに使用したILE−RPGのソース

呼び出しプロシージャーは単なる回数稼ぎのプログラムです。
呼び出されるサブ・プロシージャーは日付の妥当性チェックのプログラムです。実戦使用に耐えます。

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     H*---------------------------------------------------------------  
     H DATEDIT(*YMD-)                                                   
     D*---------------------------------------------------------------  
     D LDAY            S              2  0 DIM(12) CTDATA PERRCD(12)    
     D LDAY2           S              2  0 DIM(02) INZ(3)               
     D                 DS                                               
     D  W@YMD                  1      8  0                              
     D  W@YY                   3      4  0                              
     D  W@MM                   5      6  0                              
     D  M                      5      6  0                              
     D  W@DD                   7      8  0                              
     D P@RC            S              1                                 
     D*--------------------------------------                           
     D \CHKYMD         PR                                               
     D                                8P 0                              
     D                                1                                 
     C*---------------------------------------------------------------  
     C     *ENTRY        PLIST                                          
     C                   PARM                    P@CNT             6    
     C* 初期処理                                                        
     C                   MOVE      P@CNT         W@CNT             6 0    
     C                   Z-ADD     900100        W@YMD                    
     C                   Z-ADD     000           X                 6 0    
     C* ----------------------------------------------------------        
     C     001           DO        W@CNT         X                        
     C*                                                                   
     C                   ADD       001           W@DD                     
     C     W@DD          IFGT      031                                    
     C                   Z-ADD     001           W@DD                     
     C                   ADD       001           W@MM                     
     C     W@DD          IFGT      013                                    
     C                   Z-ADD     001           W@MM                     
     C                   ADD       001           W@YY                     
     C                   ENDIF                                            
     C                   ENDIF                                            
     C*                                                                   
     C                   Z-ADD     W@YMD         P@YMD             8 0    
     C                   CALLP     \CHKYMD(P@YMD:P@RC)                    
     C*                                                                   
     C                   ENDDO                                            
     C* ----------------------------------------------------------        
     C                   SETON                                        LR  
     C                   RETURN                                           
     P* ここからサブ・プロシージャー                                      
     P \CHKYMD         B                                                  
     D \CHKYMD         PI                                                 
     D  P@YMD                         8P 0                                
     D  P@RC                          1                                   
     D*---------------------------------------------------------------    
     D                 DS                                                 
     D  W@YMD                  1      8  0                                
     D  W@YY                   3      4  0                                
     D  W@MM                   5      6  0                                
     D  M                      5      6  0                                
     D  W@DD                   7      8  0                                
     C*---------------------------------------------------------------    
     C*                  Z-ADD     0             X@MM(1)                  
     C                   Z-ADD     LDAY2(2)      X                 7 0    
     C* 初期処理                                                          
     C                   EXSR      SBINZ                                 
     C* 本処理                                                         
     C                   EXSR      SBMAIN                                
     C* 終了処理                                                         
     C                   EXSR      SBEND                                 
     C*---------------------------------------------------------------   
     C     SBINZ         BEGSR                                           
     C* 定義                                                             
     C                   Z-ADD     000           W                 7 0   
     C                   Z-ADD     00            R                 7 0   
     C                   Z-ADD     00            LEAP              7 0   
     C* 閏年判定                                                         
     C                   Z-ADD     P@YMD         W@YMD                   
     C     W@YY          DIV       04            W                       
     C                   MVR                     R                       
     C* 2月末日取得                                                     
     C     R             IFEQ      00                                     
     C                   Z-ADD     01            LEAP                     
     C                   ELSE                                             
     C                   Z-ADD     00            LEAP                     
     C                   ENDIF                                            
     C                   ADD       LEAP          LDAY(2)                  
     C*                                                                   
     C                   ENDSR                                            
     C*---------------------------------------------------------------    
     C     SBMAIN        BEGSR                                            
     C* 月チェック                                                        
     C     W@MM          IFLT      01                                     
     C     W@MM          ANDGT     12                                     
     C                   MOVE      *ZERO         P@RC                     
     C                   ELSE                                             
     C* 日チェック                                                        
     C     W@DD          IFLT      01                                     
     C     W@DD          ANDGT     LDAY(M)                                
     C                   MOVE      *ZERO         P@RC                     
     C                   ENDIF                                            
     C                   ENDIF                                         
     C*                                                                
     C                   ENDSR                                         
     C*--------------------------------------------------------------- 
     C     SBEND         BEGSR                                         
     C*                                                                
     C                   SETON                                        LR
     C                   RETURN                                        
     C*                                                                
     C                   ENDSR                                         
     P                 E                                               
** LDAY **                                                             
312831303130313130313031                                               


プログラム・モジュールから実行プログラム作成

別々のコンパイル・タイミングで作成されたモジュールを組み合わせて、実行プログラムを作成する場合は
次のような手順になります。


手順1.モジュールの作成

CRTRPGMOD MODULE(WRKLIB/TESTR)  /*サブのつもりです。*/

別のタイミングで(あるいは別の場所で)
CRTRPGMOD MODULE(WRKLIB/TESTRPG)   /*メインのつもりです。*/ 


手順2.実行プログラムの作成

CRTPGM PGM(WRKLIB/TESTRPG) MODULE(WRKLIB/TESTRPG WRKLIB/TESTR) −
DETAIL(*BASIC)



手順3.実行

CALL  WRKLIB/TESTRPG)


以下にサンプル・プログラムを示します。

メイン・プロシージャー

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     H DATEDIT(*YMD-)                                                    
     D*------------------------------------                              
     D* プロトタイプの指定                                               
     D TESTR           PR                                                
     D                                4A                                 
     D                               10I 0                               
     D*------------------------------------                              
     D  AA             S              4A                                 
     D  BB             S             10I 0                               
     C*------------------------------------                              
     C                   MOVEL     '1234'        AA                      
     C                   Z-ADD     9876          BB                      
     C*                                                                  
     C                   CALLP     TESTR  (AA: BB )                      
     C     AA            DSPLY                                           
     C     BB            DSPLY                                           
     C                   SETON                                        LR 


サブ・プロシージャー

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     H     NOMAIN                       
     DTESTR            PR                                                
     D  AA                            4A                                 
     D  BB                           10I 0           
     PTESTR            B                   EXPORT
     P*                                    ******      
     D*------------------------------------                              
     DTESTR            PI                                                
     D  AA                            4A                                 
     D  BB                           10I 0                               
     C*------------------------------------                              
     C*                                                                  
     C                   MOVEL     'ABCD'        AA                      
     C     BB            DIV       2             BB                      
     C*                                                                  
     C                   RETURN                                          
     C                   SETON                                        LR 
     P                 E                                                 

サブ・プロシージャーにEXPORTパラメータをつけていることに注意して下さい。
これによって、入り口点TESTRが外部属性をもち、他のプロシージャーから見えるようになります。
EXPORTされていないと、外部からTESTRの入り口点が見えません。
CRTPGMでは一見ノーマルにバインドが完了するが、正常にRUNしません。(LOOPすることもある。)

(本来なら、バインドの際になんらかのメッセージがでて、しかるべきと思うのですが)



CLプロシージャーの呼び出し

サンプルのみ紹介します。

RPGによるメイン・プロシージャー
....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
     H DATEDIT(*YMD-)                                                    
     D*------------------------------------                              
     D* プロトタイプの指定                                               
     D TESTCL          PR                                                
     D                                4A                                 
     D                               09P 0                               
     D*------------------------------------                              
     D  AA             S              4A                                 
     D  BB             S             09P 0                               
     C*------------------------------------                              
     C                   MOVEL     '1234'        AA                      
     C                   Z-ADD     9876          BB                      
     C*                                                                  
     C                   CALLP     TESTCL (AA: BB )                      
     C     AA            DSPLY                                           
     C     BB            DSPLY                                           
     C                   SETON                                        LR 
     C                   RETURN                                          
CLで扱える数値データはパック10進数のみです。


CLによるサブ・プロシージャー
PGM   PARM(&AA  &CC)                                                
                                                   
      DCL  &AA  *CHAR  4                           
      DCL  &CC  *DEC   9                           
                                                   
      CHGVAR    &AA  VALUE('EFGH')                 
      CHGVAR    &CC  VALUE(&CC  * 2)               
                                                   
ENDPGM                                             


プロトタイプについて

プロトタイプという一見わずらわしい宣言が呼び出し側にあります。
マニュアルには四の五のと説明がありますが、真相はコンパイルが別タイミングになるため、
呼び出し側からどのタイプのデータをパラメータとして準備して呼び出ししたらよいのかわからないので、
それをコンパイラーに知らせるためのもののようです。
たしか、はるかむかし、PL/1でも同じようなことがあったと記憶しています。
そのときのマニュアルには上記理由がきちんと書いてありました。そして、プロトタイプ(相当)を
記述しないと、呼び出しのときの属性でパラメータリストが作成されるとあったと思います。


関数型の呼び出し

ILE−COBOLにはSIN,COSなどの数学関数がいくつかあるのに、ILE−RPGには
それがありません。そのためにわざわざCOBOLを導入するのも、と数学関数COS,SINを作成し
関数呼出しをしてみました。SINはCOSの移相を90°ずらせただけです。
プロシージャーのサンプルを紹介します。

....+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
      *関数型の呼出しと関数プロシージャー
     H DATEDIT(*YMD-)
      *---------------------------------------------------------------
      *プロトタイプの指定          ↓戻り
     DCOS              PR             8F
     D                                8F
      *
     DSIN              PR             8F
     D                                8F
      *---------------------------------------------------------------
      *WORKエリア指定
     D  A              S              8F
      *
     D STR             DS
     D  XX                           12S11
     D  DUMY1                         1A
     D  CX                           12S11
     D  DUMY2                         1A
     D  SX                           12S11
     D  DUMY3                         1A
     D  R                            12S11
      *
     D  X              S              8F
      *---------------------------------------------------------------
     C                   CLEAR                   STR
     C                   EVAL      X  = 0.0
     C                   EVAL      XX = X
     C                   EVAL      CX = COS(X)
     C                   EVAL      SX = SIN(X)
     C                   EVAL      R  = SIN(X)*SIN(X) + COS(X)*COS(X)
     C     STR           DSPLY
      *
     C                   EVAL      X  = 3.141592/2.0
     C                   EVAL      XX = X
     C                   EVAL      CX = COS(X)
     C                   EVAL      SX = SIN(X)
     C                   EVAL      R  = SIN(X)*SIN(X) + COS(X)*COS(X)
     C     STR           DSPLY
     C     '---'         DSPLY
      *
     C* COS  0.0 --> 0.1
     C                   Z-ADD     000           X
     C     X             DOWLT     0.1
     C                   EVAL      XX = X
     C                   EVAL      CX = COS(X)
     C                   EVAL      SX = SIN(X)
     C                   EVAL      R  = SIN(X)*SIN(X) + COS(X)*COS(X)
     C     STR           DSPLY
     C                   ADD       0.01          X
     C                   ENDDO
     C                   SETON                                        LR
     C*
     C                   RETURN
      *=================================================================
      *ここから自作関数
     PCOS              B
      *関数型の戻りを示す          ↓
     DCOS              PI             8F
     D  X                             8F
      *
     D T               S              8F
     D Y               S              8F
     D WK              S              8F
     D N               S              7P 0
     C*---------------------------------------------------------------
     C                   Z-ADD     001           Y
     C                   Z-ADD     001           T
     C                   Z-ADD     001           N
      *テーラー展開による計算
     C     001           DO        999           N
     C                   EVAL      T = -T*X*X/((2*N)*(2*N-1))
      *絶対値を取得
     C                   Z-ADD     T             WK
     C     T             IFLT      0
     C     0             SUB       T             WK
     C                   ENDIF
      *
     C     WK            IFLE      0.1E-11
     C                   LEAVE
     C                   ELSE
     C                   EVAL      Y = Y + T
     C                   ENDIF
     C                   ENDDO
     C                   RETURN    Y
     PCOS              E
      *----------------------------------------------------------------
     PSIN              B
      *関数型の戻りを示す          ↓
     DSIN              PI             8F
     D  X                             8F
      *
     D Y               S              8F
     D W               S              8F
     C*---------------------------------------------------------------
     C                   EVAL      W = X -3.14159265/2.000000000000
     C                   EVAL      Y = COS(W)
     C                   RETURN    Y
     PSIN              E

計算はテーラー展開による多項式の近似計算を行っています。
近似したかどうかは、高次項の計算結果が、十分0に近いかどうかで判定しています。
計算は倍精度の浮動小数点(FORTRANではREAL*8相当)で行っています。
プロトタイプおよび独立変数(スカラー)の定義に8Fとあるのが浮動小数点の定義です。
関数型の中にある、定数0.1E−10は0.1*10のマイナス10乗、すなわち
0.00000000001のことです。まちがっても、0.0とやらないでください。

近似のための繰返しはせいぜい12、3回です。あたえるパラメータの値によって繰り返し回数はかわります。

◆原子力コードによるシミュレーションでもないかぎり、十分実用に耐えるはずです。

プログラムのコンパイル

このプログラムのコンパイルは、モジュール経由でバインドするのでないので、
(すなわち、一気に実行プログラムをつくるので、)CRTBNDRPGで行います。
DFTACTGRPパラメータを*NOとすることを忘れないで下さい。

関数型呼出しの要点

1.呼出し側のプロトタイプ指定で戻りのデータ属性をつけます。
2.呼出しは、EVAL命令でY=COS(X)のように関数型の呼出しをします。
3.関数型のサブプロシージャーではインターフェイスで戻りのデータ属性をつけます。
4.同プロシージャーの中では、RETURN Yのように戻す式を指定します。




近いうちに、TAN,LOG,LOG10など作ってみたいと思っています




次ページへ 目 次 へ


(C)COPYRIGHT ISHIOKA KATSUHIDE 2000、2011