*** SELUNBOX PROGRAM Version 1.03: (SELUNBOX.SAS) ***;
*** CREATED BY: Edward Cary Bean, Jr. ***;
***             U.S. Bureau of Census, Office of the Director ***;
*** DATE:       July 25, 1990 ***;
*** REVISED:    Oct. 12, 1990 ***;
*** REVISED:    Oct. 14, 1997 ***;
*** PURPOSE:    Converts a "BOXED" ASCII text file into ***;
***             a SAS Data Set with formats and Format Catalog. ***;
*** NOTE:       The "BOXED" input to this program is both data and information ***;
***             defining the data. It is CRITICAL that this program and ***;
***             the ASCII text file it reads not be modified by ***;
***             program users. If modifications or corrections are required ***;
***             contact the program creator so that the master program ***;
***             can be modified or corrected. The key to proper data ***;
***             transfer is CONSISTENCY! ***;
*** USER INPUT: 1) Directory Location of Source "BOXED" File ***;
***             2) "BOXED" File Name ***;
***             3) Output Data Set Directory Location ***;
***             4) Output Format Catalog Directory Location ***;
***             5) Selection of ALL or Specific Variables to UNBOX ***;
*** PGM OUTPUT: 1) A SAS Data Set (fully labeled and formatted) ***;
***             2) A SAS Format Catalog ***;
*** REVISION 1  Fixed LRECL problem for PC's & smaller systems ***;
*** REVISION 2  Fixed field input location problem for TEXTDEC variable ***;
************************************************************************;

****************************************************************;
*** CRITICAL RUN TIME MACRO VARIABLES WHICH MUST BE ADJUSTED ***;
*** ======== FOR THIS PROGRAM TO RUN PROPERLY!!!!!!!!!!!!!!! ***;
****************************************************************;
%LET SWDIR=SYSWK1$:[E_BEAN.SAS606.BOX]; *** CRITICAL location of software catalog directory ***;

*********************************************;
*** MACRO VARIABLE INITIALIZATION SECTION ***;
***  (NO adjustments required)            ***;
*********************************************;
%LET BOXVERS=1.01;*** The Program Version Variable ***;
%LET ANS=;        *** Temporary Variable for users answers ***;
%LET INPDIR=;     *** Input Directory ***;
%LET INPBOX=;     *** Input Data Set Name ***;
%LET INPSPEC=;    *** Output File Specification ***;
%LET FMTDIR=;     *** Output Formats Directory ***;
%LET OUTDIR=;     *** Output Data Set Directory  ***;
%LET SELOPT=;     *** Select Individual Variables Option ***;
************************************;
*** MACRO INITIALIZATION SECTION ***;
************************************;
*** Define the Generic Query Window ***;
%window Query IROW=2 ROWS=18
  #2 @5 ITM PROTECT=YES
  #4 @5 'QUESTION:'
  #6 @5 QUEST PROTECT=YES
  #8 @5 '>> '
  #8 @8 ANS 40
  #10 @5 'NOTE:'
  #12 @5 NOTE1 70 PROTECT=YES
  #13 @5 NOTE2 70 PROTECT=YES
  #14 @5 NOTE3 70 PROTECT=YES;
run;
*** Define Macro to run Query Window ***;
%MACRO ASK(ARG1,ARG2);
  %let ANS=;      run;   *** Clear "ANS" MacroVar ***;
  %display Query; run;   *** Run Query Window ***;
  %let TMPSTR=%QUOTE(&ARG1&ARG2);
  %GLOBAL &TMPSTR;
  %let &TMPSTR=&ANS;
  %let ITM=;      run;   *** Clear ITM ***;
  %let QUEST=;    run;   *** Clear QUEST ***;
%MEND ASK;
***************************;
*** BEGIN QUERY SECTION ***;
***************************;
*** BEGIN QUERY 1 ***;
%let QUEST=What is the INPUT Directory Specification?;
%let NOTE1=Provide the FULL Operating System Directory Path Specification.;
%let NOTE2=(DO NOT include the name of the "BOXFILE" in the Path.);
%let NOTE3=EXAMPLE: WORK$:[homedir.subdir] or /u/username/subdir/;
%ASK(INPDIR);RUN;
%put &INPDIR;RUN;
*** BEGIN QUERY 2 ***;
%let QUEST=What is the name of the "BOXFILE"?;
%let NOTE1=DO NOT include the ".box" portion of the name.;
%let NOTE2=Only enter the portion preceeding the ".box" suffix.;
%let NOTE3=EXAMPLE: MYFILE      (NOT! /username/subdir/MYFILE.BOX);
%ASK(INPBOX);RUN;
%put &INPBOX;RUN;
*** BEGIN QUERY 3 ***;
%let QUEST=Where should the "UNBOXED" SAS Data Set be placed?;
%let NOTE1=Provide a FULL Operating System Directory Path Specification.;
%let NOTE2=(The location of the future SAS Data Set Library);
%let NOTE3=EXAMPLE: user$[a_username.subdir] or /u/username/subdir/;
%ASK(OUTDIR);RUN;
%put &OUTDIR;RUN;
*** BEGIN QUERY 4 ***;
%let QUEST=Where should the "UNBOXED" SAS Format Catalog be placed?;
%let NOTE1=Provide a FULL operating system Directory Path Specification.;
%let NOTE2=(The location of the future SAS Format Library);
%let NOTE3=EXAMPLE: USER$:[username.subdir] or /u/username/subdir;
%ASK(FMTDIR);RUN;
%put &FMTDIR;RUN;
*** BEGIN QUERY 5 ***;
%let QUEST=Automatically SELECT ALL VARIABLES for "UNBOXing"?;
%let NOTE1=Enter a "Y" to UNBOX all variables.;
%let NOTE2=Make NO ENTRY to be able to select individual variables!;
%let NOTE3=;
%ASK(SELOPT);RUN;
%put "SELOPT='&SELOPT'";RUN;

DATA _NULL_;
call symput('SELOPT',upcase("&SELOPT"));
RUN;


**************************;
*** START TEMP SECTION ***;
**************************;
/*
%LET INPDIR=SYSWK1$:[E_BEAN.SAS606];
%LET INPBOX=BXNM;
%LET OUTDIR=DIR$DATA:[E_BEAN.TMP];
%LET FMTDIR=DIR$DATA:[E_BEAN.TMP];
RUN;
*/
************************;
*** END TEMP SECTION ***;
************************;

**************************;
*** BEGIN MAIN PROGRAM ***;
**************************;
options obs=MAX;
%let INPSPEC=&INPDIR&INPBOX%STR(.box);
libname SWLIB "&SWDIR";
libname OUTLIB "&OUTDIR";
libname FMTLIB "&FMTDIR";
filename BOXFILE "&INPSPEC";
run;
DATA
 GEN
   (KEEP=
      BOXVERS
      BOXTYPE
      NUMDS
      BOXNAME
      BOXLAB
      NCONV
   )
 DST
   (KEEP=
      DRTYPE
      MEMNAME
      RECLEN
      NOBS
      REQOBS
      CRDATE
      MODATE
      IDXCOUNT
      ENGINE
      MEMLABEL
   )
 VAR
   (KEEP=
      DRTYPE
      VARNUM
      NAME
      VTYPE
      TEXTPOS
      TEXTLEN
      TEXTDEC
      FORMAT
      LABEL


      SEL

   )
 FMT
   (KEEP=
      DRTYPE
      FMTNAME
      START
      END
      LABEL
      MIN
      MAX
      DEFALT
      FUZZ
      PREFIX
      MULT
      FILL
      NOEDIT
      TYPE
      SEXCL
      EEXCL
      HLO
   )
;
INFILE BOXFILE LRECL=250 PAD;
format
  BRTYPE   2.
  DRTYPE   3.
  BOXVERS  6.2
  BOXTYPE  3.
  NUMDS    3.
  BOXNAME  $CHAR8.
  BOXLAB   $CHAR40.
  NCONV    $CHAR8.
;
FORMAT
  MEMNAME  $CHAR8.
  RECLEN   12.
  NOBS     14.
  REQOBS   14.
  MEMLABEL $CHAR40.
  CRDATE   $CHAR16.
  MODATE   $CHAR16.
  IDXCOUNT 10.
  ENGINE   $CHAR8.
;
FORMAT
  VARNUM   6.
  NAME     $CHAR8.
  ALIAS    $CHAR20.
  VTYPE    1.
  TEXTPOS  6.
  TEXTLEN  4.
  TEXTDEC  2.
  FORMAT   $CHAR8.
  LABEL    $CHAR40.


  SEL      $CHAR1.

;
FORMAT
  FMTNAME  $CHAR8.
  START    $CHAR16.
  END      $CHAR16.
  LABEL    $CHAR40.
  MIN      3.
  MAX      3.
  DEFALT   3.
  FUZZ     16.
  PREFIX   $CHAR2.
  MULT     BEST12.
  FILL     $CHAR1.
  NOEDIT   3.
  TYPE     $CHAR1.
  SEXCL    $CHAR1.
  EEXCL    $CHAR1.
  HLO      $CHAR3.
;


*SEL=upcase("&SELOPT");
SEL="&SELOPT";


IF BRTYPE=99 THEN STOP;
input
  BRTYPE  1-2 @;
  IF BRTYPE=1 THEN
  DO;
    INPUT
      BOXVERS  3-8
      BOXTYPE  9-11
      NUMDS    12-14
      BOXNAME  15-34
      BOXLAB   35-134
      NCONV    135-154
    ;
    OUTPUT GEN;
  END;
  IF BRTYPE=2 THEN
  DO;
    INPUT
      DRTYPE   3-5
      MEMNAME  6-25
      RECLEN   26-39
      NOBS     40-53
      REQOBS   54-67
      CRDATE   68-83
      MODATE   84-99
      IDXCOUNT 100-109
      ENGINE   110-129
      MEMLABEL 130-229
    ;
    OUTPUT DST;
  END;
  IF BRTYPE=3 THEN
  DO;
    INPUT
      DRTYPE   3-5
      VARNUM   6-11
      NAME     12-31
      VTYPE    52-52
      TEXTPOS  53-58
      TEXTLEN  59-62
      TEXTDEC  63-64
      FORMAT   65-84
      LABEL    88-187
    ;
    OUTPUT VAR;
  END;
  IF BRTYPE=4 THEN
  DO;
    INPUT
      DRTYPE   3-5
      FMTNAME  6-25
      START    26-45
      END      46-65
      LABEL    66-165
      MIN      166-168
      MAX      169-171
      DEFALT   172-174
      FUZZ     175-190
      PREFIX   191-192
      MULT     193-204
      FILL     205
      NOEDIT   206-208
      TYPE     209
      SEXCL    210
      EEXCL    211
      HLO      212-214
    ;
    OUTPUT FMT;
  END;
RUN;
data _NULL_;   *** Get GENERAL INFO into macro vars ***;
set GEN;
if _N_=1 then
  do;
    call symput('BOXTYPE',trim(BOXTYPE));
    call symput('NUMDS',trim(NUMDS));
    call symput('NCONV',trim(NCONV));
  end;
RUN;
data _NULL_;   *** Get Longest Logical Record Lenght into macro var ***;
set VAR END=EOVAR;
retain
  maxpos
  maxlen 0
;
if (textpos gt maxpos ) then
do;
  maxpos = textpos;
  maxlen = textlen;
end;
if EOVAR then
do;
  lrl=maxpos + maxlen + 2;
  if (lrl lt 250 )then lrl = 250;
  call symput('MLRL', trim(left(lrl)));
end;
run;
********************************************************;
%MACRO MAC1(ARGV1);      %*** START OF MAC1 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
%*****************************************************;
%*** Put Data Set Information into Macro Variables ***;
%*****************************************************;
%GLOBAL DSNAM_&MCCNT ;
%GLOBAL DSLAB_&MCCNT ;
%LET DSNAM_&MCCNT=;
%LET DSLAB_&MCCNT=;
RUN;
data _NULL_;
set DST;                 %*** Read Data Set Infomation ***;
if DRTYPE=&MCCNT then
do;
  call symput("DSNAM_&MCCNT",trim(MEMNAME));
  call symput("DSLAB_&MCCNT",trim(MEMLABEL));
  stop;
end;
run;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC1;              %*** END   OF MAC1 MACRO ******;
********************************************************;
%MAC1(&NUMDS);RUN;


%MACRO MACVIEW;
%IF "&SELOPT" ^= "Y" %THEN
%DO;
proc FSVIEW
  MODIFY
  data=VAR(CNTLLEV=MEM)
  fromula=SWLIB.boxcat.unbox.formula;
run;
%END;
%MEND MACVIEW; RUN;
%MACVIEW;RUN;


********************************************************;
%MACRO MAC2(ARGV1);      %*** START OF MAC2 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
%************************************************;
%*** Split into Individual VAR Info Data Sets ***;
%************************************************;
DATA VAR_&MCCNT;
format OUTTYPE $1. OUTDEC $1.;
SET VAR;
if VTYPE=2 then OUTTYPE="$";
else OUTTYPE="";
TEXTEND=TEXTPOS+TEXTLEN-1;
if VTYPE=1 and TEXTDEC^=0 then OUTDEC=(put(TEXTDEC,1.));
else OUTDEC="";




if DRTYPE = &MCCNT and  SEL ^= "" then OUTPUT;



RUN;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC2;              %*** END   OF MAC2 MACRO ******;
********************************************************;
%MAC2(&NUMDS);RUN;
filename TMP1 'unbox1.tmp';RUN;
data _NULL_;
file TMP1;
put "/**** START OF FILE TMP1 GENERATED CODE ****/";
RUN;
********************************************************;
%MACRO MAC3(ARGV1);      %*** START OF MAC3 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
data _NULL_;
SET VAR_&MCCNT end= EOD;
file TMP1 MOD;
if _N_ = 1 then
do;
  if &MCCNT = 1 then
  do;
    put "FILENAME BOXFILE '&INPSPEC';";
    put "LIBNAME OUTLIB '&OUTDIR';";
    put "OPTIONS OBS=MAX;";
    put "DATA";
  end;
  put "  OUTLIB.&&DSNAM_&MCCNT";
  put "    ( KEEP =";
end;
put "      " NAME ;
if EOD then
do;
  put "    )";
end;
RUN;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC3;              %*** END   OF MAC3 MACRO ******;
********************************************************;
%MAC3(&NUMDS);RUN;
********************************************************;
%MACRO MAC4(ARGV1);      %*** START OF MAC4 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
data _NULL_;
set VAR_&MCCNT end=EOD;
file TMP1 MOD;
if _N_ = 1 then
do;
  if &MCCNT = 1 then
  do;
    put ";";
    put "INFILE BOXFILE LRECL=&MLRL;";
    put "INPUT XAXAXAXA 1-2 @;";
    put "IF XAXAXAXA = 99 then";
    put "DO;";
    put "  INPUT XBXBXBXB 3-5 @;";
  end;
  put "  IF XBXBXBXB = &MCCNT then";
  put "  DO;";
  put "    INPUT";
end;
put "      " NAME OUTTYPE TEXTPOS +(-1) "-" TEXTEND OUTDEC;
if EOD then
do;
  put "    ;";
  put "    OUTPUT OUTLIB.&&DSNAM_&MCCNT;";
  put "  END;";
end;
RUN;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC4;              %*** END   OF MAC4 MACRO ******;
********************************************************;
%MAC4(&NUMDS);RUN;
********************************************************;
%MACRO MAC5(ARGV1);      %*** START OF MAC5 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
data _NULL_;
set VAR_&MCCNT end=EOD;
file TMP1 MOD;
if _N_ = 1 then
do;
  if &MCCNT = 1 then
  do;
    put "END;";
  end;
  put "PROC DATASETS LIBRARY=OUTLIB MEMTYPE=DATA;";
  put "  MODIFY &&DSNAM_&MCCNT (LABEL='&&DSLAB_&MCCNT');";
end;
if LABEL^="" then
do;
  put "     LABEL " NAME +(-1) "='" LABEL +(-1) "';" ;
end;
if EOD then
do;
  put "RUN;";
end;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC5;              %*** END   OF MAC5 MACRO ******;
********************************************************;
%MAC5(&NUMDS);RUN;
***********************************************;
*** INCLUDE THE GENERATED CODE IN FILE TMP1 ***;
***********************************************;
%INCLUDE TMP1;RUN;
******************************************;
*** FIX RESERVE WORD "DEFAULT" PROBLEM ***;
******************************************;
proc datasets memtype=DATA;
modify FMT;
rename DEFALT=DEFAULT;
RUN;
****************************;
*** BUILD FORMAT CATALOG ***;
****************************;
proc format library=FMTLIB cntlin=FMT;
RUN;
********************************************************;
%MACRO MAC6(ARGV1);      %*** START OF MAC6 MACRO ******;
%DO MCCNT=1 %TO &ARGV1 ; %*** START OF MACRO DO LOOP ***;
%*******************************************************;
%let FMTSPC=&OUTDIR&&DSNAM_&MCCNT%STR(.fmt);RUN;
%let OUTSPC=&OUTDIR&&DSNAM_&MCCNT;RUN;
filename FMT1 "&FMTSPC";RUN;
data _NULL_;
set VAR_&MCCNT end=EOD;
file FMT1;
if _N_ = 1 then
do;
  put "/* FILENAME = '&FMTSPC' */";
  put "/* Include this file with a %INCLUDE satement in SAS programs */";
  put "/* in order to use predefined VARIABLE FORMATS for: */";
  put "/*    COLLECTION      = '&INPBOX' */";
  put "/*    DATA SET        = '&OUTSPC' */";
  put "/* This file AutoGenerated by SAS Program UNBOX.SAS Version '&BOXVERS' */";
  put "/* E.C.Bean,Jr. - DIR - programmer */";
  put ;
  put "FORMAT";
end;
if FORMAT^="" then
do;
  put "  " NAME FORMAT +(-1) ".";
end;
if EOD then
do;
  put "; /* END of %INCLUDE File for Data Set '&OUTSPC' */";
end;
%*******************************************************;
%END;                    %*** END   OF MACRO DO LOOP ***;
%MEND MAC6;              %*** END   OF MAC6 MACRO ******;
********************************************************;
%MAC6(&NUMDS);RUN;
*****************************;
*** Reset Macro Variables ***;
*****************************;
%LET BOXVERS=;    *** The Program Version Variable ***;
%LET ANS=;        *** Temporary Variable for users answers ***;
%LET INPDIR=;     *** Input Directory ***;
%LET INPBOX=;     *** Input Data Set Name ***;
%LET INPSPEC=;    *** Output File Specification ***;
%LET FMTDIR=;     *** Output Formats Directory ***;
%LET OUTDIR=;     *** Output Data Set Directory  ***;
%LET SELOPT=;     *** Select Individual Variables Option ***;
%LET SWDIR=;  *** CRITICAL location of software catalog directory ***;
********************************;
*** END of UNBOX.SAS PROGRAM ***;
********************************;