home *** CD-ROM | disk | FTP | other *** search
- /* UpDateCopy.e
- ** Copies multiple files/directories to one destination.
- ** Not existing directories are created.
- ** Already existing files are only replaced by newer ones
- ** (UpDateCopy first checks for versions-string and then
- ** for dates).
- **
- ** $VER: UpDateCopy.e 0.52 (21.02.97)
- **
- ** This program is Cardware. If you use it you should send an Email to
- ** the author. Also small presents are very welcome.
- ** You may use this sourcefile or parts of it freely in your programs.
- ** But please do not spread a modified version under this name (UpDateCopy).
- ** For Bugreports, ideas or anything else send a Email to:
- ** ss37@irz.inf.tu-dresden.de
- **
- ** Sven Steiniger, 1996, 1997
- **
- ** Fold-start: ->// ""
- ** Fold-stop: ->\\
- **
- ** History:
- ** 0.52: - improved SMARTINFO-option
- ** 0.51: - removed bug of version-scan-routines
- ** 0.50: - added FAST-option
- ** 0.49: - added SMARTINFO option
- ** - added wildcard-check. Now you can also use '*' as wildcard and
- ** you can also pass devices as sources (eq. ram:)
- ** 0.48: - used exthelp-feature OF ReadArgs()
- ** - no longer needs 'c:copy'-command. Implemented an own routine.
- ** 0.47: - file was not closed before SetProtection()/SetFileDate()
- ** 0.46: - added PAPF-option -> archive protection flag is not changed
- ** 0.45: - added CLONE-option -> Datestamp is copied
- ** 0.44: - removed a unnecessary module. Saves 1K of executable size!
- ** - removed unnecessary ExamineFH()
- ** - now file gets only examined if really necessary
- ** - optimized a bit
- ** - FIXED: TESTMODE was buggy -> Directories were still created.
- ** 0.43: - add new option TESTMODE; dont copy/replace files
- ** 0.42: - add new option NODATECHECK; dont compare datestamps
- ** 0.41: - replaced ALL reads/writes by fread/fwrite
- ** 0.40: - first PUBLIC release
- */
-
- OPT OSVERSION=37
- OPT REG=5
-
- MODULE 'dos/dos','dos/dosasl','dos/dostags','dos/rdargs'
-
- RAISE "MEM" IF String()=NIL,
- "addp" IF AddPart()=DOSFALSE,
- "^C" IF CtrlC()=TRUE,
- "copy" IF FileLength()=-1,
- "MEM" IF AllocDosObject()=NIL,
- "fatt" IF SetProtection()=DOSFALSE,
- "fatt" IF SetComment()=DOSFALSE,
- "fatt" IF SetFileDate()=DOSFALSE
-
- CONST MAXPATH=255, -> Maximum path length
- SPACEADD=3, -> Number of spaces per indent
- SAFETYBYTES=100, -> Maximum length of versionstring
- BIGFILEMEM=100000 -> Files bigger than that are not read
- -> completly into memory
-
- CONST PATHLENGTH=MAXPATH-1,
- BIGFILESIZE=BIGFILEMEM-SAFETYBYTES
-
-
- ENUM PDIR_Error,
- PDIR_Skipped,
- PDIR_Created
-
- ENUM PFILE_Error,
- PFILE_Skipped,
- PFILE_Copied,
- PFILE_Replaced
-
- DEF frompath[MAXPATH]:STRING, -> actual sourcepath
- fromlist:PTR TO LONG, -> pointer to array of sourcestrings
- topath[MAXPATH]:STRING, -> destinationpath
- doinfo, -> should we write informations ?
- recursiv, -> scan recursively through subdirectories ?
- ignoreprotection, -> clear delete-protection ?
- checkversion, -> compare version-strings ?
- checkdates, -> compare datestamps ?
- testmode, -> test modus ? (do not copy/replace files)
- clone, -> copy datestamp ?
- cleararchivebit, -> clear archivebit OF copied file
- smartinfo, -> only display copied/replaced files
- fastdisplay, -> no linefeed
- dirlock=NIL -> PTR TO lock-structure OF destination path
-
- PROC main() HANDLE
- ->// "main()"
- DEF rdargs=NIL,
- myargs:PTR TO LONG,
- template,
- myrdargs=NIL:PTR TO rdargs,
- exthelp[1000]:STRING
-
- /* Initialize argument-array */
- myargs:=[
- NIL, -> fromlist
- NIL, -> destination path
- FALSE, -> ~showinfo
- FALSE, -> scan recursiv throuhg subdirectories
- FALSE, -> ignore protectionbits
- FALSE, -> deep scan
- FALSE, -> ~compare datestamps
- FALSE, -> testmode
- FALSE, -> clone
- FALSE, -> preserve archive protection flag
- FALSE, -> smartinfo
- FALSE -> fastdisplay
- ]:LONG
-
- myrdargs:=AllocDosObject(DOS_RDARGS,NIL)
-
- StrCopy(exthelp, '\n'+
- ' UpDateCopy v0.52\n'+
- ' -----------------\n'+
- ' Copy files and directories.\n'+
- ' Not existing directories are created and\n'+
- ' already existing files are only replaced\n'+
- ' by newer ones. Allows pattern-matching and\n'+
- ' multiple sourcedirectories/files.\n\n'+
- 'Sven Steiniger, 1996, 1997\n',
- ALL)
- StrAdd(exthelp, '\n'+
- ' FROM - source directory/file(s)\n'+
- ' TO - destination directory\n'+
- ' QUIET - no outputs\n'+
- ' ALL - scans through subdirectories recursively\n'+
- ' FORCE - ignore delete-protectionbit\n'+
- ' DEEP - compare version-strings\n'+
- ' NODATECHECK - don''t compare datestamps\n'+
- ' TESTMODE - neither copy/replace files nor create directories\n'+
- ' CLONE - copy datestamp\n'+
- ' PAPF - don''t clear the archive protection flag\n'+
- ' SMARTINFO - only displays copied/replaced files\n'+
- ' FAST - fast output. No linefeeds\n',
- ALL)
- myrdargs.exthelp:=exthelp
-
- /* Parse Commandline */
- IF rdargs:=ReadArgs(template:='FROM/M,TO/A,QUIET/S,ALL/S,FORCE/S,DEEP/S,'+
- 'NDC=NODATECHECK/S,TESTMODE/S,CLONE/S,PAPF/S,'+
- 'SMARTINFO/S,FAST/S',
- myargs,myrdargs)
-
- /* Copy Datas to global variables */
- fromlist := myargs[0]
- StrCopy(topath,myargs[1],ALL)
- doinfo := Not(myargs[2])
- recursiv := myargs[3]
- ignoreprotection := myargs[4]
- checkversion := myargs[5]
- checkdates := Not(myargs[6])
- testmode := myargs[7]
- clone := myargs[8]
- cleararchivebit := Not(myargs[9])
- smartinfo := myargs[10]
- fastdisplay := myargs[11]
-
- IF fromlist=NIL THEN Throw("ARGS",'No source specified.')
- init_arguments()
-
- IF doinfo
- PrintF('Updating files to "\s".\n',topath)
- IF testmode THEN PrintF('** Testmode **\n')
- ENDIF
-
- IF fastdisplay
- PrintF('\n')
- smartinfo:=FALSE
- ENDIF
-
- WHILE fromlist[] -> 'fromlist' is array of string-pointers
- StrCopy(frompath,fromlist[]++,ALL) -> copy the string and increment 'fromlist'
- checkWildCard(frompath)
- scan_directory(frompath,'',1) -> then process this directory
- ENDWHILE
-
- ENDIF
-
- EXCEPT DO -> Cleanup
-
- IF fastdisplay THEN reportLine(0,'',NIL,NIL)
-
- free_arguments()
- IF rdargs THEN FreeArgs(rdargs)
- FreeDosObject(DOS_RDARGS,myrdargs)
-
- IF exception
- /* Print error description */
- PrintF('Error: ')
- SELECT exception
- CASE "MEM" ; PrintF('Not enough memory.\n')
- CASE "addp" ; PrintF('Path too long !?\n')
- CASE "^C" ; PrintF('User abort.\n')
- CASE "copy" ; PrintF('Could not copy file.\n')
- CASE "open" ; PrintF('Could not open file.\n')
- CASE "anly" ; PrintF('Could not analyse file.\n')
- CASE "fatt" ; PrintF('Could not set file attributes.\n')
- DEFAULT ; PrintF('\s\n',exceptioninfo)
- ENDSELECT
- ELSE
- PrintF('Finished.\n')
- ENDIF
-
- CleanUp(exception)
-
- ENDPROC
- ->\\
-
- versionstring: CHAR '$VER: UpDateCopy 0.52 (21.02.97)',0
-
-
- /* checks the arguments provied by user
- */
- PROC init_arguments()
- ->// "init_arguments()"
-
- IF (dirlock:=Lock(topath,SHARED_LOCK))=NIL -> check if destination
- Throw("dir",'Could not lock destination directory') -> directory exists
- ENDIF
- /* Enable Version Check if datestamp-check is switch off */
- IF checkdates=FALSE THEN checkversion:=TRUE
-
- ENDPROC
- ->\\
-
- /* handles so special cases with wildcards
- ** Parameter:
- ** file - file/dir to be checked
- */
- PROC checkWildCard(file:PTR TO CHAR)
- ->// "checkWildCard"
- DEF len
-
- len:=StrLen(file)
- IF file[len-1]="*"
- -> replace '*'-wildcard by '#?'
- CopyMem('#?',file+len-1,3)
- ELSEIF file[len-1]=":"
- -> it's an device. Therefore add wildcard
- CopyMem('#?',file+len,3)
- ENDIF
-
- ENDPROC
- ->\\
-
- /* Cleanup datas allocated during init_arguments
- */
- PROC free_arguments()
- ->// "free_arguments()"
- UnLock(dirlock) -> Unlock destination directory
- ENDPROC
- ->\\
-
-
- /* Scans a directory and copies files/creates subdirectories
- ** Parameter:
- ** directory - name of directory to be scanned
- ** path - the current delta path
- ** depth - recursion level
- ** Example:
- ** The source path is "esource:src".
- ** 'directory' is "esource:src/tools/file".
- ** Then 'path' have to be "tools/file".
- */
- PROC scan_directory(directory,path,depth) HANDLE
- ->// "scan_directory()"
- DEF info:PTR TO fileinfoblock,
- anchor=NIL:PTR TO anchorpath,
- error,
- fullpath,
- mypath[MAXPATH]:STRING,
- length
-
- /* Create and initialize anchor structure needed for
- ** scanning through directory.
- ** This structure has no fixed size.
- */
- anchor:=NewR(SIZEOF anchorpath+MAXPATH)
- anchor.strlen:=PATHLENGTH
-
- -> Get start of string
- fullpath:=anchor+SIZEOF anchorpath
-
- error:=MatchFirst(directory,anchor)
- WHILE error=DOSFALSE
-
- CtrlC()
-
- info:=anchor.info -> get fileinfoblock
- IF info.direntrytype>0 -> is it a directory ?
-
- StrCopy(mypath,path,ALL) -> init new delta path
- AddPart(mypath,info.filename,PATHLENGTH) -> including new subdirectory
-
- process_directory(fullpath,info,mypath, -> knows what to do with this
- depth*SPACEADD) -> directory
-
- IF recursiv -> scan subdirectories ?
- length:=StrLen(fullpath)
- IF (length+5)<MAXPATH
- CopyMem('/#?',fullpath+length,4) -> add pattern matching
- ENDIF
- scan_directory(fullpath,mypath,depth+1) -> call our self with new subdirectory
- fullpath[length]:=0 -> remove pattern matching
- ENDIF
-
- ELSE
-
- process_file(fullpath,info,path, -> knows what to do with it
- depth*SPACEADD)
-
- ENDIF
-
- error:=MatchNext(anchor) -> Next entry
- ENDWHILE
-
- EXCEPT DO
-
- IF anchor
- MatchEnd(anchor) -> Clean up
- Dispose(anchor)
- ENDIF
-
- ReThrow()
-
- ENDPROC
- ->\\
-
-
- /* takes care of fastdisplay-option
- */
- PROC reportLine(spaceanz,fmtstr,arg1,arg2)
-
- IF fastdisplay
- PrintF([141,$1b,"[","M",0]:CHAR)
- spaceanz:=SPACEADD
- ENDIF
- WHILE spaceanz-->=0 DO FputC(stdout," ")
- PrintF(fmtstr,arg1,arg2) -> Write directory name & status
- PrintF('\n')
-
- ENDPROC
-
- /* Prints a directory status.
- ** Parameter:
- ** spaces - number of leading spaces
- ** status - status (PDIR_Error, PDIR_Skipped, PDIR_Created)
- ** path - directory path
- */
- PROC printDirStatus(spaces,status,path)
- ->// "printDirStatus()"
- DEF stri
-
- IF doinfo
- SELECT status
- CASE PDIR_Created ; stri:='created'
- CASE PDIR_Skipped ; IF smartinfo THEN RETURN -> don't display skipped dirs with smartinfo
- stri:='skipped'
- DEFAULT ; stri:='Error!!'
- ENDSELECT
- reportLine(spaces,'\e[1m\s\e[0m..\s',path,stri) -> Write directory name & status
- ENDIF
-
- ENDPROC
- ->\\
-
- /* Process an directory. If it doesnt exists it will be created
- ** Parameter:
- ** directory - full path of source directory
- ** info - pointer to fileinfoblock of source directory
- ** path - delta path of directory
- */
- PROC process_directory(directory,info:PTR TO fileinfoblock,path,spaces)
- ->// "process_directory()"
- DEF stri[MAXPATH]:STRING,
- lock
-
- StrCopy(stri,topath,ALL)
- AddPart(stri,path,PATHLENGTH) -> thats the destion-directory
-
- IF lock:=Lock(stri,SHARED_LOCK) -> Exists this Directory ?
- printDirStatus(spaces, PDIR_Skipped, path)
- UnLock(lock) -> Unlock directory
-
- ELSEIF testmode -> Don't create directory in testmode
- printDirStatus(spaces, PDIR_Created, path) -> but write out a info
-
- ELSEIF lock:=CreateDir(stri) -> Create the directory
- printDirStatus(spaces, PDIR_Created, path)
- UnLock(lock) -> No erros, unlock directory
- copyAdditionalInformations(stri,info)
-
- ELSE -> Directory could not be created
- printDirStatus(spaces, PDIR_Error, path) -> as it does not exists before
- Throw("dir",'Could not create directory') -> something went wrong
- ENDIF
-
- ENDPROC
- ->\\
-
-
-
- /* Prints a file status.
- ** Parameter:
- ** spaces - number of leading spaces
- ** status - status (PFILE_Error, PFILE_Skipped, PFILE_Created, PFILE_Skipped)
- ** file - filename
- */
- PROC printFileStatus(spaces,status,file)
- ->// "printFileStatus()"
- DEF stri
-
- IF doinfo
- SELECT status
- CASE PFILE_Copied ; stri:='copied'
- CASE PFILE_Replaced ; stri:='replaced'
- CASE PFILE_Skipped ; IF smartinfo THEN RETURN -> don't display skipped dirs with smartinfo
- stri:='skipped'
- DEFAULT ; stri:='Error!!'
- ENDSELECT
- reportLine(spaces,'\s..\s',file,stri) -> Write file status
- ENDIF
-
- ENDPROC
- ->\\
-
- /* Processes an file. If it does not exists or is newer it is copied.
- ** Parameter:
- ** file - full source filename (include path)
- ** info - ptr to fileinfoblock of sourcefile
- ** path - deltapath to directory (exclude filename !)
- */
- PROC process_file(file,info:PTR TO fileinfoblock,path,spaces) HANDLE
- ->// "process_file()"
- DEF stri[MAXPATH]:STRING,
- filepath[MAXPATH]:STRING,
- fh=NIL,
- toinfo=NIL:PTR TO fileinfoblock,
- result=0,
- frombuf=NIL
-
- StrCopy(filepath,path,ALL) -> create deltapath
- AddPart(filepath,info.filename,PATHLENGTH) -> inclusive filename
-
- StrCopy(stri,topath,ALL) -> create full destination
- AddPart(stri,filepath,PATHLENGTH) -> filepath
-
- IF fh:=Open(stri,MODE_OLDFILE) -> Open destinationfile
-
- IF checkversion THEN result,frombuf:=compareversion(file,stri)
-
- IF checkdates AND (result=0)
- /* Fileinfoblock have to be LONGWORD-aligned therefore
- ** use dos.library to create this
- */
- toinfo:=AllocDosObject(DOS_FIB,NIL)
-
- -> fill fileinfoblock
- IF ExamineFH(fh,toinfo)=DOSFALSE THEN Throw("file",'Could not examine file ?!')
-
- /* Compare versionstrings was either not specified by user
- ** or was not successfull. Therefore Compare filedates if
- ** the user want it.
- */
- result:=CompareDates(toinfo.datestamp,info.datestamp)
- ENDIF
- IF result>0 -> fromfile newer than tofile ?
- Close(fh) ; fh:=NIL -> close destination
-
- IF ignoreprotection THEN SetProtection(stri,0) -> Clear protectionflags
- -> if specified
- copyfile(file,info,stri,frombuf) -> copy the file
- printFileStatus(spaces, PFILE_Replaced, filepath)
- ELSE
- printFileStatus(spaces, PFILE_Skipped, filepath)
- ENDIF
- ELSE -> destination does not exists
- copyfile(file,info,stri) -> copy file
- printFileStatus(spaces, PFILE_Copied, filepath)
- ENDIF
-
- EXCEPT DO -> Cleanup
-
- /* compareversion() may return the contents of the
- ** sourcefile. We must free this buffer
- */
- IF frombuf THEN Dispose(frombuf)
-
- IF toinfo THEN FreeDosObject(DOS_FIB,toinfo)
- IF fh THEN Close(fh)
-
- IF exception THEN printFileStatus(spaces, PFILE_Error, filepath)
- ReThrow()
-
- ENDPROC
- ->\\
-
-
- /* Copies a file. For files >BIGFILESIZE Bytes c:copy is
- ** used.
- ** Parameter:
- ** fromfile - full path of sourcefile
- ** tofile - full path of destinationfile
- ** frombuf - Contents of sourcefile. If NIL then sourcefile
- ** is read
- */
- PROC copyfile(fromfile,frominfo:PTR TO fileinfoblock,tofile,frombuf=NIL) HANDLE
- ->// "copyfile()"
- DEF fhfrom=NIL,
- fhto=NIL,
- length,
- buf=NIL,
- steplength,actlength
-
- IF testmode THEN RETURN
-
- IF (fhfrom:=Open(fromfile,OLDFILE)) AND -> open sourcefile
- (fhto:=Open(tofile,NEWFILE)) -> open destinationfile
-
- IF (length:=FileLength(fromfile))>BIGFILESIZE
- /* Files >BIGFILESIZE are not read completly into memory but in parts
- ** of BIGFILESIZE Bytes.
- */
-
- /* Alloc new buffer */
- buf:=NewR(BIGFILESIZE)
-
- /* steplength is the length of the current block to be read */
- /* actlength is the position within the file */
- steplength:=actlength:=BIGFILESIZE
-
- REPEAT
- /* Read next block to buffer. If steplength<0 then EOF is reached */
- IF steplength>0
- IF Fread(fhfrom,buf,steplength,1)<1 THEN Raise("copy")
- ENDIF
-
- /* Write buffer to destinationfile */
- IF Fwrite(fhto,buf,steplength,1)<1 THEN Raise("copy")
-
- IF (actlength:=actlength+BIGFILESIZE)>length
- steplength:=length-(actlength-BIGFILESIZE)
- ENDIF
-
- /* Read until version-string was found or EOF */
- UNTIL steplength<=0
-
- ELSE
-
- IF frombuf -> we already know the
- -> contents of the sourcefile
- /* Write buffer to destinationfile */
- IF Fwrite(fhto,frombuf,length,1)<1 THEN Raise("copy")
- ELSE
- buf:=NewR(length) -> alloc new buffer
-
- /* Read sourcefile into buffer */
- IF Fread(fhfrom,buf,length,1)<1 THEN Raise("copy")
- /* Write buffer TO destinationfile */
- IF Fwrite(fhto,buf,length,1)<1 THEN Raise("copy")
- ENDIF
-
- ENDIF
- ELSE -> There went something wrong
- Raise("copy")
- ENDIF
-
- EXCEPT DO
-
- IF buf THEN Dispose(buf)
- IF fhfrom THEN Close(fhfrom)
- IF fhto THEN Close(fhto)
-
- ReThrow()
-
- /* Everything went ok. Copy comment, protection flags etc. */
- copyAdditionalInformations(tofile,frominfo)
-
- ENDPROC
- ->\\
-
- /* Copies extra informations like protectionbits, comment etc.
- ** 'name' must be a valid File- or Directory path
- ** 'info' is the fileinfoblock of the original file/directories
- ** (the dates are copied from it)
- **
- ** Note: the file may not be opened or locked!
- */
- PROC copyAdditionalInformations(name,info:PTR TO fileinfoblock)
- ->// "copyAdditionalInformations()"
-
- DEF protection
-
- /* Clear protectionbit (or not) */
- protection:=info.protection
- IF cleararchivebit THEN protection:=protection AND Not(FIBF_ARCHIVE)
-
- SetProtection(name,protection) -> Copy protection bits
- SetComment(name,info.comment) -> Copy comment
-
- /* Copy datestamp if clone option is activated */
- IF clone THEN SetFileDate(name,info.datestamp)
-
- ENDPROC
- ->\\
-
-
- /* Compares the version-strings of two files
- ** Parameter:
- ** fromfile - full path of sourcefile
- ** tofile - full path of destinationfile
- **
- ** Returns
- ** -1 if tofile-version>fromfile-version
- ** 0 if =
- ** 1 if <
- ** *AND* the contents of the sourcefile or NIL
- */
- PROC compareversion(fromfile,tofile) HANDLE
- ->// "compareversion()"
- DEF buffer=NIL:PTR TO CHAR,
- version1,base1,
- version2,base2
-
- version2,base2,buffer:=getVersionOfFile(tofile)
- /* We dont need the destination contents. Therefore delete buffer
- */
- IF buffer
- Dispose(buffer)
- buffer:=NIL
- ENDIF
- /* if version is -1 then no version-string was found */
- IF version2=-1 THEN RETURN 0,NIL
-
- version1,base1,buffer:=getVersionOfFile(fromfile)
- IF version1=-1 THEN RETURN 0,buffer
-
- /* Compare the version, reversion of source/destionation
- ** multiply with other base to get same number of signifant numbers
- */
- RETURN IF (version2*base1)>=(version1*base2) THEN -1 ELSE 1,buffer
-
- EXCEPT -> Cleanup
-
- IF buffer THEN Dispose(buffer)
- ReThrow()
-
- ENDPROC
- ->\\
-
-
- /* Gets the version-number of a file
- ** Parameter:
- ** filename - full path of file
- ** Returns the version, base and a buffer with the contents of the file
- ** (description for version,base see getversion())
- ** buffer may be NIL if file was to large
- */
- PROC getVersionOfFile(filename) HANDLE
- ->// "getVersionOfFile()"
- DEF fh=NIL,
- buffer=NIL:PTR TO CHAR,
- version,base,
- steplength,filelength,actlength
-
- IF fh:=Open(filename,OLDFILE)
-
- filelength:=FileLength(filename)
- IF filelength>BIGFILEMEM
- /* Files >BIGFILESIZE are not read completly into memory but in parts
- ** of BIGFILESIZE Bytes.
- ** As we may skip a versionstring the last SAFETYBYTES are copied
- ** to start of new BIGFILESIZE block everytime.
- */
-
- /* Alloc new buffer and read filecontents into it */
- buffer:=NewR(BIGFILEMEM)
- IF Fread(fh,buffer,BIGFILEMEM,1)<1 THEN Raise("anly")
-
- /* steplength is the length of the current block to be read */
- steplength:=BIGFILESIZE
- /* actlength is the position within the file */
- actlength:=BIGFILEMEM
-
- REPEAT
-
- /* Get version. If version=-1 then read next block */
- version,base:=getversion(buffer,steplength+SAFETYBYTES)
- IF version=-1
-
- /* The version-string was maybe at the end of buffer
- ** and therfore skipped. Copy the last SAFETYBYTES bytes
- ** to start of buffer to not lose the version-string.
- */
- CopyMem(buffer+steplength,buffer,SAFETYBYTES)
-
- /* Increase actlength. If actlength is greater than filelength
- ** then set steplength to the number of bytes left.
- */
- actlength:=actlength+BIGFILESIZE
- IF actlength>filelength
- steplength:=filelength-(actlength-BIGFILESIZE)
- ENDIF
-
- /* Read next block to buffer. If steplength<0 then EOF is reached */
- IF steplength>0
- IF Fread(fh,buffer+SAFETYBYTES,steplength,1)<1 THEN Raise("anly")
- ENDIF
-
- ENDIF
-
- /* Read until version-string was found or EOF */
- UNTIL (version<>-1) OR (steplength<=0)
-
- Dispose(buffer)
- buffer:=NIL
-
- ELSE
- /* We have got a small file. Load it completly into memory.
- ** Alloc new buffer and read filecontents into it
- */
- buffer:=NewR(filelength)
- IF Fread(fh,buffer,filelength,1)<1 THEN Raise("anly")
-
- /* get versions and reversion of sourcefile */
- version,base:=getversion(buffer,filelength)
- ENDIF
-
- /* We dont need the filehandle any longer */
- Close(fh)
- fh:=NIL
-
- ELSE
- Raise("open")
- ENDIF
-
- EXCEPT
- IF fh THEN Close(fh)
- IF buffer THEN Dispose(buffer)
- ReThrow()
-
- ENDPROC version,base,buffer
- ->\\
-
-
- /* Search for a version-string in a file
- ** Parameter:
- ** buffer - Contents of file
- ** bufferlength - length of buffer in bytes
- ** Returns version,base
- ** if no version-string was found then -1 is returned as version
- ** Example: version=81259, base=10000 means
- ** Versionnumber is 81259/10000=8.1259
- */
- PROC getversion(buffer:PTR TO CHAR,bufferlength)
- ->// "getversion()"
- DEF version=-1:REG,base:REG
-
- MOVEA.L buffer,A0 -> A0..buffer
- MOVE.L bufferlength,D0 -> D0..bufferlength
- SUBQ.L #1,D0
- MOVE.B #"$",D1
- MOVE.L #"VER:",D2
- gv_search_loop:
- SUBQ.L #1,D0
- BLT.W gv_ende -> bufferend reached ?
- CMP.B (A0)+,D1
- BNE.S gv_search_loop -> Found a "$" ?
- CMP.L (A0),D2 -> Yes, then next characters="VER:"
- BNE.S gv_search_loop
-
- SUBQ.L #4,D0 -> We have found a version-string
- BLT.S gv_ende
- ADDQ.L #4,A0 -> skip "VER:"
-
- MOVE.B #" ",D1
- gv_skipspaces1: -> skip all spaces before programname
- SUBQ.L #1,D0
- BLT.S gv_ende -> bufferend reached ?
- CMP.B (A0)+,D1
- BEQ.S gv_skipspaces1
- ADDQ.L #1,D0 -> all spaces skipped; we have gone
- SUBQ.L #1,A0 -> one step too far.
-
- gv_skipname: -> skip programname
- SUBQ.L #1,D0
- BLT.S gv_ende -> bufferend reached ?
- CMP.B (A0)+,D1
- BNE.S gv_skipname
- ADDQ.L #1,D0 -> go one step back
- SUBQ.L #1,A0
-
- gv_skipspaces2: -> skip spaces before version-number
- SUBQ.L #1,D0
- BLT.S gv_ende -> bufferend reached ?
- CMP.B (A0)+,D1
- BEQ.S gv_skipspaces2
- ADDQ.L #1,D0 -> go one step back
- SUBQ.L #1,A0
-
- MOVEQ #0,version
- MOVE.B #".",D1
- MOVEQ #0,D2
- gv_getversion1: -> get version until we found a "."
- SUBQ.L #1,D0
- BLT.S gv_ende -> bufferend reached ?
- MOVE.B (A0)+,D2
- SUBI.L #"0",D2 -> Transform character "0".."9" into number
- MULU.W #10,version -> version:=version*10
- ADD.L D2,version -> +number
- CMP.B (A0),D1
- BNE.S gv_getversion1
- SUBQ.L #1,D0 -> skip "."
- ADDQ.L #1,A0
-
- MOVE.B #" ",D1
- MOVEQ #1,base
- gv_getversion2: -> get reversion
- SUBQ.L #1,D0
- BLT.S gv_ende -> bufferend reached ?
- MOVE.B (A0)+,D2
- SUBI.L #"0",D2 -> Transform character "0".."9" into number
- MULU.W #10,version -> version:=version*10
- MULU.W #10,base -> base:=base*10
- ADD.L D2,version -> +number
- CMP.B (A0),D1
- BNE.S gv_getversion2
-
- gv_ende:
-
- ENDPROC version,base
- ->\\
-
-