program simdif
     implicit integer (a-z)

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c
c     SIMDIF -- compare two SIMTEL20 index files and list differences.
c
c
c        Author:
c
c           Gregory D. Flint, Purdue University Computing Center, 1990.
c
c
c        Warranty notice:
c
c           Purdue University Computing Center (PUCC) warrants only
c           that PUCC testing has been applied to this code.  No other
c           warranty, expressed or implied, is applicable.
c
c
c        Description:
c
c           The program reads two input files as follows:
c
c              old - previous simtel20 index file,
c              new - current simtel20 index file.
c
c           It compares the two files and generates five report files as
c           follows:
c
c              add - a list of files whose entries were added to the new
c                    index,
c              chg - a list of files whose entries were changed in the
c                    new index (version, size, date, desc, etc.),
c              del - a list of files whose entries were deleted from the
c                    new index,
c              ftp - the contents of the add & chg files formatted for
c                    use by the autoftp program (available from
c                    SIMTEL20), and
c              lst - statistics about the run.
c
c
c         Notes:
c
c            Should the format of the index file change, the parameter
c            statements that appear in each routine will need to be
c            changed.
c
c            Do not try to compare index files across a format change
c            after changing the parameter statements as the old file
c            will fail to parse properly.
c
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc



c-----------------------------------------------------------------------
c     parameters:
c
c        flds = number of fields (+1) in the index files.
c
c        ldrv, ldir, ... = length of a field (+1 if data near max size)
c        pdrv, pdir, ... = position of an output field
c
c        linp = length of an input line (including quote marks)
c
c        add, chg, ... = unit numbers for the seven input/output files
c-----------------------------------------------------------------------

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     parameter ( add =  3 )
     parameter ( chg =  4 )
     parameter ( del =  7 )
     parameter ( ftp =  8 )
     parameter ( lst =  9 )
     parameter ( new = 10 )
     parameter ( old = 11 )


c-----------------------------------------------------------------------
c     /chars/ -- character variable common block
c
c        ascii  = symbol in the index indicating an ascii file
c        inline = input line (from old or new file)
c        outnew = parsed input line from new file
c        outold = parsed output line from old file
c-----------------------------------------------------------------------

     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold


c-----------------------------------------------------------------------
c     /intgrs/ -- integer variable common block
c
c        added  = number of entries added to the new file
c        chged  = number of entries changed in the new file
c        deled  = number of entries deleted from the new file
c        haderr = if non-zero, indicates the file with a parse error
c        nlines = number of entries read from the new file
c        olines = number of entries read from the old file
c-----------------------------------------------------------------------

     common / intgrs / added, chged, deled, haderr, nlines, olines


c-----------------------------------------------------------------------
c     /fields/ -- field related data
c
c        flen() = array containing the length of each field
c        fpos() = array containing the starting position of each field
c        fptr   = integer pointer to field being processed
c        fquo() = logical array indicating whether or not the field is
c                 bracketed by quote marks
c-----------------------------------------------------------------------

     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo


c-----------------------------------------------------------------------
c     /eoflag/ -- end of file detected flags
c
c       ndone = true if eof detected on old file
c       odone = true if eof detected on new file
c-----------------------------------------------------------------------

     common / eoflag / ndone, odone
     logical ndone, odone


c
c     open the files and prime the pumps.
c

     open (old, file="simold")
     open (new, file="simnew")
     open (del, file="simdel")
     open (add, file="simadd")
     open (chg, file="simchg")
     open (lst, file="simlst")
     open (ftp, file="simftp")
c
     read (old, 10, end=50) inline
  10 format (a)
     olines = olines + 1
     call split (old)
     if (haderr .ne. 0) go to 90
     read (new, 10, end=70) inline
     nlines = nlines + 1
     call split (new)
     if (haderr .ne. 0) go to 110

c
c     main loop
c

  20 if (outold(pdrv:pver-1) .lt. outnew(pdrv:pver-1)) then
        call dels
     else if (outold(pdrv:pver-1) .gt. outnew(pdrv:pver-1)) then
        call adds
     else
        call chgs
     endif
     if (haderr .eq. old) go to 90
     if (haderr .eq. new) go to 110
     if (.not.(odone.and.ndone)) go to 20
c
     write (lst, 30) olines, nlines
  30 format (1x,i6," lines read from old file."/
    *        1x,i6," lines read from new file.")
     write (lst, 40) added, chged, deled
  40 format (/1x,i6," files added."/
    *         1x,i6," files changed."/
    *         1x,i6," files deleted.")
c
     stop "simdif -- normal termination"

c
c     error processing
c
c
  50 write (lst, 60)
  60 format (1x,"Empty ""old"" file."/)
     go to 130
c
  70 write (lst, 80)
  80 format (1x,"Empty ""new"" file."/)
     go to 130
c
  90 write (lst, 100) fptr
 100 format (1x,"Parse of ""old"" file failed at field",i2/)
     go to 130
c
 110 write (lst, 120) fptr
 120 format (1x,"Parse of ""new"" file failed at field",i2/)
c     go to 130
c
 130 write (lst, 30) olines, nlines
     stop "simdif -- errors detected."
c
     end
     subroutine adds
     implicit integer (a-z)

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c     adds -- process entries added to the new index file
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     parameter ( add =  3 )
     parameter ( chg =  4 )
     parameter ( del =  7 )
     parameter ( ftp =  8 )
     parameter ( lst =  9 )
     parameter ( new = 10 )
     parameter ( old = 11 )
c
     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold
c
     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo
c
     common / intgrs / added, chged, deled, haderr, nlines, olines
c
     common / eoflag / ndone, odone
     logical ndone, odone


c-----------------------------------------------------------------------
c
c     1) list the addition.
c     2) add it to the autoftp file.
c     3) increment the count.
c     4) get and split another line from the new file.
c     5) if end of file, set parsed new line to all [upper case] Z's.
c
c-----------------------------------------------------------------------

     write (add, 10) (outnew(fpos(i):fpos(i)+flen(i)-1),i=1,flds-1)
  10 format (1x,3("""",a,""","),4(a,","),"""",a,"""")
c
     write (ftp, 20) outnew(pdrv:pdrv+ldrv-1), outnew(pdir:pdir+ldir-1)
  20 format ("-d ",2a)
     if (outnew(ptyp:ptyp) .eq. ascii) then
        write (ftp, 30) outnew(pnam:pnam+lnam-1)
  30    format ("-a ",a)
     else
        write (ftp, 40) outnew(pnam:pnam+lnam-1)
  40    format ("-8 ",a)
     endif
c
     added = added + 1
c
     read (new, 50, end=60) inline
  50 format (a)
     nlines = nlines + 1
     call split (new)
     return
c
  60 ndone = .true.
     do 70 i = 1, pend
        outnew(i:i) = "Z"
  70 continue
     return
c
     end
     subroutine blckda
     implicit integer (a-z)

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c     blckda -- preset labeled common block data
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold
c
     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo
c
     common / intgrs / added, chged, deled, haderr, nlines, olines
c
     common / eoflag / ndone, odone
     logical ndone, odone


c-----------------------------------------------------------------------
c     note that not all fields in each block are preset
c-----------------------------------------------------------------------

     data ascii / "7" /
c
     data flen / ldrv, ldir, lnam, lver, lsiz, ltyp, ldat, ldes, lend /
     data fpos / pdrv, pdir, pnam, pver, psiz, ptyp, pdat, pdes, pend /
     data fquo / 3*.true., 4*.false., .true., .false. /
c
     data added, chged, deled, haderr, nlines, olines / 6*0 /
c
     data ndone, odone / .false., .false. /
c
     end
     subroutine chgs
     implicit integer (a-z)

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c     chgs -- process entries that changed from the old to the new file
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     parameter ( add =  3 )
     parameter ( chg =  4 )
     parameter ( del =  7 )
     parameter ( ftp =  8 )
     parameter ( lst =  9 )
     parameter ( new = 10 )
     parameter ( old = 11 )
c
     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold
c
     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo
c
     common / intgrs / added, chged, deled, haderr, nlines, olines
c
     common / eoflag / ndone, odone
     logical ndone, odone


c-----------------------------------------------------------------------
c
c     1) if there is no change, skip to 5) below
c     2) list the change.
c     3) add it to the autoftp file.
c     4) increment the count.
c     5) get and split another line from both files.
c     6) if end of file, set parsed new/old line to all Z's.
c
c-----------------------------------------------------------------------

     if (outold .eq. outnew) go to 50
c
     write (chg, 10) olines, nlines,
    *   (outold(fpos(i):fpos(i)+flen(i)-1),i=1,flds-1),
    *   (outnew(fpos(i):fpos(i)+flen(i)-1),i=1,flds-1)
  10 format (1x,"old: ",i6,"   new: ",i6/
    *        1x,"< ",3("""",a,""","),4(a,","),"""",a,""""/
    *        1x,"> ",3("""",a,""","),4(a,","),"""",a,""""/
    *        1x,25("-"))
c
c
     write (ftp, 20) outnew(pdrv:pdrv+ldrv-1), outnew(pdir:pdir+ldir-1)
  20 format ("-d ",2a)
     if (outnew(ptyp:ptyp) .eq. ascii) then
        write (ftp, 30) outnew(pnam:pnam+lnam-1)
  30    format ("-a ",a)
     else
        write (ftp, 40) outnew(pnam:pnam+lnam-1)
  40    format ("-8 ",a)
     endif
     chged = chged + 1
c
  50 read (new, 60, end=70) inline
  60 format (a)
     nlines = nlines + 1
     call split (new)
     if (haderr .ne. 0) return
     go to 90
c
  70 ndone = .true.
     do 80 i = 1, pend
        outnew(i:i) = "Z"
  80 continue
c
  90 read (old, 60, end=100) inline
     olines = olines + 1
     call split (old)
     return
c
 100 odone = .true.
     do 110 i = 1, pend
        outold(i:i) = "Z"
 110 continue
     return
c
     end
     subroutine dels
     implicit integer (a-z)

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c     dels -- process entries deleted from the new index file
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     parameter ( add =  3 )
     parameter ( chg =  4 )
     parameter ( del =  7 )
     parameter ( ftp =  8 )
     parameter ( lst =  9 )
     parameter ( new = 10 )
     parameter ( old = 11 )
c
     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold
c
     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo
c
     common / intgrs / added, chged, deled, haderr, nlines, olines
c
     common / eoflag / ndone, odone
     logical ndone, odone


c-----------------------------------------------------------------------
c
c     1) list the deletion.
c     2)
increment the count.
c     3) get and split another line from the old file.
c     4) if end of file, set parsed old line to all [upper case] Z's.
c
c-----------------------------------------------------------------------

     write (del, 10) (outold(fpos(i):fpos(i)+flen(i)-1),i=1,flds-1)
  10 format (1x,3("""",a,""","),4(a,","),"""",a,"""")
c
     deled = deled + 1
c
     read (old, 20, end=30) inline
  20 format (a)
     olines = olines + 1
     call split (old)
     return
c
  30 odone = .true.
     do 40 i = 1, pend
        outold(i:i) = "Z"
  40 continue
     return
c
     end
     subroutine split (newold)
     implicit integer (a-z)
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c     split -- parse the input line and set the new/old output line
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

     parameter ( flds = 9)
c
     parameter ( ldrv =  4    ,  pdrv =           1 )
     parameter ( ldir = 20    ,  pdir = pdrv + ldrv )
     parameter ( lnam = 12    ,  pnam = pdir + ldir )
     parameter ( lver =  2 + 1,  pver = pnam + lnam )
     parameter ( lsiz =  6 + 1,  psiz = pver + lver )
     parameter ( ltyp =  1    ,  ptyp = psiz + lsiz )
     parameter ( ldat =  6    ,  pdat = ptyp + ltyp )
     parameter ( ldes = 46    ,  pdes = pdat + ldat )
     parameter ( lend =  0    ,  pend = pdes + ldes )
c
     parameter ( linp = 1+ldrv+1 + 1+ldir+1 + 1+lnam+1 +
    *                     lver   +   lsiz   +   ltyp   +
    *                     ldat   + 1+ldes+1 +   flds   )
c
     parameter ( add =  3 )
     parameter ( chg =  4 )
     parameter ( del =  7 )
     parameter ( ftp =  8 )
     parameter ( lst =  9 )
     parameter ( new = 10 )
     parameter ( old = 11 )
c
     common / chars / ascii, inline, outnew, outold
     character*1      ascii
     character*(linp) inline
     character*(pend) outnew, outold
c
     common / fields / flen(flds), fpos(flds), fptr, fquo(flds)
     logical fquo
c
     common / intgrs / added, chged, deled, haderr, nlines, olines
c
     character*(pend) splits, temp


c-----------------------------------------------------------------------
c
c     1) preset the input pointer and result string
c     2) loop for each field
c        a) build a temporary string from it
c        b) right justify the field if it is not quote-mark-bracketed
c        c) move the temporary string into the result string
c     3) move the result string into the appropriate output string
c
c-----------------------------------------------------------------------

     inptr = 1
     splits = " "
c
     do 20 fptr = 1, flds-1
        if (fquo(fptr)) inptr = inptr + 1
        temptr = 1
  10    if ((fquo(fptr).and.inline(inptr:inptr).ne."""") .or.
    *       (.not.fquo(fptr).and.inline(inptr:inptr).ne.",")) then
           if (temptr .gt. flen(fptr)) then
              haderr = newold
              return
           endif
           temp(temptr:temptr) = inline(inptr:inptr)
           temptr = temptr + 1
           inptr = inptr + 1
           go to 10
        endif
        if (fquo(fptr)) then
           inptr = inptr + 2
           splits(fpos(fptr):fpos(fptr)+temptr-1-1) = temp(1:temptr-1)
        else
           inptr = inptr + 1
           splits(fpos(fptr+1)-temptr+1:fpos(fptr+1)-1) =
    *         temp(1:temptr-1)
        endif
  20 continue
c
     if (newold .eq. old) then
        outold = splits
     else
        outnew = splits
     endif
     return
c
     end