Macros for SAS Application Developers
https://github.com/sasjs/core
mp_include.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Performs a wrapped \%include
4  @details This macro wrapper is necessary if you need your included code to
5  know that it is being \%included.
6 
7  If you are using %include in a regular program, you could make use of the
8  following macro variables:
9 
10  @li SYSINCLUDEFILEDEVICE
11  @li SYSINCLUDEFILEDIR
12  @li SYSINCLUDEFILEFILEREF
13  @li SYSINCLUDEFILENAME
14 
15  However these variables are NOT available inside a macro, as documented here:
16 https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n1j5tcc0n2xczyn1kg1o0606gsv9.htm
17 
18  This macro can be used in place of the %include statement, and will insert
19  the following (equivalent) global variables:
20 
21  @li _SYSINCLUDEFILEDEVICE
22  @li _SYSINCLUDEFILEDIR
23  @li _SYSINCLUDEFILEFILEREF
24  @li _SYSINCLUDEFILENAME
25 
26  These can be used whenever testing _within a macro_. Outside of the macro,
27  the regular automatic variables will still be available (thanks to a
28  concatenated file list in the include statement).
29 
30  Example usage:
31 
32  filename example temp;
33  data _null_;
34  file example;
35  put '%macro test();';
36  put '%put &=_SYSINCLUDEFILEFILEREF;';
37  put '%put &=SYSINCLUDEFILEFILEREF;';
38  put '%mend; %test()';
39  put '%put &=SYSINCLUDEFILEFILEREF;';
40  run;
41  %mp_include(example)
42 
43  @param [in] fileref The fileref of the file to be included. Must be provided.
44  @param [in] prefix= (_) The prefix to apply to the global variables.
45  @param [in] opts= (SOURCE2) The options to apply to the %inc statement
46  @param [in] errds= (work.mp_abort_errds) There is no clean way to end a
47  process within a %include called within a macro. Furthermore, there is no
48  way to test if a macro is called within a %include. To handle this
49  particular scenario, the %mp_abort() macro will test for the existence of
50  the `_SYSINCLUDEFILEDEVICE` variable and return the outputs (msg,mac) inside
51  this dataset.
52  It will then run an abort cancel FILE to stop the include running, and pass
53  the dataset back.
54 
55  IMPORTANT NOTE - it is NOT possible to read this dataset as part of _this_
56  macro! When running abort cancel FILE, ALL macros are closed, so instead it
57  is necessary to invoke "%mp_abort(mode=INCLUDE)" OUTSIDE of macro wrappers.
58 
59 
60  @version 9.4
61  @author Allan Bowe
62 
63  <h4> SAS Macros </h4>
64  @li mf_getuniquefileref.sas
65  @li mp_abort.sas
66 
67 **/
68 
69 %macro mp_include(fileref
70  ,prefix=_
71  ,opts=SOURCE2
72  ,errds=work.mp_abort_errds
73 )/*/STORE SOURCE*/;
74 
75 /* prepare precode */
76 %local tempref;
77 %let tempref=%mf_getuniquefileref();
78 data _null_;
79  file &tempref;
80  set sashelp.vextfl(where=(fileref="%upcase(&fileref)"));
81  put '%let _SYSINCLUDEFILEDEVICE=' xengine ';';
82  name=scan(xpath,-1,'/\');
83  put '%let _SYSINCLUDEFILENAME=' name ';';
84  path=subpad(xpath,1,length(xpath)-length(name)-1);
85  put '%let _SYSINCLUDEFILEDIR=' path ';';
86  put '%let _SYSINCLUDEFILEFILEREF=' "&fileref;";
87 run;
88 
89 /* prepare the errds */
90 data &errds;
91  length msg mac $1000;
92  call missing(msg,mac);
93  iftrue='1=0';
94 run;
95 
96 /* include the include */
97 %inc &tempref &fileref/&opts;
98 
99 %mp_abort(iftrue= (&syscc ne 0)
100  ,mac=%str(&_SYSINCLUDEFILEDIR/&_SYSINCLUDEFILENAME)
101  ,msg=%str(syscc=&syscc after executing &_SYSINCLUDEFILENAME)
102 )
103 
104 filename &tempref clear;
105 
106 %mend mp_include;