In this sample program, the deepest invoked macro has an options statement to turn off mprinting. However, the macro is invoked via CALL EXECUTE, and not sure why the MPRINT continues anyway. Why would that be ?
%macro foo; options nomprint; /* mprint continues anyway ? */ data _null_; * not quite inception level oddness; set sashelp.cars(obs=1); if make = 'x' then put 'really?'; run; options mprint; %mend; %macro doit; data _null_; call execute ('%foo;'); run; %mend; options mprint; %doit; options nomprint;
Will log
MPRINT(DOIT): data _null_;
MPRINT(DOIT): call execute ('%foo;');
MPRINT(DOIT): run;
MPRINT(FOO): options nomprint;
MPRINT(FOO): data _null_;
MPRINT(FOO): * not quite inception level oddness;
MPRINT(FOO): set sashelp.cars(obs=1);
MPRINT(FOO): if make = 'x' then put 'really?';
MPRINT(FOO): run;
MPRINT(FOO): options mprint;
It is just another symptom of timing issue when submitting macro calls via CALL EXECUTE().
You used single quotes to prevent the macro from running while the data step is compiled. But becuase you did not wrap the macro call in %NRSTR() the macro actually ran while the data step was executing and the resulting code was pushed onto the stack to run.
You left out the key part of the SAS log that shows that:
NOTE: CALL EXECUTE generated line. 1 + options nomprint; 1 + data _null_; * not quite inception level oddness; set sashelp.cars(obs=1); if make = 'x' then put 'really?'; run; NOTE: There were 1 observations read from the data set SASHELP.CARS.
So just fix your CALL EXECUTE() string.
data _null_;
call execute ('%nrstr(%foo);');
run;
And now the lines of generated code that CALL EXECUTE() shows are also clearer, showing the macro call you actually passed, not the code that the macro you called generated.
MPRINT(DOIT): %foo; NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds NOTE: CALL EXECUTE generated line. 1 + %foo; MPRINT(FOO): options nomprint; NOTE: There were 1 observations read from the data set SASHELP.CARS.
It is just another symptom of timing issue when submitting macro calls via CALL EXECUTE().
You used single quotes to prevent the macro from running while the data step is compiled. But becuase you did not wrap the macro call in %NRSTR() the macro actually ran while the data step was executing and the resulting code was pushed onto the stack to run.
You left out the key part of the SAS log that shows that:
NOTE: CALL EXECUTE generated line. 1 + options nomprint; 1 + data _null_; * not quite inception level oddness; set sashelp.cars(obs=1); if make = 'x' then put 'really?'; run; NOTE: There were 1 observations read from the data set SASHELP.CARS.
So just fix your CALL EXECUTE() string.
data _null_;
call execute ('%nrstr(%foo);');
run;
And now the lines of generated code that CALL EXECUTE() shows are also clearer, showing the macro call you actually passed, not the code that the macro you called generated.
MPRINT(DOIT): %foo; NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds NOTE: CALL EXECUTE generated line. 1 + %foo; MPRINT(FOO): options nomprint; NOTE: There were 1 observations read from the data set SASHELP.CARS.
To add to the confusion, any symbol (macro variable) resolutions in macro calls invoked via the EXECUTE are resolved during the DATA Step run-time, not during the normally presumed stacked code submission time. This can cause EXCUTE invoked macro calls to behave unintuitive ways.
%NRSTR can be used to stack macro invocation for submission after the step completes. That is why you might see
call execute ('%nrstr(%myMacro(arg=' || data-step-var || '))' );
Such a call forces macro logic and evaluations within the macro and step code it generates to occur linearly at macro invocation time.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.