www.sas.com > Service and Support > Technical Support
 
Technical Support SAS - The power to know(tm)
  TS Home | Intro to Services | News and Info | Contact TS | Site Map | FAQ | Feedback


/*---------------------------------------------------------------------+
|               Copyright (c) 1995, SAS Institute Inc.                 |
|                 Unpublished - All Rights Reserved                    |
|                      S A S / C   S A M P L E                         |
|                                                                      |
|                                                                      |
|         NAME: SASCBRW                                                |
|     LANGUAGE: C (CICS)                                               |
|      PURPOSE: Traditional CICS FILEA sample program used in          |
|                 Appendix 1, Second Edition, of the SAS/C CICS User's |
|                 Guide.  See this appendix for a more detailed        |
|                 explanation of the SASCALL, SASCMNU, SASCBRW samples |
|                 as well as the SASCAMA, SASCAMB, and SASCAMC BMS     |
|                 maps.                                                |
|   MVS -                                                              |
|      PREPROCESS, COMPILE, LINK: Submit prefix.SAMPLE.AUX(SASCBRW)    |
|                 where "prefix" is the installation defined           |
|                 high-level qualifier for the SAS/C product.          |
|      EXECUTE: See Appendix 1, Second Edition, of the SAS/C CICS      |
|                 User's Guide for additional information.  Use the    |
|                 sample PPT input (prefix.SAMPLE.AUX(SASCTBLS) to     |
|                 define the resources to CICS.                        |
|   TSO -                                                              |
|   PREPROCESS: LCCCP CLIST                                            |
|      COMPILE: LC370 CLIST using the RENT and EXTNAME options.        |
|         LINK: CLK370B CLIST using the CICS, and RENT options.        |
|      EXECUTE: see EXECUTE under MVS above                            |
|   CMS -                                                              |
|   PREPROCESS: LCCCP EXEC                                             |
|      COMPILE: LC370 EXEC using the RENT and EXTNAME options.         |
|        CLINK: CLINK EXEC using the CICS option; resulting object code|
|                 must be ported to an MVS operating system for final  |
|                 link-editing with the CICS Execution Interface stub  |
|                 routines.                                            |
|         LINK: Use the LCCCXXL cataloged procedure using the NOCLINK  |
|                 and RENT options.  Input must be specified via the   |
|                 SYSLIN DD statement, not the SYSIN DD statement.     |
|      EXECUTE: see EXECUTE under MVS above                            |
|                                                                      |
+---------------------------------------------------------------------*/
#include <dfhbmsca.h> /* Useful BMS definitions */
#include <sascaga.h>  /* C struct defining Map A, produced by DSECT2C*/
#include <sascagc.h>  /* C struct defining Map C, produced by DSECT2C*/
#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, used in backward paging */
char ridf[6] = "000000"; /* Record key, used in forward paging  */
char currop;             /* Indicates in which direction the    */
                         /* browsing is currently moving; F or B */
char lastop;             /* Indicates the previous browsing direction*/
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 */

/* The 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 */
void 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(i.e., 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();  /* Cause more records to be read */
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,'\0',SASCAGCE);  /* Clear map C */

memcpy(rid,ridb,6);
memcpy(ridf,ridb,6);

/* READPREV commands will re-read the last record that was */
/* read by a READNEXT command, so do an extra READPREV to  */
/* account for this behaviour                              */
if ((lastop == 'F') && (status != 'H'))
 {
  EXEC CICS READPREV DATASET("FILEA") INTO(&filea) RIDFLD(rid)
            LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));
 }

build_prev();  /* Cause more records to be read */
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. */
/* Keep in mind that the user could decide to press PF1 or PF2 at    */
/* anytime.  Pressing these keys is an implicit request for forward  */
/* or backward paging, respectivly.  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 'F'/'B' <ENTER>-key processing continues.                  */
void receive()
{
for(;;)   /* Continue to process page requests until CLEAR is pressed */
          /* or the user does not enter a direction indicator         */
 {
 lastop = currop;  /* Remember which direction the reading is going */

 /* Read the latest screen */
 EXEC CICS RECEIVE MAP("SASCAGC");
 /* When the MAPFAIL condition occurs here, the browse operation will*/
 /* end.  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 re-send the map */
         /* This will eventually result 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 past the end of the file */
/* is attempted.                                                */
void too_high()
{
status = 'H';  /* Set the status so that further reads are prevented */
memcpy(ridf,rid,6);
memcpy(ridb,rid,6);
sascagc.diro = ' '; /* Indicate that forward paging has ceased */
strcpy(sascagc.msg1o,"Hi-End of File"); /* Prepare an informative msg */
sascagc.msg1a= DFHBMASB;
}  /* end of too_high  */




/* This function is called when a read before the beginning of  */
/* the file is attempted.                                       */
void too_low()
{
status = 'L';  /* Set the status so that further reads are prevented */
strcpy(ridf,"000000");
strcpy(ridb,"000000");
sascagc.diro = ' '; /* Indicate that backward paging has ceased */
strcpy(sascagc.msg2o,"Lo-End of File"); /* Prepare an informative msg */
sascagc.msg2a = DFHBMASB;
}  /* end of too_high  */

/* 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();   /* 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();  /* 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();   /* no return from smnu() */
}  /* end of errors() */



/* This function causes the main menu to be displayed on the screen */
/* and returns control to CICS */
void smnu()
{
memset(&sascaga,'\0',SASCAGAE); /* Clear Map A */
sascaga.msga = DFHBMASB;
memcpy(sascaga.msgo,messages,strlen(messages)); /* Move the message */
                                                /* to the map       */
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 4 READNEXT commands to fill the  */
/* screen in a forward paging mode.                              */
void build_next()
{
int i;
for(i=1; i<= 4; i++)    /* 4 iterations to fill the screen  */
 {
  EXEC CICS READNEXT DATASET("FILEA") INTO(&filea) RIDFLD(rid)
            LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));

  if (status == 'H') /* If we read past the end of the file, STOP! */
   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:
     {
      /* 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:
     {
      /* 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:
     {
      /* 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 4 READPREV commands to fill the  */
/* screen in a backward paging mode.                             */
void build_prev()
{
int i;
for(i=1; i <= 4; i++)    /* 4 iterations to fill the screen  */
 {
  EXEC CICS READPREV DATASET("FILEA") INTO(&filea) RIDFLD(rid)
            LENGTH(sizeof(struct FILEA)) KEYLENGTH(sizeof(rid));

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

  switch(i)    /* The records will be displayed in ASCECNDING order */
   {           /* So, put the last one read at the top of the screen*/
    case 4:
     {
      /* 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:
     {
      /* 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:
     {
      /* 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() */

Copyright (c) 2000 SAS Institute Inc. All Rights Reserved.
Terms of Use & Legal Information | Privacy Statement