Chapter Contents

Previous

Next
Examples

SASCBRW: Perform Browse Function

The SASCBRW program corresponds to the IBM programs DFH$xBRW (where x has the same values as mentioned earlier). It is the program that does the browse operation. It will start with the first record, or you can specify a starting place. The program can page forward and backward through the file.

#include <dfhbmsca.h> /* useful BMS definitions */

   /* C struct defining Map A, produced by DSECT2C */
#include <sascaga.h>

   /* C struct defining Map C, produced by DSECT2C */
#include <sascagc.h>
#include <ctype.h>    /* standard C type header */
#include <string.h>   /* standard C string handling header */

   /* general-purpose variables */
short i;
char rid[6] = "000000";  /* record key, the account number */
char ridb[6] = "000000"; /* record key, for backward paging */
char ridf[6] = "000000"; /* record key, for forward paging */

   /* indicates in which direction the browsing */
   /* is currently moving: F or B               */
char currop;

   /* indicates the previous browsing direction */
char lastop;
char status;             /* file status: 'H', 'L', or ' ' */
char messages[39];       /* message holding area */
short comlen;            /* length of CICS commarea */
char keynum[6];          /* record key, the account number */

   /* FILEA record layout */
struct FILEA{
   char stat;
   char numb[6];
   char name[20];
   char addrx[20];
   char phone[8];
   char datex[8];
   char amount[8];
   char comment[9];
} filea;

   /* function prototypes */
void errors(void);
void smnu(void);
void smsg(void);
void not_found(void);
void build_next(void);
void build_prev(void);
void page_forward(void);
void page_backward(void);
void receive(void);
void too_high(void);
void too_low(void);

   /* The main function begins here. */
main()
{

      /* Prepare to handle paging requests via PF keys. */
   EXEC CICS HANDLE AID CLEAR(smsg)
                        PF1(page_forward)
                        PF2(page_backward);

      /* Prepare to handle error conditions. */
   EXEC CICS HANDLE CONDITION ERROR(errors)
                              MAPFAIL(smsg)
                              NOTFND(not_found);

      /* Read the initial screen. */
   EXEC CICS RECEIVE MAP("SASCAGA");

      /* Was a starting account number provided? */
   if (memcmp(sascaga.keyl,"\0 \0",2) == 0){

         /* No, so default to zero. */
      strcpy(rid,"000000");
      strcpy(ridf,"000000");
   }
   else{
         /* Yes, so validate all of its digits. */
      for(i=0;i<=5;i++){
         if (isdigit((int) sascaga.KEYI[i]) == 0){
            strcpy(messages,"ACCOUNT NUMBER MUST BE NUMERIC");
            smnu();    /* There is no return from smnu(). */
         }
      }

         /* Save the starting account number for */
         /* use in either direction.             */
      memcpy(rid,sascaga.keyi,6);
      memcpy(ridf,sascaga.keyi,6);
      memcpy(ridb,sascaga.keyi,6);
   }

      /* Initiate the VSAM browse file operation. */
   EXEC CICS STARTBR DATASET("FILEA") RIDFLD(rid);

      /* Is the current account number 999999 */
      /* (the absolute maximum)?              */
   if (memcmp(rid,"999999",6) != 0){

         /* No, so page forward. */
      page_forward();
   }
   else{

         /* Yes, so set the status to HIGH and page backward. */
      status = 'H';
      page_backward();
   }
receive();    /* There is no return from receive(). */
}             /* end of main function */

   /* This function processes a forward paging request. */
void page_forward()
{
currop = 'F'; /* Set the indicator to forward paging mode. */

   /* Prepare to handle reading past the end of the file. */
EXEC CICS HANDLE CONDITION ENDFILE(too_high);

memset(&sascagc,'\0',SASCAGCE);   /* Clear Map C. */
memcpy(rid,ridf,6);
build_next();                     /* Read more records. */
memcpy(ridf,rid,6);

EXEC CICS SEND MAP("SASCAGC") ERASE; /* Display Map C. */
}                            /* end of page_forward function  */

   /* This function processes a backward paging request. */
void page_backward()
{
currop = 'B';   /* Set the indicator to backward paging mode. */

   /* Prepare to handle reading before the beginning of the file. */
EXEC CICS HANDLE CONDITION ENDFILE(too_low);

memset(&sascagc,',SASCAGCE);          /* Clear Map C. */
memcpy(rid,ridb,6);
memcpy(ridf,ridb,6);

   /* READPREV commands will reread the last record read by a    */
   /* READNEXT command, so perform an extra READPREV to account  */
   /* for this behavior.                                         */
if ((lastop == 'F') && (status != 'H')){
   EXEC CICS READPREV DATASET("FILEA") INTO(&filea) RIDFLD(rid)
             LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));
}
build_prev();                        /* Read more records. */
memcpy(ridb,rid,6);

EXEC CICS SEND MAP("SASCAGC") ERASE; /* Display Map C. */
}                               /* end of page_backward function */

   /* This function controls the continual processing of     */
   /* page requests. Remember that the user can decide to    */
   /* press PF1 or PF2 at any time. Pressing these keys      */
   /* is an implicit request for forward or backward paging, */
   /* respectively. When a PF key is pressed, the            */
   /* appropriate function is driven; then control           */
   /* returns to the next executable statement within the    */
   /* for(;;) loop. From that point, normal FORWARD/BACKWARD */
   /* <ENTER> key processing continues.                      */
void receive()
{
   /* Continue to process page requests until the CLEAR key is   */
   /* pressed or the user does not enter a direction indicator.  */
for(;;){

      /* Remember which direction the reading is going. */
   lastop = currop;

      /* Read the latest screen. */
   EXEC CICS RECEIVE MAP("SASCAGC");

      /* When the MAPFAIL condition occurs here, the browse */
      /* operation ends, and  smsg() will be driven.        */
   status = ' ';

      /* Did the user enter a forward page request by keying an F ? */
   if (memcmp(sascagc.diri,"F",1) == 0){

         /* Yes, so cause forward paging to occur. */
      page_forward();
   }

      /* Did the user enter a backward page request by keying a B ? */
   else
      if (memcmp(sascagc.diri,"B",1) == 0){

            /* Yes, so cause backward paging to occur. */
         page_backward();
      }
      else{

            /* Neither F nor B was keyed, so resend the map. This */
            /* eventually results in a MAPFAIL condition and,     */
            /* therefore, the end of the browse operation.        */
         EXEC CICS SEND MAP("SASCAGC");
      }
   }                   /* end of for(;;) loop */
}                      /* end of receive() */


   /* This function is called when a read is attempted past */
   /* the end of file.                                      */
void too_high()
{
      /* Set status so that further reads are prevented. */
   status = 'H';
   memcpy(ridf,rid,6);
   memcpy(ridb,rid,6);

      /* Indicate that forward paging has ceased. */
   sascagc.diro = ' ';

      /* Prepare an informative message. */
   strcpy(sascagc.msg1o,"Hi-End of File");
   sascagc.msg1a= DFHBMASB;
}                      /* end of too_high() */

   /* This function is called when a read is attempted */
   /* before the beginning of the file.                */
void too_low()
{
      /* Set status so that further reads are prevented. */
   status = 'L';
   strcpy(ridf,"000000");
   strcpy(ridb,"000000");

      /* Indicate that backward paging has ceased. */
   sascagc.diro = ' ';

      /* Prepare an informative message. */
   strcpy(sascagc.msg2o,"Lo-End of File");
   sascagc.msg2a = DFHBMASB;
}                      /* end of too_low */

   /* This function is called when the specified starting       */
   /* account number is not found.  The VSAM browse             */
   /* operation is ended and appropriate messages are prepared. */
void not_found()
{
   strcpy(messages,"End of File - Please Restart");

   EXEC CICS ENDBR DATASET("FILEA");

   smnu();             /* There is no return from smnu() */
}                      /* end of not_found() */

   /* This function prepares an informative */
   /* message and calls smnu().             */
void smsg()
{
   strcpy(messages,"Press CLEAR to Exit");
   smnu();             /* There is no return from smnu(). */
}                      /* end of smsg() */

   /* This function is called when a severe and   */
   /* unrecoverable error is detected.  It        */
   /* causes a CICS transaction dump to be taken, */
   /* and prepares an error message.              */
void errors()
{
   EXEC CICS DUMP DUMPCODE("ERRS");

   strcpy(messages,"Transaction Terminated");
   smnu();             /* There is no return from smnu(). */
}                      /* end of errors() */

/* This function displays the main menu on */
   /* the screen and returns control to CICS. */
void smnu()
{    memset(&sascaga,'\0',SASCAGAE);    /* Clear Map A. */
     sascaga.msga = DFHBMASB;        /* Move the message to the map. */
     memcpy(sascaga.msgo,messages,strlen(messages));
     memset(messages,'\0',39);  /* Clear the message variable. */

     EXEC CICS SEND MAP("SASCAGA") ERASE;

     EXEC CICS RETURN;
 }
                           /* end of smnu() */

   /* This function performs up to four READNEXT            */
   /* commands to fill the screen in a forward paging mode. */
void build_next()
0
    int i;
        /* It takes four iterations to fill the screen. */
    for(i=1; i<= 4; i++){
        EXEC CICS READNEXT DATASET("FILEA") INTO(&filea) RIDFLD(rid)
                  LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));
           /* If you read past the end of the file, STOP. */
        if (status == 'H')
           break;
        switch(i){
        case 1:{ 
             /* Move the record fields to line 1 of the map. */
           memcpy(sascagc.number1o,filea.numb,sizeof(filea.numb));
           memcpy(sascagc.name1o,filea.name,sizeof(filea.name));
           memcpy(sascagc.amount1o,filea.amount,sizeof(filea.amount));
           memcpy(ridb,rid,6);
           break; 
        }
                          /* end of case: 1 */
        case 2:0
              /* Move the record fields to line 2 of the map. */
           memcpy(sascagc.number2o,filea.numb,sizeof(filea.numb));
           memcpy(sascagc.name2o,filea.name,sizeof(filea.name));
           memcpy(sascagc.amount2o,filea.amount,sizeof(filea.amount));
           break;
        }                 /* end of case: 2 */

        case 3:0
            /* Move the record fields to line 3 of the map. */
          memcpy(sascagc.number3o,filea.numb,sizeof(filea.numb));
          memcpy(sascagc.name3o,filea.name,sizeof(filea.name));
          memcpy(sascagc.amount3o,filea.amount,sizeof(filea.amount));
          break;
       }                 /* end of case: 3 */
       case 4:0
            /* Move the record fields to line 4 of the map. */
          memcpy(sascagc.number4o,filea.numb,sizeof(filea.numb));
          memcpy(sascagc.name4o,filea.name,sizeof(filea.name));
          memcpy(sascagc.amount4o,filea.amount,sizeof(filea.amount));
          break;
       }                 /* end of case: 4 */
    }                    /* end of switch(i) *
    }                    /* end of for loop */ }
 }                       /* end of build_next() */


   /* This function performs up to four READPREV commands  */
   /* to fill the  screen in a backward paging mode.       */
void build_prev()
0
    int i;

        /* It takes 4 iterations to fill the screen. */
    for(i=1; i <= 4; i++)0
       EXEC CICS READPREV DATASET("FILEA") INTO(&filea) RIDFLD(rid)
                 LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));

           /* If we read before the beginning of the file, STOP. */
       if (status == 'L')
           break;

           /* The records will be displayed in ascending order,  */
          /* so put the last one read at the top of the screen. */
       switch(i)0
          case 4:0
                /* Move the record fields to line 1 of the map. */
             memcpy(sascagc.number1o,filea.numb,sizeof(filea.numb));
             memcpy(sascagc.name1o,filea.name,sizeof(filea.name));
             memcpy(sascagc.amount1o,filea.amount,sizeof(filea.amount));
             break;
           }             /* end of case: 4 */
           case 3:0
                /* Move the record fields to line 2 of the map. */
             memcpy(sascagc.number2o,filea.numb,sizeof(filea.numb));
             memcpy(sascagc.name2o,filea.name,sizeof(filea.name));
             memcpy(sascagc.amount2o,filea.amount,sizeof(filea.amount));
             break;
          }              /* end of case: 3 */
           case 2:0
                /* Move the record fields to line 3 of the map. */
             memcpy(sascagc.number3o,filea.numb,sizeof(filea.numb));
             memcpy(sascagc.name3o,filea.name,sizeof(filea.name));
             memcpy(sascagc.amount3o,filea.amount,sizeof(filea.amount));
             break;
          }
              /* end of case: 2 */

          case 1:{
               /* Move the record fields to line 4 of the map. */
            memcpy(sascagc.number4o,filea.numb,sizeof(filea.numb));
            memcpy(sascagc.name4o,filea.name,sizeof(filea.name));
            memcpy(sascagc.amount4o,filea.amount,sizeof(filea.amount));
            break;

         }              /* end of case: 1 */
      }                 /* end of switch(i) */
   }                    /* end of for loop */
}                       /* end of build_prev() */


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.