1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1996-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                                                                      *
19***********************************************************************/
20#pragma prototyped
21
22/*
23 * crc
24 */
25
26#define crc_description \
27	"32 bit CRC (cyclic redundancy check)."
28#define crc_options	"\
29[+polynomial?The 32 bit crc polynomial bitmask with implicit bit 32.]:[mask:=0xedb88320]\
30[+done?XOR the final crc value with \anumber\a. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0]\
31[+init?The initial crc value. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0]\
32[+rotate?XOR each input character with the high order crc byte (instead of the low order).]\
33[+size?Include the total number of bytes in the crc. \anumber\a, if specified, is first XOR'd into the size.]:?[number:=0]\
34"
35#define crc_match	"crc"
36#define crc_open	crc_open
37#define crc_print	long_print
38#define crc_data	long_data
39#define crc_scale	0
40
41typedef uint32_t Crcnum_t;
42
43typedef struct Crc_s
44{
45	_SUM_PUBLIC_
46	_SUM_PRIVATE_
47	_INTEGRAL_PRIVATE_
48	Crcnum_t		init;
49	Crcnum_t		done;
50	Crcnum_t		xorsize;
51	Crcnum_t		tab[256];
52	unsigned int		addsize;
53	unsigned int		rotate;
54} Crc_t;
55
56#define CRC(p,s,c)		(s = (s >> 8) ^ (p)->tab[(s ^ (c)) & 0xff])
57#define CRCROTATE(p,s,c)	(s = (s << 8) ^ (p)->tab[((s >> 24) ^ (c)) & 0xff])
58
59static Sum_t*
60crc_open(const Method_t* method, const char* name)
61{
62	register Crc_t*		sum;
63	register const char*	s;
64	register const char*	t;
65	register const char*	v;
66	register int		i;
67	register int		j;
68	Crcnum_t		polynomial;
69	Crcnum_t		x;
70
71	if (sum = newof(0, Crc_t, 1, 0))
72	{
73		sum->method = (Method_t*)method;
74		sum->name = name;
75	}
76	polynomial = 0xedb88320;
77	s = name;
78	while (*(t = s))
79	{
80		for (t = s, v = 0; *s && *s != '-'; s++)
81			if (*s == '=' && !v)
82				v = s;
83		i = (v ? v : s) - t;
84		if (isdigit(*t) || v && i >= 4 && strneq(t, "poly", 4) && (t = v + 1))
85			polynomial = strtoul(t, NiL, 0);
86		else if (strneq(t, "done", i))
87			sum->done = v ? strtoul(v + 1, NiL, 0) : ~sum->done;
88		else if (strneq(t, "init", i))
89			sum->init = v ? strtoul(v + 1, NiL, 0) : ~sum->init;
90		else if (strneq(t, "rotate", i))
91			sum->rotate = 1;
92		else if (strneq(t, "size", i))
93		{
94			sum->addsize = 1;
95			if (v)
96				sum->xorsize = strtoul(v + 1, NiL, 0);
97		}
98		if (*s == '-')
99			s++;
100	}
101	if (sum->rotate)
102	{
103		Crcnum_t	t;
104		Crcnum_t	p[8];
105
106		p[0] = polynomial;
107		for (i = 1; i < 8; i++)
108			p[i] = (p[i-1] << 1) ^ ((p[i-1] & 0x80000000) ? polynomial : 0);
109		for (i = 0; i < elementsof(sum->tab); i++)
110		{
111			t = 0;
112			x = i;
113			for (j = 0; j < 8; j++)
114			{
115				if (x & 1)
116					t ^= p[j];
117				x >>= 1;
118			}
119			sum->tab[i] = t;
120		}
121	}
122	else
123	{
124		for (i = 0; i < elementsof(sum->tab); i++)
125		{
126			x = i;
127			for (j = 0; j < 8; j++)
128				x = (x>>1) ^ ((x & 1) ? polynomial : 0);
129			sum->tab[i] = x;
130		}
131	}
132	return (Sum_t*)sum;
133}
134
135static int
136crc_init(Sum_t* p)
137{
138	Crc_t*		sum = (Crc_t*)p;
139
140	sum->sum = sum->init;
141	return 0;
142}
143
144static int
145crc_block(Sum_t* p, const void* s, size_t n)
146{
147	Crc_t*			sum = (Crc_t*)p;
148	register Crcnum_t	c = sum->sum;
149	register unsigned char*	b = (unsigned char*)s;
150	register unsigned char*	e = b + n;
151
152	if (sum->rotate)
153		while (b < e)
154			CRCROTATE(sum, c, *b++);
155	else
156		while (b < e)
157			CRC(sum, c, *b++);
158	sum->sum = c;
159	return 0;
160}
161
162static int
163crc_done(Sum_t* p)
164{
165	register Crc_t*		sum = (Crc_t*)p;
166	register Crcnum_t	c;
167	register uintmax_t	n;
168	int			i;
169	int			j;
170
171	c = sum->sum;
172	if (sum->addsize)
173	{
174		n = sum->size ^ sum->xorsize;
175		if (sum->rotate)
176			while (n)
177			{
178				CRCROTATE(sum, c, n);
179				n >>= 8;
180			}
181		else
182			for (i = 0, j = 32; i < 4; i++)
183			{
184				j -= 8;
185				CRC(sum, c, n >> j);
186			}
187	}
188	sum->sum = c ^ sum->done;
189	sum->total_sum ^= (sum->sum &= 0xffffffff);
190	return 0;
191}
192