IFS

8. RPG による IFS 開発 (1)

V3R1M0 で IBM が発表したIFS ( Intergated File System ) は UNIX との互換ファイル、
つまり Windows や LINUX , UNIX で扱われている一般的なストリーム・ファイルを
保管するためのシステムであり、もう既にご存知の方も多いはずである。
ところが RPG プログラムで IFS ストリーム・ファイルを扱うとなると
C言語のランタイム・ライブラリー( QC2LE ) で公開されている関数(プロシージャー)を利用する必要がある。
従って C言語に精通していない人(= RPGプログラマーの大半の人) は容易に
QC2LE を扱うことができないので、どうしても RPG による IFS 開発は敷居が高いものになってしまう。
米国誌では Scott Klement 氏が開発したライブラリーをダウンロードして利用することを
勧めているが、この方法も一般的ではない。
そこでこのシリーズでは本来ある System i の OS の機能を使って RPG による IFS 開発の
手法と原理を解説することとする。
Step by Step で進めて行くことになる。

■ファイルのオープン

最初の入門は IFS ストリーム・ファイルをオープンして、クローズするだけの簡単なものから始めよう。
IFS ファィル : /A001/TEST.TXT というテキスト・ファイルをオープンするだけの簡単な例を次に紹介する。

【 サンプル:TESTOPN 】
-------------------------------------------------------------------------------------------
0001.00 H DATEDIT(*YMD/)  BNDDIR('QC2LE')                                             
0002.00 F********** IFS のオープン ********************************************       
0003.00 F*                                                                            
0004.00 F* COMIPLE:                                                                   
0005.00 F*    CRTRPGMOD QTEMP/TESTIFS SRCFILE(MYSRCLIB/QRPGLESRC) AUT*ALL)            
0006.00 F*    CRTPGM    MYLIB/TESTIFS MODULE(QTEMP/TESTIFS) ACTGRP(*NEW) AUT(*ALL)    
0007.00 F*                                                                            
0008.00 F**********************************************************************       
0009.00 D FD              S             10I 0                                         
0010.00                                                                               
0011.00 D OPEN_           PR            10I 0 EXTPROC('open')                         
0012.00 D  PATH                           *   VALUE                                   
0013.00 D  FLAG                         10I 0 VALUE                                   
0014.00 D  MODE                         10I 0 VALUE OPTIONS(*NOPASS)                  
0015.00 D  CODEPAGE                     10I 0 VALUE OPTIONS(*NOPASS)                  
0016.00 D  TOPAGE                       10I 0 VALUE OPTIONS(*NOPASS)                  
0017.00                                                                               
0018.00 D CLOSE_          PR                  EXTPROC('close')                        
0019.00 D  FILEID                       10I 0 VALUE                                   
0020.00                                                                               
0021.00 D TRUE            S             10I 0 INZ(0)                                  
0022.00 D FALSE           S             10I 0 INZ(-1)                                 
0023.00 D PERROR_         PR                  EXTPROC('perror')                       
0024.00 D  STR                            *   VALUE                             
0025.00                                                                         
0026.00 D O_RDONLY        S             10I 0 INZ(1)                            
0027.00 D PATH            S             14A   INZ('/A001/TEST.TXT')             
0028.00 D MSG             S             80A   INZ(' オープン・エラーです ')     
0029.00 D SUCCESS         S             80A   INZ(' 読取り成功です ')           
0030.00                                                                         
0031.00  /FREE                                                                  
0032.00      FD = OPEN_(%ADDR(PATH): O_RDONLY);                                 
0033.00     IF (FD < 0);                                                        
0034.00        PERROR_(%ADDR(MSG));                                             
0035.00        RETURN;                                                          
0036.00     ELSE;                                                               
0037.00        PERROR_(%ADDR(SUCCESS));                                         
0038.00     ENDIF;                                                              
0039.00     CLOSE_(FD);                                                         
0040.00     *INLR = *ON;                                                        
0041.00  /END-FREE                                                              
-------------------------------------------------------------------------------------------
【 解説 】

最初に 0001.00 H DATEDIT(*YMD/) BNDDIR('QC2LE') の 「BNDDIR('QC2LE')」とは
C言語のランタイム・ライブラリーをコンパイル時にバインドするために バインド・ディレクリー QC2LE
バインドすることを宣言している。
次に BNDDIR を使用しているために CRTBNDRPG によるコンパイルはできないので
CRTRPGOD + CRTPGM によるコンパイルをすることを

0004.00 F* COMIPLE:                                                                   
0005.00 F*    CRTRPGMOD QTEMP/TESTIFS SRCFILE(MYSRCLIB/QRPGLESRC) AUT*ALL)
0006.00 F*    CRTPGM    MYLIB/TESTIFS MODULE(QTEMP/TESTIFS) ACTGRP(*NEW) AUT(*ALL)

によって指示している。ACTGRP(*NO) も忘れずに指定しておかないとプログラムが
メモリ内に残ってしまうので注意が必要である。

0009.00 D FD              S             10I 0

とは、ファイル記述子と呼ばれるオープンしたファイルを識別するための識別子である。
ファイル記述子は open 関数(プロシージャー) によってオープンが成功すれば結果の値として生成される。
open 関数(プロシージャー) のプロトタイプは

0011.00 D OPEN_           PR            10I 0 EXTPROC('open')
0012.00 D  PATH                           *   VALUE
0013.00 D  FLAG                         10I 0 VALUE
0014.00 D  MODE                         10I 0 VALUE OPTIONS(*NOPASS)
0015.00 D  CODEPAGE                     10I 0 VALUE OPTIONS(*NOPASS)
0016.00 D  TOPAGE                       10I 0 VALUE OPTIONS(*NOPASS)

として定義されている。

● open 関数

open 関数は システム API 解説書の中では次のように紹介されている。

------- 構文 ---------------------------------------------------------------
#include <fcntrl.h>

int open(const char* path, int oflag, ...);
【 パラメータ 】

path (入力)

オープンするファイルの NULL 終了パス名を指すポインター。

oflag (入力)

オープンするファイルのファイル状況フラッグおよびファイル・アクセス・モード。

mode (入力)

mode_t タイプの任意指定の 3番目のパラメータ。
O_CREAT フラグが設定され場合に必要になります

codepage (入力)

unsigned int タイプの任意選択の 4番目のパラメータ。
OCODEPAGE フラグが設定される場合に必要になります。
このパラメータは、次のいずれかまたは両方を指定します。

  • ファイルにおけるデータのコード・ページ (ファイルの作成時)
  • 今回のオープン中にファイルから読み取られたり、ファイルに書き込まれたりする
    データのコード・ページ
■ path (入力)

path で解説されている「NULL 終了パス名を指すポインター」とは char* のことであり C言語でいう
char* とは文字列が NULL (0x00) で終わっている文字列のポインターのことである。
これを RPG で表現すると例えば、

%ADDR(PATH)

のような記述となる。( PATH の最後には NULL が付加されているものとする。)

■ oflag (入力)

次に oflag (入力)で説明されているファイル・アクセス・モードとは、このファイルを作成するのか
または単に読み取りモードで開くのか、あるいは存在していなければ強制的に作成するのか、
などを示すパラメータである。
oflag (入力)には様々なオプションを指定することができるようになっているが各オプションは

0013.00 D  FLAG                         10I 0 VALUE 

でわかるように整数値(int) である。
さらにオプションは

0026.00 D O_RDONLY        S             10I 0 INZ(1)

のように O_RDONLY (読取り専用でオープン) の値は 1 という固定値( INZ(1) ) であるが
O_RDONLY 以外にも

D O_CREAT         S             10I 0 INZ(8)   
D O_TRUNC         S             10I 0 INZ(64)  
D O_CCSID         S             10I 0 INZ(32)  
D O_WRONLY        S             10I 0 INZ(2)   
D S_IWUSR         S             10I 0 INZ(128) 
D S_IRUSR         S             10I 0 INZ(256) 

のようなオプションがあるが、これらを OR で結合したとしても 2進数上ではビットが
重ならないような値として設定されている。

■ mode (入力)

mode (入力) は oflag (入力) に O_CREAT (作成) が指定されたときに指定が必要であるが

0014.00 D  MODE                         10I 0 VALUE OPTIONS(*NOPASS)

OPTIONS(*NOPASS) が示しているように省略可能なパラメータである。

■ codepage (入力)

codepage (入力) は oflag (入力) に O_CODEPAGE (コード・ページ) が指定されたときに
指定が必要である。コード・ページ とは CCSID を示す言語コードの値であり

 Shift_JIS のコード・ページ   943
 UTF-8 のコード・ページ      1028

が基本的なものとして覚えておいてよいだろう。
IFS ストリーム・ファイルのコード・ページは WRKLNK の「8= 属性の表示」で確認することができる。

● close 関数

次に close関数は

0018.00 D CLOSE_          PR                  EXTPROC('close')
0019.00 D  FILEID                       10I 0 VALUE  

によって示されているようにファイル識別子を使ってファイルをクローズする関数である。
ようやく演算命令の説明に入るのだが、この TESTOPN という RPG はフリー・フォーマットとして記述している。
フリー・フォーマットとは

  /FREE
              :
      --(フリー・フォーマット)--
              :
  /END-FREE

として記述することができ、従来の RPG のように桁位置に制約はなく自由に記述することができる。
日本国内ではフリー・フォーマットの普及は少ないが、米国誌のサンプル・ソースは
100% フリー・フォーマットで記述されている。
ここでフリー・フォーマットで記述を紹介した理由は米国誌へ習えという意味ではなく C言語の関数を
利用する場合にはフリー・フォーマットのほうが C言語に近く自然であり、記述も少なくて済むように
なるからである。固定フォーマットでC関数を記述すると、かなり長くて見づらいソースになってしまう。
そこであえてフリー・フォーマットのソースとした。
フリー・フォーマットの場合は C言語と同じように文末は「;」 (セミコロン)で終了する必要がある。

0032.00      FD = OPEN_(%ADDR(PATH): O_RDONLY);

は C言語では

             fd = open(path, O_RDONLY);

と記述することができる。どうだろうか? フリー・フォーマットは C言語に実によく似ている。
open 関数が成功すると結果の値としての FD には正の値が戻るがエラーの場合は FD は負の値となる。
そこで

0023.00 D PERROR_         PR                  EXTPROC('perror')
0024.00 D  STR                            *   VALUE
  :
0028.00 D MSG             S             80A   INZ(' オープン・エラーです ')
  :
0033.00     IF (FD < 0);
0034.00        PERROR_(%ADDR(MSG));
0035.00        RETURN; 

のようにして perror 関数を使ってエラーメッセージを出力している。
C 言語であれば

            perror("オープン・エラーです");

と記述するところである。この perror という C言語の関数は C言語ではよく利用される
エラー・メッセージを出力かるための関数である。
プログラムが指定した「オープン・エラーです」という文字列だけでなくシステムが
エラー・メッセージを併せて出力するので真のエラーの原因を追究することができるようになる。
ただし perror によるシステムのエラー・メッセージは System i で提供されている CPF メッセージのような
詳細なものではない。
最後にこの TESTOPN を実行すると次のようにメッセージされる。

------------------------------------------------------------------------------
 読取り成功です                                    
   :  エラーはありません。                         
 実行キーを押して端末セッションを終了してください。
                                                   
------------------------------------------------------------------------------

ファイルのオープンするだけの簡単なサンプルを紹介したが RPG による
IFS ストリーム・ファイルの操作の基本は理解して頂けたはずである。