There is a documented oddity that the automatic macro variable SYSINCLUDEFILENAME won't resolve inside a macro.
The docs say:
Restriction: This variable does not resolve in a macro definition that is included with the %INCLUDE statement. To resolve in included code, the reference must be outside of a macro definition. See Using the SYSINCLUDEFILE Automatic Macro Variables in Included Macro Definitions.
https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n19hjgfztbsglan14ekohdzq5s97.htm
While the docs suggest the problem relates to the macro definition being in the %included file, it also happens when just the macro call is in an %included file.
Does anyone understand why this would happen? I've never known a macro variable that exists in a symbol table but can't be resolved when a macro executes.
I played with it a little, and found that even though the reference to SYSINCLUDEFILENAME won't resolve (or maybe it resolves to null), if you use %put _automatic_ inside a macro, it will show that the automatic macro variable SYSINCLUDEFILENAME has a value.
So this means it's there in the symbol table (assuming we can trust that %put _automatic_ isn't doing any trickery to make it appear), but for some reason it can't be resolved. This doesn't make any sense to me.
Again, I know it's documented. But trying to understand oddities like this sometimes provide insights into the inner workings of the macro language.
My test code:
%macro try() ;
%put Inside Macro sysincludefilename is empty: &=sysincludefilename ;
%put ;
%put But %nrstr(%%)put _automatic_ in the macro shows sysincludefilename has a value ;
%put _automatic_ ;
%mend try ;
filename code "%sysfunc(pathname(work))/myinclude.sas";
data _null_ ;
file code ;
put
'%put Open Code: &=sysincludefilename ;'
/'%try()'
;
run;
%include code / source2;
Without knowing how SAS actually works internally we can only guess.
Either it was on purpose for some reason, or it was a side effect of how include files and macro calls work and they decided rather than change it to just document the behavior.
It is also not there in the SASHELP.VMACRO values for while a macro is running.
If you need it in the macro you need to push it in when you CALL the macro:
%macro try(caller) ;
%put Inside Macro sysincludefilename is empty: &=sysincludefilename &=caller;
%mend try ;
filename code temp;
data _null_ ;
file code ;
put
'%put Open Code: &=sysincludefilename ;'
/'%try(&sysincludefilename)'
;
run;
My new theory is that when code is generated (e.g. by the macro processor executing a macro), SYSINCLUDEFILENAME is not assigned a value. So in order for SYSINCLUDEFILENAME to have a value, it means tokens are literally being read from the %include file.
I tried CALL EXECUTE. If you %INCLUDE a file that uses CALL EXECUTE to generate a PUT statement to resolve SYSINCLUDEFILENAME, it also returns null. So my guess is the limitation is in the method used to assign a value to SYSINCLUDEFILENAME. I think it sees code that has been generated (by some code in the include file) as not being code that came from the current include file.
I think I'm happier with this being an issue with how/when SYSINCLUDEFILENAME is given a value, rather than it being an issue with the macro language not being able to resolve a a macro variable. And it also fits with the original example. It's not really that the macro variable does not resolve (which is what the docs says, imprecisely). It's that the macro variable resolves to a null value, which is indeed the value of the macro variable when there is no current %include file. That said, I still don't understand why %put _automatic_ inside a macro would show that SYSINCLUDEFILENAME has a value.
My call execute test:
filename code "%sysfunc(pathname(work))/myinclude.sas";
data _null_ ;
file code ;
put
/'data null ; '
/' put "Non-generated code sysincludefilename=&sysincludefilename sysvlong=&sysvlong" ; '
/' call execute(''data _null_ ; put "Generated code sysincludefilename=&sysincludefilename sysvlong=&sysvlong" ; run ;'') ;'
/'run ;'
;
run;
%include code / source2;
Returns:
13 %include code / source2; NOTE: %INCLUDE (level 1) file CODE is file C:\Users\Q\AppData\Local\Temp\SAS Temporary Files\_TD1036_MD3V5PHC_\myinclude.sas. 14 + 15 +data null ; 16 + put "Non-generated code sysincludefilename=&sysincludefilename sysvlong=&sysvlong" ; 17 + call execute('data _null_ ; put "Generated code sysincludefilename=&sysincludefilename 17 !+sysvlong=&sysvlong" ; run ;') ; 18 +run ; Non-generated code sysincludefilename=myinclude.sas sysvlong=9.04.01M7P080520 NOTE: The data set WORK.NULL has 1 observations and 0 variables. NOTE: CALL EXECUTE generated line. 1 + data _null_ ; put "Generated code sysincludefilename= sysvlong=9.04.01M7P080520" ; run ; Generated code sysincludefilename= sysvlong=9.04.01M7P080520 NOTE: %INCLUDE (level 1) ending.
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.
Select SAS Training centers are offering in-person courses. View upcoming courses for: