|
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;
}
}
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2025 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.