Interfaces with the Macro Facility
Interfaces with the Macro Facility
Interacting with the Macro Facility during DATA Step Execution
CALL EXECUTE Routine Timing Details
Example of Using CALL EXECUTE Incorrectly
Example of Common Problem with CALL EXECUTE
Using SAS Language Functions in the DATA Step and Macro Facility
Interfaces with the SQL Procedure
Interfaces with the SAS Component Language
How Macro References Are Resolved by SCL
Referencing Macro Variables in Submit Blocks
Considerations for Sharing Macros between SCL Programs
Example Using Macros in an SCL Program
Using %SYSRPUT with SAS/CONNECT
Example Using %SYSRPUT to Check the Value of a Return Code on a Remote Host
An interface with the macro facility is not part of the macro processor but rather a SAS software feature that enables another portion of the SAS language to interact with the macro facility during execution. For example, a DATA step interface enables you to access macro variables from the DATA step. Macro facility interfaces are useful because, in general, macro processing happens before DATA step, SQL, SCL, or SAS/CONNECT execution. The connection between the macro facility and the rest of SAS is not usually dynamic. But by using an interface to the macro facility, you can dynamically connect the macro facility to the rest of SAS.
Note: The %SYSFUNC and %QSYSFUNC macro functions enable you to use SAS language functions with the macro processor. The %SYSCALL macro statement enables you to use SAS language CALL routines with the macro processor. These elements of the macro language are not considered true macro facility interfaces and they are discussed in this section. See “Macro Language Elements” on page 159 for more information about these macro language elements.
DATA step interfaces consist of eight tools that enable a program to interact with the macro facility during DATA step execution. Because the work of the macro facility takes place before DATA step execution begins, information provided by macro statements has already been processed during DATA step execution. You can use one of the DATA step interfaces to interact with the macro facility during DATA step execution. You can use DATA step interfaces to do the following:
• pass information from a DATA step to a subsequent step in a SAS program
• invoke a macro based on information available only when the DATA step executes
• resolve a macro variable while a DATA step executes
• delete a macro variable
• pass information about a macro variable from the macro facility to the DATA step
The following table lists the DATA step interfaces by category and their uses.
Table 8.1 DATA Step Interfaces to the Macro Facility
CALL EXECUTE is useful when you want to execute a macro conditionally. But you must remember that if CALL EXECUTE produces macro language elements, those elements execute immediately. If CALL EXECUTE produces SAS language statements, or if the macro language elements generate SAS language statements, those statements execute after the end of the DATA step’s execution.
Note: Macro references execute immediately and SAS statements do not execute until after a step boundary. You cannot use CALL EXECUTE to invoke a macro that contains references for macro variables that are created by CALL SYMPUT in that macro.
In this example, the CALL EXECUTE routine is used incorrectly:
data prices; /* ID for price category and actual price */
input code amount;
datalines;
56 300
99 10000
24 225
;
%macro items;
%global special;
%let special=football;
%mend items;
data sales; /* incorrect usage */
set prices;
length saleitem $ 20;
call execute('%items'),
saleitem="&special";
run;
In the DATA SALES step, the assignment statement for SALEITEM requires the value of the macro variable SPECIAL at DATA step compilation. CALL EXECUTE does not produce the value until DATA step execution. Thus, you receive a message about an unresolved macro variable, and the value assigned to SALEITEM is &special.
In this example, it would be better to eliminate the macro definition (the %LET macro statement is valid in open code) or move the DATA SALES step into the macro ITEMS. In either case, CALL EXECUTE is not necessary or useful. Here is one version of this program that works:
data prices; /* ID for price category and actual price */
input code amount;
datalines;
56 300
99 10000
24 225
;
%let special=football; /* correct usage */
data sales;
set prices;
length saleitem $ 20;
saleitem="&special";
run;
The %GLOBAL statement is not necessary in this version. Because the %LET statement is executed in open code, it automatically creates a global macro variable. (See “Scopes of Macro Variables” on page 47 for more information about macro variable scopes.)
This example shows a common pattern that causes an error.
/* This version of the example shows the problem. */
data prices; /* ID for price category and actual price */
input code amount;
cards;
56 300
99 10000
24 225
;
data names; /* name of sales department and item sold */
input dept $ item $;
datalines;
BB Boat
SK Skates
;
%macro items(codevar=); /* create macro variable if needed */
%global special;
data _null_;
set names;
if &codevar=99 and dept='BB' then call symput('special', item);
run;
%mend items;
data sales; /* attempt to reference macro variable fails */
set prices;
length saleitem $ 20;
if amount > 500 then
call execute('%items(codevar=' || code || ')' );
saleitem="&special";
run;
In this example, the DATA SALES step still requires the value of SPECIAL during compilation. The CALL EXECUTE routine is useful in this example because of the conditional IF statement. But as in the first example, CALL EXECUTE still invokes the macro ITEMS during DATA step execution — not during compilation. The macro ITEMS generates a DATA _NULL_ step that executes after the DATA SALES step has ceased execution. The DATA _NULL_ step creates SPECIAL, and the value of SPECIAL is available after the _NULL_ step ceases execution, which is much later than when the value was needed.
This version of the example corrects the problem:
/* This version solves the problem. */
data prices; /* ID for price category and actual price */
input code amount;
datalines;
56 300
99 10000
24 225
;
data names; /* name of sales department and item sold */
input dept $ item $;
cards;
BB Boat
SK Ski
;
%macro items(codevar=); /* create macro variable if needed */
%global special;
data _null_;
set names;
if &codevar=99 and dept='BB' then
call symput('special', item);
run;
%mend items;
data _null_; /* call the macro in this step */
set prices;
if amount > 500 then
call execute('%items(codevar=' || code || ')' );
run;
data sales; /* use the value created by the macro in this step */
set prices;
length saleitem $ 20;
saleitem="&special";
run;
This version uses one DATA _NULL_ step to call the macro ITEMS. After that step ceases execution, the DATA _NULL_ step generated by ITEMS executes and creates the macro variable SPECIAL. Then the DATA SALES step references the value of SPECIAL as usual.
The macro functions %SYSFUNC and %QSYSFUNC can call SAS language functions and functions written with SAS/TOOLKIT software to generate text in the macro facility. %SYSFUNC and %QSYSFUNC have one difference: the %QSYSFUNC masks special characters and mnemonics and %SYSFUNC does not. For more information about these functions, see “%SYSFUNC and %QSYSFUNC Functions” on page 278.
%SYSFUNC arguments are a single SAS language function and an optional format. See the following examples:
%sysfunc(date(),worddate.)
%sysfunc(attrn(&dsid,NOBS))
You cannot nest SAS language functions within %SYSFUNC. However, you can nest %SYSFUNC functions that call SAS language functions, as in the following statement:
%sysfunc(compress(%sysfunc(getoption(sasautos)),%str(%)%(%')))
This example returns the value of the SASAUTOS= system option, using the COMPRESS function to eliminate opening parentheses, closing parentheses, and single quotation marks from the result. Note the use of the %STR function and the unmatched parentheses and quotation marks that are marked with a percent sign (%).
All arguments in SAS language functions within %SYSFUNC must be separated by commas. You cannot use argument lists preceded by the word OF.
Because %SYSFUNC is a macro function, you do not need to enclose character values in quotation marks as you do in SAS language functions. For example, the arguments to the OPEN function are enclosed in quotation marks when the function is used alone but do not require quotation marks when used within %SYSFUNC.
Here are some examples of the contrast between using a function alone and within %SYSFUNC:
• dsid = open("Sasuser.Houses","i");
• dsid = open("&mydata","&mode");
• %let dsid = %sysfunc(open(Sasuser.Houses,i));
• %let dsid = %sysfunc(open(&mydata,&mode));
You can use %SYSFUNC and %QSYSFUNC to call all of the DATA step SAS functions except the ones that are listed in table Table 17.2 on page 279. In the macro facility, SAS language functions called by %SYSFUNC can return values with a length up to 32K. However, within the DATA step, return values are limited to the length of a data set character variable.
The %SYSCALL macro statement enables you to use SAS language CALL routines with the macro processor, and it is described in “Macro Statements” on page 291.
Structured Query Language (SQL) is a standardized, widely used language for retrieving and updating data in databases and relational tables. SAS software’s SQL processor enables you to do the following:
• create tables and views
• retrieve data stored in tables
• retrieve data stored in SQL and SAS/ACCESS views
• add or modify values in tables
• add or modify values in SQL and SAS/ACCESS views
SQL provides the INTO clause in the SELECT statement for creating SAS macro variables. You can create multiple macro variables with a single INTO clause. The INTO clause follows the same scoping rules as the %LET statement. See “Macro Variables” on page 21 for a summary of how macro variables are created. For further details and examples relating to the INTO clause, see “INTO Clause” on page 287.
PROC SQL also provides macro tools to do the following:
• stop execution of a job if an error occurs
• execute programs conditionally based on data values
The following table provides information about macro variables created by SQL that affect job execution.
Table 8.2 Macro Variables That Affect Job Execution
You can use the SAS macro facility to define macros and macro variables for an SCL program. Then, you can pass parameters between macros and the rest of the program. Also, through the use of the autocall and compiled stored macro facilities, macros can be used by more than one SCL program.
Note: Macro modules can be more complicated to maintain than a program segment because of the symbols and macro quoting that might be required. Also, implementing modules as macros does not reduce the size of the compiled SCL code. Program statements generated by a macro are added to the compiled code as if those lines existed at that location in the program.
The following table lists the SCL macro facility interfaces.
Table 8.3 SCL Interfaces to the Macro Facility
Category |
Tool |
Description |
Read or Write |
SYMGET |
Returns the value of a global macro variable during SCL execution. |
|
SYMGETN |
Returns the value of a global macro variable as a numeric value. |
|
CALL SYMPUT |
Assigns a value produced in SCL to a global macro variable. |
|
CALL SYMPUTN |
Assigns a numeric value to a global macro variable. |
Note: It is inefficient to use SYMGETN to retrieve values that are not assigned with SYMPUTN. It is also inefficient to use & to reference a macro variable that was created with CALL SYMPUTN. Instead, use SYMGETN. In addition, it is inefficient to use SYMGETN and CALL SYMPUTN with values that are not numeric.
For details about these elements, see “DATA Step Call Routines for Macros” on page 231 and “DATA Step Functions for Macros” on page 241.
An important point to remember when using the macro facility with SCL is that macros and macro variable references in SCL programs are resolved when the SCL program compiles, not when you execute the application. To further control the assignment and resolution of macros and macro variables, use the following techniques:
• If you want macro variables to be assigned and retrieved when the SCL program executes, use CALL SYMPUT and CALL SYMPUTN in the SCL program.
• If you want a macro call or macro variable reference to resolve when an SCL program executes, use SYMGET and SYMGETN in the SCL program.
In SCL, macro variable references are resolved at compile time unless they are in a Submit block. When SCL encounters a name prefixed with an ampersand (&) in a Submit block, it checks whether the name following the ampersand is the name of an SCL variable. If so, SCL substitutes the value of the corresponding variable for the variable reference in the submit block. If the name following the ampersand does not match any SCL variable, the name passes intact (including the ampersand) with the submitted statements. When SAS processes the statements, it attempts to resolve the name as a macro variable reference
To guarantee that a name is passed as a macro variable reference in submitted statements, precede the name with two ampersands (for example, &&DSNAME). If you have both a macro variable and an SCL variable with the same name, a reference with a single ampersand substitutes the SCL variable. To force the macro variable to be substituted, reference it with two ampersands (&&).
Sharing macros between SCL programs can be useful, but it can also raise some configuration management problems. If a macro is used by more than one program, you must keep track of all the programs that use it so that you can recompile all of them each time the macro is updated. Because SCL is compiled, each SCL program that calls a macro must be recompiled whenever that macro is updated.
CAUTION:
Recompile the SCL program. If you fail to recompile the SCL program when you update the macro, you run the risk of the compiled SCL being out of sync with the source.
This SCL program is for an example application with the fields BORROWED, INTEREST, and PAYMENT. The program uses the macros CKAMOUNT and CKRATE to validate values entered into fields by users. The program calculates the payment, using values entered for the interest rate (INTEREST) and the sum of money (BORROWED).
/* Display an error message if AMOUNT */
/* is less than zero or larger than 1000. */
%macro ckamount(amount);
if (&amount < 0) or (&amount > 1000) then
do;
erroron borrowed;
_msg_='Amount must be between $0 and $1,000.';
stop;
end;
else erroroff borrowed;
%mend ckamount;
/* Display an error message if RATE */
/* is less than 0 or greater than 1.5 */
%macro ckrate(rate);
if (&rate < 0) or (&rate > 1) then
do;
erroron interest;
_msg_='Rate must be between 0 and 1.5';
stop;
end;
else erroroff interest;
%mend ckrate;
/* Open the window with BORROWED at 0 and INTEREST at .5. */
INIT:
control error;
borrowed=0;
interest=.5;
return;
MAIN:
/* Run the macro CKAMOUNT to validate */
/* the value of BORROWED. */
%ckamount(borrowed)
/* Run the macro CKRATE to validate */
/* the value of INTEREST. */
%ckrate(interest)
/* Calculate payment. */
payment=borrowed*interest;
return;
TERM:
return;
The %SYSRPUT macro statement is submitted with SAS/CONNECT to a remote host to retrieve the value of a macro variable stored on the remote host. %SYSRPUT assigns that value to a macro variable on the local host. %SYSRPUT is similar to the %LET macro statement because it assigns a value to a macro variable. However, %SYSRPUT assigns a value to a variable on the local host, not on the remote host where the statement is processed. The %SYSRPUT statement places the macro variable in the current scope of the local host.
Note: The names of the macro variables on the remote and local hosts must not contain a leading ampersand.
The %SYSRPUT statement is useful for capturing the value of the automatic macro variable SYSINFO and passing that value to the local host. SYSINFO contains return-code information provided by some SAS procedures. Both the UPLOAD and the DOWNLOAD procedures of SAS/CONNECT can update the macro variable SYSINFO and set it to a nonzero value when the procedure terminates due to errors. You can use %SYSRPUT on the remote host to send the value of the SYSINFO macro variable back to the local SAS session. Thus, you can submit a job to the remote host and test whether a PROC UPLOAD or DOWNLOAD step has successfully completed before beginning another step on either the remote host or the local host.
To use %SYSRPUT, you must have invoked a remote SAS windowing environment session by submitting the DMR option with the SAS command. For details about using %SYSRPUT, see the SAS/CONNECT documentation.
To create a new macro variable or to modify the value of an existing macro variable on a remote host or a server, use the %SYSLPUT macro statement.
This example illustrates how to download a file and return information about the success of the step. When remote processing is completed, the job checks the value of the return code stored in RETCODE. Processing continues on the local host if the remote processing is successful. In this example, the %SYSRPUT statement follows a PROC DOWNLOAD step, so the value returned by SYSINFO indicates the success of the PROC DOWNLOAD step:
/* This code executes on the remote host. */
rsubmit;
proc download data=remote.mydata out=local.mydata;
run;
/* RETCODE is on the local host. */
/* SYSINFO is on the remote host. */
%sysrput retcode=&sysinfo;
endrsubmit;
/* This code executes on the local host. */
%macro checkit;
%if &retcode = 0 %then
%do;
further processing on local host
%end;
%mend checkit;
%checkit
To determine the success or failure of a step executed on a remote host, use the %SYSRPUT macro statement to check the value of the automatic macro variable SYSERR.
For more details and syntax of the %SYSRPUT statement, see “%SYSRPUT Statement” on page 330.
The %SYSLPUT statement is a macro statement that is submitted in the client session to assign a value that is available in the client session to a macro variable that can be accessed from the server session. If you are signed on to multiple server sessions, %SYSLPUT submits the macro assignment statement to the most recently used server session. If you are signed on to only one server session, %SYSLPUT submits the macro assignment statement to that server session. If you are not signed on to any session, an error condition results. Like the %LET statement, the %SYSLPUT statement assigns a value to a macro variable. Unlike %LET, the %SYSRPUT statement assigns a value to a variable in the server session rather than in the client session where the statement is executed. The %SYSRPUT statement stores the macro variable in the Global Symbol Table in the server session.
For details about using %SYSLPUT, see the SAS/CONNECT documentation.
%SYSLPUT enables you to dynamically assign values to variables that are used by macros that are executed in a server session. The macro statement %SYSLPUT is used to create the macro variable REMID in the server session and to use the value of the client macro variable RUNID. The REMID variable is used by the %DOLIB macro, which is executed in a server session. This process finds out which operating system-specific library assignment should be used in the server session.
%macro assignlib (runid);
signon rem &runid
%syslput remid=&runid
rsubmit rem &runid
%macro dolib;
%if (&runid eq 1) %then %do;
libname mylib 'h:';
%end;
%else %if (&runid eq 2) %then %do;
libname mylib '/afs/some/unix/path';
%end;
%mend;
%dolib;
endrsubmit;
%mend;
18.220.184.6