xref: /inferno-os/os/boot/libflate/deflate.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include "lib9.h"
2*74a4d8c2SCharles.Forsyth #include <flate.h>
3*74a4d8c2SCharles.Forsyth 
4*74a4d8c2SCharles.Forsyth typedef struct Chain	Chain;
5*74a4d8c2SCharles.Forsyth typedef struct Chains	Chains;
6*74a4d8c2SCharles.Forsyth typedef struct Dyncode	Dyncode;
7*74a4d8c2SCharles.Forsyth typedef struct Huff	Huff;
8*74a4d8c2SCharles.Forsyth typedef struct LZblock	LZblock;
9*74a4d8c2SCharles.Forsyth typedef struct LZstate	LZstate;
10*74a4d8c2SCharles.Forsyth 
11*74a4d8c2SCharles.Forsyth enum
12*74a4d8c2SCharles.Forsyth {
13*74a4d8c2SCharles.Forsyth 	/*
14*74a4d8c2SCharles.Forsyth 	 * deflate format paramaters
15*74a4d8c2SCharles.Forsyth 	 */
16*74a4d8c2SCharles.Forsyth 	DeflateUnc	= 0,			/* uncompressed block */
17*74a4d8c2SCharles.Forsyth 	DeflateFix	= 1,			/* fixed huffman codes */
18*74a4d8c2SCharles.Forsyth 	DeflateDyn	= 2,			/* dynamic huffman codes */
19*74a4d8c2SCharles.Forsyth 
20*74a4d8c2SCharles.Forsyth 	DeflateEob	= 256,			/* end of block code in lit/len book */
21*74a4d8c2SCharles.Forsyth 	DeflateMaxBlock	= 64*1024-1,		/* maximum size of uncompressed block */
22*74a4d8c2SCharles.Forsyth 
23*74a4d8c2SCharles.Forsyth 	DeflateMaxExp	= 10,			/* maximum expansion for a block */
24*74a4d8c2SCharles.Forsyth 
25*74a4d8c2SCharles.Forsyth 	LenStart	= 257,			/* start of length codes in litlen */
26*74a4d8c2SCharles.Forsyth 	Nlitlen		= 288,			/* number of litlen codes */
27*74a4d8c2SCharles.Forsyth 	Noff		= 30,			/* number of offset codes */
28*74a4d8c2SCharles.Forsyth 	Nclen		= 19,			/* number of codelen codes */
29*74a4d8c2SCharles.Forsyth 
30*74a4d8c2SCharles.Forsyth 	MaxOff		= 32*1024,
31*74a4d8c2SCharles.Forsyth 	MinMatch	= 3,			/* shortest match possible */
32*74a4d8c2SCharles.Forsyth 	MaxMatch	= 258,			/* longest match possible */
33*74a4d8c2SCharles.Forsyth 
34*74a4d8c2SCharles.Forsyth 	/*
35*74a4d8c2SCharles.Forsyth 	 * huffman code paramaters
36*74a4d8c2SCharles.Forsyth 	 */
37*74a4d8c2SCharles.Forsyth 	MaxLeaf		= Nlitlen,
38*74a4d8c2SCharles.Forsyth 	MaxHuffBits	= 16,			/* max bits in a huffman code */
39*74a4d8c2SCharles.Forsyth 	ChainMem	= 2 * (MaxHuffBits - 1) * MaxHuffBits,
40*74a4d8c2SCharles.Forsyth 
41*74a4d8c2SCharles.Forsyth 	/*
42*74a4d8c2SCharles.Forsyth 	 * coding of the lz parse
43*74a4d8c2SCharles.Forsyth 	 */
44*74a4d8c2SCharles.Forsyth 	LenFlag		= 1 << 3,
45*74a4d8c2SCharles.Forsyth 	LenShift	= 4,			/* leaves enough space for MinMatchMaxOff */
46*74a4d8c2SCharles.Forsyth 	MaxLitRun	= LenFlag - 1,
47*74a4d8c2SCharles.Forsyth 
48*74a4d8c2SCharles.Forsyth 	/*
49*74a4d8c2SCharles.Forsyth 	 * internal lz paramaters
50*74a4d8c2SCharles.Forsyth 	 */
51*74a4d8c2SCharles.Forsyth 	DeflateOut	= 4096,			/* output buffer size */
52*74a4d8c2SCharles.Forsyth 	BlockSize	= 8192,			/* attempted input read quanta */
53*74a4d8c2SCharles.Forsyth 	DeflateBlock	= DeflateMaxBlock & ~(BlockSize - 1),
54*74a4d8c2SCharles.Forsyth 	MinMatchMaxOff	= 4096,			/* max profitable offset for small match;
55*74a4d8c2SCharles.Forsyth 						 * assumes 8 bits for len, 5+10 for offset
56*74a4d8c2SCharles.Forsyth 						 * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
57*74a4d8c2SCharles.Forsyth 						 */
58*74a4d8c2SCharles.Forsyth 	HistSlop	= 512,			/* must be at lead MaxMatch */
59*74a4d8c2SCharles.Forsyth 	HistBlock	= 64*1024,
60*74a4d8c2SCharles.Forsyth 	HistSize	= HistBlock + HistSlop,
61*74a4d8c2SCharles.Forsyth 
62*74a4d8c2SCharles.Forsyth 	HashLog		= 13,
63*74a4d8c2SCharles.Forsyth 	HashSize	= 1<<HashLog,
64*74a4d8c2SCharles.Forsyth 
65*74a4d8c2SCharles.Forsyth 	MaxOffCode	= 256,			/* biggest offset looked up in direct table */
66*74a4d8c2SCharles.Forsyth 
67*74a4d8c2SCharles.Forsyth 	EstLitBits	= 8,
68*74a4d8c2SCharles.Forsyth 	EstLenBits	= 4,
69*74a4d8c2SCharles.Forsyth 	EstOffBits	= 5,
70*74a4d8c2SCharles.Forsyth };
71*74a4d8c2SCharles.Forsyth 
72*74a4d8c2SCharles.Forsyth /*
73*74a4d8c2SCharles.Forsyth  * knuth vol. 3 multiplicative hashing
74*74a4d8c2SCharles.Forsyth  * each byte x chosen according to rules
75*74a4d8c2SCharles.Forsyth  * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
76*74a4d8c2SCharles.Forsyth  * with reasonable spread between the bytes & their complements
77*74a4d8c2SCharles.Forsyth  *
78*74a4d8c2SCharles.Forsyth  * the 3 byte value appears to be as almost good as the 4 byte value,
79*74a4d8c2SCharles.Forsyth  * and might be faster on some machines
80*74a4d8c2SCharles.Forsyth  */
81*74a4d8c2SCharles.Forsyth /*
82*74a4d8c2SCharles.Forsyth #define hashit(c)	(((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
83*74a4d8c2SCharles.Forsyth */
84*74a4d8c2SCharles.Forsyth #define hashit(c)	((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
85*74a4d8c2SCharles.Forsyth 
86*74a4d8c2SCharles.Forsyth /*
87*74a4d8c2SCharles.Forsyth  * lempel-ziv style compression state
88*74a4d8c2SCharles.Forsyth  */
89*74a4d8c2SCharles.Forsyth struct LZstate
90*74a4d8c2SCharles.Forsyth {
91*74a4d8c2SCharles.Forsyth 	uchar	hist[HistSize];
92*74a4d8c2SCharles.Forsyth 	ulong	pos;				/* current location in history buffer */
93*74a4d8c2SCharles.Forsyth 	ulong	avail;				/* data available after pos */
94*74a4d8c2SCharles.Forsyth 	int	eof;
95*74a4d8c2SCharles.Forsyth 	ushort	hash[HashSize];			/* hash chains */
96*74a4d8c2SCharles.Forsyth 	ushort	nexts[MaxOff];
97*74a4d8c2SCharles.Forsyth 	int	now;				/* pos in hash chains */
98*74a4d8c2SCharles.Forsyth 	int	dot;				/* dawn of time in history */
99*74a4d8c2SCharles.Forsyth 	int	prevlen;			/* lazy matching state */
100*74a4d8c2SCharles.Forsyth 	int	prevoff;
101*74a4d8c2SCharles.Forsyth 	int	maxcheck;			/* compressor tuning */
102*74a4d8c2SCharles.Forsyth 
103*74a4d8c2SCharles.Forsyth 	uchar	obuf[DeflateOut];
104*74a4d8c2SCharles.Forsyth 	uchar	*out;				/* current position in the output buffer */
105*74a4d8c2SCharles.Forsyth 	uchar	*eout;
106*74a4d8c2SCharles.Forsyth 	ulong	bits;				/* bit shift register */
107*74a4d8c2SCharles.Forsyth 	int	nbits;
108*74a4d8c2SCharles.Forsyth 	int	rbad;				/* got an error reading the buffer */
109*74a4d8c2SCharles.Forsyth 	int	wbad;				/* got an error writing the buffer */
110*74a4d8c2SCharles.Forsyth 	int	(*w)(void*, void*, int);
111*74a4d8c2SCharles.Forsyth 	void	*wr;
112*74a4d8c2SCharles.Forsyth 
113*74a4d8c2SCharles.Forsyth 	ulong	totr;				/* total input size */
114*74a4d8c2SCharles.Forsyth 	ulong	totw;				/* total output size */
115*74a4d8c2SCharles.Forsyth 	int	debug;
116*74a4d8c2SCharles.Forsyth };
117*74a4d8c2SCharles.Forsyth 
118*74a4d8c2SCharles.Forsyth struct LZblock
119*74a4d8c2SCharles.Forsyth {
120*74a4d8c2SCharles.Forsyth 	ushort	parse[DeflateMaxBlock / 2 + 1];
121*74a4d8c2SCharles.Forsyth 	int	lastv;				/* value being constucted for parse */
122*74a4d8c2SCharles.Forsyth 	ulong	litlencount[Nlitlen];
123*74a4d8c2SCharles.Forsyth 	ulong	offcount[Noff];
124*74a4d8c2SCharles.Forsyth 	ushort	*eparse;			/* limit for parse table */
125*74a4d8c2SCharles.Forsyth 	int	bytes;				/* consumed from the input */
126*74a4d8c2SCharles.Forsyth 	int	excost;				/* cost of encoding extra len & off bits */
127*74a4d8c2SCharles.Forsyth };
128*74a4d8c2SCharles.Forsyth 
129*74a4d8c2SCharles.Forsyth /*
130*74a4d8c2SCharles.Forsyth  * huffman code table
131*74a4d8c2SCharles.Forsyth  */
132*74a4d8c2SCharles.Forsyth struct Huff
133*74a4d8c2SCharles.Forsyth {
134*74a4d8c2SCharles.Forsyth 	short	bits;				/* length of the code */
135*74a4d8c2SCharles.Forsyth 	ushort	encode;				/* the code */
136*74a4d8c2SCharles.Forsyth };
137*74a4d8c2SCharles.Forsyth 
138*74a4d8c2SCharles.Forsyth /*
139*74a4d8c2SCharles.Forsyth  * encoding of dynamic huffman trees
140*74a4d8c2SCharles.Forsyth  */
141*74a4d8c2SCharles.Forsyth struct Dyncode
142*74a4d8c2SCharles.Forsyth {
143*74a4d8c2SCharles.Forsyth 	int	nlit;
144*74a4d8c2SCharles.Forsyth 	int	noff;
145*74a4d8c2SCharles.Forsyth 	int	nclen;
146*74a4d8c2SCharles.Forsyth 	int	ncode;
147*74a4d8c2SCharles.Forsyth 	Huff	codetab[Nclen];
148*74a4d8c2SCharles.Forsyth 	uchar	codes[Nlitlen+Noff];
149*74a4d8c2SCharles.Forsyth 	uchar	codeaux[Nlitlen+Noff];
150*74a4d8c2SCharles.Forsyth };
151*74a4d8c2SCharles.Forsyth 
152*74a4d8c2SCharles.Forsyth static	int	deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
153*74a4d8c2SCharles.Forsyth static	int	lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
154*74a4d8c2SCharles.Forsyth static	void	wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
155*74a4d8c2SCharles.Forsyth static	int	bitcost(Huff*, ulong*, int);
156*74a4d8c2SCharles.Forsyth static	int	huffcodes(Dyncode*, Huff*, Huff*);
157*74a4d8c2SCharles.Forsyth static	void	wrdyncode(LZstate*, Dyncode*);
158*74a4d8c2SCharles.Forsyth static	void	lzput(LZstate*, ulong bits, int nbits);
159*74a4d8c2SCharles.Forsyth static	void	lzflushbits(LZstate*);
160*74a4d8c2SCharles.Forsyth static	void	lzflush(LZstate *lz);
161*74a4d8c2SCharles.Forsyth static	void	lzwrite(LZstate *lz, void *buf, int n);
162*74a4d8c2SCharles.Forsyth 
163*74a4d8c2SCharles.Forsyth static	int	hufftabinit(Huff*, int, ulong*, int);
164*74a4d8c2SCharles.Forsyth static	int	mkgzprecode(Huff*, ulong *, int, int);
165*74a4d8c2SCharles.Forsyth 
166*74a4d8c2SCharles.Forsyth static	int	mkprecode(Huff*, ulong *, int, int, ulong*);
167*74a4d8c2SCharles.Forsyth static	void	nextchain(Chains*, int);
168*74a4d8c2SCharles.Forsyth static	void	leafsort(ulong*, ushort*, int, int);
169*74a4d8c2SCharles.Forsyth 
170*74a4d8c2SCharles.Forsyth /* conversion from len to code word */
171*74a4d8c2SCharles.Forsyth static int lencode[MaxMatch];
172*74a4d8c2SCharles.Forsyth 
173*74a4d8c2SCharles.Forsyth /*
174*74a4d8c2SCharles.Forsyth  * conversion from off to code word
175*74a4d8c2SCharles.Forsyth  * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
176*74a4d8c2SCharles.Forsyth */
177*74a4d8c2SCharles.Forsyth static int offcode[MaxOffCode];
178*74a4d8c2SCharles.Forsyth static int bigoffcode[256];
179*74a4d8c2SCharles.Forsyth 
180*74a4d8c2SCharles.Forsyth /* litlen code words LenStart-285 extra bits */
181*74a4d8c2SCharles.Forsyth static int litlenbase[Nlitlen-LenStart];
182*74a4d8c2SCharles.Forsyth static int litlenextra[Nlitlen-LenStart] =
183*74a4d8c2SCharles.Forsyth {
184*74a4d8c2SCharles.Forsyth /* 257 */	0, 0, 0,
185*74a4d8c2SCharles.Forsyth /* 260 */	0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
186*74a4d8c2SCharles.Forsyth /* 270 */	2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
187*74a4d8c2SCharles.Forsyth /* 280 */	4, 5, 5, 5, 5, 0, 0, 0
188*74a4d8c2SCharles.Forsyth };
189*74a4d8c2SCharles.Forsyth 
190*74a4d8c2SCharles.Forsyth /* offset code word extra bits */
191*74a4d8c2SCharles.Forsyth static int offbase[Noff];
192*74a4d8c2SCharles.Forsyth static int offextra[] =
193*74a4d8c2SCharles.Forsyth {
194*74a4d8c2SCharles.Forsyth 	0,  0,  0,  0,  1,  1,  2,  2,  3,  3,
195*74a4d8c2SCharles.Forsyth 	4,  4,  5,  5,  6,  6,  7,  7,  8,  8,
196*74a4d8c2SCharles.Forsyth 	9,  9,  10, 10, 11, 11, 12, 12, 13, 13,
197*74a4d8c2SCharles.Forsyth 	0,  0,
198*74a4d8c2SCharles.Forsyth };
199*74a4d8c2SCharles.Forsyth 
200*74a4d8c2SCharles.Forsyth /* order code lengths */
201*74a4d8c2SCharles.Forsyth static int clenorder[Nclen] =
202*74a4d8c2SCharles.Forsyth {
203*74a4d8c2SCharles.Forsyth         16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
204*74a4d8c2SCharles.Forsyth };
205*74a4d8c2SCharles.Forsyth 
206*74a4d8c2SCharles.Forsyth /* static huffman tables */
207*74a4d8c2SCharles.Forsyth static	Huff	litlentab[Nlitlen];
208*74a4d8c2SCharles.Forsyth static	Huff	offtab[Noff];
209*74a4d8c2SCharles.Forsyth static	Huff	hofftab[Noff];
210*74a4d8c2SCharles.Forsyth 
211*74a4d8c2SCharles.Forsyth /* bit reversal for brain dead endian swap in huffman codes */
212*74a4d8c2SCharles.Forsyth static	uchar	revtab[256];
213*74a4d8c2SCharles.Forsyth static	ulong	nlits;
214*74a4d8c2SCharles.Forsyth static	ulong	nmatches;
215*74a4d8c2SCharles.Forsyth 
216*74a4d8c2SCharles.Forsyth int
deflateinit(void)217*74a4d8c2SCharles.Forsyth deflateinit(void)
218*74a4d8c2SCharles.Forsyth {
219*74a4d8c2SCharles.Forsyth 	ulong bitcount[MaxHuffBits];
220*74a4d8c2SCharles.Forsyth 	int i, j, ci, n;
221*74a4d8c2SCharles.Forsyth 
222*74a4d8c2SCharles.Forsyth 	/* byte reverse table */
223*74a4d8c2SCharles.Forsyth 	for(i=0; i<256; i++)
224*74a4d8c2SCharles.Forsyth 		for(j=0; j<8; j++)
225*74a4d8c2SCharles.Forsyth 			if(i & (1<<j))
226*74a4d8c2SCharles.Forsyth 				revtab[i] |= 0x80 >> j;
227*74a4d8c2SCharles.Forsyth 
228*74a4d8c2SCharles.Forsyth 	/* static Litlen bit lengths */
229*74a4d8c2SCharles.Forsyth 	for(i=0; i<144; i++)
230*74a4d8c2SCharles.Forsyth 		litlentab[i].bits = 8;
231*74a4d8c2SCharles.Forsyth 	for(i=144; i<256; i++)
232*74a4d8c2SCharles.Forsyth 		litlentab[i].bits = 9;
233*74a4d8c2SCharles.Forsyth 	for(i=256; i<280; i++)
234*74a4d8c2SCharles.Forsyth 		litlentab[i].bits = 7;
235*74a4d8c2SCharles.Forsyth 	for(i=280; i<Nlitlen; i++)
236*74a4d8c2SCharles.Forsyth 		litlentab[i].bits = 8;
237*74a4d8c2SCharles.Forsyth 
238*74a4d8c2SCharles.Forsyth 	memset(bitcount, 0, sizeof(bitcount));
239*74a4d8c2SCharles.Forsyth 	bitcount[8] += 144 - 0;
240*74a4d8c2SCharles.Forsyth 	bitcount[9] += 256 - 144;
241*74a4d8c2SCharles.Forsyth 	bitcount[7] += 280 - 256;
242*74a4d8c2SCharles.Forsyth 	bitcount[8] += Nlitlen - 280;
243*74a4d8c2SCharles.Forsyth 
244*74a4d8c2SCharles.Forsyth 	if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
245*74a4d8c2SCharles.Forsyth 		return FlateInternal;
246*74a4d8c2SCharles.Forsyth 
247*74a4d8c2SCharles.Forsyth 	/* static offset bit lengths */
248*74a4d8c2SCharles.Forsyth 	for(i = 0; i < Noff; i++)
249*74a4d8c2SCharles.Forsyth 		offtab[i].bits = 5;
250*74a4d8c2SCharles.Forsyth 
251*74a4d8c2SCharles.Forsyth 	memset(bitcount, 0, sizeof(bitcount));
252*74a4d8c2SCharles.Forsyth 	bitcount[5] = Noff;
253*74a4d8c2SCharles.Forsyth 
254*74a4d8c2SCharles.Forsyth 	if(!hufftabinit(offtab, Noff, bitcount, 5))
255*74a4d8c2SCharles.Forsyth 		return FlateInternal;
256*74a4d8c2SCharles.Forsyth 
257*74a4d8c2SCharles.Forsyth 	bitcount[0] = 0;
258*74a4d8c2SCharles.Forsyth 	bitcount[1] = 0;
259*74a4d8c2SCharles.Forsyth 	if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
260*74a4d8c2SCharles.Forsyth 		return FlateInternal;
261*74a4d8c2SCharles.Forsyth 
262*74a4d8c2SCharles.Forsyth 	/* conversion tables for lens & offs to codes */
263*74a4d8c2SCharles.Forsyth 	ci = 0;
264*74a4d8c2SCharles.Forsyth 	for(i = LenStart; i < 286; i++){
265*74a4d8c2SCharles.Forsyth 		n = ci + (1 << litlenextra[i - LenStart]);
266*74a4d8c2SCharles.Forsyth 		litlenbase[i - LenStart] = ci;
267*74a4d8c2SCharles.Forsyth 		for(; ci < n; ci++)
268*74a4d8c2SCharles.Forsyth 			lencode[ci] = i;
269*74a4d8c2SCharles.Forsyth 	}
270*74a4d8c2SCharles.Forsyth 	/* patch up special case for len MaxMatch */
271*74a4d8c2SCharles.Forsyth 	lencode[MaxMatch-MinMatch] = 285;
272*74a4d8c2SCharles.Forsyth 	litlenbase[285-LenStart] = MaxMatch-MinMatch;
273*74a4d8c2SCharles.Forsyth 
274*74a4d8c2SCharles.Forsyth 	ci = 0;
275*74a4d8c2SCharles.Forsyth 	for(i = 0; i < 16; i++){
276*74a4d8c2SCharles.Forsyth 		n = ci + (1 << offextra[i]);
277*74a4d8c2SCharles.Forsyth 		offbase[i] = ci;
278*74a4d8c2SCharles.Forsyth 		for(; ci < n; ci++)
279*74a4d8c2SCharles.Forsyth 			offcode[ci] = i;
280*74a4d8c2SCharles.Forsyth 	}
281*74a4d8c2SCharles.Forsyth 
282*74a4d8c2SCharles.Forsyth 	ci = ci >> 7;
283*74a4d8c2SCharles.Forsyth 	for(; i < 30; i++){
284*74a4d8c2SCharles.Forsyth 		n = ci + (1 << (offextra[i] - 7));
285*74a4d8c2SCharles.Forsyth 		offbase[i] = ci << 7;
286*74a4d8c2SCharles.Forsyth 		for(; ci < n; ci++)
287*74a4d8c2SCharles.Forsyth 			bigoffcode[ci] = i;
288*74a4d8c2SCharles.Forsyth 	}
289*74a4d8c2SCharles.Forsyth 	return FlateOk;
290*74a4d8c2SCharles.Forsyth }
291*74a4d8c2SCharles.Forsyth 
292*74a4d8c2SCharles.Forsyth static void
deflatereset(LZstate * lz,int level,int debug)293*74a4d8c2SCharles.Forsyth deflatereset(LZstate *lz, int level, int debug)
294*74a4d8c2SCharles.Forsyth {
295*74a4d8c2SCharles.Forsyth 	memset(lz->nexts, 0, sizeof lz->nexts);
296*74a4d8c2SCharles.Forsyth 	memset(lz->hash, 0, sizeof lz->hash);
297*74a4d8c2SCharles.Forsyth 	lz->totr = 0;
298*74a4d8c2SCharles.Forsyth 	lz->totw = 0;
299*74a4d8c2SCharles.Forsyth 	lz->pos = 0;
300*74a4d8c2SCharles.Forsyth 	lz->avail = 0;
301*74a4d8c2SCharles.Forsyth 	lz->out = lz->obuf;
302*74a4d8c2SCharles.Forsyth 	lz->eout = &lz->obuf[DeflateOut];
303*74a4d8c2SCharles.Forsyth 	lz->prevlen = MinMatch - 1;
304*74a4d8c2SCharles.Forsyth 	lz->prevoff = 0;
305*74a4d8c2SCharles.Forsyth 	lz->now = MaxOff + 1;
306*74a4d8c2SCharles.Forsyth 	lz->dot = lz->now;
307*74a4d8c2SCharles.Forsyth 	lz->bits = 0;
308*74a4d8c2SCharles.Forsyth 	lz->nbits = 0;
309*74a4d8c2SCharles.Forsyth 	lz->maxcheck = (1 << level);
310*74a4d8c2SCharles.Forsyth 	lz->maxcheck -= lz->maxcheck >> 2;
311*74a4d8c2SCharles.Forsyth 	if(lz->maxcheck < 2)
312*74a4d8c2SCharles.Forsyth 		lz->maxcheck = 2;
313*74a4d8c2SCharles.Forsyth 	else if(lz->maxcheck > 1024)
314*74a4d8c2SCharles.Forsyth 		lz->maxcheck = 1024;
315*74a4d8c2SCharles.Forsyth 
316*74a4d8c2SCharles.Forsyth 	lz->debug = debug;
317*74a4d8c2SCharles.Forsyth }
318*74a4d8c2SCharles.Forsyth 
319*74a4d8c2SCharles.Forsyth int
deflate(void * wr,int (* w)(void *,void *,int),void * rr,int (* r)(void *,void *,int),int level,int debug)320*74a4d8c2SCharles.Forsyth deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
321*74a4d8c2SCharles.Forsyth {
322*74a4d8c2SCharles.Forsyth 	LZstate *lz;
323*74a4d8c2SCharles.Forsyth 	LZblock *lzb;
324*74a4d8c2SCharles.Forsyth 	int ok;
325*74a4d8c2SCharles.Forsyth 
326*74a4d8c2SCharles.Forsyth 	lz = malloc(sizeof *lz + sizeof *lzb);
327*74a4d8c2SCharles.Forsyth 	if(lz == nil)
328*74a4d8c2SCharles.Forsyth 		return FlateNoMem;
329*74a4d8c2SCharles.Forsyth 	lzb = (LZblock*)&lz[1];
330*74a4d8c2SCharles.Forsyth 
331*74a4d8c2SCharles.Forsyth 	deflatereset(lz, level, debug);
332*74a4d8c2SCharles.Forsyth 	lz->w = w;
333*74a4d8c2SCharles.Forsyth 	lz->wr = wr;
334*74a4d8c2SCharles.Forsyth 	lz->wbad = 0;
335*74a4d8c2SCharles.Forsyth 	lz->rbad = 0;
336*74a4d8c2SCharles.Forsyth 	lz->eof = 0;
337*74a4d8c2SCharles.Forsyth 	ok = FlateOk;
338*74a4d8c2SCharles.Forsyth 	while(!lz->eof || lz->avail){
339*74a4d8c2SCharles.Forsyth 		ok = deflateb(lz, lzb, rr, r);
340*74a4d8c2SCharles.Forsyth 		if(ok != FlateOk)
341*74a4d8c2SCharles.Forsyth 			break;
342*74a4d8c2SCharles.Forsyth 	}
343*74a4d8c2SCharles.Forsyth 	if(ok == FlateOk && lz->rbad)
344*74a4d8c2SCharles.Forsyth 		ok = FlateInputFail;
345*74a4d8c2SCharles.Forsyth 	if(ok == FlateOk && lz->wbad)
346*74a4d8c2SCharles.Forsyth 		ok = FlateOutputFail;
347*74a4d8c2SCharles.Forsyth 	free(lz);
348*74a4d8c2SCharles.Forsyth 	return ok;
349*74a4d8c2SCharles.Forsyth }
350*74a4d8c2SCharles.Forsyth 
351*74a4d8c2SCharles.Forsyth static int
deflateb(LZstate * lz,LZblock * lzb,void * rr,int (* r)(void *,void *,int))352*74a4d8c2SCharles.Forsyth deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
353*74a4d8c2SCharles.Forsyth {
354*74a4d8c2SCharles.Forsyth 	Dyncode dyncode, hdyncode;
355*74a4d8c2SCharles.Forsyth 	Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
356*74a4d8c2SCharles.Forsyth 	ulong litcount[Nlitlen];
357*74a4d8c2SCharles.Forsyth 	long nunc, ndyn, nfix, nhuff;
358*74a4d8c2SCharles.Forsyth 	uchar *slop, *hslop;
359*74a4d8c2SCharles.Forsyth 	ulong ep;
360*74a4d8c2SCharles.Forsyth 	int i, n, m, mm, nslop;
361*74a4d8c2SCharles.Forsyth 
362*74a4d8c2SCharles.Forsyth 	memset(lzb->litlencount, 0, sizeof lzb->litlencount);
363*74a4d8c2SCharles.Forsyth 	memset(lzb->offcount, 0, sizeof lzb->offcount);
364*74a4d8c2SCharles.Forsyth 	lzb->litlencount[DeflateEob]++;
365*74a4d8c2SCharles.Forsyth 
366*74a4d8c2SCharles.Forsyth 	lzb->bytes = 0;
367*74a4d8c2SCharles.Forsyth 	lzb->eparse = lzb->parse;
368*74a4d8c2SCharles.Forsyth 	lzb->lastv = 0;
369*74a4d8c2SCharles.Forsyth 	lzb->excost = 0;
370*74a4d8c2SCharles.Forsyth 
371*74a4d8c2SCharles.Forsyth 	slop = &lz->hist[lz->pos];
372*74a4d8c2SCharles.Forsyth 	n = lz->avail;
373*74a4d8c2SCharles.Forsyth 	while(n < DeflateBlock && (!lz->eof || lz->avail)){
374*74a4d8c2SCharles.Forsyth 		/*
375*74a4d8c2SCharles.Forsyth 		 * fill the buffer as much as possible,
376*74a4d8c2SCharles.Forsyth 		 * while leaving room for MaxOff history behind lz->pos,
377*74a4d8c2SCharles.Forsyth 		 * and not reading more than we can handle.
378*74a4d8c2SCharles.Forsyth 		 *
379*74a4d8c2SCharles.Forsyth 		 * make sure we read at least HistSlop bytes.
380*74a4d8c2SCharles.Forsyth 		 */
381*74a4d8c2SCharles.Forsyth 		if(!lz->eof){
382*74a4d8c2SCharles.Forsyth 			ep = lz->pos + lz->avail;
383*74a4d8c2SCharles.Forsyth 			if(ep >= HistBlock)
384*74a4d8c2SCharles.Forsyth 				ep -= HistBlock;
385*74a4d8c2SCharles.Forsyth 			m = HistBlock - MaxOff - lz->avail;
386*74a4d8c2SCharles.Forsyth 			if(m > HistBlock - n)
387*74a4d8c2SCharles.Forsyth 				m = HistBlock - n;
388*74a4d8c2SCharles.Forsyth 			if(m > (HistBlock + HistSlop) - ep)
389*74a4d8c2SCharles.Forsyth 				m = (HistBlock + HistSlop) - ep;
390*74a4d8c2SCharles.Forsyth 			if(m & ~(BlockSize - 1))
391*74a4d8c2SCharles.Forsyth 				m &= ~(BlockSize - 1);
392*74a4d8c2SCharles.Forsyth 
393*74a4d8c2SCharles.Forsyth 			/*
394*74a4d8c2SCharles.Forsyth 			 * be nice to the caller: stop reads that are too small.
395*74a4d8c2SCharles.Forsyth 			 * can only get here when we've already filled the buffer some
396*74a4d8c2SCharles.Forsyth 			 */
397*74a4d8c2SCharles.Forsyth 			if(m < HistSlop){
398*74a4d8c2SCharles.Forsyth 				if(!m || !lzb->bytes)
399*74a4d8c2SCharles.Forsyth 					return FlateInternal;
400*74a4d8c2SCharles.Forsyth 				break;
401*74a4d8c2SCharles.Forsyth 			}
402*74a4d8c2SCharles.Forsyth 
403*74a4d8c2SCharles.Forsyth 			mm = (*r)(rr, &lz->hist[ep], m);
404*74a4d8c2SCharles.Forsyth 			if(mm > 0){
405*74a4d8c2SCharles.Forsyth 				/*
406*74a4d8c2SCharles.Forsyth 				 * wrap data to end if we're read it from the beginning
407*74a4d8c2SCharles.Forsyth 				 * this way, we don't have to wrap searches.
408*74a4d8c2SCharles.Forsyth 				 *
409*74a4d8c2SCharles.Forsyth 				 * wrap reads past the end to the beginning.
410*74a4d8c2SCharles.Forsyth 				 * this way, we can guarantee minimum size reads.
411*74a4d8c2SCharles.Forsyth 				 */
412*74a4d8c2SCharles.Forsyth 				if(ep < HistSlop)
413*74a4d8c2SCharles.Forsyth 					memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
414*74a4d8c2SCharles.Forsyth 				else if(ep + mm > HistBlock)
415*74a4d8c2SCharles.Forsyth 					memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
416*74a4d8c2SCharles.Forsyth 
417*74a4d8c2SCharles.Forsyth 				lz->totr += mm;
418*74a4d8c2SCharles.Forsyth 				n += mm;
419*74a4d8c2SCharles.Forsyth 				lz->avail += mm;
420*74a4d8c2SCharles.Forsyth 			}else{
421*74a4d8c2SCharles.Forsyth 				if(mm < 0)
422*74a4d8c2SCharles.Forsyth 					lz->rbad = 1;
423*74a4d8c2SCharles.Forsyth 				lz->eof = 1;
424*74a4d8c2SCharles.Forsyth 			}
425*74a4d8c2SCharles.Forsyth 		}
426*74a4d8c2SCharles.Forsyth 		ep = lz->pos + lz->avail;
427*74a4d8c2SCharles.Forsyth 		if(ep > HistSize)
428*74a4d8c2SCharles.Forsyth 			ep = HistSize;
429*74a4d8c2SCharles.Forsyth 		if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
430*74a4d8c2SCharles.Forsyth 			ep = lz->pos + DeflateMaxBlock - lzb->bytes;
431*74a4d8c2SCharles.Forsyth 		m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
432*74a4d8c2SCharles.Forsyth 		lzb->bytes += m;
433*74a4d8c2SCharles.Forsyth 		lz->pos = (lz->pos + m) & (HistBlock - 1);
434*74a4d8c2SCharles.Forsyth 		lz->avail -= m;
435*74a4d8c2SCharles.Forsyth 	}
436*74a4d8c2SCharles.Forsyth 	if(lzb->lastv)
437*74a4d8c2SCharles.Forsyth 		*lzb->eparse++ = lzb->lastv;
438*74a4d8c2SCharles.Forsyth 	if(lzb->eparse > lzb->parse + nelem(lzb->parse))
439*74a4d8c2SCharles.Forsyth 		return FlateInternal;
440*74a4d8c2SCharles.Forsyth 	nunc = lzb->bytes;
441*74a4d8c2SCharles.Forsyth 
442*74a4d8c2SCharles.Forsyth 	if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
443*74a4d8c2SCharles.Forsyth 	|| !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
444*74a4d8c2SCharles.Forsyth 		return FlateInternal;
445*74a4d8c2SCharles.Forsyth 
446*74a4d8c2SCharles.Forsyth 	ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
447*74a4d8c2SCharles.Forsyth 	if(ndyn < 0)
448*74a4d8c2SCharles.Forsyth 		return FlateInternal;
449*74a4d8c2SCharles.Forsyth 	ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
450*74a4d8c2SCharles.Forsyth 		+ bitcost(dofftab, lzb->offcount, Noff)
451*74a4d8c2SCharles.Forsyth 		+ lzb->excost;
452*74a4d8c2SCharles.Forsyth 
453*74a4d8c2SCharles.Forsyth 	memset(litcount, 0, sizeof litcount);
454*74a4d8c2SCharles.Forsyth 
455*74a4d8c2SCharles.Forsyth 	nslop = nunc;
456*74a4d8c2SCharles.Forsyth 	if(nslop > &lz->hist[HistSize] - slop)
457*74a4d8c2SCharles.Forsyth 		nslop = &lz->hist[HistSize] - slop;
458*74a4d8c2SCharles.Forsyth 
459*74a4d8c2SCharles.Forsyth 	for(i = 0; i < nslop; i++)
460*74a4d8c2SCharles.Forsyth 		litcount[slop[i]]++;
461*74a4d8c2SCharles.Forsyth 	hslop = &lz->hist[HistSlop - nslop];
462*74a4d8c2SCharles.Forsyth 	for(; i < nunc; i++)
463*74a4d8c2SCharles.Forsyth 		litcount[hslop[i]]++;
464*74a4d8c2SCharles.Forsyth 	litcount[DeflateEob]++;
465*74a4d8c2SCharles.Forsyth 
466*74a4d8c2SCharles.Forsyth 	if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
467*74a4d8c2SCharles.Forsyth 		return FlateInternal;
468*74a4d8c2SCharles.Forsyth 	nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
469*74a4d8c2SCharles.Forsyth 	if(nhuff < 0)
470*74a4d8c2SCharles.Forsyth 		return FlateInternal;
471*74a4d8c2SCharles.Forsyth 	nhuff += bitcost(hlitlentab, litcount, Nlitlen);
472*74a4d8c2SCharles.Forsyth 
473*74a4d8c2SCharles.Forsyth 	nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
474*74a4d8c2SCharles.Forsyth 		+ bitcost(offtab, lzb->offcount, Noff)
475*74a4d8c2SCharles.Forsyth 		+ lzb->excost;
476*74a4d8c2SCharles.Forsyth 
477*74a4d8c2SCharles.Forsyth 	lzput(lz, lz->eof && !lz->avail, 1);
478*74a4d8c2SCharles.Forsyth 
479*74a4d8c2SCharles.Forsyth 	if(lz->debug){
480*74a4d8c2SCharles.Forsyth 		fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
481*74a4d8c2SCharles.Forsyth 			nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
482*74a4d8c2SCharles.Forsyth 		fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
483*74a4d8c2SCharles.Forsyth 	}
484*74a4d8c2SCharles.Forsyth 
485*74a4d8c2SCharles.Forsyth 	if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
486*74a4d8c2SCharles.Forsyth 		lzput(lz, DeflateUnc, 2);
487*74a4d8c2SCharles.Forsyth 		lzflushbits(lz);
488*74a4d8c2SCharles.Forsyth 
489*74a4d8c2SCharles.Forsyth 		lzput(lz, nunc & 0xff, 8);
490*74a4d8c2SCharles.Forsyth 		lzput(lz, (nunc >> 8) & 0xff, 8);
491*74a4d8c2SCharles.Forsyth 		lzput(lz, ~nunc & 0xff, 8);
492*74a4d8c2SCharles.Forsyth 		lzput(lz, (~nunc >> 8) & 0xff, 8);
493*74a4d8c2SCharles.Forsyth 		lzflush(lz);
494*74a4d8c2SCharles.Forsyth 
495*74a4d8c2SCharles.Forsyth 		lzwrite(lz, slop, nslop);
496*74a4d8c2SCharles.Forsyth 		lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
497*74a4d8c2SCharles.Forsyth 	}else if(ndyn < nfix && ndyn < nhuff){
498*74a4d8c2SCharles.Forsyth 		lzput(lz, DeflateDyn, 2);
499*74a4d8c2SCharles.Forsyth 
500*74a4d8c2SCharles.Forsyth 		wrdyncode(lz, &dyncode);
501*74a4d8c2SCharles.Forsyth 		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
502*74a4d8c2SCharles.Forsyth 		lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
503*74a4d8c2SCharles.Forsyth 	}else if(nhuff < nfix){
504*74a4d8c2SCharles.Forsyth 		lzput(lz, DeflateDyn, 2);
505*74a4d8c2SCharles.Forsyth 
506*74a4d8c2SCharles.Forsyth 		wrdyncode(lz, &hdyncode);
507*74a4d8c2SCharles.Forsyth 
508*74a4d8c2SCharles.Forsyth 		m = 0;
509*74a4d8c2SCharles.Forsyth 		for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
510*74a4d8c2SCharles.Forsyth 			lzb->parse[m++] = MaxLitRun;
511*74a4d8c2SCharles.Forsyth 		lzb->parse[m++] = i;
512*74a4d8c2SCharles.Forsyth 
513*74a4d8c2SCharles.Forsyth 		wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
514*74a4d8c2SCharles.Forsyth 		lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
515*74a4d8c2SCharles.Forsyth 	}else{
516*74a4d8c2SCharles.Forsyth 		lzput(lz, DeflateFix, 2);
517*74a4d8c2SCharles.Forsyth 
518*74a4d8c2SCharles.Forsyth 		wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
519*74a4d8c2SCharles.Forsyth 		lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
520*74a4d8c2SCharles.Forsyth 	}
521*74a4d8c2SCharles.Forsyth 
522*74a4d8c2SCharles.Forsyth 	if(lz->eof && !lz->avail){
523*74a4d8c2SCharles.Forsyth 		lzflushbits(lz);
524*74a4d8c2SCharles.Forsyth 		lzflush(lz);
525*74a4d8c2SCharles.Forsyth 	}
526*74a4d8c2SCharles.Forsyth 	return FlateOk;
527*74a4d8c2SCharles.Forsyth }
528*74a4d8c2SCharles.Forsyth 
529*74a4d8c2SCharles.Forsyth static void
lzwrite(LZstate * lz,void * buf,int n)530*74a4d8c2SCharles.Forsyth lzwrite(LZstate *lz, void *buf, int n)
531*74a4d8c2SCharles.Forsyth {
532*74a4d8c2SCharles.Forsyth 	int nw;
533*74a4d8c2SCharles.Forsyth 
534*74a4d8c2SCharles.Forsyth 	if(n && lz->w){
535*74a4d8c2SCharles.Forsyth 		nw = (*lz->w)(lz->wr, buf, n);
536*74a4d8c2SCharles.Forsyth 		if(nw != n){
537*74a4d8c2SCharles.Forsyth 			lz->w = nil;
538*74a4d8c2SCharles.Forsyth 			lz->wbad = 1;
539*74a4d8c2SCharles.Forsyth 		}else
540*74a4d8c2SCharles.Forsyth 			lz->totw += n;
541*74a4d8c2SCharles.Forsyth 	}
542*74a4d8c2SCharles.Forsyth }
543*74a4d8c2SCharles.Forsyth 
544*74a4d8c2SCharles.Forsyth static void
lzflush(LZstate * lz)545*74a4d8c2SCharles.Forsyth lzflush(LZstate *lz)
546*74a4d8c2SCharles.Forsyth {
547*74a4d8c2SCharles.Forsyth 	lzwrite(lz, lz->obuf, lz->out - lz->obuf);
548*74a4d8c2SCharles.Forsyth 	lz->out = lz->obuf;
549*74a4d8c2SCharles.Forsyth }
550*74a4d8c2SCharles.Forsyth 
551*74a4d8c2SCharles.Forsyth static void
lzput(LZstate * lz,ulong bits,int nbits)552*74a4d8c2SCharles.Forsyth lzput(LZstate *lz, ulong bits, int nbits)
553*74a4d8c2SCharles.Forsyth {
554*74a4d8c2SCharles.Forsyth 	bits = (bits << lz->nbits) | lz->bits;
555*74a4d8c2SCharles.Forsyth 	for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
556*74a4d8c2SCharles.Forsyth 		*lz->out++ = bits;
557*74a4d8c2SCharles.Forsyth 		if(lz->out == lz->eout)
558*74a4d8c2SCharles.Forsyth 			lzflush(lz);
559*74a4d8c2SCharles.Forsyth 		bits >>= 8;
560*74a4d8c2SCharles.Forsyth 	}
561*74a4d8c2SCharles.Forsyth 	lz->bits = bits;
562*74a4d8c2SCharles.Forsyth 	lz->nbits = nbits;
563*74a4d8c2SCharles.Forsyth }
564*74a4d8c2SCharles.Forsyth 
565*74a4d8c2SCharles.Forsyth static void
lzflushbits(LZstate * lz)566*74a4d8c2SCharles.Forsyth lzflushbits(LZstate *lz)
567*74a4d8c2SCharles.Forsyth {
568*74a4d8c2SCharles.Forsyth 	if(lz->nbits)
569*74a4d8c2SCharles.Forsyth 		lzput(lz, 0, 8 - (lz->nbits & 7));
570*74a4d8c2SCharles.Forsyth }
571*74a4d8c2SCharles.Forsyth 
572*74a4d8c2SCharles.Forsyth /*
573*74a4d8c2SCharles.Forsyth  * write out a block of n samples,
574*74a4d8c2SCharles.Forsyth  * given lz encoding and counts for huffman tables
575*74a4d8c2SCharles.Forsyth  */
576*74a4d8c2SCharles.Forsyth static void
wrblock(LZstate * out,int litoff,ushort * soff,ushort * eoff,Huff * litlentab,Huff * offtab)577*74a4d8c2SCharles.Forsyth wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
578*74a4d8c2SCharles.Forsyth {
579*74a4d8c2SCharles.Forsyth 	ushort *off;
580*74a4d8c2SCharles.Forsyth 	int i, run, offset, lit, len, c;
581*74a4d8c2SCharles.Forsyth 
582*74a4d8c2SCharles.Forsyth 	if(out->debug > 2){
583*74a4d8c2SCharles.Forsyth 		for(off = soff; off < eoff; ){
584*74a4d8c2SCharles.Forsyth 			offset = *off++;
585*74a4d8c2SCharles.Forsyth 			run = offset & MaxLitRun;
586*74a4d8c2SCharles.Forsyth 			if(run){
587*74a4d8c2SCharles.Forsyth 				for(i = 0; i < run; i++){
588*74a4d8c2SCharles.Forsyth 					lit = out->hist[litoff & (HistBlock - 1)];
589*74a4d8c2SCharles.Forsyth 					litoff++;
590*74a4d8c2SCharles.Forsyth 					fprint(2, "\tlit %.2ux %c\n", lit, lit);
591*74a4d8c2SCharles.Forsyth 				}
592*74a4d8c2SCharles.Forsyth 				if(!(offset & LenFlag))
593*74a4d8c2SCharles.Forsyth 					continue;
594*74a4d8c2SCharles.Forsyth 				len = offset >> LenShift;
595*74a4d8c2SCharles.Forsyth 				offset = *off++;
596*74a4d8c2SCharles.Forsyth 			}else if(offset & LenFlag){
597*74a4d8c2SCharles.Forsyth 				len = offset >> LenShift;
598*74a4d8c2SCharles.Forsyth 				offset = *off++;
599*74a4d8c2SCharles.Forsyth 			}else{
600*74a4d8c2SCharles.Forsyth 				len = 0;
601*74a4d8c2SCharles.Forsyth 				offset >>= LenShift;
602*74a4d8c2SCharles.Forsyth 			}
603*74a4d8c2SCharles.Forsyth 			litoff += len + MinMatch;
604*74a4d8c2SCharles.Forsyth 			fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
605*74a4d8c2SCharles.Forsyth 		}
606*74a4d8c2SCharles.Forsyth 	}
607*74a4d8c2SCharles.Forsyth 
608*74a4d8c2SCharles.Forsyth 	for(off = soff; off < eoff; ){
609*74a4d8c2SCharles.Forsyth 		offset = *off++;
610*74a4d8c2SCharles.Forsyth 		run = offset & MaxLitRun;
611*74a4d8c2SCharles.Forsyth 		if(run){
612*74a4d8c2SCharles.Forsyth 			for(i = 0; i < run; i++){
613*74a4d8c2SCharles.Forsyth 				lit = out->hist[litoff & (HistBlock - 1)];
614*74a4d8c2SCharles.Forsyth 				litoff++;
615*74a4d8c2SCharles.Forsyth 				lzput(out, litlentab[lit].encode, litlentab[lit].bits);
616*74a4d8c2SCharles.Forsyth 			}
617*74a4d8c2SCharles.Forsyth 			if(!(offset & LenFlag))
618*74a4d8c2SCharles.Forsyth 				continue;
619*74a4d8c2SCharles.Forsyth 			len = offset >> LenShift;
620*74a4d8c2SCharles.Forsyth 			offset = *off++;
621*74a4d8c2SCharles.Forsyth 		}else if(offset & LenFlag){
622*74a4d8c2SCharles.Forsyth 			len = offset >> LenShift;
623*74a4d8c2SCharles.Forsyth 			offset = *off++;
624*74a4d8c2SCharles.Forsyth 		}else{
625*74a4d8c2SCharles.Forsyth 			len = 0;
626*74a4d8c2SCharles.Forsyth 			offset >>= LenShift;
627*74a4d8c2SCharles.Forsyth 		}
628*74a4d8c2SCharles.Forsyth 		litoff += len + MinMatch;
629*74a4d8c2SCharles.Forsyth 		c = lencode[len];
630*74a4d8c2SCharles.Forsyth 		lzput(out, litlentab[c].encode, litlentab[c].bits);
631*74a4d8c2SCharles.Forsyth 		c -= LenStart;
632*74a4d8c2SCharles.Forsyth 		if(litlenextra[c])
633*74a4d8c2SCharles.Forsyth 			lzput(out, len - litlenbase[c], litlenextra[c]);
634*74a4d8c2SCharles.Forsyth 
635*74a4d8c2SCharles.Forsyth 		if(offset < MaxOffCode)
636*74a4d8c2SCharles.Forsyth 			c = offcode[offset];
637*74a4d8c2SCharles.Forsyth 		else
638*74a4d8c2SCharles.Forsyth 			c = bigoffcode[offset >> 7];
639*74a4d8c2SCharles.Forsyth 		lzput(out, offtab[c].encode, offtab[c].bits);
640*74a4d8c2SCharles.Forsyth 		if(offextra[c])
641*74a4d8c2SCharles.Forsyth 			lzput(out, offset - offbase[c], offextra[c]);
642*74a4d8c2SCharles.Forsyth 	}
643*74a4d8c2SCharles.Forsyth }
644*74a4d8c2SCharles.Forsyth 
645*74a4d8c2SCharles.Forsyth /*
646*74a4d8c2SCharles.Forsyth  * look for the longest, closest string which matches
647*74a4d8c2SCharles.Forsyth  * the next prefix.  the clever part here is looking for
648*74a4d8c2SCharles.Forsyth  * a string 1 longer than the previous best match.
649*74a4d8c2SCharles.Forsyth  *
650*74a4d8c2SCharles.Forsyth  * follows the recommendation of limiting number of chains
651*74a4d8c2SCharles.Forsyth  * which are checked.  this appears to be the best heuristic.
652*74a4d8c2SCharles.Forsyth  */
653*74a4d8c2SCharles.Forsyth static int
lzmatch(int now,int then,uchar * p,uchar * es,ushort * nexts,uchar * hist,int runlen,int check,int * m)654*74a4d8c2SCharles.Forsyth lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
655*74a4d8c2SCharles.Forsyth {
656*74a4d8c2SCharles.Forsyth 	uchar *s, *t;
657*74a4d8c2SCharles.Forsyth 	int ml, off, last;
658*74a4d8c2SCharles.Forsyth 
659*74a4d8c2SCharles.Forsyth 	ml = check;
660*74a4d8c2SCharles.Forsyth 	if(runlen >= 8)
661*74a4d8c2SCharles.Forsyth 		check >>= 2;
662*74a4d8c2SCharles.Forsyth 	*m = 0;
663*74a4d8c2SCharles.Forsyth 	if(p + runlen >= es)
664*74a4d8c2SCharles.Forsyth 		return runlen;
665*74a4d8c2SCharles.Forsyth 	last = 0;
666*74a4d8c2SCharles.Forsyth 	for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
667*74a4d8c2SCharles.Forsyth 		off = (ushort)(now - then);
668*74a4d8c2SCharles.Forsyth 		if(off <= last || off > MaxOff)
669*74a4d8c2SCharles.Forsyth 			break;
670*74a4d8c2SCharles.Forsyth 		s = p + runlen;
671*74a4d8c2SCharles.Forsyth 		t = hist + (((p - hist) - off) & (HistBlock-1));
672*74a4d8c2SCharles.Forsyth 		t += runlen;
673*74a4d8c2SCharles.Forsyth 		for(; s >= p; s--){
674*74a4d8c2SCharles.Forsyth 			if(*s != *t)
675*74a4d8c2SCharles.Forsyth 				goto matchloop;
676*74a4d8c2SCharles.Forsyth 			t--;
677*74a4d8c2SCharles.Forsyth 		}
678*74a4d8c2SCharles.Forsyth 
679*74a4d8c2SCharles.Forsyth 		/*
680*74a4d8c2SCharles.Forsyth 		 * we have a new best match.
681*74a4d8c2SCharles.Forsyth 		 * extend it to it's maximum length
682*74a4d8c2SCharles.Forsyth 		 */
683*74a4d8c2SCharles.Forsyth 		t += runlen + 2;
684*74a4d8c2SCharles.Forsyth 		s += runlen + 2;
685*74a4d8c2SCharles.Forsyth 		for(; s < es; s++){
686*74a4d8c2SCharles.Forsyth 			if(*s != *t)
687*74a4d8c2SCharles.Forsyth 				break;
688*74a4d8c2SCharles.Forsyth 			t++;
689*74a4d8c2SCharles.Forsyth 		}
690*74a4d8c2SCharles.Forsyth 		runlen = s - p;
691*74a4d8c2SCharles.Forsyth 		*m = off - 1;
692*74a4d8c2SCharles.Forsyth 		if(s == es || runlen > ml)
693*74a4d8c2SCharles.Forsyth 			break;
694*74a4d8c2SCharles.Forsyth matchloop:;
695*74a4d8c2SCharles.Forsyth 		last = off;
696*74a4d8c2SCharles.Forsyth 	}
697*74a4d8c2SCharles.Forsyth 	return runlen;
698*74a4d8c2SCharles.Forsyth }
699*74a4d8c2SCharles.Forsyth 
700*74a4d8c2SCharles.Forsyth static int
lzcomp(LZstate * lz,LZblock * lzb,uchar * ep,ushort * parse,int finish)701*74a4d8c2SCharles.Forsyth lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
702*74a4d8c2SCharles.Forsyth {
703*74a4d8c2SCharles.Forsyth 	ulong cont, excost, *litlencount, *offcount;
704*74a4d8c2SCharles.Forsyth 	uchar *p, *q, *s, *es;
705*74a4d8c2SCharles.Forsyth 	ushort *nexts, *hash;
706*74a4d8c2SCharles.Forsyth 	int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
707*74a4d8c2SCharles.Forsyth 
708*74a4d8c2SCharles.Forsyth 	litlencount = lzb->litlencount;
709*74a4d8c2SCharles.Forsyth 	offcount = lzb->offcount;
710*74a4d8c2SCharles.Forsyth 	nexts = lz->nexts;
711*74a4d8c2SCharles.Forsyth 	hash = lz->hash;
712*74a4d8c2SCharles.Forsyth 	now = lz->now;
713*74a4d8c2SCharles.Forsyth 
714*74a4d8c2SCharles.Forsyth 	p = &lz->hist[lz->pos];
715*74a4d8c2SCharles.Forsyth 	if(lz->prevlen != MinMatch - 1)
716*74a4d8c2SCharles.Forsyth 		p++;
717*74a4d8c2SCharles.Forsyth 
718*74a4d8c2SCharles.Forsyth 	/*
719*74a4d8c2SCharles.Forsyth 	 * hash in the links for any hanging link positions,
720*74a4d8c2SCharles.Forsyth 	 * and calculate the hash for the current position.
721*74a4d8c2SCharles.Forsyth 	 */
722*74a4d8c2SCharles.Forsyth 	n = MinMatch;
723*74a4d8c2SCharles.Forsyth 	if(n > ep - p)
724*74a4d8c2SCharles.Forsyth 		n = ep - p;
725*74a4d8c2SCharles.Forsyth 	cont = 0;
726*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n - 1; i++){
727*74a4d8c2SCharles.Forsyth 		m = now - ((MinMatch-1) - i);
728*74a4d8c2SCharles.Forsyth 		if(m < lz->dot)
729*74a4d8c2SCharles.Forsyth 			continue;
730*74a4d8c2SCharles.Forsyth 		s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
731*74a4d8c2SCharles.Forsyth 
732*74a4d8c2SCharles.Forsyth 		cont = (s[0] << 16) | (s[1] << 8) | s[2];
733*74a4d8c2SCharles.Forsyth 		h = hashit(cont);
734*74a4d8c2SCharles.Forsyth 		prevoff = 0;
735*74a4d8c2SCharles.Forsyth 		for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
736*74a4d8c2SCharles.Forsyth 			v = (ushort)(now - then);
737*74a4d8c2SCharles.Forsyth 			if(v <= prevoff || v >= (MinMatch-1) - i)
738*74a4d8c2SCharles.Forsyth 				break;
739*74a4d8c2SCharles.Forsyth 			prevoff = v;
740*74a4d8c2SCharles.Forsyth 		}
741*74a4d8c2SCharles.Forsyth 		if(then == (ushort)m)
742*74a4d8c2SCharles.Forsyth 			continue;
743*74a4d8c2SCharles.Forsyth 		nexts[m & (MaxOff-1)] = hash[h];
744*74a4d8c2SCharles.Forsyth 		hash[h] = m;
745*74a4d8c2SCharles.Forsyth 	}
746*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++)
747*74a4d8c2SCharles.Forsyth 		cont = (cont << 8) | p[i];
748*74a4d8c2SCharles.Forsyth 
749*74a4d8c2SCharles.Forsyth 	/*
750*74a4d8c2SCharles.Forsyth 	 * now must point to the index in the nexts array
751*74a4d8c2SCharles.Forsyth 	 * corresponding to p's position in the history
752*74a4d8c2SCharles.Forsyth 	 */
753*74a4d8c2SCharles.Forsyth 	prevlen = lz->prevlen;
754*74a4d8c2SCharles.Forsyth 	prevoff = lz->prevoff;
755*74a4d8c2SCharles.Forsyth 	maxdefer = lz->maxcheck >> 2;
756*74a4d8c2SCharles.Forsyth 	excost = 0;
757*74a4d8c2SCharles.Forsyth 	v = lzb->lastv;
758*74a4d8c2SCharles.Forsyth 	for(;;){
759*74a4d8c2SCharles.Forsyth 		es = p + MaxMatch;
760*74a4d8c2SCharles.Forsyth 		if(es > ep){
761*74a4d8c2SCharles.Forsyth 			if(!finish || p >= ep)
762*74a4d8c2SCharles.Forsyth 				break;
763*74a4d8c2SCharles.Forsyth 			es = ep;
764*74a4d8c2SCharles.Forsyth 		}
765*74a4d8c2SCharles.Forsyth 
766*74a4d8c2SCharles.Forsyth 		h = hashit(cont);
767*74a4d8c2SCharles.Forsyth 		runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
768*74a4d8c2SCharles.Forsyth 
769*74a4d8c2SCharles.Forsyth 		/*
770*74a4d8c2SCharles.Forsyth 		 * back out of small matches too far in the past
771*74a4d8c2SCharles.Forsyth 		 */
772*74a4d8c2SCharles.Forsyth 		if(runlen == MinMatch && m >= MinMatchMaxOff){
773*74a4d8c2SCharles.Forsyth 			runlen = MinMatch - 1;
774*74a4d8c2SCharles.Forsyth 			m = 0;
775*74a4d8c2SCharles.Forsyth 		}
776*74a4d8c2SCharles.Forsyth 
777*74a4d8c2SCharles.Forsyth 		/*
778*74a4d8c2SCharles.Forsyth 		 * record the encoding and increment counts for huffman trees
779*74a4d8c2SCharles.Forsyth 		 * if we get a match, defer selecting it until we check for
780*74a4d8c2SCharles.Forsyth 		 * a longer match at the next position.
781*74a4d8c2SCharles.Forsyth 		 */
782*74a4d8c2SCharles.Forsyth 		if(prevlen >= runlen && prevlen != MinMatch - 1){
783*74a4d8c2SCharles.Forsyth 			/*
784*74a4d8c2SCharles.Forsyth 			 * old match at least as good; use that one
785*74a4d8c2SCharles.Forsyth 			 */
786*74a4d8c2SCharles.Forsyth 			n = prevlen - MinMatch;
787*74a4d8c2SCharles.Forsyth 			if(v || n){
788*74a4d8c2SCharles.Forsyth 				*parse++ = v | LenFlag | (n << LenShift);
789*74a4d8c2SCharles.Forsyth 				*parse++ = prevoff;
790*74a4d8c2SCharles.Forsyth 			}else
791*74a4d8c2SCharles.Forsyth 				*parse++ = prevoff << LenShift;
792*74a4d8c2SCharles.Forsyth 			v = 0;
793*74a4d8c2SCharles.Forsyth 
794*74a4d8c2SCharles.Forsyth 			n = lencode[n];
795*74a4d8c2SCharles.Forsyth 			litlencount[n]++;
796*74a4d8c2SCharles.Forsyth 			excost += litlenextra[n - LenStart];
797*74a4d8c2SCharles.Forsyth 
798*74a4d8c2SCharles.Forsyth 			if(prevoff < MaxOffCode)
799*74a4d8c2SCharles.Forsyth 				n = offcode[prevoff];
800*74a4d8c2SCharles.Forsyth 			else
801*74a4d8c2SCharles.Forsyth 				n = bigoffcode[prevoff >> 7];
802*74a4d8c2SCharles.Forsyth 			offcount[n]++;
803*74a4d8c2SCharles.Forsyth 			excost += offextra[n];
804*74a4d8c2SCharles.Forsyth 
805*74a4d8c2SCharles.Forsyth 			runlen = prevlen - 1;
806*74a4d8c2SCharles.Forsyth 			prevlen = MinMatch - 1;
807*74a4d8c2SCharles.Forsyth 			nmatches++;
808*74a4d8c2SCharles.Forsyth 		}else if(runlen == MinMatch - 1){
809*74a4d8c2SCharles.Forsyth 			/*
810*74a4d8c2SCharles.Forsyth 			 * no match; just put out the literal
811*74a4d8c2SCharles.Forsyth 			 */
812*74a4d8c2SCharles.Forsyth 			if(++v == MaxLitRun){
813*74a4d8c2SCharles.Forsyth 				*parse++ = v;
814*74a4d8c2SCharles.Forsyth 				v = 0;
815*74a4d8c2SCharles.Forsyth 			}
816*74a4d8c2SCharles.Forsyth 			litlencount[*p]++;
817*74a4d8c2SCharles.Forsyth 			nlits++;
818*74a4d8c2SCharles.Forsyth 			runlen = 1;
819*74a4d8c2SCharles.Forsyth 		}else{
820*74a4d8c2SCharles.Forsyth 			if(prevlen != MinMatch - 1){
821*74a4d8c2SCharles.Forsyth 				/*
822*74a4d8c2SCharles.Forsyth 				 * longer match now. output previous literal,
823*74a4d8c2SCharles.Forsyth 				 * update current match, and try again
824*74a4d8c2SCharles.Forsyth 				 */
825*74a4d8c2SCharles.Forsyth 				if(++v == MaxLitRun){
826*74a4d8c2SCharles.Forsyth 					*parse++ = v;
827*74a4d8c2SCharles.Forsyth 					v = 0;
828*74a4d8c2SCharles.Forsyth 				}
829*74a4d8c2SCharles.Forsyth 				litlencount[p[-1]]++;
830*74a4d8c2SCharles.Forsyth 				nlits++;
831*74a4d8c2SCharles.Forsyth 			}
832*74a4d8c2SCharles.Forsyth 
833*74a4d8c2SCharles.Forsyth 			prevoff = m;
834*74a4d8c2SCharles.Forsyth 
835*74a4d8c2SCharles.Forsyth 			if(runlen < maxdefer){
836*74a4d8c2SCharles.Forsyth 				prevlen = runlen;
837*74a4d8c2SCharles.Forsyth 				runlen = 1;
838*74a4d8c2SCharles.Forsyth 			}else{
839*74a4d8c2SCharles.Forsyth 				n = runlen - MinMatch;
840*74a4d8c2SCharles.Forsyth 				if(v || n){
841*74a4d8c2SCharles.Forsyth 					*parse++ = v | LenFlag | (n << LenShift);
842*74a4d8c2SCharles.Forsyth 					*parse++ = prevoff;
843*74a4d8c2SCharles.Forsyth 				}else
844*74a4d8c2SCharles.Forsyth 					*parse++ = prevoff << LenShift;
845*74a4d8c2SCharles.Forsyth 				v = 0;
846*74a4d8c2SCharles.Forsyth 
847*74a4d8c2SCharles.Forsyth 				n = lencode[n];
848*74a4d8c2SCharles.Forsyth 				litlencount[n]++;
849*74a4d8c2SCharles.Forsyth 				excost += litlenextra[n - LenStart];
850*74a4d8c2SCharles.Forsyth 
851*74a4d8c2SCharles.Forsyth 				if(prevoff < MaxOffCode)
852*74a4d8c2SCharles.Forsyth 					n = offcode[prevoff];
853*74a4d8c2SCharles.Forsyth 				else
854*74a4d8c2SCharles.Forsyth 					n = bigoffcode[prevoff >> 7];
855*74a4d8c2SCharles.Forsyth 				offcount[n]++;
856*74a4d8c2SCharles.Forsyth 				excost += offextra[n];
857*74a4d8c2SCharles.Forsyth 
858*74a4d8c2SCharles.Forsyth 				prevlen = MinMatch - 1;
859*74a4d8c2SCharles.Forsyth 				nmatches++;
860*74a4d8c2SCharles.Forsyth 			}
861*74a4d8c2SCharles.Forsyth 		}
862*74a4d8c2SCharles.Forsyth 
863*74a4d8c2SCharles.Forsyth 		/*
864*74a4d8c2SCharles.Forsyth 		 * update the hash for the newly matched data
865*74a4d8c2SCharles.Forsyth 		 * this is constructed so the link for the old
866*74a4d8c2SCharles.Forsyth 		 * match in this position must be at the end of a chain,
867*74a4d8c2SCharles.Forsyth 		 * and will expire when this match is added, ie it will
868*74a4d8c2SCharles.Forsyth 		 * never be examined by the match loop.
869*74a4d8c2SCharles.Forsyth 		 * add to the hash chain only if we have the real hash data.
870*74a4d8c2SCharles.Forsyth 		 */
871*74a4d8c2SCharles.Forsyth 		for(q = p + runlen; p != q; p++){
872*74a4d8c2SCharles.Forsyth 			if(p + MinMatch <= ep){
873*74a4d8c2SCharles.Forsyth 				h = hashit(cont);
874*74a4d8c2SCharles.Forsyth 				nexts[now & (MaxOff-1)] = hash[h];
875*74a4d8c2SCharles.Forsyth 				hash[h] = now;
876*74a4d8c2SCharles.Forsyth 				if(p + MinMatch < ep)
877*74a4d8c2SCharles.Forsyth 					cont = (cont << 8) | p[MinMatch];
878*74a4d8c2SCharles.Forsyth 			}
879*74a4d8c2SCharles.Forsyth 			now++;
880*74a4d8c2SCharles.Forsyth 		}
881*74a4d8c2SCharles.Forsyth 	}
882*74a4d8c2SCharles.Forsyth 
883*74a4d8c2SCharles.Forsyth 	/*
884*74a4d8c2SCharles.Forsyth 	 * we can just store away the lazy state and
885*74a4d8c2SCharles.Forsyth 	 * pick it up next time.  the last block will have finish set
886*74a4d8c2SCharles.Forsyth 	 * so we won't have any pending matches
887*74a4d8c2SCharles.Forsyth 	 * however, we need to correct for how much we've encoded
888*74a4d8c2SCharles.Forsyth 	 */
889*74a4d8c2SCharles.Forsyth 	if(prevlen != MinMatch - 1)
890*74a4d8c2SCharles.Forsyth 		p--;
891*74a4d8c2SCharles.Forsyth 
892*74a4d8c2SCharles.Forsyth 	lzb->excost += excost;
893*74a4d8c2SCharles.Forsyth 	lzb->eparse = parse;
894*74a4d8c2SCharles.Forsyth 	lzb->lastv = v;
895*74a4d8c2SCharles.Forsyth 
896*74a4d8c2SCharles.Forsyth 	lz->now = now;
897*74a4d8c2SCharles.Forsyth 	lz->prevlen = prevlen;
898*74a4d8c2SCharles.Forsyth 	lz->prevoff = prevoff;
899*74a4d8c2SCharles.Forsyth 
900*74a4d8c2SCharles.Forsyth 	return p - &lz->hist[lz->pos];
901*74a4d8c2SCharles.Forsyth }
902*74a4d8c2SCharles.Forsyth 
903*74a4d8c2SCharles.Forsyth /*
904*74a4d8c2SCharles.Forsyth  * make up the dynamic code tables, and return the number of bits
905*74a4d8c2SCharles.Forsyth  * needed to transmit them.
906*74a4d8c2SCharles.Forsyth  */
907*74a4d8c2SCharles.Forsyth static int
huffcodes(Dyncode * dc,Huff * littab,Huff * offtab)908*74a4d8c2SCharles.Forsyth huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
909*74a4d8c2SCharles.Forsyth {
910*74a4d8c2SCharles.Forsyth 	Huff *codetab;
911*74a4d8c2SCharles.Forsyth 	uchar *codes, *codeaux;
912*74a4d8c2SCharles.Forsyth 	ulong codecount[Nclen], excost;
913*74a4d8c2SCharles.Forsyth 	int i, n, m, v, c, nlit, noff, ncode, nclen;
914*74a4d8c2SCharles.Forsyth 
915*74a4d8c2SCharles.Forsyth 	codetab = dc->codetab;
916*74a4d8c2SCharles.Forsyth 	codes = dc->codes;
917*74a4d8c2SCharles.Forsyth 	codeaux = dc->codeaux;
918*74a4d8c2SCharles.Forsyth 
919*74a4d8c2SCharles.Forsyth 	/*
920*74a4d8c2SCharles.Forsyth 	 * trim the sizes of the tables
921*74a4d8c2SCharles.Forsyth 	 */
922*74a4d8c2SCharles.Forsyth 	for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
923*74a4d8c2SCharles.Forsyth 		;
924*74a4d8c2SCharles.Forsyth 	for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
925*74a4d8c2SCharles.Forsyth 		;
926*74a4d8c2SCharles.Forsyth 
927*74a4d8c2SCharles.Forsyth 	/*
928*74a4d8c2SCharles.Forsyth 	 * make the code-length code
929*74a4d8c2SCharles.Forsyth 	 */
930*74a4d8c2SCharles.Forsyth 	for(i = 0; i < nlit; i++)
931*74a4d8c2SCharles.Forsyth 		codes[i] = littab[i].bits;
932*74a4d8c2SCharles.Forsyth 	for(i = 0; i < noff; i++)
933*74a4d8c2SCharles.Forsyth 		codes[i + nlit] = offtab[i].bits;
934*74a4d8c2SCharles.Forsyth 
935*74a4d8c2SCharles.Forsyth 	/*
936*74a4d8c2SCharles.Forsyth 	 * run-length compress the code-length code
937*74a4d8c2SCharles.Forsyth 	 */
938*74a4d8c2SCharles.Forsyth 	excost = 0;
939*74a4d8c2SCharles.Forsyth 	c = 0;
940*74a4d8c2SCharles.Forsyth 	ncode = nlit+noff;
941*74a4d8c2SCharles.Forsyth 	for(i = 0; i < ncode; ){
942*74a4d8c2SCharles.Forsyth 		n = i + 1;
943*74a4d8c2SCharles.Forsyth 		v = codes[i];
944*74a4d8c2SCharles.Forsyth 		while(n < ncode && v == codes[n])
945*74a4d8c2SCharles.Forsyth 			n++;
946*74a4d8c2SCharles.Forsyth 		n -= i;
947*74a4d8c2SCharles.Forsyth 		i += n;
948*74a4d8c2SCharles.Forsyth 		if(v == 0){
949*74a4d8c2SCharles.Forsyth 			while(n >= 11){
950*74a4d8c2SCharles.Forsyth 				m = n;
951*74a4d8c2SCharles.Forsyth 				if(m > 138)
952*74a4d8c2SCharles.Forsyth 					m = 138;
953*74a4d8c2SCharles.Forsyth 				codes[c] = 18;
954*74a4d8c2SCharles.Forsyth 				codeaux[c++] = m - 11;
955*74a4d8c2SCharles.Forsyth 				n -= m;
956*74a4d8c2SCharles.Forsyth 				excost += 7;
957*74a4d8c2SCharles.Forsyth 			}
958*74a4d8c2SCharles.Forsyth 			if(n >= 3){
959*74a4d8c2SCharles.Forsyth 				codes[c] = 17;
960*74a4d8c2SCharles.Forsyth 				codeaux[c++] = n - 3;
961*74a4d8c2SCharles.Forsyth 				n = 0;
962*74a4d8c2SCharles.Forsyth 				excost += 3;
963*74a4d8c2SCharles.Forsyth 			}
964*74a4d8c2SCharles.Forsyth 		}
965*74a4d8c2SCharles.Forsyth 		while(n--){
966*74a4d8c2SCharles.Forsyth 			codes[c++] = v;
967*74a4d8c2SCharles.Forsyth 			while(n >= 3){
968*74a4d8c2SCharles.Forsyth 				m = n;
969*74a4d8c2SCharles.Forsyth 				if(m > 6)
970*74a4d8c2SCharles.Forsyth 					m = 6;
971*74a4d8c2SCharles.Forsyth 				codes[c] = 16;
972*74a4d8c2SCharles.Forsyth 				codeaux[c++] = m - 3;
973*74a4d8c2SCharles.Forsyth 				n -= m;
974*74a4d8c2SCharles.Forsyth 				excost += 3;
975*74a4d8c2SCharles.Forsyth 			}
976*74a4d8c2SCharles.Forsyth 		}
977*74a4d8c2SCharles.Forsyth 	}
978*74a4d8c2SCharles.Forsyth 
979*74a4d8c2SCharles.Forsyth 	memset(codecount, 0, sizeof codecount);
980*74a4d8c2SCharles.Forsyth 	for(i = 0; i < c; i++)
981*74a4d8c2SCharles.Forsyth 		codecount[codes[i]]++;
982*74a4d8c2SCharles.Forsyth 	if(!mkgzprecode(codetab, codecount, Nclen, 8))
983*74a4d8c2SCharles.Forsyth 		return -1;
984*74a4d8c2SCharles.Forsyth 
985*74a4d8c2SCharles.Forsyth 	for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
986*74a4d8c2SCharles.Forsyth 		;
987*74a4d8c2SCharles.Forsyth 
988*74a4d8c2SCharles.Forsyth 	dc->nlit = nlit;
989*74a4d8c2SCharles.Forsyth 	dc->noff = noff;
990*74a4d8c2SCharles.Forsyth 	dc->nclen = nclen;
991*74a4d8c2SCharles.Forsyth 	dc->ncode = c;
992*74a4d8c2SCharles.Forsyth 
993*74a4d8c2SCharles.Forsyth 	return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
994*74a4d8c2SCharles.Forsyth }
995*74a4d8c2SCharles.Forsyth 
996*74a4d8c2SCharles.Forsyth static void
wrdyncode(LZstate * out,Dyncode * dc)997*74a4d8c2SCharles.Forsyth wrdyncode(LZstate *out, Dyncode *dc)
998*74a4d8c2SCharles.Forsyth {
999*74a4d8c2SCharles.Forsyth 	Huff *codetab;
1000*74a4d8c2SCharles.Forsyth 	uchar *codes, *codeaux;
1001*74a4d8c2SCharles.Forsyth 	int i, v, c;
1002*74a4d8c2SCharles.Forsyth 
1003*74a4d8c2SCharles.Forsyth 	/*
1004*74a4d8c2SCharles.Forsyth 	 * write out header, then code length code lengths,
1005*74a4d8c2SCharles.Forsyth 	 * and code lengths
1006*74a4d8c2SCharles.Forsyth 	 */
1007*74a4d8c2SCharles.Forsyth 	lzput(out, dc->nlit-257, 5);
1008*74a4d8c2SCharles.Forsyth 	lzput(out, dc->noff-1, 5);
1009*74a4d8c2SCharles.Forsyth 	lzput(out, dc->nclen-4, 4);
1010*74a4d8c2SCharles.Forsyth 
1011*74a4d8c2SCharles.Forsyth 	codetab = dc->codetab;
1012*74a4d8c2SCharles.Forsyth 	for(i = 0; i < dc->nclen; i++)
1013*74a4d8c2SCharles.Forsyth 		lzput(out, codetab[clenorder[i]].bits, 3);
1014*74a4d8c2SCharles.Forsyth 
1015*74a4d8c2SCharles.Forsyth 	codes = dc->codes;
1016*74a4d8c2SCharles.Forsyth 	codeaux = dc->codeaux;
1017*74a4d8c2SCharles.Forsyth 	c = dc->ncode;
1018*74a4d8c2SCharles.Forsyth 	for(i = 0; i < c; i++){
1019*74a4d8c2SCharles.Forsyth 		v = codes[i];
1020*74a4d8c2SCharles.Forsyth 		lzput(out, codetab[v].encode, codetab[v].bits);
1021*74a4d8c2SCharles.Forsyth 		if(v >= 16){
1022*74a4d8c2SCharles.Forsyth 			if(v == 16)
1023*74a4d8c2SCharles.Forsyth 				lzput(out, codeaux[i], 2);
1024*74a4d8c2SCharles.Forsyth 			else if(v == 17)
1025*74a4d8c2SCharles.Forsyth 				lzput(out, codeaux[i], 3);
1026*74a4d8c2SCharles.Forsyth 			else /* v == 18 */
1027*74a4d8c2SCharles.Forsyth 				lzput(out, codeaux[i], 7);
1028*74a4d8c2SCharles.Forsyth 		}
1029*74a4d8c2SCharles.Forsyth 	}
1030*74a4d8c2SCharles.Forsyth }
1031*74a4d8c2SCharles.Forsyth 
1032*74a4d8c2SCharles.Forsyth static int
bitcost(Huff * tab,ulong * count,int n)1033*74a4d8c2SCharles.Forsyth bitcost(Huff *tab, ulong *count, int n)
1034*74a4d8c2SCharles.Forsyth {
1035*74a4d8c2SCharles.Forsyth 	ulong tot;
1036*74a4d8c2SCharles.Forsyth 	int i;
1037*74a4d8c2SCharles.Forsyth 
1038*74a4d8c2SCharles.Forsyth 	tot = 0;
1039*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++)
1040*74a4d8c2SCharles.Forsyth 		tot += count[i] * tab[i].bits;
1041*74a4d8c2SCharles.Forsyth 	return tot;
1042*74a4d8c2SCharles.Forsyth }
1043*74a4d8c2SCharles.Forsyth 
1044*74a4d8c2SCharles.Forsyth static int
mkgzprecode(Huff * tab,ulong * count,int n,int maxbits)1045*74a4d8c2SCharles.Forsyth mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
1046*74a4d8c2SCharles.Forsyth {
1047*74a4d8c2SCharles.Forsyth 	ulong bitcount[MaxHuffBits];
1048*74a4d8c2SCharles.Forsyth 	int i, nbits;
1049*74a4d8c2SCharles.Forsyth 
1050*74a4d8c2SCharles.Forsyth 	nbits = mkprecode(tab, count, n, maxbits, bitcount);
1051*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++){
1052*74a4d8c2SCharles.Forsyth 		if(tab[i].bits == -1)
1053*74a4d8c2SCharles.Forsyth 			tab[i].bits = 0;
1054*74a4d8c2SCharles.Forsyth 		else if(tab[i].bits == 0){
1055*74a4d8c2SCharles.Forsyth 			if(nbits != 0 || bitcount[0] != 1)
1056*74a4d8c2SCharles.Forsyth 				return 0;
1057*74a4d8c2SCharles.Forsyth 			bitcount[1] = 1;
1058*74a4d8c2SCharles.Forsyth 			bitcount[0] = 0;
1059*74a4d8c2SCharles.Forsyth 			nbits = 1;
1060*74a4d8c2SCharles.Forsyth 			tab[i].bits = 1;
1061*74a4d8c2SCharles.Forsyth 		}
1062*74a4d8c2SCharles.Forsyth 	}
1063*74a4d8c2SCharles.Forsyth 	if(bitcount[0] != 0)
1064*74a4d8c2SCharles.Forsyth 		return 0;
1065*74a4d8c2SCharles.Forsyth 	return hufftabinit(tab, n, bitcount, nbits);
1066*74a4d8c2SCharles.Forsyth }
1067*74a4d8c2SCharles.Forsyth 
1068*74a4d8c2SCharles.Forsyth static int
hufftabinit(Huff * tab,int n,ulong * bitcount,int nbits)1069*74a4d8c2SCharles.Forsyth hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
1070*74a4d8c2SCharles.Forsyth {
1071*74a4d8c2SCharles.Forsyth 	ulong code, nc[MaxHuffBits];
1072*74a4d8c2SCharles.Forsyth 	int i, bits;
1073*74a4d8c2SCharles.Forsyth 
1074*74a4d8c2SCharles.Forsyth 	code = 0;
1075*74a4d8c2SCharles.Forsyth 	for(bits = 1; bits <= nbits; bits++){
1076*74a4d8c2SCharles.Forsyth 		code = (code + bitcount[bits-1]) << 1;
1077*74a4d8c2SCharles.Forsyth 		nc[bits] = code;
1078*74a4d8c2SCharles.Forsyth 	}
1079*74a4d8c2SCharles.Forsyth 
1080*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++){
1081*74a4d8c2SCharles.Forsyth 		bits = tab[i].bits;
1082*74a4d8c2SCharles.Forsyth 		if(bits){
1083*74a4d8c2SCharles.Forsyth 			code = nc[bits]++ << (16 - bits);
1084*74a4d8c2SCharles.Forsyth 			if(code & ~0xffff)
1085*74a4d8c2SCharles.Forsyth 				return 0;
1086*74a4d8c2SCharles.Forsyth 			tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
1087*74a4d8c2SCharles.Forsyth 		}
1088*74a4d8c2SCharles.Forsyth 	}
1089*74a4d8c2SCharles.Forsyth 	return 1;
1090*74a4d8c2SCharles.Forsyth }
1091*74a4d8c2SCharles.Forsyth 
1092*74a4d8c2SCharles.Forsyth 
1093*74a4d8c2SCharles.Forsyth /*
1094*74a4d8c2SCharles.Forsyth  * this should be in a library
1095*74a4d8c2SCharles.Forsyth  */
1096*74a4d8c2SCharles.Forsyth struct Chain
1097*74a4d8c2SCharles.Forsyth {
1098*74a4d8c2SCharles.Forsyth 	ulong	count;				/* occurances of everything in the chain */
1099*74a4d8c2SCharles.Forsyth 	ushort	leaf;				/* leaves to the left of chain, or leaf value */
1100*74a4d8c2SCharles.Forsyth 	char	col;				/* ref count for collecting unused chains */
1101*74a4d8c2SCharles.Forsyth 	char	gen;				/* need to generate chains for next lower level */
1102*74a4d8c2SCharles.Forsyth 	Chain	*up;				/* Chain up in the lists */
1103*74a4d8c2SCharles.Forsyth };
1104*74a4d8c2SCharles.Forsyth 
1105*74a4d8c2SCharles.Forsyth struct Chains
1106*74a4d8c2SCharles.Forsyth {
1107*74a4d8c2SCharles.Forsyth 	Chain	*lists[(MaxHuffBits - 1) * 2];
1108*74a4d8c2SCharles.Forsyth 	ulong	leafcount[MaxLeaf];		/* sorted list of leaf counts */
1109*74a4d8c2SCharles.Forsyth 	ushort	leafmap[MaxLeaf];		/* map to actual leaf number */
1110*74a4d8c2SCharles.Forsyth 	int	nleaf;				/* number of leaves */
1111*74a4d8c2SCharles.Forsyth 	Chain	chains[ChainMem];
1112*74a4d8c2SCharles.Forsyth 	Chain	*echains;
1113*74a4d8c2SCharles.Forsyth 	Chain	*free;
1114*74a4d8c2SCharles.Forsyth 	char	col;
1115*74a4d8c2SCharles.Forsyth 	int	nlists;
1116*74a4d8c2SCharles.Forsyth };
1117*74a4d8c2SCharles.Forsyth 
1118*74a4d8c2SCharles.Forsyth /*
1119*74a4d8c2SCharles.Forsyth  * fast, low space overhead algorithm for max depth huffman type codes
1120*74a4d8c2SCharles.Forsyth  *
1121*74a4d8c2SCharles.Forsyth  * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
1122*74a4d8c2SCharles.Forsyth  * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
1123*74a4d8c2SCharles.Forsyth  * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
1124*74a4d8c2SCharles.Forsyth  * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
1125*74a4d8c2SCharles.Forsyth  * pp 12-21, Springer Verlag, New York, 1995.
1126*74a4d8c2SCharles.Forsyth  */
1127*74a4d8c2SCharles.Forsyth static int
mkprecode(Huff * tab,ulong * count,int n,int maxbits,ulong * bitcount)1128*74a4d8c2SCharles.Forsyth mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
1129*74a4d8c2SCharles.Forsyth {
1130*74a4d8c2SCharles.Forsyth 	Chains cs;
1131*74a4d8c2SCharles.Forsyth 	Chain *c;
1132*74a4d8c2SCharles.Forsyth 	int i, m, em, bits;
1133*74a4d8c2SCharles.Forsyth 
1134*74a4d8c2SCharles.Forsyth 	/*
1135*74a4d8c2SCharles.Forsyth 	 * set up the sorted list of leaves
1136*74a4d8c2SCharles.Forsyth 	 */
1137*74a4d8c2SCharles.Forsyth 	m = 0;
1138*74a4d8c2SCharles.Forsyth 	for(i = 0; i < n; i++){
1139*74a4d8c2SCharles.Forsyth 		tab[i].bits = -1;
1140*74a4d8c2SCharles.Forsyth 		tab[i].encode = 0;
1141*74a4d8c2SCharles.Forsyth 		if(count[i] != 0){
1142*74a4d8c2SCharles.Forsyth 			cs.leafcount[m] = count[i];
1143*74a4d8c2SCharles.Forsyth 			cs.leafmap[m] = i;
1144*74a4d8c2SCharles.Forsyth 			m++;
1145*74a4d8c2SCharles.Forsyth 		}
1146*74a4d8c2SCharles.Forsyth 	}
1147*74a4d8c2SCharles.Forsyth 	if(m < 2){
1148*74a4d8c2SCharles.Forsyth 		if(m != 0){
1149*74a4d8c2SCharles.Forsyth 			tab[cs.leafmap[0]].bits = 0;
1150*74a4d8c2SCharles.Forsyth 			bitcount[0] = 1;
1151*74a4d8c2SCharles.Forsyth 		}else
1152*74a4d8c2SCharles.Forsyth 			bitcount[0] = 0;
1153*74a4d8c2SCharles.Forsyth 		return 0;
1154*74a4d8c2SCharles.Forsyth 	}
1155*74a4d8c2SCharles.Forsyth 	cs.nleaf = m;
1156*74a4d8c2SCharles.Forsyth 	leafsort(cs.leafcount, cs.leafmap, 0, m);
1157*74a4d8c2SCharles.Forsyth 
1158*74a4d8c2SCharles.Forsyth 	for(i = 0; i < m; i++)
1159*74a4d8c2SCharles.Forsyth 		cs.leafcount[i] = count[cs.leafmap[i]];
1160*74a4d8c2SCharles.Forsyth 
1161*74a4d8c2SCharles.Forsyth 	/*
1162*74a4d8c2SCharles.Forsyth 	 * set up free list
1163*74a4d8c2SCharles.Forsyth 	 */
1164*74a4d8c2SCharles.Forsyth 	cs.free = &cs.chains[2];
1165*74a4d8c2SCharles.Forsyth 	cs.echains = &cs.chains[ChainMem];
1166*74a4d8c2SCharles.Forsyth 	cs.col = 1;
1167*74a4d8c2SCharles.Forsyth 
1168*74a4d8c2SCharles.Forsyth 	/*
1169*74a4d8c2SCharles.Forsyth 	 * initialize chains for each list
1170*74a4d8c2SCharles.Forsyth 	 */
1171*74a4d8c2SCharles.Forsyth 	c = &cs.chains[0];
1172*74a4d8c2SCharles.Forsyth 	c->count = cs.leafcount[0];
1173*74a4d8c2SCharles.Forsyth 	c->leaf = 1;
1174*74a4d8c2SCharles.Forsyth 	c->col = cs.col;
1175*74a4d8c2SCharles.Forsyth 	c->up = nil;
1176*74a4d8c2SCharles.Forsyth 	c->gen = 0;
1177*74a4d8c2SCharles.Forsyth 	cs.chains[1] = cs.chains[0];
1178*74a4d8c2SCharles.Forsyth 	cs.chains[1].leaf = 2;
1179*74a4d8c2SCharles.Forsyth 	cs.chains[1].count = cs.leafcount[1];
1180*74a4d8c2SCharles.Forsyth 	for(i = 0; i < maxbits-1; i++){
1181*74a4d8c2SCharles.Forsyth 		cs.lists[i * 2] = &cs.chains[0];
1182*74a4d8c2SCharles.Forsyth 		cs.lists[i * 2 + 1] = &cs.chains[1];
1183*74a4d8c2SCharles.Forsyth 	}
1184*74a4d8c2SCharles.Forsyth 
1185*74a4d8c2SCharles.Forsyth 	cs.nlists = 2 * (maxbits - 1);
1186*74a4d8c2SCharles.Forsyth 	m = 2 * m - 2;
1187*74a4d8c2SCharles.Forsyth 	for(i = 2; i < m; i++)
1188*74a4d8c2SCharles.Forsyth 		nextchain(&cs, cs.nlists - 2);
1189*74a4d8c2SCharles.Forsyth 
1190*74a4d8c2SCharles.Forsyth 	bits = 0;
1191*74a4d8c2SCharles.Forsyth 	bitcount[0] = cs.nleaf;
1192*74a4d8c2SCharles.Forsyth 	for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
1193*74a4d8c2SCharles.Forsyth 		m = c->leaf;
1194*74a4d8c2SCharles.Forsyth 		bitcount[bits++] -= m;
1195*74a4d8c2SCharles.Forsyth 		bitcount[bits] = m;
1196*74a4d8c2SCharles.Forsyth 	}
1197*74a4d8c2SCharles.Forsyth 	m = 0;
1198*74a4d8c2SCharles.Forsyth 	for(i = bits; i >= 0; i--)
1199*74a4d8c2SCharles.Forsyth 		for(em = m + bitcount[i]; m < em; m++)
1200*74a4d8c2SCharles.Forsyth 			tab[cs.leafmap[m]].bits = i;
1201*74a4d8c2SCharles.Forsyth 
1202*74a4d8c2SCharles.Forsyth 	return bits;
1203*74a4d8c2SCharles.Forsyth }
1204*74a4d8c2SCharles.Forsyth 
1205*74a4d8c2SCharles.Forsyth /*
1206*74a4d8c2SCharles.Forsyth  * calculate the next chain on the list
1207*74a4d8c2SCharles.Forsyth  * we can always toss out the old chain
1208*74a4d8c2SCharles.Forsyth  */
1209*74a4d8c2SCharles.Forsyth static void
nextchain(Chains * cs,int list)1210*74a4d8c2SCharles.Forsyth nextchain(Chains *cs, int list)
1211*74a4d8c2SCharles.Forsyth {
1212*74a4d8c2SCharles.Forsyth 	Chain *c, *oc;
1213*74a4d8c2SCharles.Forsyth 	int i, nleaf, sumc;
1214*74a4d8c2SCharles.Forsyth 
1215*74a4d8c2SCharles.Forsyth 	oc = cs->lists[list + 1];
1216*74a4d8c2SCharles.Forsyth 	cs->lists[list] = oc;
1217*74a4d8c2SCharles.Forsyth 	if(oc == nil)
1218*74a4d8c2SCharles.Forsyth 		return;
1219*74a4d8c2SCharles.Forsyth 
1220*74a4d8c2SCharles.Forsyth 	/*
1221*74a4d8c2SCharles.Forsyth 	 * make sure we have all chains needed to make sumc
1222*74a4d8c2SCharles.Forsyth 	 * note it is possible to generate only one of these,
1223*74a4d8c2SCharles.Forsyth 	 * use twice that value for sumc, and then generate
1224*74a4d8c2SCharles.Forsyth 	 * the second if that preliminary sumc would be chosen.
1225*74a4d8c2SCharles.Forsyth 	 * however, this appears to be slower on current tests
1226*74a4d8c2SCharles.Forsyth 	 */
1227*74a4d8c2SCharles.Forsyth 	if(oc->gen){
1228*74a4d8c2SCharles.Forsyth 		nextchain(cs, list - 2);
1229*74a4d8c2SCharles.Forsyth 		nextchain(cs, list - 2);
1230*74a4d8c2SCharles.Forsyth 		oc->gen = 0;
1231*74a4d8c2SCharles.Forsyth 	}
1232*74a4d8c2SCharles.Forsyth 
1233*74a4d8c2SCharles.Forsyth 	/*
1234*74a4d8c2SCharles.Forsyth 	 * pick up the chain we're going to add;
1235*74a4d8c2SCharles.Forsyth 	 * collect unused chains no free ones are left
1236*74a4d8c2SCharles.Forsyth 	 */
1237*74a4d8c2SCharles.Forsyth 	for(c = cs->free; ; c++){
1238*74a4d8c2SCharles.Forsyth 		if(c >= cs->echains){
1239*74a4d8c2SCharles.Forsyth 			cs->col++;
1240*74a4d8c2SCharles.Forsyth 			for(i = 0; i < cs->nlists; i++)
1241*74a4d8c2SCharles.Forsyth 				for(c = cs->lists[i]; c != nil; c = c->up)
1242*74a4d8c2SCharles.Forsyth 					c->col = cs->col;
1243*74a4d8c2SCharles.Forsyth 			c = cs->chains;
1244*74a4d8c2SCharles.Forsyth 		}
1245*74a4d8c2SCharles.Forsyth 		if(c->col != cs->col)
1246*74a4d8c2SCharles.Forsyth 			break;
1247*74a4d8c2SCharles.Forsyth 	}
1248*74a4d8c2SCharles.Forsyth 
1249*74a4d8c2SCharles.Forsyth 	/*
1250*74a4d8c2SCharles.Forsyth 	 * pick the cheapest of
1251*74a4d8c2SCharles.Forsyth 	 * 1) the next package from the previous list
1252*74a4d8c2SCharles.Forsyth 	 * 2) the next leaf
1253*74a4d8c2SCharles.Forsyth 	 */
1254*74a4d8c2SCharles.Forsyth 	nleaf = oc->leaf;
1255*74a4d8c2SCharles.Forsyth 	sumc = 0;
1256*74a4d8c2SCharles.Forsyth 	if(list > 0 && cs->lists[list-1] != nil)
1257*74a4d8c2SCharles.Forsyth 		sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
1258*74a4d8c2SCharles.Forsyth 	if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
1259*74a4d8c2SCharles.Forsyth 		c->count = sumc;
1260*74a4d8c2SCharles.Forsyth 		c->leaf = oc->leaf;
1261*74a4d8c2SCharles.Forsyth 		c->up = cs->lists[list-1];
1262*74a4d8c2SCharles.Forsyth 		c->gen = 1;
1263*74a4d8c2SCharles.Forsyth 	}else if(nleaf >= cs->nleaf){
1264*74a4d8c2SCharles.Forsyth 		cs->lists[list + 1] = nil;
1265*74a4d8c2SCharles.Forsyth 		return;
1266*74a4d8c2SCharles.Forsyth 	}else{
1267*74a4d8c2SCharles.Forsyth 		c->leaf = nleaf + 1;
1268*74a4d8c2SCharles.Forsyth 		c->count = cs->leafcount[nleaf];
1269*74a4d8c2SCharles.Forsyth 		c->up = oc->up;
1270*74a4d8c2SCharles.Forsyth 		c->gen = 0;
1271*74a4d8c2SCharles.Forsyth 	}
1272*74a4d8c2SCharles.Forsyth 	cs->free = c + 1;
1273*74a4d8c2SCharles.Forsyth 
1274*74a4d8c2SCharles.Forsyth 	cs->lists[list + 1] = c;
1275*74a4d8c2SCharles.Forsyth 	c->col = cs->col;
1276*74a4d8c2SCharles.Forsyth }
1277*74a4d8c2SCharles.Forsyth 
1278*74a4d8c2SCharles.Forsyth static int
pivot(ulong * c,int a,int n)1279*74a4d8c2SCharles.Forsyth pivot(ulong *c, int a, int n)
1280*74a4d8c2SCharles.Forsyth {
1281*74a4d8c2SCharles.Forsyth 	int j, pi, pj, pk;
1282*74a4d8c2SCharles.Forsyth 
1283*74a4d8c2SCharles.Forsyth 	j = n/6;
1284*74a4d8c2SCharles.Forsyth 	pi = a + j;	/* 1/6 */
1285*74a4d8c2SCharles.Forsyth 	j += j;
1286*74a4d8c2SCharles.Forsyth 	pj = pi + j;	/* 1/2 */
1287*74a4d8c2SCharles.Forsyth 	pk = pj + j;	/* 5/6 */
1288*74a4d8c2SCharles.Forsyth 	if(c[pi] < c[pj]){
1289*74a4d8c2SCharles.Forsyth 		if(c[pi] < c[pk]){
1290*74a4d8c2SCharles.Forsyth 			if(c[pj] < c[pk])
1291*74a4d8c2SCharles.Forsyth 				return pj;
1292*74a4d8c2SCharles.Forsyth 			return pk;
1293*74a4d8c2SCharles.Forsyth 		}
1294*74a4d8c2SCharles.Forsyth 		return pi;
1295*74a4d8c2SCharles.Forsyth 	}
1296*74a4d8c2SCharles.Forsyth 	if(c[pj] < c[pk]){
1297*74a4d8c2SCharles.Forsyth 		if(c[pi] < c[pk])
1298*74a4d8c2SCharles.Forsyth 			return pi;
1299*74a4d8c2SCharles.Forsyth 		return pk;
1300*74a4d8c2SCharles.Forsyth 	}
1301*74a4d8c2SCharles.Forsyth 	return pj;
1302*74a4d8c2SCharles.Forsyth }
1303*74a4d8c2SCharles.Forsyth 
1304*74a4d8c2SCharles.Forsyth static	void
leafsort(ulong * leafcount,ushort * leafmap,int a,int n)1305*74a4d8c2SCharles.Forsyth leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
1306*74a4d8c2SCharles.Forsyth {
1307*74a4d8c2SCharles.Forsyth 	ulong t;
1308*74a4d8c2SCharles.Forsyth 	int j, pi, pj, pn;
1309*74a4d8c2SCharles.Forsyth 
1310*74a4d8c2SCharles.Forsyth 	while(n > 1){
1311*74a4d8c2SCharles.Forsyth 		if(n > 10){
1312*74a4d8c2SCharles.Forsyth 			pi = pivot(leafcount, a, n);
1313*74a4d8c2SCharles.Forsyth 		}else
1314*74a4d8c2SCharles.Forsyth 			pi = a + (n>>1);
1315*74a4d8c2SCharles.Forsyth 
1316*74a4d8c2SCharles.Forsyth 		t = leafcount[pi];
1317*74a4d8c2SCharles.Forsyth 		leafcount[pi] = leafcount[a];
1318*74a4d8c2SCharles.Forsyth 		leafcount[a] = t;
1319*74a4d8c2SCharles.Forsyth 		t = leafmap[pi];
1320*74a4d8c2SCharles.Forsyth 		leafmap[pi] = leafmap[a];
1321*74a4d8c2SCharles.Forsyth 		leafmap[a] = t;
1322*74a4d8c2SCharles.Forsyth 		pi = a;
1323*74a4d8c2SCharles.Forsyth 		pn = a + n;
1324*74a4d8c2SCharles.Forsyth 		pj = pn;
1325*74a4d8c2SCharles.Forsyth 		for(;;){
1326*74a4d8c2SCharles.Forsyth 			do
1327*74a4d8c2SCharles.Forsyth 				pi++;
1328*74a4d8c2SCharles.Forsyth 			while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
1329*74a4d8c2SCharles.Forsyth 			do
1330*74a4d8c2SCharles.Forsyth 				pj--;
1331*74a4d8c2SCharles.Forsyth 			while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
1332*74a4d8c2SCharles.Forsyth 			if(pj < pi)
1333*74a4d8c2SCharles.Forsyth 				break;
1334*74a4d8c2SCharles.Forsyth 			t = leafcount[pi];
1335*74a4d8c2SCharles.Forsyth 			leafcount[pi] = leafcount[pj];
1336*74a4d8c2SCharles.Forsyth 			leafcount[pj] = t;
1337*74a4d8c2SCharles.Forsyth 			t = leafmap[pi];
1338*74a4d8c2SCharles.Forsyth 			leafmap[pi] = leafmap[pj];
1339*74a4d8c2SCharles.Forsyth 			leafmap[pj] = t;
1340*74a4d8c2SCharles.Forsyth 		}
1341*74a4d8c2SCharles.Forsyth 		t = leafcount[a];
1342*74a4d8c2SCharles.Forsyth 		leafcount[a] = leafcount[pj];
1343*74a4d8c2SCharles.Forsyth 		leafcount[pj] = t;
1344*74a4d8c2SCharles.Forsyth 		t = leafmap[a];
1345*74a4d8c2SCharles.Forsyth 		leafmap[a] = leafmap[pj];
1346*74a4d8c2SCharles.Forsyth 		leafmap[pj] = t;
1347*74a4d8c2SCharles.Forsyth 		j = pj - a;
1348*74a4d8c2SCharles.Forsyth 
1349*74a4d8c2SCharles.Forsyth 		n = n-j-1;
1350*74a4d8c2SCharles.Forsyth 		if(j >= n){
1351*74a4d8c2SCharles.Forsyth 			leafsort(leafcount, leafmap, a, j);
1352*74a4d8c2SCharles.Forsyth 			a += j+1;
1353*74a4d8c2SCharles.Forsyth 		}else{
1354*74a4d8c2SCharles.Forsyth 			leafsort(leafcount, leafmap, a + (j+1), n);
1355*74a4d8c2SCharles.Forsyth 			n = j;
1356*74a4d8c2SCharles.Forsyth 		}
1357*74a4d8c2SCharles.Forsyth 	}
1358*74a4d8c2SCharles.Forsyth }
1359