DATA Step, Macro, Functions and more

adding "return code" to a macro

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 18
Accepted Solution

adding "return code" to a macro

I have a macro which, when executed, sets a global variable (named &SearchResult) to a 1 or 0. I would instead prefer the macro itself evaluate to 1 or 0, without having to set a global variable.

 

BTW - this will be used for program control. The macro is checking whether a log file contains the word SUCCESS, and if so, the main program is allowed to continue processing.

 

Here is what I have now:

%macro CheckFileForString(FilenameAndPath=,
                          SearchString=);
%global SearchResult; %let SearchResult = 0; /* default unless the string is found */

/* scan FilenameAndPath for SearchString */ filename finp ("&FilenameAndPath"); data result; infile finp filename = _filepath truncover; input a_line $1000.; /* read first 1000 bytes of each line */ if find(a_line,"&SearchString") then do;  call symput('SearchResult',1); /* set the return code */ end; run; %mend; %macro main_program; /* search a log file for the string SUCCESS */ %CheckFileForString(FilenameAndPath=C:\TEMP\LOGFILE.LOG, SearchString= SUCCESS);
%IF &SearchResult = 1 %THEN
%PUT NOTE: Processing can continue;
%ELSE %PUT ERROR: The log file does not contain the word SUCCESS. Processing must halt; %mend; %main_program;

Here is how I would prefer to setup %main_program. %CheckFileForString needs to evaluate to a 1 or 0, but I'm not sure how to accomplish that.

%macro main_program;
/* check if a log file contains the word SUCCESS */ %IF %CheckFileForString(FilenameAndPath=C:\TEMP\LCM_PYLOG.LOG, SearchString= SUCCESS) = 1 %THEN
%PUT NOTE: Processing can continue; %ELSE %PUT ERROR: The log file does not contain the word SUCCESS. Processing must halt; %mend; %main_program;

 


Accepted Solutions
Solution
a week ago
Trusted Advisor
Posts: 1,259

Re: adding "return code" to a macro

So, you may want to combine what @andreas_lds and @ballardw have suggested:

  1. Avoid SAS code in macro CheckFileForString.
  2. Let the macro code end with a (local) macro variable reference.

The result, a (preliminary) function-style version of CheckFileForString, could look something like this:

%macro CheckFileForString(FilenameAndPath=,
                          SearchString=);
%local SearchResult filrf rc fid c;
%let SearchResult = 0; /* default unless the string is found */
%let filrf=srcf;
%let rc=%sysfunc(filename(filrf, &FilenameAndPath));
%let fid=%sysfunc(fopen(&filrf));
%if &fid > 0 %then %do;
  %do %while(%sysfunc(fread(&fid))=0);
    %let rc=%sysfunc(fget(&fid, c, 1000)); /* read first 1000 bytes of each line */
    %if %index(%superq(c), &SearchString) %then %let SearchResult=1; /* set the return code */
  %end;
  %let rc=%sysfunc(fclose(&fid));
%end;
%let rc=%sysfunc(filename(filrf));
&SearchResult
%mend CheckFileForString;

View solution in original post


All Replies
Occasional Contributor
Posts: 17

Re: adding "return code" to a macro

You don't want to use SYSCC?

 

You can add this in the beginning of your code

%Let syscc=0; ** Operating Environment Condition Code **;

 

And after each macro, you can add this into your code:

if &syscc>0 then your log message.

 

From SAS notes (Usage Note 35553)

:

SYSCC is a read/write automatic macro variable that enables you to reset the job condition code and to recover from conditions that prevent subsequent steps from running. The values for SYSCC are:

  • 0 is no errors no warnings
  • 4 is warnings
  • > 4 is an error occurred
Occasional Contributor
Posts: 18

Re: adding "return code" to a macro

I was not aware of SYSCC - it sounds very useful for trapping unexpected errors. Thank you!

 

If you don't mind, could you please demonstrate how I would incorporate this logic? If I'm not mistaken, my %CheckFileForString macro does not generate an "error" per se, even if the string isn't found.

 

Or are you simply suggesting that I replace my own &SearchResult with &SYSCC?

Super User
Posts: 13,583

Re: adding "return code" to a macro

Here is one way to expose a single value without a global macro variable:

%macro dummy (value);
   %if &value=10 %then %let result=1;
   %else %let result=0;
   &result
%mend;

%macro main_program;
   /* search a log file for the string SUCCESS */
 
 %IF %dummy(10) = 1 %THEN 
   %PUT NOTE: Processing can continue;
 %ELSE 
   %PUT ERROR: The value is not 10. Processing must halt;
%mend;

%main_program;

The local macro variable result exposed as a single statement without any ; to end the statement.

 

Test other values with something like:

%put %dummy(5);

 

You might want to include a LRECL parameter on our INFILE statement.

Occasional Contributor
Posts: 18

Re: adding "return code" to a macro

Thank you! I don't have much experience working with infile (usually, I work with existing SAS datasets)

 and I appreciate you pointing out my omission of LRECL.

 

Valued Guide
Posts: 584

Re: adding "return code" to a macro

Macros returning values can't use data-steps or procs, only macro-code is allowed. In the following example sashelp.class is not printed, but the code is returned to the calling macro.

 

%macro dummy;
   %local z;
   %let z = 100;
  
   proc print data=sashelp.class;
   run;

   &z.

%mend;

%macro testbox;
   %local result;
   %let result = %dummy;
   %put -----------;
   %put &result.;
   %put -----------;
%mend;

%testbox;
Occasional Contributor
Posts: 18

Re: adding "return code" to a macro

Posted in reply to andreas_lds

I definitely need to learn more about when macros resolve to "text" and when they resolve to "executetable code". Your example helps with that understanding. Thanks!

 

 

Solution
a week ago
Trusted Advisor
Posts: 1,259

Re: adding "return code" to a macro

So, you may want to combine what @andreas_lds and @ballardw have suggested:

  1. Avoid SAS code in macro CheckFileForString.
  2. Let the macro code end with a (local) macro variable reference.

The result, a (preliminary) function-style version of CheckFileForString, could look something like this:

%macro CheckFileForString(FilenameAndPath=,
                          SearchString=);
%local SearchResult filrf rc fid c;
%let SearchResult = 0; /* default unless the string is found */
%let filrf=srcf;
%let rc=%sysfunc(filename(filrf, &FilenameAndPath));
%let fid=%sysfunc(fopen(&filrf));
%if &fid > 0 %then %do;
  %do %while(%sysfunc(fread(&fid))=0);
    %let rc=%sysfunc(fget(&fid, c, 1000)); /* read first 1000 bytes of each line */
    %if %index(%superq(c), &SearchString) %then %let SearchResult=1; /* set the return code */
  %end;
  %let rc=%sysfunc(fclose(&fid));
%end;
%let rc=%sysfunc(filename(filrf));
&SearchResult
%mend CheckFileForString;
Occasional Contributor
Posts: 18

Re: adding "return code" to a macro

Posted in reply to FreelanceReinhard

Thank you - I see you also improved how the macro works with the file, which I appreciate!

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 8 replies
  • 119 views
  • 0 likes
  • 5 in conversation