好むと好まざるにかかわらず RPG で Unicode を扱う必要がある時代はすぐそこにやってきている。
今から少しずつでも Unicode に馴染んでおきたいものである。
RPG で Unicode ( UTF-8 ) のストリーム・ファイルを IFS に出力するにはどのようにすればよいのだろうか ?
RPG で IFS へ Unicode ファイルを出力するサンプルを紹介しよう。
------------------------------------------------------------------------------------
0001.00 H DFTNAME(TESTUNI) DATEDIT(*YMD/) BNDDIR('QC2LE')
0002.00 F******** IFS への UNICODE 出力 ***************************************
0003.00 F*
0004.00 F* CRTRPGMOD QTEMP/TESTUNI SRCFILE(PGMRLIB/QRPGLESRC) AUT(*ALL)
0005.00 F* CRTPGM OBJLIB/TESTUNI MODULE(QTEMP/TESTUNI)
0006.00 F* SRVPGM(QSYS/QP0LLIB1) AUT(*ALL)
0007.00 F*
0008.00 F**********************************************************************
0009.00 D FD S 10I 0
0010.00 D DATA S 1000C CCSID(1200)
0011.00
0012.00 D OPEN_ PR 10I 0 EXTPROC('open')
0013.00 D PATH * VALUE
0014.00 D FLAG 10I 0 VALUE
0015.00 D MODE 10I 0 VALUE OPTIONS(*NOPASS)
0016.00 D CODEPAGE 10I 0 VALUE OPTIONS(*NOPASS)
0017.00 D TOPAGE 10I 0 VALUE OPTIONS(*NOPASS)
0018.00
0019.00 D WRITE_ PR 10I 0 EXTPROC('write')
0020.00 D DESC 10I 0 VALUE
0021.00 D DATA * VALUE
0022.00 D DTALEN 10I 0 VALUE
0023.00
0024.00 D CLOSE_ PR EXTPROC('close')
0025.00 D DESC 10I 0 VALUE
0026.00
0027.00 D PERROR_ PR EXTPROC('perror')
0028.00 D STR * VALUE
0029.00
0030.00 D O_CREAT S 10I 0 INZ(8)
0031.00 D O_TRUNC S 10I 0 INZ(64)
0032.00 D O_CCSID S 10I 0 INZ(32)
0033.00 D O_WRONLY S 10I 0 INZ(2)
0034.00 D S_IWUSR S 10I 0 INZ(128)
0035.00 D S_IRUSR S 10I 0 INZ(256)
0036.00 D PATH S 14A INZ('/A001/TEST.TXT')
0037.00 D MSG S 80A INZ(' オープン・エラーです ')
0038.00
0039.00 /FREE
0040.00 FD = OPEN_(%ADDR(PATH):
0041.00 O_CREAT + O_TRUNC + O_CCSID + O_WRONLY :
0042.00 S_IWUSR + S_IRUSR :
0043.00 1208);
0044.00 IF (FD < 0);
0045.00 PERROR_(%ADDR(MSG));
0046.00 RETURN;
0047.00 ENDIF;
0048.00 DATA = %UCS2('hello UNICODE');
0049.00 WRITE_(FD : %ADDR(DATA) : %LEN(%TRIMR(DATA)) * 2);
0050.00 CLOSE_(FD);
0051.00 *INLR = *ON;
0052.00 /END-FREE
------------------------------------------------------------------------------------
CRTRPGMOD QTEMP/TESTUNI SRCFILE(PGMRLIB/QRPGLESRC) AUT(*ALL) CRTPGM OBJLIB/TESTUNI MODULE(QTEMP/TESTUNI) SRVPGM(QSYS/QP0LLIB1) AUT(*ALL)
のようにして QSYS/QP0LLIB1 *SRVPGM をバインドしてビルドする必要がある。
QSYS/QP0LLIB1 とは open, read, write, close 等の IFS API が保管されている
サービス・プログラムである。これらの関数は C/400 の関数( QC2LE ) ではないので
BNDDIR('QC2LE') には含まれていない。従って明示的にバインドしてやる必要がある。
米国雑誌でも IFS の入出力を RPG で行う方法のサンプル・ソースはよく紹介されているが
いずれも ある公開ライブラリーをダウンロードして導入しなければならない。
上記のように、どのような System i でも 動作する IFS への入出力の事例を示しているのは
珍しいはずである。(もちろん IBM マニュアルには掲載されていない。)
上記の例では IFS の入出力の open, write, close を使っている以外として Unicode に係わる部分は
0010.00 D DATA S 1000C CCSID(1200)
0040.00 FD = OPEN_(%ADDR(PATH):
0041.00 O_CREAT + O_TRUNC + O_CCSID + O_WRONLY :
0042.00 S_IWUSR + S_IRUSR :
0043.00 1208);
0048.00 DATA = %UCS2('hello UNICODE');
の行だけである。
最初に DATA という 1000バイトのフィールドの定義で 1000C の C は、この DATA が
UCS-2 ( CCSID 13488 ) であることを宣言している。
CCSID(1200) は UTF-16 という意味である。( UTF-8 つまり CCSID(1208) を定義することはできない。)
次に CCSID = 1208 (UTF-8) を無理やり指定して ( UTF-16 であれば 1200 ) O_CCSID を
オプション指定することによって open 関数を実行している。
これによって WRKLNK で作成された IFS ストリーム・ファイルの属性を調べれば
CCSID は 1208 つまり UTF-8 となっているはずである。
さらに
DATA = %UCS2('hello UNICODE');
によって 'hello UNICODE' という文字列を UTF-16 に置き換えている。
%UCS2 とは IBM によって RPG 上で提供されている Unicode 変換のための BIFF 関数である。
この TESTUNI というプログラムを実行してみると IFS には
h e l l o U N I C O D E
という文字列が UTF-16 として出力されてるのを確認することができる。
半角で入力したはずの英小文字も倍角となっているのだから、これは UTF-16 である。
ところで %UCS2 は日本語漢字も UTF-16 に変換できるのだろうか ?
試してみたところ文字化けして全くダメであった。
また RPG は UTF-8 への変換をサポートする機能はあるのだろうか ?
これも %USC2 は UCS-2 ( CCSID 13488 ) だけへの変換であり、 UTF-8 への変換は
全くサポートされていない。
現実では Uncode は UTF-8 による使用が全世界で圧倒的多数を占めている。
IBM の対応は遅れている感が否めない。
EnterpriseServer では UNI_CODE *SRVPGM をユーザーに提供して UTF-8, EBCDIC, ASCII
の相互変換をサポートしている。