Quentin
Quentin

Reputation: 6378

Echo SAS macro invocation to SAS log

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

Answers (2)

Joe
Joe

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

Robert Penridge
Robert Penridge

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.

UPDATE

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

Related Questions