[comp.sources.wanted] Wanted: Arithmetic and CRC-16 Checksum pgm in "C"

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);
}