|
Thomas Raddatz.
I'm not a system-state user, so I don't have any idea. But there are other on this list who may now how to change it to system state. But below is the 10-year old code. I'll look for the #includes that were unique to the old System/C language that IBM offered before ILE C came out. That's what I originally wrote it with.
-Bob Cozzi www.RPGxTools.com If everything is under control, you are going too slow. - Mario Andretti
/***********************************************************/ /* This program will retrieve the current description of */ /* the message ID or IDs from the specified message file. */ /* */ /* The input is: xxxxxxxxxxyyyyyyyyyy zzz9999 */ /* msgf msgflib msgid */ /* (c) 1994 by Robert Cozzi, Jr. -All rights reserved. */ /***********************************************************/
#include <stdlib.h> #include <string.h> #include <ctype.h>
#include <openapi.h>
#include <mimchobs.h> #include <micomput.h> #include <miindex.h> #include <miptrnam.h> #include <mispcobj.h> #include <mispace.h> #include <milib.h> /* #include <errutil.h> */
/* These includes contain the *MSGF object templetes */ #include "CRCTOOL/H/MSGFTMPL" /* Templates of current structure */ #include "CRCTOOL/H/RTNMSGFT" /* Return templates for *MSGF */ #include "CRCTOOL/H/WWVLDTBL" /* Validity checking table include */
/* Used by MATPTR for pointer type */ #define SYSPTR 0x01 #define SPCPTR 0x02 #define DTAPTR 0x03 #define INSPTR 0x04
/* Used by FNDINXEN for "rule" */ #define _EQUAL _FIND_EQUALS #define _EQ _FIND_EQUALS #define _GT _FIND_GREATER #define _LT _FIND_LESSER #define _GE _FIND_NOT_LESSER #define _LE _FIND_NOT_GREATER #define _FIRST _FIND_FIRST #define _LAST _FIND_LAST #define _BETWEEN _BETWEEN
#define _JOB -4 #define _JOBINT -2 #define _JOBDMP -1
#define MAXMSGS 1 /* Maximum number of message IDs to return */
#define DO { /* Beginning Bracket */ #define ENDDO } /* Ending bracket */ #define ENDIF } /* Ending bracket */ #define ENDELSE } /* Ending bracket */ #define ENDCASE } /* Ending bracket */ #define ENDFOR } /* Ending bracket */ #define ENDPGM } /* Ending bracket */
#define or | /* Bit-wise OR */ CLE0003W The character is not valid. #define and & /* Bit-wise AND */
#define OR || /* Logical inclusive OR */ CLE0003W The character is not valid. CLE0003W The character is not valid. #define AND && /* Redefine logical AND */ #define NE != /* Redefine Not Equal */ #define EQ == /* Redefine Equal operation */ #define GE >= /* Redefine Greater than or equal */ #define LE <= /* Redefine Less than or equal */ #define GT > /* Redefine Greater than */ #define LT < /* Redefine Less than */
#define RTVCTL -1 /* Value used to control retrieval process */
/*******************************************************/
/* This macro replace the character after the last */ /* non-blank character, with a null terminator. */
/* It simulates %TRIMR() in RPG IV but with a null. */
/*******************************************************/
#define addnull(p,cs) if ((p=strchr(cs,' ')) NE NULL) *p=0x00
/*******************/ /* *ENTRY PLIST */ /*******************/ struct entry_plist { char *pgmname; _RTN_MSG_Header_t *rcvdta; /* Retrieved message description */ int *rcvdtalen; /* Length of previous parameter */ char *format; /* Type of info to retrieve */ char *msgfname; /* Message file name */ char *msgid; /* Message ID to retrieve */ char *relid; /* Relative message ID */ } *epl;
int parms; /* Number of parameters passed to pgm */
/*****************************************/ /* Reply value validity checking table */ /*****************************************/ _WWVLDTBL_t *reply_table;
/********************************/ /* Simple conversion routine */ /********************************/ _Packed union tagBinary2 { short bin2; char char2[2]; } binary2;
/**************************************/ /* Non-specific declares begin here */ /**************************************/ char *ptr; short msgid_offset; short msgid_length; char msgid[MSGIDLEN+1];
short short_sev;
int offset = 0; int cnt, length, i, x, y, z;
int bytes_used = 0; /* Offset from start of return var */ int bytes_remain; /* Number of bytes remaining in */ /* the return variable. */ int rpyhdr; int reply_size; /* Number of bytes to be copied */ /* to the return variable. */ char type; unsigned int bitmask = 0;
/***********************************************/ /* "Work" fields to receive input parameters */ /***********************************************/ char msgf[11]; char msgflib[11]; char from_msgid[MSGIDLEN+1]; char to_msgid[MSGIDLEN+1]; char rule[10]; int field_cnt;
/********************************************/ /* Returned values "pointer to" variables */ /********************************************/ _RTN_Rpy_Offset_t reply; /* Reply values offset header */ _RTN_Text_Fmt_t *fstlvlrtn; /* 1st-level text format */ _RTN_Text_Fmt_t *seclvlrtn; /* 2nd-level text format */ _RTN_Dft_Rpy_t *dftrpy; /* Default reply value format */ _RTN_Spcval_t *specval; /* Special values list */ _RTN_Fields_t *fields; /* Message fields to return */ _RTN_Field_Fmt_t *msgfmt; /* Message data field format */ _RTN_Excp_Handler_t *excphdl; /* Exception handling routine */ _RTN_Alert_t *alert_option; /* Exception handling routine */ _RTN_Valid_Replies_t *valid; /* Validity checking table */
void cvtmsgfld(_RTN_Field_Fmt_t *, _MSG_Field_Struct_t *);
/*******************************************************/ /* M A I N F u n c t i o n B e g i n s H e r e */ /*******************************************************/
main(int argc, char *argv) {
_SYSPTR msgd; /* Points to message file object */ _SPCPTR msgdesc; /* Points to the message descript */ _MPTR_Template_T msgatr; /* MATPTR template */ _IIX_Opt_List_T *f; /* FNDINXEN-option list */ _MSG_Index_t *index; /* Index of current "key" */ char *indx_buf; /* Buffer to retrieve index into */ char *space; /* Pointer into MSGF's ASP */
int *rcvlen; /* Return variable length */ char *values; /* Offset to valid reply values */ _MSG_Text_t *fstlvl; /* Message 1st-level text */ _MSG_Text_t *seclvl; /* Message 2nd-level text */ _MSG_Fields_t *msgfld; /* Message fields */ _MSG_Field_Struct_t *msgfield; /* Internal msgdta field format */ _MSG_Rpy_List_t *replies; /* Message valid reply structure */ _MSG_Spcval_t *spcval; /* Message reply special values */ _MSG_Excp_Handler_t *dftpgm; /* Default program to call */ _MSG_Alert_t *alert; /* Alert table */
binary2.bin2 = 0;
epl=(struct entry_plist *) argv; /* Establish the parameter list */
parms = argc; /* Establish the number of parameters */
strncpy(msgf,epl->msgfname,10); strncpy(msgflib,epl->msgfname+10,10); strncpy(msgid,epl->msgid,MSGIDLEN);
if (parms >= 7) strncpy(rule,epl->relid,10); else strncpy(rule,"*SAME ",10);
/*******************************************************/ /* Since the RSLVSP requires null terminated strings, */ /* the ADDNULL macro is used to insert a null after */ /* the last non-blank character. */ /* For example, "*LIBL....." would be replace with */ /* "*LIBL\0...." (Where \0 denotes x'00' and .... */ /* denotes blanks.) */ /*******************************************************/ addnull(ptr,msgflib); addnull(ptr,msgf);
/*******************************************************/ /* A system pointer to the message file object is */ /* resolved. The _AUTH_ALL is used because, while */ /* I'm writing this, I don't have time to figure out */ /* the percise authority needed. */ /*******************************************************/ if (TrapErrors()) { msgd = rslvsp(_Msgf,msgf,msgflib,_AUTH_ALL);
/*******************************************************/ /* Using the point variable we just got, we resolve */ /* a pointer to the associated space of the message */ /* file. A C pointer is used here to allow easy */ /* manipulation of the message file's associated space*/ /*******************************************************/ space = (char *) setsppfp(msgd);
/*******************************************************/ /* Materialize the pointer to get the name of the */ /* message file and the library it is in. */ /*******************************************************/ if ( strcmp(msgflib,"*LIBL ")==0 OR strcmp(msgflib,"*LIBL")==0 ) { msgatr.Obj_Ptr.Template_Size = sizeof(_MPTR_Template_T); msgatr.Obj_Ptr.Ptr_Type = SYSPTR; matptr(&msgatr,msgd); memcpy(epl->rcvdta->sndmsgflib,msgatr.Sys_Ptr.Library_ID.Name,10); } else memcpy(epl->rcvdta->sndmsgflib,epl->msgfname+10,10);
} else { return; }
UnTrapErrors();
/*******************************************************/ /* Allocate enough storage (memory) to hold the */ /* number index entries that will be returned. */ /*******************************************************/ indx_buf = malloc(MAXMSGS*sizeof(_MSG_Index_t));
/*******************************************************/ /* Allocate enough storage (memory) to hold the */ /* number of index entry control templates that */ /* will be returned. */ /* Right now (12/21/90) only one template is used. */ /*******************************************************/ f = malloc(sizeof(_IIX_Opt_List_T)+(MAXMSGS*sizeof(_IIX_Entry_T)));
if (parms >= 6) { if (memcmp(msgid,"*FIRST ",MSGIDLEN)==0) f->Rule = _FIRST; else if (memcmp(msgid,"*LAST ",MSGIDLEN)==0) f->Rule = _LAST; else if (parms >= 7) { if (memcmp(rule,"*SAME ",10)==0) f->Rule = _EQUAL; else if (memcmp(rule," ",10)==0) f->Rule = _EQUAL; else if (memcmp(rule,"*EQ ",10)==0) f->Rule = _EQUAL; else if (memcmp(rule,"*EQUAL ",10)==0) f->Rule = _EQUAL; else if (memcmp(rule,"*EQUALS ",10)==0) f->Rule = _EQUAL; else if (memcmp(rule,"*NEXT ",10)==0) f->Rule = _GT; else if (memcmp(rule,"*GT ",10)==0) f->Rule = _GT;
else if (memcmp(rule,"*PRV ",10)==0) f->Rule = _LT; else if (memcmp(rule,"*LT ",10)==0) f->Rule = _LT; else if (memcmp(rule,"*GE ",10)==0) f->Rule = _GE; else if (memcmp(rule,"*LE ",10)==0) f->Rule = _LE; else if (memcmp(rule,"*FIRST ",10)==0) f->Rule = _FIRST; else if (memcmp(rule,"*LAST ",10)==0) f->Rule = _LAST; else f->Rule= _EQUAL; } else f->Rule= _EQUAL; } else f->Rule= _FIRST;
f->Occ_Count = MAXMSGS; /* Number of "keys" to get */ f->Arg_Length = MSGIDLEN; /* Length of "search" argument */
/*******************************************************/ /* Now go get the index entry--this is equal to the */ /* RPGIII CHAIN operation code. */ /*******************************************************/ fndinxen(indx_buf,msgd,f,msgid);
/*******************************************************/ /* If not "keys" were returned, then the CHAIN was */ /* unsuccessful. So, return blanks in the msgid. */ /*******************************************************/ if (f->Ret_Count==0) { memcpy(epl->rcvdta->msgid," ",MSGIDLEN); goto endpgm; }
/*******************************************************/ /* The offset to, and the length of the first index */ /* entry are copied to work-variables. */ /*******************************************************/ msgid_offset = f->Entry[0].Entry_Offset; msgid_length = f->Entry[0].Entry_Length;
/*******************************************************/ /* Set the pointer variable to point at the index */ /* of the message just "found". Since FNDINXEN will */ /* (optionally) return multiple values, the returned */ /* index "buffer" plus the offset are used to set */ /* the pointer to the specific index entry. */ /*******************************************************/ index = (_MSG_Index_t *) (indx_buf+msgid_offset);
/*******************************************************/ /* Copy the message ID retrieved to the return var. */ /*******************************************************/ memcpy(epl->rcvdta->msgid,index->msgid,7);
/*******************************************************/ /* If format(MSGD0100) is specified, then each and */ /* every message ID attribute is returned. */ /* This process initializes each control field to -1. */ /*******************************************************/ if (memcmp(epl->format,"MSGD0100",8)==0) { epl->rcvdta->fstlvl = RTVCTL; epl->rcvdta->seclvl = RTVCTL; epl->rcvdta->replies = RTVCTL; epl->rcvdta->msgfld = RTVCTL; epl->rcvdta->dftpgm = RTVCTL; epl->rcvdta->alert = RTVCTL; epl->rcvdta->pdpcode = RTVCTL; }
/*******************************************************/ /* Resolve is performed here so that the length of */ /* each data area can be check before the data is */ /* retrieved. If the data area is longer than the */ /* length of the "return data structure" then the */ /* specific message information is not retrieved. */ /*******************************************************/
if ((index->fstlvl > 0) AND (epl->rcvdta->fstlvl == RTVCTL)) fstlvl = ( _MSG_Text_t *) (space + index->fstlvl);
if ((index->seclvl > 0) AND (epl->rcvdta->seclvl == RTVCTL)) seclvl = ( _MSG_Text_t *) (space + index->seclvl);
if ((index->replies > 0) AND (epl->rcvdta->replies == RTVCTL)) replies = ( _MSG_Rpy_List_t *) (space + index->replies);
if ((index->msgfld > 0) AND (epl->rcvdta->msgfld == RTVCTL)) msgfld = ( _MSG_Fields_t *) (space + index->msgfld);
if ((index->pgmtocall > 0) AND (epl->rcvdta->dftpgm == RTVCTL)) dftpgm = ( _MSG_Excp_Handler_t *) (space + index->pgmtocall);
if ((index->alert > 0) AND (epl->rcvdta->alert == RTVCTL)) alert = ( _MSG_Alert_t *) (space + index->alert);
/*******************************************************/ /* Since the message severity is located in the */ /* message ID index entry, it is always returned. */ /*******************************************************/ epl->rcvdta->msgsev = index->msgsev;
/********************************************************/ /* Retrieve the return-variable's length so that we */ /* don't go passed the end-of-data. */ /********************************************************/ rcvlen = epl->rcvdtalen;
/********************************************************/ /* Use a pointer to address the return-variable */ /* (This should simplify access.) */ /********************************************************/ ptr = (char *) epl->rcvdta;
/********************************************************/ /* Set the "bytes used" to start at the returned-data */ /* area of the return variable. */ /********************************************************/ bytes_used = (sizeof(_RTN_MSG_Header_t)-1);
/*****************************************************/ /*****************************************************/ /************************ ************************/ /********************* *********************/ /****************** ******************/ /*************** ***************/ /************ ************/ /********* *********/ /****** ******/ /*** ***/ /** D A T A R E T R I E V A L R O U T I N E S **/ /*** ***/ /****** ******/ /********* *********/ /************ ************/ /*************** ***************/ /****************** ******************/ /********************* *********************/ /************************ ************************/ /*****************************************************/ /*****************************************************/
/*****************************************************/ /* F I R S T L E V E L M E S S A G E T E X T */ /*****************************************************/
if ((epl->rcvdta->fstlvl == RTVCTL) AND (index->fstlvl > 0))
if (bytes_used + (sizeof(_RTN_Text_Fmt_t)-1) < *rcvlen) {
/********************************************************/ /* Insert the offest to the first-level message text */ /********************************************************/ epl->rcvdta->fstlvl = bytes_used;
/********************************************************/ /* Calculate the number of bytes remaining in the */ /* return variable. To determine how many message */ /* text bytes can be returned. */ /********************************************************/ x = *rcvlen - bytes_used + (sizeof(_RTN_Text_Fmt_t)-1);
/********************************************************/ /* Return the shorter of the two values. */ /********************************************************/ if (x GT fstlvl->msglen) x = fstlvl->msglen;
/********************************************************/ /* Set a point within the return variable that is */ /* formated as the returned message text. */ /********************************************************/ fstlvlrtn = (_RTN_Text_Fmt_t *) (ptr+bytes_used);
/********************************************************/ /* Insert the returned length of the message text */ /* Insert the available (internal length) of the */ /* message text. */ /********************************************************/ fstlvlrtn->rtnlen = x; fstlvlrtn->avllen = fstlvl->msglen;
/********************************************************/ /* Copy the sizes to the return variable */ /* Then, copy the message text. Note that the */ /* message text is not first copied to the fstlvlrtn */ /* structure. This speeds things up a bit. */ /********************************************************/ memcpy(fstlvlrtn->msgtxt,fstlvl->msgtxt,x);
/***********************************************************/ /* Now, the number-of-bytes-used is incremented to */ /* include the message text being returned. */ /***********************************************************/ bytes_used += (sizeof(_RTN_Text_Fmt_t)-1) + x;
} /*** END of First-level Message Text ***/
/*******************************************************/ /* S E C O N D L E V E L M E S S A G E T E X T */ /*******************************************************/ if ((epl->rcvdta->seclvl == RTVCTL) AND (index->seclvl > 0)) if (bytes_used + (sizeof(_RTN_Text_Fmt_t)-1) < *rcvlen) {
/*********************************************************/ /* Insert the offset to the second-level message text */ /*********************************************************/ epl->rcvdta->seclvl = bytes_used;
/********************************************************/ /* Calculate the number of bytes remaining in the */ /* return variable. To determine how many message */ /* text bytes can be returned. */ /********************************************************/ x = *rcvlen - bytes_used + (sizeof(_RTN_Text_Fmt_t)-1);
/********************************************************/ /* Return the shorter of the two values. */ /********************************************************/ if (x GT seclvl->msglen) x=seclvl->msglen;
/********************************************************/ /* Set a point within the return variable that is */ /* formated as the returned message text. */ /********************************************************/ seclvlrtn = (_RTN_Text_Fmt_t *) (ptr+bytes_used);
/********************************************************/ /* Insert the returned length of the message text */ /* Insert the available (internal length) of the */ /* message text. */ /********************************************************/ seclvlrtn->rtnlen = x; seclvlrtn->avllen = seclvl->msglen;
/********************************************************/ /* Copy the sizes to the return variable */ /* Then, copy the message text. Note that the */ /* message text is not first copied to the seclvlfmt */ /* structure. This speeds things up a bit. */ /********************************************************/ memcpy(seclvlrtn->msgtxt,seclvl->msgtxt,x);
/***********************************************************/ /* Now, the number-of-bytes-used is incremented to */ /* include the message text being returned. */ /***********************************************************/ bytes_used += (sizeof(_RTN_Text_Fmt_t)-1) + x;
} /*** End of Second-Level Message Text ***/
/******************************/ /* R E P L Y V A L U E S */ /******************************/ if ((epl->rcvdta->replies == RTVCTL) AND (index->replies > 0)) {
/************************************************************/ /* R E P L Y V A L U E S : O F F S E T H E A D E R */ /************************************************************/
if ((replies->spcval > 0) OR (replies->vld_tbl > 0) OR (replies->dft_rpy_len > 0)) {
/*********************************************************/ /* Save the offset of the reply values in the receiver */ /* variable to be returned to the caller. */ /*********************************************************/ epl->rcvdta->replies = bytes_used; rpyhdr=bytes_used; /* Also save as shorter name for ease */
/********************************************************/ /* Point passed the reply values' offset header. */ /* This offset will be where the reply values begin. */ /********************************************************/ bytes_used += sizeof(_RTN_Rpy_Offset_t);
/**************************************************************/ /* +++++++++++++++++++++++++++ */ /* + R E P L Y V A L U E S + D E F A U L T R E P L Y */ /* +++++++++++++++++++++++++++ */ /**************************************************************/
/********************************************************/ /* If there are enough bytes available, go get the */ /* default reply. */ /********************************************************/ if ((replies->dft_rpy_len > 0) AND (bytes_used + replies->dft_rpy_len + sizeof(_RTN_Dft_Rpy_t)-1 < *rcvlen)) {
/****************************************************/ /* Set a point to the return variable, formatted */ /* list the default reply. */ /****************************************************/ dftrpy = (_RTN_Dft_Rpy_t *) (ptr + bytes_used);
/*********************************/ /* Set offset to default reply */ /*********************************/ reply.dftrpy = bytes_used;
/***************************************************/ /* Copy in the length of the default reply value */ /* to the return variable. */ /***************************************************/ x = *rcvlen - (bytes_used + replies->dft_rpy_len); x += (sizeof(_RTN_Dft_Rpy_t)-1);
/********************************************************/ /* Return the shorter of the two values. */ /********************************************************/ if (x GT replies->dft_rpy_len) x=replies->dft_rpy_len; else x -= (sizeof(_RTN_Dft_Rpy_t)-1);
dftrpy->rtnlen = x; dftrpy->avllen = replies->dft_rpy_len;
/********************************************************/ /* Copy in the default reply and its length. */ /********************************************************/ memcpy(dftrpy->dfttxt,replies->dft_rpy,x);
/********************************************************/ /* Add the length of the default-reply to bytes used. */ /********************************************************/ bytes_used += x + (sizeof(_RTN_Dft_Rpy_t)-1);
ENDIF /* End of default reply routine */
/********************************************************************/ /* +++++++++++++++++++++++++++ */ /* + R E P L Y V A L U E S + V A L I D I T Y C H E C K I N G */ /* +++++++++++++++++++++++++++ */ /********************************************************************/ if ((replies->vld_tbl > 0) AND ((bytes_used + sizeof(_RTN_Valid_Replies_t)-1) < *rcvlen)) {
/********************************************************/ /* Point at the reply validity checking table */ /********************************************************/ reply_table = (_WWVLDTBL_t *) (space + replies->vld_tbl);
reply.vldtbl = bytes_used;
/********************************************************/ /* Set target of the following copy statements to */ /* the return variable, but make the pointer think it */ /* is pointing at the validity structure. */ /********************************************************/ valid = (_RTN_Valid_Replies_t *) (ptr+bytes_used);
/********************************************************/ /* Maximum length of a valid reply. */ /********************************************************/ valid->length = reply_table->wcovfln; valid->digits = 0;
/********************************************************/ /* Determine the type of reply type and translate it */ /* to the command form. */ /********************************************************/
bitmask = reply_table->checkname;
switch (bitmask) { case _NUMERIC_vt: memcpy(valid->type,"*DEC ",10); valid->digits = reply_table->wcovnmln; break; case _DIGIT_vt: memcpy(valid->type,"*DEC ",10); valid->digits = reply_table->wcovnmln; break; case _ALPHA_vt: memcpy(valid->type,"*ALPHA ",10); break; case _NAME_vt: memcpy(valid->type,"*NAME ",10); break; case _ALPHA_NAME_vt: memcpy(valid->type,"*CHAR ",10); break; case _CHAR_vt: memcpy(valid->type,"*CHAR ",10); break; default: memcpy(valid->type,"*NONE ",10); ENDCASE
bitmask = reply_table->list_type;
/********************************************************/ /* Determine the validity checking type: VALUES, RANGE */ /* etc. and then insert the check routine name into */ /* the return variable. NOTE: For relationship */ /* checking, only the boolean operator is returned. */ /********************************************************/ switch (bitmask) { /********************************************************/ /* Since the length of the "values list" is dependent */ /* on which validity checking routine is performed, */ /* (not really, but the length is stored in several */ /* locations,) the length is copied, based on the */ /* type of validity checking being performed. */ /********************************************************/
case _RANGE_vt: memcpy(valid->check,"RANGE ",10); valid->len_values = reply_table->range_length; break; case _VALUES_vt: memcpy(valid->check,"VALUES ",10); valid->len_values = reply_table->values_length; break; case _GT_vt: memcpy(valid->check,"*GT ",10); valid->len_values = reply_table->rel_length; break; case _GE_vt: memcpy(valid->check,"*GE ",10); valid->len_values = reply_table->rel_length; break; case _EQ_vt: memcpy(valid->check,"*EQ ",10); valid->len_values = reply_table->rel_length; break; case _NE_vt: memcpy(valid->check,"*NE ",10); valid->len_values = reply_table->rel_length; break; case _LE_vt: memcpy(valid->check,"*LE ",10); valid->len_values = reply_table->rel_length; break; case _LT_vt: memcpy(valid->check,"*LT ",10); valid->len_values = reply_table->rel_length; break; default: memcpy(valid->check,"*NONE ",10); valid->len_values = 0; ENDCASE
valid->num_values = reply_table->num_values;
bytes_used += (sizeof(_RTN_Valid_Replies_t)-1);
/********************************************************* /* Now, if any valid replies (aka VALUES) exist, then */ /* copy them in, one by one. */ /*********************************************************
/********************************************************* /* Copy the valid replies to the return variable. */ /* The length of the reply is used, for the copy, */ /* while the offset or array element size is based */ /* on a fixed length (32-bytes at this writting). */ /* This compresses the returned values into elements */ /* no larger than the size of the reply value. */ /********************************************************/ if (replies->values > 0) { values = (char *) (space + replies->values); reply_size = valid->length; /* Use MAXLEN */ bitmask = reply_table->checkname; if ((bitmask == _NUMERIC_vt) OR (bitmask == _DIGIT_vt)) reply_size++; for (i = 0 ; i < valid->num_values; i++) { x = i * valid->len_values; memcpy(ptr+bytes_used,values+x,reply_size); bytes_used += reply_size; ENDFOR valid->len_values = reply_size; /* Use Repy size */ ENDIF
ENDIF /**** END of Validity Checking Table */
/**************************************************************/ /* R E P L Y V A L U E S : S P E C I A L V A L U E S */ /**************************************************************/
if ((replies->spcval > 0) AND ((bytes_used + sizeof(_RTN_Spcval_t)-1) <= *rcvlen)) {
/**********************************/ /* Set offset to special values */ /**********************************/ reply.spcval = bytes_used;
/***************************************************/ /* Set a pointer to the special values, within */ /* the message file object (space). */ /***************************************************/ spcval = (_MSG_Spcval_t *) (space + replies->spcval);
/***************************************************/ /* Set a "formatted" pointer within the return */ /* variable for the special values. */ /***************************************************/ specval = (_RTN_Spcval_t *) (ptr + bytes_used);
/***************************************************/ /* The length of each special value is fixed, as */ /* of this date. Should it change in the future, */ /* the named constant REPLY_SIZE should be */ /* adjusted to accommodate the new size. */ /* ------ */ /* The length of each special value and the */ /* number of special values is copied directly */ /* into the return varaible. No compression */ /* techniques are applied as of this writing. */ /***************************************************/ specval->num_spcval = spcval->num_spcval; specval->len_spcval = REPLY_SIZE;
/***************************************************/ /* Calculate the total size of spcval array. */ /* The number of special values is always twice */ /* the number of elements. */ /***************************************************/ reply_size = specval->num_spcval * 2 * specval->len_spcval;
/***************************************************/ /* Determine the number of bytes that remain */ /* available in the return variable. */ /***************************************************/ bytes_remain = *rcvlen - (bytes_used + reply_size);
/********************************************************/ /* Compare the bytes_available to the bytes to be used */ /* and return the shorter of the two values. */ /* NOTE: Be sure to also reduce the size of the */ /* bytes remaining by the length of the structure's */ /* prefix. */ /********************************************************/ if (reply_size GT bytes_remain) reply_size = bytes_remain-(sizeof(_RTN_Spcval_t)-1);
/********************************************************/ /* Copy the special values to the return variable. */ /********************************************************/ memcpy(specval->spcval,spcval->spcval,reply_size);
bytes_used += (sizeof(_RTN_Spcval_t)-1) + reply_size;
ENDIF /* END of Special Values */
/********************************************************/ /* Since we're done with the reply values, copy the */ /* reply value offset header to the return-variable. */ /********************************************************/ memcpy(ptr+rpyhdr,&reply,sizeof(_RTN_Rpy_Offset_t));
ENDIF /*** END of check for any reply values */
ENDIF /*** END of check for reply values request */
/************************************/ /* Message D A T A F I E L D S */ /************************************/ if ((epl->rcvdta->msgfld == RTVCTL) AND (index->msgfld > 0) AND (msgfld->fldcnt > 0))
/***************************************************/ /* If there is enough space left then go for it. */ /***************************************************/ if (((bytes_used + sizeof(_RTN_Field_Fmt_t)) < *rcvlen) AND (msgfld->fldcnt > 0)) {
/****************************************************/ /* Insert the offest to the message data fields. */ /****************************************************/ epl->rcvdta->msgfld = bytes_used; /* Insert current offset */
fields = (_RTN_Fields_t *) (ptr + bytes_used);
/****************************************************/ /* The number of message data fields is copied */ /* to the return-variable. */ /****************************************************/ fields->num_msgfields=msgfld->fldcnt;
bytes_used += 2; /* skip the field count */
/***********************************************************/ /* Allocate enough memory to contain the internal */ /* and external form of one message data field. */ /***********************************************************/ msgfield = malloc(sizeof(_MSG_Field_Struct_t)); msgfmt = malloc(sizeof(_RTN_Field_Fmt_t));
/***********************************************************/ /* Translate and copy each message data field to the */ /* return variable. The number of bytes remaining is */ /* checked after each copy, it insure that the return */ /* variable's size is not exceeded. */ /***********************************************************/ for (cnt=0; cnt < msgfld->fldcnt AND (bytes_used + sizeof(_RTN_Field_Fmt_t)) < *rcvlen ; cnt++) {
/***********************************************************/ /* First, the internal message data field description is */ /* moved into a structure/template for easy readability. */ /***********************************************************/ msgfield->msg_fld_type = msgfld->msg_fld[cnt][0]; msgfield->msg_fld_len = msgfld->msg_fld[cnt][2]; msgfield->msg_fld_digits = msgfld->msg_fld[cnt][1];
/***********************************************************/ /* Then the message data field is translated from the */ /* internal format to the external format that will be */ /* returned to the calling program. */ /***********************************************************/ cvtmsgfld(msgfmt,msgfield); memcpy(ptr+bytes_used,msgfmt,sizeof(_RTN_Field_Fmt_t));
/***********************************************************/ /* Now, the number-of-bytes-used is incremented to */ /* include the 20-some odd number of bytes used for */ /* the message data field. */ /***********************************************************/ bytes_used += sizeof(_RTN_Field_Fmt_t); } }
/***************************************************************/ /* Message E X C E P T I O N H A N D L I N G T A B L E */ /***************************************************************/ if ((epl->rcvdta->dftpgm == RTVCTL) AND (index->pgmtocall > 0))
if ((dftpgm->len + 9) > 0) {
/********************************************************/ /* Insert the offset to the exception handling data */ /********************************************************/ epl->rcvdta->dftpgm = bytes_used;
excphdl = (_RTN_Excp_Handler_t *) (ptr+bytes_used);
/********************************************************/ /* Translate, then copy the LOGPRB parameter. */ /********************************************************/ if (dftpgm->logsrv == 'Y') memcpy(excphdl->logsrv,"*YES ",10); else memcpy(excphdl->logsrv,"*NO ",10);
/********************************************************/ /* Copy the rest of the exception handling routing */ /********************************************************/ memcpy(excphdl->program,dftpgm->program,(dftpgm->len - 1));
/***********************************************************/ /* Update the bytes_used field. */ /***********************************************************/ bytes_used += dftpgm->len + 9;
/********************************************************/ /* E N D o f E X C E P T I O N H A N D L I N G */ /********************************************************/ ENDIF
/***************************************************/ /* Message A L E R T O P T I O N T A B L E */ /***************************************************/ if ((epl->rcvdta->alert == RTVCTL) AND (index->alert > 0))
if ( (bytes_used + sizeof(_RTN_Alert_t)) <= *rcvlen) {
/********************************************************/ /* Insert the offset to the alert option table */ /********************************************************/ epl->rcvdta->alert = bytes_used;
alert_option = (_RTN_Alert_t *) (ptr + bytes_used);
/********************************************************/ /* Translate the alert option to the command form */ /********************************************************/ switch (alert->type) { case 'I': memcpy(alert_option->type,"*IMMED ",10); break; case 'D': memcpy(alert_option->type,"*DEFER ",10); break; case 'U': memcpy(alert_option->type,"*UNATTEND ",10); break; default: memcpy(alert_option->type,"*IMMED ",10); }
alert_option->resource = alert->resource;
/***********************************************************/ /* Update the bytes_used field. */ /***********************************************************/ bytes_used += sizeof(_RTN_Alert_t);
/********************************************************/ /* E N D o f A L E R T O P T I O N T A B L E */ /********************************************************/ ENDIF
endpgm:
epl->rcvdta->bytes_rtn = bytes_used; /* Return bytes_used */
ENDPGM /************ END of the main C PROGRAM function ************/
/***********************************************/ /* F U N C T I O N S B E G I N H E R E */ /***********************************************/
/*************************************************************/ /* C O N V E R T M E S S A G E D A T A F I E L D S */ /*************************************************************/ void cvtmsgfld(_RTN_Field_Fmt_t *format,_MSG_Field_Struct_t *fmt) {
/**************************************/ /* Check High-bit for ON condition. */ /* If high-bit is ON, then the FMT */ /* message data field is *VARY. */ /**************************************/ type=fmt->msg_fld_type;
if ((type and 0x80)==0x80) { memcpy(format->msg_fld_vary,"*VARY ",10); type &= 0x7F; /* Set off "high" bit */ } else memcpy(format->msg_fld_vary," ",10);
/***************************************************************/ /* Zero out the message field length and decimal positions. */ /***************************************************************/ format->msg_len = 0; format->msg_digits = 0;
/*******************************************/ /* Translate the message data field type */ /* from the internal form to the command */ /* definition form. e.g., x'44' -> *CHAR */ /* NOTE: The high-bit will have been */ /* stripped away by this point. */ /*******************************************/ switch (type) { case _QTDChar: memcpy(format->msg_fld,_QTDCHAR ,10); break; case _Char: memcpy(format->msg_fld,_CHAR ,10); break; case _Dec: memcpy(format->msg_fld,_DEC ,10); break; case _Hex: memcpy(format->msg_fld,_HEX ,10); break; case _Bin: memcpy(format->msg_fld,_BIN ,10); break; case _Spp: memcpy(format->msg_fld,_SPP ,10); break; case _Dts: memcpy(format->msg_fld,_DTS ,10); break; case _Syp: memcpy(format->msg_fld,_SYP ,10); break; case _Itv: memcpy(format->msg_fld,_ITV ,10); break; }
/************************************************************/ /* Now, copy the message data field length and decimal */ /* positions into Bin(2) numbers. They are stored in the */ /* traditional form: union { short, char[2] } */ /************************************************************/ if (type == _Dec) { binary2.char2[1] = fmt->msg_fld_len; format->msg_len = binary2.bin2; binary2.char2[1] = fmt->msg_fld_digits; format->msg_digits = binary2.bin2; } else { binary2.char2[0] = fmt->msg_fld_digits; binary2.char2[1] = fmt->msg_fld_len; format->msg_len = binary2.bin2; format->msg_digits = 0; }
}
_______________________________________________ This is the MI Programming on the AS400 / iSeries (MI400) mailing list To post a message email: MI400@xxxxxxxxxxxx To subscribe, unsubscribe, or change list options, visit: http://lists.midrange.com/mailman/listinfo/mi400 or email: MI400-request@xxxxxxxxxxxx Before posting, please take a moment to review the archives at http://archive.midrange.com/mi400.
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.