System i が AS/400 に始まって iSeries や Systemi i、 IBM i などの名前に変遷してきた中で
今さら S/38 (System 38)でもないと思われるが S/38 のDNAの遍歴は立派に今でも System i に
残っていて、毎日のように見かける QCPFMSG は S/38 の OS の名前が QCPF であったことに由来している。
RPG でも RPG38 というオブジェクト属性の RPGプログラムが現存しているのと同様に
S/38 環境下で作成されたと思われる DSPF38 も残っている。
問題は DSPF38 も System i 環境でもそのままで動作するのだが API : QDFRTVFD によって
ファイル構造を調べようとすると
CPF0679 : オブジェクト xxxx が表示装置ファイルでない
とのエラーが戻ってきて QDFRTVFD は動作しない。
オブジェクト属性 DSPF38 を強制的に DSPF に書き換える API も存在しない。
( API : QLICVTTP :タイプの変換は オブジェクト・タイプを MI などで使用する HEX コードに
変換するものであってオブジェクト・タイプそのものを変換するわけではない。
API : QLICOBJD :オブジェクト記述の変換ユーザー定義を変更することはできるが
オブジェクト・タイプを変換することはできない。)
ライブラリー QSYS38 は存在しているが QSYS38 の中には S/38 用の QDFRTVFD *PGM は存在しない。
そこで考え出された方法とは
DSPF38 のソースを検索して、そのソースから QTEMP に一時的に DSPF を作成して
それを QDFRTVFD で調査する
という方法である。
弊社の製品の中では次のように QDFRTVFD で CPF0679 が発生した場合は QDFRTVFD38 という自前で作成した
関数を呼び出すようにしている。
QDFRTVFD(&qdffbase_t, sizeof(QDFFBASE_t),"DSPF0100", DSPFFLIB, &errcode);
if(errcode.BYTESAVL != 0){/* APIERR */
if(strncmp(errcode.MSGID, "CPF0679", 7) == 0){/* DSPF38 */
if((QDFRTVFD38(formatBuf, &format_size, "DSPF0100", DSPFFLIB,
&errcode)) == FALSE){/* S38 でも失敗 */
return FALSE;
}/* S38 でも失敗 */
}/* DSPF38 */
return FALSE;
関数 : QDFRTVFD とは先に紹介したように、QTEMP に DSPF を *NOLIST *NOSOURCE で作成しているので
パフォーマンス的には何の問題もない。
【QDFRTVFD38】
/***************************************************************/ int QDFRTVFD38(void *formatBuf, int* format_size, char* FORMAT, char* DSPFFLIB, void *errcode) /***************************************************************/ { Qus_OBJD0200_t objd0200; ERRSTRUCTURE apierr; char srcf[11], srcflib[11], srcmbr[11], cmd[128], dspfflib[21]; int len; QDFFBASE_t qdffbase_t; apierr.BYTESPRO = 160; apierr.BYTESAVL = 0; QUSROBJD(&objd0200, sizeof(Qus_OBJD0200_t), "OBJD0200", DSPFFLIB, "*FILE ", &apierr); memcpy(srcf, objd0200.Source_File_Name, 10); srcf[10] = 0x00; len = triml(srcf, ' '); if(len > 0) srcf[len] = 0x00; memcpy(srcflib, objd0200.Source_File_Lib_Name, 10); srcflib[10] = 0x00; len = triml(srcflib, ' '); if(len > 0) srcflib[len] = 0x00; memcpy(srcmbr, objd0200.Source_File_Mbr_Name, 10); srcmbr[10] = 0x00; len = triml(srcmbr, ' '); if(len > 0) srcmbr[len] = 0x00; sprintf(cmd, "CRTDSPF QTEMP/%s SRCFILE(%s/%s) LVLCHK(*NO) OPTION(*NOSRC *NOLIST) AUT(*ALL)", srcmbr, srcflib, srcf); if((system(cmd)) != ERROR){/* 成功 */ memcpy(dspfflib, DSPFFLIB, 20); strcpy(&dspfflib[10], "QTEMP "); QDFRTVFD(&qdffbase_t, sizeof(QDFFBASE_t), "DSPF0100", dspfflib, &apiierr); if(apierr.BYTESAVL != 0){/* APIERR */ return FALSE; }/* APIERR */ /* format_size を動的に確保 */ *format_size = qdffbase_t.WDFFSIZE; formatBuf = (char*)malloc(*format_size + 1); QDFRTVFD(formatBuf, *format_size, "DSPF0100", dspfflib, &apierr); if(apierr.BYTESAVL != 0){/* APIERR */ free(formatBuf); return FALSE }/* APIERR */ return TRUE; }/* 成功 */ return TRUE; }