弊社のスタッフのための参考として 操作員メッセージ(QSYSOPR) メッセージをすべて
表示するサンプルを作成してので紹介する。
プログラム・メッセージの検索には API:QMHRTVPM を使用するが
QSYSOPR は非プログラム・メッセージであるので API:QMHRTVM を使用する。
また、このサンプルは API の利用でエラーとなったときに QMHRTVM によって
エラー・メッセージを取得して表示することのサンプルでもある。
特にどのように LOOP すべきかを示している例でもある。
0001.00 #include <stdio.h> 0002.00 #include <stdlib.h> 0003.00 #include <string.h> 0004.00 #include <QMHRCVM.h> 0005.00 #include <QMHRTVM.h> 0006.00 0007.00 #define TRUE 0 0008.00 #define FALSE -1 0009.00 typedef struct { 0010.00 int BYTESPRO; 0011.00 int BYTESAVL; 0012.00 char MSGID[7]; 0013.00 char RESRVD; 0014.00 char EXCPDATA[100]; 0015.00 } ERRSTRUCTURE; /* Define the error return structure */ 0016.00 ERRSTRUCTURE errcode;/* Error Code Structure for RCVMSG */ 0017.00 void ApiError(char* place, int stmno, ERRSTRUCTURE* errcode, char* pgm); 0018.00 0019.00 void main(void){ 0020.00 typedef struct { 0021.00 Qmh_Rcvm_RCVM0200_t rcvm0200; 0022.00 char Message[256]; 0023.00 } MSG0200; 0024.00 MSG0200 msg0200; 0025.00 char msg_key[4], old_key[4], msg_type[10], msg[132]; 0026.00 int len, pos, waittime = 0; 0027.00 int i; 0028.00 0029.00 printf("** TESTOPR **\n"); 0030.00 getchar(); 0031.00 0032.00 errcode.BYTESPRO = 160; 0033.00 errcode.BYTESAVL = 0; 0034.00 0035.00 memset(&msg0200, 0, sizeof(MSG0200)); 0036.00 memset(msg_key, ' ', sizeof(msg_key)); 0037.00 memcpy(msg_type, "*FIRST ", 10); 0038.00 i = 0; 0039.00 while(1){/*while*/ 0040.00 memcpy(old_key, msg_key, 4); 0041.00 QMHRCVM((char*)&msg0200, sizeof(MSG0200), "RCVM0200", "QSYSOPR QSYS ", 0042.00 msg_type, msg_key, waittime, "*SAME ", &errcode); 0043.00 if(errcode.BYTESAVL != 0){/* APIERR */ 0044.00 ApiError("QMHRCVM", __LINE__, &errcode, "TESTOPR"); break; 0045.00 }/* APIERR */ 0046.00 memcpy(msg_key, msg0200.rcvm0200.Message_Key, 4); 0047.00 if(memcmp(msg0200.rcvm0200.Message_Key, old_key, 4) == 0) break; 0048.00 pos = msg0200.rcvm0200.Length_Data_Returned; 0049.00 len = msg0200.rcvm0200.Length_Message_Returned; 0050.00 memcpy(msg, &msg0200.Message[pos], len); 0051.00 msg[len] = 0x00; 0052.00 i ++; 0053.00 printf("[%d] %s\n", i, msg); 0054.00 memcpy(msg_type, "*NEXT ", 10); 0055.00 }/*while*/ 0056.00 getchar(); 0057.00 } 0058.00 /*********************************************************************/ 0059.00 void ApiError(char* place, int stmno, ERRSTRUCTURE* errcode, char* pgm) 0060.00 /*********************************************************************/ 0061.00 { 0062.00 char msgid[8], msgdta[101], Message[512]; 0063.00 int msglen, msgdtalen, pos; 0064.00 char* ptr; 0065.00 typedef struct { 0066.00 Qmh_Rtvm_RTVM0100_t rtvm0100; 0067.00 char msg[512]; 0068.00 } ERRMSG; 0069.00 ERRMSG errmsg; 0070.00 0071.00 memset(msgid, 0, sizeof(msgid)); 072.00 memcpy(msgid, errcode->MSGID, 7); 073.00 msgid[7] = 0x00; 074.00 if(msgid[0] == 0x00 || msgid[0] == ' '){/*msgid なし */ 075.00 perror("APIERROR"); 076.00 printf(" at %s, STMNO=%d\n", place, stmno); 077.00 getchar(); 078.00 return; 079.00 }/*msgid なし */ 080.00 memset(msgdta, 0, sizeof(msgdta)); 081.00 memcpy(msgdta, errcode->EXCPDATA, 100); 082.00 msgdta[100] = 0x00; 083.00 msglen = sizeof(ERRMSG); 084.00 msgdtalen = strlen(msgdta); 085.00 memset(&errmsg, 0, sizeof(ERRMSG)); 086.00 QMHRTVM(&errmsg, msglen, "RTVM0100", msgid, "QCPFMSG *LIBL ", 087.00 msgdta, msgdtalen, "*YES ", "*YES ", errcode); 088.00 memset(Message, 0, sizeof(Message)); 089.00 memcpy(Message, errmsg.msg, 512); 090.00 ptr = strstr(Message, "&N"); 091.00 if(ptr != NULL){ 092.00 pos = (int)(ptr - Message); 093.00 Message[pos] = 0x00; 094.00 } 095.00 printf("PGM-%s:APIERR %s-%s\n", pgm, msgid, Message); 0096.00 printf(" at %s, STMNO=%d\n", place, stmno); 0097.00 }
【 解説 】
最初は メッセージ・キー msg_key をブランクにセットしてメッセージ・タイプ msg_type を
*FIRST にセットしてから QMHRTVM によって最初のメッセージを受け取る。
2回目以降は取得したメッセージ・キーを指定すると同時に メッセージ・タイプを *NEXT に
セットして次のメッセージを受け取る。
ただし次のメッセージが見つからなかった場合でも同じメッセージが残ってしまうので
そのままでは 永久 LOOP してしまう。
old_key によって前のメッセージ・キーと変わりが無ければ LOOP を終了するようにしている。