/**************************************************************
 * STATA_WRAPPER should work for you as is, but you may need 
 *  to edit this file to set the values for the macro variables:
 *  ustata  -- if you are using STATA_WRAPPER in a UNIX or Linux environment
 *  wstata  -- if you are using STATA_WRAPPER in a Windows environment
 *
 * There are instructions further down in this file explaining where 
 *  and how to edit the settings of these macro variables.
 * Do a find for "let ustata" or "let wstata".
 **************************************************************/

run;   ** Because the world needs more run statements. **;


%MACRO stata_wrapper(swoptions,out_dir);  
run;   %** Because the world needs more run statements. **;
%** If an error has occurred before call to STATA_WRAPPER then fail immediately. **;
%if &syserr.^=0 %then %goto nevrmind;  
               
/*********************************************************************************************
** Macro: STATA_WRAPPER
** Input: Most recently created SAS WORK dataset and some Stata code to process.
**         
** Output: by default will be included in the SAS output window/.lst file.
**        
** Dependency:  You need to have the Stata installed on your computer and have the 
**               Stata command -usesas- installed for STATA_WRAPPER to load your
**               SAS dataset into Stata.  It would also be a good idea to have the
**               Stata command -savasas- installed as well if you want to pass data
**               back to your SAS session.
**         
** 
** Programmer: Dan Blanchette   dan_blanchette@unc.edu 
** Developed at Research Computing at The University of North Carolina at Chapel Hill
** Date: 20March2008
** Modified: 24Apr2008 - Added Stata command -sas_work- that changes directory (cd's) to
**                        the SAS WORK library/directory.  It also returns the local macro
**                        r(sas_work) so that it can be used if needed.
**         
** Modified: 27Jun2008 - Fixed problem with NOTES being shut off after running:
**                        %stata_wrapper(code) datalines;
**         
** Disclaimer:  This program is free to use and to distribute as long as credit is given 
**               to Dan Blanchette and Research Computing at UNC-CH.
**              The University of North Carolina at Chapel Hill is not responsible
**               for results created by this macro.  It is the responsibility of the user
**               to check the quality of the output.  There is no warranty on this software 
**               either expressed or implied.
**              This program is released under the terms and conditions of 
**               GNU General Public License. 
** Comments: 
**   STATA_WRAPPER SAS macro when invoked by the SAS System passes the most recently created SAS dataset
**    in the WORK library to Stata and runs the Stata code written after the %stata_wrapper(code) datalines; 
**    line.  The log of the Stata code will be included in the SAS output window or .lst file unless an 
**    output directory name is specified.
**
** REQUIRED INPUT TO STATA_WRAPPER:
**  -- STATA_WRAPPER needs to have the most recently created dataset by SAS to be in the WORK library 
**      and a Stata do-file to process. 
**             
** LIST OF OPTIONS:
** NOTE:  Options can be used in any order.  You can specify as many as you want
**         or none at all. 
**             
** -code     -- Used when only using writing Stata code to be submitted by STATA_WRAPPER.  You must
**               use it like so (You have to have "datalines;" after the call to STATA_WAPPER) :
**               %stata_wrapper(code) datalines;
**                  svyset myPSUvar [pweight=myWeightVar], strata(MyStratumVar) 
**                  svy:mean income weight height, over(agegroup race)
**                ;;  ** You should put at least one semi-colon after all your Stata code **;
**                 ** Your Stata code cannot contain any semi-colons.  Do not use #delimit; **;
**                 ** If you really want to use semi-colons in your Stata code, use "datalines4;" **;
**                  *  and end your Stata code with 4 semi-colons starting at the very  **;
**                  *  beginning of the line (column 1 through column 4) **;
**               %stata_wrapper(code) datalines4;
**                  svyset myPSUvar [pweight=myWeightVar], strata(MyStratumVar) 
**                  svy:mean income weight height, over(agegroup race)
**               ;;;;  ** You need 4 semi-colons starting at the beginning of the line. **;
**             
** -replace  -- If an output directory is specified and the output files you want to output already exist, 
**               -replace will then overwrite them with the files generated by STATA_WRAPPER
**             
** -nodata   -- Indicates not to load the most recent SAS dataset in the WORK library into Stata.
**               This should be used when your Stata code does not require that dataset. 
**             
** -noformats -- Specifies not to create value labels (which is the default) from SAS user-defined formats 
**               that are stored in a SAS formats catalog file that has the same name as the dataset and is 
**               in the WORK directory.  For example: MySasData.sas7bcat .  If this file doesn't exist, 
**               -usesas- will look for the file formats.sas7bcat in the WORK directory.
**               
** -int      -- (Windows only option, not for Linux/UNIX) Keep interactive Stata running.  You have to 
**               exit/close Stata before you can return to SAS or exit/close SAS since SAS is waiting 
**               for Stata to stop running.
**             
** -log      -- Includes the Stata log in your SAS log rather than your SAS output window/.lst file.
**             
** =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
**   Since STATA_WRAPPER uses the Stata command -usesas- to load the most recently created SAS dataset in
**    the WORK library the following are options to be used by -usesas- when called by STATA_WRAPPER:
** =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
**            
** -char2lab -- Specifies to encode long SAS character variables like the Stata command -encode-.  Character 
**               variables that are too long for a Stata string variable are maintained in value labels.
**            
** -float    -- Specifies that numeric variables that would otherwise be stored as numeric type double be 
**               stored with numeric type float.  This option should only be used if you are certain you 
**               have no integer variables that have more than 7 digits (like an id variable).
**            
** -quotes   -- Specifies that double quotes that exist in string variables are to be replaced with single 
**               quotes.  Since the data are written out to an ASCII file and then read into Stata, double 
**               quotes are not allowed.
** =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
**             
** -messy    -- Puts the files generated by STATA_WRAPPER used to create the Stata log file in the directory
**               named in the pathname provided in the call to the STATA_WRAPPER macro.
**             
**             
** SETTING UP STATA_WRAPPER 
**  These are instructions to edit the stata_wrapper.mac file.
**             
** NOTE:  If you are setting up this macro on your computer for the first time,
**         please choose which version of Stata you are going to have STATA_WRAPPER use.
**         If you do not choose to set one of the following switches, STATA_WRAPPER will
**         figure out what version of Stata you are running for you.  This may 
**         add a noticeable amount of time to processing so you may want to set these 
**         switches to the correct version of Stata.  You can easily figure out what 
**         version of Stata you are using by looking at the top of your results window 
**         in Stata or by typing in the command -about- at the Stata command line.
**         One advantage of leaving STATA_WRAPPER to figure out what version of Stata is 
**         being used is that when you upgrade your version of Stata you will not have to
**         update stata_wrapper.
**  
**  NOTE:
**  --  If you are running STATA_WRAPPER on UNIX or Linux then
**       you need to be able to start a Stata batch job by:
**       stata -b do mydofile.do
**       If not, then change the setting of the ustata macro variable.
**********************************************************************************************/
 %local ustata;
/** One of these may work: **
 %let ustata=stata;
 %let ustata=/usr/local/stata/stata;
 %let ustata=/usr/local/stata/stata-mp;
 %let ustata=/usr/local/stata/stata-se;  */
 %let ustata=/usr/local/stata/stata;


/**********************************************************************************************
**
**  --  If you are running STATA_WRAPPER on Windows, you need to tell STATA_WRAPPER where the Stata 
**       executable file is located.
**       If you do not know where your Stata executable file is located, find your Stata
**       short-cut icon, right click on it, choose "properties", and look in the "target" field.
**       This will show you where the Stata executable file is located on your hard drive.
**
***********************************************************************************************/

 %local wstata;
%** Change what is inside the parentheses to the location of your Stata executable file **; 
/** One of these may work: **;
 %let wstata=%nrstr(C:\Stata9\wsestata.exe);
 %let wstata=%nrstr(C:\Stata9\wmpstata.exe); */
 %let wstata=%nrstr(C:\Stata9\wstata.exe);


 
/** STATA_WRAPPER will try the following (plus up to ver 12) if the first does not work:
    %let wstata=%nrstr(C:\Stata8\wsestata.exe);                ** Stata 8 SE **;
    %let wstata=%nrstr(C:\Program Files\Stata8\wsestata.exe);  ** Stata 8 SE **;
    %let wstata=%nrstr(D:\Stata8\wsestata.exe);                ** Stata 8 SE **;
    %let wstata=%nrstr(C:\Program Files\Stata8\wstata.exe);    ** Stata 8 **;
    %let wstata=%nrstr(D:\Stata8\wstata.exe);                  ** Stata 8 **;
    %let wstata=%nrstr(C:\Stata8\wsestata.exe);                ** Stata 8 SE **;
    %let wstata=%nrstr(C:\Stata\wstata.exe);    ** default version Stata catcher **;
  ** then STATA_WRAPPER searches your path **
 ************************************************/




/*********************************************************************************************
** 
** HOW TO USE THE STATA_WRAPPER MACRO: 
** Using the STATA_WRAPPER macro requires that you understand how to use the "%include" statement
**  and that you know how to call a SAS macro.
**
**  %include'LOCATION AND NAME OF A FILE THAT CONTAINS SAS CODE';
**
** For example, if you have copied this file to "C:\SASmacros", then you tell SAS 
**  about this macro by adding the following line to your SAS program:
**
**  %include 'C:\SASmacros\stata_wrapper.mac'; 
**
** This statement makes SAS aware of the STATA_WRAPPER macro which is in the file stata_wrapper.mac.
** To use the macro you have to make a call to it.  To do that you add a line like the 
**  following to your SAS program:
**
**  %stata_wrapper([options], "[folder to save Stata output]");
**  But you don't really have to specify anything if you want to use the defaults:
**  %stata_wrapper;
**
**
**  ** create data set that contains only the observations and variable(s) needed for the Stata command 
**   *  to be run:  **;
**  data test;
**   set my_data (keep=math cses one school
**                where=(gender=1));
**  run;
**
**  ** write some Stata code to be submitted by STATA_WRAPPER: **;
**  %stata_wrapper(code) datalines;
**   eq cses: cses
**   eq one: one
**   gllamm math cses, i(school) eqs(one cses)  diff adapt nrf(2) 
**  ;;;; ** end Stata code with at least one semi-colon **;
**
**  ** Have STATA_WRAPPER submit the above Stata code to Stata  **;
**  %stata_wrapper;
**
**
**  Or you can submit a Stata do-file saved in some other directory:
**  %stata_wrapper(code) datalines;
**    do  "C:\my_project\my_stata_code.do"
**  ;;;;
**
**  ** Have STATA_WRAPPER submit the above Stata code to Stata  **;
**  %stata_wrapper;
**
**
** The information inside the parentheses is passed on to the STATA_WRAPPER macro.  The first
** string of information is any/all STATA_WRAPPER options.  The second string 
** of information is the location you want to save your Stata log file if you do not want it
** included in the SAS output window/.lst file.  This is somewhat like a LIBNAME statement.  
**
**
** EXAMPLE USE OF THE STATA_WRAPPER MACRO:
**  %include "C:\SASmacros\stata_wrapper.mac"; ** Include macro once in a SAS session and call it **;
**                                              *  as many times as you like in that session.     **;
**
**  data work.ToBeStata;   ** This makes a copy of the SAS dataset in the in the work library. **;
**   set in.mySASfile (keep= math school
**                     where=(gender=2));
**  run;
** 
**  ** write some Stata code to be submitted to Stata by STATA_WRAPPER **;
**  %stata_wrapper(code) datalines;
**   matrix b1 = [12, 2, 8]
**   gllamm math , i(school) from(b1) copy
**  ;;;;
**
**  ** now submit the above code to Stata **;
**  %stata_wrapper;  
** 
** 
**  OTHER EXAMPLE CALLS:
**                
**  ** Save the Stata log file "_[some_big_number]_stata_code.log  **; 
**  ** in C:\MyData\, overwriting it if  it already exists.    **; 
**  %stata_wrapper(-replace,"C:\MyData\");  
**                
**  ** Run the Stata do-file "my_stata_code.do in C:\MyProject\ and **; 
**   * save the Stata log file "_[some_big_number]_stata_code.log  **; 
**   * in C:\MyData\, overwriting the log file if it already exists.    **; 
**  %stata_wrapper(code);  
**    do "C:\MyProject\my_stata_code.do"
**  ;;;;
**  %stata_wrapper(-replace,"C:\MyData\");  
**                
**                
**  This example is like a USESTATA SAS macro.
**
**  %stata_wrapper(code) datalines; 
**    use "C:\My Project\Data\some_data.dta"
**    savasas using "some_data.sas7bdat"
**  ;;;;
**
**  * specify not to use the most recently created SAS dataset in WORK **;
**  *  since your Stata code does not need it. **;
**  %stata_wrapper(-nodata);
**
**  ** now you can access this data set from your WORK library/directory because  **;
**   *  no directory name was specified in the call to -savasas- above. **;
**  proc contents work.some_data;
**  run;
**                
** The above example assumes that Stata is not set up to cd to some other directory when 
**  Stata is started up.  If you are not in the SAS WORK library/directory at the moment
**  when -savasas- is invoked you can use the Stata command -sas_work- to cd you to that
**  directory.  This command is only available while running STATA_WRAPPER.
**  Here is an example using -sas_work-
**                
**  %stata_wrapper(code) datalines; 
**    use "C:\My Project\Data\some_data.dta"
**    sas_work
**    return list  // this is optional but shows that the local macro r(sas_work) exists now
**    savasas using "some_data.sas7bdat"
**  ;;;;
**
**  %stata_wrapper(-nodata);
**
**  proc contents work.some_data;
**  run;
** 
***********************************************************************************************/


 %local usagelog;
%** SET LOCATION OF USAGE LOG FILE **;
%let usagelog="specify what file name and location you want here";
%if "&sysscp."="WIN" %then %do;
 %let usagelog="x:\software\temp\stata_wrapper_usage.log";  %* windoze *;
%end;
%else %if "&sysscp."="RS6000" %then %do;
 %let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/stata_wrapper_usage.log";  %* AIX nodes *;
%end;
%else %if "&sysscp."="AIX 64" %then %do;
 %let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/stata_wrapper_usage.log";  %* AIX nodes *;
%end;
%else %if "&sysscp."="LINUX" %then %do;   %* linux boxes *;
  %let usagelog="/afs/isis.unc.edu/home/d/a/danb/usage/stata_wrapper_usage.log";  
%end;


/***************************************************************************/
/****** !NO MORE EDITS TO THE MACRO SHOULD BE MADE BEYOND THIS POINT! ******/
/***************************************************************************/

 %** local macro vars used in stata_wrapper: **;
 %local char2lab code decpos diffhour diffmin diffsec work_dir drive dset fail 
        fail7 fdset float formats http i ii int isysver j jj k kk ldset lst_name 
        messy newname no_out_dir notes obs pwdir pwdrive quotes replace slash 
        sw_dsn sw_last swtartdat swtfns swlog temp_dir unix u_sysrc w_sysrc ;


%** make sure sas version is an integer so it can be properly evaluated **;
%let isysver = %sysevalf(&sysver.,integer);  

 %** Save option settings so they can be restored at the end of this macro. **;
%let notes=%sysfunc(getoption(notes)); 
%let obs=%sysfunc(getoption(obs)); 

options obs=MAX;   %*** Reason for maximizing it is because user could have        **;
                     %*  set it lower than the number of variables in the dataset. **;
options nonotes;   %** Shut off notes while program is running in order to reduce log size. **;

%** Time how long STATA_WRAPPER takes to run **;
%let swtartdat=%sysfunc(datetime());

%let sprog=stata_wrapper;
%let http=%nrstr(http://www.unc.edu/home/danb/sas_to_stata/)&sprog..html;


%** initialize macro vars **;
%let diffhour=0;
%let diffmin=0;
%let diffsec=0;
%let fail=0;
%let no_out_dir=0;

%if %length(%nrbquote(&out_dir.)) = 0 %then %let no_out_dir = 1;

%if %nrbquote(%index(%nrbquote(&out_dir.),%str(%")))=1
   or %nrbquote(%index(%nrbquote(&out_dir.),%str(%')))=1
      %then %let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),2,%length(%nrbquote(&out_dir.))-2));


%let code=0;
%** create stata_code.do in the WORK library: **;
%if %index(%lowcase(%nrbquote(&swoptions.)),code) %then %do;
  %let code=1;
  
  data _null_;
   file "%nrbquote(%sysfunc(pathname(work)))/stata_code.do";
   infile datalines truncover;
   input @1  sw $2. ;
   put _infile_;

%end;
options obs=&obs. &notes. ;  %** Restore options. **;
%if &code.=1 %then %goto nevrmind;


%** Find out what directory SAS currently is using as the present working directory **;
 %*  so that it can be restored at end of macro. **;
libname ________ " ";  %** ________ is a very unlikely libname **;
%let pwdir=%nrbquote(%sysfunc(pathname(________)))/;
%let pwdrive= ;
%if %index(%nrbquote(&pwdir),\) %then %do;
   %let pwdrive= %qsubstr(%nrbquote(&pwdir.),1,2);   %** get drive info eg. "D:"  **;
%end;


%**  use the work directory to store the temporary SAS files that this program creates ***;
%let temp_dir = %nrbquote(%sysfunc(pathname(work)));
%let work_dir = %nrbquote(%sysfunc(pathname(work)));

%** this is first time program goes to a fail label **;
%** Work directory cannot start with a back slash because stata_wrapper needs to cd to it. **;
%if %index(%nrbquote(&work_dir.),\)=1 %then %goto fail1; 

%* if out_dir not specified then make it the work_dir **;
%if &no_out_dir. = 1 %then %let out_dir=%nrbquote(&work_dir.);

%** initialize var **;
%let newname=;
 
%** check to see if new log file name provided in %nrbquote(&out_dir.) **;
%if %nrbquote(%length(&out_dir.)) > 0  %then %do;  
 %if %nrbquote(%index(%qlowcase(&out_dir.),.log)) %then %do;
  %** if Stata dataset name provided with directory info **;
  %if "%qlowcase(%substr(%nrbquote(&out_dir.),%length(%nrbquote(&out_dir.))-3,4))"=".log" %then %do;  
    %** if no backslash provided:  savstata(D:mydata.log) then add in the backslash **;
   %if "&sysscp"="WIN" 
     and %nrbquote(%index(%nrbquote(&out_dir.),:)) = 2 and %nrbquote(%index(%nrbquote(&out_dir.),\)) ^= 3 %then 
    %let out_dir = %nrbquote(%substr(%nrbquote(&out_dir.),1,2)\%substr(%nrbquote(&out_dir.),3,%length(%nrbquote(&out_dir.))-2));  
   %let newname=%nrbquote(%substr(%nrbquote(&out_dir.),1,%length(%nrbquote(&out_dir.))-4));
   %if %index(%nrbquote(&newname),\) %then %do;
    %do %while(%nrbquote(%index(%nrbquote(&newname),\)));
     %let newname=%nrbquote(%substr(%nrbquote(&newname),%index(%nrbquote(&newname),\)+1,%length(&newname)-(%index(%nrbquote(&newname),\))));
    %end;
    %let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),1,%index(%nrbquote(&out_dir.),%nrbquote(&newname))-1));
   %end;
   %else %if %index(%nrbquote(&newname),/) %then %do;
    %do %while(%nrbquote(%index(%nrbquote(&newname),/)));
     %let newname=%nrbquote(%substr(%nrbquote(&newname),%index(%nrbquote(&newname),/)+1,%length(&newname)-(%index(%nrbquote(&newname),/))));
    %end;
    %let out_dir=%nrbquote(%substr(%nrbquote(&out_dir.),1,%index(%nrbquote(&out_dir.),%nrbquote(&newname))-1));
   %end;
   %else %let out_dir=;  %** only new name provided **;
  %end;
 %end; %** end of if %index(%nrbquote(&out_dir.),.log) do loop **;
%end; %** end of if length(%nrbquote(&out_dir.)) = 0 do loop **;
 
 
%let swoptions=%lowcase(%nrbquote(&swoptions));
%let sw_dsn=&sysdsn;  %** preserve these to restore after setting up usagelog **;

%** log usage of stata_wrapper if usage log file exists **;
%if %sysfunc(fileexist(&usagelog)) %then %do;
 data _null_;
  file &usagelog mod;
   put " ";
   date=datetime() ;
   put " stata_wrapper macro " date dateampm.  ;
  put "  &sysuserid. stata_wrapper(&swoptions., &out_dir.)";
%end;

%let sysdsn=&sw_dsn; %** restore after setting up usagelog **; 

%** Initialize macro vars for stata_wrapper options **;
%let int=0;
%let nodata=0;
%let replace= ;
%let swlog=0;
%let char2lab= ;
%let formats=formats;
%let float= ;
%let quotes= ;
%let messy=0;

%if %nrstr(&swoptions)^=%nrstr() %then %do;
 %** Find out what options were specified **;
 %if %index(&swoptions,rep) %then %let replace=replace; %** set replace option  **;
 %if %index(&swoptions,nod) %then %let nodata=1; %** set nodata option  **;
 %if %index(&swoptions,int) %then %let int=1; %** set int option  **;
 %if %index(&swoptions,log) %then %let swlog=1; %** set log option  **;
 %if %index(&swoptions,fl)   %then %let float=float;  %** set float option  **;
 %if %index(&swoptions,nofor) %then %let formats=;  %** set noformats option  **;
 %if %index(&swoptions,qu)   %then %let quotes=quotes; %** set quote option  **;
 %if %index(&swoptions,cha)  %then %let char2lab=char2lab;  %** set char2lab option  **;
 %if %index(&swoptions,mes) %then %let messy=1; %** set messy option  **;
%end;



%if &nodata=0 %then %do;
  %*** Use the most recently created SAS work dataset.  ***;
  %let sw_last=&syslast;
  %let ldset=%length(&syslast);
  %let decpos=%index(&syslast,.);
  %let dset=%substr(&syslast,&decpos.+1,&ldset.-&decpos);
%end;

%** Figure out whether the operating system uses forward slashes or back slashes in   **;
 %*  directory paths and make sure that out_dir has the appropriate slash at the end. **;
%let unix=0;
%let drive= ;
%IF %index(%nrbquote(&temp_dir.),\) %THEN %do;
   %let unix=0;   %** unix=0 implies windows platform **;
   %let drive= %qsubstr("&work_dir.",2,2);   %** get drive info eg. "d:"  **;
   %let temp_dir = %nrbquote(&temp_dir.)\;   %** tack on a back slash **;
   %if "&out_dir."=""  %then %goto fail3;  
   %else %if "&out_dir."=" " %then %goto fail3;
   %else %if "&out_dir."="." %then %goto fail3;
   %let slash= %qsubstr("&out_dir.",%length("&out_dir.")-1,1);   %** check if back slash at end **;
   %if "&slash"^="\" %THEN %do;
     %let out_dir= %nrbquote(&out_dir.)\;   %** add a back slash at end if it is not there already **;
   %end;
   %let slash= %qsubstr("&work_dir.",%length("&work_dir.")-1,1);   %** check if back slash at end **;
   %if "&slash"^="\" %THEN %do;
     %let work_dir= %nrbquote(&work_dir.)\;   %** add a back slash at end if it is not there already **;
   %end;
   %end;
%ELSE %IF %index(%nrbquote(&temp_dir.),/) %THEN %do;
  %let unix=1;  %** unix or unix-like platform **;
  %let temp_dir = %nrbquote(&temp_dir.)/;  %** tack on a forward slash **;
    %** make sure that out_dir is not a relative directory name like: ../mydata/ **;
  libname ________ "&out_dir.";  %** ________ is a very unlikely libname **;
  %let out_dir=%nrbquote(%sysfunc(pathname(________)));
  %let slash= %qsubstr("&out_dir.",%length("&out_dir.")-1,1);  %** check if back slash at end **;
  %if "&slash"^="/" %THEN %do;
    %let out_dir= %nrbquote(&out_dir.)/;  %** add a forward slash at end if it is not there already **;
  %end;
  %let slash= %qsubstr("&work_dir.",%length("&work_dir.")-1,1);  %** check if back slash at end **;
  %if "&slash"^="/" %THEN %do;
    %let work_dir= %nrbquote(&work_dir.)/;  %** add a forward slash at end if it is not there already **;
  %end;
%END; %** ELSE IF index("temp_dir",/) THEN do loop **;

 
%if &int. = 1 and &unix. = 1 %then %do;
  options notes;
    %put NOTE: The "-int" option is for Windows only.  Stata will be run in batch.;
  options nonotes;
%end;

%** Make sure the dataset name and any option passed to stata_wrapper is in lower case. **;
%let dset=%lowcase(%nrbquote(&dset));
%if %length(&newname)>0 %then %let fdset=%nrbquote(&newname);
%else %let fdset=%lowcase(%nrbquote(&dset));

%if &nodata=0 %then %do;
  %if %index(&syslast,WORK)^=1 %then %goto fail2;
%end;

%** if obs are set to zero, error in program previous to stata_wrapper **;
%if &obs=0 %then %goto fail6;  



%** check to see if user has set up Windows Stata correctly. **;
%** if not then check other likely places the Stata executable would be. **;
%let fail7=0;

%if &unix.=0 and %sysfunc(fileexist("&wstata."))=0 %then %do %while(&fail7=0);
   %let drives =C D Y;
   %let exe =wsestata wmpstata wstata;
   %let versions =12 11 10 9 8 7 6;
   %do i = 1 %to 3;  %** one for each drive **;
    %let ii =%scan(&drives.,&i.,%nrstr( ));
    %do j = 1 %to 3;  %** one for each exe of stata **;
     %let jj =%scan(&exe.,&j.,%nrstr( ));
     %do k = 1 %to 7;  %** one for each version of stata **;
      %let kk =%scan(&versions.,&k.,%nrstr( ));
 
   %let wstata=%str(&ii.:\Stata&kk.\&jj..exe);
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;
     %let wstata=%str(&ii.:\Program Files\Stata-&kk.\&jj..exe);  %** Stata-9 **;
   %end;
   %else %goto exist;  %** file exists **;
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;
     %let wstata=%str(&ii.:\Program Files\Stata&kk.\&jj..exe);   %** Stata9 **;
   %end;
   %else %goto exist;  %** file exists **;
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;
     %let wstata=%str(&ii.:\Stata-&kk.\&jj..exe);  %** Stata-9 **;
   %end;
   %else %goto exist;  %** file exists **;
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;  
     %let wstata=%str(&ii.:\Stata&kk.\&jj..exe);   %** Stata9 **;
   %end;
   %else %goto exist;  %** file exists **;
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;
     %let wstata=%str(&ii.:\Stata\&jj..exe);
   %end;
   %else %goto exist;  %** file exists **;
   %if %sysfunc(fileexist("&wstata"))=0 %then %do;
    %** nothing **;
   %end;
   %else %goto exist;  %** file exists **;
     %end;  %** of k loop **;
    %end;  %** of j loop **;
   %end;  %** of i loop **;
   %do;  %** check path for Stata executable **;
     %let i=1;
     %let delim=%str(;);
     %do %until (%qscan(%sysget(PATH),&i.,%str(&delim.)) = );
       %let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wsestata.exe";
       %if %sysfunc(fileexist("&wstata"))=0 %then
         %let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wmpstata.exe";
       %if %sysfunc(fileexist("&wstata"))=0 %then 
         %let wstata="%qscan(%sysget(PATH),&i.,%str(&delim.))\wstata.exe";
       %if %sysfunc(fileexist("&wstata")) %then %do; 
         %let fail7=2; 
         %let i=200000;  %** break loop if found it **;
       %end;
       %let i=%eval(&i.+1);
     %end;
     %if fail7=2 %then %goto exist;  %** file exists **;
   %end; %** of checking path for Stata executable **;
  
   %if %sysfunc(fileexist("&wstata."))=0 %then %do;
     %let fail7=1;  %** give up **;
   %end;
  %exist: ;
  %if &fail7=0 %then  %let fail7=2;  %** found file so break while loop **;
%end;  %** end of if unix=0 then do while loop **;

  
%if &fail7=1 %then %goto fail7;

  
libname ________ "&out_dir.";  %** ________ is a very unlikely libname **;
%if &syslibrc.^=0 %then %do;
 libname ________ clear;  %** do away with it now **;
 %goto fail4;  %** exit if not a valid pathname **;
%end;

libname ________ clear;  %** do away with it now **;


%if &messy=1 %then %do;
 %if &no_out_dir. = 1 %then %let out_dir=%nrbquote(&pwdir.);
  %**  Use the output directory to store the SAS program files that this macro creates. ***;
 %let temp_dir =%nrbquote(&out_dir.); 
 %if &unix.=0 %then %do;
  %let windrive= %qsubstr("&out_dir.",2,2);   %** get drive info eg. "d:"  **;
  %sysexec &windrive;  ** change to whatever drive files are going **;
 %end;
 %** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
 %sysexec cd %nrbquote(&out_dir.) ;   %** change to the drive and directory where the Stata do-files are. **;
%end;

%* temporary file name...make it unique *;
%let swtfns = &sysjobid.&sysindex.;

%if %sysfunc(fileexist("&out_dir._&swtfns._stata_code.log")) %then %do;
  %if &replace.^=replace %then %do;
     %goto fail5;
  %end;
%end;


data _null_;
 file "&temp_dir._&swtfns._stata_wrapper.do" ls=2000;
    put "program define sas_work, rclass";
    put "display as text `""cd `""&work_dir.""'""' ";
    put "quietly  cd `""&work_dir.""' ";
    put "  return local sas_work `""&work_dir.""'";
    put "end ";
  %if &int = 1 and &unix. = 0 %then %do;
    put "program define swexitnote";
    put "di as res _n _dup(`c(linesize)') ""-"" ";  %** create a horizontal line **;
    put "di as res ""NOTE: You have to exit Stata before you can return to SAS or exit/close SAS. "" ";
    put "di as res _dup(`c(linesize)') ""-"" ";
    put "end ";
  %end;
  %if &nodata=0 %then %do;
    put "capture program drop swvtest";
    put "program define swvtest";
    put "if _caller() <=8 { ";
    put "  di as text ""You need Stata 8.1 or newer to use -usesas-""" ; 
    put "} ";
    put "end";
  %end;
  put "log using ""&out_dir._&swtfns._stata_code.log"", &replace. ";
  %if &int = 0 and &unix. = 0 %then %do;
    put "set more off";
  %end;
  %if &nodata=0 %then %do;
    put "swvtest";
    put "usesas using ""&work_dir.&fdset..sas7bdat"", &formats. &char2lab. &quotes. &float. ";
  %end;
  put "do ""&work_dir.stata_code.do"" ";
  %if &int = 0 %then %do;
    put "exit, clear STATA";
  %end;
  %else %if &unix. = 0 %then %do;
    put "swexitnote";
  %end;
run;


%** initialize macro vars for system return codes **;
%let u_sysrc=0; 
%let w_sysrc=0;  
%if &unix.=1 %then %do;
  %** This submits the Stata do-file stata_code . ***;
  %** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
  %sysexec cd %nrbquote(&temp_dir.) ;   %** change to the drive and directory where the Stata do-files are. **;
   %** Run Stata in batch from within the directory where the temp files are. **;
   %sysexec %nrbquote(&ustata.) -b do "_&swtfns._stata_wrapper.do";  
   %let u_sysrc=&sysrc;  %** store value of sysrc until after loop **;
%end; %** if unix=1 then do loop **;

%if &unix.=0 %then %do;
  %sysexec &drive.;
  %** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
  %sysexec cd %nrbquote(&work_dir.) ;
     %** Run Stata interactively. **;
  %sysexec "&wstata."  do "&temp_dir._&swtfns._stata_wrapper.do";  
  %let w_sysrc=&sysrc;  %** store value of sysrc until after loop **;
%end;  %** if unix=0 then do loop **;
%if &u_sysrc^=0 %then %goto fail8;
%if &w_sysrc^=0 %then %goto fail7; 


%* only include Stata output to SAS lst if out_dir not specified **;
%if %nrbquote(&out_dir.) = %nrbquote(&work_dir.) %then %do;
  %if %sysfunc(fileexist(%nrbquote(&out_dir._&swtfns._stata_code.log))) %then %do;
     data _null_;
    %if &swlog. = 0 %then %do;
      file print;
    %end;
    %else %do;
      file log;
    %end;
      %* probably only need to set lrecl to 256 since that is the max linesize for Stata *;
      infile "%nrbquote(&out_dir._&swtfns._stata_code.log)"  lrecl=32767 truncover; 
      input @1 results $char1.;  %** this line is basically irrelevant **;
      put _infile_;  %** this is magic **;
     run;
  %end;
%end;
%else %if %nrbquote(&out_dir.) ^= %nrbquote(&work_dir.) %then %do;
  %* user specified to save results separately *;
  %if %sysfunc(fileexist(%nrbquote(&out_dir._&swtfns._stata_code.log))) %then %do;
    options notes; 
    %put   *   ;
    %put NOTE: STATA_WRAPPER has created the Stata log file:    *  ; 
    %put     %nrbquote(&out_dir._&swtfns._stata_code.log)   *  ;
    %put   *   ;
  %end;
%end;


options nonotes;  %** Make sure notes are shut off while deleting temp files and figuring out run time. **;


%goto okay;

%fail1: %put   *   ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put The work directory cannot start with a forward slash ( \ ) because              *  ;
        %put STATA_WRAPPER needs to cd to it.                                                   *  ;
        %put Is it possible to reassign your work directory to a drive like C: or D: ?      *  ;  
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put   *  ;
        %let fail=1;
%goto okay;

 %** The following are all the failure messages returned to the user when the macro **;
  %*  is unable to process the input SAS dataset.                                   **;
%fail2: 
        %put  * ;  
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %if "%lowcase(&dset.)"="_null_" %then %do;
          %put You do not have a SAS dataset in the WORK library for          *  ;
          %put  STATA_WRAPPER to load into Stata.                                *  ;
        %end;
        %else
         %put The input dataset &dset. has to be in the work library.         *  ;
        %put For more help check here: &http.   * ;
         %** SAS 8 will put a note at the end of the log stating what page errors           **;
          %* occurred but earlier versions do not. So insert bad code to generate an error. **;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put  *  ;
        %let fail=2;
%goto okay;


%fail3: %put  *  ;  
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put You did not tell STATA_WRAPPER what directory you want to save the Stata log file.    *  ;
        %put Your call to STATA_WRAPPER should look something like this:                          *  ;
        %put %nrstr(%%)stata_wrapper(,"C:\mydata\",-replace)                                         *  ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put  *  ;
        %let fail=3;
%goto okay;

%fail4: %put  *  ;  
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put The directory %nrbquote(&out_dir.) does not exist.                 *  ;
        %put For more help check here: &http.   *  ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put  *  ;
        %let fail=4;
%goto okay;


%fail5: %put  *  ;  
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put The log file %nrbquote(&out_dir.)_&swtfns._stata_code.log already exists.                     *  ;
        %put If you want to overwrite this file, then use the STATA_WRAPPER option "-replace".    *  ;
        %put Like:  %nrstr(%%)stata_wrapper(%nrbquote(&out_dir.),-replace &swoptions.)%nrstr(;)     ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put  *  ;
        %let fail=5;
%goto okay;


%fail6: %put   *   ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put The input dataset &dset. has no observations.               *  ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put   *  ;
        %let fail=6;
%goto okay;



%fail7: %put  *  ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put STATA_WRAPPER was not able to get Stata to execute.                                *   ;
        %put This is not where your Stata executable file is located:                       *   ;
        %put &wstata.                                                          *   ;
        %put There are instructions in the top section of the stata_wrapper.mac file             *  ;
        %put that explain how to edit the stata_wrapper.mac file to set the                      *  ;
        %put macro variable wstata to the correct location of your Stata executable file.    *  ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
              STATA_WRAPPER did not successfully run your Stata do-file
        %put  *  ;
        %let fail=7;
%goto okay;

%fail8: %put   *  ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put STATA_WRAPPER was not able to get Stata to execute.                        *   ;
        %put This is not how to call Stata:                                         *   ;
        %put &ustata.                                                           *;
        %put There are instructions in the top section of the stata_wrapper.mac file    *   ;
        %put that explain how to edit the stata_wrapper.mac file to set the             *   ;
        %put macro variable ustata to the correct way to call Stata.                *   ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
               STATA_WRAPPER did not successfully run your Stata do-file
        %put   *   ;
        %let fail=8;
%goto okay;

%fail9: %put   *  ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put For reasons unknown STATA_WRAPPER was not able to get Stata to execute.    *   ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
               STATA_WRAPPER did not successfully run your Stata do-file
        %put   *   ;
        %let fail=9;
%goto okay;

%fail10: %put   *  ;
        %put ERROR: STATA_WRAPPER did not successfully run your Stata do-file              *  ;
        %put     *   ;
        %put For more help check here: &http.   * ;
        %if &isysver.<8 %then 
               STATA_WRAPPER did not successfully run your Stata do-file
        %put   *   ;
        %let fail=10;
%goto okay;



%okay: %put ;

%if &messy.=1  %then %do;
       options notes; 
       %put   *   ;
       %put NOTE: STATA_WRAPPER has created its intermediary files in:   *  ;
       %put          %nrbquote(&out_dir.)      *  ;
       %put   *   ;
%end;

options nonotes;  %** Make sure notes are shut off while deleting temp files and figuring out run time. **;

%** Figure out how much time stata_wrapper took to process the Stata do-file. **;
%** initialize macro vars **;
%let diffhour=%sysfunc(compress(%sysfunc(hour(%sysfunc(datetime())-&swtartdat.))));
%let diffmin=%sysfunc(compress(%sysfunc(minute(%sysfunc(datetime())-&swtartdat.))));
%let diffsec=%sysfunc(compress(%sysfunc(second(%sysfunc(datetime())-&swtartdat.))));

 options notes;
 %if &diffhour.>0 %then %put NOTE:  STATA_WRAPPER took about &diffhour. hours and &dffmin. minutes to run.     *   ;
 %else %if &diffmin.=0 %then %put NOTE:  STATA_WRAPPER took less than a minute to run.    *  ;
 %else %put NOTE:  STATA_WRAPPER took about &diffmin. mins to run.                      *  ;

 options nonotes;
%if %sysfunc(fileexist(&usagelog.)) %then %do;
 data _null_;
  difftime=compress("&diffhour."||":"||"&diffmin."||":"||round(&diffsec.,0.1));
  file &usagelog. mod;
  put "   SAS dataset name: &dset.  pwd=&pwdir. ";
  put "   Elapsed time for STATA_WRAPPER macro is " difftime;
  put "   fail=&fail. ";
 run;
%end;

options obs=&obs. &notes. ;  %** Restore options. **;
 %** Make sure that the last dataset created in work is the users dataset. **;
%let sysdsn=&sw_dsn.;
%let syslast=&sw_last.;

%if &unix.=0 %then %do;
 %sysexec &pwdrive. ;   %** change to the drive that SAS started out in. **;
%end;  %** end of if unix=0 do loop **;
%** sysexec requires no quotes even when changing to dirs with spaces in windows or unix **;
%sysexec cd &pwdir. ;   %** change to the directory that SAS started out in. **;
%nevrmind: ;  %** Go to here if an error occurred before stata_wrapper started **;

%MEND stata_wrapper;