|SAS Companion for the OS/390 Environment|
REXX, the procedure language for computing platforms that conform to the IBM Systems Application Architecture (SAA), is well known for combining powerful programming features with ease of use. By enabling SAS users to supplement the SAS language with REXX, the SAS interface to REXX provides new SAS programming possibilities in the OS/390 environment.
|Enabling the Interface|
The SAS system options REXXMAC and REXXLOC control the REXX interface.
|Invoking a REXX Exec|
SAS REXX execs are REXX programs. They are stored in a library that is allocated to the SASREXX DDname (or to another DDname, as specified by the SAS system option REXXLOC=). A REXX exec is submitted as part of a SAS program in the same way as any other global SAS statement.
To run a REXX exec from within SAS, do the following:
Note: You can invoke a REXX exec from
an SCL program, but you should enclose the statement in a SUBMIT block. Otherwise,
the exec will be executed at compile time rather than at run time.
The following example invokes a REXX exec called
YOUREXEC, which resides in
example works in both batch and TSO environments.
options rexxmac; filename sasrexx 'your.rexx.library' disp=shr; yourexec;
In batch, you can also use a JCL DD statement to allocate the REXX library externally:
//jobname JOB ... // EXEC SAS //SASREXX DD DSN=YOUR.REXX.LIBRARY,DISP=SHR //SYSIN DD * options rexxmac; yourexec; /* //
A REXX exec can have zero, one, or multiple arguments. You call the exec by specifying its name, followed by arguments (if any), followed by a semicolon. You can place the exec anywhere that a global SAS statement, such as an OPTIONS or TITLE statement, can be placed.
The exec is invoked when the DATA step is compiled. This means that it is executed only once, rather than for each observation in the DATA step.
A Simple REXX Exec provides an example of a REXX exec called VERIFY that takes as its argument a single data set name. This REXX exec can be invoked by submitting the following statement from a SAS program:
A SAS REXX exec submits SAS statements through the SAS subcommand environment by specifying or defaulting to 'SAS' as its "address". When a REXX exec receives control, the default subcommand environment for that program is 'SAS'. As illustrated in this example, any SAS language statement can then be passed to SAS for execution.
|Interacting with the SAS Session from a REXX Exec|
One of the main advantages of using the REXX interface is that it provides three kinds of communication between the REXX exec and the SAS session:
A set of SAS directives enables a REXX exec to print to the
SAS log. SAS directives use a leading
++ sequence to differentiate
them from normal SAS language statements that are submitted to the SAS subcommand
Three directives are available:
You can use the GETEXEC function in SAS statements that are submitted to the SAS subcommand environment to retrieve the value of any variable in the submitting REXX exec. The syntax of the GETEXEC function is as follows:
|value = GETEXEC(REXX-variable)|
where REXX-variable is a SAS expression that represents the name of a REXX variable in uppercase and value receives the value of the specified REXX variable.
See Using the GETEXEC DATA Step Function
for an example of the GETEXEC function.
You can call the PUTEXEC routine in SAS statements that are submitted to the SAS subcommand environment to assign the value of any variable in the submitting REXX EXEC. The syntax of the PUTEXEC routine is as follows:
|CALL PUTEXEC(REXX-variable, value)|
See Using the PUTEXEC DATA Step Routine
for an example of the PUTEXEC routine.
The REXX special variable RC is always set when any command string is submitted to an external environment.
SAS REXX execs are slightly different from ordinary execs, however, in the way RC is set. When an ordinary exec submits OS/390 commands, the RC variable is set to the command return code when control returns to REXX. The strings that are submitted to SAS, however, are not necessarily complete execution units. SAS collects SAS language elements until a RUN statement is encountered, at which point the SAS step is executed. While partial program fragments are being submitted, the RC is set to 0. The SAS return code is not assigned to the REXX variable RC until the string that contains the RUN statement is submitted.
The RC value is set to the value of the &SYSERR macro variable. See Checking the SAS Return Code in a REXX Exec for an example of how the REXX variable RC can be tested after a SAS step has been executed.
|Changing the Host Command Environment|
When a REXX EXEC that is invoked under SAS receives control, the default host command environment for that program is 'SAS'. You can use the ADDRESS instruction followed by the name of an environment to change to a different host command environment:
address tso address sas address mvs
See Using the GETEXEC DATA Step Function for an example of using the ADDRESS instruction to execute a TSO statement.
You can also use the ADDRESS built-in function to determine which host command environment is currently active:
hcmdenv = address()Use the SUBCOM command to determine whether a host command environment is available before trying to issue commands to that environment. The following example checks to see whether SAS is available:
/* REXX */ address mvs "subcom sas" say "subcom sas rc:" rc if rc = 1 then sas="not " else sas="" say "sas environment is "sas"available"
|Comparing the REXX Interface to the X Statement|
The X statement can be used to invoke a REXX exec. (See X.) However, compared to the REXX interface, the X statement has the following limitations:
|Comparing SAS REXX Execs to ISPF Edit Macros|
In their structure and invocation, SAS REXX execs are analogous to ISPF EDIT macros.
|Examples of REXX Execs|
This REXX exec, called VERIFY, takes as its argument a single data set name. The REXX exec checks to see whether the data set exists. If so, the REXX exec routes a message to the SAS log to that effect. If the data set does not exist, the REXX exec creates the data set and then sends an appropriate message to the SAS log.
/*-------------- REXX exec VERIFY --------------*/ Parse Upper Arg fname . retcode = Listdsi("'"fname"'") If retcode = 0 Then Do Address SAS "++SASLOG" fname "already exists" End Else Do Address TSO "ALLOC FI(#TEMP#) DA('"fname"') RECFM(FB) LRECL(80) BLKSIZE(6160) DSORG(PS) SPACE(10 5) TRACK NEW" Address SAS "++SASLOG" fname "created" Address TSO "FREE FI(#TEMP#)" End Exit
This REXX exec executes a TSO command that generates a list of all filenames beginning with a specified prefix, then deletes the files named in the list and places the names of the deleted files in a SAS data set.
/*------------- REXX exec DELDIR --------------*/ Parse Upper Arg file_prefx . /*------ Execute the TSO LISTC Command --------*/ x = Outtrap('list.') Address TSO "LISTC LVL('"FILE_PREFX"') " /*--- Process Output from the LISTC Command ---*/ idx = 0 file_del.= '' Do line = 1 To list.0 By 1 Parse Var list.line word1 word2 word3 If word1 = 'NONVSAM' Then Do fname = word3 Address TSO "DELETE '"fname"'" idx = idx + 1 file_del.idx = fname file_stat.idx = 'DELETED' End End /*--- Pass a DATA step into the SAS System ----*/ Address SAS '++SASLOG' "data results (keep = dsname status); " " total = getexec('IDX'); " " put 'Total OS/390 files deleted: ' total; " " do i = 1 to total; " " dsnm = getexec('FILE_DEL.' || trim(left(i)));" " stat = getexec('FILE_STAT.' || trim(left(i)));" " output; " " end; " " run; " /*---------- Execute a SAS Procedure ----------*/ " proc print; " " run; " /*---------- Return to the SAS System ---------*/ Exit
This REXX exec reads a set of high-level qualifiers from a SAS data set and writes them to REXX stem variables so that they can be processed by the REXX exec. Then the REXX exec loops through the high-level qualifiers, calling the DELDIR routine for each one in turn.
/*------------ REXX exec DELMANY -------------*/ /* Accepts as arguments up to 5 high-level */ /* qualifiers Parse Upper Arg arg1 arg2 arg3 arg4 arg5 . hlq.='' /*-=- Pass a DATA step into the SAS System ---*/ Address SAS '++SASLOG' " data prefixes; " " input prefix $ 1-20; " " cards; " ""arg1 ""arg2 ""arg3 ""arg4 ""arg5 "run; " " data _null_; " " set prefixes; " " rexxvar = 'HLQ.' || trim(left(_N_)); " " call putexec(trim(rexxvar),prefix); " " call putexec('HLQ.0', trim(left(_N_))); " " run; " /*---------- Call the DELDIR REXX exec -------*/ Do idx = 1 To hlq.0 pre = hlq.idx Call deldir pre End /*------------ Return to SAS -----------------*/ Exit rc
This REXX exec, called SHOWRC, demonstrates how the REXX variable RC can be tested after a SAS step has run:
/*-------------- REXX exec SHOWRC ------------*/ /* Accepts as argument a SAS data set */ Parse Upper Arg ds_name . Address SAS '++SASLOG' "data newdata; " " set "ds_name"; " " run; " If rc = 0 Then Say 'SAS DATA step completed successfully' Else Say 'SAS DATA step terminated with rc=' rc Exit
Top of Page
Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.