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: SVC99                                                  |
|     LANGUAGE: C                                                      |
|      PURPOSE: Demonstrate how to call SVC 99 from within a SAS/C     |
|               application.                                           |
|        NOTES: SVC99 is a collection of sub-routines. SVC99C is a     |
|               C MAIN function that invokes SVC99 functions.          |
|   MVS -                                                              |
|      COMPILE, LINK, EXECUTE: SUBMIT prefix.SAMPLE.AUX(SVC99CLG)      |
|   TSO -                                                              |
|      COMPILE: LC370 CLIST                                            |
|         LINK: Refer to SVC99C sample                                 |
|      EXECUTE: CALL 'your.load.lib(SVC99C)'                           |
|         NOTE: Ensure you compile SVC99 before LINKING or EXECUTING   |
|               SVC99C                                                 |
|   CMS -  NA                                                          |
|   MISC NOTES: Function Descriptions:                                 |
|                                                                      |
|   These functions provide a simple interface to dynamically          |
|   allocate and unallocate data sets and the INTERNAL READER using    |
|   SVC 99.  Four external functions are provided.                     |
|                                                                      |
|   alc_ds    allocates a data set and associates it with a            |
|             ddname provided by the caller                            |
|                                                                      |
|   *-----------alc_ds call construct----------------------------*     |
|   int alc_ds (                                                       |
|        char * ddname,   The ddname to associate with the             |
|                         allocated data set.                          |
|        char * dsname,   The data set name to allocate.  An           |
|                         optional member name in parentheses          |
|                         may follow the dsname.                       |
|        char * status,   The initial data set status.  Valid          |
|                         values are:                                  |
|                             "old"                                    |
|                             "mod"                                    |
|                             "new"                                    |
|                             "shr"                                    |
|        char * normdisp,  The data set normal disposition.            |
|        char * conddisp,  The data set conditional disposition.       |
|        char * spc_unit,  Space Unit (ie. TRK, CYL, xxx)              |
|        int    spc_prim,  Space Primary                               |
|        int    spc_sec,   Space Secondary                             |
|        int    spc_blks,  Directory Blocks                            |
|        char * recfm,     DCB RECFM (ie. F, FB, VB, etc)              |
|        int    lrecl,     DCB LRECL                                   |
|        int    blksize,   DCB BLKSIZE                                 |
|        char * dsorg)     DCB DSORG (ie. PS, PO, DA, etc)             |
|                                                                      |
|                                                                      |
|   *-----------unalc_ds call construct----------------------------*   |
|   unalc_ds  unallocates a data set associated with a ddname          |
|                                                                      |
|   int unalc_ds (                                                     |
|        char * ddname,    The ddname to unallocate                    |
|                                                                      |
|        char * normdisp,  The normal disposition for the dataset.     |
|                          valid values are:                           |
|                             "uncatlg"                                |
|                             "catlg"                                  |
|                             "delete"                                 |
|                             "keep"                                   |
|                             ""       (Accept the default action).    |
|        char * conddisp)  The conditional disposition for the         |
|                          dataset.  Valid valuse are:                 |
|                             "uncatlg"                                |
|                             "catlg"                                  |
|                             "delete"                                 |
|                             "keep"                                   |
|                             ""       (Accept the default action).    |
|                                                                      |
|   *-----------alc_intr call construct--------------------------*     |
|   alc_intr  allocates the Interal Reader (INTRDR) to a ddname with   |
|             the specified class                                      |
|                                                                      |
|   int alc_intr (                                                     |
|        char * ddname,    The ddname to associate with the            |
|                          allocated data set.                         |
|                                                                      |
|        char * class)     The class of the SYSOUT dataset.            |
|                                                                      |
|   *-----------alc_syso call construct--------------------------*     |
|   alc_syso  allocates the a SYSOUT dataset.  Allow a SYSOUT          |
|             program to be specified along with a class.              |
|                                                                      |
|   int alc_syso (                                                     |
|        char * ddname,    The ddname to associate with the            |
|                          allocated data set.                         |
|                                                                      |
|        char * class,     The class of the SYSOUT dataset.            |
|        char * program)   The SYSOUT program to run.                  |
|                                                                      |
|                                                                      |
|   The returned values from all functions are the same.  A return     |
|   value of 20 indicates that one or more of the parameter values     |
|   to alc_ds, unalc_ds, alc_intr, or alc_syso is incorrect. All       |
|   other values are the actual return codes from the SVC 99 call.     |
|                                                                      |
|   For all return values other than 20, the external variables        |
|   s99error and s99info are set to reflect the action taken by        |
|   the SVC 99 call.                                                   |
|                                                                      |
| SYSTEM NOTES: Written for MVS                                        |
|   MISC NOTES: See IBM SVC 99 documentation for complete details      |
|               on SVC 99.                                             |
|                -- MVS/XA SPL: System Macros and Facilities, Vol 1    |
|                   GC28-1150-2                                        |
|                                                                      |
+---------------------------------------------------------------------*/

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <svc.h>

/*-------------------------------------------------------------------*/
/*                                                                   */
/*  The following two variables are externally visible.  After a     */
/*  call to alc_ds, unalc_ds, alc_intr, or alc_syso, the contain the */
/*  returned error and info codes from SVC 99.                       */
/*                                                                   */
/*-------------------------------------------------------------------*/

short s99error;                /* Returned error code                */
short s99info;                 /* Returned info code                 */

#define MAXTU 20               /* Maximum number of text units       */
                               /* This should be increased if more   */
                               /* parameters are added               */
#define MAXTULEN 60            /* Maximum length of the PARM part of */
                               /* any text unit                      */

static struct s99tu {          /* Array of text units                */
     short key;                /* Key for type of parameter          */
     short number;             /* Number of len/parm pairs to follow */
     short len;                /* Length of the following parm       */
     char parm[MAXTULEN];      /* Parameter value                    */
       } tu[MAXTU];

static struct s99tu *tuptr[MAXTU];
                               /* Array of pointers to text units    */

static struct s99rb {          /* Request block                      */
     char len;                 /* Length of the request block (20)   */
     char verb;                /* Action verb                        */
#define VRBAL 1                /* Allocate verb value                */
#define VRBUN 2                /* Unallocate verb value              */
     short flags1;             /* Some flags                         */
     short errcode;            /* Error code                         */
     short infocode;           /* Info code                          */
     struct s99tu ** txtpp;    /* Pointer to text pointer array      */
     int reserved;             /* Reserved space                     */
     int flags2;               /* More flags                         */
       } rb;

static struct s99rb * rbptr;   /* Pointer to the request block       */

static struct s99rb ** ptrptr; /* Pointer to rbptr (loaded into R1)  */

static int s99call (           /* Set up parameters and call SVC 99  */
     int action,               /* Action verb                        */
     char * ddname,            /* ddname                             */
     char * dsname,            /* dsname with optional member        */
     char * status,            /* Status string                      */
     char * normdisp,          /* norm disposition string            */
     char * conddisp,          /* cond disposition string            */
     char * spc_unit,          /* Space Unit (ie. TRK, CYL, xxx)     */
     int    spc_prim,          /* Space Primary                      */
     int    spc_sec,           /* Space Secondary                    */
     int    spc_blks,          /* Directory Blocks                   */
     char * recfm,             /* DCB RECFM (ie. F, FB, VB, etc)     */
     int    lrecl,             /* DCB LRECL                          */
     int    blksize,           /* DCB BLKSIZE                        */
     char * dsorg,             /* DCB DSORG (ie. PS, PO, DA, etc)    */
     char * syso_cls,          /* SYSOUT Class                       */
     char * syso_pgm           /* SYSOUT Pgm name (ie. INTRDR)       */
         );

static int s99edit (           /* Edit a parameter string            */
     char * original,          /* Original (unedited) string         */
     char * new                /* New (edited) string                */
         );

#eject

/*-------------------------------------------------------------------*/
/*                                                                   */
/*  alc_ds - Dynamically allocate a dataset.  Accept space, dcb,     */
/*           status, normal and conditional disposition.             */
/*                                                                   */
/*-------------------------------------------------------------------*/

int alc_ds(
     char * ddname,            /* ddname to attach                   */
     char * dsname,            /* dsname with optional member name   */
     char * status,            /* Initial data set status            */
     char * normdisp,          /* Data set norm disposition          */
     char * conddisp,          /* Data set cond disposition          */
     char * spc_unit,          /* Space Unit (ie. TRK, CYL, xxx)     */
     int    spc_prim,          /* Space Primary                      */
     int    spc_sec,           /* Space Secondary                    */
     int    spc_blks,          /* Directory Blocks                   */
     char * recfm,             /* DCB RECFM (ie. F, FB, VB, etc)     */
     int    lrecl,             /* DCB LRECL                          */
     int    blksize,           /* DCB BLKSIZE                        */
     char * dsorg)             /* DCB DSORG (ie. PS, PO, DA, etc)    */
{
     /* Call s99call with appropriate parms.                         */
     return ( s99call (VRBAL, ddname, dsname,
                       status, normdisp, conddisp,
                       spc_unit, spc_prim, spc_sec, spc_blks,
                       recfm, lrecl, blksize, dsorg,
                       "", "") );
}

#eject
/*-------------------------------------------------------------------*/
/*                                                                   */
/*  unalc_ds - Dynamically release any allocated dataset. Accept a   */
/*           normal and conditional disposition.                     */
/*                                                                   */
/*-------------------------------------------------------------------*/

int unalc_ds (
     char * ddname,            /* ddname to unallocate               */
     char * normdisp,          /* Data set norm disposition          */
     char * conddisp)          /* Data set cond disposition          */
{
     /* Call s99call with appropriate parms.                         */
     return ( s99call (VRBUN, ddname, "",
                       "", normdisp, conddisp,
                       "", 0, 0, 0,
                       "", 0, 0, "",
                       "", "") );
}

#eject
/*-------------------------------------------------------------------*/
/*                                                                   */
/*  alc_intr -- Dynamically allocate the internal reader (INTRDR)    */
/*              for the purpose of submitting jobs from a C program. */
/*                                                                   */
/*-------------------------------------------------------------------*/

int alc_intr (
     char * ddname,            /* ddname to attach                   */
     char * class)             /* SYSOUT CLASS                       */
{

     return ( s99call (VRBAL, ddname, "",
                       "", "", "",
                       "", 0, 0, 0,
                       "", 0, 0, "",
                       class, "INTRDR") );
}


#eject
/*-------------------------------------------------------------------*/
/*                                                                   */
/*  alc_syso -- Dynamically allocate a SYSOUT dataset.  Allow a      */
/*              program to be specified (such as INTRDR).            */
/*                                                                   */
/*-------------------------------------------------------------------*/

int alc_syso (
     char * ddname,            /* ddname to attach                   */
     char * class,             /* SYSOUT CLASS                       */
     char * program)           /* SYSOUT Program to run              */
{

     return ( s99call (VRBAL, ddname, "",
                       "", "", "",
                       "", 0, 0, 0,
                       "", 0, 0, "",
                       class, program) );
}


#eject
/*-------------------------------------------------------------------*/
/*                                                                   */
/*  s99call - From the parameters given, build a list of "text units"*/
/*            and then issue an SVC 99.  This is the real workhorse. */
/*                                                                   */
/*            REF:  MVS/XA SPL: System Macros and Facilities, Vol 1  */
/*                  GC28-1150-2                                      */
/*-------------------------------------------------------------------*/

static int s99call (
     int action,                  /* Action verb                     */
     char * ddname,               /* ddname                          */
     char * dsname,               /* dsname with optional member     */
     char * status,               /* Status string                   */
     char * normdisp,             /* norm disposition string         */
     char * conddisp,             /* cond disposition string         */
     char * spc_unit,             /* Space Unit (ie. TRK, CYL, xxx)  */
     int    spc_prim,             /* Space Primary                   */
     int    spc_sec,              /* Space Secondary                 */
     int    spc_blks,             /* Directory Blocks                */
     char * recfm,                /* DCB RECFM (ie. F, FB, VB, etc)  */
     int    lrecl,                /* DCB LRECL                       */
     int    blksize,              /* DCB BLKSIZE                     */
     char * dsorg,                /* DCB DSORG (ie. PS, PO, DA, etc) */
     char * syso_cls,             /* SYSOUT Class                    */
     char * syso_pgm)             /* SYSOUT Pgm name (ie. INTRDR)    */
{
     char str[256];               /* Working copy of strings         */
     int stlen;                   /* Length of string in str         */
     char *p;                     /* Work char pointer               */
     int rc;                      /* Return code from SVC 99         */
     int ntu;                     /* Number of text units created    */
     int i;                       /* Counter for loops               */
     union                        /* Data area for mapping ints      */
        {                         /*   to 1, 2, & 3 byte areas       */
       int ival;                  /* The integer */
       struct                     /* Struct to overlay a 1 byte area */
           {
           char t1[3];
           char val1;
           } c1;
       struct                     /* Struct to overlay a 2 byte area */
           {
           char t2[2];
           char val2[2];
           } c2;
       struct                     /* Struct to overlay a 3 byte area */
           {
           char t3;
           char val3[3];
           } c3;
        } data;


     /***********************************************************
               Initialize all of the data structures
     ***********************************************************/

     memset ((char *)tu, '\0', sizeof(tu));
     memset ((char *)tuptr, '\0', sizeof(tuptr));
     memset ((char *)&rb, '\0', sizeof(rb));

     ptrptr = &rbptr;
     rbptr = (struct s99rb *) ( (int)&rb | 0x80000000);

     rb.len = 20;
     rb.verb = action;
     rb.txtpp = &tuptr[0];

     s99error = 0;
     s99info = 0;

     ntu = 0;

     /***********************************************************
               Each parm maps to a text unit.  If the parm is
               Not NULL or not ZERO, then create a text unit
               for it.
     ***********************************************************/

     /***********************************************************
              DDNAME Text unit
            -----------------------------------------------
                  Ex: For ddname of DD1, code
                     KEY   #    LEN    PARM
                     0001  0001 0003   C4 C4 F1
     ***********************************************************/

     if (s99edit(ddname,str))
          return (20);

     stlen = strlen (str);
     if ( (stlen == 0) || (stlen > 8) )
          return (20);

     tu[ntu].key = 0x0001;
     tu[ntu].number = 1;
     tu[ntu].len = stlen;
     memcpy (tu[ntu].parm, str, stlen);
     tuptr[ntu] = &tu[ntu];
     ntu++;

     /***********************************************************
              DSNAME Text unit
            -----------------------------------------------
                  Ex: For dsname of MYDATA, code
                     KEY   #    LEN    PARM
                     0002  0001 0006   D4 E8 C4 C1 E3 C1
     ***********************************************************/

     if (s99edit(dsname,str))
          return (20);

     p = strchr (str, '(');
     if (p != NULL)
          *p = '\0';

     stlen = strlen (str);
     if (stlen > 44)
          return (20);

     if (stlen > 0)
     {
          tu[ntu].key = 0x0002;
          tu[ntu].number = 1;
          tu[ntu].len = stlen;
          memcpy (tu[ntu].parm, str, stlen);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              MEMBER_NAME text unit
            -----------------------------------------------
                  Ex: To specify the member name MEM1, code
                     KEY   #    LEN    PARM
                     0003  0001 0004   D4 C5 D4 F1
     ***********************************************************/

     p = strchr (dsname, '(');
     if (p != NULL)
     {
          p++;
          if (s99edit(p,str))
               return (20);
          p = strchr (str, ')');
          if (p == NULL)
               return (20);
          *p = '\0';

          stlen = strlen (str);
          if (stlen > 8)
               return (20);
          if (stlen > 0)
          {
               tu[ntu].key = 0x0003;
               tu[ntu].number = 1;
               tu[ntu].len = stlen;
               memcpy (tu[ntu].parm, str, stlen);
               tuptr[ntu] = &tu[ntu];
               ntu++;
          }
     }

     /***********************************************************
     DISPOSITION NOTES:
        In JCL:
           ...,disp=(status,normdisp,conddisp)

        status is the current status before executing the job.
        normdisp is the way the dataset is to be left if everything
                 works.
        conddisp is the way the dataset is to be left if a failure
                 occurs.
     ***********************************************************/
     /***********************************************************
              STATUS text unit
            -----------------------------------------------
                  Ex: To specify a status of new, code
                     KEY   #    LEN    PARM
                     0004  0001 0001   04

              NOTE: This text unit is mutually exclusive with
                    the SYSOUT text units.  So, higher level
                    functions must assure that they are not
                    specified together.
     ***********************************************************/

     if (s99edit(status,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
          if (strcmp(str, "OLD") == 0)
               data.ival = 1;
          else if (strcmp(str, "MOD") == 0)
               data.ival = 2;
          else if (strcmp(str, "NEW") == 0)
               data.ival = 4;
          else if (strcmp(str, "SHR") == 0)
               data.ival = 8;
          else
               return (20);

          tu[ntu].key = 0x0004;
          tu[ntu].number = 1;
          tu[ntu].len = 1;
          tu[ntu].parm[0] = data.c1.val1;
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              NORMAL DISPOSITION text unit
            -----------------------------------------------
                  Ex: To specify a normdisp of DELETE, code
                     KEY   #    LEN    PARM
                     0005  0001 0001   04

              NOTE: This text unit is mutually exclusive with
                    the SYSOUT text units.  So, higher level
                    functions must assure that they are not
                    specified together.
     ***********************************************************/

     if (s99edit(normdisp,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
          if (strcmp(str, "UNCATLG") == 0)
               data.ival = 1;
          else if (strcmp(str, "CATLG") == 0)
               data.ival = 2;
          else if (strcmp(str, "DELETE") == 0)
               data.ival = 4;
          else if (strcmp(str, "KEEP") == 0)
               data.ival = 8;
          else
               return (20);

          tu[ntu].key = 0x0005;
          tu[ntu].number = 1;
          tu[ntu].len = 1;
          tu[ntu].parm[0] = data.c1.val1;
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              CONDITIONAL DISPOSITION text unit
            -----------------------------------------------
                  Ex: To specify a conddisp of DELETE, code
                     KEY   #    LEN    PARM
                     0006  0001 0001   04

              NOTE: This text unit is mutually exclusive with
                    the SYSOUT text units.  So, higher level
                    functions must assure that they are not
                    specified together.
     ***********************************************************/

     if (s99edit(conddisp,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
          if (strcmp(str, "UNCATLG") == 0)
               data.ival = 1;
          else if (strcmp(str, "CATLG") == 0)
               data.ival = 2;
          else if (strcmp(str, "DELETE") == 0)
               data.ival = 4;
          else if (strcmp(str, "KEEP") == 0)
               data.ival = 8;
          else
               return (20);

          tu[ntu].key = 0x0006;
          tu[ntu].number = 1;
          tu[ntu].len = 1;
          tu[ntu].parm[0] = data.c1.val1;
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              DCB DSORG text unit
              Create the text unit for the dsorg
            -----------------------------------------------
                  Ex: To specify a dsorg of PO, code
                     KEY   #    LEN    PARM
                     003C  0001 0002   02 00
     ***********************************************************/

     if (s99edit(dsorg,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
          if (strcmp(str, "TCAM") == 0)
               data.ival =0x0004;
          else if (strcmp(str, "VSAM") == 0)
               data.ival =0x0008;
          else if (strcmp(str, "TCAMTQ") == 0)
               data.ival =0x0020;
          else if (strcmp(str, "TCAMTX") == 0)
               data.ival =0x0040;
          else if (strcmp(str, "GS") == 0)
               data.ival =0x0080;
          else if (strcmp(str, "PO") == 0)
               data.ival =0x0200;
          else if (strcmp(str, "POU") == 0)
               data.ival =0x0300;
          else if (strcmp(str, "MQ") == 0)
               data.ival =0x0400;
          else if (strcmp(str, "CQ") == 0)
               data.ival =0x0800;
          else if (strcmp(str, "CX") == 0)
               data.ival =0x1000;
          else if (strcmp(str, "DA") == 0)
               data.ival =0x2000;
          else if (strcmp(str, "DAU") == 0)
               data.ival =0x2100;
          else if (strcmp(str, "PS") == 0)
               data.ival =0x4000;
          else if (strcmp(str, "PSU") == 0)
               data.ival =0x4100;
          else
               return (20);

          tu[ntu].key = 0x003C;
          tu[ntu].number = 1;
          tu[ntu].len = 2;
          memcpy(tu[ntu].parm, data.c2.val2, 2);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              DCB RECFM   text unit
            -----------------------------------------------
                  Ex: To specify a RECFM of F, code
                     KEY   #    LEN    PARM
                     0049  0001 0001   80
     ***********************************************************/

     if (s99edit(recfm,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
        data.ival = 0;
        for (i=0; i< stlen; i++)
        {
             if ((str[i] == 'M') || (str[i] == 'R'))
                  data.ival += 0x02;
             else if ((str[i] == 'A') || (str[i] == 'G'))
                  data.ival += 0x04;
             else if (str[i] == 'S')
                  data.ival += 0x08;
             else if (str[i] == 'B')
                  data.ival += 0x10;
             else if ((str[i] == 'D') || (str[i] == 'T'))
                  data.ival += 0x20;
             else if (str[i] == 'V')
                  data.ival += 0x40;
             else if (str[i] == 'F')
                  data.ival += 0x80;
             else if (str[i] == 'U')
                  data.ival += 0xC0;
             else
                   return (20);
          }

          tu[ntu].key = 0x0049;
          tu[ntu].number = 1;
          tu[ntu].len = 1;
          tu[ntu].parm[0] = data.c1.val1;
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }


     /***********************************************************
              DCB LRECL   text unit
            -----------------------------------------------
                  Ex: To specify an LRECL of 80, code
                     KEY   #    LEN    PARM
                     0042  0001 0002   00 50

           NOTE: for variable len spanned recoreds processed
                 under QSAM and BSAM, the logical records exceed
                 32,756.  SO, the parm should be coded as
                 0x8000 for these types of files.  This function
                 does not account for this type of file.
     ***********************************************************/

     if ((lrecl > 0) && (lrecl <= 32760))
     {

          tu[ntu].key = 0x0042;
          tu[ntu].number = 1;
          tu[ntu].len = 2;
          data.ival = lrecl;
          memcpy(tu[ntu].parm, data.c2.val2, 2);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }


     /***********************************************************
              DCB BLKSIZE text unit
            -----------------------------------------------
                  Ex: To specify an BLKSIZE of 80, code
                     KEY   #    LEN    PARM
                     0030  0001 0002   00 50

     ***********************************************************/

     if ((blksize > 0) && (blksize <= 32760))
     {

          tu[ntu].key = 0x0030;
          tu[ntu].number = 1;
          tu[ntu].len = 2;
          data.ival = blksize;
          memcpy(tu[ntu].parm, data.c2.val2, 2);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
              SPACE UNIT SIZE text unit
            -----------------------------------------------
                  Ex: To specify an Unit of TRK, code
                     KEY   #    LEN    PARM
                     0007  0000  -      -

                  Ex: To specify an Unit of CYL, code
                     KEY   #    LEN    PARM
                     0008  0000  -      -

                  Ex: To specify an Unit in blks of size 80, code
                     KEY   #    LEN    PARM
                     0009  0001 0003   00 00 50

     ***********************************************************/

     if (s99edit(spc_unit,str))
          return (20);

     stlen = strlen(str);
     if (stlen > 0)
     {
        if (strcmp(str, "TRK") == 0)
           {
           tu[ntu].key = 0x0007;
           tu[ntu].number = 0;
           }
        else if (strcmp(str, "CYL") == 0)
           {
           tu[ntu].key = 0x0008;
           tu[ntu].number = 0;
           }
        else
           {
           data.ival = atoi(str);
           if ((data.ival > 0) && (data.ival <= 32760))
              {
              tu[ntu].key = 0x0009;
              tu[ntu].number = 1;
              tu[ntu].len = 3;
              memcpy(tu[ntu].parm, data.c3.val3, 3);
              }
           else
              return (20);
           }

       tuptr[ntu] = &tu[ntu];
       ntu++;
     }


     /***********************************************************
              SPACE PRIMARY Text unit
            -----------------------------------------------
                  Ex: To specify a primary space of 20, code
                     KEY   #    LEN    PARM
                     000A  0001 0003   00 00 14

     ***********************************************************/

     if (spc_prim > 0)
     {
       tu[ntu].key = 0x000A;
       tu[ntu].number = 1;
       tu[ntu].len = 3;
       data.ival = spc_prim;
       memcpy(tu[ntu].parm, data.c3.val3, 3);
       tuptr[ntu] = &tu[ntu];
       ntu++;
     }




     /***********************************************************
              SPACE SECONDARY Text Unit
            -----------------------------------------------
                  Ex: To specify a secondary space of 10, code
                     KEY   #    LEN    PARM
                     000B  0001 0003   00 00 0A

     ***********************************************************/

     if (spc_sec > 0)
     {
       tu[ntu].key = 0x000B;
       tu[ntu].number = 1;
       tu[ntu].len = 3;
       data.ival = spc_sec;
       memcpy(tu[ntu].parm, data.c3.val3, 3);
       tuptr[ntu] = &tu[ntu];
       ntu++;
     }



     /***********************************************************
              SPACE DIR BLKS  Text Unit
            -----------------------------------------------
                  Ex: To specify two dir blks in a PDS, code
                     KEY   #    LEN    PARM
                     000C  0001 0003   00 00 02

     ***********************************************************/

     if (spc_blks > 0)
     {
       tu[ntu].key = 0x000C;
       tu[ntu].number = 1;
       tu[ntu].len = 3;
       data.ival = spc_blks;
       memcpy(tu[ntu].parm, data.c3.val3, 3);
       tuptr[ntu] = &tu[ntu];
       ntu++;
     }


     /***********************************************************
              SYSOUT CLASS text unit
            -----------------------------------------------
                  Ex: To specify a SYSOUT data set with class A, code
                     KEY   #    LEN    PARM
                     0018  0001 0001   C1
     ***********************************************************/

     if (s99edit(syso_cls, str))
          return (20);

     stlen = strlen (str);
     if (stlen == 1)
     {
          /* Text unit for the SYSOUT Class */
          tu[ntu].key = 0x0018;
          tu[ntu].number = 1;
          tu[ntu].len = stlen;
          memcpy (tu[ntu].parm, str, stlen);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }
     else if (stlen > 1)          /* Invalid Class            */
          return (20);


     /***********************************************************
              SYSOUT PROGRAM NAME text unit
            -----------------------------------------------
                  Ex: To specify the pgm name MYWRITER, code
                     KEY   #    LEN    PARM
                     0019  0001 0008   D4 E8 E6 D9 C9 E3 C5 D9
     ***********************************************************/

     if (s99edit(syso_pgm,str))
          return (20);

     stlen = strlen (str);
     if (stlen > 0)
     {
          stlen = 6;
          tu[ntu].key = 0x0019;
          tu[ntu].number = 1;
          tu[ntu].len = stlen;
          memcpy (tu[ntu].parm, str, stlen);
          tuptr[ntu] = &tu[ntu];
          ntu++;
     }

     /***********************************************************
                        Issue the SVC 99
     ***********************************************************/

     ntu--;
     tuptr[ntu] = (struct s99tu *) ( (int)tuptr[ntu] | 0x80000000);

     _ldregs(R1, ptrptr);
     _ossvc(99);
     rc = _stregs(R15);

     s99error = rb.errcode;
     s99info = rb.infocode;

     return (rc);

}

#eject
/*-------------------------------------------------------------------*/
/*                                                                   */
/*  s99edit                                                          */
/*                                                                   */
/*  This function edits a string passed as a parameter to one of     */
/*  the external functions.  It copies the string from the first     */
/*  argument (original) to the second argument (new), removes all    */
/*  leading and trailing white space, and converts the string to     */
/*  upper case.                                                      */
/*                                                                   */
/*  Return value is 0 if the string was edited, or 1 if the string   */
/*  was too long (>255 bytes).                                       */
/*                                                                   */
/*-------------------------------------------------------------------*/

static int s99edit (           /* Edit a parameter string            */
     char * original,             /* Original (unedited) string      */
     char * new)                  /* New (edited) string             */
{
     int n;                    /* Length of string */

     /* Find the first non-white-space character in the string */

     while (isspace(*original))
          original++;

     /* If the whole string is white space, just set the new string
        to null and return ok.  */

     if (*original == '\0')
     {
          *new = '\0';
          return (0);
     }

     /* Check the length of the string to see if we can copy it */

     n = strlen (original);
     if (n > 255)
          return (1);

     /* Copy the string and trim trailing white space */

     strcpy (new, original);

     for (--n; n > 0 && isspace(*(new+n)); n--)
          ;
     *(new+(++n)) = '\0';

     /* Convert string to upper case */

     strupr (new);

     return (0);

}

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