You are on page 1of 8

program CSV2SAT

*
*-----------------------------------------------------------------------
*
* Copyright 2006 Kevin G. Rhoads
* Portions Copyright 1993, 1995, 1996 Kevin G. Rhoads
*
* This is designed to compile with either
* 16 bit: Microsoft Fortran 4.x or 5.x
* 32 bit: Microsoft FPS 1, FPS 4, Digital DVF 5, Digital/Compaq CVF 6
*
* It uses the filename hacking routines Copyright Kevin G. Rhoads
*
*-----------------------------------------------------------------------
* The purpose of this program is to aid in the analysis of data from WDQs
* The data is captured by DataQ and exported to a
* Comma Separated Value (.CSV) file which is Excel's preferred ASCII import
* format. Fortunately, CSV formats are easily read and written in programs
* written with most HLLs, including C and Fortran.
*
* This specific program is intended to process one or more CSV files whose
* names are specified on the command-line. (This allows support for a
* form of drag&drop under Win3.0 or later, under Win9x and NT the path
* must be 8.3 naming convention compatible for drag&drop to reliably
* work.)
*
* Command line access is via Microsoft extensions, this limits portability
* a trifle. Digital/Compaq supports the MS extensions. IIRC Watcom
* will hack these as is, Absoft requires a little source massaging.
* Language is Fortran77 using common extensions. (So, I've been coding
* Fortran for about 33 years, C for only about 10 years. And it is MUCH
* harder to make wild pointer errors in Fortran. Plus I've got filename
* hacking routines in Fortran, that I've been writing and using since IBM
* PC-DOS 1.1 and IBM Personal FORTRAN v1.0. If you don't like Fortran,
* I'll recode the d*** thing in MASM . . . ;-)
*
* Input files are given .CSV extensions by default, output files match
* input file names with the extension changed to .SAT; output files are
* in CSV format. Output files can be manually imported into Excel, or read
* with a text editor. Automatic importing into Excel requires the extension
* to be changed to .CSV; it is recommended that this is best achieved from
* the command prompt using:
* REN *.SAT *.SAT.CSV
*
* The .CSV input file is four or five column, with optionally sampling
* time in the first column, channel 1 in the next column to channel 4
* in the last column. Presently, channel 1 is tap 1 value &c.
*
* Real (i.e., C "float") variables are used for the read-in as the
* numbers in the .CSV input file are real/float formatted.
*
*
*-----------------------------------------------------------------------
*
* Yes, Fortran will allow you to use undeclared variables. But I don't.
*
character drive*1,path*63,file*8,ext*3,defext*3,defin*3,altin*3
character*127 outfile,infile,arg,lines(5)
character*17 acol2,acol3
integer*4 nargs,argstat,namelen
integer*2 curarg,icol2,icol3
logical cmdline
external nargs,getarg
integer maxinputs,datarate
parameter (maxinputs=1400000)
* real col2,col3,temp,start(maxinputs),end(maxinputs)
* real when,col2,col3,temp,whens(maxinputs)
real when,col2,col3,temp,col4,col5
real owhen,ocol2,ocol3,ocol4,ocol5
* integer current(maxinputs),force(maxinputs)
* real current(maxinputs),force(maxinputs),temp2(maxinputs)
* real temp3(maxinputs),work(maxinputs)
*
* for 16 bit compiles, we force these two arrays into separate segments
* common /NotNear1/ current
* common /NotNear2/ force
* common /NotNear3/ temp2
* common /NotNear4/ temp3
* common /NotNear5/ work
*
* integer input,i,least
integer input,i,j,k,numlines,iostat,grumble
logical verbose,combine,twocol,threecol,onecol,fourcol,fivecol
logical double
integer len_trim
intrinsic len_trim
external fnchk,fnovr
*-----
print *,' CSV Data Reformatting Program '
print *,' Copyright 2005 Kevin G. Rhoads'
print *,' Portions Copyright 1993, 1995, 1996 Kevin G. Rhoads'
print *,' Version 1.00.10 - 1/25/2006 '
print *,' '
verbose = .false.
defin = 'CSV'
altin = 'CSV'
defext = 'TXT'
twocol = .false.
threecol = .false.
grumble = 0
* DataQ is 240 samples/sec, CRREL data is 1000 samples/sec
datarate = 240
* datarate = 1000
* datarate = 100
double = .false.
*
* under MS-DOS and it's derivatives (e.g., Win95) the command-line
* is parsed ala Unix, zero based indexing, argv[0] is the progname
* so we have command line arguments IFF number of args (i.e., narg())
* is greater than 1
*
curarg = 1
cmdline = (nargs().gt.1)
5901 continue
combine = .false.
if (cmdline) then
* get next filename
call getarg(curarg,arg,argstat)
* any more left?
curarg = curarg + 1
cmdline = (nargs().gt.curarg)
*
if (arg(1:1).eq.'-'.or.arg(1:1).eq.'/') then
if (arg(2:2).eq.'C'.or.arg(2:2).eq.'c') then
if (arg(3:3).eq.'O'.or.arg(3:3).eq.'o') then
do 101 i = 1,len(arg)

if ( arg(i:i).eq.'=' .or. arg(i:i).eq.':' ) then
arg(i:i) = ' '
goto 102
else
arg(i:i) = ' '
endif
101 continue
102 read (arg,'(f12.0)',err=103) temp
if (temp.ge.0.0 .and. temp.lt.100.0) then
* combine_range = temp
* print *,' combine_range = ',combine_range
endif
103 continue
endif
elseif (arg(2:2).eq.'B'.or.arg(2:2).eq.'b') then
if (arg(3:3).eq.'A'.or.arg(3:3).eq.'a') then
do 106 i = 1,len(arg)
if ( arg(i:i).eq.'=' .or. arg(i:i).eq.':' ) then
arg(i:i) = ' '
goto 107
else
arg(i:i) = ' '
endif
106 continue
107 read (arg,'(f12.0)',err=108) temp
if (temp.ge.0.0 .and. temp.lt.100.0) then
* barf_current = temp
* print *,' barf_current = ',barf_current
endif
108 continue
endif
elseif (arg(2:2).eq.'O'.or.arg(2:2).eq.'o') then
if (arg(3:3).eq.'U'.or.arg(3:3).eq.'u') then
do 111 i = 1,len(arg)
if ( arg(i:i).eq.'=' .or. arg(i:i).eq.':' ) then
arg(i:i) = ' '
defext = arg(i+1:i+3)
goto 112
else
arg(i:i) = ' '
endif
111 continue
112 continue
endif
elseif (arg(2:2).eq.'I'.or.arg(2:2).eq.'i') then
if (arg(3:3).eq.'N'.or.arg(3:3).eq.'n') then
do 113 i = 1,len(arg)
if ( arg(i:i).eq.'=' .or. arg(i:i).eq.':' ) then
arg(i:i) = ' '
defin = arg(i+1:i+3)
goto 114
else
arg(i:i) = ' '
endif
113 continue
114 continue
endif
endif
if (cmdline) goto 5901
endif
*
drive = ' '
path = ' '
file = ' '
ext = defin
call fnchk(arg,infile,drive,path,file,ext)
* fnchk takes apart the input path, and any blank pieces are replaced with the
* specified pieces, then the path is reassembled into the output string
* so this call supplies CSV as the extension if the arg specifies a path
* with no extension
*
else
stop ' Bye'
endif
*
* prepare for processing here . . .
*
open (unit=10,file=infile,status='old',err=5907)
goto 4300
*
* possibly try alternate extension
5907 continue
if (defin .ne. altin ) then
drive = ' '
path = ' '
file = ' '
ext = altin
call fnchk(arg,infile,drive,path,file,ext)
open (unit=10,file=infile,status='old',err=5902)
else
goto 5902
endif

4300 continue
namelen = len_trim(infile)
print *,' Infile = ',infile(1:namelen)
ext = defext
call fnovr(infile,outfile,drive,path,file,ext)
* fnovr takes apart the input path, and all pieces are replaced with the
* specified non-blank pieces, then the path is reassembled into the output
* string -- so this call replaces the extension with EDG
*
namelen = len_trim(outfile)
print *,' Outfile = ',outfile(1:namelen)
print *,' '
open (unit=11,file=outfile,status='unknown',err=5904)
input = 0
read (10,'(A)',err=5904) lines(1)
j = len_trim(lines(1))
k = 0
numlines = 1
do 1 i = 1,j
if (lines(1)(i:i) .eq. ',') k = k + 1
1 continue
if (k.ne.0) goto 10
read (10,'(A)',err=5904) lines(2)
j = len_trim(lines(2))
k = 0
numlines = 2
do 2 i = 1,j
if (lines(2)(i:i) .eq. ',') k = k + 1
2 continue
if (k.ne.0) goto 10
read (10,'(A)',err=5904) lines(3)
j = len_trim(lines(3))
k = 0
numlines = 3
do 3 i = 1,j
if (lines(3)(i:i) .eq. ',') k = k + 1
3 continue
if (k.ne.0) goto 10
read (10,'(A)',err=5904) lines(4)
j = len_trim(lines(4))
k = 0
numlines = 4
do 4 i = 1,j
if (lines(4)(i:i) .eq. ',') k = k + 1
4 continue
10 continue
onecol = k.eq.0
twocol = k.eq.1
threecol = k.eq.2
fourcol = k.eq.3
fivecol = k.eq.4
if (onecol) then
read (10,*,err=5804) ocol2
elseif (twocol) then
read (10,*,err=5804) ocol2,ocol3
elseif (threecol) then
read (10,*,err=5804) owhen,ocol2,ocol3
elseif (fourcol) then
read (10,*,err=5804) ocol2,ocol3,ocol4,ocol5
elseif (fivecol) then
read (10,*,err=5804) owhen,ocol2,ocol3,ocol4,ocol5
* whens(1) = owhen
else
namelen = len_trim(infile)
print *,' I don''t understand input file format'
print *,' skipping ',infile(1:namelen)
if (cmdline) goto 5901
stop ' Arrgh, they got me . . .'
endif
goto 5899
5804 continue
rewind (unit=10,iostat=iostat)
if (iostat.ne.0) print *,' Rewind iostat = ',iostat
read (10,'(A)',err=5904) lines(5)
numlines = numlines + 1
goto 10
5899 continue
input = 1
* current(input) = col2
* force(input) = col3
* print *,ocol2,ocol3
*
* do processing here . . .
*
* Fortran 77 does not have do while or do until constructions, but
* those are mere syntactical sugar for the proper use of GOTO
* [GOTOs are NOT harmful, UNDISCIPLINED use of GOTOs is . . .
* but the same can be said of pointers, . . .]
*
4400 continue
if (onecol) then
read (10,*,err=5905) col2
elseif (twocol) then
read (10,*,err=5905) col2,col3
elseif (threecol) then
read (10,*,err=5905) when,col2,col3
elseif (fourcol) then
read (10,*,err=5905) col2,col3,col4,col5
elseif (fivecol) then
read (10,*,err=5905) when,col2,col3,col4,col5
endif
input = input + 1
* current(input) = col2
* force(input) = col3
* the err=5905 is the usual loop termination, exit upon running out of input (or
other input error)
*
* process
*
* ocol5 = col5
* ocol4 = col4
* ocol3 = col3
* ocol2 = col2
** loop termination before array over-run
* if (input.ge.maxinputs) goto 5905
goto 4400
*
* end of input processing
*
*
* begin post processing next
*
5905 continue
* begin post processing
*
*
* end of post processing
*
*
rewind (unit=10,err=5911)
5911 rewind (unit=10,err=5912)
5912 continue
print *,' Input = ',input
if (onecol.and.double) then
write (11,7006) 'SAT_TXT_FILE',2,input,datarate
else
write (11,7006) 'SAT_TXT_FILE',k+1,input,datarate
endif
do 11 i = 1,input
if (onecol) then
read (10,*,err=5906) col2
if (double) then
write (acol2,7003) col2
write (acol3,7003) col2
do 32 j = 1,17
if (acol2(j:j).ne.' ') then
icol2 = j
goto 33
endif
32 continue
33 continue
do 34 j = 1,17
if (acol3(j:j).ne.' ') then
icol3 = j
goto 35
endif
34 continue
35 continue
write (11,*) acol2(icol2:len_trim(acol2))//' '//
& acol3(icol3:len_trim(acol3))
else
write (11,7003) col2
endif
elseif (twocol) then
read (10,*,err=5906) col2,col3
write (acol2,7003) col2
write (acol3,7003) col3
do 12 j = 1,17
if (acol2(j:j).ne.' ') then
icol2 = j
goto 13
endif
12 continue
13 continue
do 14 j = 1,17
if (acol3(j:j).ne.' ') then
icol3 = j
goto 15
endif
14 continue
15 continue
write (11,*) acol2(icol2:len_trim(acol2))//' '//

& acol3(icol3:len_trim(acol3))
elseif (threecol) then
read (10,*,err=5906) when,col2,col3
write (acol2,7003) col2
write (acol3,7003) col3
do 22 j = 1,17
if (acol2(j:j).ne.' ') then
icol2 = j
goto 23
endif
22 continue
23 continue
do 24 j = 1,17
if (acol3(j:j).ne.' ') then
icol3 = j
goto 25
endif
24 continue
25 continue
write (11,*) acol2(icol2:len_trim(acol2))//' '//
& acol3(icol3:len_trim(acol3))
endif
11 continue
*
5904 continue
close (unit=11,status='keep',err=5906)
5906 continue
5902 continue
close (unit=10,status='keep',err=5903)
5903 continue
*
* more input files remain to be processed?
if (cmdline) goto 5901
*
stop ' Bye'
* 7001 format(i5,a,i5,a,i5,a,i5,a,i5)
* 7002 format(i5,a,i5,a,i5,a,i5,a,i5,a,i5)
7003 format (g14.7)
7004 format (g14.7,' ',g14.7)
7005 format (g14.7,' ',g14.7,' ',g14.7)
7006 format (A/I1/I6/i6)
end