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) 1996, SAS Institute Inc.              |
|                  Unpublished - All Rights Reserved                 |
|                      S A S / C   S A M P L E                       |
|                                                                    |
|         NAME: DESCRIBE                                             |
|     LANGUAGE: C                                                    |
|      PURPOSE: This program demonstrates the use of the SAS/C FSSL. |
|               Specifically, this routine allows a dataset name to  |
|               be entered.  Upon entry it will provide misc infor-  |
|               mation on the dataset.  At the user request it will  |
|               also allow a detailed description about the dataset  |
|               to be entered.  The description is stored in a       |
|               master "DSINFO" file.  When the dataset name is      |
|               entered this file is searched for an old description.|
| SYSTEM NOTES: This routine will run on either CMS or TSO           |
|                                                                    |
|   MVS -                                                            |
| COMPILE/LINK: SUBMIT prefix.SAMPLE.AUX(DESCRIBE)                   |
|               where "prefix" is the installation defined high-level|
|               qualifier for the SAS/C product.                     |
|      EXECUTE: execute under TSO, see below                         |
|   TSO -                                                            |
|      COMPILE: LC370 CLIST                                          |
|         LINK: CLK370 CLIST                                         |
|      EXECUTE: CALL your.load.lib(DESCRIBE)                         |
|               At compile time the decision is made (by preprocessor|
|               control) whether to generate OS or CMS specific code.|
|   CMS -                                                            |
|      COMPILE: GLOBAL MACLIB LC370 L$FSSL                           |
|               LC370 DESCRIBE                                       |
|         LINK: GLOBAL TXTLIB LC370BAS LC370STD L$FSSL               |
|               CLINK DESCRIBE (GENMOD                               |
|      EXECUTE: DESCRIBE                                             |
|                                                                    |
|   MISC NOTES: SAS/C FSSL must be installed.                        |
|               If running in OS, dataset names must be entered in   |
|               fully qualified format.                              |
|          ---> The master "DSINFO" file must be preallocated.  The  |
|               only requirement is that the RECFM=FBS.              |
|                                                                    |
+-------------------------------------------------------------------*/

#include <lcio.h>
#if defined(OSVS)                      /* choose OS or CMS          */
   #include <os.h>
#elif defined(CMS)
   #include <cmsstat.h>
#endif
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <l$fappl.h>

#define  TRUE           1
#define  FALSE          0
#define  MAX_DSN       45
#define  DSN         1000
#define  DSCRNO      1001

 struct   FS_TERMATTR     * scr_attr;
 struct   FS_READPAN        input;
 struct   FS_READSCR        screen;
 FILE   * dsnfp;
 char   * info = "panel1";
 char     errmsg(|132|);
 char     xline(|80|);
 char     status(|51|);
 long     oldpos;
 int      fldno = 10000;
 int      dsnattr, xlen, row, col;
 /* dataset description structure */
 struct dscrp {
    char     dsn(|MAX_DSN+2|);
    char     lrecl(|6|);
    char     blksize(|6|);
    char     recfm(|6|);
    char     descript(|10|)(|61|);
    time_t   time;
    char     userid(|L_cuserid+1|);
 } dsinfo;


/*-------------------------------------------------------------------+
| The main will request that the screen definitions are set up,      |
|  display the screen and wait for input.  When input has been       |
|  entered, it will decide what to do.  Possible decisions are:      |
|     (1) terminate program, or                                      |
|     (2) edit dataset description, or                               |
|     (3) enter dataset name                                         |
+-------------------------------------------------------------------*/
main()
{
 int      rc;

   /* make the screen ready */
   define_screen();

   /* open dataset description file */
   save_descrp(0);

   /* continue while user wants to... */
   /*  after each input check the user's response; */
   /*  this response can be either PFkeys or data (enter key) */
   while (TRUE) {

      /* display panel */
      strcpy(status, "PF 3/15 - END, PF 12/24 - Edit Description");
      rc = fsdspn(info, 0, 1, 1, DSN, 1, FS_FORCE);
      if (rc != FS_OK && rc != FS_DFLTVIEW) {
         fsterm();
         printf("ERROR: panel display failure\n");
         exit(EXIT_FAILURE);
       }

      /* wait for input from user */
      screen = fsrdsc();

      /* check for 'the end' */
      if ( (screen.aid == PF_3) || (screen.aid == PF_15) ) {
         fsterm();
         fclose(dsnfp);
         return(0);
       }

      /* check for request of dataset description entry */
      else if ( (screen.aid == PF_12) || (screen.aid == PF_24) ) {
         if (dsn_dscrp())
            save_descrp(1);
         continue;
       }

      /* not a PF key...read fields */
      input = fsrdpn(info);

      /* get dataset characteristics and old description */
      if (dsn_info())
         save_descrp(-1);

    }

}


/*-------------------------------------------------------------------+
| This routine will obtain the characteristics about the dataset     |
|  name entered by the user.  The name must be in its fully qualified|
|  format.                                                           |
+-------------------------------------------------------------------*/
dsn_info()
 {
 #if defined(CMS)                     /* used only in CMS           */
    struct cmsstat cmsinfo;
 #elif defined(OSVS)                  /* used only in OS            */
    char     alloc(|80|);
 #endif
 int      rc, i, lreclp, blkszp;
 char     recfmp;

   /* did user modify any field? */
   if (input.count) {

      /* check for null entry */
      /*  if so then tell user of the error */
      if (strlen(dsinfo.dsn) == 0) {
         strcpy(status, "INVALID ENTRY - REENTER");
         fsuppn(info, 0, 1, 1, DSN, 1, FS_FORCE);
         sleep(5);
         return(FALSE);
       }

      /* TSO? */
      /* compile OS dependent code iff in OS environment */
      #if defined(OSVS)

         /* allow no embedded blanks in dataset name */
         for (i=0; iprim_row - 14;

   /* tell user what this half of the screen is for */
   attr2 = PROTECTED;
   color = RED;
   col = 20;
   fsdffd(info, n++, row, col, 25, "Enter Dataset Description",
          &attr2, color, BLANK);
   row += 2;

   /* get modifier user's id */
   color = GREEN;
   cuserid(dsinfo.userid);
   col = 5;
   fsdffd(info, n++, row, col, L_cuserid, dsinfo.userid,
          &attr2, color, BLANK);

   /* get modifier user's time */
   time(&dsinfo.time);
   col += L_cuserid + 10;
   fsdffd(info, n++, row, col, 25, ctime(&dsinfo.time),
          &attr2, color, BLANK);

   /* display all description entries */
   row++;
   col = 10;
   attr  = REVERSE_VIDEO | BRIGHT | AUTOREAD | MUST_ENTER;
   color = GREEN;
   for (i=0; i<10; i++) {
      row++;
      fsdffd(info, n++, row, col, 60, dsinfo.descript(|i|),
             &attr, color, BLANK);
    }

   /* give the user some info */
   color = YELLOW;
   row++;
   col = 20;
   fsdffd(info, n++, row, col, 26, "Any PF key terminates edit",
          &attr2, color, BLANK);

   /* display new screen */
   fsdspn(info, 0, 1, 1, DSN, 1, FS_FORCE);

   /* allow input */
   screen = fsrdsc();

   /* store input */
   input = fsrdpn(info);

   /* check for no mod */
   if (screen.aid == ENTER_KEY) rc = TRUE;
   else rc = FALSE;     /* no mod if any PFkey pressed */

   /* ok...restore screen */
   fsrmfd(info, DSN);
   dsnattr = BRIGHT | AUTOREAD | MUST_ENTER;
   color   = BLUE;
   fsdffd(info, DSN, 3, 25, MAX_DSN, dsinfo.dsn,
          &dsnattr, color, NULL);

   /* remove description fields */
   n = DSCRNO;
   for (i=0; i<14; i++) {
      fsrmfd(info, n++);
    }

 return(rc);
 }


/*-------------------------------------------------------------------+
| This routine creates the full screen image.  It sets up the full   |
|  screen environment, defines the panel, defines all the fields,    |
|  and other misc fs needs.                                          |
+-------------------------------------------------------------------*/
define_screen()
 {
 int     rc;
 static int color, color2, attr;

   /* get FS mode up */
   if ((rc = fsinit(errmsg)) != FS_OK) {
      fsterm();
      printf("ERROR: initialization failure\n");
      exit(EXIT_FAILURE);
    }

   /* get screen attribute capability */
   if ((int)(scr_attr = fsrttm()) == FS_INITERR) {
      fsterm();
      printf("ERROR: terminal read failure\n");
      exit(EXIT_FAILURE);
    }

   /* set line separator */
   memset(xline, '-', scr_attr->prim_col-1);
   xline(|scr_attr->prim_col|) = '\0';
   xlen = strlen(xline);

   /* define panel size */
   if ((rc = fsdfpn(info, scr_attr->prim_row, scr_attr->prim_col))
       != FS_OK) {
      fsterm();
      printf("ERROR: panel definition failure\n");
      exit(EXIT_FAILURE);
    }

   /* display title */
   row = 1;
   title(info, "Dataset Description", row);

   /* allow users to enter dataset name */
   row += 2;
   col  = 5;
   attr  = BRIGHT | PROTECTED;
   color = WHITE;
   fsdffd(info, fldno++, row, col, 19, "Enter Dataset Name:",
          &attr, color, BLANK);
   col += 20;
   dsnattr = BRIGHT | AUTOREAD | MUST_ENTER;
   color   = BLUE;
   fsdffd(info, DSN, row, col, MAX_DSN, dsinfo.dsn,
          &dsnattr, color, NULL);

   /* create fields for dataset characteristics...recfm */
   /*  note: this field will be the internal hex value for the recfm */
   row += 2;
   col = 5;
   color = WHITE;
   fsdffd(info, fldno++, row, col, 6, "RECFM:",
          &attr, color, BLANK);
   col += 7;
   color2 = GREEN;
   fsdffd(info, fldno++, row, col, 2, dsinfo.recfm,
          &attr, color2, BLANK);

   /* ...lrecl */
   col += 11;
   fsdffd(info, fldno++, row, col, 6, "LRECL:",
          &attr, color, BLANK);
   col += 7;
   fsdffd(info, fldno++, row, col, 5, dsinfo.lrecl,
          &attr, color2, BLANK);

   /* ...blksize */
   col += 11;
   fsdffd(info, fldno++, row, col, 8, "BLKSIZE:",
          &attr, color, BLANK);
   col += 9;
   fsdffd(info, fldno++, row, col, 5, dsinfo.blksize,
          &attr, color2, BLANK);

   /* create field for messages */
   row += 2;
   col  = 15;
   attr  = BRIGHT | PROTECTED;
   color = YELLOW;
   fsdffd(info, fldno++, row, col, 50, status,
          &attr, color, BLANK);

   /* separate screen...visible effect only */
   row++;
   color = RED;
   fsdffd(info, fldno++, row, 2, xlen, xline, &attr, color, BLANK);

 return(0);
 }


/*-------------------------------------------------------------------+
| The title routine will create a title across the screen.           |
+-------------------------------------------------------------------*/
title(panel, ttl, row)
 char  *panel;
 char  *ttl;
 int    row;
 {
  char  *work;
  int    bg, len;
  static int attr = PROTECTED | BRIGHT;
  static int color = CYAN;

   /* create the title as ----- title ----- */
   work = malloc((scr_attr->prim_col+3));
   memset(work, '-', scr_attr->prim_col);
   *(work+scr_attr->prim_col) = '\0';
   len = strlen(ttl);
   bg = (scr_attr->prim_col / 2) - (len / 2);
   memcpy(work+bg-2, "  ", 2);
   memcpy(work+bg, ttl, len);
   memcpy(work+bg+len, "  ", 2);

   /* display title */
   fsdffd(panel, fldno++, row, 2, scr_attr->prim_col-1, work,
          &attr, color, BLANK);

 return(0);
 }


/*-------------------------------------------------------------------+
| This routine will handle all requests for I/O for the dataset      |
|  description info.  Requests are:                                  |
|     -1 = read request                                              |
|      0 = open request                                              |
|      1 = write request                                             |
| Note: The I/O method used is a simple brute force search and is    |
|       not intended to show good/effecient I/O.                     |
+-------------------------------------------------------------------*/
save_descrp(type)
 int type;
 {
  struct dscrp oldinfo;
  int rc, i;

   /* open request */
   if (type == 0) {
      quiet(TRUE);
      dsnfp = fopen("DSINFO", "rb+");
      if (dsnfp == NULL) dsnfp = fopen("DSINFO", "wb+");
      if (dsnfp == NULL) {
         printf("ERROR: open failure on DSINFO\n");
         exit(EXIT_FAILURE);
       }
      quiet(FALSE);
      oldpos = -1;
    }

   /* read request */
   else if (type == -1) {

      /* start search...search in a straight brute force way */
      rewind(dsnfp);

      /* ok, search */
      while (TRUE) {
         oldpos = ftell(dsnfp);
         quiet(TRUE);
         rc = fread((char*)&oldinfo, sizeof(oldinfo), 1, dsnfp);
         quiet(FALSE);
         if (rc == 0) {
            oldpos = -1;
            clearerr(dsnfp);
            return(FALSE);
          }

         /* check if dsn read is one requested */
         if (!memcmp(oldinfo.dsn, dsinfo.dsn, strlen(dsinfo.dsn))) {
            /* found it...copy description */
            for (i=0; i<10; i++)
               strcpy(dsinfo.descript(|i|), oldinfo.descript(|i|));
            break;
          }
       }
    }

   /* write request */
   else {

      /* go directly to old position in dataset, or eof */
      if (oldpos < 0)
         fseek(dsnfp, 0, SEEK_END);
      else
         fseek(dsnfp, oldpos, SEEK_SET);

      /* write */
      fwrite((char*)&dsinfo, sizeof(dsinfo), 1, dsnfp);

    }

 return(TRUE);
 }


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