/*
 *	Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *	This will be free software, but only when it is finished.
 */

/*
 *
 * CRC32 code extracted out from  symbol.c  into its own file
 * by Matti Aarnio <mea@nic.funet.fi> 9-Sept-1999
 *
 */

#include <sys/types.h>

#ifndef __
# ifdef __STDC__
#  define __(x) x
# else
#  define __(x) ()
# endif
#endif

/* crc table and hash algorithm from pathalias */
/*
 * fold a string into a long int.  31 bit crc (from andrew appel).
 * the crc table is computed at run time by crcinit() -- we could
 * precompute, but it takes 1 clock tick on a 750.
 *
 * This fast table calculation works only if POLY is a prime polynomial
 * in the field of integers modulo 2.  Since the coefficients of a
 * 32-bit polynomail won't fit in a 32-bit word, the high-order bit is
 * implicit.  IT MUST ALSO BE THE CASE that the coefficients of orders
 * 31 down to 25 are zero.  Happily, we have candidates, from
 * E. J.  Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
 *      x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
 *      x^31 + x^3 + x^0
 *
 * We reverse the bits to get:
 *      111101010000000000000000000000001 but drop the last 1
 *         f   5   0   0   0   0   0   0
 *      010010000000000000000000000000001 ditto, for 31-bit crc
 *         4   8   0   0   0   0   0   0
 */

#define POLY32 0xf5000000       /* 32-bit polynomial */
#define POLY31 0x48000000       /* 31-bit polynomial */
#define POLY POLY31     /* use 31-bit to avoid sign problems */

static long CrcTable[128];
static int crcinit_done = 0;

static void crcinit __((void));
static void
crcinit()
{       
	register int i,j;
	register long sum;

	for (i = 0; i < 128; i++) {
		sum = 0;
		for (j = 7-1; j >= 0; --j)
			if (i & (1 << j))
				sum ^= POLY >> j;
		CrcTable[i] = sum;
	}
	crcinit_done = 1;
}

/* Arbitary octet sequence of "slen" bytes */
extern unsigned long crc32n __((const unsigned char *, int));

unsigned long
crc32n(s,slen)
     const unsigned char *s;
     int slen;
{
	unsigned long key;

	if (!crcinit_done)
	  crcinit();

	/* Input string is to be CRCed to form a new key-id */
	key = 0;
	for (; slen > 0; ++s, --slen)
	  key = (key >> 7) ^ CrcTable[(key ^ *s) & 0x7f];

	key &= 0xFFFFFFFFUL;

	return key;
}

/* Zero-terminated "string" */
extern unsigned long crc32 __((const unsigned char *));

unsigned long
crc32(s)
     const unsigned char *s;
{
	unsigned long key;

	if (!crcinit_done)
	  crcinit();

	/* Input string is to be CRCed to form a new key-id */
	key = 0;
	for (; *s; ++s)
	  key = (key >> 7) ^ CrcTable[(key ^ *s) & 0x7f];

	key &= 0xFFFFFFFFUL;

	return key;
}
