langdon@lll-lcc.UUcp (Bruce Langdon) (02/02/86)
--------------------------------------------------------------------------- Utility CHECK provides a way to find the length of a file (in bytes, and in lines for text files), and sorting out different versions of files (by comparing their CRC's). There are two files, CHECK.ACT and CRC.ACT. CRC shows a progression from a straight Action version, updCRCa, to a machine language version updCRCx of updCRCa, to a straight Action version that uses a table but is fastest. If you compile and write and executable file to be run without recompiling, consider removing the ; from SET $491... so it will not run on top of something else. If you have the run-time libraries SYSLIB and SYSIO, remove the ; from those INCLUDEs to make an executable file that doesn't need the Action cartridge to run. At least with DOS XL, CHECK can be re-run without re-reading it off disk by just typing 'RUN'. This is the purpose of 'Entry'. Other features useful in other programs include: fast disk read error handling fixing up the DOS file name (force upper case, prefix D: if needed) locating the buffer run-time library does not set device=0; do it yourself in case. ---------------------------------------------------------------------- Bruce Langdon L-472 langdon%lll-lcc@lll-crg.ARPA Physics Department "langdon#bruce%d"@lll-mfe.ARPA Lawrence Livermore National Laboratory Livermore, CA 94550 (415) 422-5444 UUCP: ..{gymble,ihnp4,seismo}!lll-crg!lll-lcc!langdon --------------------------------------------------------------------------- ; CHECK 8/17/85-12/21, A. B. Langdon ; Determine length, CRC and checksum of file. ; Also number of lines, for text file. ;SET $491=$4000 SET 14=$491^ BYTE JMP=[$4C]: CARD Entry ;INCLUDE "D:SYSLIB.ACT" ;INCLUDE "D:SYSIO.ACT" ; Using channel 1, Close caused "system error" with DOS 2.1 but not DOS XL. ; ACS bbs has a block read (BLKIO.ACT) in machine code segments that is ; smaller and has a general purpose call to CIO. Here, I'll leave mine ; as it illustrates use of the language and is just as fast. ; First global ARRAY, other than BYTE ARRAY of length less than 257, ; is placed AFTER rest of program (undocumented?). BYTE ARRAY buffer(257) ; locate the buffer. CARD FLen, ; File length up to 64K i, CSum, NLines BYTE OpOK, CSum0=CSum, CSum1=CSum+1, text BYTE CIO_status ; global for CIO return value (per ACS convention) INCLUDE "CRC.ACT" CARD FUNC GetAD(BYTE chan CARD addr, len) ; Block read TYPE IOCB=[BYTE hid,dno,com,sta CARD badr,put,blen BYTE aux1,aux2,aux3,aux4,aux5,aux6] IOCB POINTER ic BYTE chan16 BYTE POINTER b chan16 = (chan&$07) LSH 4 ic = $340+chan16 ic.com = 7 ; read ic.blen = len ic.badr = addr [$AE chan16 $20 $E456 $8C CIO_status] ; LDX chan, JSR CIO; STY CIO_status FLen ==+ ic.blen ; this to RETURN is special to this application. IF CIO_status = $88 THEN EOF(chan)=1 IF (FLen&$FF) = 0 THEN ; likely last sector of b = addr+ic.blen-1 ; a DOS 4 file. WHILE b^ = 0 DO b ==- 1 ic.blen ==- 1 FLen == -1 OD FI FI b = addr FOR i = 1 TO ic.blen DO IF b^ = $9B THEN NLines ==+ 1 FI CSum0 ==+ b^ CSum1 ==+ CSum0 updCRC(b^) b ==+ 1 OD RETURN (ic.blen) CARD FUNC GetCD(BYTE chan) ; Read a word CARD c GetAD(chan,@c,2) RETURN (c) PROC FixFlSp(BYTE ARRAY FileSpec) IF FileSpec(2)<>': AND FileSpec(3)<>': THEN ; prefix "D:" to file name FileSpec^==+2 i=FileSpec^ WHILE i>2 DO FileSpec(i)=FileSpec(i-2) i==-1 OD FileSpec(1)='D FileSpec(2)=': FI ; Could also convert to upper case: if >$60 then subtract $20. RETURN PROC SysErr(BYTE errno) PROC MyError(BYTE errno) IF errno=$80 THEN Error=SysErr Error(errno) FI ; break quits PrintF("error %I. Try again%E",errno) OpOK=0 RETURN PROC End=*() [$68$AA$68$CD$2E8$90$5$CD$2E6$90$F3 $48$8A$48$60] ; entry: PLA; TAX; PLA; CMP MEMLO+1; BCC lab; CMP MEMTOP+1; BCC entry; ; lab: PHA; TXA; PHA; RTS ; Trace back thru RTS's and return to cartridge or DOS. ; From ACS bulletin board. PROC CHECK() CHAR ARRAY FileSpec(20) BYTE b, SHFLOK=$2BE CARD fwa, lwa, BufLen, MEMTOP=$2E5, MEMLO=$2E7 BufLen=MEMTOP-$80-buffer SysErr=Error DO Print("File Spec=") SHFLOK=$40 ; upper case InputS(FileSpec) IF FileSpec^=0 THEN END() FI FixFlSp(FileSpec) Close(2) OpOK=1 Error=MyError Open(2,FileSpec,4,0) UNTIL OpOK OD Error=SysErr FLen=0 CSum=0 CRC=0 text=1 NLines=0 ; With DOS 4, this artifice ensures ; that each GetAD reads one byte into ; next sector, to anticipate EOF. BufLen ==& $FF00 GetAD(2,buffer,1) IF buffer(0) = $FF THEN text=0 FI WHILE EOF(2) = 0 DO GetAD(2,buffer,BufLen) OD updCRC(0) updCRC(0) PrintF("End of file. %H bytes%E",FLen) PrintF(" checksum=%H, CRC=%H%E",CSum,CRC) IF text THEN PrintF("%I lines%E",NLines) FI Close(2) RETURN PROC Main() device=0 ; in case MAC/65 has been here SetupCRC() DO CHECK() PrintE(" (RETURN to end)") OD RETURN SET Entry=Main --------------------------------------------------------------------------- MODULE; CRC.ACT 12/21/85 A. B. Langdon ; Before use, do SetupCRC(). ; For each data set, first set global CRC=0. ; After calling updCRC(data) with all ; data bytes, do updCRC(0) twice. ; If CRCx is the CRC of a byte string, ; then the CRC of that string, followed by ; the hi and lo bytes of CRCx, is zero. CARD CRC: BYTE CRCl=CRC, CRCh=CRC+1 CARD ARRAY CRCtable(256) ;PROC updCRCa(BYTE b) ; Action version ; From C code by D. Krantz, ; Dr. Dobb's Journal, June 1985. ; Takes 99 jiffies for 2000 bytes. ; BYTE i ; CARD flag ; FOR i=0 TO 7 DO ; flag = CRC&$8000 ; CRC ==LSH 1 ; IF b&$80 THEN CRC ==% 1 FI ; IF flag THEN CRC ==XOR $1021 FI ; b ==LSH 1 ; OD ;RETURN PROC updCRC(BYTE b) ; Adaptation to this CRC of the algorithm ; by W.D.Schwaderer, PC Tech Journal, 4/85. ; Takes 14 jiffies for 2000 bytes. CARD tem BYTE teml=tem, temh=tem+1 teml = b temh = CRCl CRC = tem XOR CRCtable(CRCh) RETURN PROC updCRCx=*(BYTE b) ; Machine language for Dr. Dobb's routine. ; Takes 35 jiffies for 2000 bytes. [$85$A0] ; STA $A0 [$A2$8] ; loop over 8 bits [$26$A0] ; 3 byte shift of data [$2E CRC $2E CRC+1] ; and CRC [$90$10 $AD CRC $49$21 $8D CRC] ; if carry, then XOR [$AD CRC+1 $49$10 $8D CRC+1] ; poly bits [$CA $D0$E3] ; loop RETURN PROC SetupCRC() FOR i=0 TO $FF DO ; set up CRC table CRCl=0 CRCh=i updCRCx(0) CRCtable(i)=CRC OD ; <0.1 sec. RETURN MODULE; end CRC ---------------------------------------------------------------------------