Viewing contents of file '../idllib/iuedac/iuelib/pro/con_sav.pro'
;******************************************************************************
;+
;*NAME:
;
;	CON_SAV
;
;*CLASS:
;
;*CATEGORY:
;
;	IUESIPS
;
;*PURPOSE:
;
;	Converts RDAF *.sav files to a format compatible with the host
;	operating system.  CON_SAV can convert files created with IUESAVE
;	under VMS IDL version 1 or version 2, and files created under DEC
;	or SunOS IDL version 2 to the appropriate format for the host
;	operating system.  Output files are written using IDL FORTRAN
;	compatible unformatted write statements of the form
;	WRITEU,UNIT,H,W,F,E. 
;     
;*CALLING SEQUENCE:
;
;	CON_SAV,IMAGET,cpupar
;
;*PARAMETERS:
;
;	IMAGET   (REQ) (I) (0) (S)  
;	         File name of .sav file (without .sav extension).
;	         Corrected data is written over original file on 
;	         UNIX systems.  Wildcards are accepted.
;
;	CPUPAR   (OPT) (I) (I) (0)
;	         Parameter to identify data translation mode.
;
;			no conversion        0
;
;			VAX     to  MIPSEL   1
;			MIPSEL  to  VAX      2
;
;			VAX     to  SPARC    3
;			SPARC   to  VAX      4
;
;			MIPSEL  to  SPARC    5
;			SPARC   to  MIPSEL   6
;
;	         Supported Data Types:
;
;			VAX    - VAXstations, MicroVAX
;			MIPSEL - DECstations, IBM 386
;			SPARC  - SparcStations, Sun 4##
;
;		 Note: No Conversion is required between like data types,
;		       such as DECstations and IBM 386s.
;
;		 If CPUPAR is not given in the call, the user will be
;		 prompted for it.
;
;		 Note that only two modes are allowed for a given machine.
;		 The allowed modes are those in which the final data format
;		 is compatible with the host operating system.
;
;*EXAMPLES:
;
;	to convert swp1234cii.sav:
;	   con_sav,'swp1234cii'
;
;	to convert all .sav files in users account:
;	   con_sav,'*'
;
;*SYSTEM VARIABLES USED:
;
;	!err_string
;
;*INTERACTIVE INPUT:
;
;	If CPUPAR is not given in the call, the user will be  prompted for it.
;
;*SUBROUTINES CALLED:
;
;	TRANS_BYTES
;	PARCHECK
;	DECOMPOSE
;	CHKFITS
;       CONMENU
;       PLATFORM
;
;*FILES USED:
;
;	imaget given in calling sequence.
;
;*SIDE EFFECTS:
;
;*RESTRICTIONS:
;
;	Program requires that the .SAV files be transferred to the host 
;	CPU verbatim (e.g., using the -v option in DNICP or binary mode 
;	in FTP).  Files transferred as ascii files (e.g., without the -v 
;	option in DNICP) appear to be corrupted in that the 1st 2 bytes 
;	are removed(?) and end-of-record bytes are added.
;
;	SAV files created using the IDL routine SAVLIST are not properly 
;	converted by this program.
;
;	Not for use with fit formatted files.
;
;*NOTES:
;
;*PROCEDURE:
;
;	CON_SAV uses the procedure PLATFORM to determine the host operating
;       system and cpu architecture.  The allowed conversion options are then
;       defined based on the operating system and cpu type.  The user is asked
;       to select from the allowed conversion options and may also be asked if
;       the input file was created on a VMS system.  Findfile is used to expand
;       wildcard filename inputs to a string array.  Each input file is checked
;       to determine if it is in fits format.  If it is, the file is not
;       converted.  Then each input file is opened, and read into a byte array
;       of length determined by the FSAT command. 
;
;	The IUESAVE files consist of a record containing a four integer 
; 	vector which gives the number of elements in the H, W, F, & E 
;	vectors, followed by a record containing the H, W, F, & E vectors. 
;	Under VMS IDL version 1, the second record usually consists of 
;       several blocks.  Under VMS IDL version 2, the H, W, F, & E vectors 
;	are contained in a single block unless the number of bytes in the 
;	second record exceeds 32767 bytes.  Under Unix or Ultrix IDL, the
;	second record always consists of a single block.  In addition to 
;	the bytes which contain the data, extra bytes are included at the 
;	beginning and end of each block.  VMS FORWRT and WRITEU commands 
;	add a 4 byte longword at the beginning of each record, and a 2 
;	byte integer (the block size) at the beginning and end of each 
;	block.  If the number of bytes in the second record of a VMS 
;       IDL Version 2 file exceeds 32767 bytes, the 4 inter-block bytes
;       are preceeded by one "garbage" byte, which must also be removed.
;       Unix or Ultrix WRITEU commands add a 4 byte longword 
;	(the blocksize) at the beginning and end of each block. 
;  
;       Varible-length record files transferred from vms using the binary 
;       mode of Multinet FTP are slightly different in format.  Multinet 
;       removes the dcl-added bytes during the file transfer.  If the vms 
;       file had carriage-return, carriage-control file attributes however, 
;       Multinet adds a byte 10 (i.e., a cntl-J or line feed) at the end 
;       of each block or record.  VMS users are therefore prompted for 
;       whether Multinet was used.  Note that a new version of Multinet is 
;       expected in the fall of 93 which will offer other modes for binary 
;       file tranfer.
;
;	The number of elements in the H, W, F, and E arrays, and the
;	blocksize of the second record containing the H, W, F, and E
;	arrays are determine from the first 12 to 20 bytes in the input
;	file.  The block size is determined from the 2 byte integer 
;	(files created on the VAX) or 4 byte longword (files created on 
;	a UNIX machine) present at the start of the second record.  The 
;	non-data bytes are removed, and the data portion of the second
;	record is concatenated into a single array.  The bytes 
;	representing the H, W, F & E vectors are extracted from this 
;	array and converted to a format compatible with the host 
;	operating system by TRANS_BYTES.  The byte vectors are converted 
;	to the proper type, and written out to disk using WRITEU.  If 
;	the host cpu is a VMS system, a new version of the output file 
;	is opened using the /SEGMENTED keyword.  On a UNIX machine, the 
;	output file is opened with the /F77_UNFORMATTED keyword and 
;	written over the old input file.
;
;*MODIFICATION HISTORY:
;
;       8/21/89  RWT version 1
;	9/14/89  RWT uses FINDFILE to allow use of wildcards 
;	6/07/90  RWT modify to be compatible with both UNIX and ULTRIX
;	2/27/91  GRA modify to allow conversions between VMS version 1
;		     or version 2 *.sav files, ULTRIX, and SunOS *.sav
;		     files. Input is accomplished by associating the 
;		     entire input file with a single byte array of length
;		     status.size. Added ERROR keyword to OPENR statments.
;	4/1/91   PJL added  PARCHECK; updated prolog
;	5/1/91   RWT add support for DOS
;	6/13/91  GRA merged vms and sun versions, changed "dos" to "DOS"
;	7/25/91  PJL cleaned up; tested VAX to SUN and SUN to VAX options; 
;	  	     updated prolog
;       10/25/91 GRA globally changed all references to "syspar" to 
;		     "cpupar", changed cpupar to reference data formats as
;		     specified by the !version.arch system variable; used 
;		     /block keyword when opening the input file on a VMS 
;		     machine so that the rms information can be bypassed; 
;		     corrected error in blocksize byte removal from large
;		     data records for files created under VMS IDL version 
;		     2; condensed VMS and Unix branches; updated prolog; 
;		     tested on ultrix/vax, ultrix/mipsel, vms/vax, 
;		     sunos/sparc.
;       10/29/91 GRA changed blocksize byte removal for large VMS IDL V2
;                    files so that "extra" byte is removed before blocksize
;                    bytes rather than after; cleaned up print statements;
;                    tested on ultrix/vax, ultrix/mipsel, vms/vax, 
;                    sunos/sparc; updated prolog.
;       4/27/93  RWT add option for vms files transferred via Multinet FTP 
;                    and replace trans_bytes calls for integer conversion
;                    with intrinsic byteorder commands.
;	15 Nov 93  PJL added CHKFITS
;        9 Jun 94  PJL replaced !version with CONMENU and PLATFORM
;       28 Sep 94  RWT add support for Multinet block mode
;-
;******************************************************************************
 pro con_sav,imaget,cpupar
;
 npar = n_params(0)
 if (npar eq 0) then begin
    print,'CON_SAV,IMAGET,cpupar'
    retall
 endif  ; npar eq 0
 parcheck,npar,[1,2],'CON_SAV'
;
 platform,dummy,sysos=sys
 conmenu,cpupar,cpustr,from_vms_system=from_vms_system
;
; ask user if file originated on VMS system if it was possible
;
 test_from_vms = cpupar ne 0
 if test_from_vms then begin
    vms_possible = where([1,2,3,5] eq cpupar,ask_vms)
   ;
    if (ask_vms gt 0) then begin
       from_vms_system = ''
       print,' '
       read,'Were the input files formatted for a VMS system? ',from_vms_system
       yesno,from_vms_system
       if (from_vms_system) then begin
         mn = ''
         print,' '
         print,'Were Files transferred with MultiNet FTP (y (def) or n)?'
         read,'(note: type n if using MultiNet block mode) ',mn
         yesno,mn
       endif
    endif else begin
       from_vms_system = 0
    endelse  ; sys ne vms or ultrix
 endif  ; test_from_vms
; 
; form string array of files to convert
;
 decompose,imaget,d,p,n,ext,vers
 imaget = d + p + n + '.sav'
 str = findfile(imaget,count=savn)
;
 print,' '
 print,'Found ' + strtrim(savn,2) + ' *.sav files.'
;
 if (savn eq 0) then begin
    print,' '
    print,'Returning from CON_SAV'
    print,' '
    return
 endif  ; savn
;
 for i=0,savn-1 do begin
   ;
    print,' '
    print,'Converting ' + str(i) + ' from ' + cpustr + ' format.'
;
;  make sure not a fits file
;
    chkfits,str(i),newsips,/silent
    if (newsips) then begin
       print,str(i) + ' is a fits file.  File will not be converted.'
       goto,nextfile
    endif  ; newsips
;
   ; open file and read all records into a single byte array
   ;
    openr,/get_lun,un,str(i),error = err,/block
   ;
    if (err ne 0) then begin
       print,' '
       print,'Error accessing file '+str(i)
       print,'   '+!err_string
       print,'   Proceeding to next file...'
       goto,nextfile
    endif  ; err
   ;
    stat = fstat(un)
    siz = stat.size
   ;
    rec = assoc(un,bytarr(siz))
    brec = rec(0)
    free_lun,un
   ;
    if from_vms_system then begin 
      ;
      ; BEGIN CONVERSION FOR DATA FROM A VMS SYSTEM
      ;
      ; define byte representation of beginning longword (if not multinet)
      ; and byte representation of the 4 element integer 
      ; vector (n_elements of H, W, F, & E) in first record
      ;
      mnc = 2 * (mn)                      ; mnc=2 for multinet, 0 for woll.
      if (not mn) then begin
          bl = brec(0:3)
          if (cpupar gt 2) then byteorder,bl,/lswap
          l = long(bl,0,1)
          l = l(0)
          if (l le 0) then begin
             print,' '
             print,'Error converting '+str(i)
             print,'   File may be corrupted, or already converted.'
             print,'   Proceeding to next file...'
             goto,nextfile
          endif  ; l le 0
      endif  ; not mn
      ;
      ; convert byte representations to final type
      ;
       bnum = brec(4-mnc:11-mnc)
       if (cpupar gt 2) then byteorder,bnum,/sswap
       num = long(fix(bnum,0,4))
       snum = strtrim(num,2)
       snum = snum(0)+' '+snum(1)+' '+snum(2)+' '+snum(3)
      ;
      ; print n_elements H, W, F, & E
      ;
       print,' '
       print,'Number of entries in H, W, F, & E = ' + snum
      ;
      ; define byte representation of second record blocksize
      ; convert to host cpu internal format
      ;
      if (mn) then begin         ; if multinet
          remove = 3L
          blksize = 32768L
      endif else begin           ; if not multinet
          bblksize = brec(12:13)
          if (cpupar gt 2) then byteorder,bblksize,/sswap
          blksize = fix(bblksize,0,1)
          blksize = long(blksize(0))
      ;
      ; make corrections to blocksize and number of bytes to remove at
      ; beginning of blocks if the number of bytes written to the 
      ; H, W, F, & E block exceeds 32767 under VMS IDL Version 2
      ;
          if (blksize eq 32767L) then begin
             blksize = 32768L
             remove = 5L
          endif else begin
             remove = 4L
          endelse  ; blksize eq 32767L
      ;
      ; check for error and print blksize
      ;
          if (blksize le 0) then begin
             print,' '
             print,'Error converting '+str(i)
             print,'   File may be corrupted, or already converted.'
             print,'   Proceeding to next file...'
             goto,nextfile
             print,' '
          endif else begin
             print,' '
             print,'Data record blocksize = ' + strtrim(blksize,2)
             print,' '
          endelse  ; blksize le 0
          blksize = blksize + 2L        ; spacing between bytes to be removed
      endelse
      ; 
      ; define tot vector to include blocksize bytes to eof
      ; define tbyt to be n_elements tot (siz-12)
      ;
       tot = brec(12-mnc:siz-1L)
       tbyt = n_elements(tot)
      ;
       neob = tbyt / blksize         ; # of end-of-block words
      ;
      ; remove integers from start & end of each block in byte array
      ; remove 4 bytes at a time unless file ends on a block boundary
      ; (then remove just 2 bytes)
      ;
       tmp = tot
      ;
       for n=1,neob do begin
             ind = (blksize*n) + remove - 1L*(remove eq 5L)
             if (ind le (tbyt-1L)) then tmp(ind-remove*n) = tot(ind:*)
       endfor  ; n
      ;
       if (mn) then tmp = tmp(3L:*) else tmp = tmp(4L:*) ; remove header
      ;
    endif else begin
      ;
      ; BEGIN CONVERSION FOR DATA FROM A UNIX OR DOS SYSTEM
      ;
      ; define byte representations of beginning and ending blocksize
      ; longwords, and byte representation of the 4 element integer
      ; vector (n_elements of H, W, F, E) in first record
      ;
       bl = brec(0:3)
       bl2 = brec(12:15)
       bnum = brec(4:11)
      ;
      ; convert byte representations to host cpu internal format
      ;
       if (cpupar gt 2) then byteorder,bl,/lswap
       if (cpupar gt 2) then byteorder,bl2,/lswap
       if (cpupar gt 2) then byteorder,bnum,/sswap
;       trans_bytes,bl,3,cpupar
;       trans_bytes,bl2,3,cpupar
;       trans_bytes,bnum,2,cpupar
      ;
      ; convert byte representations to final type
      ;
       l = long(bl,0,1)
       l2 = long(bl2,0,1)
       l = l(0)
       l2 = l2(0)
       num = long(fix(bnum,0,4))
       snum = strtrim(num,2)
       snum = snum(0)+' '+snum(1)+' '+snum(2)+' '+snum(3)
      ;
      ; check for error and print n_elements H, W, F, E
      ;
       if (l ne l2) then begin
          print,' '
          print,'Error converting '+str(i)
          print,'   File may be corrupted, or already converted.'
          print,'   Proceeding to next file...'
          goto,nextfile
       endif else begin
          print,' '
          print,'Number of entries in H, W, F, & E = '+snum
       endelse  ; l
      ;
      ; define byte representations of beginning and ending blocksize
      ; longwords for second data record.
      ;   
       bblksize = brec(16:19)
       bblksize2 = brec(siz-4L:siz-1L)
      ;
      ; convert byte representations to host cpu internal format
      ;
       
       if (cpupar gt 2) then byteorder,bblksize,/lswap
       if (cpupar gt 2) then byteorder,bblksize2,/lswap
;       trans_bytes,bblksize,3,cpupar
;       trans_bytes,bblksize2,3,cpupar
      ;
      ; convert byte representations to final type
      ;
       blksize = long(bblksize,0,1)
       blksize2 = long(bblksize,0,1)
       blksize = blksize(0)
       blksize2 = blksize2(0)
      ;
      ; check for error and print blocksize
      ;
       if (blksize ne blksize2) then begin
          print,' '
          print,'Error converting '+str(i)
          print,'   File may be corrupted, or already converted.'
          print,'   Proceeding to next file...'
          print,' '
          goto,nextfile
       endif else begin
          print,' '
          print,'Data record blocksize = ' + strtrim(blksize,2)
          print,' '
       endelse  ;  blksize
      ;
      ; form temporary byte array containing H, W, F, & E 
      ;
       tmp = bytarr(blksize)
       tmp(0) = brec(20L:blksize+20L-1L)
      ;
    endelse  ; from_vms_system
   ;
   ; check tmp vector against the number of bytes needed for H, W, F, & E
   ;
    rnum = n_elements(tmp)
    fnum = num(0)*2L + (num(1) + num(2) + num(3))*4L
   ;
    if (fnum gt rnum) then begin
       print,' '
       print,'Fewer bytes remaining than expected.'
       print,'  Proceeding to next file...'
       goto,nextfile
    endif  ; fnum gt rnum
   ;
   ; form index based on num values
   ;
    hind = (num(0) * 2L) - 1L
    wind = hind + (num(1) * 4L)
    find = wind + (num(2) * 4L)
    eind = find + (num(3) * 4L)
   ;
   ; extract byte representations of H, W, F, & E
   ;
    bh = tmp(0:hind)
    bw = tmp(hind+1L:wind)
    bf = tmp(wind+1L:find)
    be = tmp(find+1L:eind)
   ;
   ; convert byte representations to host cpu internal format 
   ;
    if (cpupar gt 2) then byteorder,bh,/sswap
;   trans_bytes,bh,2,cpupar
    trans_bytes,bw,4,cpupar
    trans_bytes,bf,4,cpupar
    trans_bytes,be,4,cpupar
   ;
   ; convert byte representations to final type
   ;
    h = fix(bh,0,num(0))
    w = float(bw,0,num(1))
    f = float(bf,0,num(2))
    e = float(be,0,num(3))
   ;
   ; strip version number from final output name
   ;
    decompose,str(i),d,p,n,ext,ver
    name = d+p+n+ext
   ; 
   ; write vectors to file using segmented keyword if cpu is vms
   ; and f77_unformatted keyword if cpu is a unix machine with
   ; unformatted write statments
   ;
    if (sys eq 'vms') then openw,/get_lun,un,name,/segmented else   $
       openw,/get_lun,un,name,/f77_unformatted
   ;
    num = fix(num)
    writeu,un,num
    writeu,un,h,w,f,e
   ;
    free_lun,un
   ;
    nextfile:
   ;
 endfor  ; i
;
 return
 end  ; con_sav