home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 6 File
/
06-File.zip
/
gdiff.zip
/
gdiff.for
< prev
next >
Wrap
Text File
|
1999-11-22
|
57KB
|
1,928 lines
c program to compute a gdiff difference between two files
c
c
c Error returns
c 1- failed to specify input file
c 2- problem computing md4 (oldfile)
c 3- problem computing md4 (newfile)
c 4 - bad -blocksize option
c 5 - verification requires an output file
c 31 - could not open old file
c 32 - problem rewinding old file
c 33 - old file is empty
c 34 - unable to read entire oldfile into memory
c 35 - unable to allocate memory while creating synopsis
c 36 - verification failure
c 37 - unable to open temporary file
c 41 - problem allocating memory to create diff file
c 42 - problem opening newfile
c 43 - internal write problem
c 46 - error writing to ouptut file
c 47 - problem allocating memory to read newfile
c 48 - problem reading newfile (possibly eof)
c 49 - unable to open output file
c 51 - unable to open "difference file"
c 52 - not a gdiff formatted difference file
c 53 - unable to read from difference file
c 54 - unimplemented "large move" gdiff command encountered
c 55 - error in ungdiff procedure
c 56 - illegal gdiff code
include 'fsublib.fi'
character *140 oldfile,newfile,opt1,out_file
CHARACTER *80 MK_TEMPFILENAME,TMPNAME,version
character *32 comp_md4,amd4,bmd4,newmd4,newmd4b
integer synsize,oldsize
integer numargs,istat,do_gdiff,do_ungdiff
integer blocksize,nblocks
integer do_synopsis
character *(*) synopsis !allocated later
logical qgotold,q_domd4,qgotnew,q_ungdiff,qgotout,quiet,qverify
integer i36
common /cm36/i36,quiet
c ------ being user changeable parameters
c blocksize used in synopsis creation (0=program chooses
c note that blocksize can be overridded by a -blocksize=nnnn argument
blocksize=0
i36=6 ! std output unit number
quiet=.false.
version='GDIFF ver. 1.01'
c ------- end of user changeable parameters
c read arguments from command line
numargs=iargc()
q_ungdiff=qgotold=q_domd4=qgotnew=qgotout=qverify=.false.
oldfile=' '
newfile=' '
out_file=' '
do jj=1, numargs-1
mm=igetarg(jj,opt1)
if (opt1(1:1).eq.'-') then
call captaliz(opt1)
if (opt1(1:4).eq.'-MD4') then
q_domd4=.true.
endif
if (opt1(1:4).eq.'-V') then
qverify=.true.
endif
if (opt1(1:8).eq.'-VERSION') then
print *,version
call fexit(0)
stop
endif
if (opt1(1:4).eq.'-U') then
q_ungdiff=.true.
endif
if (opt1(1:4).eq.'-Q') then
quiet=.true.
endif
if (opt1(1:3).eq.'-B=') then
read(opt1(4:lentrim(opt1)),*,iostat=ierr)
1 blocksize
if (ierr.ne.0) then
print *,'ERROR Bad blocksize option:',
1 opt1(1:lentrim(opt1))
call fexit(4)
stop
endif
endif
cycle ! get next argument
endif
if (.not.qgotold) then !not an option, must be afilename
oldfile=opt1
qgotold=.true.
elseif (.not.qgotnew) then
newfile=opt1
qgotnew=.true.
else !the output (difference) file
out_file=opt1
i36=36
endif
enddo
if (oldfile.eq. ' ' .or. oldfile.eq.'?')
1 then
print *,'GDiff -- compute a difference between two files'
print *,' '
print *,'Syntax:'
print *,' x:>GDiff oldfile newfile [out_file]',
1 ' [-options]'
print *,' '
print *,'Notes: '
print *,' * If out_file is not specified, output ',
1 'is written to stdout '
print *,' * Options: '
print *,' -MD4 -- just compute an MD4 of oldfile ',
1 ' (and newfile)'
print *,' -u -- undiff (newfile should be',
1 ' a Gdiff difference file)'
print *,' -b=nnn -- use a blocksize of nnn',
1 ' (0<nnn<2000, 0=program chooses). '
print *,' -q -- quiet (suppress status ',
1 ' messages)'
print *,' -v -- verify '
print *,' -version -- display version info '
print *, ' * GDiff will work on any kind of file',
1 ' (text or binary)'
print *,' * GDiff uses the RSYNC algorithim to compute',
1 ' differences'
print *,' * Specification of the GDIFF format can be',
1 ' found at: '
print *,
1 ' http://www.w3.org/TR/NOTE-gdiff-19970901.html '
print *,' '
print *,'Examples: '
print *,' x:>GDIFF bigdoc.old bigdoc.new bigdoc.dif -v '
print *,' x:>GDIFF -u bigdoc.old bigdoc.dif > bigdoc.nu2'
call fexit(0)
stop
endif
if (newfile.eq.' '.and.(.not.q_domd4)) then
print *,'ERROR you must specify a newfile, ',
1 'or a difference file'
call fexit(1)
stop
endif
if (qverify.and.(.not.q_Ungdiff).and.i36.eq.6) then
print *,'ERROR to verify, you must specify an output file'
call fexit(5)
stop
endif
c just do an md4?
if (q_domd4) then
amd4=comp_md4(oldfile,1)
if (amd4(1:5).eq.'ERROR') then
call fexit(2)
stop 'error'
endif
if (newfile.ne.' ') then
bmd4=comp_md4(newfile,1)
if (bmd4(1:5).eq.'ERROR') then
call fexit(3)
stop 'error'
endif
endif
write(6,*)amd4,' ',bmd4
call fexit(0)
stop
endif
c compute the GDIFF file, or the undiff file.
c in either case, open the oldfile
c open the "old" file
open(unit=41,file=oldfile,access='sequential',status='old',
1 form='unformatted',recordtype='fixed',iostat=ierr,
1 action='read')
if (ierr.ne.0) then
print *,'ERROR no such file: ',oldfile
call fexit(31)
stop
endif
rewind(unit=41,iostat=ierr)
if (ierr.ne.0) then
print *,'ERROR unable to read: ',oldfile
call fexit(32)
stop
endif
oldsize=filesize(41)
if (oldsize.eq.0) then
print *,'ERROR empty ',oldfile
call fexit(33)
stop
endif
c possibly adjust blocksize
if (blocksize.le.0.and. (.not.q_ungdiff)) then
if (oldsize.lt.10000) then
blocksize=50
elseif (oldsize.lt.25000) then
blocksize=100
elseif (oldsize.lt.100000) then
blocksize=250
elseif (oldsize.lt.2500000) then
blocksize=500
else
blocksize=1000
endif
if (.not.quiet.and.i36.ne.6) then
print *,'Using blocksize of ',blocksize
endif
endif
c Undifference?
if (q_ungdiff) then
istat=do_ungdiff(41,newfile,out_file,0)
close(unit=41,iostat=ierr)
if (istat.ne.0) then !some kind of error
call fexit(istat) !write it as output status
WRITE(6,81)ISTAT
81 FORMAT('ERROR: ',I5)
call fexit(istat)
stop ! and give up
endif
call fexit(0)
stop
endif
c --- IF here : compute a gdiff difference file
c first, compute a rync synopsis
c so let's allocate space for the synopsis
nblocks=(float(oldsize)/float(blocksize))+0.99999
synsize=nblocks*20
allocate (synopsis*synsize,stat=ierr)
if (ierr.ne.0) then
call fexit(35)
stop
endif
c if here, file is open and ready to read
C print *,' pre dosyn ',nblocks,blocksize
istat=do_synopsis(41,oldsize,synopsis,blocksize,nblocks)
C print *,' post dosyn '
if (istat.ne.0) then !some kind of error
call fexit(istat) !write it as output status
stop ! and give up
endif
c then use rsync to compute a gdiff formatted diference file
c (write it to stdout)
istat=do_gdiff(newfile,synopsis,out_file,blocksize,nblocks)
deallocate(synopsis,stat=ierr)
if (istat.ne.0) then !some kind of error
call fexit(istat) !write it as output status
WRITE(6,181)ISTAT
181 FORMAT('ERROR: ',I5)
stop ! and give up
endif
c verify ?
if ((.not.qverify).or.(i36.eq.6)) then
close(unit=41,iostat=ierr)
call fexit(0)
stop
endif
c md4 of "newfile"
newmd4=comp_md4(newfile,1)
c md4 of "reconstruction"
TMPNAME=MK_TEMPFILENAME()
ii=do_ungdiff(41,out_file,TMPNAME,1)
if (ii.ne.0) then
call fexit(36)
stop
endif
newmd4b=comp_md4(TMPNAME,1)
close(unit=41,iostat=ierr)
if (newmd4.ne.newmd4b) then
print *,'ERROR verification failed! '
print *,' (md4 hashes are: ',newmd4,newmd4b,')'
call fexit(36)
OPEN(UNIT=61,FILE=TMPNAME,IOSTAT=IERR) !DELETE TEMPFILE
CLOSE(UNIT=61,STATUS='DELETE',IOSTAT=IERR)
STOP
ELSE
IF (.NOT.QUIET) THEN
PRINT *,'Reconstructed file passes verification test'
ENDIF
endif
OPEN(UNIT=61,FILE=TMPNAME,IOSTAT=IERR) !DELETE TEMPFILE
CLOSE(UNIT=61,STATUS='DELETE',IOSTAT=IERR)
call fexit(0) !SUCCESS
end
C---------
C CREATE A TEMPORARY FILE NAME
CHARACTER *(*) FUNCTION MK_TEMPFILENAME()
CHARACTER *80 ANAME,TMPDIR
CHARACTER *13 ANAME0
INCLUDE 'FSUBLIB.FI'
logical qexist
integer *2 ihr,imin,isec,ihsec
INTEGER MM,NN
II=FGETENV('TEMP',TMPDIR)
IF (II.EQ.0) THEN
PRINT *,'ERROR no TEMP directory (can not verify)'
call fexit(37)
STOP
endif
if (tmpdir(lentrim(tmpdir):lentrim(tmpdir)).eq.'\') then
tmpdir=tmpdir(1:lentrim(tmpdir)-1)
endif
call gettim(ihr,imin,isec,ihsec)
do mm=11,99
nn=10000+imin*360+isec*60+ihsec
write(aname0,55)nn,mm
55 format('\GDF',I5,'.T',I2)
aname=tmpdir(1:lentrim(tmpdir))//aname0
inquire(file=aname,exist=qexist)
if (.NOT.qexist) EXIT
enddo
if (qexist) then
PRINT *,'ERROR could not find unused temp name ',
1 ' (can not verify)'
call fexit(37)
STOP
endif
mk_tempfilename=aname
return
end
c=--------------------------------------
c compute an rsync synopsis
integer function do_synopsis(iunit,oldsize,synopsis,
1 blocksize,nblocks)
character *(*) synopsis,ablock
character *32 md1,comp_md4
character *20 ablock20
character *8 rs1,rsync32
integer oldsize,i1
integer blocksize,nblocks,inext,iunit
integer mm,jj,ith1
allocate (ablock*blocksize,stat=ierr)
if (ierr.ne.0) then
do_synopsis=35
return
endif
c 20 character entries per block: 4 for rsync32, 16 for md4
inext=1
do ii=1,nblocks
iget=min(blocksize,1+oldsize-inext)
read(iunit)ablock(1:iget)
inext=inext+blocksize
ith1=0
rs1=rsync32(ablock(1:iget))
do mm=1,7,2
read(rs1(mm:MM+1),99)jj
ith1=ith1+1
ablock20(ith1:ith1)=char(jj)
enddo
99 format(z2)
md1=comp_md4(ablock(1:iget),0)
do mm=1,31,2
read(md1(mm:MM+1),99)jj
ith1=ith1+1
ablock20(ith1:ith1)=char(jj)
enddo
i1=(ii-1)*20
synopsis(i1+1:i1+20)=ablock20
enddo
c note: synopsis is returned as an argument
do_synopsis=0 !no error
deallocate(ablock,stat=ierr)
return
end
c------------------
c compute a 32 bit rolling checksum
character *(*) function rsync32(astring)
character *(*) astring
character *8 chksum8
integer chksum,i2,isum,isumb,ilen
ilen=len(astring)
isumb=isum=0
do i1=1,ilen
i2=ichar(astring(i1:i1))
isum=isum+i2
isumb=((ilen-i1+1)*i2) + isumb
enddo
isum=mod(isum,65536)
if (isum.lt.0)isum=isum+65536
isumb=mod(isumb,65536)
if (isumb.lt.0)isumb=isumb+65536
chksum=isum + (65536*isumb)
write(chksum8,883,iostat=ierr)chksum
883 format(z8)
rsync32=chksum8
return
END
c=--------------------------------------
c compute md4 of a file. Call it asL
c aa=comp_md4(contents,mode)
c where aa is character *32
c contents: filename, or string
c filemode: if 1, contents is read from filename.
c otherwise, contents contains the contents
character *(*) function comp_MD4(contents,filemode)
character *32 a32
character *(*)contents
integer addme,lenorig,lenorig8,filemode
integer *1 pads(64)
data pads/'80'x,63*'00'x/
integer *1 i1a(4) !use this for working with
integer i4a
equivalence (i4a,i1a)
integer mess16(16),x(0:15) !16 word chunk to digest
integer *1 mess64(64)
equivalence(mess16,mess64,x)
integer lenbits(2) !# bits in message
integer *1 lenbits_1(8)
equivalence(lenbits,lenbits_1)
character *32 ans
integer leftover,addbytes,dessize
integer a,b,c,d,aa,bb,cc,dd,il,icc,k,i16,i1,len2,len3,j
integer s11,s12,s13,s14,s21,s22,s23,s24,s31,s32,s33,s34
integer inbuffer,endbuffer
character *1 a1lc(6)
data a1lc/'a','b','c','d','e','f'/
character *2048 buffer2048
character *1 achar64(64)
integer ikk,ngrab
include 'fsublib.fi'
c read the inputfile?
if (filemode.eq.1) then
open(unit=43,file=contents,access='sequential',status='old',
1 form='unformatted',recordtype='fixed',iostat=ierr,
1 action='read')
if (ierr.ne.0) then
write(a32,77)ierr
77 format('ERROR opening file: ',i6)
comp_md4=a32
return
endif
rewind(unit=43,iostat=ierr)
if (ierr.ne.0) then
comp_md4='ERROR could not rewind file'
return
endif
dessize=filesize(43)
if (dessize.eq.0) then
comp_md4='ERROR empty file'
return
endif
else !use contents as is
dessize=len(contents)
endif
c nb: md4 of '' is d41d8cd98f00b204e9800998ecf8427e
lenorig=dessize
lenorig8=8*lenorig
lenbits(1)=lenorig8
leftover=mod(lenorig8,512)
c pad message to multiple of 512 bits.
c Last 2 words are 64 bit # bits in message
if (leftover.eq.448) addme=512
if (leftover.lt.448) addme=448-leftover
if (leftover.gt.448) addme=960-leftover
addBYTES=addme/8
c starting values of registers
a ='67452301'x
b ='efcdab89'x
c ='98badcfe'x
d ='10325476'x
len2=lenorig+ADDBYTES
len3=len2+8 ! FINAL LENGTH IN BYTES, must be multiple of 64
c load buffer
if (filemode.eq.1.and.lenorig.gt.2048) then
read(43,iostat=ierr)buffer2048
inbuffer=1
endbuffer=2048
else
endbuffer=0
endif
c loop through entire message -- 16 words at a time
do i1 = 0,((len3/64)-1)
i16=i1*64
c if file mode, load up achar64 buffer (possibly from 2k buffer)
if (filemode.eq.1) then ! read from file
if (i16+64.le.endbuffer) then !use the buffer (perhaps refill it)
do ii1=inbuffer,inbuffer+63
achar64(1+ii1-inbuffer)=buffer2048(ii1:ii1)
enddo
inbuffer=inbuffer+64
if (inbuffer.gt.1985.and.(endbuffer+2048.lt.lenorig))
1 then
read(43,iostat=ierr)buffer2048
endbuffer=endbuffer+2048
inbuffer=1
endif
else ! near the end of the file
if (i16.lt.lenorig) then
ngrab=min(64,lenorig-i16)
read(43)(achar64(ikk),ikk=1,ngrab)
endif !direct read of achar64
endif ! read from buffer
endif ! read from file
do j=1,64 ! start computing stuff for this 64byte
k=i16+j !add this byte
C add byte from message, padding, or length
if (k.le.lenorig) then
if (filemode.eq.1) then
mess64(j)=ichar(achar64(j))
else
mess64(j)=ichar(contents(k:k))
endif
else
if (k.le.len2) then
mess64(j)=pads(k-lenorig)
else
mess64(j)=lenbits_1(k-len2)
ENDIF
ENDIF
ENDDO !64 BYTES OF BLOCK
c transform this block of 16 chars to 4 values. Save prior values first */
aa=a
bb=b
cc=c
dd=d
c do 4 rounds, 16 operations per round (rounds differ in bit'ing functions
S11=3
S12=7
S13=11
S14=19
call round1_4(a, b, c, d, x( 0), S11) ! /* 1 */
call round1_4(d, a, b, c, x( 1), S12) ! /* 2 */
call round1_4(c, d, a, b, x( 2), S13) ! /* 3 */
call round1_4(b, c, d, a, x( 3), S14) ! /* 4 */
call round1_4(a, b, c, d, x( 4), S11) ! /* 5 */
call round1_4(d, a, b, c, x( 5), S12) ! /* 6 */
call round1_4(c, d, a, b, x( 6), S13) ! /* 7 */
call round1_4(b, c, d, a, x( 7), S14) ! /* 8 */
call round1_4(a, b, c, d, x( 8), S11) ! /* 9 */
call round1_4(d, a, b, c, x( 9), S12) ! /* 10 */
call round1_4(c, d, a, b, x(10), S13) ! /* 11 */
call round1_4(b, c, d, a, x(11), S14) ! /* 12 */
call round1_4(a, b, c, d, x(12), S11) ! /* 13 */
call round1_4(d, a, b, c, x(13), S12) ! /* 14 */
call round1_4(c, d, a, b, x(14), S13) ! /* 15 */
call round1_4(b, c, d, a, x(15), S14) ! /* 16 */
c /* Round 2 */
S21=3
S22=5
S23=9
S24=13
call round2_4(a, b, c, d, x( 0), S21) ! /* 17 */
call round2_4(d, a, b, c, x( 4), S22) ! /* 18 */
call round2_4(c, d, a, b, x( 8), S23) ! /* 19 */
call round2_4(b, c, d, a, x(12), S24) ! /* 20 */
call round2_4(a, b, c, d, x( 1), S21) ! /* 21 */
call round2_4(d, a, b, c, x( 5), S22) ! /* 22 */
call round2_4(c, d, a, b, x( 9), S23) ! /* 23 */
call round2_4(b, c, d, a, x(13), S24) ! /* 24 */
call round2_4(a, b, c, d, x( 2), S21) ! /* 25 */
call round2_4(d, a, b, c, x( 6), S22) ! /* 26 */
call round2_4(c, d, a, b, x(10), S23) ! /* 27 */
call round2_4(b, c, d, a, x(14), S24) ! /* 28 */
call round2_4(a, b, c, d, x( 3), S21) ! /* 29 */
call round2_4(d, a, b, c, x( 7), S22) ! /* 30 */
call round2_4(c, d, a, b, x(11), S23) ! /* 31 */
call round2_4(b, c, d, a, x(15), S24)! /* 32 */
c /* Round 3 */
S31= 3
S32= 9
S33= 11
S34= 15
call round3_4(a, b, c, d, x( 0), S31) ! /* 33 */
call round3_4(d, a, b, c, x( 8), S32) ! /* 34 */
call round3_4(c, d, a, b, x( 4), S33) ! /* 35 */
call round3_4(b, c, d, a, x(12), S34) ! /* 36 */
call round3_4(a, b, c, d, x( 2), S31) ! /* 37 */
call round3_4(d, a, b, c, x(10), S32) ! /* 38 */
call round3_4(c, d, a, b, x( 6), S33) ! /* 39 */
call round3_4(b, c, d, a, x(14), S34) ! /* 40 */
call round3_4(a, b, c, d, x( 1), S31) ! /* 41 */
call round3_4(d, a, b, c, x( 9), S32) ! /* 42 */
call round3_4(c, d, a, b, x( 5), S33) ! /* 43 */
call round3_4(b, c, d, a, x(13), S34) ! /* 44 */
call round3_4(a, b, c, d, x( 3), S31) ! /* 45 */
call round3_4(d, a, b, c, x(11), S32) ! /* 46 */
call round3_4(c, d, a, b, x( 7), S33) ! /* 47 */
call round3_4(b, c, d, a, x(15), S34) ! /* 48 */
A=AA+A
B=BB+B
C=CC+C
D=D+DD
enddo
i4a=a
write(ans(1:8),'(4(z2))')i1a
i4a=b
write(ans(9:16),'(4(z2))')i1a
i4a=c
write(ans(17:24),'(4(z2))')i1a
i4a=d
write(ans(25:32),'(4(z2))')i1a
c convert to lower case
do il=1, 32
icc=index('ABCDEF',ANS(IL:il))
if (icc.gt.0) ans(il:il)=a1lc(icc)
enddo
close(unit=43,iostat=ierr)
comp_md4=ans
return
end
C /* md4 round 1 to 4 functins */
SUBROUTINE round1_4(a1,b1,c1,d1,kk,shift)
INTEGER A1,B1,C1,D1,Kk,SHIFT,T1,T2,f_4
t1=a1+f_4(b1,c1,d1)+ kk
t2=ISHC(t1,shift)
A1=T2
return
END
SUBROUTINE round2_4(a1,b1,c1,d1,kk,shift)
INTEGER A1,B1,C1,D1,Kk,SHIFT,T1,T2,g_4,aconst
aconst='5a827999'x
t1=a1+G_4(b1,c1,d1)+ kk + aconst
t2=ISHC(t1,shift)
A1=T2
return
END
SUBROUTINE round3_4(a1,b1,c1,d1,kk,shift)
INTEGER A1,B1,C1,D1,Kk,SHIFT,aconst,T1,T2,h_4
aconst='6ed9eba1'x
t1=a1+H_4(b1,c1,d1)+ kk + aconst
t2=ISHC(t1,shift)
A1=T2
return
END
c*********** Basic functions */
c* F_4(x, y, z) == (((x) & (y)) | ((~x) & (z))) */
INTEGER FUNCTION f_4(X,Y,Z)
INTEGER X,Y,Z,T1,NOTX,t2
t1=Iand(x,y)
notx=NOT(x)
t2=Iand(notx,z)
t2=Ior(t1,t2)
f_4=t2
RETURN
END
c* G_4(x, y, z) == (((x) & (z)) | ((x) & (y)) | ((y) & (z)) ) */
INTEGER FUNCTION G_4(X,Y,Z)
INTEGER X,Y,Z,T1,T2,t3,t4
T1=Iand(x,y)
t2=Iand(x,z)
t3=iand(y,z)
t4=Ior(t1,t2)
g_4=ior(t3,t4)
RETURN
END
c* H_4(x, y, z) == ((x) ^ (y) ^ (z)) */
INTEGER FUNCTION H_4(X,Y,Z)
INTEGER X,Y,Z,T1
t1=IEor(x,y)
H_4=IEor(t1,z)
RETURN
END
c------------------------------
c capitalize a string
subroutine captaliz(sent)
character *(*)sent
character *1 char
do 100 ij=1,len(sent)
let=ichar(sent(ij:IJ))
if (let.ge.97.and.let.le.122) sent(ij:ij)=char(let-32)
100 continue
return
end
c-----------------------
c using synopsis, and the rsync algorithim, compute a difference and
c output it as a gdiff file (to stdout)
integer function do_gdiff(newfile,synopsis,out_file,
1 blocksize,nblocks)
include 'fsublib.fi'
character *(*) synopsis,newfile,ablock,out_file
character *4 ctmp4
character *8 ctmp8
character *32 ctmp32,comp_md4
character *16 ctmp16
character *20 aline20
integer mm,ierr,ierrout,ioerror,iserror
integer ierr1,ierr2,ierr3,ierr4
integer i36
logical quiet
common /cm36/i36,quiet
integer hasht(0:65535)
character *10 t1
character *5 t2
character *1 ac1,ac1a
integer rsyncs16(:)
integer rsyncs(:)
integer index_rsyncs16(:)
character *16 md4s(:)
integer nblocks,blocksize,ll
integer matchblock,read_new
integer ib1,ib2,ialpha,ibeta,chksum
integer rsync_increment_s
integer ihasht,i1,blklen,ifoo,gdiff_write,write_6
logical qfirst_32
character *1 wastype
integer was0,was1,newsize,def_blksiz
common /ccache/wastype,was0,was1,newsize,def_blksiz
c the newfile buffer
character *96384 buffer
integer bufstart,bufend
common /ccache2/buffer,bufstart,bufend
c do some initializations
def_blksiz=blocksize ! default blocksize, used by gdiff_write
qfirst_32=.false.
wastype=' '
do mm=0,65535
hasht(mm)=0
enddo
c create some storage space
allocate(rsyncs(1:nblocks),stat=ierr1)
allocate(index_rsyncs16(1:nblocks),stat=ierr2)
allocate(md4s(1:nblocks),stat=ierr3)
allocate(rsyncs16(1:nblocks),stat=ierr4)
if (ierr1+ierr2+ierr3+ierr4.ne.0) then
do_gdiff=41
return
endif
C print *,' post allocate '
c read in nblocks from synopsis (rsync32~md4 pairs)
do mm=1,nblocks
i1=1+((mm-1)*20)
aline20=synopsis(i1:i1+19)
write(ctmp8,68,err=2024)aline20(1:4)
read(ctmp8,68,err=2024)rsyncs(mm)
md4s(mm)=aline20(5:20)
write(ctmp4,66,err=2024)aline20(1:2)
66 format(z4)
68 format(z8)
read(ctmp4,66,err=2024)rsyncs16(mm)
enddo
C print *,' done reading synops8s '
c sort each record (sort by leftmost 16 bit hash, as stored in rsyncs16)
call quik_indexsort(rsyncs16,index_rsyncs16,nblocks)
C print *,' post quik '
c now make the 65k hash table
call make_hashtable(nblocks,index_rsyncs16,rsyncs16,hasht)
C print *,' post hash '
c now open the new version as unit 21 (will set newsize global)
ifoo=read_new(0,0,newfile)
if (ifoo.le.0) then !problem
do_gdiff=42
return
endif
c open output file and write gdidff header
c open output file
if (i36.ne.6) then
open(unit=i36,file=out_file,recordtype='FIXED',
1 access='sequential',
1 form='unformatted',iostat=ierr,action='WRITE')
if (ierr.ne.0) then
print *,'ERROR Unable to open output file: ',out_file
do_gdiff=49
return
endif
endif
t1='d1ffd1ff04'
read(t1,13)t2
13 format(z10)
ioerror=write_6(t2)
if (ioerror.ne.0) then
do_gdiff=46
return
endif
c set up stuff to prance through
ib1=1
ib2=ib1+blocksize
allocate(ablock*blocksize,stat=ierr)
if (ierr.ne.0) then
do_gdiff=47
return
endif
c read first block (blocksize bytes) of data
blklen=read_new(1,ib2-1,ablock)
if (BLKLEN.lt.0) then
PRINT *,'ERROR at first block read'
do_gdiff=48
return
endif
c compute the rsync for the first block..
call rsync32_compute(ablock,chksum,ialpha,ibeta)
C print *,' rsync done '
c now start the waltz
c from ith char, look for matching block
c if not found, write the character
c if found, write the character
c note that writeit will "cache" results
do while (ib1.le.newsize) ! stop when all chars examined
matchblock=0
c check the check16 against the hashtable, etc.
ihasht=hasht(ibeta)
if (ihasht.Ne.0) then
DO LL=IHASHT,NBLOCKS
mm=index_rsyncs16(LL)
IF (RSYNCS16(MM).NE.IBETA) EXIT !NO MATCH
IF (RSYNCS(MM).NE.CHKSUM) CYCLE !TRY NEXT 32BIT HASH
blklen=read_new(ib1,ib2-1,ablock) !now get actual block
if (BLKLEN.lt.0) then !to compute md4
print *,'ERROR at block read pre md4 '
do_gdiff=48
return
endif
ctmp32=comp_md4(ablock(1:blklen),0)
read(ctmp32,133,err=2024)ctmp16 !try the 128 bit hash
133 format(z32)
if (qfirst_32) then ! just look at first 32 bits?
if (ctmp16(1:4).ne.md4s(mm)(1:4)) cycle
else
if (ctmp16.ne.md4s(mm)) cycle !look at 128 bits
endif
matchblock=mm
exit
enddo
endif !hash table match
c no match? record this character, and roll the rsync ...
if (matchblock.eq.0) then !not a matching block
iserror=gdiff_write('C',ib1,0)
if (iserror.ne.0) then
rsync_gdiff=46
return
endif
c COMPUTE ROLLING CHECKSUM (also save alpha,beta
if (ib2.le.newsize) then !increment 32bit checksum
ifoo=read_new(ib2,ib2,ac1)
if (ifoo.lt.0) then
print *,
1 'ERROR reading last char (',ib2,') for rolling checksum'
do_gdif=48
return
endif
ifoo=read_new(ib1,ib1,ac1a)
if (ifoo.lt.0) then
print *,
1 'ERROR reading first char (',ib1,') for rolling checksum'
do_gdif=48
return
endif
chksum=rsync_increment_s(ac1a,ac1,ialpha, !compute rolling checksum
1 ibeta,blocksize)
ib1=ib1+1 ! begin next block here
ib2=ib2+1
else
if (ib1.ge.newsize) exit !all done
ib1=ib1+1 ! begin next block here
blklen=read_new(ib1,newsize,ablock) !too messy to compute increment,
if (blklen.lt.0) then
do_gdiff=48
print *,'ERROR reading near end of file block '
return
endif
call rsync32_compute(ablock(1:blklen),chksum, !so just compute using
1 ialpha,ibeta) !all characters
ib2=newsize+1
endif
cycle !get next block
endif ! not a match
c if here, got a rsync16, 32, and md4 match. So write some results
iserror=gdiff_write('B',matchblock,blklen)
if (iserror.ne.0) then
rsync_gdiff=49
return
endif
if (ib2.gt.newsize) exit ! done
ib1=ib1+blocksize ! skip past this block, and start searching again
ib2=ib1+blocksize
blklen=read_new(ib1,ib2-1,ablock)
if (blklen.lt.0) then
print *,'ERROR reading skip to next block '
do_gdiff=48
return
endif
call rsync32_compute(ablock(1:blklen),chksum,ialpha,ibeta)
enddo !scan over all characters
c add any "unmatched characters
iserror=gdiff_write('F',0,0)
if (iserror.ne.0) then
rsync_gdiff=46
return
endif
call write_int(0,1) ! close gdiff file
close (unit=21,iostat=ierrout) !close new file
close (unit=36,iostat=ierrout) ! close output file
if (.not.quiet.and.i36.ne.6) then
open(unit=i36,file=out_file,iostat=ierr,
1 action='read',form='unformatted')
if (ierr.ne.0) return
iout=filesize(36)
if (lentrim(out_File).lt.40) then
write(6,51)iout,out_file(1:lentrim(out_file))
51 format('OK ',i9,' bytes written to difference file ',a)
else
write(6,53)iout,out_file(1:lentrim(out_file))
53 format('OK ',i9,' bytes written to difference file: '/a)
endif
close(unit=i36,iostat=ierr)
endif
deallocate(rsyncs,stat=ierr )
deallocate(md4s,stat=ierr )
deallocate(rsyncs16,stat=ierr )
deallocate(index_rsyncs16,stat=ierr )
deallocate(ablock,stat=ierr)
do_gdiff=0
return
c ------ status and errors
2024 continue
do_gdiff=43
return
end
c-------------------------------------------
c write to an output device (on unit i36)
integer function write_6(ac)
character *(*)ac
integer i36
logical quiet
common /cm36/i36,quiet
if (i36.ne.6) then
write(i36,iostat=ierr)ac
write_6=ierr
return
else
ill=len(ac)
do mm=1,ill
write(i36,55,iostat=ierr)ac(mm:mm)
if (ierr.ne.0) then
write_6=ierr
return
endif
enddo
write_6=0
return
endif
55 format(a1,$)
end
c-------------------------------------------
c function to read from unit 21, into astring.
c start and end bytes of read are given, as well
c as file size (if end of read>filesize, read
c until filesize).
c Returns astring in argument,
c function value is length of astring (usually
c 1+end-start, but possibly 1+file_size-start read from
integer function read_new(istart,iend0,astring)
include 'fsublib.fi'
integer istart,iend,iend0
character *(*) astring
integer ido,ierr
character *1 wastype
integer was0,was1,newsize,def_blksiz
common /ccache/wastype,was0,was1,newsize,def_blksiz
c the newfile buffer
character *96384 buffer
integer bufstart,bufend
common /ccache2/buffer,bufstart,bufend
c initialize?
if (istart+iend0.eq.0) then
open(unit=21,file=astring,
1 access='SEQUENTIAL',
1 status='old',form='unformatted',
1 recordtype='fixed',iostat=ierr,action='read')
if (ierr.ne.0) then
print *,'ERROR unable to open ',
1 astring(1:lentrim(astring))
read_new=-1
return
else
newsize=filesize(21)
read_new=newsize
endif
c prime the buffer
bufstart=1
BUFEND=MIN(NEWSIZE,96384)
read(21,iostat=ierr)buffer(1:BUFEND)
if (ierr.ne.0) then !error reading
read_new=-1
endif
return ! end of initialization
endif
iend=min(iend0,newsize) !correct upper limit
ido=1+iend-istart ! characters to be returned
c check for bad range
if (iend.lt.istart.or.istart.gt.newsize) then ! check for error
PRINT *,'ERROR out of range ',ISTART,IEND,NEWSIZE
read_new=-1
return
endif
c within buffer? don't do anything
if (istart.ge.bufstart.and.iend.le.bufend) then
continue
c otherwise, reload buffer
c if (iend.lt.bufstart .or. istart.gt.bufend) then !get fancy later
else
II=SEEKUNIT(21,ISTART-1,0)
IF (II.LT.0) THEN
PRINT *,'ERROR BAD SEEKUNIT ',ISTART,II
READ_NEW=-1
RETURN
ENDIF
NRD=1+MIN(NEWSIZE,ISTART+96383)-ISTART
read(21,iostat=ierr)buffer(1:NRD)
IF (IERR.NE.0) THEN
PRINT *,'ERROR BAD READ ',IERR,ISTART,NRD
READ_NEW=-1
RETURN
ENDIF
BUFSTART=ISTART
BUFEND=BUFSTART+NRD-1
ENDIF
c now we are ready to send back the info
ioff1=1+istart-bufstart
ioff2=ioff1+ido-1
astring(1:ido)=buffer(ioff1:ioff2)
read_new=ido
return
end
c-------------------------------------------
c write to stout using gdiff format
c if B (block found) call, then need to use "blksiz" (current
c blocksize) to find end (use def_blksize for beginning
integer function gdiff_write(atype,iat,blksiz)
character *(*)atype
integer iat,iserror ,blksiz
integer ndo,ns1,blklen,read_new
integer jas1,jassize
character *1 wastype
CHARACTER *4096 C4096
integer was0,was1,newsize,def_blksiz,write_6
common /ccache/wastype,was0,was1,newsize,def_blksiz
COMMON /CSUM/KSUM
DATA KSUM/0/
iserror=0
if (wastype.eq.' ') then ! first call
if (atype.eq.'C') then
was0=was1=iat
else
was0=((iat-1)*def_blksiz)+1
was1=was0+blksiz-1
endif
wastype=atype
gdiff_write=0
return
endif
c case 1: C,B
if (atype.ne.'C'.and.wastype.eq.'C') then ! flush chars, start new block
ndo=1+was1-was0
if (ndo.lt.247) then
call write_int(ndo,1)
else
if (ndo.lt.65536) then ! 2 bytes
call write_int(247,1)
call write_int(ndo,2)
else
call write_int(248,1)
call write_int(ndo,4)
endif
endif
do jj=was0,was1,4096
blklen=read_new(JJ,MIN(JJ+4095,WAS1),C4096)
if (blklen.GE.1) then
iserror=write_6(c4096(1:blklen))
else
print *,'ERROR with ',Jj
endif
if (iserror.ne.0.or.blklen.lt.0) then
print *,'ERROR writing character run ',blklen,iserror
gdiff_write=-1
return
endif
enddo
wastype=atype !not strictly needed if "F"
was0=((iat-1)*def_blksiz)+1
was1=was0+blksiz-1
gdiff_write=0
return
endif
c case 2: C,C
if (atype.eq.'C'.and.wastype.eq.'C') then !augment a characters run
was1=iat
gdiff_write=0
return
endif
c case 3: B,B
if (atype.eq.'B'.and.wastype.eq.'B') then !augment a block run, or flush
ns1=(iat-1)*def_blksiz
if (ns1.eq.was1) then !augment
was1=was1+blksiz
gdiff_write=0
return
endif
jas1=was0 ! record a copy range
jassize=1+was1-was0
if (jas1.lt.65536) then
if (jassize.lt.256) then
call write_int(249,1)
call write_int(jas1,2)
call write_int(jassize,1)
elseif (jassize.lt.65536) then
call write_int(250,1)
call write_int(jas1,2)
call write_int(jassize,2)
else
call write_int(251,1)
call write_int(jas1,2)
call write_int(jassize,4)
endif
else !position > 65535
if (jassize.lt.256) then
call write_int(252,1)
call write_int(jas1,4)
call write_int(jassize,1)
elseif (jassize.lt.65536) then
call write_int(253,1)
call write_int(jas1,4)
call write_int(jassize,2)
else
call write_int(254,1)
call write_int(jas1,4)
call write_int(jassize,4)
endif
endif
was0=ns1+1
was1=was0+blksiz-1
gdiff_write=0
return
endif
c case 4: B,C
if (atype.ne.'B'.and.wastype.eq.'B') then !flush a block run, start char run
jas1=was0 ! record a copy range
jassize=1+was1-was0
if (jas1.lt.65536) then
if (jassize.lt.256) then
call write_int(249,1)
call write_int(jas1,2)
call write_int(jassize,1)
elseif (jassize.lt.65536) then
call write_int(250,1)
call write_int(jas1,2)
call write_int(jassize,2)
else
call write_int(251,1)
call write_int(jas1,2)
call write_int(jassize,4)
endif
else !position > 65536
if (jassize.lt.256) then
call write_int(252,1)
call write_int(jas1,4)
call write_int(jassize,1)
elseif (jassize.lt.65536) then
call write_int(253,1)
call write_int(jas1,4)
call write_int(jassize,2)
else
call write_int(254,1)
call write_int(jas1,4)
call write_int(jassize,4)
endif
endif
was0=was1=iat
wastype=atype !not strictly needed if "F"
gdiff_write=0
return
endif
end
cc--------------
c write a 1, 2 or 4 byte integer to unit
subroutine write_int(ival,nbytes)
integer ival,iserror,nbytes
character *1 c1
character *2 c2
character *4 c4
character *8 c8
integer write_6
111 format(z4)
1111 format(z8)
if (nbytes.eq.1) then
c1=char(ival)
iserror=write_6(c1)
if (iserror.gt.0) goto 10
return
endif
if (nbytes.eq.2) then
write(c4,111)ival
read(c4,111)c2
iserror=write_6(c2)
if (iserror.gt.0) goto 10
return
endif
c otherwise use 4bytes (assume value < 2billion
write(c8,1111)ival
read(c8,1111)c4
iserror=write_6(c4)
if (iserror.gt.0) goto 10
return
10 print *,'ERROR writing integer: ',ival
stop
end
subroutine make_hashtable(nblocks,index_rsyncs16,
1 rsyncs16,hasht)
integer rsyncs16(1)
integer index_rsyncs16(1)
integer hasht(0:65535)
integer ink,mm,ll,nblocks
do mm=1,nblocks
ink=index_rsyncs16(mm)
ll=rsyncs16(ink)
if (hasht(ll).eq.0) then
hasht(ll)=mm
endif
enddo
return
end
c---------------
subroutine rsync32_compute(astring,chksum,ialpha,ibeta)
integer chksum,ialpha,ibeta
character *(*)astring
integer isum,i2,i1,ilen
ilen=len(astring)
c compute alpha
isum=0
do i1=1,ilen
i2=ichar(astring(i1:i1))
isum=isum+i2
enddo
isum=mod(isum,65536)
if (isum.lt.0)isum=isum+65536
ialpha=isum
c compute beta
isum=0
do i1=1,ilen
i2=ichar(astring(i1:i1))
isum=((ilen-i1+1)*i2) + isum
enddo
isum=mod(isum,65536)
if (isum.lt.0)isum=isum+65536
ibeta=isum
chksum=ialpha + (65536*ibeta)
return
end
c----------------
c COMPUTE ROLLING CHECKSUM */
integer function rsync_increment_s(oldchar,newchar,ialpha,
1 ibeta,ib)
character *1 oldchar,newchar
integer ialpha,ibeta,ioldchar,inewchar,ib
IOLDCHAR=ichar(oldchar)
INEWCHAR=ichar(newchar)
ialpha=ialpha- Ioldchar + Inewchar
ialpha=mod(ialpha,65536)
if (ialpha.lt.0) ialpha=65536+ialpha
ibeta=ibeta-(ib*ioldchar)+ialpha
ibeta=mod(ibeta,65536)
if (ibeta.lt.0) ibeta=65536+ibeta
rsync_increment_s=ialpha+(ibeta*65536)
return
end
c==============================================================
c sort to an index. Index is integer, array to sort is integer
c Based on QUIKSORT
SUBROUTINE quik_iNDEXSORT(X,xindex,nx)
integer x(1),pivotv
integer xindex(1),nx
integer stack(5000)
integer segbeg,segend,segsize,ep,bp,mid
integer lenend,lenbeg,newpivot,nspt,ij
logical QPopSort_rsync
nspt=0
c initialize stack
do 2 ij=1,5000
stack(ij)=0
2 continue
do 3 ij=1,nx
xindex(ij)=ij
3 continue
segbeg=1
segend=nx
c first "sort"
call indqsort3_rsync(segbeg,mid,segend,pivotv,x,xindex)
if (nx.le.3) goto 2000
100 continue
bp=segbeg
ep=segend
C print *,bp,MID,EP,':',
C 1 X(XINDEX(BP)),X(XINDEX(MID)),X(XINDEX(EP))
200 continue
if (x(xindex(bp)).le.pivotv .and.bp.lt.segend) then
bp=bp+1
C print *,'bp ',bp,SEGEND,X(XINDEX(BP))
goto 200
endif
300 continue
if (x(xindex(ep)).ge.pivotv.and.Ep.gt.segbeg) then
ep=ep-1
C PRINT *,' EP ',EP,SEGBEG,X(XINDEX(EP))
goto 300
endif
if (ep.gt.bp) then
call intswap_rsync(xindex(bp),xindex(ep))
bp=bp+1
ep=ep-1
C PRINT *,' BP EP ',BP,EP
goto 200
endif
if (bp.gt.mid) then
if (ep.gt.mid) then
call intswap_rsync(xindex(ep),xindex(mid))
newpivot=ep
else
newpivot=mid
endif
else
call intswap_rsync(xindex(bp),xindex(mid))
newpivot=bp
endif
lenend=segend-newpivot
lenbeg=newpivot-segbeg
if (lenend.gt.lenbeg) then
call pushsort_rsync(newpivot+1,segend,stack,nspt)
segend=newpivot-1
segsize=lenbeg
else
call pushsort_rsync(segbeg,newpivot-1,stack,nspt)
segbeg=newpivot+1
segsize=lenend
endif
call indqsort3_rsync(segbeg,mid,segend,pivotv,x,xindex)
if (segsize.gt.3) goto 100
1000 continue
if (.not.QPopSort_rsync(segbeg,segend,stack,nspt)) then
goto 2000
else
segsize=segend-segbeg+1
call indqsort3_rsync(segbeg,mid,segend,pivotv,x,xindex)
if (segsize.le.3) then
goto 1000
else
goto 100
endif
endif
2000 continue
C print *,' endo quitk'
return
end
c--------
subroutine indqsort3_rsync(segbeg,mid,segend,pivotv,x,xindex)
integer x(1),pivotv
integer segbeg,mid,segend
integer xindex(1)
mid=(segbeg+segend)/2
if (segbeg+1.eq.segend) then
if (x(xindex(segbeg)).gt.x(xindex(segend))) then
call intswap_rsync(xindex(segbeg),xindex(segend))
endif
return
endif
if (x(xindex(segbeg)).gt.x(xindex(mid))) then
if (x(xindex(segbeg)).gt.x(xindex(segend))) then
call intswap_rsync(xindex(segbeg),xindex(segend))
if (x(xindex(segbeg)).gt.x(xindex(mid))) then
call intswap_rsync(xindex(segbeg),xindex(mid))
endif
else
call intswap_rsync(xindex(segbeg),xindex(mid))
endif
else
if (x(xindex(mid)).gt.x(xindex(segend))) then
call intswap_rsync(xindex(mid),xindex(segend))
if (x(xindex(segbeg)).gt.x(xindex(mid))) then
call intswap_rsync(xindex(segbeg),xindex(mid))
endif
else
continue
endif
endif
pivotv=x(xindex(mid))
return
end
subroutine intswap_rsync(ix,iy)
integer it,ix,iy
it=ix
ix=iy
iy=it
return
end
subroutine pushsort_rsync(sb,se,stack,stackct)
integer se,sb,stack(1),stackct
if (stackct+2.gt.5000) then
c print *,'ERROR in QUIKSORT: ARRAY TOO LONG '
stop 0
endif
stackct=stackct+1
stack(stackct)=sb
stackct=stackct+1
stack(stackct)=se
return
end
logical function QPopSort_rsync(sb,se,stack,stkpoint)
integer sb,se,stack(1),stkpoint
if (stkpoint-1.le.0)then
qpopsort_rsync=.false.
return
endif
se=stack(stkpoint)
stkpoint=stkpoint-1
sb=stack(stkpoint)
stkpoint=stkpoint-1
qpopsort_rsync =.true.
return
end
c-----------------------
c using difference file, and old file, recreate "new file" (ungdiff)
integer function do_ungdiff(iunit,dif_file,out_file,iquiet)
character *(*) dif_file,out_file
integer iunit,iquiet
character *1 c1
character *1000 c1000
character *4 c4,c4a
character *2 c2,c2a
character *8 c8
integer i4,iget,nget,c_to_int,write_6,iserror,ierr
include 'fsublib.fi'
integer i36
logical quiet
common /cm36/i36,quiet
c iunit points to the "old file"
c now open the "dif_file"
open(unit=42,file=dif_file,access='sequential',status='old',
1 form='unformatted',recordtype='fixed',iostat=ierr,
1 action='read')
if (ierr.ne.0) then
do_ungdiff=51
return
endif
c is this a real difference file
read(42,iostat=ierr)c1000(1:4),c1
c note: dif_file will be gone through sequentially. 41 (oldfile)
c will be jumped around in
c8='d1ffd1ff'
read(c8,13)c4
13 format(z8)
if (c4.ne.c1000(1:4)) then
do_ungdiff=52
print *,'ERROR not a gdiff formatted difference file'
return
endif
c open output file?
if (i36.ne.6) then
open(unit=i36,file=out_file,recordtype='FIXED',
1 access='sequential',
1 form='unformatted',iostat=ierr,action='WRITE')
if (ierr.ne.0) then
print *,'ERROR Unable to open output file: ',out_file
do_gdiff=49
return
endif
endif
c read codes from difference file, and write info accordingly
do while (1.eq.1) !do forever
read(42,err=1010)c1
itype=ichar(c1)
if (itype.eq.0) then
exit !eof marker
elseif (itype.eq.255) then
do_ungdiff=54
print *, 'ERROR gdiff copy operation too large'
return
elseif (itype.gt.0 .and. itype.lt.247) then ! 1 to 246 chars to write
read(42,err=1010)c1000(1:itype) !(from out_file)
iserror=write_6(c1000(1:itype))
if (iserror.ne.0) goto 1010
elseif (itype.eq.247.or.itype.eq.248) then ! get >255 bytes
if (itype.eq.247) then ! from out_file
read(42,err=1010)c2
i4=c_to_int(c2)
else
read(42,err=1010)c4
i4=c_to_int(c4)
endif
do jj=1,i4,1000
nget=min(1000,1+i4-jj)
read(42,err=1010)c1000(1:nget)
iserror=write_6(c1000(1:nget))
if (iserror.ne.0) goto 1010
enddo
else !copy bytes from oldfile
if (itype.eq.249) then
read(42,err=1010)c2,c1
istart=c_to_int(c2)
iget=ichar(c1)
elseif (itype.eq.250) then
read(42,err=1010)c2,c2a
istart=c_to_int(c2)
iget=c_to_int(c2a)
elseif (itype.eq.251) then
read(42,err=1010)c2,c4
istart=c_to_int(c2)
iget=c_to_int(c4)
elseif (itype.eq.252) then
read(42,err=1010)c4,c1
istart=c_to_int(c4)
iget=ichar(c1)
elseif (itype.eq.253) then
read(42,err=1010)c4,c2
istart=c_to_int(c4)
iget=c_to_int(c2)
elseif (itype.eq.254) then
read(42,err=1010)c4,c4a
istart=c_to_int(c4)
iget=c_to_int(c4a)
else
do_ungdiff=56
return
endif !copy byte codes
II=SEEKUNIT(iunit,istART-1,0)
IF (II.LT.0) goto 1010
do mm=1,iget,1000
nget=min(1000,1+iget-mm)
read(iunit,err=1010)c1000(1:nget)
iserror=write_6(c1000(1:nget))
if (iserror.ne.0) goto 1010
enddo
endif ! bytes code
enddo !scanning diff file
close(unit=iunit,iostat=ierr) !oldfile
close(unit=42,iostat=ierr) !diff
close(unit=36,iostat=ierr) !output
do_ungdiff=0
if (.not.quiet.and.i36.ne.6.and.iquiet.ne.1) then
open(unit=i36,file=out_file,iostat=ierr,
1 action='read',form='unformatted')
if (ierr.ne.0) return
iout=filesize(36)
if (lentrim(out_File).lt.40) then
write(6,51)iout,out_file(1:lentrim(out_file))
51 format('OK ',i9,' bytes written to ',a)
else
write(6,53)iout,out_file(1:lentrim(out_file))
53 format('OK ',i9,' bytes written to '/a)
endif
close(unit=i36,iostat=ierr)
endif
return
1010 do_ungdiff=55 !unspecified io error
return
end
c-------------------
c character to integer
integer function c_to_int(cc)
character *(*)cc
INTEGER JJ
CHARACTER *4 C4
CHARaCTER *8 C8
if (len(cc).eq.1) then
c_to_int=ichar(cc)
return
endif
if (len(cc).eq.2) then
write(c4,99)cc
99 format(z4)
read(c4,99)jj
c_to_int=jj
return
endif
if (len(cc).eq.4) then
write(c8,199)cc
199 format(z8)
read(c8,199)jj
c_to_int=jj
return
endif
print *,'ERROR Overflow in c_to_int '
stop
end