弊社のスタッフのための参考として 操作員メッセージ(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 を終了するようにしている。