BookmarkSubscribeRSS Feed
RichardAD
Quartz | Level 8

DOSUBL is an amazing feature, but I can't seem to figure out how to make it show the source code that it is running.

The options SOURCE and SOURCE2 does not seem to do it.

For example:

 

The data set "x" is created and the NOTEs for that are shown. However, there are no source lines in the log !

 

data source_lines;
source_line = 'options source source2; data x; y=1; run; %let abc=1;' ;
run ;

data _null_;
set source_lines ;
rc = dosubl(source_line);
abc=symget('abc'); put abc=;
run;
data _null_;
set x; /* created in dosubl side session */
put _all_;
run;

Will log

138 data source_lines;
139 source_line = 'options source source2; data x; y=1; run; %let abc=1;' ;
140 run ;

NOTE: The data set WORK.SOURCE_LINES has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

141
142 data _null_;
143 set source_lines ;
144 rc = dosubl(source_line);
145 abc=symget('abc'); put abc=;
146 run;
********************************************* Could we please see the source that is making the NOTE?
NOTE: The data set WORK.X has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds

abc=1
NOTE: There were 1 observations read from the data set WORK.SOURCE_LINES.

147 data _null_;
148 set x; /* created in dosubl side session */
149 put _all_;
150 run;

y=1 _ERROR_=0 _N_=1
NOTE: There were 1 observations read from the data set WORK.X.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

 

 

MPRINT is a possibility, but I want the side session open code source to show in the log.

 

%macro zzz ;
data ggg ;
set sashelp.class ;
run ;
%mend ;

data _null_ ;
rc = dosubl('options mprint ; %zzz');
run ;

Will log

 

185 %macro zzz ;
186 data ggg ;
187 set sashelp.class ;
188 run ;
189 %mend ;
190
191 data _null_ ;
192 rc = dosubl('options mprint ; %zzz');
193 run ;

MPRINT(ZZZ): data ggg ;
MPRINT(ZZZ): set sashelp.class ;
MPRINT(ZZZ): run ;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set WORK.GGG has 19 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds


If the side session %includes a source code file, the included source is not logged either!

 

* create example include file ;
filename foo catalog 'work.example.step.source' ;
data _null_ ;
  file foo ;
  put 'data qqq ;'
    / 'input x y z ;'
    / 'datalines ;'
    / '1 2 3'
    / '4 5 6'
    / '7 8 9'
    / ';'
    ;
run ;

data _null_ ;
  rc = dosubl ('options source2; %include foo / source ;');
run ;
data _null_ ;
  set qqq ;
  put x y z ;
run ;

Will log 

 

 

242 * create example include file ;
243 filename foo catalog 'work.example.step.source' ;
244 data _null_ ;
245 file foo ;
246 put 'data qqq ;'
247 / 'input x y z ;'
248 / 'datalines ;'
249 / '1 2 3'
250 / '4 5 6'
251 / '7 8 9'
252 / ';'
253 ;
254 run ;

NOTE: The file FOO is:
Catalog Name=WORK.EXAMPLE.STEP.SOURCE,
Catalog Page Size=4096,
Number of Catalog Pages=5,
Created=Thu, Feb 6, 2025 02:58:33 AM,
Last Modified=Thu, Feb 6, 2025 03:07:30 AM,
Filename=....example.sas7bcat,
Release Created=9.0401M7,Host Created=Linux,
Inode Number=###########,
Access Permission=rw-rw-rw-,
Owner Name=########,File Size= 28KB,
File Size (bytes)=28672

NOTE: 7 records were written to the file FOO.
The minimum record length was 1.
The maximum record length was 13.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

255
256 data _null_ ;
257 rc = dosubl ('%include foo / source2 ;'); * tried it with / source too ;
258 run ;

NOTE: %INCLUDE (level 1) file FOO is file WORK.EXAMPLE.STEP.SOURCE.

*************************** THERE IS NO SOURCE or SOURCE2 here !!! *****************************
NOTE: The data set WORK.QQQ has 3 observations and 3 variables. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds NOTE: %INCLUDE (level 1) ending. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 259 data _null_ ; 260 set qqq ; 261 put x y z ; 262 run ; 1 2 3 4 5 6 7 8 9 NOTE: There were 3 observations read from the data set WORK.QQQ. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds

 

 

 

I want the side session to log the same way the main session would... (+ sign for the source2)

480        %include foo / source2 ;
NOTE: %INCLUDE (level 1) file FOO is file WORK.EXAMPLE.STEP.SOURCE.
481       +data qqq ;
482       +input x y z ;
483       +datalines ;

NOTE: The data set WORK.QQQ has 3 observations and 3 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.01 seconds
      
487       +;
7 REPLIES 7
russt_sas
SAS Employee

Unfortunately there is no option that will allow this.  You could switch to CALL EXECUTE instead as it shows the contents in the log, for example:

 

data source_lines;
source_line = 'options source source2; data x; y=1; run; %let abc=1;' ;
run ;

data _null_;
set source_lines ;
*rc = dosubl(source_line);
call execute(source_line);
abc=symget('abc'); put abc=;
run;
data _null_;
set x; /* created in dosubl side session */
put _all_;
run;

 

The log shows this: 

1 data source_lines;
2 source_line = 'options source source2; data x; y=1; run; %let abc=1;' ;
3 run ;

NOTE: The data set WORK.SOURCE_LINES has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.12 seconds
cpu time 0.04 seconds


4
5 data _null_;
6 set source_lines ;
7 *rc = dosubl(source_line);
8 call execute(source_line);
9 abc=symget('abc'); put abc=;
10 run;

NOTE: DATA statement used (Total process time):
real time 0.12 seconds
cpu time 0.06 seconds

abc=1
NOTE: There were 1 observations read from the data set WORK.SOURCE_LINES.

NOTE: CALL EXECUTE generated line.
1 + options source source2;
1 + data x; y=1; run;

NOTE: The data set WORK.X has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.10 seconds
cpu time 0.00 seconds


11 data _null_;
12 set x; /* created in dosubl side session */
13 put _all_;
14 run;

y=1 _ERROR_=0 _N_=1
NOTE: There were 1 observations read from the data set WORK.X.
NOTE: DATA statement used (Total process time):
real time 0.03 seconds
cpu time 0.00 seconds

Tom
Super User Tom
Super User

But the timing of when the code runs is different.  Code passed through CALL EXECUTE() runs after the current data step finishes.  DOSUBL() manages to run the code immediately in a separate (side?) session so that the later SYMGET() function call can retrieve the updated macro variables value.

 

That is basically the whole reason why they decided they needed to make DOSUBL().

russt_sas
SAS Employee

That is correct CALL EXECUTE and DOSUBL are similar in what they can accomplish but are different in regards to the timing of when things execute.  There are may times that DOSUBL and CALL EXECUTE can return the same results.  Was not sure if you were aware of it so wanted to bring it to your attention but as for DOSUBL there is no way to have that code echoed to the log, sorry.

Tom
Super User Tom
Super User

Does not appear to be possible.  Might want to raise it with SAS as an enhancement request.

 

You might put the code into the log yourself.  Easy with your example since you already have it in a variable.

data _null_;
  set source_lines ;
  rc = dosubl(source_line);
  abc=symget('abc'); 
  put _n_= rc= abc=
    / source_line=:$quote.
  ;
run;
RichardAD
Quartz | Level 8

What I ended up doing was throwing a cloud of %put on the invisible source.

 

What is really needed is what you suggest.

OPTION DOSUBL_SOURCE

OPTION DOSUBL_SOURCE2

and a DOSUBL_<option> for any other <option> DOSUBL might gimmick.

 

My real situation is writing a FCMP SUBROUTINE do_something that creates a temp file and writes generated code to it corresponding to the something and then runs the codegen via DOSUBL that includes the temp file.  Seems overly complicated but the approach does make sense for the current situation I am in.

 

The subroutine is using the following pattern when it writes to the temp file.

length tempref $8 ;
rc = filename(tempref,' ','TEMP') ;
tempfid = fopen(tempfid,'A');

do until (codegen_done) ;
  ...
  compute source_code_line 
  ...
  source_code_line =
source_code_line
|| ' %put %nrstr( || source_code_line || ');' /* pixie dust */
; rc = fput(tempfid, source_code_line) ; rc = fwrite(tempfid) ; end ;
... tempfid = fclose(fid) ;
rc = dosubl('%include ' || tempref || ' / source2 ;') ; rc = filename(tempref) ;
Tom
Super User Tom
Super User

Why use the "scl" functions to write the file?
Doesn't the FILEVAR= option of the FILE statement work in FCMP functions?

Tom
Super User Tom
Super User

Your work around might work as long as the generated code is simple enough that inserting the %PUT statements doesn't cause trouble.  

 

Again if the code is complicated I am not sure I totally trust macro function %NRSTR() to get the macro quoting right.  Since you are using SAS code to generate it why not generate the value using single quotes to make sure that macro triggers are not resolved during the %PUT statement execution.  You can always add a call to DEQUOTE() to remove them if you want a neater SAS log.

  source_code_line = catx(' ',source_code_line
    ,'%put %qsysfunc(dequote(',quote(trim(source_code_line),"'"),'));'
    )
  ;

It also might make the SAS log make more sense if you move the %PUT before the actual code.

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 1248 views
  • 2 likes
  • 3 in conversation