[net.sources] CRC program

hugh@hcrvax.UUCP (Hugh Redelmeier) (11/15/84)

The following program is a command to calculate the CRC of files.
It is useful for the same purposes as sum(1).  It calculates the
true CRC16 (unlike CP/M utilities that say they calculate CRCs
but really just hash).  Crc detects more errors than old sum(1);
for example, it detects exchanges of characters.  It is also
(now) in the public domain.
Usage: crc [file ...]
The crc of the source is 8dc7.
----------------- tear here ----------------------
/*
 * Calculate CRC16 of a file.
 * CRC16 polynomial: x**0 + x**2 + x**15 + x**16 (0xA001)
 * (CCITT polynomial: x**0 + x**5 + x**12 + x**16 (0x8408))
 * Initial condition: 0
 *
 * There are really two programs.  The first (compiled with
 * "TABLE" defined) calculates CRC tables to be included
 * in the second (compiled without "TABLE").
 *
 * D. Hugh Redelmeier  1983 April 15
 * Latest change: 1984 April 2.
 */

#include <stdio.h>

#ifdef TABLE
main() {
	register unsigned s, t;
	register int i;

	printf("unsigned short CRCtab[256] = {");
	for (t=0; ; ) {
		if (t%8 == 0)
			printf("\n");
		s = t;
		for (i=8; i--; )
			s = s>>1 ^ (s&1? 0xA001 : 0);
		printf("\t0x%04x", s);
		if (++t == 256)
			break;
		printf(",");
		}
	printf("};\n");
	}

#else

unsigned short CRCtab[256] = {
	0x0000,	0xc0c1,	0xc181,	0x0140,	0xc301,	0x03c0,	0x0280,	0xc241,
	0xc601,	0x06c0,	0x0780,	0xc741,	0x0500,	0xc5c1,	0xc481,	0x0440,
	0xcc01,	0x0cc0,	0x0d80,	0xcd41,	0x0f00,	0xcfc1,	0xce81,	0x0e40,
	0x0a00,	0xcac1,	0xcb81,	0x0b40,	0xc901,	0x09c0,	0x0880,	0xc841,
	0xd801,	0x18c0,	0x1980,	0xd941,	0x1b00,	0xdbc1,	0xda81,	0x1a40,
	0x1e00,	0xdec1,	0xdf81,	0x1f40,	0xdd01,	0x1dc0,	0x1c80,	0xdc41,
	0x1400,	0xd4c1,	0xd581,	0x1540,	0xd701,	0x17c0,	0x1680,	0xd641,
	0xd201,	0x12c0,	0x1380,	0xd341,	0x1100,	0xd1c1,	0xd081,	0x1040,
	0xf001,	0x30c0,	0x3180,	0xf141,	0x3300,	0xf3c1,	0xf281,	0x3240,
	0x3600,	0xf6c1,	0xf781,	0x3740,	0xf501,	0x35c0,	0x3480,	0xf441,
	0x3c00,	0xfcc1,	0xfd81,	0x3d40,	0xff01,	0x3fc0,	0x3e80,	0xfe41,
	0xfa01,	0x3ac0,	0x3b80,	0xfb41,	0x3900,	0xf9c1,	0xf881,	0x3840,
	0x2800,	0xe8c1,	0xe981,	0x2940,	0xeb01,	0x2bc0,	0x2a80,	0xea41,
	0xee01,	0x2ec0,	0x2f80,	0xef41,	0x2d00,	0xedc1,	0xec81,	0x2c40,
	0xe401,	0x24c0,	0x2580,	0xe541,	0x2700,	0xe7c1,	0xe681,	0x2640,
	0x2200,	0xe2c1,	0xe381,	0x2340,	0xe101,	0x21c0,	0x2080,	0xe041,
	0xa001,	0x60c0,	0x6180,	0xa141,	0x6300,	0xa3c1,	0xa281,	0x6240,
	0x6600,	0xa6c1,	0xa781,	0x6740,	0xa501,	0x65c0,	0x6480,	0xa441,
	0x6c00,	0xacc1,	0xad81,	0x6d40,	0xaf01,	0x6fc0,	0x6e80,	0xae41,
	0xaa01,	0x6ac0,	0x6b80,	0xab41,	0x6900,	0xa9c1,	0xa881,	0x6840,
	0x7800,	0xb8c1,	0xb981,	0x7940,	0xbb01,	0x7bc0,	0x7a80,	0xba41,
	0xbe01,	0x7ec0,	0x7f80,	0xbf41,	0x7d00,	0xbdc1,	0xbc81,	0x7c40,
	0xb401,	0x74c0,	0x7580,	0xb541,	0x7700,	0xb7c1,	0xb681,	0x7640,
	0x7200,	0xb2c1,	0xb381,	0x7340,	0xb101,	0x71c0,	0x7080,	0xb041,
	0x5000,	0x90c1,	0x9181,	0x5140,	0x9301,	0x53c0,	0x5280,	0x9241,
	0x9601,	0x56c0,	0x5780,	0x9741,	0x5500,	0x95c1,	0x9481,	0x5440,
	0x9c01,	0x5cc0,	0x5d80,	0x9d41,	0x5f00,	0x9fc1,	0x9e81,	0x5e40,
	0x5a00,	0x9ac1,	0x9b81,	0x5b40,	0x9901,	0x59c0,	0x5880,	0x9841,
	0x8801,	0x48c0,	0x4980,	0x8941,	0x4b00,	0x8bc1,	0x8a81,	0x4a40,
	0x4e00,	0x8ec1,	0x8f81,	0x4f40,	0x8d01,	0x4dc0,	0x4c80,	0x8c41,
	0x4400,	0x84c1,	0x8581,	0x4540,	0x8701,	0x47c0,	0x4680,	0x8641,
	0x8201,	0x42c0,	0x4380,	0x8341,	0x4100,	0x81c1,	0x8081,	0x4040};

main(argc, argv) int argc; char *argv[]; {
	FILE *f;
	int fi;
	char *fn;
	register unsigned s;
	register int c;	/* must hold and distinguiah EOF and 0xFF */

	fi = 1;
	f = stdin;
	fn = "";
	do {
		if (fi != argc) {
			fn = argv[fi];
			f = fopen(fn, "r");
			if (f==NULL) {
				fprintf(stderr, "%s: can't open %s\n",
					argv[0], fn);
				exit(1);
				}
			}
		s = 0;
		while ((c=getc(f)) != EOF)
			s = CRCtab[(s^c)&0xFF] ^ s>>8;
		printf("%s CRC16 is %04x\n", fn, s);
		fclose(f);
		} while (++fi < argc);
	exit(0);
	}
#endif