Chapter Contents

Previous

Next
execshv

Examples of SUBCOM Processing

These examples demonstrate the SUBCOM interface to CMS and TSO. In the first example, three subcommands are accepted: ECHO repeats operands, SETRC sets a return code, and EXEC invokes a TSO CLIST or CMS EXEC. The program can be executed either interactively or noninteractively depending on the value of the interact option in execinit .

A copy of this example is provided with the compiler and library. See your SAS Software Representative for SAS/C compiler products for more information.

#include <exec.h>
#include <ctype.h>
#include <lcstring.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

main(int argc, char **argv)
{
      /* If 0, next input expected from EXEC.  If nonzero, next input */
      /* expected from terminal.                                      */
   int interact;

   char *input, *cmdname, *operands;
   int maxrc = 0;
   int thisrc;
   char msgbuff[120];
   int result;

   interact = (argc > 1 && tolower(*argv[1]) == 'i');

      /* If first argument starts with 'i', use interactive mode.     */
   result = execinit("EXAMPLE", interact);
   if (result  != 0) exit(EXIT_FAILURE);
      /* Check for failure of execinit */

   for(;;) {
      operands = input = execget();

         /* Obtain next input line. */
      if (!input)
         break;

      cmdname = execid(&operands);

         /* Obtain command name.  If error in execid, expect          */
         /* CLIST/EXEC input next.                                    */
      if (!cmdname) {
         interact = 1;
         continue;
      }

      strupr(cmdname);                   /* Upper case command name   */
      if (!*cmdname)                     /* Check for null input.     */
         continue;

         /* If execid did an EXEC for us, note and continue.          */
      else if (strcmp(cmdname, "*EXEC") == 0) {
         interact = 0;
         continue;
      }

         /* If we just switched from EXEC to the terminal, note this. */
      else if (strcmp(cmdname, "*ENDEXEC") == 0) {
         interact = 1;
         thisrc = atoi(operands);

            /* Extract EXEC return code. Remember it might be missing.*/
         if (operands)
            sprintf(msgbuff, "EXEC return code %d", thisrc);
         else
            strcpy(msgbuff, "EXEC return code unavailable");

            /* Inform user of return code. */
         result = execmsg("EXAM001I", msgbuff);
         if (result != 0 && errno == EINTR) break;
            /* Check for unexpected signal */
      }

         /* Terminate if END received. */
      else if (strcmp(cmdname, "END") == 0)
         break;

      else if (strcmp(cmdname, "EXEC") == 0) {

            /* Call EXEC for EXEC subcommand and expect input from it.*/
         thisrc = execcall(input);
         interact = 0;
         if (thisrc != 0) {
            sprintf(msgbuff,"EXEC failed with return code %d",thisrc);
            result = execmsg("EXAM005E",msgbuff);
            if (result != 0 && errno == EINTR) break;
               /* just quit after OpenEdition signal */
         }
      }

         /* If command is ECHO, repeat its operands.                  */
      else if (strcmp(cmdname, "ECHO") == 0) {
         result = execmsg(0, operands);
         if (result != 0 && errno == EINTR) break;
         thisrc = 0;
      }

         /* If command is SETRC, set return code as requested.     */
      else if (strcmp(cmdname, "SETRC") == 0) {
         char *number_end;
         thisrc = strtol(operands, &number_end, 10);
         if (!number_end) {
            sprintf(msgbuff, "Invalid return code: %s",operands);
            result = execmsg("EXAM002E", msgbuff);
            if (result != 0 && errno == EINTR) break;
            thisrc = 12;
         }
         else {
            sprintf(msgbuff, "Return code set to %d", thisrc);
            execmsg("EXAM003I", msgbuff);
            if (result != 0 && errno == EINTR) break;
         }
      }

         /* If unknown command name, try to EXEC it.               */
      else {
         errno = 0;                  /* Make sure errno is clear   */
         thisrc = execcall(input);
         if (thisrc != 0 && errno == EINTR) break;
         interact = 0;
      }
      maxrc = execrc(thisrc);        /* Inform EXEC of return code.*/
      if (maxrc < 0 && errno == EINTR) break;
   }
   sprintf(msgbuff, "Maximum return code was %d", maxrc);
   execmsg("EXAM004I", msgbuff);     /* Announce max return code.  */
   execend();                        /* Cancel SUBCOM connection.  */
   return maxrc;                     /* Return max return code.    */
}


CLIST Example for SUBCOM Processing

The following CLIST illustrates the use of subcommand processing under TSO. The CLIST provides subcommands to the SAS/C SUBCMD sample.

CONTROL NOCAPS
WRITE SUBCOM EXAMPLE: starting.

   /* Issue the echo subcommand a few times. */
ECHO This is the first subcommand.
ECHO Your userid is &SYSUID..
SETRC 0     /* Try the SETRC subcommand. */
WRITE SUBCOM EXAMPLE: return code is now &LASTCC
SETRC 8     /* Set the return code to 8 */
WRITE SUBCOM EXAMPLE: return code is now &LASTCC
SETRC 0     /* and back to 0 */
WRITE

   /* Experiment with 'execmsg' by changing current       */
   /* message handling.  The PCF-II X facility is used to */
   /* direct PROFILE requests to TSO.                     */
X PROFILE MSGID    /* Request message ID display.         */
WRITE PROFILE MSGID (complete message)
SETRC 0
WRITE
X PROFILE NOMSGID  /* Request message ID suppression.     */
WRITE PROFILE NOMSGID (just the text)
SETRC 0 
WRITE 
CONTROL NOMSG 
WRITE CONTROL NOMSG (no message) 
SETRC 0 
WRITE 
CONTROL MSG 
WRITE SET SYSOUTTRAP = 5 (trap messages within CLIST) 
SET SYSOUTTRAP = 5 
SETRC 0 
SET I = 1 
WRITE Output produced by SETRC subcommand: 
DO WHILE &  I <  = &  SYSOUTLINE    /* Write output of SETRC subcommand. */    
   SET MSG = &  STR(&  &  SYSOUTLINE&  I)    
   WRITE &  MSG    
   SET I = &  I + 1 
END 
SET SYSOUTTRAP = 0 
WRITE

   /* Tell the example program to invoke another CLIST,   */   
   /* this one called SUBSUB.  When it finishes, display  */   
   /* its return code.  SUBSUB returns the sum of its     */
   /* arguments as its return code.                       */ 
%SUBSUB 12 2 
WRITE SUBCOM EXAMPLE: subsub returned &  LASTCC. 
END

   /* Invoked by SUBCOM CLIST */ 
PROC 2 VAL1 VAL2 
CONTROL NOCAPS 
WRITE SUBSUB EXAMPLE: Received arguments &  VAL1 and &  VAL2 
EXIT CODE(&  VAL1+&  VAL2)


TSO REXX Example for SUBCOM Processing

The following REXX EXEC illustrates the use of subcommand processing with TSO REXX. The EXEC provides input to the SAS/C SUBCMD example.

address example                /* REXX SUBCOM example                 */

   /* Issue the echo subcommand a few times.                          */
"echo This is the first subcommand."
"echo Your userid is " sysvar("SYSUID")
"setrc 0"                                 /* try the SETRC subcommand */
say "SUBCOMR EXAMPLE: return code is now " RC
"setrc 8"                                 /* Set the return code to 8 */
say "SUBCOMR EXAMPLE: return code is now " RC
"setrc 0"                                 /* and back to 0            */
say " "
  /* Put an echo subcommand on the stack for execution after the EXEC */
  /* completes.                                                       */
queue 'echo This line is written after the EXEC is completed.'
  /* Experiment with "execmsg" by changing current message handling.  */
address tso "profile msgid"
say "PROFILE MSGID (complete message)"
"setrc 0"
say " "
address tso "profile nomsgid"
say "PROFILE NOMSGID (just the text)"
"setrc 0"
say " "
save = msg("OFF")
say "MSG(OFF) (no message)"
"setrc 0"
say " "
save = msg(save)

   /* Tell the example program to invoke a CLIST named SUBSUB. When   */
   /* it finishes, display its return code. SUBSUB returns the sum    */
   /* of its arguments as its return code.                            */
"%subsub 12 2"
say "SUBCOMR EXAMPLE: subsub returned " RC

   /* Now invoke a REXX EXEC named SUBSUBR, which performs the same   */
   /* function as the SUBSUB CLIST. Note that the negative return     */
   /* code produced by this call to subsubr will be flagged as an     */
   /* error by REXX.                                                  */
"%subsubr 5 -23"
say "SUBCOMR EXAMPLE: subsubr returned " RC

The following is the SUBSUBR EXEC invoked by the previous example.

/* REXX EXEC invoked by SUBCOMR EXEC                               */
parse arg val1 val2 .
say "SUBSUBR EXAMPLE: Received arguments " VAL1 " and " VAL2
exit val1+val2


CMS EXEC Example for SUBCOM Processing

The following example illustrates the use of the SAS/C SUBCOM facility under CMS. Subcommands are provided to the SUBCOM SAS/C program. By default, the subcommands are sent to the environment with the same name as the macro filetype, in this case "EXAMPLE".

   /*  REXX */
say 'SUBCOM EXAMPLE: starting.'
   /* Issue the echo subcommand a few times.                          */
'echo This is the first subcommand.'
'echo Your userid is' userid()'.'
'setrc 0'                           /* Try the setrc subcommand.      */
say 'SUBCOM EXAMPLE: return code is now' rc
                                    /* REXX variable 'rc'             */
'setrc 8'                           /* Set the return code to 8.      */
say 'SUBCOM EXAMPLE: return code is now' rc
                                    /* REXX variable 'rc'             */
'setrc 0'                           /* And back to 0.                 */
say ''

   /* Experiment with 'execmsg' by changing the current EMSG setting. */
   /* The subcommand 'setrc 0' will cause a message (or part of a     */
   /* message or nothing) to be sent. Note that the REXX 'address'    */
   /* statement is used to change the subcommand environment to CMS.  */
address  COMMAND 'CP SET EMSG ON'        /* Display both ID and text. */
say 'SET EMSG ON (complete message)'
'setrc 0'
say ''
address COMMAND 'CP SET EMSG CODE'       /* Display just the ID.      */
say 'SET EMSG CODE (just the id)'
'setrc 0'
say ''
address COMMAND 'CP SET EMSG TEXT'       /* Display just the text.    */
say 'SET EMSG TEXT (just the text)'
'setrc 0'
say ''
address COMMAND 'CP SET EMSG OFF'        /* Don't display anything.   */
say 'SET EMSG OFF (no message)'
'setrc 0'
say ''
address COMMAND 'CP SET EMSG ON'         /* Back to normal.           */

   /* Finally, tell SUBCOM C to invoke another macro, this one called */
   /* 'SUBSUB'. When it finishes, display the return code. SUBSUB     */
   /* returns the number of arguments it got as the return code.      */
'exec subsub arg1 arg2'
say 'SUBCOM EXAMPLE: subsub was passed' rc 'arguments.'
trace ?r
'end'
exit 0
   /* invoked by SUBCOM EXAMPLE                                       */
arg args
say 'SUBSUB EXAMPLE: Got' words(args) 'arguments.'
return words(args)


Chapter Contents

Previous

Next

Top of Page

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