allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (01/30/89)
Posting-number: Volume 6, Issue 25 Submitted-by: naz@hslrswi.UUCP (Norman H. Azadian) Archive-name: chksum #--------------------------------CUT HERE------------------------------------- #! /bin/sh # # This is a shell archive. Save this into a file, edit it # and delete all lines above this comment. Then give this # file to sh by executing the command "sh file". The files # will be extracted into the current directory owned by # you with default permissions. # # The files contained herein are: # # -rw-r--r-- 1 naz 1991 Jan 25 15:14 readme # -rw-r--r-- 1 naz 536 Jan 25 15:05 makefile # -rw-r--r-- 1 naz 436 Jan 25 14:53 debug.h # -rw-r--r-- 1 naz 2837 Jan 25 14:41 gen.h # -rw-r--r-- 1 naz 8136 Jan 25 14:41 chksum.c # -rw-r--r-- 1 naz 11016 Jan 25 15:14 crc32.c # echo 'x - readme' if test -f readme; then echo 'shar: not overwriting readme'; else sed 's/^X//' << '________This_Is_The_END________' > readme X XChksum is a little program that I've developed and used a lot over the Xyears. The prime difference between it and the ones that it copies, is Xthat it can read a list of pathnames from stdin. This turns out to be Xvery handy indeed. Also, it uses a 32-bit CRC, which means that a false Xmatch is 2**16 times less likely than with the 16-bit brands. It Xproduces identical results on both PCs and VAXen. X XThe 32-bit CRC routine was donated by kind souls on the net. I have Xtweaked it for my use, principally by adding inline optimized assembly Xcode for my PC. I don't pretend to know what is going on inside, and I Xregard it as a minor miracle that it actually produces the same numbers Xon PCs as on VAXen. Perhaps somebody will tell me if it produces the X"right" numbers. X XI've developed it on an Aztec C compiler, currently version 4.10a. You Xshouldn't have much trouble porting it to your favorite compiler. I Xhave found that on the VAX I had to comment-out the #asm stuff in Xcrc32.c, in spite of the fact that it is already conditionally compiled Xout. I have stubbed-out my debugging stuff, so the printd()'s and Xinitdebug() won't produce any code. X XIf you don't have string.h, then you probably don't have the string Xlibrary either. No sweat, all you need do is delete the include for Xstring.h, and add the following routine to chksum.c: X X local void strcpy(dst, src) X char *dst, *src; X { X while ((*dst++ = *src++) != '\0') X continue; X } X XYou'll need to remove the reference to the library in the makefile too. XIf all else fails, the DOS executable is now available at fine Xcomp.binaries.pc newsgroups everywhere. X XI hereby donate this program to the Public Domain for any and all Xpurposes. Enjoy. X XHere is the output of "chksum -v *.h *.c makefile": X X26b5c1c7 436 debug.h X02180ae4 2837 gen.h X872b0f18 8136 chksum.c X6d239b68 11016 crc32.c X44bdd9f4 536 makefile X==================== X86c94990 22961 Grand Totals for 5 files ________This_Is_The_END________ if test `wc -c < readme` -ne 1991; then echo 'shar: readme was damaged during transit (should have been 1991 bytes)' fi fi ; : end of overwriting check echo 'x - makefile' if test -f makefile; then echo 'shar: not overwriting makefile'; else sed 's/^X//' << '________This_Is_The_END________' > makefile X# /usr/bin/src 870407 NHA X X#this is for 4.3bsd XCOPT= -O XCFLAGS= -I. -c XLNFLAGS= -o chksum XCC= /bin/cc XLN= /bin/cc X X#this is for the Aztec version 4.10a under DOS X#AOPT= -186 X#COPT= +a +2 X#AFLAGS= -DMODEL=3 $(AOPT) X#CFLAGS= -I. -ansi -c +l +b $(COPT) X#LNFLAGS= -t -g X#LIBS= -lstringl -lcl X#CC= /manx/cc.exe X#LN= ln X#RM= del X X.c.o: X ${CC} ${CFLAGS} $< X X.c.asm: X ${CC} -at ${CFLAGS} $< X X Xchksum.exe: chksum.o crc32.o X $(LN) $(LNFLAGS) chksum.o crc32.o $(LIBS) X Xclean: X -rm *.o X -rm *.sym X -rm *.dbg X -rm chksum.exe ________This_Is_The_END________ if test `wc -c < makefile` -ne 536; then echo 'shar: makefile was damaged during transit (should have been 536 bytes)' fi fi ; : end of overwriting check echo 'x - debug.h' if test -f debug.h; then echo 'shar: not overwriting debug.h'; else sed 's/^X//' << '________This_Is_The_END________' > debug.h X/* /usr/include/stub/debug.h 890123 NHA */ X/* This is the version for use with public sharing of my sources */ X/* The intent is to neutralize initdebug() and printd() so that */ X/* any compiler will swallow them without complaint */ X/* You may have to tweak this for yours */ X X#ifndef __DEBUG__ X#define __DEBUG__ X X/** #define printd + **/ X#define printd X#define initdebug(acptr,avptr,confile,lstfile,initstring) X X#endif __DEBUG__ ________This_Is_The_END________ if test `wc -c < debug.h` -ne 436; then echo 'shar: debug.h was damaged during transit (should have been 436 bytes)' fi fi ; : end of overwriting check echo 'x - gen.h' if test -f gen.h; then echo 'shar: not overwriting gen.h'; else sed 's/^X//' << '________This_Is_The_END________' > gen.h X/* /usr/include/stub/gen.h 890123 NHA */ X/* This is the version for use with public sharing of my sources */ X/* The intent is to neutralize initdebug() and printd() so that */ X/* any compiler will swallow them without complaint */ X X#ifndef __GEN__ X#define __GEN__ X X#include <stdio.h> X#include <fcntl.h> X#include <ctype.h> X/** #include "config.h" **/ X#include <debug.h> X X#define import extern X#define local static X#define export X/** This will not work with prototypes in version 4.10a **/ X/** typedef char bool; **/ Xtypedef int bool; X#define NULLFP ((int (*)())0) /* NULL Function Pointer */ X X#define YES 1 X#define NO 0 X#define NOBREAK /* used for a switch case which flows into next */ X#define CRLF 037 /* Unit Separator sometimes replaces \n\r pair */ X X/*** NOTE that this include must follow the definition of bool ***/ X/** #include <window.h> **/ /* Norman's direct windows */ X/** import WINDOW *wopen(char *dev); **/ X X/* macros */ X#define abs(x) ((x < 0) ? (-(x)) : (x)) X#define max(x,y) (((x) < (y)) ? (y) : (x)) X#define min(x,y) (((x) < (y)) ? (x) : (y)) X X X/* for use with Aztec farcall(), sysint(), and segreg() functions */ Xstruct regs { int ax, bx, cx, dx, si, di, ds, es; }; Xstruct segregs { unsigned cs, ss, ds, es; }; X X/* use this to fiddle with longs and pointers and such */ Xunion u_long { X unsigned long lunsigned; X long lsigned; X void *ptr; X struct { X unsigned lo; X unsigned hi; X } half; X struct { X unsigned char b0; /* Least Significant byte */ X unsigned char b1; X unsigned char b2; X unsigned char b3; /* Most Significant byte */ X } byte; X }; X X X#define BIT0 0x0001 X#define BIT1 0x0002 X#define BIT2 0x0004 X#define BIT3 0x0008 X#define BIT4 0x0010 X#define BIT5 0x0020 X#define BIT6 0x0040 X#define BIT7 0x0080 X#define BIT8 0x0100 X#define BIT9 0x0200 X#define BIT10 0x0400 X#define BIT11 0x0800 X#define BIT12 0x1000 X#define BIT13 0x2000 X#define BIT14 0x4000 X#define BIT15 0x8000 X X#define BIT0L 0x00000001 X#define BIT1L 0x00000002 X#define BIT2L 0x00000004 X#define BIT3L 0x00000008 X#define BIT4L 0x00000010 X#define BIT5L 0x00000020 X#define BIT6L 0x00000040 X#define BIT7L 0x00000080 X#define BIT8L 0x00000100 X#define BIT9L 0x00000200 X#define BIT10L 0x00000400 X#define BIT11L 0x00000800 X#define BIT12L 0x00001000 X#define BIT13L 0x00002000 X#define BIT14L 0x00004000 X#define BIT15L 0x00008000 X#define BIT16L 0x00010000 X#define BIT17L 0x00020000 X#define BIT18L 0x00040000 X#define BIT19L 0x00080000 X#define BIT20L 0x00100000 X#define BIT21L 0x00200000 X#define BIT22L 0x00400000 X#define BIT23L 0x00800000 X#define BIT24L 0x01000000 X#define BIT25L 0x02000000 X#define BIT26L 0x04000000 X#define BIT27L 0x08000000 X#define BIT28L 0x10000000 X#define BIT29L 0x20000000 X#define BIT30L 0x40000000 X#define BIT31L 0x80000000 X X#endif __GEN__ ________This_Is_The_END________ if test `wc -c < gen.h` -ne 2837; then echo 'shar: gen.h was damaged during transit (should have been 2837 bytes)' fi fi ; : end of overwriting check echo 'x - chksum.c' if test -f chksum.c; then echo 'shar: not overwriting chksum.c'; else sed 's/^X//' << '________This_Is_The_END________' > chksum.c X/* /usr/bin/src/chksum.c 880118 NHA */ X X#define DEBUG 0 X#define MAJOR 'P' X#define MINOR 'C' X X#include <gen.h> X#include <string.h> X X#define SUCCESS 0 X#define FAILURE (!SUCCESS) X X X#ifdef __STDC__ Ximport char *gets(void *buffer); Ximport int open(char *filename, int mode); Ximport int read(int fd, void *buf, int count); Ximport int close(int fd); Ximport char *getenv(char *name); Ximport void exit(int status); Ximport unsigned long crc32buf(unsigned long initialSum, X unsigned char *buf, unsigned count); X#else Ximport char *gets(); Ximport int open(); Ximport int read(); Ximport int close(); Ximport char *getenv(); Ximport void exit(); Ximport unsigned long crc32buf(); X#endif __STDC__ X Xlocal unsigned char buffer[BUFSIZ]; /* reads go into this buffer */ Xlocal bool showCount; /* show the byte count [-c] */ Xlocal bool showError; /* show Errors in any case */ Xlocal bool totalOnly; /* don't show file sums [-t] */ Xlocal bool verbose; /* print filenames [-v] */ Xlocal bool firstFile; /* only true for 1st file */ Xlocal unsigned fileCount; /* # of files processed OK */ Xlocal unsigned errorCount; /* # of files with errors */ Xlocal unsigned long sum; /* checksum for a file */ Xlocal unsigned long grandSum; /* checksum over all files */ Xlocal unsigned long byteCount; /* byte count for a file */ Xlocal unsigned long grandByteCount; /* byte count over all files */ X X X X X/*+ c h k s u m X * Calculate two chksums for the file. X * One is simply the chksum of the bytes in the file. X * The other is updating the grandSum with the bytes in the file. X * The grandSum is only updated for files after the first file. X * The byteCount and grandByteCount variables are also updated. X * Return FAILURE for file errors, else SUCCESS. X */ Xlocal bool chksum(fd) Xint fd; /* File Descriptor */ X { X int status; /* status returned from sys calls */ X X printd(4, "chksum(%d)\n", fd); X X sum = 0L; X while (1) X { X /* read next bufferload from the file */ X status = read( fd, buffer, sizeof buffer ); X printd(9, "read status=%d\n", status); X if (status < 0) X { X printd(4, "chksum(): returning FAILURE\n"); X return FAILURE; X } X if (status == 0) X break; /* End Of File */ X X /* update checksums */ X sum = crc32buf(sum, buffer, (unsigned)status); X if ( ! firstFile ) X grandSum = crc32buf(grandSum, buffer, (unsigned)status); X X /* update byte counts */ X byteCount += (unsigned long)status; X grandByteCount += (unsigned long)status; X X printd(8, "sum=%08lx, grandSum=%08lx, byteCount=%ld, grandByteCount=%ld\n", X sum, grandSum, byteCount, grandByteCount); X } X X printd(4, "chksum(): returning SUCCESS with sum=%08lx, grandSum=%08lx\n", X sum, grandSum); X return SUCCESS; X } X X X X/*+ s u m F i l e X * Given a filename, calculate the checksum, do any necessary displaying, X * and update all the necessary global variables. X * If the filename is a NULL pointer or a pointer to '\0', we use stdin. X * In the event of file access errors, a sum of 0 is printed. X */ Xlocal void sumFile(filename) Xchar *filename; X { X int fd; /* File Descriptor */ X char name[88]; X bool isBad; /* YES for file errors */ X X printd(4, "sumFile(%s)\n", filename); X byteCount = 0L; X X /* open input file. NULL or ptr to '\0' is taken to mean standard input */ X if (filename == NULL || filename[0] == '\0') X { X strcpy(name, "--Stdin--"); X fd = fileno(stdin); X } X else X { X strcpy(name, filename); X fd = open(filename, O_RDONLY); X if (fd < 0) X { X isBad = YES; X ++errorCount; X sum = 0L; X printd(2, "sumFile(%s): can't open file for read\n", filename); X if (showError) X fprintf(stderr, "chksum: can't open \"%s\" for reading\n", X filename); X } X else X isBad = NO; X } X X /* calculate the checksum */ X if (0 <= fd) X { X if (chksum(fd) == SUCCESS) X { X isBad = NO; X ++fileCount; X if (firstFile) X { X grandSum = sum; X firstFile = NO; X } X } X else X { X isBad = YES; X ++errorCount; X sum = 0L; X printd(2, "sumFile(%s): error reading file\n", name); X if (showError) X fprintf(stderr, "chksum: error reading file \"%s\"\n", X filename); X } X if (fd != fileno(stdin)) X close(fd); X } X X /* report the results */ X if ( ! totalOnly) X { X printf("%08lx", sum); X if (showCount) X printf(" %10lu", byteCount); X if (verbose) X if (isBad) X printf(" %s *** ERROR ***", name); X else X printf(" %s", name); X putchar('\n'); X } X printd(4, "sumFile(): returning\n"); X } X X X X/*+ u s a g e X * Spew out the help message. X */ Xlocal void usage() X { X fprintf(stderr, "chksum -- calculate 32-bit checksum for file(s), output to stdout\n"); X fprintf(stderr, "Usage: chksum [-cehtv] {file|--|-}...\n"); X fprintf(stderr, "-c Count bytes also\n"); X fprintf(stderr, "-e give extended Error reports on stderr\n"); X fprintf(stderr, "-h Help; give this help message and exit\n"); X fprintf(stderr, "-t Total only; don't list sum for each file\n"); X fprintf(stderr, "-v Verbose; list filenames along with checksums\n"); X fprintf(stderr, "-- take filenames from stdin, 1 name per line\n"); X fprintf(stderr, "- take stdin as a file\n"); X fprintf(stderr, "Filenames may be mixed with options.\n"); X fprintf(stderr, "Exit status is the number of file errors encountered.\n"); X exit(1); X } /* usage */ X X X X/*+ m a i n X * See usage() for command line parameters. X */ Xexport int main(ac, av) Xint ac; Xchar **av; X { X char *p; X char line[BUFSIZ]; /* for reading from stdin */ X char switchar; X X /* initialize */ X initdebug(&ac, &av, "/dev/con", "/dev/fifo", "**0"); X showCount = NO; /* default is no byte counts */ X showError = NO; /* default is no reports on stderr*/ X totalOnly = NO; /* default is show all checksums */ X verbose = NO; /* default is no filenames */ X firstFile = YES; /* no files checksummed yet */ X fileCount = 0; X errorCount = 0; X grandSum = 0L; X grandByteCount = 0L; X p = getenv("SWITCHAR"); X if (p == NULL) X switchar = '-'; X else X switchar = *p; X X /* process command line arguments */ X for (--ac, ++av ; 0 < ac ; --ac, ++av) X { X printd(7, "main(): ac = %d, *av = '%s'\n", ac, *av); X if (av[0][0] == switchar) X switch (av[0][1]) X { X case 'C': X case 'c': X showCount = YES; X break; X case 'E': X case 'e': X showError = YES; X break; X case 'H': X case 'h': X usage(); X break; X case 'T': X case 't': X totalOnly = YES; X break; X case 'V': X case 'v': X verbose = YES; X break; X case '-': /* take filenames from stdin */ X while (gets(line) != NULL) X sumFile(line); X if (showError && ferror(stdin)) X fprintf(stderr, "chksum: error reading standard input\n"); X clearerr(stdin); X break; X case '\0': X sumFile(NULL); /* use standard input for file */ X break; X default: X fprintf(stderr, "chksum: unknown option %s\n", av[0]); X } /* switch */ X else X sumFile(av[0]); /* file */ X } X X X /* put out the Grand Total */ X if ((fileCount + errorCount) == 0) X usage(); /* no files specified */ X else if ((fileCount + errorCount) == 1) X { /* one file specified */ X if (totalOnly) X { X printf("%08lx", grandSum); X if (showCount) X printf(" %10lu", grandByteCount); X putchar('\n'); X } X } X else X { /* multiple files specified */ X if ( ! totalOnly) X { X printf("========"); X if (showCount) X printf("============"); X putchar('\n'); X } X printf("%08lx", grandSum); X if (showCount) X printf(" %10lu", grandByteCount); X if (verbose) X { X if (showCount) X printf(" Grand Totals for %u files", fileCount); X else X printf(" Grand Total for %u files", fileCount); X if (errorCount == 1) X printf(" ***** plus 1 ERROR *****"); X else if (1 < errorCount) X printf(" ***** plus %u ERRORS *****", errorCount); X } X putchar('\n'); X } X printd(3, "chksum: returning %u", errorCount); X exit(errorCount); X } /* main */ ________This_Is_The_END________ if test `wc -c < chksum.c` -ne 8136; then echo 'shar: chksum.c was damaged during transit (should have been 8136 bytes)' fi fi ; : end of overwriting check echo 'x - crc32.c' if test -f crc32.c; then echo 'shar: not overwriting crc32.c'; else sed 's/^X//' << '________This_Is_The_END________' > crc32.c X/* /usr/lib/src/pd/crc32.c 881102 NHA */ X/* X * Crc - 32 BIT ANSI X3.66 CRC checksum files X */ X X#define TEST 0 X#define DEBUG 0 X#define FAST 0 X X#define MAJOR 'L' X#define MINOR 'C' X X#include <gen.h> X X#define OK 0 X#define ERROR (-1) X#define LINT_ARGS X X/**********************************************************************\ X|* *| X|* Demonstration program to compute the 32-bit CRC used as the frame *| X|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| X|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| X|* protocol). The 32-bit FCS was added via the Federal Register, *| X|* 1 June 1982, p.23798. I presume but don't know for certain that *| X|* this polynomial is or will be included in CCITT V.41, which *| X|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| X|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| X|* errors by a factor of 10^-5 over 16-bit FCS. *| X|* *| X\**********************************************************************/ X X/* Need an unsigned type capable of holding 32 bits; */ Xtypedef unsigned long int UNS_32_BITS; X X/* X * Copyright (C) 1986 Gary S. Brown. You may use this program, or X * code or tables extracted from it, as desired without restriction. X */ X/* First, the polynomial itself and its table of feedback terms. The */ X/* polynomial is */ X/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ X/* Note that we take it "backwards" and put the highest-order term in */ X/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ X/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ X/* the MSB being 1. */ X X/* Note that the usual hardware shift register implementation, which */ X/* is what we're using (we're merely optimizing it by doing eight-bit */ X/* chunks at a time) shifts bits into the lowest-order term. In our */ X/* implementation, that means shifting towards the right. Why do we */ X/* do it this way? Because the calculated CRC must be transmitted in */ X/* order from highest-order term to lowest-order term. UARTs transmit */ X/* characters in order from LSB to MSB. By storing the CRC this way, */ X/* we hand it to the UART in the order low-byte to high-byte; the UART */ X/* sends each low-bit to hight-bit; and the result is transmission bit */ X/* by bit from highest- to lowest-order term without requiring any bit */ X/* shuffling on our part. Reception works similarly. */ X X/* The feedback terms table consists of 256, 32-bit entries. Notes: */ X/* */ X/* 1. The table can be generated at runtime if desired; code to do so */ X/* is shown later. It might not be obvious, but the feedback */ X/* terms simply represent the results of eight shift/xor opera- */ X/* tions for all combinations of data and CRC register values. */ X/* */ X/* 2. The CRC accumulation logic is the same for all CRC polynomials, */ X/* be they sixteen or thirty-two bits wide. You simply choose the */ X/* appropriate table. Alternatively, because the table can be */ X/* generated at runtime, you can start by generating the table for */ X/* the polynomial in question and use exactly the same "updcrc", */ X/* if your application needn't simultaneously handle two CRC */ X/* polynomials. (Note, however, that XMODEM is strange.) */ X/* */ X/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ X/* of course, 32-bit entries work OK if the high 16 bits are zero. */ X/* */ X/* 4. The values must be right-shifted by eight bits by the "updcrc" */ X/* logic; the shift must be unsigned (bring in zeroes). On some */ X/* hardware you could probably optimize the shift in assembler by */ X/* using byte-swap instructions. */ X Xstatic UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ X0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, X0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, X0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, X0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, X0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, X0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, X0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, X0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, X0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, X0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, X0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, X0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, X0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, X0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, X0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, X0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, X0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, X0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, X0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, X0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, X0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, X0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, X0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, X0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, X0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, X0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, X0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, X0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, X0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, X0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, X0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, X0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, X0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, X0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, X0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, X0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, X0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, X0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, X0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, X0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, X0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, X0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, X0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, X0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, X0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, X0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, X0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, X0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, X0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, X0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, X0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, X0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, X0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, X0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, X0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, X0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, X0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, X0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, X0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, X0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, X0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, X0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, X0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, X0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d X}; X X X X/*+ c r c 3 2 b u f X * Given an initial 32-bit CRC and a buffer, calculate the new CRC. X * Returns the new CRC. X */ Xexport UNS_32_BITS crc32buf( crc, cp, cnt ) XUNS_32_BITS crc; /* initial CRC */ Xunsigned char *cp; /* pointer to buffer */ Xunsigned cnt; /* # chars in buffer */ X { X printd(3, "crc32buf(%lu, %p, %u)\n", crc, cp, cnt); X X#if FAST X#asm X;es:si holds pointer to buffer (cp) X;cx holds count (cnt) X;dx,ax holds crc hi,lo X mov cx, word ptr 14[bp] ;cnt X jcxz done X mov ax, word ptr 6[bp] ;crc lo X mov dx, word ptr 8[bp] ;crc hi X les bx, dword ptr 10[bp] ;cp X mov si, bx Xagain: X mov bl, es:byte ptr [si] ;octet X xor bl, al ;crc ^ octet & 0377 X xor bh, bh X shl bx, 1 X shl bx, 1 ;bx is index into crc_32_tab X mov al, ah ;crc >>= 8 X mov ah, dl X mov dl, dh X xor dh, dh X xor ax, word ptr crc_32_tab_[bx] ;low word X xor dx, word ptr crc_32_tab_[bx+2] ;high word X inc si X loop again X mov word ptr 6[bp], ax ;crc lo X mov word ptr 8[bp], dx ;crc hi Xdone: X#endasm X#else FAST X#define W 16 X#define B 8 X while( cnt-- ) { X# if SWAPPED X crc = (crc<<B) ^ crc_32_tab[(crc>>(W-B)) ^ *cp++]; X# else SWAPPED X crc = (crc>>B) ^ crc_32_tab[(crc & ((1<<B)-1)) ^ *cp++]; X# endif SWAPPED X printd(8, "crc32buf(): cnt=%u, crc=%08lx\n", cnt, crc); X } X#endif FAST X X printd(3, "crc32buf(): returning %lu\n", crc); X return( crc ); X} /* crc32buf() */ X X X X/*+ c r c 3 2 1 X * Given a 32-bit CRC and a byte, return the new CRC which includes the byte. X */ Xexport UNS_32_BITS crc321( crc, octet ) XUNS_32_BITS crc; Xunsigned char octet; X { X UNS_32_BITS newcrc; X printd(3, "crc321(%lu, %#02x)\n", crc, octet); X#if FAST X#asm X mov bl, byte ptr 10[bp] ;octet X xor bl, byte ptr 6[bp] ;(crc ^ octet) & 0377 X xor bh, bh X shl bx, 1 X shl bx, 1 ;bx is index into crc_32_tab X mov ax, word ptr crc_32_tab_[bx] ;low word X mov dx, word ptr crc_32_tab_[bx+2] ;high word X xor ax, word ptr 7[bp] ;xor with (crc >> 8), low word X xor dl, byte ptr 9[bp] ;xor with (crc >> 8), high byte X mov word ptr -4[bp], ax ;store in newcrc X mov word ptr -2[bp], dx ; for printf() and return value X#endasm X#else FAST X newcrc = (crc_32_tab[((crc) ^ (octet)) & 0377] ^ ((crc) >> 8)); X#endif FAST X printd(3, "crc321(): returning %lu\n", newcrc); X return newcrc; X} /* crc321() */ X X X#if TEST X X#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) X X Xlocal crc32file(name) Xchar *name; X{ X register FILE *fin; X register unsigned long oldcrc32; X register unsigned long crc32; X register unsigned long oldcrc; X register c; X register long charcnt; X X oldcrc32 = 0xFFFFFFFF; charcnt = 0; X#ifdef M_I86SM X if ((fin=fopen(name, "rb"))==NULL) X#else X if ((fin=fopen(name, "r"))==NULL) X#endif X { X perror(name); X return ERROR; X } X while ((c=getc(fin))!=EOF) { X ++charcnt; X/** oldcrc32 = UPDC32(c, oldcrc32); **/ X oldcrc32 = crc321(oldcrc32, c); X } X X if (ferror(fin)) { X perror(name); X charcnt = -1; X } X fclose(fin); X X crc32 = oldcrc32; oldcrc = oldcrc32 = ~oldcrc32; X X/* X crc32 = UPDC32((oldcrc32 & 0377), crc32); oldcrc32 >>=8; X crc32 = UPDC32((oldcrc32 & 0377), crc32); oldcrc32 >>=8; X crc32 = UPDC32((oldcrc32 & 0377), crc32); oldcrc32 >>=8; X crc32 = UPDC32((oldcrc32 & 0377), crc32); oldcrc32 >>=8; X printf("%08lX ", crc32); X*/ X X printf("%08lX %7ld %s\n", oldcrc, charcnt, name); X X return OK; X} X X Xexport main(argc, argp) Xchar **argp; X{ X register errors = 0; X X while( --argc > 0) X errors |= crc32file( *++argp); X exit(errors != 0); X} X#endif TEST ________This_Is_The_END________ if test `wc -c < crc32.c` -ne 11016; then echo 'shar: crc32.c was damaged during transit (should have been 11016 bytes)' fi fi ; : end of overwriting check exit 0