Reputation: 6378
Is there a system option or similar that will automatically echo macro invocations to the SAS log? When debugging code, I would like to see in the log every macro invocation, including what parameters were passed.
So that if I submit %Test(x=1) the log will show something like:
MACRO INVOKED: %TEST(x=1)
When calling a macro in open code, this is not an issue, because the macro call is shown in the usual log. But when outer macros call inner macros, the actual call to %inner is not shown by default. I tried turning on MLOGIC, MPRINT, etc, but couldn't find something that would show me the macro call itself. I think what I want is an MINVOCATION option.
Below I fake an MINVOCATION option by adding /parmbuff to macro definitions, but was hoping for a way to see macro calls without mucking with the macro definition.
%macro test(x=0,y=0,debug=0) /parmbuff ;
%if &debug %then %put MINVOCATION: %nrstr(%%)&sysmacroname&syspbuff ;
data _null_ ;
x=&x ;
y=&y ;
put x= y= ;
run ;
%mend test ;
%macro outer(debug=0) /parmbuff ;
%if &debug %then %put MINVOCATION: %nrstr(%%)&sysmacroname&syspbuff ;
%test(x=1,debug=&debug)
%test(x=1,y=2,debug=&debug)
%mend outer ;
options mprint mprintnest ;
%outer(debug=1)
Returns the desired:
908 options mprint mprintnest ;
909 %outer(debug=1)
MINVOCATION: %OUTER(debug=1)
MINVOCATION: %TEST(x=1,debug=1)
MPRINT(OUTER.TEST): data _null_ ;
MPRINT(OUTER.TEST): x=1 ;
MPRINT(OUTER.TEST): y=0 ;
MPRINT(OUTER.TEST): put x= y= ;
MPRINT(OUTER.TEST): run ;
x=1 y=0
MINVOCATION: %TEST(x=1,y=2,debug=1)
MPRINT(OUTER.TEST): data _null_ ;
MPRINT(OUTER.TEST): x=1 ;
MPRINT(OUTER.TEST): y=2 ;
MPRINT(OUTER.TEST): put x= y= ;
MPRINT(OUTER.TEST): run ;
x=1 y=2
Upvotes: 1
Views: 561
Reputation: 63424
If you're willing to update all of your macros, which it sounds like you'd have to do anyways, then what about adding:
%put _local_;
at the top of each? At macro invocation, the only local macro variables defined will be those parameters, right?
%macro mymacro(x=,y=,z=);
%put _local_;
proc print data=sashelp.class;
run;
%mend mymacro;
%mymacro(x=1,y=2);
Gives a log of:
08 %mymacro(x=1,y=2);
MYMACRO X 1
MYMACRO Y 2
MYMACRO Z
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.05 seconds
cpu time 0.03 seconds
You could always also put the macro name in there:
%macro mymacro(x=,y=,z=);
%put MACRO INVOKED: &sysmacroname;
%put Parameters:;
%put _local_;
proc print data=sashelp.class;
run;
%mend mymacro;
%mymacro(x=1,y=2);
Though it's returned as part of the %put _local_
so it's probably extraneous.
Upvotes: 0
Reputation: 8513
I think you may be looking for option mlogic
.
Example code:
option mprint mlogic ;
%macro y(blah);
%put &blah;
%mend;
%macro x();
%y(hello);
%put x;
%mend;
%x;
Gives:
MLOGIC(X): Beginning execution.
MLOGIC(Y): Beginning execution.
MLOGIC(Y): Parameter BLAH has value hello
MLOGIC(Y): %PUT &blah
hello
MLOGIC(Y): Ending execution.
MPRINT(X): ;
MLOGIC(X): %PUT x
x
MLOGIC(X): Ending execution.
You can see it tells you when the macro begins execution, which macro is executing, and also the value of any paramters passed in.
Based on your clarifications, this was the closest I could find. Basically you need to setup a libname for 'stored' macros. When you define your macro, add the options / store source
to tell it to store the source code for the macro into the stored macro library:
libname mac "e:\temp";
option mstored sasmstore=mac;
%macro blah(something=whatever) / store source;
%put hi;
%mend;
You can later retrieve the source code by using the %copy
macro (SAS v9+). This macro has options to write the source to a file rather than the log. You can then read in the file and extract the default parameter values yourself.
%COPY blah / source;
Gives:
%macro blah(something=whatever) / store source;
%put hi;
%mend;
This whitepaper goes into additional details.
It's a lot of extra steps I know but that seems to be a pretty unusual request.
You may be better off rethinking your strategy. For example, a far simpler method might simply be to define your defaults this way:
%macro hasDefaults(x=1,y=2);
%local default_x default_y;
%let default_x = 1;
%let default_y = 2;
%if &x ne &default_x %then %do;
%put The default for x was changed from &default_x to &x.;
%end;
%mend;
This is far from ideal as well, but you'll have to weigh up what will work better for your needs.
Upvotes: 1