× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Thanks a lot Bob. Your code is pretty well documented and I am sure that I can learn a lot from it.

Thomas Raddatz.



Bob Cozzi schrieb:
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 thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

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.