kusano fc6ab3
/* infback9.c -- inflate deflate64 data using a call-back interface
kusano fc6ab3
 * Copyright (C) 1995-2008 Mark Adler
kusano fc6ab3
 * For conditions of distribution and use, see copyright notice in zlib.h
kusano fc6ab3
 */
kusano fc6ab3
kusano fc6ab3
#include "zutil.h"
kusano fc6ab3
#include "infback9.h"
kusano fc6ab3
#include "inftree9.h"
kusano fc6ab3
#include "inflate9.h"
kusano fc6ab3
kusano fc6ab3
#define WSIZE 65536UL
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   strm provides memory allocation functions in zalloc and zfree, or
kusano fc6ab3
   Z_NULL to use the library memory allocation functions.
kusano fc6ab3
kusano fc6ab3
   window is a user-supplied window and output buffer that is 64K bytes.
kusano fc6ab3
 */
kusano fc6ab3
int ZEXPORT inflateBack9Init_(strm, window, version, stream_size)
kusano fc6ab3
z_stream FAR *strm;
kusano fc6ab3
unsigned char FAR *window;
kusano fc6ab3
const char *version;
kusano fc6ab3
int stream_size;
kusano fc6ab3
{
kusano fc6ab3
    struct inflate_state FAR *state;
kusano fc6ab3
kusano fc6ab3
    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
kusano fc6ab3
        stream_size != (int)(sizeof(z_stream)))
kusano fc6ab3
        return Z_VERSION_ERROR;
kusano fc6ab3
    if (strm == Z_NULL || window == Z_NULL)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    strm->msg = Z_NULL;                 /* in case we return an error */
kusano fc6ab3
    if (strm->zalloc == (alloc_func)0) {
kusano fc6ab3
        strm->zalloc = zcalloc;
kusano fc6ab3
        strm->opaque = (voidpf)0;
kusano fc6ab3
    }
kusano fc6ab3
    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
kusano fc6ab3
    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
kusano fc6ab3
                                               sizeof(struct inflate_state));
kusano fc6ab3
    if (state == Z_NULL) return Z_MEM_ERROR;
kusano fc6ab3
    Tracev((stderr, "inflate: allocated\n"));
kusano fc6ab3
    strm->state = (voidpf)state;
kusano fc6ab3
    state->window = window;
kusano fc6ab3
    return Z_OK;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   Build and output length and distance decoding tables for fixed code
kusano fc6ab3
   decoding.
kusano fc6ab3
 */
kusano fc6ab3
#ifdef MAKEFIXED
kusano fc6ab3
#include <stdio.h></stdio.h>
kusano fc6ab3
kusano fc6ab3
void makefixed9(void)
kusano fc6ab3
{
kusano fc6ab3
    unsigned sym, bits, low, size;
kusano fc6ab3
    code *next, *lenfix, *distfix;
kusano fc6ab3
    struct inflate_state state;
kusano fc6ab3
    code fixed[544];
kusano fc6ab3
kusano fc6ab3
    /* literal/length table */
kusano fc6ab3
    sym = 0;
kusano fc6ab3
    while (sym < 144) state.lens[sym++] = 8;
kusano fc6ab3
    while (sym < 256) state.lens[sym++] = 9;
kusano fc6ab3
    while (sym < 280) state.lens[sym++] = 7;
kusano fc6ab3
    while (sym < 288) state.lens[sym++] = 8;
kusano fc6ab3
    next = fixed;
kusano fc6ab3
    lenfix = next;
kusano fc6ab3
    bits = 9;
kusano fc6ab3
    inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work);
kusano fc6ab3
kusano fc6ab3
    /* distance table */
kusano fc6ab3
    sym = 0;
kusano fc6ab3
    while (sym < 32) state.lens[sym++] = 5;
kusano fc6ab3
    distfix = next;
kusano fc6ab3
    bits = 5;
kusano fc6ab3
    inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work);
kusano fc6ab3
kusano fc6ab3
    /* write tables */
kusano fc6ab3
    puts("    /* inffix9.h -- table for decoding deflate64 fixed codes");
kusano fc6ab3
    puts("     * Generated automatically by makefixed9().");
kusano fc6ab3
    puts("     */");
kusano fc6ab3
    puts("");
kusano fc6ab3
    puts("    /* WARNING: this file should *not* be used by applications.");
kusano fc6ab3
    puts("       It is part of the implementation of this library and is");
kusano fc6ab3
    puts("       subject to change. Applications should only use zlib.h.");
kusano fc6ab3
    puts("     */");
kusano fc6ab3
    puts("");
kusano fc6ab3
    size = 1U << 9;
kusano fc6ab3
    printf("    static const code lenfix[%u] = {", size);
kusano fc6ab3
    low = 0;
kusano fc6ab3
    for (;;) {
kusano fc6ab3
        if ((low % 6) == 0) printf("\n        ");
kusano fc6ab3
        printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits,
kusano fc6ab3
               lenfix[low].val);
kusano fc6ab3
        if (++low == size) break;
kusano fc6ab3
        putchar(',');
kusano fc6ab3
    }
kusano fc6ab3
    puts("\n    };");
kusano fc6ab3
    size = 1U << 5;
kusano fc6ab3
    printf("\n    static const code distfix[%u] = {", size);
kusano fc6ab3
    low = 0;
kusano fc6ab3
    for (;;) {
kusano fc6ab3
        if ((low % 5) == 0) printf("\n        ");
kusano fc6ab3
        printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits,
kusano fc6ab3
               distfix[low].val);
kusano fc6ab3
        if (++low == size) break;
kusano fc6ab3
        putchar(',');
kusano fc6ab3
    }
kusano fc6ab3
    puts("\n    };");
kusano fc6ab3
}
kusano fc6ab3
#endif /* MAKEFIXED */
kusano fc6ab3
kusano fc6ab3
/* Macros for inflateBack(): */
kusano fc6ab3
kusano fc6ab3
/* Clear the input bit accumulator */
kusano fc6ab3
#define INITBITS() \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold = 0; \
kusano fc6ab3
        bits = 0; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that some input is available.  If input is requested, but denied,
kusano fc6ab3
   then return a Z_BUF_ERROR from inflateBack(). */
kusano fc6ab3
#define PULL() \
kusano fc6ab3
    do { \
kusano fc6ab3
        if (have == 0) { \
kusano fc6ab3
            have = in(in_desc, &next); \
kusano fc6ab3
            if (have == 0) { \
kusano fc6ab3
                next = Z_NULL; \
kusano fc6ab3
                ret = Z_BUF_ERROR; \
kusano fc6ab3
                goto inf_leave; \
kusano fc6ab3
            } \
kusano fc6ab3
        } \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Get a byte of input into the bit accumulator, or return from inflateBack()
kusano fc6ab3
   with an error if there is no input available. */
kusano fc6ab3
#define PULLBYTE() \
kusano fc6ab3
    do { \
kusano fc6ab3
        PULL(); \
kusano fc6ab3
        have--; \
kusano fc6ab3
        hold += (unsigned long)(*next++) << bits; \
kusano fc6ab3
        bits += 8; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that there are at least n bits in the bit accumulator.  If there is
kusano fc6ab3
   not enough available input to do that, then return from inflateBack() with
kusano fc6ab3
   an error. */
kusano fc6ab3
#define NEEDBITS(n) \
kusano fc6ab3
    do { \
kusano fc6ab3
        while (bits < (unsigned)(n)) \
kusano fc6ab3
            PULLBYTE(); \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Return the low n bits of the bit accumulator (n <= 16) */
kusano fc6ab3
#define BITS(n) \
kusano fc6ab3
    ((unsigned)hold & ((1U << (n)) - 1))
kusano fc6ab3
kusano fc6ab3
/* Remove n bits from the bit accumulator */
kusano fc6ab3
#define DROPBITS(n) \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold >>= (n); \
kusano fc6ab3
        bits -= (unsigned)(n); \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Remove zero to seven bits as needed to go to a byte boundary */
kusano fc6ab3
#define BYTEBITS() \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold >>= bits & 7; \
kusano fc6ab3
        bits -= bits & 7; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that some output space is available, by writing out the window
kusano fc6ab3
   if it's full.  If the write fails, return from inflateBack() with a
kusano fc6ab3
   Z_BUF_ERROR. */
kusano fc6ab3
#define ROOM() \
kusano fc6ab3
    do { \
kusano fc6ab3
        if (left == 0) { \
kusano fc6ab3
            put = window; \
kusano fc6ab3
            left = WSIZE; \
kusano fc6ab3
            wrap = 1; \
kusano fc6ab3
            if (out(out_desc, put, (unsigned)left)) { \
kusano fc6ab3
                ret = Z_BUF_ERROR; \
kusano fc6ab3
                goto inf_leave; \
kusano fc6ab3
            } \
kusano fc6ab3
        } \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   strm provides the memory allocation functions and window buffer on input,
kusano fc6ab3
   and provides information on the unused input on return.  For Z_DATA_ERROR
kusano fc6ab3
   returns, strm will also provide an error message.
kusano fc6ab3
kusano fc6ab3
   in() and out() are the call-back input and output functions.  When
kusano fc6ab3
   inflateBack() needs more input, it calls in().  When inflateBack() has
kusano fc6ab3
   filled the window with output, or when it completes with data in the
kusano fc6ab3
   window, it calls out() to write out the data.  The application must not
kusano fc6ab3
   change the provided input until in() is called again or inflateBack()
kusano fc6ab3
   returns.  The application must not change the window/output buffer until
kusano fc6ab3
   inflateBack() returns.
kusano fc6ab3
kusano fc6ab3
   in() and out() are called with a descriptor parameter provided in the
kusano fc6ab3
   inflateBack() call.  This parameter can be a structure that provides the
kusano fc6ab3
   information required to do the read or write, as well as accumulated
kusano fc6ab3
   information on the input and output such as totals and check values.
kusano fc6ab3
kusano fc6ab3
   in() should return zero on failure.  out() should return non-zero on
kusano fc6ab3
   failure.  If either in() or out() fails, than inflateBack() returns a
kusano fc6ab3
   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
kusano fc6ab3
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
kusano fc6ab3
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
kusano fc6ab3
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
kusano fc6ab3
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
kusano fc6ab3
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
kusano fc6ab3
 */
kusano fc6ab3
int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc)
kusano fc6ab3
z_stream FAR *strm;
kusano fc6ab3
in_func in;
kusano fc6ab3
void FAR *in_desc;
kusano fc6ab3
out_func out;
kusano fc6ab3
void FAR *out_desc;
kusano fc6ab3
{
kusano fc6ab3
    struct inflate_state FAR *state;
kusano fc6ab3
    z_const unsigned char FAR *next;    /* next input */
kusano fc6ab3
    unsigned char FAR *put;     /* next output */
kusano fc6ab3
    unsigned have;              /* available input */
kusano fc6ab3
    unsigned long left;         /* available output */
kusano fc6ab3
    inflate_mode mode;          /* current inflate mode */
kusano fc6ab3
    int lastblock;              /* true if processing last block */
kusano fc6ab3
    int wrap;                   /* true if the window has wrapped */
kusano fc6ab3
    unsigned char FAR *window;  /* allocated sliding window, if needed */
kusano fc6ab3
    unsigned long hold;         /* bit buffer */
kusano fc6ab3
    unsigned bits;              /* bits in bit buffer */
kusano fc6ab3
    unsigned extra;             /* extra bits needed */
kusano fc6ab3
    unsigned long length;       /* literal or length of data to copy */
kusano fc6ab3
    unsigned long offset;       /* distance back to copy string from */
kusano fc6ab3
    unsigned long copy;         /* number of stored or match bytes to copy */
kusano fc6ab3
    unsigned char FAR *from;    /* where to copy match bytes from */
kusano fc6ab3
    code const FAR *lencode;    /* starting table for length/literal codes */
kusano fc6ab3
    code const FAR *distcode;   /* starting table for distance codes */
kusano fc6ab3
    unsigned lenbits;           /* index bits for lencode */
kusano fc6ab3
    unsigned distbits;          /* index bits for distcode */
kusano fc6ab3
    code here;                  /* current decoding table entry */
kusano fc6ab3
    code last;                  /* parent table entry */
kusano fc6ab3
    unsigned len;               /* length to copy for repeats, bits to drop */
kusano fc6ab3
    int ret;                    /* return code */
kusano fc6ab3
    static const unsigned short order[19] = /* permutation of code lengths */
kusano fc6ab3
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
kusano fc6ab3
#include "inffix9.h"
kusano fc6ab3
kusano fc6ab3
    /* Check that the strm exists and that the state was initialized */
kusano fc6ab3
    if (strm == Z_NULL || strm->state == Z_NULL)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    state = (struct inflate_state FAR *)strm->state;
kusano fc6ab3
kusano fc6ab3
    /* Reset the state */
kusano fc6ab3
    strm->msg = Z_NULL;
kusano fc6ab3
    mode = TYPE;
kusano fc6ab3
    lastblock = 0;
kusano fc6ab3
    wrap = 0;
kusano fc6ab3
    window = state->window;
kusano fc6ab3
    next = strm->next_in;
kusano fc6ab3
    have = next != Z_NULL ? strm->avail_in : 0;
kusano fc6ab3
    hold = 0;
kusano fc6ab3
    bits = 0;
kusano fc6ab3
    put = window;
kusano fc6ab3
    left = WSIZE;
kusano fc6ab3
    lencode = Z_NULL;
kusano fc6ab3
    distcode = Z_NULL;
kusano fc6ab3
kusano fc6ab3
    /* Inflate until end of block marked as last */
kusano fc6ab3
    for (;;)
kusano fc6ab3
        switch (mode) {
kusano fc6ab3
        case TYPE:
kusano fc6ab3
            /* determine and dispatch block type */
kusano fc6ab3
            if (lastblock) {
kusano fc6ab3
                BYTEBITS();
kusano fc6ab3
                mode = DONE;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            NEEDBITS(3);
kusano fc6ab3
            lastblock = BITS(1);
kusano fc6ab3
            DROPBITS(1);
kusano fc6ab3
            switch (BITS(2)) {
kusano fc6ab3
            case 0:                             /* stored block */
kusano fc6ab3
                Tracev((stderr, "inflate:     stored block%s\n",
kusano fc6ab3
                        lastblock ? " (last)" : ""));
kusano fc6ab3
                mode = STORED;
kusano fc6ab3
                break;
kusano fc6ab3
            case 1:                             /* fixed block */
kusano fc6ab3
                lencode = lenfix;
kusano fc6ab3
                lenbits = 9;
kusano fc6ab3
                distcode = distfix;
kusano fc6ab3
                distbits = 5;
kusano fc6ab3
                Tracev((stderr, "inflate:     fixed codes block%s\n",
kusano fc6ab3
                        lastblock ? " (last)" : ""));
kusano fc6ab3
                mode = LEN;                     /* decode codes */
kusano fc6ab3
                break;
kusano fc6ab3
            case 2:                             /* dynamic block */
kusano fc6ab3
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
kusano fc6ab3
                        lastblock ? " (last)" : ""));
kusano fc6ab3
                mode = TABLE;
kusano fc6ab3
                break;
kusano fc6ab3
            case 3:
kusano fc6ab3
                strm->msg = (char *)"invalid block type";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(2);
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case STORED:
kusano fc6ab3
            /* get and verify stored block length */
kusano fc6ab3
            BYTEBITS();                         /* go to byte boundary */
kusano fc6ab3
            NEEDBITS(32);
kusano fc6ab3
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
kusano fc6ab3
                strm->msg = (char *)"invalid stored block lengths";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            length = (unsigned)hold & 0xffff;
kusano fc6ab3
            Tracev((stderr, "inflate:       stored length %lu\n",
kusano fc6ab3
                    length));
kusano fc6ab3
            INITBITS();
kusano fc6ab3
kusano fc6ab3
            /* copy stored block from input to output */
kusano fc6ab3
            while (length != 0) {
kusano fc6ab3
                copy = length;
kusano fc6ab3
                PULL();
kusano fc6ab3
                ROOM();
kusano fc6ab3
                if (copy > have) copy = have;
kusano fc6ab3
                if (copy > left) copy = left;
kusano fc6ab3
                zmemcpy(put, next, copy);
kusano fc6ab3
                have -= copy;
kusano fc6ab3
                next += copy;
kusano fc6ab3
                left -= copy;
kusano fc6ab3
                put += copy;
kusano fc6ab3
                length -= copy;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       stored end\n"));
kusano fc6ab3
            mode = TYPE;
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case TABLE:
kusano fc6ab3
            /* get dynamic table entries descriptor */
kusano fc6ab3
            NEEDBITS(14);
kusano fc6ab3
            state->nlen = BITS(5) + 257;
kusano fc6ab3
            DROPBITS(5);
kusano fc6ab3
            state->ndist = BITS(5) + 1;
kusano fc6ab3
            DROPBITS(5);
kusano fc6ab3
            state->ncode = BITS(4) + 4;
kusano fc6ab3
            DROPBITS(4);
kusano fc6ab3
            if (state->nlen > 286) {
kusano fc6ab3
                strm->msg = (char *)"too many length symbols";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       table sizes ok\n"));
kusano fc6ab3
kusano fc6ab3
            /* get code length code lengths (not a typo) */
kusano fc6ab3
            state->have = 0;
kusano fc6ab3
            while (state->have < state->ncode) {
kusano fc6ab3
                NEEDBITS(3);
kusano fc6ab3
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
kusano fc6ab3
                DROPBITS(3);
kusano fc6ab3
            }
kusano fc6ab3
            while (state->have < 19)
kusano fc6ab3
                state->lens[order[state->have++]] = 0;
kusano fc6ab3
            state->next = state->codes;
kusano fc6ab3
            lencode = (code const FAR *)(state->next);
kusano fc6ab3
            lenbits = 7;
kusano fc6ab3
            ret = inflate_table9(CODES, state->lens, 19, &(state->next),
kusano fc6ab3
                                &(lenbits), state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid code lengths set";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       code lengths ok\n"));
kusano fc6ab3
kusano fc6ab3
            /* get length and distance code code lengths */
kusano fc6ab3
            state->have = 0;
kusano fc6ab3
            while (state->have < state->nlen + state->ndist) {
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = lencode[BITS(lenbits)];
kusano fc6ab3
                    if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                if (here.val < 16) {
kusano fc6ab3
                    NEEDBITS(here.bits);
kusano fc6ab3
                    DROPBITS(here.bits);
kusano fc6ab3
                    state->lens[state->have++] = here.val;
kusano fc6ab3
                }
kusano fc6ab3
                else {
kusano fc6ab3
                    if (here.val == 16) {
kusano fc6ab3
                        NEEDBITS(here.bits + 2);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        if (state->have == 0) {
kusano fc6ab3
                            strm->msg = (char *)"invalid bit length repeat";
kusano fc6ab3
                            mode = BAD;
kusano fc6ab3
                            break;
kusano fc6ab3
                        }
kusano fc6ab3
                        len = (unsigned)(state->lens[state->have - 1]);
kusano fc6ab3
                        copy = 3 + BITS(2);
kusano fc6ab3
                        DROPBITS(2);
kusano fc6ab3
                    }
kusano fc6ab3
                    else if (here.val == 17) {
kusano fc6ab3
                        NEEDBITS(here.bits + 3);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        len = 0;
kusano fc6ab3
                        copy = 3 + BITS(3);
kusano fc6ab3
                        DROPBITS(3);
kusano fc6ab3
                    }
kusano fc6ab3
                    else {
kusano fc6ab3
                        NEEDBITS(here.bits + 7);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        len = 0;
kusano fc6ab3
                        copy = 11 + BITS(7);
kusano fc6ab3
                        DROPBITS(7);
kusano fc6ab3
                    }
kusano fc6ab3
                    if (state->have + copy > state->nlen + state->ndist) {
kusano fc6ab3
                        strm->msg = (char *)"invalid bit length repeat";
kusano fc6ab3
                        mode = BAD;
kusano fc6ab3
                        break;
kusano fc6ab3
                    }
kusano fc6ab3
                    while (copy--)
kusano fc6ab3
                        state->lens[state->have++] = (unsigned short)len;
kusano fc6ab3
                }
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* handle error breaks in while */
kusano fc6ab3
            if (mode == BAD) break;
kusano fc6ab3
kusano fc6ab3
            /* check for end-of-block code (better have one) */
kusano fc6ab3
            if (state->lens[256] == 0) {
kusano fc6ab3
                strm->msg = (char *)"invalid code -- missing end-of-block";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* build code tables -- note: do not change the lenbits or distbits
kusano fc6ab3
               values here (9 and 6) without reading the comments in inftree9.h
kusano fc6ab3
               concerning the ENOUGH constants, which depend on those values */
kusano fc6ab3
            state->next = state->codes;
kusano fc6ab3
            lencode = (code const FAR *)(state->next);
kusano fc6ab3
            lenbits = 9;
kusano fc6ab3
            ret = inflate_table9(LENS, state->lens, state->nlen,
kusano fc6ab3
                            &(state->next), &(lenbits), state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid literal/lengths set";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            distcode = (code const FAR *)(state->next);
kusano fc6ab3
            distbits = 6;
kusano fc6ab3
            ret = inflate_table9(DISTS, state->lens + state->nlen,
kusano fc6ab3
                            state->ndist, &(state->next), &(distbits),
kusano fc6ab3
                            state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid distances set";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       codes ok\n"));
kusano fc6ab3
            mode = LEN;
kusano fc6ab3
kusano fc6ab3
        case LEN:
kusano fc6ab3
            /* get a literal, length, or end-of-block code */
kusano fc6ab3
            for (;;) {
kusano fc6ab3
                here = lencode[BITS(lenbits)];
kusano fc6ab3
                if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                PULLBYTE();
kusano fc6ab3
            }
kusano fc6ab3
            if (here.op && (here.op & 0xf0) == 0) {
kusano fc6ab3
                last = here;
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = lencode[last.val +
kusano fc6ab3
                            (BITS(last.bits + last.op) >> last.bits)];
kusano fc6ab3
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                DROPBITS(last.bits);
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(here.bits);
kusano fc6ab3
            length = (unsigned)here.val;
kusano fc6ab3
kusano fc6ab3
            /* process literal */
kusano fc6ab3
            if (here.op == 0) {
kusano fc6ab3
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
kusano fc6ab3
                        "inflate:         literal '%c'\n" :
kusano fc6ab3
                        "inflate:         literal 0x%02x\n", here.val));
kusano fc6ab3
                ROOM();
kusano fc6ab3
                *put++ = (unsigned char)(length);
kusano fc6ab3
                left--;
kusano fc6ab3
                mode = LEN;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* process end of block */
kusano fc6ab3
            if (here.op & 32) {
kusano fc6ab3
                Tracevv((stderr, "inflate:         end of block\n"));
kusano fc6ab3
                mode = TYPE;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* invalid code */
kusano fc6ab3
            if (here.op & 64) {
kusano fc6ab3
                strm->msg = (char *)"invalid literal/length code";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* length code -- get extra bits, if any */
kusano fc6ab3
            extra = (unsigned)(here.op) & 31;
kusano fc6ab3
            if (extra != 0) {
kusano fc6ab3
                NEEDBITS(extra);
kusano fc6ab3
                length += BITS(extra);
kusano fc6ab3
                DROPBITS(extra);
kusano fc6ab3
            }
kusano fc6ab3
            Tracevv((stderr, "inflate:         length %lu\n", length));
kusano fc6ab3
kusano fc6ab3
            /* get distance code */
kusano fc6ab3
            for (;;) {
kusano fc6ab3
                here = distcode[BITS(distbits)];
kusano fc6ab3
                if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                PULLBYTE();
kusano fc6ab3
            }
kusano fc6ab3
            if ((here.op & 0xf0) == 0) {
kusano fc6ab3
                last = here;
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = distcode[last.val +
kusano fc6ab3
                            (BITS(last.bits + last.op) >> last.bits)];
kusano fc6ab3
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                DROPBITS(last.bits);
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(here.bits);
kusano fc6ab3
            if (here.op & 64) {
kusano fc6ab3
                strm->msg = (char *)"invalid distance code";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            offset = (unsigned)here.val;
kusano fc6ab3
kusano fc6ab3
            /* get distance extra bits, if any */
kusano fc6ab3
            extra = (unsigned)(here.op) & 15;
kusano fc6ab3
            if (extra != 0) {
kusano fc6ab3
                NEEDBITS(extra);
kusano fc6ab3
                offset += BITS(extra);
kusano fc6ab3
                DROPBITS(extra);
kusano fc6ab3
            }
kusano fc6ab3
            if (offset > WSIZE - (wrap ? 0: left)) {
kusano fc6ab3
                strm->msg = (char *)"invalid distance too far back";
kusano fc6ab3
                mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracevv((stderr, "inflate:         distance %lu\n", offset));
kusano fc6ab3
kusano fc6ab3
            /* copy match from window to output */
kusano fc6ab3
            do {
kusano fc6ab3
                ROOM();
kusano fc6ab3
                copy = WSIZE - offset;
kusano fc6ab3
                if (copy < left) {
kusano fc6ab3
                    from = put + copy;
kusano fc6ab3
                    copy = left - copy;
kusano fc6ab3
                }
kusano fc6ab3
                else {
kusano fc6ab3
                    from = put - offset;
kusano fc6ab3
                    copy = left;
kusano fc6ab3
                }
kusano fc6ab3
                if (copy > length) copy = length;
kusano fc6ab3
                length -= copy;
kusano fc6ab3
                left -= copy;
kusano fc6ab3
                do {
kusano fc6ab3
                    *put++ = *from++;
kusano fc6ab3
                } while (--copy);
kusano fc6ab3
            } while (length != 0);
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case DONE:
kusano fc6ab3
            /* inflate stream terminated properly -- write leftover output */
kusano fc6ab3
            ret = Z_STREAM_END;
kusano fc6ab3
            if (left < WSIZE) {
kusano fc6ab3
                if (out(out_desc, window, (unsigned)(WSIZE - left)))
kusano fc6ab3
                    ret = Z_BUF_ERROR;
kusano fc6ab3
            }
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
kusano fc6ab3
        case BAD:
kusano fc6ab3
            ret = Z_DATA_ERROR;
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
kusano fc6ab3
        default:                /* can't happen, but makes compilers happy */
kusano fc6ab3
            ret = Z_STREAM_ERROR;
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
        }
kusano fc6ab3
kusano fc6ab3
    /* Return unused input */
kusano fc6ab3
  inf_leave:
kusano fc6ab3
    strm->next_in = next;
kusano fc6ab3
    strm->avail_in = have;
kusano fc6ab3
    return ret;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
int ZEXPORT inflateBack9End(strm)
kusano fc6ab3
z_stream FAR *strm;
kusano fc6ab3
{
kusano fc6ab3
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    ZFREE(strm, strm->state);
kusano fc6ab3
    strm->state = Z_NULL;
kusano fc6ab3
    Tracev((stderr, "inflate: end\n"));
kusano fc6ab3
    return Z_OK;
kusano fc6ab3
}