/* Automatically generated by
	VMPluginCodeGenerator VMMaker.oscog-eem.2347 uuid: 062614a7-e3da-4b30-997a-9568911b9ff5
   from
	DeflatePlugin VMMaker.oscog-eem.2347 uuid: 062614a7-e3da-4b30-997a-9568911b9ff5
 */
static char __buildInfo[] = "DeflatePlugin VMMaker.oscog-eem.2347 uuid: 062614a7-e3da-4b30-997a-9568911b9ff5 " __DATE__ ;



#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
#include "sqConfig.h"			/* Configuration options */
#include "sqVirtualMachine.h"	/*  The virtual machine proxy definition */
#include "sqPlatformSpecific.h"	/* Platform specific definitions */

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#ifdef SQUEAK_BUILTIN_PLUGIN
# undef EXPORT
# define EXPORT(returnType) static returnType
#endif

#include "sqMemoryAccess.h"


/*** Constants ***/
#define DeflateHashMask 0x7FFF
#define DeflateHashShift 5
#define DeflateHashTableSize 32768
#define DeflateMaxDistance 0x8000
#define DeflateMaxDistanceCodes 30
#define DeflateMaxLiteralCodes 0x11E
#define DeflateMaxMatch 258
#define DeflateMinMatch 3
#define DeflateWindowMask 0x7FFF
#define DeflateWindowSize 32768
#define MaxBits 16
#define StateNoMoreData 1


/*** Function Prototypes ***/
static sqInt comparewithmin(sqInt here, sqInt matchPos, sqInt minLength);
static sqInt deflateBlockchainLengthgoodMatch(sqInt lastIndex, sqInt chainLength, sqInt goodMatch);
static sqInt determineSizeOfReadStream(sqInt rcvr);
static sqInt determineSizeOfWriteStream(sqInt rcvr);
static sqInt encodeLiteral(sqInt lit);
static sqInt encodeMatchdistance(sqInt length, sqInt dist);
static sqInt findMatchlastLengthlastMatchchainLengthgoodMatch(sqInt here, sqInt lastLength, sqInt lastMatch, sqInt maxChainLength, sqInt goodMatch);
EXPORT(const char*) getModuleName(void);
static sqInt insertStringAt(sqInt here);
static sqInt loadDeflateStreamFrom(sqInt rcvr);
static sqInt loadZipEncoderFrom(sqInt rcvr);
static sqInt nextZipBitsput(sqInt nBits, sqInt value);
EXPORT(sqInt) primitiveDeflateBlock(void);
EXPORT(sqInt) primitiveDeflateUpdateHashTable(void);
EXPORT(sqInt) primitiveInflateDecompressBlock(void);
EXPORT(sqInt) primitiveUpdateAdler32(void);
EXPORT(void) primitiveUpdateGZipCrc32(void);
EXPORT(sqInt) primitiveZipSendBlock(void);
static sqInt sendBlockwithwithwith(sqInt literalStream, sqInt distanceStream, sqInt litTree, sqInt distTree);
EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
static sqInt shouldFlush(void);
static sqInt updateHashAt(sqInt here);
static sqInt updateHash(sqInt nextValue);
static usqInt zipDecodeValueFromsize(unsigned int *table, sqInt tableSize);
static sqInt zipDecompressBlock(void);
static sqInt zipNextBits(sqInt n);


/*** Variables ***/

#if !defined(SQUEAK_BUILTIN_PLUGIN)
static sqInt (*byteSizeOf)(sqInt oop);
static sqInt (*failed)(void);
static sqInt (*fetchClassOf)(sqInt oop);
static sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer);
static sqInt (*fetchPointerofObject)(sqInt index, sqInt oop);
static void * (*firstIndexableField)(sqInt oop);
static sqInt (*instanceSizeOf)(sqInt classObj);
static sqInt (*isBytes)(sqInt oop);
static sqInt (*isPointers)(sqInt oop);
static sqInt (*isWords)(sqInt oop);
static sqInt (*methodArgumentCount)(void);
static sqInt (*nilObject)(void);
static sqInt (*pop)(sqInt nItems);
static sqInt (*popthenPush)(sqInt nItems, sqInt oop);
static sqInt (*positive32BitIntegerFor)(unsigned int integerValue);
static usqInt (*positive32BitValueOf)(sqInt oop);
static sqInt (*primitiveFail)(void);
static sqInt (*pushBool)(sqInt trueOrFalse);
static sqInt (*pushInteger)(sqInt integerValue);
static sqInt (*slotSizeOf)(sqInt oop);
static sqInt (*stackIntegerValue)(sqInt offset);
static sqInt (*stackObjectValue)(sqInt offset);
static sqInt (*stackValue)(sqInt offset);
static sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer);
static sqInt (*superclassOf)(sqInt classPointer);
#else /* !defined(SQUEAK_BUILTIN_PLUGIN) */
extern sqInt byteSizeOf(sqInt oop);
extern sqInt failed(void);
extern sqInt fetchClassOf(sqInt oop);
extern sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer);
extern sqInt fetchPointerofObject(sqInt index, sqInt oop);
extern void * firstIndexableField(sqInt oop);
extern sqInt instanceSizeOf(sqInt classObj);
extern sqInt isBytes(sqInt oop);
extern sqInt isPointers(sqInt oop);
extern sqInt isWords(sqInt oop);
extern sqInt methodArgumentCount(void);
extern sqInt nilObject(void);
extern sqInt pop(sqInt nItems);
extern sqInt popthenPush(sqInt nItems, sqInt oop);
extern sqInt positive32BitIntegerFor(unsigned int integerValue);
extern usqInt positive32BitValueOf(sqInt oop);
extern sqInt primitiveFail(void);
extern sqInt pushBool(sqInt trueOrFalse);
extern sqInt pushInteger(sqInt integerValue);
extern sqInt slotSizeOf(sqInt oop);
extern sqInt stackIntegerValue(sqInt offset);
extern sqInt stackObjectValue(sqInt offset);
extern sqInt stackValue(sqInt offset);
extern sqInt storeIntegerofObjectwithValue(sqInt index, sqInt oop, sqInt integer);
extern sqInt superclassOf(sqInt classPointer);
extern
#endif
struct VirtualMachine* interpreterProxy;
static const char *moduleName =
#ifdef SQUEAK_BUILTIN_PLUGIN
	"ZipPlugin VMMaker.oscog-eem.2347 (i)"
#else
	"ZipPlugin VMMaker.oscog-eem.2347 (e)"
#endif
;
static sqInt readStreamInstSize;
static sqInt writeStreamInstSize;
static unsigned int zipBaseDistance[] = {
/*0*/	0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
/*20*/	1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
	};
static unsigned int zipBaseLength[] = {
/*0*/	0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
/*20*/	64, 80, 96, 112, 128, 160, 192, 224, 0
	};
static sqInt zipBitBuf;
static sqInt zipBitPos;
static sqInt zipBlockPos;
static sqInt zipBlockStart;
static unsigned char* zipCollection;
static sqInt zipCollectionSize;
static unsigned int zipCrcTable[] = {
/*0*/	0, 1996959894, 3993919788U, 2567524794U, 124634137, 1886057615, 3915621685U,
/*7*/	2657392035U, 249268274, 2044508324, 3772115230U, 2547177864U, 162941995, 2125561021,
/*14*/	3887607047U, 2428444049U, 498536548, 1789927666, 4089016648U, 2227061214U,
/*20*/	450548861, 1843258603, 4107580753U, 2211677639U, 325883990, 1684777152, 4251122042U,
/*27*/	2321926636U, 335633487, 1661365465, 4195302755U, 2366115317U, 997073096, 1281953886,
/*34*/	3579855332U, 2724688242U, 1006888145, 1258607687, 3524101629U, 2768942443U,
/*40*/	901097722, 1119000684, 3686517206U, 2898065728U, 853044451, 1172266101, 3705015759U,
/*47*/	2882616665U, 651767980, 1373503546, 3369554304U, 3218104598U, 565507253, 1454621731,
/*54*/	3485111705U, 3099436303U, 671266974, 1594198024, 3322730930U, 2970347812U,
/*60*/	795835527, 1483230225, 3244367275U, 3060149565U, 1994146192, 31158534, 2563907772U,
/*67*/	4023717930U, 1907459465, 112637215, 2680153253U, 3904427059U, 2013776290, 251722036,
/*74*/	2517215374U, 3775830040U, 2137656763, 141376813, 2439277719U, 3865271297U,
/*80*/	1802195444, 476864866, 2238001368U, 4066508878U, 1812370925, 453092731, 2181625025U,
/*87*/	4111451223U, 1706088902, 314042704, 2344532202U, 4240017532U, 1658658271, 366619977,
/*94*/	2362670323U, 4224994405U, 1303535960, 984961486, 2747007092U, 3569037538U,
/*100*/	1256170817, 1037604311, 2765210733U, 3554079995U, 1131014506, 879679996, 2909243462U,
/*107*/	3663771856U, 1141124467, 855842277, 2852801631U, 3708648649U, 1342533948, 654459306,
/*114*/	3188396048U, 3373015174U, 1466479909, 544179635, 3110523913U, 3462522015U,
/*120*/	1591671054, 702138776, 2966460450U, 3352799412U, 1504918807, 783551873, 3082640443U,
/*127*/	3233442989U, 3988292384U, 2596254646U, 62317068, 1957810842, 3939845945U, 2647816111U,
/*134*/	81470997, 1943803523, 3814918930U, 2489596804U, 225274430, 2053790376,
/*140*/	3826175755U, 2466906013U, 167816743, 2097651377, 4027552580U, 2265490386U, 503444072,
/*147*/	1762050814, 4150417245U, 2154129355U, 426522225, 1852507879, 4275313526U, 2312317920U,
/*154*/	282753626, 1742555852, 4189708143U, 2394877945U, 397917763, 1622183637,
/*160*/	3604390888U, 2714866558U, 953729732, 1340076626, 3518719985U, 2797360999U, 1068828381,
/*167*/	1219638859, 3624741850U, 2936675148U, 906185462, 1090812512, 3747672003U, 2825379669U,
/*174*/	829329135, 1181335161, 3412177804U, 3160834842U, 628085408, 1382605366,
/*180*/	3423369109U, 3138078467U, 570562233, 1426400815, 3317316542U, 2998733608U, 733239954,
/*187*/	1555261956, 3268935591U, 3050360625U, 752459403, 1541320221, 2607071920U, 3965973030U,
/*194*/	1969922972, 40735498, 2617837225U, 3943577151U, 1913087877, 83908371,
/*200*/	2512341634U, 3803740692U, 2075208622, 213261112, 2463272603U, 3855990285U, 2094854071,
/*207*/	198958881, 2262029012U, 4057260610U, 1759359992, 534414190, 2176718541U, 4139329115U,
/*214*/	1873836001, 414664567, 2282248934U, 4279200368U, 1711684554, 285281116,
/*220*/	2405801727U, 4167216745U, 1634467795, 376229701, 2685067896U, 3608007406U, 1308918612,
/*227*/	956543938, 2808555105U, 3495958263U, 1231636301, 1047427035, 2932959818U, 3654703836U,
/*234*/	1088359270, 936918000, 2847714899U, 3736837829U, 1202900863, 817233897,
/*240*/	3183342108U, 3401237130U, 1404277552, 615818150, 3134207493U, 3453421203U, 1423857449,
/*247*/	601450431, 3009837614U, 3294710456U, 1567103746, 711928724, 3020668471U, 3272380065U,
/*254*/	1510334235, 755167117
	};
static unsigned int zipDistanceCodes[] = {
/*0*/	0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
/*20*/	8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
/*40*/	10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
/*60*/	11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
/*80*/	12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
/*100*/	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
/*120*/	13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
/*140*/	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
/*160*/	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
/*180*/	14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
/*200*/	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
/*220*/	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
/*240*/	15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
/*260*/	18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
/*280*/	23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
/*300*/	24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
/*320*/	26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
/*340*/	26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
/*360*/	27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/*380*/	27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/*400*/	28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/*420*/	28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/*440*/	28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
/*460*/	29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
/*480*/	29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
/*500*/	29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
	};
static unsigned int* zipDistanceFreq;
static unsigned int* zipDistances;
static unsigned int* zipDistTable;
static sqInt zipDistTableSize;
static unsigned int zipExtraDistanceBits[] = {
/*0*/	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
/*20*/	9, 9, 10, 10, 11, 11, 12, 12, 13, 13
	};
static unsigned int zipExtraLengthBits[] = {
/*0*/	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
/*20*/	4, 4, 4, 4, 5, 5, 5, 5, 0
	};
static unsigned int* zipHashHead;
static unsigned int* zipHashTail;
static sqInt zipHashValue;
static sqInt zipLiteralCount;
static unsigned int* zipLiteralFreq;
static sqInt zipLiteralSize;
static unsigned char* zipLiterals;
static unsigned int* zipLitTable;
static sqInt zipLitTableSize;
static sqInt zipMatchCount;
static unsigned int zipMatchLengthCodes[] = {
/*0*/	257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268,
/*16*/	269, 269, 269, 269,
/*20*/	270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, 273, 273, 273, 273,
/*36*/	273, 273, 273, 273,
/*40*/	274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275,
/*56*/	276, 276, 276, 276,
/*60*/	276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
/*76*/	277, 277, 277, 277,
/*80*/	278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
/*96*/	279, 279, 279, 279,
/*100*/	279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280,
/*116*/	280, 280, 280, 280,
/*120*/	280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281, 281,
/*136*/	281, 281, 281, 281,
/*140*/	281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
/*156*/	281, 281, 281, 281,
/*160*/	282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
/*176*/	282, 282, 282, 282,
/*180*/	282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283, 283,
/*196*/	283, 283, 283, 283,
/*200*/	283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
/*216*/	283, 283, 283, 283,
/*220*/	283, 283, 283, 283, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
/*236*/	284, 284, 284, 284,
/*240*/	284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284
	};
static sqInt zipPosition;
static sqInt zipReadLimit;
static unsigned char* zipSource;
static sqInt zipSourceLimit;
static sqInt zipSourcePos;
static sqInt zipState;



/*	Compare the two strings and return the length of matching characters.
	minLength is a lower bound for match lengths that will be accepted.
	Note: here and matchPos are zero based. */

	/* DeflatePlugin>>#compare:with:min: */
static sqInt
comparewithmin(sqInt here, sqInt matchPos, sqInt minLength)
{
    sqInt length;


	/* First test if we can actually get longer than minLength */
	if (!((zipCollection[here + minLength]) == (zipCollection[matchPos + minLength]))) {
		return 0;
	}
	if (!((zipCollection[(here + minLength) - 1]) == (zipCollection[(matchPos + minLength) - 1]))) {
		return 0;
	}
	if (!((zipCollection[here]) == (zipCollection[matchPos]))) {
		return 0;
	}
	if (!((zipCollection[here + 1]) == (zipCollection[matchPos + 1]))) {
		return 1;
	}
	length = 2;
	while ((length < DeflateMaxMatch)
	 && ((zipCollection[here + length]) == (zipCollection[matchPos + length]))) {
		length += 1;
	}
	return length;
}


/*	Continue deflating the receiver's collection from blockPosition to
	lastIndex. Note that lastIndex must be at least MaxMatch away from the end
	of collection
 */

	/* DeflatePlugin>>#deflateBlock:chainLength:goodMatch: */
static sqInt
deflateBlockchainLengthgoodMatch(sqInt lastIndex, sqInt chainLength, sqInt goodMatch)
{
    unsigned int distance;
    sqInt flushNeeded;
    sqInt hasMatch;
    sqInt here;
    sqInt here1;
    sqInt hereLength;
    sqInt hereMatch;
    sqInt i;
    sqInt lit;
    unsigned int literal;
    sqInt matchResult;
    sqInt newLength;
    sqInt newMatch;
    sqInt nextValue;
    sqInt nextValue1;
    sqInt nextValue2;
    unsigned int prevEntry;
    unsigned int prevEntry1;
    unsigned int prevEntry2;

	hereLength = 0;
	hereMatch = 0;
	if (zipBlockPos > lastIndex) {
		return 0;
	}
	if (zipLiteralCount >= zipLiteralSize) {
		return 1;
	}
	hasMatch = 0;
	here = zipBlockPos;
	while (here <= lastIndex) {
		if (!hasMatch) {

			/* Find the first match */
			matchResult = findMatchlastLengthlastMatchchainLengthgoodMatch(here, DeflateMinMatch - 1, here, chainLength, goodMatch);
			/* begin insertStringAt: */
			nextValue = zipCollection[(here + DeflateMinMatch) - 1];
			zipHashValue = ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ nextValue) & DeflateHashMask;
			prevEntry = zipHashHead[zipHashValue];
			zipHashHead[zipHashValue] = here;
			zipHashTail[here & DeflateWindowMask] = prevEntry;
			hereMatch = matchResult & 0xFFFF;
			hereLength = ((usqInt) matchResult >> 16);
		}
		matchResult = findMatchlastLengthlastMatchchainLengthgoodMatch(here + 1, hereLength, hereMatch, chainLength, goodMatch);
		newMatch = matchResult & 0xFFFF;

		/* Now check if the next match is better than the current one.
		   If not, output the current match (provided that the current match
		   is at least MinMatch long) */
		newLength = ((usqInt) matchResult >> 16);
		if ((hereLength >= newLength)
		 && (hereLength >= DeflateMinMatch)) {

			/* Encode the current match */
			/* begin encodeMatch:distance: */
			zipLiterals[zipLiteralCount] = (hereLength - DeflateMinMatch);
			zipDistances[zipLiteralCount] = (here - hereMatch);
			literal = zipMatchLengthCodes[hereLength - DeflateMinMatch];
			zipLiteralFreq[literal] = ((zipLiteralFreq[literal]) + 1);
			if ((here - hereMatch) < 257) {
				distance = zipDistanceCodes[(here - hereMatch) - 1];
			}
			else {
				distance = zipDistanceCodes[256 + (((usqInt) ((here - hereMatch) - 1) >> 7))];
			}
			zipDistanceFreq[distance] = ((zipDistanceFreq[distance]) + 1);
			zipLiteralCount += 1;
			zipMatchCount += 1;
			flushNeeded = (zipLiteralCount == zipLiteralSize)
			 || (((zipLiteralCount & 0xFFF) == 0)
			 && (shouldFlush()));
			for (i = 1; i < hereLength; i += 1) {
				/* begin insertStringAt: */
				here1 = (here += 1);
				/* begin updateHash: */
				nextValue1 = zipCollection[(here1 + DeflateMinMatch) - 1];
				zipHashValue = ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ nextValue1) & DeflateHashMask;
				prevEntry1 = zipHashHead[zipHashValue];
				zipHashHead[zipHashValue] = here1;
				zipHashTail[here1 & DeflateWindowMask] = prevEntry1;
			}
			hasMatch = 0;
			here += 1;
		}
		else {

			/* Either the next match is better than the current one or we didn't
			   have a good match after all (e.g., current match length < MinMatch).
			   Output a single literal. */
			/* begin encodeLiteral: */
			lit = zipCollection[here];
			zipLiterals[zipLiteralCount] = lit;
			zipDistances[zipLiteralCount] = 0;
			zipLiteralFreq[lit] = ((zipLiteralFreq[lit]) + 1);
			zipLiteralCount += 1;
			flushNeeded = (zipLiteralCount == zipLiteralSize)
			 || (((zipLiteralCount & 0xFFF) == 0)
			 && (shouldFlush()));
			here += 1;
			if ((here <= lastIndex)
			 && (!flushNeeded)) {

				/* Cache the results for the next round */
				/* begin insertStringAt: */
				nextValue2 = zipCollection[(here + DeflateMinMatch) - 1];
				zipHashValue = ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ nextValue2) & DeflateHashMask;
				prevEntry2 = zipHashHead[zipHashValue];
				zipHashHead[zipHashValue] = here;
				zipHashTail[here & DeflateWindowMask] = prevEntry2;
				hasMatch = 1;
				hereMatch = newMatch;
				hereLength = newLength;
			}
		}
		if (flushNeeded) {
			zipBlockPos = here;
			return 1;
		}
	}
	zipBlockPos = here;
	return 0;
}


/*	Determine the inst size of the class above DeflateStream by
	looking for the first class whose inst size is less than 13. */

	/* InflatePlugin>>#determineSizeOfReadStream: */
static sqInt
determineSizeOfReadStream(sqInt rcvr)
{
    sqInt class;

	class = fetchClassOf(rcvr);
	while ((class != (nilObject()))
	 && ((instanceSizeOf(class)) >= 13)) {
		class = superclassOf(class);
	}
	if (class == (nilObject())) {
		return 0;
	}
	readStreamInstSize = instanceSizeOf(class);
	return 1;
}


/*	Determine the inst size of the class above DeflateStream or
	ZipEncoder by looking for the first class whose inst size is less than 7. */

	/* DeflatePlugin>>#determineSizeOfWriteStream: */
static sqInt
determineSizeOfWriteStream(sqInt rcvr)
{
    sqInt class;

	class = fetchClassOf(rcvr);
	while ((class != (nilObject()))
	 && ((instanceSizeOf(class)) >= 7)) {
		class = superclassOf(class);
	}
	if (class == (nilObject())) {
		return 0;
	}
	writeStreamInstSize = instanceSizeOf(class);
	return 1;
}


/*	Encode the given literal */

	/* DeflatePlugin>>#encodeLiteral: */
static sqInt
encodeLiteral(sqInt lit)
{
	zipLiterals[zipLiteralCount] = lit;
	zipDistances[zipLiteralCount] = 0;
	zipLiteralFreq[lit] = ((zipLiteralFreq[lit]) + 1);
	zipLiteralCount += 1;
	return (zipLiteralCount == zipLiteralSize)
	 || (((zipLiteralCount & 0xFFF) == 0)
	 && (shouldFlush()));
}


/*	Encode the given match of length length starting at dist bytes ahead */

	/* DeflatePlugin>>#encodeMatch:distance: */
static sqInt
encodeMatchdistance(sqInt length, sqInt dist)
{
    unsigned int distance;
    unsigned int literal;

	zipLiterals[zipLiteralCount] = (length - DeflateMinMatch);
	zipDistances[zipLiteralCount] = dist;
	literal = zipMatchLengthCodes[length - DeflateMinMatch];
	zipLiteralFreq[literal] = ((zipLiteralFreq[literal]) + 1);
	if (dist < 257) {
		distance = zipDistanceCodes[dist - 1];
	}
	else {
		distance = zipDistanceCodes[256 + (((usqInt) (dist - 1) >> 7))];
	}
	zipDistanceFreq[distance] = ((zipDistanceFreq[distance]) + 1);
	zipLiteralCount += 1;
	zipMatchCount += 1;
	return (zipLiteralCount == zipLiteralSize)
	 || (((zipLiteralCount & 0xFFF) == 0)
	 && (shouldFlush()));
}


/*	Find the longest match for the string starting at here.
	If there is no match longer than lastLength return lastMatch/lastLength.
	Traverse at most maxChainLength entries in the hash table.
	Stop if a match of at least goodMatch size has been found. */

	/* DeflatePlugin>>#findMatch:lastLength:lastMatch:chainLength:goodMatch: */
static sqInt
findMatchlastLengthlastMatchchainLengthgoodMatch(sqInt here, sqInt lastLength, sqInt lastMatch, sqInt maxChainLength, sqInt goodMatch)
{
    sqInt bestLength;
    sqInt chainLength;
    sqInt distance;
    sqInt length;
    sqInt length1;
    sqInt limit;
    unsigned int matchPos;
    sqInt matchResult;


	/* Compute the default match result */

	/* There is no way to find a better match than MaxMatch */
	matchResult = (((usqInt) lastLength << 16)) | lastMatch;
	if (lastLength >= DeflateMaxMatch) {
		return matchResult;
	}

	/* Compute the distance to the (possible) match */
	matchPos = zipHashHead[((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ (zipCollection[(here + DeflateMinMatch) - 1])) & DeflateHashMask];

	/* Note: It is required that 0 < distance < MaxDistance */
	distance = here - matchPos;
	if (!((distance > 0)
		 && (distance < DeflateMaxDistance))) {
		return matchResult;
	}

	/* Max. nr of match chain to search */
	chainLength = maxChainLength;
	if (here > DeflateMaxDistance) {

		/* Limit for matches that are too old */
		limit = here - DeflateMaxDistance;
	}
	else {
		limit = 0;
	}
	bestLength = lastLength;
	while (1) {

		/* Compare the current string with the string at match position */
		/* begin compare:with:min: */
		if (!((zipCollection[here + bestLength]) == (zipCollection[matchPos + bestLength]))) {
			length = 0;
			goto l1;
		}
		if (!((zipCollection[(here + bestLength) - 1]) == (zipCollection[(matchPos + bestLength) - 1]))) {
			length = 0;
			goto l1;
		}
		if (!((zipCollection[here]) == (zipCollection[matchPos]))) {
			length = 0;
			goto l1;
		}
		if (!((zipCollection[here + 1]) == (zipCollection[matchPos + 1]))) {
			length = 1;
			goto l1;
		}
		length1 = 2;
		while ((length1 < DeflateMaxMatch)
		 && ((zipCollection[here + length1]) == (zipCollection[matchPos + length1]))) {
			length1 += 1;
		}
		length = length1;
	l1:	/* end compare:with:min: */;
		if ((here + length) > zipPosition) {
			length = zipPosition - here;
		}
		if ((length == DeflateMinMatch)
		 && ((here - matchPos) > (DeflateMaxDistance / 4))) {
			length = DeflateMinMatch - 1;
		}
		if (length > bestLength) {

			/* We have a new (better) match than before */
			/* Compute the new match result */
			matchResult = (((usqInt) length << 16)) | matchPos;

			/* There is no way to find a better match than MaxMatch */
			bestLength = length;
			if (bestLength >= DeflateMaxMatch) {
				return matchResult;
			}
			if (bestLength > goodMatch) {
				return matchResult;
			}
		}
		if (!(((chainLength -= 1)) > 0)) {
			return matchResult;
		}
		matchPos = zipHashTail[matchPos & DeflateWindowMask];
		if (matchPos <= limit) {
			return matchResult;
		}
	}
	return 0;
}


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

	/* InterpreterPlugin>>#getModuleName */
EXPORT(const char*)
getModuleName(void)
{
	return moduleName;
}


/*	Insert the string at the given start position into the hash table.
	Note: The hash value is updated starting at MinMatch-1 since
	all strings before have already been inserted into the hash table
	(and the hash value is updated as well). */

	/* DeflatePlugin>>#insertStringAt: */
static sqInt
insertStringAt(sqInt here)
{
    sqInt nextValue;
    unsigned int prevEntry;

	/* begin updateHash: */
	nextValue = zipCollection[(here + DeflateMinMatch) - 1];
	zipHashValue = ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ nextValue) & DeflateHashMask;
	prevEntry = zipHashHead[zipHashValue];
	zipHashHead[zipHashValue] = here;
	zipHashTail[here & DeflateWindowMask] = prevEntry;
	return 0;
}

	/* DeflatePlugin>>#loadDeflateStreamFrom: */
static sqInt
loadDeflateStreamFrom(sqInt rcvr)
{
    sqInt oop;

	if (!((isPointers(rcvr))
		 && ((slotSizeOf(rcvr)) >= 15))) {
		return 0;
	}
	oop = fetchPointerofObject(0, rcvr);
	if (!(isBytes(oop))) {
		return 0;
	}
	if (writeStreamInstSize == 0) {
		if (!(determineSizeOfWriteStream(rcvr))) {
			return 0;
		}
		if ((slotSizeOf(rcvr)) < (writeStreamInstSize + 5)) {
			writeStreamInstSize = 0;
			return 0;
		}
	}
	zipCollection = firstIndexableField(oop);
	zipCollectionSize = byteSizeOf(oop);
	zipPosition = fetchIntegerofObject(1, rcvr);

	/* zipWriteLimit := interpreterProxy fetchInteger: 3 ofObject: rcvr. */
	zipReadLimit = fetchIntegerofObject(2, rcvr);
	oop = fetchPointerofObject(writeStreamInstSize, rcvr);
	if (!((isWords(oop))
		 && ((slotSizeOf(oop)) == DeflateHashTableSize))) {
		return 0;
	}
	zipHashHead = firstIndexableField(oop);
	oop = fetchPointerofObject(writeStreamInstSize + 1, rcvr);
	if (!((isWords(oop))
		 && ((slotSizeOf(oop)) == DeflateWindowSize))) {
		return 0;
	}
	zipHashTail = firstIndexableField(oop);
	zipHashValue = fetchIntegerofObject(writeStreamInstSize + 2, rcvr);

	/* zipBlockStart := interpreterProxy fetchInteger: writeStreamInstSize + 4 ofObject: rcvr. */
	zipBlockPos = fetchIntegerofObject(writeStreamInstSize + 3, rcvr);
	oop = fetchPointerofObject(writeStreamInstSize + 5, rcvr);
	if (!(isBytes(oop))) {
		return 0;
	}
	zipLiteralSize = slotSizeOf(oop);
	zipLiterals = firstIndexableField(oop);
	oop = fetchPointerofObject(writeStreamInstSize + 6, rcvr);
	if (!((isWords(oop))
		 && ((slotSizeOf(oop)) >= zipLiteralSize))) {
		return 0;
	}
	zipDistances = firstIndexableField(oop);
	oop = fetchPointerofObject(writeStreamInstSize + 7, rcvr);
	if (!((isWords(oop))
		 && ((slotSizeOf(oop)) == DeflateMaxLiteralCodes))) {
		return 0;
	}
	zipLiteralFreq = firstIndexableField(oop);
	oop = fetchPointerofObject(writeStreamInstSize + 8, rcvr);
	if (!((isWords(oop))
		 && ((slotSizeOf(oop)) == DeflateMaxDistanceCodes))) {
		return 0;
	}
	zipDistanceFreq = firstIndexableField(oop);
	zipLiteralCount = fetchIntegerofObject(writeStreamInstSize + 9, rcvr);
	zipMatchCount = fetchIntegerofObject(writeStreamInstSize + 10, rcvr);
	return !(failed());
}

	/* DeflatePlugin>>#loadZipEncoderFrom: */
static sqInt
loadZipEncoderFrom(sqInt rcvr)
{
    sqInt oop;

	if (writeStreamInstSize == 0) {
		if (!(determineSizeOfWriteStream(rcvr))) {
			return 0;
		}
		if ((slotSizeOf(rcvr)) < (writeStreamInstSize + 3)) {
			writeStreamInstSize = 0;
			return 0;
		}
	}
	if (!((isPointers(rcvr))
		 && ((slotSizeOf(rcvr)) >= (writeStreamInstSize + 3)))) {
		return 0;
	}
	oop = fetchPointerofObject(0, rcvr);
	if (!(isBytes(oop))) {
		return primitiveFail();
	}
	zipCollection = firstIndexableField(oop);
	zipCollectionSize = byteSizeOf(oop);
	zipPosition = fetchIntegerofObject(1, rcvr);

	/* zipWriteLimit := interpreterProxy fetchInteger: 3 ofObject: rcvr. */
	zipReadLimit = fetchIntegerofObject(2, rcvr);
	zipBitBuf = fetchIntegerofObject(writeStreamInstSize + 1, rcvr);
	zipBitPos = fetchIntegerofObject(writeStreamInstSize + 2, rcvr);
	return !(failed());
}


/*	Require:
	zipCollection, zipCollectionSize, zipPosition,
	zipBitBuf, zipBitPos.
	 */

	/* DeflatePlugin>>#nextZipBits:put: */
static sqInt
nextZipBitsput(sqInt nBits, sqInt value)
{
	if (!((value >= 0)
		 && ((1U << nBits) > value))) {
		return primitiveFail();
	}
	zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value) << zipBitPos)));
	zipBitPos += nBits;
	while ((zipBitPos >= 8)
	 && (zipPosition < zipCollectionSize)) {
		zipCollection[zipPosition] = (zipBitBuf & 0xFF);
		zipPosition += 1;
		zipBitBuf = ((usqInt) zipBitBuf) >> 8;
		zipBitPos -= 8;
	}
	return 0;
}


/*	Primitive. Deflate the current contents of the receiver. */

	/* DeflatePlugin>>#primitiveDeflateBlock */
EXPORT(sqInt)
primitiveDeflateBlock(void)
{
    sqInt chainLength;
    sqInt goodMatch;
    sqInt lastIndex;
    sqInt rcvr;
    sqInt result;

	if (!((methodArgumentCount()) == 3)) {
		return primitiveFail();
	}
	goodMatch = stackIntegerValue(0);
	chainLength = stackIntegerValue(1);
	lastIndex = stackIntegerValue(2);
	rcvr = stackObjectValue(3);
	if (failed()) {
		return null;
	}
	if (!(loadDeflateStreamFrom(rcvr))) {
		return primitiveFail();
	}
	result = deflateBlockchainLengthgoodMatch(lastIndex, chainLength, goodMatch);
	if (!(failed())) {

		/* Store back modified values */
		storeIntegerofObjectwithValue(writeStreamInstSize + 2, rcvr, zipHashValue);
		storeIntegerofObjectwithValue(writeStreamInstSize + 3, rcvr, zipBlockPos);
		storeIntegerofObjectwithValue(writeStreamInstSize + 9, rcvr, zipLiteralCount);
		storeIntegerofObjectwithValue(writeStreamInstSize + 10, rcvr, zipMatchCount);
	}
	if (!(failed())) {
		pop(4);
		pushBool(result);
	}
	return 0;
}


/*	Primitive. Update the hash tables after data has been moved by delta. */

	/* DeflatePlugin>>#primitiveDeflateUpdateHashTable */
EXPORT(sqInt)
primitiveDeflateUpdateHashTable(void)
{
    sqInt delta;
    int entry;
    sqInt i;
    sqInt table;
    int *tablePtr;
    sqInt tableSize;

	if (!((methodArgumentCount()) == 2)) {
		return primitiveFail();
	}
	delta = stackIntegerValue(0);
	table = stackObjectValue(1);
	if (failed()) {
		return null;
	}
	if (!(isWords(table))) {
		return primitiveFail();
	}
	tableSize = slotSizeOf(table);
	tablePtr = firstIndexableField(table);
	for (i = 0; i < tableSize; i += 1) {
		entry = tablePtr[i];
		if (entry >= delta) {
			tablePtr[i] = (entry - delta);
		}
		else {
			tablePtr[i] = 0;
		}
	}
	pop(2);
	return 0;
}


/*	Primitive. Inflate a single block. */

	/* InflatePlugin>>#primitiveInflateDecompressBlock */
EXPORT(sqInt)
primitiveInflateDecompressBlock(void)
{
    sqInt oop;
    sqInt rcvr;

	if (!((methodArgumentCount()) == 2)) {
		return primitiveFail();
	}
	oop = stackValue(0);
	if (!(isWords(oop))) {
		return primitiveFail();
	}
	zipDistTable = firstIndexableField(oop);

	/* literal table */
	zipDistTableSize = slotSizeOf(oop);
	oop = stackValue(1);
	if (!(isWords(oop))) {
		return primitiveFail();
	}
	zipLitTable = firstIndexableField(oop);

	/* Receiver (InflateStream) */
	zipLitTableSize = slotSizeOf(oop);
	rcvr = stackValue(2);
	if (!(isPointers(rcvr))) {
		return primitiveFail();
	}
	if (readStreamInstSize == 0) {
		if (!(determineSizeOfReadStream(rcvr))) {
			return primitiveFail();
		}
		if ((slotSizeOf(rcvr)) < (readStreamInstSize + 8)) {
			readStreamInstSize = 0;
			return primitiveFail();
		}
	}
	if ((slotSizeOf(rcvr)) < (readStreamInstSize + 8)) {
		return primitiveFail();
	}
	zipReadLimit = fetchIntegerofObject(2, rcvr);
	zipState = fetchIntegerofObject(readStreamInstSize, rcvr);
	zipBitBuf = fetchIntegerofObject(readStreamInstSize + 1, rcvr);
	zipBitPos = fetchIntegerofObject(readStreamInstSize + 2, rcvr);
	zipSourcePos = fetchIntegerofObject(readStreamInstSize + 4, rcvr);
	zipSourceLimit = fetchIntegerofObject(readStreamInstSize + 5, rcvr);
	if (failed()) {
		return null;
	}
	zipReadLimit -= 1;
	zipSourcePos -= 1;

	/* collection */
	zipSourceLimit -= 1;
	oop = fetchPointerofObject(0, rcvr);
	if (!(isBytes(oop))) {
		return primitiveFail();
	}
	zipCollection = firstIndexableField(oop);

	/* source */
	zipCollectionSize = byteSizeOf(oop);
	oop = fetchPointerofObject(readStreamInstSize + 3, rcvr);
	if (!(isBytes(oop))) {
		return primitiveFail();
	}

	/* do the primitive */
	zipSource = firstIndexableField(oop);
	zipDecompressBlock();
	if (!(failed())) {

		/* store modified values back */
		storeIntegerofObjectwithValue(2, rcvr, zipReadLimit + 1);
		storeIntegerofObjectwithValue(readStreamInstSize, rcvr, zipState);
		storeIntegerofObjectwithValue(readStreamInstSize + 1, rcvr, zipBitBuf);
		storeIntegerofObjectwithValue(readStreamInstSize + 2, rcvr, zipBitPos);
		storeIntegerofObjectwithValue(readStreamInstSize + 4, rcvr, zipSourcePos + 1);
		pop(2);
	}
	return 0;
}


/*	Primitive. Update a 32bit CRC value. */

	/* DeflatePlugin>>#primitiveUpdateAdler32 */
EXPORT(sqInt)
primitiveUpdateAdler32(void)
{
    unsigned int  adler32;
    unsigned char b;
    unsigned char *bytePtr;
    sqInt collection;
    sqInt i;
    sqInt length;
    unsigned int s1;
    unsigned int s2;
    sqInt startIndex;
    sqInt stopIndex;

	if (!((methodArgumentCount()) == 4)) {
		return primitiveFail();
	}
	collection = stackObjectValue(0);
	stopIndex = stackIntegerValue(1);
	startIndex = stackIntegerValue(2);
	adler32 = positive32BitValueOf(stackValue(3));
	if (failed()) {
		return 0;
	}
	if (!((isBytes(collection))
		 && ((stopIndex >= startIndex)
		 && (startIndex > 0)))) {
		return primitiveFail();
	}
	length = byteSizeOf(collection);
	if (!(stopIndex <= length)) {
		return primitiveFail();
	}
	bytePtr = firstIndexableField(collection);
	startIndex -= 1;
	stopIndex -= 1;
	s1 = adler32 & 0xFFFF;
	s2 = (((usqInt) adler32) >> 16) & 0xFFFF;
	for (i = startIndex; i <= stopIndex; i += 1) {
		b = bytePtr[i];
		s1 = (s1 + b) % 65521;
		s2 = (s2 + s1) % 65521;
	}
	adler32 = (((usqInt) s2 << 16)) + s1;
	popthenPush(5, positive32BitIntegerFor(adler32));
	return 0;
}


/*	Primitive. Update a 32bit CRC value. */

	/* DeflatePlugin>>#primitiveUpdateGZipCrc32 */
EXPORT(void)
primitiveUpdateGZipCrc32(void)
{
    unsigned char *bytePtr;
    sqInt collection;
    sqInt crc;
    sqInt i;
    sqInt length;
    sqInt startIndex;
    sqInt stopIndex;

	if (!((methodArgumentCount()) == 4)) {
		primitiveFail();
		return;
	}
	collection = stackObjectValue(0);
	stopIndex = stackIntegerValue(1);
	startIndex = stackIntegerValue(2);
	crc = positive32BitValueOf(stackValue(3));
	if (failed()) {
		return;
	}
	if (!((isBytes(collection))
		 && ((stopIndex >= startIndex)
		 && (startIndex > 0)))) {
		primitiveFail();
		return;
	}
	length = byteSizeOf(collection);
	if (!(stopIndex <= length)) {
		primitiveFail();
		return;
	}
	bytePtr = firstIndexableField(collection);
	startIndex -= 1;
	stopIndex -= 1;
	for (i = startIndex; i <= stopIndex; i += 1) {
		crc = (zipCrcTable[(crc ^ (bytePtr[i])) & 0xFF]) ^ (((usqInt) crc) >> 8);
	}
	popthenPush(5, positive32BitIntegerFor(crc));
}

	/* DeflatePlugin>>#primitiveZipSendBlock */
EXPORT(sqInt)
primitiveZipSendBlock(void)
{
    unsigned int code;
    unsigned int dist;
    unsigned int *distArray;
    unsigned int *distBitLengths;
    sqInt distBlCount;
    unsigned int *distCodes;
    sqInt distStream;
    sqInt distTree;
    unsigned int extra;
    unsigned char lit;
    unsigned char *litArray;
    sqInt litBlCount;
    sqInt litLimit;
    sqInt litPos;
    sqInt litStream;
    sqInt litTree;
    unsigned int *llBitLengths;
    unsigned int *llCodes;
    sqInt nBits;
    sqInt nBits1;
    sqInt nBits2;
    sqInt oop;
    sqInt rcvr;
    sqInt result;
    sqInt sum;
    sqInt value;
    sqInt value1;
    sqInt value2;

	if (!((methodArgumentCount()) == 4)) {
		return primitiveFail();
	}
	distTree = stackObjectValue(0);
	litTree = stackObjectValue(1);
	distStream = stackObjectValue(2);
	litStream = stackObjectValue(3);
	rcvr = stackObjectValue(4);
	if (failed()) {
		return null;
	}
	if (!(loadZipEncoderFrom(rcvr))) {
		return primitiveFail();
	}
	if (!((isPointers(distTree))
		 && ((slotSizeOf(distTree)) >= 2))) {
		return primitiveFail();
	}
	if (!((isPointers(litTree))
		 && ((slotSizeOf(litTree)) >= 2))) {
		return primitiveFail();
	}
	if (!((isPointers(litStream))
		 && ((slotSizeOf(litStream)) >= 3))) {
		return primitiveFail();
	}
	if (!((isPointers(distStream))
		 && ((slotSizeOf(distStream)) >= 3))) {
		return primitiveFail();
	}
	/* begin sendBlock:with:with:with: */
	oop = fetchPointerofObject(0, litStream);
	litPos = fetchIntegerofObject(1, litStream);
	litLimit = fetchIntegerofObject(2, litStream);
	if (!((litPos <= litLimit)
		 && ((isBytes(oop))
		 && (litLimit <= (byteSizeOf(oop)))))) {
		result = primitiveFail();
		goto l7;
	}
	litArray = firstIndexableField(oop);
	oop = fetchPointerofObject(0, distStream);
	if (!((isWords(oop))
		 && ((litLimit <= (slotSizeOf(oop)))
		 && (((fetchIntegerofObject(1, distStream)) == litPos)
		 && ((fetchIntegerofObject(2, distStream)) == litLimit))))) {
		result = primitiveFail();
		goto l7;
	}
	distArray = firstIndexableField(oop);
	oop = fetchPointerofObject(0, litTree);
	if (!(isWords(oop))) {
		result = primitiveFail();
		goto l7;
	}
	litBlCount = slotSizeOf(oop);
	llBitLengths = firstIndexableField(oop);
	oop = fetchPointerofObject(1, litTree);
	if (!((isWords(oop))
		 && (litBlCount == (slotSizeOf(oop))))) {
		result = primitiveFail();
		goto l7;
	}
	llCodes = firstIndexableField(oop);
	oop = fetchPointerofObject(0, distTree);
	if (!(isWords(oop))) {
		result = primitiveFail();
		goto l7;
	}
	distBlCount = slotSizeOf(oop);
	distBitLengths = firstIndexableField(oop);
	oop = fetchPointerofObject(1, distTree);
	if (!((isWords(oop))
		 && (distBlCount == (slotSizeOf(oop))))) {
		result = primitiveFail();
		goto l7;
	}
	distCodes = firstIndexableField(oop);
	/* begin nextZipBits:put: */
	if (!((0 >= 0)
		 && ((1U << 0) > 0))) {
		primitiveFail();
		goto l6;
	}
	zipBitBuf = zipBitBuf | (0U << zipBitPos);
	zipBitPos += 0;
	while ((zipBitPos >= 8)
	 && (zipPosition < zipCollectionSize)) {
		zipCollection[zipPosition] = (zipBitBuf & 0xFF);
		zipPosition += 1;
		zipBitBuf = ((usqInt) zipBitBuf) >> 8;
		zipBitPos -= 8;
	}
	l6:	/* end nextZipBits:put: */;
	sum = 0;
	while ((litPos < litLimit)
	 && ((zipPosition + 4) < zipCollectionSize)) {
		lit = litArray[litPos];
		dist = distArray[litPos];
		litPos += 1;
		if (dist == 0) {

			/* literal */
			sum += 1;
			if (!(lit < litBlCount)) {
				result = primitiveFail();
				goto l7;
			}
			/* begin nextZipBits:put: */
			nBits = llBitLengths[lit];
			value = llCodes[lit];
			if (!((value >= 0)
				 && ((1U << nBits) > value))) {
				primitiveFail();
				goto l1;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value) << zipBitPos)));
			zipBitPos += nBits;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l1:	/* end nextZipBits:put: */;
		}
		else {

			/* match */
			sum = (sum + lit) + DeflateMinMatch;
			if (!(lit < 256)) {
				result = primitiveFail();
				goto l7;
			}
			code = zipMatchLengthCodes[lit];
			if (!(code < litBlCount)) {
				result = primitiveFail();
				goto l7;
			}
			/* begin nextZipBits:put: */
			nBits1 = llBitLengths[code];
			value1 = llCodes[code];
			if (!((value1 >= 0)
				 && ((1U << nBits1) > value1))) {
				primitiveFail();
				goto l4;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value1) << zipBitPos)));
			zipBitPos += nBits1;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l4:	/* end nextZipBits:put: */;
			extra = zipExtraLengthBits[code - 257];
			if (!(extra == 0)) {
				lit -= zipBaseLength[code - 257];
				/* begin nextZipBits:put: */
				if (!((lit >= 0)
					 && ((1U << extra) > lit))) {
					primitiveFail();
					goto l2;
				}
				zipBitBuf = zipBitBuf | (((usqInt)(lit) << zipBitPos));
				zipBitPos += extra;
				while ((zipBitPos >= 8)
				 && (zipPosition < zipCollectionSize)) {
					zipCollection[zipPosition] = (zipBitBuf & 0xFF);
					zipPosition += 1;
					zipBitBuf = ((usqInt) zipBitBuf) >> 8;
					zipBitPos -= 8;
				}
	l2:	/* end nextZipBits:put: */;
			}
			dist -= 1;
			if (!(dist < 32768)) {
				result = primitiveFail();
				goto l7;
			}
			if (dist < 256) {
				code = zipDistanceCodes[dist];
			}
			else {
				code = zipDistanceCodes[256 + (((usqInt) dist) >> 7)];
			}
			if (!(code < distBlCount)) {
				result = primitiveFail();
				goto l7;
			}
			/* begin nextZipBits:put: */
			nBits2 = distBitLengths[code];
			value2 = distCodes[code];
			if (!((value2 >= 0)
				 && ((1U << nBits2) > value2))) {
				primitiveFail();
				goto l5;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value2) << zipBitPos)));
			zipBitPos += nBits2;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l5:	/* end nextZipBits:put: */;
			extra = zipExtraDistanceBits[code];
			if (!(extra == 0)) {
				dist -= zipBaseDistance[code];
				/* begin nextZipBits:put: */
				if (!((dist >= 0)
					 && ((1U << extra) > dist))) {
					primitiveFail();
					goto l3;
				}
				zipBitBuf = zipBitBuf | (((usqInt)(dist) << zipBitPos));
				zipBitPos += extra;
				while ((zipBitPos >= 8)
				 && (zipPosition < zipCollectionSize)) {
					zipCollection[zipPosition] = (zipBitBuf & 0xFF);
					zipPosition += 1;
					zipBitBuf = ((usqInt) zipBitBuf) >> 8;
					zipBitPos -= 8;
				}
	l3:	/* end nextZipBits:put: */;
			}
		}
	}
	if (failed()) {
		result = null;
		goto l7;
	}
	storeIntegerofObjectwithValue(1, litStream, litPos);
	storeIntegerofObjectwithValue(1, distStream, litPos);
	result = sum;
	l7:	/* end sendBlock:with:with:with: */;
	if (!(failed())) {
		storeIntegerofObjectwithValue(1, rcvr, zipPosition);
		storeIntegerofObjectwithValue(readStreamInstSize + 1, rcvr, zipBitBuf);
		storeIntegerofObjectwithValue(readStreamInstSize + 2, rcvr, zipBitPos);
	}
	if (!(failed())) {
		pop(5);
		pushInteger(result);
	}
	return 0;
}


/*	Require: 
	zipCollection, zipCollectionSize, zipPosition,
	zipBitBuf, zipBitPos.
	 */

	/* DeflatePlugin>>#sendBlock:with:with:with: */
static sqInt
sendBlockwithwithwith(sqInt literalStream, sqInt distanceStream, sqInt litTree, sqInt distTree)
{
    unsigned int code;
    unsigned int dist;
    unsigned int *distArray;
    unsigned int *distBitLengths;
    sqInt distBlCount;
    unsigned int *distCodes;
    unsigned int extra;
    unsigned char lit;
    unsigned char *litArray;
    sqInt litBlCount;
    sqInt litLimit;
    sqInt litPos;
    unsigned int *llBitLengths;
    unsigned int *llCodes;
    sqInt nBits;
    sqInt nBits1;
    sqInt nBits2;
    sqInt oop;
    sqInt sum;
    sqInt value;
    sqInt value1;
    sqInt value2;

	oop = fetchPointerofObject(0, literalStream);
	litPos = fetchIntegerofObject(1, literalStream);
	litLimit = fetchIntegerofObject(2, literalStream);
	if (!((litPos <= litLimit)
		 && ((isBytes(oop))
		 && (litLimit <= (byteSizeOf(oop)))))) {
		return primitiveFail();
	}
	litArray = firstIndexableField(oop);
	oop = fetchPointerofObject(0, distanceStream);
	if (!((isWords(oop))
		 && ((litLimit <= (slotSizeOf(oop)))
		 && (((fetchIntegerofObject(1, distanceStream)) == litPos)
		 && ((fetchIntegerofObject(2, distanceStream)) == litLimit))))) {
		return primitiveFail();
	}
	distArray = firstIndexableField(oop);
	oop = fetchPointerofObject(0, litTree);
	if (!(isWords(oop))) {
		return primitiveFail();
	}
	litBlCount = slotSizeOf(oop);
	llBitLengths = firstIndexableField(oop);
	oop = fetchPointerofObject(1, litTree);
	if (!((isWords(oop))
		 && (litBlCount == (slotSizeOf(oop))))) {
		return primitiveFail();
	}
	llCodes = firstIndexableField(oop);
	oop = fetchPointerofObject(0, distTree);
	if (!(isWords(oop))) {
		return primitiveFail();
	}
	distBlCount = slotSizeOf(oop);
	distBitLengths = firstIndexableField(oop);
	oop = fetchPointerofObject(1, distTree);
	if (!((isWords(oop))
		 && (distBlCount == (slotSizeOf(oop))))) {
		return primitiveFail();
	}
	distCodes = firstIndexableField(oop);
	/* begin nextZipBits:put: */
	if (!((0 >= 0)
		 && ((1U << 0) > 0))) {
		primitiveFail();
		goto l6;
	}
	zipBitBuf = zipBitBuf | (0U << zipBitPos);
	zipBitPos += 0;
	while ((zipBitPos >= 8)
	 && (zipPosition < zipCollectionSize)) {
		zipCollection[zipPosition] = (zipBitBuf & 0xFF);
		zipPosition += 1;
		zipBitBuf = ((usqInt) zipBitBuf) >> 8;
		zipBitPos -= 8;
	}
	l6:	/* end nextZipBits:put: */;
	sum = 0;
	while ((litPos < litLimit)
	 && ((zipPosition + 4) < zipCollectionSize)) {
		lit = litArray[litPos];
		dist = distArray[litPos];
		litPos += 1;
		if (dist == 0) {

			/* literal */
			sum += 1;
			if (!(lit < litBlCount)) {
				return primitiveFail();
			}
			/* begin nextZipBits:put: */
			nBits = llBitLengths[lit];
			value = llCodes[lit];
			if (!((value >= 0)
				 && ((1U << nBits) > value))) {
				primitiveFail();
				goto l1;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value) << zipBitPos)));
			zipBitPos += nBits;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l1:	/* end nextZipBits:put: */;
		}
		else {

			/* match */
			sum = (sum + lit) + DeflateMinMatch;
			if (!(lit < 256)) {
				return primitiveFail();
			}
			code = zipMatchLengthCodes[lit];
			if (!(code < litBlCount)) {
				return primitiveFail();
			}
			/* begin nextZipBits:put: */
			nBits1 = llBitLengths[code];
			value1 = llCodes[code];
			if (!((value1 >= 0)
				 && ((1U << nBits1) > value1))) {
				primitiveFail();
				goto l4;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value1) << zipBitPos)));
			zipBitPos += nBits1;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l4:	/* end nextZipBits:put: */;
			extra = zipExtraLengthBits[code - 257];
			if (!(extra == 0)) {
				lit -= zipBaseLength[code - 257];
				/* begin nextZipBits:put: */
				if (!((lit >= 0)
					 && ((1U << extra) > lit))) {
					primitiveFail();
					goto l2;
				}
				zipBitBuf = zipBitBuf | (((usqInt)(lit) << zipBitPos));
				zipBitPos += extra;
				while ((zipBitPos >= 8)
				 && (zipPosition < zipCollectionSize)) {
					zipCollection[zipPosition] = (zipBitBuf & 0xFF);
					zipPosition += 1;
					zipBitBuf = ((usqInt) zipBitBuf) >> 8;
					zipBitPos -= 8;
				}
	l2:	/* end nextZipBits:put: */;
			}
			dist -= 1;
			if (!(dist < 32768)) {
				return primitiveFail();
			}
			if (dist < 256) {
				code = zipDistanceCodes[dist];
			}
			else {
				code = zipDistanceCodes[256 + (((usqInt) dist) >> 7)];
			}
			if (!(code < distBlCount)) {
				return primitiveFail();
			}
			/* begin nextZipBits:put: */
			nBits2 = distBitLengths[code];
			value2 = distCodes[code];
			if (!((value2 >= 0)
				 && ((1U << nBits2) > value2))) {
				primitiveFail();
				goto l5;
			}
			zipBitBuf = zipBitBuf | (((sqInt)((usqInt)(value2) << zipBitPos)));
			zipBitPos += nBits2;
			while ((zipBitPos >= 8)
			 && (zipPosition < zipCollectionSize)) {
				zipCollection[zipPosition] = (zipBitBuf & 0xFF);
				zipPosition += 1;
				zipBitBuf = ((usqInt) zipBitBuf) >> 8;
				zipBitPos -= 8;
			}
	l5:	/* end nextZipBits:put: */;
			extra = zipExtraDistanceBits[code];
			if (!(extra == 0)) {
				dist -= zipBaseDistance[code];
				/* begin nextZipBits:put: */
				if (!((dist >= 0)
					 && ((1U << extra) > dist))) {
					primitiveFail();
					goto l3;
				}
				zipBitBuf = zipBitBuf | (((usqInt)(dist) << zipBitPos));
				zipBitPos += extra;
				while ((zipBitPos >= 8)
				 && (zipPosition < zipCollectionSize)) {
					zipCollection[zipPosition] = (zipBitBuf & 0xFF);
					zipPosition += 1;
					zipBitBuf = ((usqInt) zipBitBuf) >> 8;
					zipBitPos -= 8;
				}
	l3:	/* end nextZipBits:put: */;
			}
		}
	}
	if (failed()) {
		return null;
	}
	storeIntegerofObjectwithValue(1, literalStream, litPos);
	storeIntegerofObjectwithValue(1, distanceStream, litPos);
	return sum;
}


/*	Note: This is coded so that it can be run in Squeak. */

	/* InterpreterPlugin>>#setInterpreter: */
EXPORT(sqInt)
setInterpreter(struct VirtualMachine*anInterpreter)
{
    sqInt ok;

	interpreterProxy = anInterpreter;
	ok = ((interpreterProxy->majorVersion()) == (VM_PROXY_MAJOR))
	 && ((interpreterProxy->minorVersion()) >= (VM_PROXY_MINOR));
	if (ok) {
		
#if !defined(SQUEAK_BUILTIN_PLUGIN)
		byteSizeOf = interpreterProxy->byteSizeOf;
		failed = interpreterProxy->failed;
		fetchClassOf = interpreterProxy->fetchClassOf;
		fetchIntegerofObject = interpreterProxy->fetchIntegerofObject;
		fetchPointerofObject = interpreterProxy->fetchPointerofObject;
		firstIndexableField = interpreterProxy->firstIndexableField;
		instanceSizeOf = interpreterProxy->instanceSizeOf;
		isBytes = interpreterProxy->isBytes;
		isPointers = interpreterProxy->isPointers;
		isWords = interpreterProxy->isWords;
		methodArgumentCount = interpreterProxy->methodArgumentCount;
		nilObject = interpreterProxy->nilObject;
		pop = interpreterProxy->pop;
		popthenPush = interpreterProxy->popthenPush;
		positive32BitIntegerFor = interpreterProxy->positive32BitIntegerFor;
		positive32BitValueOf = interpreterProxy->positive32BitValueOf;
		primitiveFail = interpreterProxy->primitiveFail;
		pushBool = interpreterProxy->pushBool;
		pushInteger = interpreterProxy->pushInteger;
		slotSizeOf = interpreterProxy->slotSizeOf;
		stackIntegerValue = interpreterProxy->stackIntegerValue;
		stackObjectValue = interpreterProxy->stackObjectValue;
		stackValue = interpreterProxy->stackValue;
		storeIntegerofObjectwithValue = interpreterProxy->storeIntegerofObjectwithValue;
		superclassOf = interpreterProxy->superclassOf;
#endif /* !defined(SQUEAK_BUILTIN_PLUGIN) */
	}
	return ok;
}


/*	Check if we should flush the current block.
	Flushing can be useful if the input characteristics change. */

	/* DeflatePlugin>>#shouldFlush */
static sqInt
shouldFlush(void)
{
    sqInt nLits;

	if (zipLiteralCount == zipLiteralSize) {
		return 1;
	}
	if (!((zipLiteralCount & 0xFFF) == 0)) {
		return 0;
	}
	if ((zipMatchCount * 10) <= zipLiteralCount) {

		/* This is basically random data.
		   There is no need to flush early since the overhead
		   for encoding the trees will add to the overall size */
		return 0;
	}
	nLits = zipLiteralCount - zipMatchCount;
	if (nLits <= zipMatchCount) {
		return 0;
	}
	return (nLits * 4) <= zipMatchCount;
}


/*	Update the hash value at position here (one based) */

	/* DeflatePlugin>>#updateHashAt: */
static sqInt
updateHashAt(sqInt here)
{
	return ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ (zipCollection[here])) & DeflateHashMask;
}


/*	Update the running hash value based on the next input byte.
	Return the new updated hash value. */

	/* DeflatePlugin>>#updateHash: */
static sqInt
updateHash(sqInt nextValue)
{
	return ((((sqInt)((usqInt)(zipHashValue) << DeflateHashShift))) ^ nextValue) & DeflateHashMask;
}


/*	Decode the next value in the receiver using the given huffman table. */

	/* InflatePlugin>>#zipDecodeValueFrom:size: */
static usqInt
zipDecodeValueFromsize(unsigned int *table, sqInt tableSize)
{
    sqInt bits;
    sqInt bits1;
    sqInt bitsNeeded;
    unsigned char byte;
    sqInt index;
    sqInt tableIndex;
    unsigned int value;


	/* Initial bits needed */
	bitsNeeded = ((usqInt) (table[0]) >> 24);
	if (bitsNeeded > MaxBits) {
		primitiveFail();
		return 0;
	}

	/* First real table */
	tableIndex = 2;
	while (1) {
		/* begin zipNextBits: */
		while (zipBitPos < bitsNeeded) {
			byte = zipSource[(zipSourcePos += 1)];
			zipBitBuf += ((usqInt)(byte) << zipBitPos);
			zipBitPos += 8;
		}
		bits1 = zipBitBuf & ((1U << bitsNeeded) - 1);
		zipBitBuf = ((usqInt) zipBitBuf) >> bitsNeeded;
		zipBitPos -= bitsNeeded;
		bits = bits1;
		index = (tableIndex + bits) - 1;
		if (index >= tableSize) {
			primitiveFail();
			return 0;
		}

		/* Lookup entry in table */
		value = table[index];
		if ((value & 0x3F000000) == 0) {
			return value;
		}

		/* Table offset in low 16 bit */
		tableIndex = value & 0xFFFF;

		/* Additional bits in high 8 bit */
		bitsNeeded = (((usqInt) value >> 24)) & 0xFF;
		if (bitsNeeded > MaxBits) {
			primitiveFail();
			return 0;
		}
	}
	return 0;
}

	/* InflatePlugin>>#zipDecompressBlock */
static sqInt
zipDecompressBlock(void)
{
    usqInt distance;
    sqInt dstPos;
    sqInt extra;
    sqInt i;
    usqInt length;
    sqInt max;
    sqInt oldBitPos;
    sqInt oldBits;
    sqInt oldPos;
    sqInt srcPos;
    usqInt value;

	max = zipCollectionSize - 1;
	while ((zipReadLimit < max)
	 && (zipSourcePos <= zipSourceLimit)) {

		/* Back up stuff if we're running out of space */
		oldBits = zipBitBuf;
		oldBitPos = zipBitPos;
		oldPos = zipSourcePos;
		value = zipDecodeValueFromsize(zipLitTable, zipLitTableSize);
		if (value < 256) {

			/* A literal */
			zipCollection[(zipReadLimit += 1)] = value;
		}
		else {

			/* length/distance or end of block */
			if (value == 256) {

				/* End of block */
				zipState = zipState & StateNoMoreData;
				return 0;
			}
			extra = (((usqInt) value >> 16)) - 1;
			length = value & 0xFFFF;
			if (extra > 0) {
				length += zipNextBits(extra);
			}
			value = zipDecodeValueFromsize(zipDistTable, zipDistTableSize);
			extra = ((usqInt) value >> 16);
			distance = value & 0xFFFF;
			if (extra > 0) {
				distance += zipNextBits(extra);
			}
			if ((zipReadLimit + length) >= max) {
				zipBitBuf = oldBits;
				zipBitPos = oldBitPos;
				zipSourcePos = oldPos;
				return 0;
			}
			dstPos = zipReadLimit;
			srcPos = zipReadLimit - distance;
			for (i = 1; i <= length; i += 1) {
				zipCollection[dstPos + i] = (zipCollection[srcPos + i]);
			}
			zipReadLimit += length;
		}
	}
	return 0;
}

	/* InflatePlugin>>#zipNextBits: */
static sqInt
zipNextBits(sqInt n)
{
    sqInt bits;
    unsigned char byte;

	while (zipBitPos < n) {
		byte = zipSource[(zipSourcePos += 1)];
		zipBitBuf += ((usqInt)(byte) << zipBitPos);
		zipBitPos += 8;
	}
	bits = zipBitBuf & ((1U << n) - 1);
	zipBitBuf = ((usqInt) zipBitBuf) >> n;
	zipBitPos -= n;
	return bits;
}


#ifdef SQUEAK_BUILTIN_PLUGIN

static char _m[] = "ZipPlugin";
void* ZipPlugin_exports[][3] = {
	{(void*)_m, "getModuleName", (void*)getModuleName},
	{(void*)_m, "primitiveDeflateBlock\000\002", (void*)primitiveDeflateBlock},
	{(void*)_m, "primitiveDeflateUpdateHashTable\000\001", (void*)primitiveDeflateUpdateHashTable},
	{(void*)_m, "primitiveInflateDecompressBlock\000\002", (void*)primitiveInflateDecompressBlock},
	{(void*)_m, "primitiveUpdateAdler32\000\001", (void*)primitiveUpdateAdler32},
	{(void*)_m, "primitiveUpdateGZipCrc32\000\001", (void*)primitiveUpdateGZipCrc32},
	{(void*)_m, "primitiveZipSendBlock\000\002", (void*)primitiveZipSendBlock},
	{(void*)_m, "setInterpreter", (void*)setInterpreter},
	{NULL, NULL, NULL}
};

#else /* ifdef SQ_BUILTIN_PLUGIN */

signed char primitiveDeflateBlockAccessorDepth = 2;
signed char primitiveDeflateUpdateHashTableAccessorDepth = 1;
signed char primitiveInflateDecompressBlockAccessorDepth = 2;
signed char primitiveUpdateAdler32AccessorDepth = 1;
signed char primitiveUpdateGZipCrc32AccessorDepth = 1;
signed char primitiveZipSendBlockAccessorDepth = 2;

#endif /* ifdef SQ_BUILTIN_PLUGIN */
