kusano 7d535a
/* inflate.c -- zlib decompression
kusano 7d535a
 * Copyright (C) 1995-2012 Mark Adler
kusano 7d535a
 * For conditions of distribution and use, see copyright notice in zlib.h
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * Change history:
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta0    24 Nov 2002
kusano 7d535a
 * - First version -- complete rewrite of inflate to simplify code, avoid
kusano 7d535a
 *   creation of window when not needed, minimize use of window when it is
kusano 7d535a
 *   needed, make inffast.c even faster, implement gzip decoding, and to
kusano 7d535a
 *   improve code readability and style over the previous zlib inflate code
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta1    25 Nov 2002
kusano 7d535a
 * - Use pointers for available input and output checking in inffast.c
kusano 7d535a
 * - Remove input and output counters in inffast.c
kusano 7d535a
 * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
kusano 7d535a
 * - Remove unnecessary second byte pull from length extra in inffast.c
kusano 7d535a
 * - Unroll direct copy to three copies per loop in inffast.c
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta2    4 Dec 2002
kusano 7d535a
 * - Change external routine names to reduce potential conflicts
kusano 7d535a
 * - Correct filename to inffixed.h for fixed tables in inflate.c
kusano 7d535a
 * - Make hbuf[] unsigned char to match parameter type in inflate.c
kusano 7d535a
 * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
kusano 7d535a
 *   to avoid negation problem on Alphas (64 bit) in inflate.c
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta3    22 Dec 2002
kusano 7d535a
 * - Add comments on state->bits assertion in inffast.c
kusano 7d535a
 * - Add comments on op field in inftrees.h
kusano 7d535a
 * - Fix bug in reuse of allocated window after inflateReset()
kusano 7d535a
 * - Remove bit fields--back to byte structure for speed
kusano 7d535a
 * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
kusano 7d535a
 * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
kusano 7d535a
 * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
kusano 7d535a
 * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
kusano 7d535a
 * - Use local copies of stream next and avail values, as well as local bit
kusano 7d535a
 *   buffer and bit count in inflate()--for speed when inflate_fast() not used
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta4    1 Jan 2003
kusano 7d535a
 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
kusano 7d535a
 * - Move a comment on output buffer sizes from inffast.c to inflate.c
kusano 7d535a
 * - Add comments in inffast.c to introduce the inflate_fast() routine
kusano 7d535a
 * - Rearrange window copies in inflate_fast() for speed and simplification
kusano 7d535a
 * - Unroll last copy for window match in inflate_fast()
kusano 7d535a
 * - Use local copies of window variables in inflate_fast() for speed
kusano 7d535a
 * - Pull out common wnext == 0 case for speed in inflate_fast()
kusano 7d535a
 * - Make op and len in inflate_fast() unsigned for consistency
kusano 7d535a
 * - Add FAR to lcode and dcode declarations in inflate_fast()
kusano 7d535a
 * - Simplified bad distance check in inflate_fast()
kusano 7d535a
 * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
kusano 7d535a
 *   source file infback.c to provide a call-back interface to inflate for
kusano 7d535a
 *   programs like gzip and unzip -- uses window as output buffer to avoid
kusano 7d535a
 *   window copying
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta5    1 Jan 2003
kusano 7d535a
 * - Improved inflateBack() interface to allow the caller to provide initial
kusano 7d535a
 *   input in strm.
kusano 7d535a
 * - Fixed stored blocks bug in inflateBack()
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta6    4 Jan 2003
kusano 7d535a
 * - Added comments in inffast.c on effectiveness of POSTINC
kusano 7d535a
 * - Typecasting all around to reduce compiler warnings
kusano 7d535a
 * - Changed loops from while (1) or do {} while (1) to for (;;), again to
kusano 7d535a
 *   make compilers happy
kusano 7d535a
 * - Changed type of window in inflateBackInit() to unsigned char *
kusano 7d535a
 *
kusano 7d535a
 * 1.2.beta7    27 Jan 2003
kusano 7d535a
 * - Changed many types to unsigned or unsigned short to avoid warnings
kusano 7d535a
 * - Added inflateCopy() function
kusano 7d535a
 *
kusano 7d535a
 * 1.2.0        9 Mar 2003
kusano 7d535a
 * - Changed inflateBack() interface to provide separate opaque descriptors
kusano 7d535a
 *   for the in() and out() functions
kusano 7d535a
 * - Changed inflateBack() argument and in_func typedef to swap the length
kusano 7d535a
 *   and buffer address return values for the input function
kusano 7d535a
 * - Check next_in and next_out for Z_NULL on entry to inflate()
kusano 7d535a
 *
kusano 7d535a
 * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
#include "zutil.h"
kusano 7d535a
#include "inftrees.h"
kusano 7d535a
#include "inflate.h"
kusano 7d535a
#include "inffast.h"
kusano 7d535a
kusano 7d535a
#ifdef MAKEFIXED
kusano 7d535a
#  ifndef BUILDFIXED
kusano 7d535a
#    define BUILDFIXED
kusano 7d535a
#  endif
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* function prototypes */
kusano 7d535a
local void fixedtables OF((struct inflate_state FAR *state));
kusano 7d535a
local int updatewindow OF((z_streamp strm, unsigned out));
kusano 7d535a
#ifdef BUILDFIXED
kusano 7d535a
   void makefixed OF((void));
kusano 7d535a
#endif
kusano 7d535a
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
kusano 7d535a
                              unsigned len));
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateResetKeep(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    strm->total_in = strm->total_out = state->total = 0;
kusano 7d535a
    strm->msg = Z_NULL;
kusano 7d535a
    if (state->wrap)        /* to support ill-conceived Java test suite */
kusano 7d535a
        strm->adler = state->wrap & 1;
kusano 7d535a
    state->mode = HEAD;
kusano 7d535a
    state->last = 0;
kusano 7d535a
    state->havedict = 0;
kusano 7d535a
    state->dmax = 32768U;
kusano 7d535a
    state->head = Z_NULL;
kusano 7d535a
    state->hold = 0;
kusano 7d535a
    state->bits = 0;
kusano 7d535a
    state->lencode = state->distcode = state->next = state->codes;
kusano 7d535a
    state->sane = 1;
kusano 7d535a
    state->back = -1;
kusano 7d535a
    Tracev((stderr, "inflate: reset\n"));
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateReset(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    state->wsize = 0;
kusano 7d535a
    state->whave = 0;
kusano 7d535a
    state->wnext = 0;
kusano 7d535a
    return inflateResetKeep(strm);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateReset2(strm, windowBits)
kusano 7d535a
z_streamp strm;
kusano 7d535a
int windowBits;
kusano 7d535a
{
kusano 7d535a
    int wrap;
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    /* get the state */
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
kusano 7d535a
    /* extract wrap request from windowBits parameter */
kusano 7d535a
    if (windowBits < 0) {
kusano 7d535a
        wrap = 0;
kusano 7d535a
        windowBits = -windowBits;
kusano 7d535a
    }
kusano 7d535a
    else {
kusano 7d535a
        wrap = (windowBits >> 4) + 1;
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
        if (windowBits < 48)
kusano 7d535a
            windowBits &= 15;
kusano 7d535a
#endif
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* set number of window bits, free window if different */
kusano 7d535a
    if (windowBits && (windowBits < 8 || windowBits > 15))
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
kusano 7d535a
        ZFREE(strm, state->window);
kusano 7d535a
        state->window = Z_NULL;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* update state and reset the rest of it */
kusano 7d535a
    state->wrap = wrap;
kusano 7d535a
    state->wbits = (unsigned)windowBits;
kusano 7d535a
    return inflateReset(strm);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
kusano 7d535a
z_streamp strm;
kusano 7d535a
int windowBits;
kusano 7d535a
const char *version;
kusano 7d535a
int stream_size;
kusano 7d535a
{
kusano 7d535a
    int ret;
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
kusano 7d535a
        stream_size != (int)(sizeof(z_stream)))
kusano 7d535a
        return Z_VERSION_ERROR;
kusano 7d535a
    if (strm == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    strm->msg = Z_NULL;                 /* in case we return an error */
kusano 7d535a
    if (strm->zalloc == (alloc_func)0) {
kusano 7d535a
#ifdef Z_SOLO
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
#else
kusano 7d535a
        strm->zalloc = zcalloc;
kusano 7d535a
        strm->opaque = (voidpf)0;
kusano 7d535a
#endif
kusano 7d535a
    }
kusano 7d535a
    if (strm->zfree == (free_func)0)
kusano 7d535a
#ifdef Z_SOLO
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
#else
kusano 7d535a
        strm->zfree = zcfree;
kusano 7d535a
#endif
kusano 7d535a
    state = (struct inflate_state FAR *)
kusano 7d535a
            ZALLOC(strm, 1, sizeof(struct inflate_state));
kusano 7d535a
    if (state == Z_NULL) return Z_MEM_ERROR;
kusano 7d535a
    Tracev((stderr, "inflate: allocated\n"));
kusano 7d535a
    strm->state = (struct internal_state FAR *)state;
kusano 7d535a
    state->window = Z_NULL;
kusano 7d535a
    ret = inflateReset2(strm, windowBits);
kusano 7d535a
    if (ret != Z_OK) {
kusano 7d535a
        ZFREE(strm, state);
kusano 7d535a
        strm->state = Z_NULL;
kusano 7d535a
    }
kusano 7d535a
    return ret;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateInit_(strm, version, stream_size)
kusano 7d535a
z_streamp strm;
kusano 7d535a
const char *version;
kusano 7d535a
int stream_size;
kusano 7d535a
{
kusano 7d535a
    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflatePrime(strm, bits, value)
kusano 7d535a
z_streamp strm;
kusano 7d535a
int bits;
kusano 7d535a
int value;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if (bits < 0) {
kusano 7d535a
        state->hold = 0;
kusano 7d535a
        state->bits = 0;
kusano 7d535a
        return Z_OK;
kusano 7d535a
    }
kusano 7d535a
    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
kusano 7d535a
    value &= (1L << bits) - 1;
kusano 7d535a
    state->hold += value << state->bits;
kusano 7d535a
    state->bits += bits;
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   Return state with length and distance decoding tables and index sizes set to
kusano 7d535a
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
kusano 7d535a
   If BUILDFIXED is defined, then instead this routine builds the tables the
kusano 7d535a
   first time it's called, and returns those tables the first time and
kusano 7d535a
   thereafter.  This reduces the size of the code by about 2K bytes, in
kusano 7d535a
   exchange for a little execution time.  However, BUILDFIXED should not be
kusano 7d535a
   used for threaded applications, since the rewriting of the tables and virgin
kusano 7d535a
   may not be thread-safe.
kusano 7d535a
 */
kusano 7d535a
local void fixedtables(state)
kusano 7d535a
struct inflate_state FAR *state;
kusano 7d535a
{
kusano 7d535a
#ifdef BUILDFIXED
kusano 7d535a
    static int virgin = 1;
kusano 7d535a
    static code *lenfix, *distfix;
kusano 7d535a
    static code fixed[544];
kusano 7d535a
kusano 7d535a
    /* build fixed huffman tables if first call (may not be thread safe) */
kusano 7d535a
    if (virgin) {
kusano 7d535a
        unsigned sym, bits;
kusano 7d535a
        static code *next;
kusano 7d535a
kusano 7d535a
        /* literal/length table */
kusano 7d535a
        sym = 0;
kusano 7d535a
        while (sym < 144) state->lens[sym++] = 8;
kusano 7d535a
        while (sym < 256) state->lens[sym++] = 9;
kusano 7d535a
        while (sym < 280) state->lens[sym++] = 7;
kusano 7d535a
        while (sym < 288) state->lens[sym++] = 8;
kusano 7d535a
        next = fixed;
kusano 7d535a
        lenfix = next;
kusano 7d535a
        bits = 9;
kusano 7d535a
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
kusano 7d535a
kusano 7d535a
        /* distance table */
kusano 7d535a
        sym = 0;
kusano 7d535a
        while (sym < 32) state->lens[sym++] = 5;
kusano 7d535a
        distfix = next;
kusano 7d535a
        bits = 5;
kusano 7d535a
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
kusano 7d535a
kusano 7d535a
        /* do this just once */
kusano 7d535a
        virgin = 0;
kusano 7d535a
    }
kusano 7d535a
#else /* !BUILDFIXED */
kusano 7d535a
#   include "inffixed.h"
kusano 7d535a
#endif /* BUILDFIXED */
kusano 7d535a
    state->lencode = lenfix;
kusano 7d535a
    state->lenbits = 9;
kusano 7d535a
    state->distcode = distfix;
kusano 7d535a
    state->distbits = 5;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#ifdef MAKEFIXED
kusano 7d535a
#include <stdio.h></stdio.h>
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
kusano 7d535a
   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
kusano 7d535a
   those tables to stdout, which would be piped to inffixed.h.  A small program
kusano 7d535a
   can simply call makefixed to do this:
kusano 7d535a
kusano 7d535a
    void makefixed(void);
kusano 7d535a
kusano 7d535a
    int main(void)
kusano 7d535a
    {
kusano 7d535a
        makefixed();
kusano 7d535a
        return 0;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
   Then that can be linked with zlib built with MAKEFIXED defined and run:
kusano 7d535a
kusano 7d535a
    a.out > inffixed.h
kusano 7d535a
 */
kusano 7d535a
void makefixed()
kusano 7d535a
{
kusano 7d535a
    unsigned low, size;
kusano 7d535a
    struct inflate_state state;
kusano 7d535a
kusano 7d535a
    fixedtables(&state);
kusano 7d535a
    puts("    /* inffixed.h -- table for decoding fixed codes");
kusano 7d535a
    puts("     * Generated automatically by makefixed().");
kusano 7d535a
    puts("     */");
kusano 7d535a
    puts("");
kusano 7d535a
    puts("    /* WARNING: this file should *not* be used by applications.");
kusano 7d535a
    puts("       It is part of the implementation of this library and is");
kusano 7d535a
    puts("       subject to change. Applications should only use zlib.h.");
kusano 7d535a
    puts("     */");
kusano 7d535a
    puts("");
kusano 7d535a
    size = 1U << 9;
kusano 7d535a
    printf("    static const code lenfix[%u] = {", size);
kusano 7d535a
    low = 0;
kusano 7d535a
    for (;;) {
kusano 7d535a
        if ((low % 7) == 0) printf("\n        ");
kusano 7d535a
        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
kusano 7d535a
               state.lencode[low].bits, state.lencode[low].val);
kusano 7d535a
        if (++low == size) break;
kusano 7d535a
        putchar(',');
kusano 7d535a
    }
kusano 7d535a
    puts("\n    };");
kusano 7d535a
    size = 1U << 5;
kusano 7d535a
    printf("\n    static const code distfix[%u] = {", size);
kusano 7d535a
    low = 0;
kusano 7d535a
    for (;;) {
kusano 7d535a
        if ((low % 6) == 0) printf("\n        ");
kusano 7d535a
        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
kusano 7d535a
               state.distcode[low].val);
kusano 7d535a
        if (++low == size) break;
kusano 7d535a
        putchar(',');
kusano 7d535a
    }
kusano 7d535a
    puts("\n    };");
kusano 7d535a
}
kusano 7d535a
#endif /* MAKEFIXED */
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   Update the window with the last wsize (normally 32K) bytes written before
kusano 7d535a
   returning.  If window does not exist yet, create it.  This is only called
kusano 7d535a
   when a window is already in use, or when output has been written during this
kusano 7d535a
   inflate call, but the end of the deflate stream has not been reached yet.
kusano 7d535a
   It is also called to create a window for dictionary data when a dictionary
kusano 7d535a
   is loaded.
kusano 7d535a
kusano 7d535a
   Providing output buffers larger than 32K to inflate() should provide a speed
kusano 7d535a
   advantage, since only the last 32K of output is copied to the sliding window
kusano 7d535a
   upon return from inflate(), and since all distances after the first 32K of
kusano 7d535a
   output will fall in the output data, making match copies simpler and faster.
kusano 7d535a
   The advantage may be dependent on the size of the processor's data caches.
kusano 7d535a
 */
kusano 7d535a
local int updatewindow(strm, out)
kusano 7d535a
z_streamp strm;
kusano 7d535a
unsigned out;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
    unsigned copy, dist;
kusano 7d535a
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
kusano 7d535a
    /* if it hasn't been done already, allocate space for the window */
kusano 7d535a
    if (state->window == Z_NULL) {
kusano 7d535a
        state->window = (unsigned char FAR *)
kusano 7d535a
                        ZALLOC(strm, 1U << state->wbits,
kusano 7d535a
                               sizeof(unsigned char));
kusano 7d535a
        if (state->window == Z_NULL) return 1;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* if window not in use yet, initialize */
kusano 7d535a
    if (state->wsize == 0) {
kusano 7d535a
        state->wsize = 1U << state->wbits;
kusano 7d535a
        state->wnext = 0;
kusano 7d535a
        state->whave = 0;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* copy state->wsize or less output bytes into the circular window */
kusano 7d535a
    copy = out - strm->avail_out;
kusano 7d535a
    if (copy >= state->wsize) {
kusano 7d535a
        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
kusano 7d535a
        state->wnext = 0;
kusano 7d535a
        state->whave = state->wsize;
kusano 7d535a
    }
kusano 7d535a
    else {
kusano 7d535a
        dist = state->wsize - state->wnext;
kusano 7d535a
        if (dist > copy) dist = copy;
kusano 7d535a
        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
kusano 7d535a
        copy -= dist;
kusano 7d535a
        if (copy) {
kusano 7d535a
            zmemcpy(state->window, strm->next_out - copy, copy);
kusano 7d535a
            state->wnext = copy;
kusano 7d535a
            state->whave = state->wsize;
kusano 7d535a
        }
kusano 7d535a
        else {
kusano 7d535a
            state->wnext += dist;
kusano 7d535a
            if (state->wnext == state->wsize) state->wnext = 0;
kusano 7d535a
            if (state->whave < state->wsize) state->whave += dist;
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
    return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/* Macros for inflate(): */
kusano 7d535a
kusano 7d535a
/* check function to use adler32() for zlib or crc32() for gzip */
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
#  define UPDATE(check, buf, len) \
kusano 7d535a
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
kusano 7d535a
#else
kusano 7d535a
#  define UPDATE(check, buf, len) adler32(check, buf, len)
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* check macros for header crc */
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
#  define CRC2(check, word) \
kusano 7d535a
    do { \
kusano 7d535a
        hbuf[0] = (unsigned char)(word); \
kusano 7d535a
        hbuf[1] = (unsigned char)((word) >> 8); \
kusano 7d535a
        check = crc32(check, hbuf, 2); \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
#  define CRC4(check, word) \
kusano 7d535a
    do { \
kusano 7d535a
        hbuf[0] = (unsigned char)(word); \
kusano 7d535a
        hbuf[1] = (unsigned char)((word) >> 8); \
kusano 7d535a
        hbuf[2] = (unsigned char)((word) >> 16); \
kusano 7d535a
        hbuf[3] = (unsigned char)((word) >> 24); \
kusano 7d535a
        check = crc32(check, hbuf, 4); \
kusano 7d535a
    } while (0)
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
/* Load registers with state in inflate() for speed */
kusano 7d535a
#define LOAD() \
kusano 7d535a
    do { \
kusano 7d535a
        put = strm->next_out; \
kusano 7d535a
        left = strm->avail_out; \
kusano 7d535a
        next = strm->next_in; \
kusano 7d535a
        have = strm->avail_in; \
kusano 7d535a
        hold = state->hold; \
kusano 7d535a
        bits = state->bits; \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Restore state from registers in inflate() */
kusano 7d535a
#define RESTORE() \
kusano 7d535a
    do { \
kusano 7d535a
        strm->next_out = put; \
kusano 7d535a
        strm->avail_out = left; \
kusano 7d535a
        strm->next_in = next; \
kusano 7d535a
        strm->avail_in = have; \
kusano 7d535a
        state->hold = hold; \
kusano 7d535a
        state->bits = bits; \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Clear the input bit accumulator */
kusano 7d535a
#define INITBITS() \
kusano 7d535a
    do { \
kusano 7d535a
        hold = 0; \
kusano 7d535a
        bits = 0; \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Get a byte of input into the bit accumulator, or return from inflate()
kusano 7d535a
   if there is no input available. */
kusano 7d535a
#define PULLBYTE() \
kusano 7d535a
    do { \
kusano 7d535a
        if (have == 0) goto inf_leave; \
kusano 7d535a
        have--; \
kusano 7d535a
        hold += (unsigned long)(*next++) << bits; \
kusano 7d535a
        bits += 8; \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Assure that there are at least n bits in the bit accumulator.  If there is
kusano 7d535a
   not enough available input to do that, then return from inflate(). */
kusano 7d535a
#define NEEDBITS(n) \
kusano 7d535a
    do { \
kusano 7d535a
        while (bits < (unsigned)(n)) \
kusano 7d535a
            PULLBYTE(); \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Return the low n bits of the bit accumulator (n < 16) */
kusano 7d535a
#define BITS(n) \
kusano 7d535a
    ((unsigned)hold & ((1U << (n)) - 1))
kusano 7d535a
kusano 7d535a
/* Remove n bits from the bit accumulator */
kusano 7d535a
#define DROPBITS(n) \
kusano 7d535a
    do { \
kusano 7d535a
        hold >>= (n); \
kusano 7d535a
        bits -= (unsigned)(n); \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/* Remove zero to seven bits as needed to go to a byte boundary */
kusano 7d535a
#define BYTEBITS() \
kusano 7d535a
    do { \
kusano 7d535a
        hold >>= bits & 7; \
kusano 7d535a
        bits -= bits & 7; \
kusano 7d535a
    } while (0)
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   inflate() uses a state machine to process as much input data and generate as
kusano 7d535a
   much output data as possible before returning.  The state machine is
kusano 7d535a
   structured roughly as follows:
kusano 7d535a
kusano 7d535a
    for (;;) switch (state) {
kusano 7d535a
    ...
kusano 7d535a
    case STATEn:
kusano 7d535a
        if (not enough input data or output space to make progress)
kusano 7d535a
            return;
kusano 7d535a
        ... make progress ...
kusano 7d535a
        state = STATEm;
kusano 7d535a
        break;
kusano 7d535a
    ...
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
   so when inflate() is called again, the same case is attempted again, and
kusano 7d535a
   if the appropriate resources are provided, the machine proceeds to the
kusano 7d535a
   next state.  The NEEDBITS() macro is usually the way the state evaluates
kusano 7d535a
   whether it can proceed or should return.  NEEDBITS() does the return if
kusano 7d535a
   the requested bits are not available.  The typical use of the BITS macros
kusano 7d535a
   is:
kusano 7d535a
kusano 7d535a
        NEEDBITS(n);
kusano 7d535a
        ... do something with BITS(n) ...
kusano 7d535a
        DROPBITS(n);
kusano 7d535a
kusano 7d535a
   where NEEDBITS(n) either returns from inflate() if there isn't enough
kusano 7d535a
   input left to load n bits into the accumulator, or it continues.  BITS(n)
kusano 7d535a
   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
kusano 7d535a
   the low n bits off the accumulator.  INITBITS() clears the accumulator
kusano 7d535a
   and sets the number of available bits to zero.  BYTEBITS() discards just
kusano 7d535a
   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
kusano 7d535a
   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
kusano 7d535a
kusano 7d535a
   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
kusano 7d535a
   if there is no input available.  The decoding of variable length codes uses
kusano 7d535a
   PULLBYTE() directly in order to pull just enough bytes to decode the next
kusano 7d535a
   code, and no more.
kusano 7d535a
kusano 7d535a
   Some states loop until they get enough input, making sure that enough
kusano 7d535a
   state information is maintained to continue the loop where it left off
kusano 7d535a
   if NEEDBITS() returns in the loop.  For example, want, need, and keep
kusano 7d535a
   would all have to actually be part of the saved state in case NEEDBITS()
kusano 7d535a
   returns:
kusano 7d535a
kusano 7d535a
    case STATEw:
kusano 7d535a
        while (want < need) {
kusano 7d535a
            NEEDBITS(n);
kusano 7d535a
            keep[want++] = BITS(n);
kusano 7d535a
            DROPBITS(n);
kusano 7d535a
        }
kusano 7d535a
        state = STATEx;
kusano 7d535a
    case STATEx:
kusano 7d535a
kusano 7d535a
   As shown above, if the next state is also the next case, then the break
kusano 7d535a
   is omitted.
kusano 7d535a
kusano 7d535a
   A state may also return if there is not enough output space available to
kusano 7d535a
   complete that state.  Those states are copying stored data, writing a
kusano 7d535a
   literal byte, and copying a matching string.
kusano 7d535a
kusano 7d535a
   When returning, a "goto inf_leave" is used to update the total counters,
kusano 7d535a
   update the check value, and determine whether any progress has been made
kusano 7d535a
   during that inflate() call in order to return the proper return code.
kusano 7d535a
   Progress is defined as a change in either strm->avail_in or strm->avail_out.
kusano 7d535a
   When there is a window, goto inf_leave will update the window with the last
kusano 7d535a
   output written.  If a goto inf_leave occurs in the middle of decompression
kusano 7d535a
   and there is no window currently, goto inf_leave will create one and copy
kusano 7d535a
   output to the window for the next call of inflate().
kusano 7d535a
kusano 7d535a
   In this implementation, the flush parameter of inflate() only affects the
kusano 7d535a
   return code (per zlib.h).  inflate() always writes as much as possible to
kusano 7d535a
   strm->next_out, given the space available and the provided input--the effect
kusano 7d535a
   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
kusano 7d535a
   the allocation of and copying into a sliding window until necessary, which
kusano 7d535a
   provides the effect documented in zlib.h for Z_FINISH when the entire input
kusano 7d535a
   stream available.  So the only thing the flush parameter actually does is:
kusano 7d535a
   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
kusano 7d535a
   will return Z_BUF_ERROR if it has not reached the end of the stream.
kusano 7d535a
 */
kusano 7d535a
kusano 7d535a
int ZEXPORT inflate(strm, flush)
kusano 7d535a
z_streamp strm;
kusano 7d535a
int flush;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
    unsigned char FAR *next;    /* next input */
kusano 7d535a
    unsigned char FAR *put;     /* next output */
kusano 7d535a
    unsigned have, left;        /* available input and output */
kusano 7d535a
    unsigned long hold;         /* bit buffer */
kusano 7d535a
    unsigned bits;              /* bits in bit buffer */
kusano 7d535a
    unsigned in, out;           /* save starting available input and output */
kusano 7d535a
    unsigned copy;              /* number of stored or match bytes to copy */
kusano 7d535a
    unsigned char FAR *from;    /* where to copy match bytes from */
kusano 7d535a
    code here;                  /* current decoding table entry */
kusano 7d535a
    code last;                  /* parent table entry */
kusano 7d535a
    unsigned len;               /* length to copy for repeats, bits to drop */
kusano 7d535a
    int ret;                    /* return code */
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
kusano 7d535a
#endif
kusano 7d535a
    static const unsigned short order[19] = /* permutation of code lengths */
kusano 7d535a
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
kusano 7d535a
        (strm->next_in == Z_NULL && strm->avail_in != 0))
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
kusano 7d535a
    LOAD();
kusano 7d535a
    in = have;
kusano 7d535a
    out = left;
kusano 7d535a
    ret = Z_OK;
kusano 7d535a
    for (;;)
kusano 7d535a
        switch (state->mode) {
kusano 7d535a
        case HEAD:
kusano 7d535a
            if (state->wrap == 0) {
kusano 7d535a
                state->mode = TYPEDO;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            NEEDBITS(16);
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
kusano 7d535a
                state->check = crc32(0L, Z_NULL, 0);
kusano 7d535a
                CRC2(state->check, hold);
kusano 7d535a
                INITBITS();
kusano 7d535a
                state->mode = FLAGS;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->flags = 0;           /* expect zlib header */
kusano 7d535a
            if (state->head != Z_NULL)
kusano 7d535a
                state->head->done = -1;
kusano 7d535a
            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
kusano 7d535a
#else
kusano 7d535a
            if (
kusano 7d535a
#endif
kusano 7d535a
                ((BITS(8) << 8) + (hold >> 8)) % 31) {
kusano 7d535a
                strm->msg = (char *)"incorrect header check";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            if (BITS(4) != Z_DEFLATED) {
kusano 7d535a
                strm->msg = (char *)"unknown compression method";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            DROPBITS(4);
kusano 7d535a
            len = BITS(4) + 8;
kusano 7d535a
            if (state->wbits == 0)
kusano 7d535a
                state->wbits = len;
kusano 7d535a
            else if (len > state->wbits) {
kusano 7d535a
                strm->msg = (char *)"invalid window size";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->dmax = 1U << len;
kusano 7d535a
            Tracev((stderr, "inflate:   zlib header ok\n"));
kusano 7d535a
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
kusano 7d535a
            state->mode = hold & 0x200 ? DICTID : TYPE;
kusano 7d535a
            INITBITS();
kusano 7d535a
            break;
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
        case FLAGS:
kusano 7d535a
            NEEDBITS(16);
kusano 7d535a
            state->flags = (int)(hold);
kusano 7d535a
            if ((state->flags & 0xff) != Z_DEFLATED) {
kusano 7d535a
                strm->msg = (char *)"unknown compression method";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            if (state->flags & 0xe000) {
kusano 7d535a
                strm->msg = (char *)"unknown header flags set";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            if (state->head != Z_NULL)
kusano 7d535a
                state->head->text = (int)((hold >> 8) & 1);
kusano 7d535a
            if (state->flags & 0x0200) CRC2(state->check, hold);
kusano 7d535a
            INITBITS();
kusano 7d535a
            state->mode = TIME;
kusano 7d535a
        case TIME:
kusano 7d535a
            NEEDBITS(32);
kusano 7d535a
            if (state->head != Z_NULL)
kusano 7d535a
                state->head->time = hold;
kusano 7d535a
            if (state->flags & 0x0200) CRC4(state->check, hold);
kusano 7d535a
            INITBITS();
kusano 7d535a
            state->mode = OS;
kusano 7d535a
        case OS:
kusano 7d535a
            NEEDBITS(16);
kusano 7d535a
            if (state->head != Z_NULL) {
kusano 7d535a
                state->head->xflags = (int)(hold & 0xff);
kusano 7d535a
                state->head->os = (int)(hold >> 8);
kusano 7d535a
            }
kusano 7d535a
            if (state->flags & 0x0200) CRC2(state->check, hold);
kusano 7d535a
            INITBITS();
kusano 7d535a
            state->mode = EXLEN;
kusano 7d535a
        case EXLEN:
kusano 7d535a
            if (state->flags & 0x0400) {
kusano 7d535a
                NEEDBITS(16);
kusano 7d535a
                state->length = (unsigned)(hold);
kusano 7d535a
                if (state->head != Z_NULL)
kusano 7d535a
                    state->head->extra_len = (unsigned)hold;
kusano 7d535a
                if (state->flags & 0x0200) CRC2(state->check, hold);
kusano 7d535a
                INITBITS();
kusano 7d535a
            }
kusano 7d535a
            else if (state->head != Z_NULL)
kusano 7d535a
                state->head->extra = Z_NULL;
kusano 7d535a
            state->mode = EXTRA;
kusano 7d535a
        case EXTRA:
kusano 7d535a
            if (state->flags & 0x0400) {
kusano 7d535a
                copy = state->length;
kusano 7d535a
                if (copy > have) copy = have;
kusano 7d535a
                if (copy) {
kusano 7d535a
                    if (state->head != Z_NULL &&
kusano 7d535a
                        state->head->extra != Z_NULL) {
kusano 7d535a
                        len = state->head->extra_len - state->length;
kusano 7d535a
                        zmemcpy(state->head->extra + len, next,
kusano 7d535a
                                len + copy > state->head->extra_max ?
kusano 7d535a
                                state->head->extra_max - len : copy);
kusano 7d535a
                    }
kusano 7d535a
                    if (state->flags & 0x0200)
kusano 7d535a
                        state->check = crc32(state->check, next, copy);
kusano 7d535a
                    have -= copy;
kusano 7d535a
                    next += copy;
kusano 7d535a
                    state->length -= copy;
kusano 7d535a
                }
kusano 7d535a
                if (state->length) goto inf_leave;
kusano 7d535a
            }
kusano 7d535a
            state->length = 0;
kusano 7d535a
            state->mode = NAME;
kusano 7d535a
        case NAME:
kusano 7d535a
            if (state->flags & 0x0800) {
kusano 7d535a
                if (have == 0) goto inf_leave;
kusano 7d535a
                copy = 0;
kusano 7d535a
                do {
kusano 7d535a
                    len = (unsigned)(next[copy++]);
kusano 7d535a
                    if (state->head != Z_NULL &&
kusano 7d535a
                            state->head->name != Z_NULL &&
kusano 7d535a
                            state->length < state->head->name_max)
kusano 7d535a
                        state->head->name[state->length++] = len;
kusano 7d535a
                } while (len && copy < have);
kusano 7d535a
                if (state->flags & 0x0200)
kusano 7d535a
                    state->check = crc32(state->check, next, copy);
kusano 7d535a
                have -= copy;
kusano 7d535a
                next += copy;
kusano 7d535a
                if (len) goto inf_leave;
kusano 7d535a
            }
kusano 7d535a
            else if (state->head != Z_NULL)
kusano 7d535a
                state->head->name = Z_NULL;
kusano 7d535a
            state->length = 0;
kusano 7d535a
            state->mode = COMMENT;
kusano 7d535a
        case COMMENT:
kusano 7d535a
            if (state->flags & 0x1000) {
kusano 7d535a
                if (have == 0) goto inf_leave;
kusano 7d535a
                copy = 0;
kusano 7d535a
                do {
kusano 7d535a
                    len = (unsigned)(next[copy++]);
kusano 7d535a
                    if (state->head != Z_NULL &&
kusano 7d535a
                            state->head->comment != Z_NULL &&
kusano 7d535a
                            state->length < state->head->comm_max)
kusano 7d535a
                        state->head->comment[state->length++] = len;
kusano 7d535a
                } while (len && copy < have);
kusano 7d535a
                if (state->flags & 0x0200)
kusano 7d535a
                    state->check = crc32(state->check, next, copy);
kusano 7d535a
                have -= copy;
kusano 7d535a
                next += copy;
kusano 7d535a
                if (len) goto inf_leave;
kusano 7d535a
            }
kusano 7d535a
            else if (state->head != Z_NULL)
kusano 7d535a
                state->head->comment = Z_NULL;
kusano 7d535a
            state->mode = HCRC;
kusano 7d535a
        case HCRC:
kusano 7d535a
            if (state->flags & 0x0200) {
kusano 7d535a
                NEEDBITS(16);
kusano 7d535a
                if (hold != (state->check & 0xffff)) {
kusano 7d535a
                    strm->msg = (char *)"header crc mismatch";
kusano 7d535a
                    state->mode = BAD;
kusano 7d535a
                    break;
kusano 7d535a
                }
kusano 7d535a
                INITBITS();
kusano 7d535a
            }
kusano 7d535a
            if (state->head != Z_NULL) {
kusano 7d535a
                state->head->hcrc = (int)((state->flags >> 9) & 1);
kusano 7d535a
                state->head->done = 1;
kusano 7d535a
            }
kusano 7d535a
            strm->adler = state->check = crc32(0L, Z_NULL, 0);
kusano 7d535a
            state->mode = TYPE;
kusano 7d535a
            break;
kusano 7d535a
#endif
kusano 7d535a
        case DICTID:
kusano 7d535a
            NEEDBITS(32);
kusano 7d535a
            strm->adler = state->check = ZSWAP32(hold);
kusano 7d535a
            INITBITS();
kusano 7d535a
            state->mode = DICT;
kusano 7d535a
        case DICT:
kusano 7d535a
            if (state->havedict == 0) {
kusano 7d535a
                RESTORE();
kusano 7d535a
                return Z_NEED_DICT;
kusano 7d535a
            }
kusano 7d535a
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
kusano 7d535a
            state->mode = TYPE;
kusano 7d535a
        case TYPE:
kusano 7d535a
            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
kusano 7d535a
        case TYPEDO:
kusano 7d535a
            if (state->last) {
kusano 7d535a
                BYTEBITS();
kusano 7d535a
                state->mode = CHECK;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            NEEDBITS(3);
kusano 7d535a
            state->last = BITS(1);
kusano 7d535a
            DROPBITS(1);
kusano 7d535a
            switch (BITS(2)) {
kusano 7d535a
            case 0:                             /* stored block */
kusano 7d535a
                Tracev((stderr, "inflate:     stored block%s\n",
kusano 7d535a
                        state->last ? " (last)" : ""));
kusano 7d535a
                state->mode = STORED;
kusano 7d535a
                break;
kusano 7d535a
            case 1:                             /* fixed block */
kusano 7d535a
                fixedtables(state);
kusano 7d535a
                Tracev((stderr, "inflate:     fixed codes block%s\n",
kusano 7d535a
                        state->last ? " (last)" : ""));
kusano 7d535a
                state->mode = LEN_;             /* decode codes */
kusano 7d535a
                if (flush == Z_TREES) {
kusano 7d535a
                    DROPBITS(2);
kusano 7d535a
                    goto inf_leave;
kusano 7d535a
                }
kusano 7d535a
                break;
kusano 7d535a
            case 2:                             /* dynamic block */
kusano 7d535a
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
kusano 7d535a
                        state->last ? " (last)" : ""));
kusano 7d535a
                state->mode = TABLE;
kusano 7d535a
                break;
kusano 7d535a
            case 3:
kusano 7d535a
                strm->msg = (char *)"invalid block type";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
            }
kusano 7d535a
            DROPBITS(2);
kusano 7d535a
            break;
kusano 7d535a
        case STORED:
kusano 7d535a
            BYTEBITS();                         /* go to byte boundary */
kusano 7d535a
            NEEDBITS(32);
kusano 7d535a
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
kusano 7d535a
                strm->msg = (char *)"invalid stored block lengths";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->length = (unsigned)hold & 0xffff;
kusano 7d535a
            Tracev((stderr, "inflate:       stored length %u\n",
kusano 7d535a
                    state->length));
kusano 7d535a
            INITBITS();
kusano 7d535a
            state->mode = COPY_;
kusano 7d535a
            if (flush == Z_TREES) goto inf_leave;
kusano 7d535a
        case COPY_:
kusano 7d535a
            state->mode = COPY;
kusano 7d535a
        case COPY:
kusano 7d535a
            copy = state->length;
kusano 7d535a
            if (copy) {
kusano 7d535a
                if (copy > have) copy = have;
kusano 7d535a
                if (copy > left) copy = left;
kusano 7d535a
                if (copy == 0) goto inf_leave;
kusano 7d535a
                zmemcpy(put, next, copy);
kusano 7d535a
                have -= copy;
kusano 7d535a
                next += copy;
kusano 7d535a
                left -= copy;
kusano 7d535a
                put += copy;
kusano 7d535a
                state->length -= copy;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            Tracev((stderr, "inflate:       stored end\n"));
kusano 7d535a
            state->mode = TYPE;
kusano 7d535a
            break;
kusano 7d535a
        case TABLE:
kusano 7d535a
            NEEDBITS(14);
kusano 7d535a
            state->nlen = BITS(5) + 257;
kusano 7d535a
            DROPBITS(5);
kusano 7d535a
            state->ndist = BITS(5) + 1;
kusano 7d535a
            DROPBITS(5);
kusano 7d535a
            state->ncode = BITS(4) + 4;
kusano 7d535a
            DROPBITS(4);
kusano 7d535a
#ifndef PKZIP_BUG_WORKAROUND
kusano 7d535a
            if (state->nlen > 286 || state->ndist > 30) {
kusano 7d535a
                strm->msg = (char *)"too many length or distance symbols";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
#endif
kusano 7d535a
            Tracev((stderr, "inflate:       table sizes ok\n"));
kusano 7d535a
            state->have = 0;
kusano 7d535a
            state->mode = LENLENS;
kusano 7d535a
        case LENLENS:
kusano 7d535a
            while (state->have < state->ncode) {
kusano 7d535a
                NEEDBITS(3);
kusano 7d535a
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
kusano 7d535a
                DROPBITS(3);
kusano 7d535a
            }
kusano 7d535a
            while (state->have < 19)
kusano 7d535a
                state->lens[order[state->have++]] = 0;
kusano 7d535a
            state->next = state->codes;
kusano 7d535a
            state->lencode = (code const FAR *)(state->next);
kusano 7d535a
            state->lenbits = 7;
kusano 7d535a
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
kusano 7d535a
                                &(state->lenbits), state->work);
kusano 7d535a
            if (ret) {
kusano 7d535a
                strm->msg = (char *)"invalid code lengths set";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            Tracev((stderr, "inflate:       code lengths ok\n"));
kusano 7d535a
            state->have = 0;
kusano 7d535a
            state->mode = CODELENS;
kusano 7d535a
        case CODELENS:
kusano 7d535a
            while (state->have < state->nlen + state->ndist) {
kusano 7d535a
                for (;;) {
kusano 7d535a
                    here = state->lencode[BITS(state->lenbits)];
kusano 7d535a
                    if ((unsigned)(here.bits) <= bits) break;
kusano 7d535a
                    PULLBYTE();
kusano 7d535a
                }
kusano 7d535a
                if (here.val < 16) {
kusano 7d535a
                    DROPBITS(here.bits);
kusano 7d535a
                    state->lens[state->have++] = here.val;
kusano 7d535a
                }
kusano 7d535a
                else {
kusano 7d535a
                    if (here.val == 16) {
kusano 7d535a
                        NEEDBITS(here.bits + 2);
kusano 7d535a
                        DROPBITS(here.bits);
kusano 7d535a
                        if (state->have == 0) {
kusano 7d535a
                            strm->msg = (char *)"invalid bit length repeat";
kusano 7d535a
                            state->mode = BAD;
kusano 7d535a
                            break;
kusano 7d535a
                        }
kusano 7d535a
                        len = state->lens[state->have - 1];
kusano 7d535a
                        copy = 3 + BITS(2);
kusano 7d535a
                        DROPBITS(2);
kusano 7d535a
                    }
kusano 7d535a
                    else if (here.val == 17) {
kusano 7d535a
                        NEEDBITS(here.bits + 3);
kusano 7d535a
                        DROPBITS(here.bits);
kusano 7d535a
                        len = 0;
kusano 7d535a
                        copy = 3 + BITS(3);
kusano 7d535a
                        DROPBITS(3);
kusano 7d535a
                    }
kusano 7d535a
                    else {
kusano 7d535a
                        NEEDBITS(here.bits + 7);
kusano 7d535a
                        DROPBITS(here.bits);
kusano 7d535a
                        len = 0;
kusano 7d535a
                        copy = 11 + BITS(7);
kusano 7d535a
                        DROPBITS(7);
kusano 7d535a
                    }
kusano 7d535a
                    if (state->have + copy > state->nlen + state->ndist) {
kusano 7d535a
                        strm->msg = (char *)"invalid bit length repeat";
kusano 7d535a
                        state->mode = BAD;
kusano 7d535a
                        break;
kusano 7d535a
                    }
kusano 7d535a
                    while (copy--)
kusano 7d535a
                        state->lens[state->have++] = (unsigned short)len;
kusano 7d535a
                }
kusano 7d535a
            }
kusano 7d535a
kusano 7d535a
            /* handle error breaks in while */
kusano 7d535a
            if (state->mode == BAD) break;
kusano 7d535a
kusano 7d535a
            /* check for end-of-block code (better have one) */
kusano 7d535a
            if (state->lens[256] == 0) {
kusano 7d535a
                strm->msg = (char *)"invalid code -- missing end-of-block";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
kusano 7d535a
            /* build code tables -- note: do not change the lenbits or distbits
kusano 7d535a
               values here (9 and 6) without reading the comments in inftrees.h
kusano 7d535a
               concerning the ENOUGH constants, which depend on those values */
kusano 7d535a
            state->next = state->codes;
kusano 7d535a
            state->lencode = (code const FAR *)(state->next);
kusano 7d535a
            state->lenbits = 9;
kusano 7d535a
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
kusano 7d535a
                                &(state->lenbits), state->work);
kusano 7d535a
            if (ret) {
kusano 7d535a
                strm->msg = (char *)"invalid literal/lengths set";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->distcode = (code const FAR *)(state->next);
kusano 7d535a
            state->distbits = 6;
kusano 7d535a
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
kusano 7d535a
                            &(state->next), &(state->distbits), state->work);
kusano 7d535a
            if (ret) {
kusano 7d535a
                strm->msg = (char *)"invalid distances set";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            Tracev((stderr, "inflate:       codes ok\n"));
kusano 7d535a
            state->mode = LEN_;
kusano 7d535a
            if (flush == Z_TREES) goto inf_leave;
kusano 7d535a
        case LEN_:
kusano 7d535a
            state->mode = LEN;
kusano 7d535a
        case LEN:
kusano 7d535a
            if (have >= 6 && left >= 258) {
kusano 7d535a
                RESTORE();
kusano 7d535a
                inflate_fast(strm, out);
kusano 7d535a
                LOAD();
kusano 7d535a
                if (state->mode == TYPE)
kusano 7d535a
                    state->back = -1;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->back = 0;
kusano 7d535a
            for (;;) {
kusano 7d535a
                here = state->lencode[BITS(state->lenbits)];
kusano 7d535a
                if ((unsigned)(here.bits) <= bits) break;
kusano 7d535a
                PULLBYTE();
kusano 7d535a
            }
kusano 7d535a
            if (here.op && (here.op & 0xf0) == 0) {
kusano 7d535a
                last = here;
kusano 7d535a
                for (;;) {
kusano 7d535a
                    here = state->lencode[last.val +
kusano 7d535a
                            (BITS(last.bits + last.op) >> last.bits)];
kusano 7d535a
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano 7d535a
                    PULLBYTE();
kusano 7d535a
                }
kusano 7d535a
                DROPBITS(last.bits);
kusano 7d535a
                state->back += last.bits;
kusano 7d535a
            }
kusano 7d535a
            DROPBITS(here.bits);
kusano 7d535a
            state->back += here.bits;
kusano 7d535a
            state->length = (unsigned)here.val;
kusano 7d535a
            if ((int)(here.op) == 0) {
kusano 7d535a
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
kusano 7d535a
                        "inflate:         literal '%c'\n" :
kusano 7d535a
                        "inflate:         literal 0x%02x\n", here.val));
kusano 7d535a
                state->mode = LIT;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            if (here.op & 32) {
kusano 7d535a
                Tracevv((stderr, "inflate:         end of block\n"));
kusano 7d535a
                state->back = -1;
kusano 7d535a
                state->mode = TYPE;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            if (here.op & 64) {
kusano 7d535a
                strm->msg = (char *)"invalid literal/length code";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->extra = (unsigned)(here.op) & 15;
kusano 7d535a
            state->mode = LENEXT;
kusano 7d535a
        case LENEXT:
kusano 7d535a
            if (state->extra) {
kusano 7d535a
                NEEDBITS(state->extra);
kusano 7d535a
                state->length += BITS(state->extra);
kusano 7d535a
                DROPBITS(state->extra);
kusano 7d535a
                state->back += state->extra;
kusano 7d535a
            }
kusano 7d535a
            Tracevv((stderr, "inflate:         length %u\n", state->length));
kusano 7d535a
            state->was = state->length;
kusano 7d535a
            state->mode = DIST;
kusano 7d535a
        case DIST:
kusano 7d535a
            for (;;) {
kusano 7d535a
                here = state->distcode[BITS(state->distbits)];
kusano 7d535a
                if ((unsigned)(here.bits) <= bits) break;
kusano 7d535a
                PULLBYTE();
kusano 7d535a
            }
kusano 7d535a
            if ((here.op & 0xf0) == 0) {
kusano 7d535a
                last = here;
kusano 7d535a
                for (;;) {
kusano 7d535a
                    here = state->distcode[last.val +
kusano 7d535a
                            (BITS(last.bits + last.op) >> last.bits)];
kusano 7d535a
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano 7d535a
                    PULLBYTE();
kusano 7d535a
                }
kusano 7d535a
                DROPBITS(last.bits);
kusano 7d535a
                state->back += last.bits;
kusano 7d535a
            }
kusano 7d535a
            DROPBITS(here.bits);
kusano 7d535a
            state->back += here.bits;
kusano 7d535a
            if (here.op & 64) {
kusano 7d535a
                strm->msg = (char *)"invalid distance code";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
            state->offset = (unsigned)here.val;
kusano 7d535a
            state->extra = (unsigned)(here.op) & 15;
kusano 7d535a
            state->mode = DISTEXT;
kusano 7d535a
        case DISTEXT:
kusano 7d535a
            if (state->extra) {
kusano 7d535a
                NEEDBITS(state->extra);
kusano 7d535a
                state->offset += BITS(state->extra);
kusano 7d535a
                DROPBITS(state->extra);
kusano 7d535a
                state->back += state->extra;
kusano 7d535a
            }
kusano 7d535a
#ifdef INFLATE_STRICT
kusano 7d535a
            if (state->offset > state->dmax) {
kusano 7d535a
                strm->msg = (char *)"invalid distance too far back";
kusano 7d535a
                state->mode = BAD;
kusano 7d535a
                break;
kusano 7d535a
            }
kusano 7d535a
#endif
kusano 7d535a
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
kusano 7d535a
            state->mode = MATCH;
kusano 7d535a
        case MATCH:
kusano 7d535a
            if (left == 0) goto inf_leave;
kusano 7d535a
            copy = out - left;
kusano 7d535a
            if (state->offset > copy) {         /* copy from window */
kusano 7d535a
                copy = state->offset - copy;
kusano 7d535a
                if (copy > state->whave) {
kusano 7d535a
                    if (state->sane) {
kusano 7d535a
                        strm->msg = (char *)"invalid distance too far back";
kusano 7d535a
                        state->mode = BAD;
kusano 7d535a
                        break;
kusano 7d535a
                    }
kusano 7d535a
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
kusano 7d535a
                    Trace((stderr, "inflate.c too far\n"));
kusano 7d535a
                    copy -= state->whave;
kusano 7d535a
                    if (copy > state->length) copy = state->length;
kusano 7d535a
                    if (copy > left) copy = left;
kusano 7d535a
                    left -= copy;
kusano 7d535a
                    state->length -= copy;
kusano 7d535a
                    do {
kusano 7d535a
                        *put++ = 0;
kusano 7d535a
                    } while (--copy);
kusano 7d535a
                    if (state->length == 0) state->mode = LEN;
kusano 7d535a
                    break;
kusano 7d535a
#endif
kusano 7d535a
                }
kusano 7d535a
                if (copy > state->wnext) {
kusano 7d535a
                    copy -= state->wnext;
kusano 7d535a
                    from = state->window + (state->wsize - copy);
kusano 7d535a
                }
kusano 7d535a
                else
kusano 7d535a
                    from = state->window + (state->wnext - copy);
kusano 7d535a
                if (copy > state->length) copy = state->length;
kusano 7d535a
            }
kusano 7d535a
            else {                              /* copy from output */
kusano 7d535a
                from = put - state->offset;
kusano 7d535a
                copy = state->length;
kusano 7d535a
            }
kusano 7d535a
            if (copy > left) copy = left;
kusano 7d535a
            left -= copy;
kusano 7d535a
            state->length -= copy;
kusano 7d535a
            do {
kusano 7d535a
                *put++ = *from++;
kusano 7d535a
            } while (--copy);
kusano 7d535a
            if (state->length == 0) state->mode = LEN;
kusano 7d535a
            break;
kusano 7d535a
        case LIT:
kusano 7d535a
            if (left == 0) goto inf_leave;
kusano 7d535a
            *put++ = (unsigned char)(state->length);
kusano 7d535a
            left--;
kusano 7d535a
            state->mode = LEN;
kusano 7d535a
            break;
kusano 7d535a
        case CHECK:
kusano 7d535a
            if (state->wrap) {
kusano 7d535a
                NEEDBITS(32);
kusano 7d535a
                out -= left;
kusano 7d535a
                strm->total_out += out;
kusano 7d535a
                state->total += out;
kusano 7d535a
                if (out)
kusano 7d535a
                    strm->adler = state->check =
kusano 7d535a
                        UPDATE(state->check, put - out, out);
kusano 7d535a
                out = left;
kusano 7d535a
                if ((
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
                     state->flags ? hold :
kusano 7d535a
#endif
kusano 7d535a
                     ZSWAP32(hold)) != state->check) {
kusano 7d535a
                    strm->msg = (char *)"incorrect data check";
kusano 7d535a
                    state->mode = BAD;
kusano 7d535a
                    break;
kusano 7d535a
                }
kusano 7d535a
                INITBITS();
kusano 7d535a
                Tracev((stderr, "inflate:   check matches trailer\n"));
kusano 7d535a
            }
kusano 7d535a
#ifdef GUNZIP
kusano 7d535a
            state->mode = LENGTH;
kusano 7d535a
        case LENGTH:
kusano 7d535a
            if (state->wrap && state->flags) {
kusano 7d535a
                NEEDBITS(32);
kusano 7d535a
                if (hold != (state->total & 0xffffffffUL)) {
kusano 7d535a
                    strm->msg = (char *)"incorrect length check";
kusano 7d535a
                    state->mode = BAD;
kusano 7d535a
                    break;
kusano 7d535a
                }
kusano 7d535a
                INITBITS();
kusano 7d535a
                Tracev((stderr, "inflate:   length matches trailer\n"));
kusano 7d535a
            }
kusano 7d535a
#endif
kusano 7d535a
            state->mode = DONE;
kusano 7d535a
        case DONE:
kusano 7d535a
            ret = Z_STREAM_END;
kusano 7d535a
            goto inf_leave;
kusano 7d535a
        case BAD:
kusano 7d535a
            ret = Z_DATA_ERROR;
kusano 7d535a
            goto inf_leave;
kusano 7d535a
        case MEM:
kusano 7d535a
            return Z_MEM_ERROR;
kusano 7d535a
        case SYNC:
kusano 7d535a
        default:
kusano 7d535a
            return Z_STREAM_ERROR;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
    /*
kusano 7d535a
       Return from inflate(), updating the total counts and the check value.
kusano 7d535a
       If there was no progress during the inflate() call, return a buffer
kusano 7d535a
       error.  Call updatewindow() to create and/or update the window state.
kusano 7d535a
       Note: a memory error from inflate() is non-recoverable.
kusano 7d535a
     */
kusano 7d535a
  inf_leave:
kusano 7d535a
    RESTORE();
kusano 7d535a
    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
kusano 7d535a
            (state->mode < CHECK || flush != Z_FINISH)))
kusano 7d535a
        if (updatewindow(strm, out)) {
kusano 7d535a
            state->mode = MEM;
kusano 7d535a
            return Z_MEM_ERROR;
kusano 7d535a
        }
kusano 7d535a
    in -= strm->avail_in;
kusano 7d535a
    out -= strm->avail_out;
kusano 7d535a
    strm->total_in += in;
kusano 7d535a
    strm->total_out += out;
kusano 7d535a
    state->total += out;
kusano 7d535a
    if (state->wrap && out)
kusano 7d535a
        strm->adler = state->check =
kusano 7d535a
            UPDATE(state->check, strm->next_out - out, out);
kusano 7d535a
    strm->data_type = state->bits + (state->last ? 64 : 0) +
kusano 7d535a
                      (state->mode == TYPE ? 128 : 0) +
kusano 7d535a
                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
kusano 7d535a
    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
kusano 7d535a
        ret = Z_BUF_ERROR;
kusano 7d535a
    return ret;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateEnd(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if (state->window != Z_NULL) ZFREE(strm, state->window);
kusano 7d535a
    ZFREE(strm, strm->state);
kusano 7d535a
    strm->state = Z_NULL;
kusano 7d535a
    Tracev((stderr, "inflate: end\n"));
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
kusano 7d535a
z_streamp strm;
kusano 7d535a
const Bytef *dictionary;
kusano 7d535a
uInt dictLength;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
    unsigned long dictid;
kusano 7d535a
    unsigned char *next;
kusano 7d535a
    unsigned avail;
kusano 7d535a
    int ret;
kusano 7d535a
kusano 7d535a
    /* check state */
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if (state->wrap != 0 && state->mode != DICT)
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
kusano 7d535a
    /* check for correct dictionary identifier */
kusano 7d535a
    if (state->mode == DICT) {
kusano 7d535a
        dictid = adler32(0L, Z_NULL, 0);
kusano 7d535a
        dictid = adler32(dictid, dictionary, dictLength);
kusano 7d535a
        if (dictid != state->check)
kusano 7d535a
            return Z_DATA_ERROR;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* copy dictionary to window using updatewindow(), which will amend the
kusano 7d535a
       existing dictionary if appropriate */
kusano 7d535a
    next = strm->next_out;
kusano 7d535a
    avail = strm->avail_out;
kusano 7d535a
    strm->next_out = (Bytef *)dictionary + dictLength;
kusano 7d535a
    strm->avail_out = 0;
kusano 7d535a
    ret = updatewindow(strm, dictLength);
kusano 7d535a
    strm->avail_out = avail;
kusano 7d535a
    strm->next_out = next;
kusano 7d535a
    if (ret) {
kusano 7d535a
        state->mode = MEM;
kusano 7d535a
        return Z_MEM_ERROR;
kusano 7d535a
    }
kusano 7d535a
    state->havedict = 1;
kusano 7d535a
    Tracev((stderr, "inflate:   dictionary set\n"));
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateGetHeader(strm, head)
kusano 7d535a
z_streamp strm;
kusano 7d535a
gz_headerp head;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    /* check state */
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
kusano 7d535a
kusano 7d535a
    /* save header structure */
kusano 7d535a
    state->head = head;
kusano 7d535a
    head->done = 0;
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
kusano 7d535a
   or when out of input.  When called, *have is the number of pattern bytes
kusano 7d535a
   found in order so far, in 0..3.  On return *have is updated to the new
kusano 7d535a
   state.  If on return *have equals four, then the pattern was found and the
kusano 7d535a
   return value is how many bytes were read including the last byte of the
kusano 7d535a
   pattern.  If *have is less than four, then the pattern has not been found
kusano 7d535a
   yet and the return value is len.  In the latter case, syncsearch() can be
kusano 7d535a
   called again with more data and the *have state.  *have is initialized to
kusano 7d535a
   zero for the first call.
kusano 7d535a
 */
kusano 7d535a
local unsigned syncsearch(have, buf, len)
kusano 7d535a
unsigned FAR *have;
kusano 7d535a
unsigned char FAR *buf;
kusano 7d535a
unsigned len;
kusano 7d535a
{
kusano 7d535a
    unsigned got;
kusano 7d535a
    unsigned next;
kusano 7d535a
kusano 7d535a
    got = *have;
kusano 7d535a
    next = 0;
kusano 7d535a
    while (next < len && got < 4) {
kusano 7d535a
        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
kusano 7d535a
            got++;
kusano 7d535a
        else if (buf[next])
kusano 7d535a
            got = 0;
kusano 7d535a
        else
kusano 7d535a
            got = 4 - got;
kusano 7d535a
        next++;
kusano 7d535a
    }
kusano 7d535a
    *have = got;
kusano 7d535a
    return next;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateSync(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    unsigned len;               /* number of bytes to look at or looked at */
kusano 7d535a
    unsigned long in, out;      /* temporary to save total_in and total_out */
kusano 7d535a
    unsigned char buf[4];       /* to restore bit buffer to byte string */
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    /* check parameters */
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
kusano 7d535a
kusano 7d535a
    /* if first time, start search in bit buffer */
kusano 7d535a
    if (state->mode != SYNC) {
kusano 7d535a
        state->mode = SYNC;
kusano 7d535a
        state->hold <<= state->bits & 7;
kusano 7d535a
        state->bits -= state->bits & 7;
kusano 7d535a
        len = 0;
kusano 7d535a
        while (state->bits >= 8) {
kusano 7d535a
            buf[len++] = (unsigned char)(state->hold);
kusano 7d535a
            state->hold >>= 8;
kusano 7d535a
            state->bits -= 8;
kusano 7d535a
        }
kusano 7d535a
        state->have = 0;
kusano 7d535a
        syncsearch(&(state->have), buf, len);
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* search available input */
kusano 7d535a
    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
kusano 7d535a
    strm->avail_in -= len;
kusano 7d535a
    strm->next_in += len;
kusano 7d535a
    strm->total_in += len;
kusano 7d535a
kusano 7d535a
    /* return no joy or set up to restart inflate() on a new block */
kusano 7d535a
    if (state->have != 4) return Z_DATA_ERROR;
kusano 7d535a
    in = strm->total_in;  out = strm->total_out;
kusano 7d535a
    inflateReset(strm);
kusano 7d535a
    strm->total_in = in;  strm->total_out = out;
kusano 7d535a
    state->mode = TYPE;
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
   Returns true if inflate is currently at the end of a block generated by
kusano 7d535a
   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
kusano 7d535a
   implementation to provide an additional safety check. PPP uses
kusano 7d535a
   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
kusano 7d535a
   block. When decompressing, PPP checks that at the end of input packet,
kusano 7d535a
   inflate is waiting for these length bytes.
kusano 7d535a
 */
kusano 7d535a
int ZEXPORT inflateSyncPoint(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    return state->mode == STORED && state->bits == 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateCopy(dest, source)
kusano 7d535a
z_streamp dest;
kusano 7d535a
z_streamp source;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
    struct inflate_state FAR *copy;
kusano 7d535a
    unsigned char FAR *window;
kusano 7d535a
    unsigned wsize;
kusano 7d535a
kusano 7d535a
    /* check input */
kusano 7d535a
    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
kusano 7d535a
        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
kusano 7d535a
        return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)source->state;
kusano 7d535a
kusano 7d535a
    /* allocate space */
kusano 7d535a
    copy = (struct inflate_state FAR *)
kusano 7d535a
           ZALLOC(source, 1, sizeof(struct inflate_state));
kusano 7d535a
    if (copy == Z_NULL) return Z_MEM_ERROR;
kusano 7d535a
    window = Z_NULL;
kusano 7d535a
    if (state->window != Z_NULL) {
kusano 7d535a
        window = (unsigned char FAR *)
kusano 7d535a
                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
kusano 7d535a
        if (window == Z_NULL) {
kusano 7d535a
            ZFREE(source, copy);
kusano 7d535a
            return Z_MEM_ERROR;
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* copy state */
kusano 7d535a
    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
kusano 7d535a
    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
kusano 7d535a
    if (state->lencode >= state->codes &&
kusano 7d535a
        state->lencode <= state->codes + ENOUGH - 1) {
kusano 7d535a
        copy->lencode = copy->codes + (state->lencode - state->codes);
kusano 7d535a
        copy->distcode = copy->codes + (state->distcode - state->codes);
kusano 7d535a
    }
kusano 7d535a
    copy->next = copy->codes + (state->next - state->codes);
kusano 7d535a
    if (window != Z_NULL) {
kusano 7d535a
        wsize = 1U << state->wbits;
kusano 7d535a
        zmemcpy(window, state->window, wsize);
kusano 7d535a
    }
kusano 7d535a
    copy->window = window;
kusano 7d535a
    dest->state = (struct internal_state FAR *)copy;
kusano 7d535a
    return Z_OK;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int ZEXPORT inflateUndermine(strm, subvert)
kusano 7d535a
z_streamp strm;
kusano 7d535a
int subvert;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    state->sane = !subvert;
kusano 7d535a
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
kusano 7d535a
    return Z_OK;
kusano 7d535a
#else
kusano 7d535a
    state->sane = 1;
kusano 7d535a
    return Z_DATA_ERROR;
kusano 7d535a
#endif
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
long ZEXPORT inflateMark(strm)
kusano 7d535a
z_streamp strm;
kusano 7d535a
{
kusano 7d535a
    struct inflate_state FAR *state;
kusano 7d535a
kusano 7d535a
    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
kusano 7d535a
    state = (struct inflate_state FAR *)strm->state;
kusano 7d535a
    return ((long)(state->back) << 16) +
kusano 7d535a
        (state->mode == COPY ? state->length :
kusano 7d535a
            (state->mode == MATCH ? state->was - state->length : 0));
kusano 7d535a
}