phil@vaxwaller.UUCP (Phil Newton) (09/25/90)
I'm interested in seeing if anyone out there has written either a Arithmetic Checksum program in "C" or a CRC-16 checksum program in "C". I need to create a utility that will allow our software engineers the ability to perform either an Arithmetic checksum or a CRC-16 checksum on a software module. Before I create this utility from scratch, I thought I'd ask and see if anyone's coded either of these Checksum algorithms already. If you have any helpful information, please email me at "... {lll-winken,zehntel,pacbell}!varian!phil" Thanks for your assistance. -- Philip T. Newton (415)945-2272 Varian Instruments 2700 Mitchell Drive Walnut Creek, CA. 94598 {zehntel,pacbell,lll-winken}!varian!phil
@tree.uucp (Chris Gonnerman) (09/30/90)
I am also interested in such a program... -- +----------------------------------------------------------------------------+ | Chris Gonnerman (Mad Programmer At Large) csusac.ecs.csus.edu!tree!jcg | | @ the Tree BBS, Sacramento, CA ucbvax!ucdavis!csusac!tree!jcg | +---------- DISCLAIMER: These opinions are mine... MINE, I say! -----------+
trt@rti.rti.org (Thomas Truscott) (10/01/90)
Here is a CRC program. I set up the main program to use memcrc_16 (CRC-16). Tom Truscott /* * Cyclic redundancy check calculation: * memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags) * * Returns the CRC of the "len" characters starting at "bfr". * The "crc_value" is initially 0, and should subsequently * be the previous result of memcrc to permit a CRC * to be calculated using multiple calls to memcrc. * The low-order "bits_per_char" bits of each character * are presented serially to the CRC, low-order bit first. * * The "poly" is the CRC generating polynomial expressed in binary: * for an N-bit CRC, for each term x^i, set the bit valued 2^(N-1-i). * Ignore the high-order x^N term which is "implied". * Both "crc_value" and "poly" are "bits_in_crc" long. * * The "flags" are used to provide special functions * needed for particular CRC implementations. * It currently supports complementation of input and output crc values. * Future flags may support bit-reversal of the input and output crc values, * the input character values, etc. This would be needed to * support the "pathalias" CRC, for example. * * Tom Truscott, trt@rti.rti.org, (919) 541-7005 */ #define CRC_COMPLEMENT 01 /* * Here are some macros that implement popular polynomials. * Eight bits per character is assumed. */ /* CRC-32 (FIPS PUB 78, CCITT X.25). Highly Recommended. */ /* 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 */ #define memcrc_32(b,l,c) memcrc(b,l,c,8,(long)0xEDB88320L,32,CRC_COMPLEMENT) /* CRC-16 (DDCMP,BISYNC). x^16 + x^15 + x^2 + x^1 */ #define memcrc_16(b,l,c) memcrc(b,l,c,8,(long)0xA001L,16,0) /* CRC-CCITT (ADCCP,HDLC,SDLC). x^16 + x12 + x^5 + x^1 */ #define memcrc_ccitt(b,l,c) memcrc(b,l,c,8,(long)0x1021L,16,CRC_COMPLEMENT) #ifdef SLOW_AND_SIMPLE long memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags) register char *bfr; int len; register long crc_value; long poly; int bits_in_crc; int flags; { register int i, val; if (flags & CRC_COMPLEMENT) { if (bits_in_crc == 32) crc_value ^= 0xffffffffL; /* needed due to bug in << */ else crc_value ^= ~(~0L << bits_in_crc); } while (--len >= 0) { val = *bfr++; for (i = 0; i < bits_per_char; i++) { crc_value = ((unsigned long)crc_value >> 1) ^ (((crc_value ^ val) & 1)? poly: 0); val >>= 1; } } if (flags & CRC_COMPLEMENT) { if (bits_in_crc == 32) crc_value ^= 0xffffffffL; else crc_value ^= ~(~0L << bits_in_crc); } return (crc_value); } #else /* * In this implementation, the CRC calculation is performed on * "bits_per_char" characters at a time by using a table lookup. * The table is recomputed whenever memcrc is called with * new CRC parameters. */ static int cached_bits_per_char, cached_flags; static long cached_poly; static long *cached_table; /* ARGSUSED */ init_crc(bits_per_char, poly, flags) int bits_per_char; long poly; int flags; { register int i, val, j; register long crc_value; extern char *malloc(); cached_table = (long *)malloc((unsigned int)(sizeof(long)*(1<<bits_per_char))); if (cached_table == 0) abort("init_crc malloc failed"); for (i = 0; i < 1<<bits_per_char; i++) { /* compute the CRC of the "i"th char */ val = i; crc_value = 0; for (j = 0; j < bits_per_char; j++) { crc_value = ((unsigned long)crc_value >> 1) ^ (((crc_value ^ val) & 1)? poly: 0); val >>= 1; } cached_table[i] = crc_value; } } long memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags) register char *bfr; int len; long crc_value; register int bits_per_char; long poly; int bits_in_crc; int flags; { register long *tabp; register int bitmask; register char *ebfr; if (bits_per_char != cached_bits_per_char || poly != cached_poly || flags != cached_flags || cached_table == 0) { init_crc(bits_per_char, poly, flags); } if (flags & CRC_COMPLEMENT) { if (bits_in_crc == 32) crc_value ^= 0xffffffffL; else crc_value ^= ~(~0L << bits_in_crc); } tabp = cached_table; /* probably more efficient this way */ bitmask = ~(~0 << bits_per_char); /* ditto */ ebfr = bfr + len; /* ditto */ while (bfr < ebfr) { crc_value = ((unsigned long)crc_value >> bits_per_char) ^ tabp[(crc_value ^ *bfr++) & bitmask]; } if (flags & CRC_COMPLEMENT) { if (bits_in_crc == 32) crc_value ^= 0xffffffffL; else crc_value ^= ~(~0L << bits_in_crc); } return (crc_value); } #endif /* * test program */ #include <stdio.h> main(argc, argv) int argc; char **argv; { FILE *fp; int errors; errors = 0; if (argc <= 1) errors += do_crc(stdin, "<stdin>"); else while (--argc > 0) { if ((fp = fopen(*++argv, "r")) == 0) { perror(*argv); errors++; continue; } errors += do_crc(fp, *argv); (void) fclose(fp); } exit(errors != 0); } do_crc(fp, fname) FILE *fp; char *fname; { char bfr[8192]; int n; long nbytes, crcval; nbytes = 0; crcval = 0; while ((n = fread(bfr, 1, sizeof(bfr), fp)) > 0) { crcval = memcrc_16(bfr, n, crcval); nbytes += n; } if (ferror(fp)) { perror(fname); return(1); } printf("%010lu %7ld %s\n", crcval, nbytes, fname); return(0); }