diff options
-rw-r--r-- | lib/libz/adler32.c | 4 | ||||
-rw-r--r-- | lib/libz/compress.c | 37 | ||||
-rw-r--r-- | lib/libz/crc32.c | 12 | ||||
-rw-r--r-- | lib/libz/deflate.c | 283 | ||||
-rw-r--r-- | lib/libz/deflate.h | 45 | ||||
-rw-r--r-- | lib/libz/example.c | 95 | ||||
-rw-r--r-- | lib/libz/gzio.c | 397 | ||||
-rw-r--r-- | lib/libz/minigzip.c | 123 | ||||
-rw-r--r-- | lib/libz/trees.c | 151 | ||||
-rw-r--r-- | lib/libz/uncompr.c | 6 | ||||
-rw-r--r-- | lib/libz/zconf.h | 92 | ||||
-rw-r--r-- | lib/libz/zutil.c | 22 | ||||
-rw-r--r-- | lib/libz/zutil.h | 64 |
13 files changed, 1076 insertions, 255 deletions
diff --git a/lib/libz/adler32.c b/lib/libz/adler32.c index 7c35d51..b1f71ce 100644 --- a/lib/libz/adler32.c +++ b/lib/libz/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-1996 Mark Adler + * Copyright (C) 1995-1998 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,7 +18,7 @@ #define DO16(buf) DO8(buf,0); DO8(buf,8); /* ========================================================================= */ -uLong adler32(adler, buf, len) +uLong ZEXPORT adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; diff --git a/lib/libz/compress.c b/lib/libz/compress.c index 686f365..31c51e6 100644 --- a/lib/libz/compress.c +++ b/lib/libz/compress.c @@ -1,5 +1,5 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,22 +8,22 @@ #include "zlib.h" /* =========================================================================== - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 8 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. */ -int compress (dest, destLen, source, sourceLen) +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; + int level; { z_stream stream; int err; @@ -42,7 +42,7 @@ int compress (dest, destLen, source, sourceLen) stream.zfree = (free_func)0; stream.opaque = (voidpf)0; - err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); + err = deflateInit(&stream, level); if (err != Z_OK) return err; err = deflate(&stream, Z_FINISH); @@ -55,3 +55,14 @@ int compress (dest, destLen, source, sourceLen) err = deflateEnd(&stream); return err; } + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/lib/libz/crc32.c b/lib/libz/crc32.c index 8fa0ee6..2e98580 100644 --- a/lib/libz/crc32.c +++ b/lib/libz/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-1996 Mark Adler + * Copyright (C) 1995-1998 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -45,7 +45,7 @@ local void make_crc_table() int n, k; uLong poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ - static Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* make exclusive-or pattern from polynomial (0xedb88320L) */ poly = 0L; @@ -65,7 +65,7 @@ local void make_crc_table() /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ -local uLongf crc_table[256] = { +local const uLongf crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, @@ -124,12 +124,12 @@ local uLongf crc_table[256] = { /* ========================================================================= * This function can be used by asm versions of crc32() */ -uLongf *get_crc_table() +const uLongf * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif - return (uLongf *)crc_table; + return (const uLongf *)crc_table; } /* ========================================================================= */ @@ -139,7 +139,7 @@ uLongf *get_crc_table() #define DO8(buf) DO4(buf); DO4(buf); /* ========================================================================= */ -uLong crc32(crc, buf, len) +uLong ZEXPORT crc32(crc, buf, len) uLong crc; const Bytef *buf; uInt len; diff --git a/lib/libz/deflate.c b/lib/libz/deflate.c index 81c649e..dc8c76c 100644 --- a/lib/libz/deflate.c +++ b/lib/libz/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,8 +36,8 @@ * * REFERENCES * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -51,7 +51,8 @@ #include "deflate.h" -char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly "; +const char deflate_copyright[] = + " deflate 1.1.1 Copyright 1995-1998 Jean-loup Gailly "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -77,12 +78,14 @@ local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); local block_state deflate_slow OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); -local uInt longest_match OF((deflate_state *s, IPos cur_match)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, charf *buf, unsigned size)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #ifdef DEBUG @@ -120,7 +123,7 @@ typedef struct config_s { compress_func func; } config; -local config configuration_table[10] = { +local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ @@ -157,14 +160,23 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) +#endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). @@ -172,10 +184,10 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ - zmemzero((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ -int deflateInit_(strm, level, version, stream_size) +int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; int level; const char *version; @@ -187,7 +199,7 @@ int deflateInit_(strm, level, version, stream_size) } /* ========================================================================= */ -int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size) z_streamp strm; int level; @@ -200,13 +212,14 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, { deflate_state *s; int noheader = 0; + static const char* my_version = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } @@ -220,6 +233,9 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (strm->zfree == Z_NULL) strm->zfree = zcfree; if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif if (windowBits < 0) { /* undocumented feature: suppress zlib header */ noheader = 1; @@ -253,6 +269,7 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { @@ -271,7 +288,7 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, } /* ========================================================================= */ -int deflateSetDictionary (strm, dictionary, dictLength) +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; @@ -290,9 +307,11 @@ int deflateSetDictionary (strm, dictionary, dictLength) if (length < MIN_MATCH) return Z_OK; if (length > MAX_DIST(s)) { length = MAX_DIST(s); - dictionary += dictLength - length; +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif } - zmemcpy((charf *)s->window, dictionary, length); + zmemcpy(s->window, dictionary, length); s->strstart = length; s->block_start = (long)length; @@ -310,7 +329,7 @@ int deflateSetDictionary (strm, dictionary, dictLength) } /* ========================================================================= */ -int deflateReset (strm) +int ZEXPORT deflateReset (strm) z_streamp strm; { deflate_state *s; @@ -340,7 +359,7 @@ int deflateReset (strm) } /* ========================================================================= */ -int deflateParams(strm, level, strategy) +int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; @@ -414,7 +433,7 @@ local void flush_pending(strm) } /* ========================================================================= */ -int deflate (strm, flush) +int ZEXPORT deflate (strm, flush) z_streamp strm; int flush; { @@ -548,42 +567,85 @@ int deflate (strm, flush) } /* ========================================================================= */ -int deflateEnd (strm) +int ZEXPORT deflateEnd (strm) z_streamp strm; { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); - status = strm->state->status; ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } -/* ========================================================================= */ -int deflateCopy (dest, source) +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) z_streamp dest; z_streamp source; { - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + ss = source->state; + + if (source == Z_NULL || dest == Z_NULL || ss == Z_NULL) { return Z_STREAM_ERROR; } *dest = *source; - return Z_STREAM_ERROR; /* to be implemented */ -#if 0 - dest->state = (struct internal_state FAR *) - (*dest->zalloc)(1, sizeof(deflate_state)); - if (dest->state == Z_NULL) return Z_MEM_ERROR; - *(dest->state) = *(source->state); + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + return Z_OK; #endif } @@ -597,7 +659,7 @@ int deflateCopy (dest, source) */ local int read_buf(strm, buf, size) z_streamp strm; - charf *buf; + Bytef *buf; unsigned size; { unsigned len = strm->avail_in; @@ -658,6 +720,7 @@ local void lm_init (s) /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ +#ifndef FASTEST local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ @@ -792,9 +855,67 @@ local uInt longest_match(s, cur_match) } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); - if ((uInt)best_len <= s->lookahead) return best_len; + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ #endif /* ASMV */ #ifdef DEBUG @@ -807,8 +928,8 @@ local void check_match(s, start, match, length) int length; { /* check that the match is indeed a match */ - if (zmemcmp((charf *)s->window + match, - (charf *)s->window + start, length) != EQUAL) { + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { @@ -816,7 +937,7 @@ local void check_match(s, start, match, length) } while (--length != 0); z_error("invalid match"); } - if (verbose > 1) { + if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } @@ -861,33 +982,35 @@ local void fill_window(s) */ } else if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy((charf *)s->window, (charf *)s->window+wsize, - (unsigned)wsize); + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage): + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif more += wsize; } if (s->strm->avail_in == 0) return; @@ -905,8 +1028,7 @@ local void fill_window(s) */ Assert(more >= 2, "more < 2"); - n = read_buf(s->strm, (charf *)s->window + s->strstart + s->lookahead, - more); + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ @@ -951,12 +1073,24 @@ local void fill_window(s) * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { @@ -974,14 +1108,17 @@ local block_state deflate_stored(s, flush) s->strstart += s->lookahead; s->lookahead = 0; - /* Stored blocks are limited to 0xffff bytes: */ - if (s->strstart == 0 || s->strstart > 0xfffe) { + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = s->strstart - 0xffff; - s->strstart = 0xffff; + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); } - - /* Emit a stored block if it is large enough: */ + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } @@ -1041,14 +1178,15 @@ local block_state deflate_fast(s, flush) if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); - bflush = _tr_tally(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH); + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ +#ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in hash table */ @@ -1060,7 +1198,9 @@ local block_state deflate_fast(s, flush) */ } while (--s->match_length != 0); s->strstart++; - } else { + } else +#endif + { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; @@ -1075,7 +1215,7 @@ local block_state deflate_fast(s, flush) } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); - bflush = _tr_tally (s, 0, s->window[s->strstart]); + _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } @@ -1154,8 +1294,8 @@ local block_state deflate_slow(s, flush) check_match(s, s->strstart-1, s->prev_match, s->prev_length); - bflush = _tr_tally(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH); + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not @@ -1181,7 +1321,8 @@ local block_state deflate_slow(s, flush) * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); - if (_tr_tally (s, 0, s->window[s->strstart-1])) { + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; @@ -1199,7 +1340,7 @@ local block_state deflate_slow(s, flush) Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally (s, 0, s->window[s->strstart-1]); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } FLUSH_BLOCK(s, flush == Z_FINISH); diff --git a/lib/libz/deflate.h b/lib/libz/deflate.h index 689adea..5cf65ec 100644 --- a/lib/libz/deflate.h +++ b/lib/libz/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-1996 Jean-loup Gailly + * Copyright (C) 1995-1998 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -83,6 +83,7 @@ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ int pending; /* nb of bytes in the pending buffer */ int noheader; /* suppress zlib header and adler32 */ @@ -272,4 +273,46 @@ ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, void _tr_align OF((deflate_state *s)); void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + #endif diff --git a/lib/libz/example.c b/lib/libz/example.c index 3830842..e313c55 100644 --- a/lib/libz/example.c +++ b/lib/libz/example.c @@ -1,5 +1,5 @@ /* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -41,7 +41,7 @@ void test_large_deflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_large_inflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong comprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); void test_sync OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_dict_deflate OF((Byte *compr, uLong comprLen)); @@ -69,6 +69,7 @@ void test_compress(compr, comprLen, uncompr, uncomprLen) if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad uncompress\n"); + exit(1); } else { printf("uncompress(): %s\n", uncompr); } @@ -86,16 +87,23 @@ void test_gzio(out, in, uncompr, uncomprLen) int err; int len = strlen(hello)+1; gzFile file; + z_off_t pos; file = gzopen(out, "wb"); if (file == NULL) { fprintf(stderr, "gzopen error\n"); exit(1); } - - if (gzwrite(file, (const voidp)hello, (unsigned)len) != len) { - fprintf(stderr, "gzwrite err: %s\n", gzerror(file, &err)); + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ gzclose(file); file = gzopen(in, "rb"); @@ -107,14 +115,41 @@ void test_gzio(out, in, uncompr, uncomprLen) uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen); if (uncomprLen != len) { fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); } - gzclose(file); - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread\n"); + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); } else { printf("gzread(): %s\n", uncompr); } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + pos, gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, uncomprLen); + uncomprLen = strlen((char*)uncompr); + if (uncomprLen != 6) { /* "hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello+7)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", uncompr); + } + + gzclose(file); } /* =========================================================================== @@ -171,12 +206,13 @@ void test_inflate(compr, comprLen, uncompr, uncomprLen) d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - d_stream.next_in = compr; + d_stream.avail_in = 0; d_stream.next_out = uncompr; + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ err = inflate(&d_stream, Z_NO_FLUSH); @@ -189,6 +225,7 @@ void test_inflate(compr, comprLen, uncompr, uncomprLen) if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad inflate\n"); + exit(1); } else { printf("inflate(): %s\n", uncompr); } @@ -223,6 +260,7 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen) CHECK_ERR(err, "deflate"); if (c_stream.avail_in != 0) { fprintf(stderr, "deflate not greedy\n"); + exit(1); } /* Feed in already compressed data and switch to no compression: */ @@ -242,6 +280,7 @@ void test_large_deflate(compr, comprLen, uncompr, uncomprLen) err = deflate(&c_stream, Z_FINISH); if (err != Z_STREAM_END) { fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); @@ -263,12 +302,12 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - d_stream.next_in = compr; d_stream.avail_in = (uInt)comprLen; + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + for (;;) { d_stream.next_out = uncompr; /* discard the output */ d_stream.avail_out = (uInt)uncomprLen; @@ -282,6 +321,7 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) if (d_stream.total_out != 2*uncomprLen + comprLen/2) { fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); } else { printf("large_inflate(): OK\n"); } @@ -292,7 +332,7 @@ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) */ void test_flush(compr, comprLen) Byte *compr; - uLong comprLen; + uLong *comprLen; { z_stream c_stream; /* compression stream */ int err; @@ -308,7 +348,7 @@ void test_flush(compr, comprLen) c_stream.next_in = (Bytef*)hello; c_stream.next_out = compr; c_stream.avail_in = 3; - c_stream.avail_out = (uInt)comprLen; + c_stream.avail_out = (uInt)*comprLen; err = deflate(&c_stream, Z_FULL_FLUSH); CHECK_ERR(err, "deflate"); @@ -321,6 +361,8 @@ void test_flush(compr, comprLen) } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; } /* =========================================================================== @@ -339,12 +381,13 @@ void test_sync(compr, comprLen, uncompr, uncomprLen) d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + err = inflateInit(&d_stream); CHECK_ERR(err, "inflateInit"); - d_stream.next_in = compr; d_stream.next_out = uncompr; - d_stream.avail_in = 2; /* just read the zlib header */ d_stream.avail_out = (uInt)uncomprLen; inflate(&d_stream, Z_NO_FLUSH); @@ -358,6 +401,7 @@ void test_sync(compr, comprLen, uncompr, uncomprLen) if (err != Z_DATA_ERROR) { fprintf(stderr, "inflate should report DATA_ERROR\n"); /* Because of incorrect adler32 */ + exit(1); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); @@ -396,6 +440,7 @@ void test_dict_deflate(compr, comprLen) err = deflate(&c_stream, Z_FINISH); if (err != Z_STREAM_END) { fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); @@ -417,12 +462,12 @@ void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - d_stream.next_in = compr; d_stream.avail_in = (uInt)comprLen; + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + d_stream.next_out = uncompr; d_stream.avail_out = (uInt)uncomprLen; @@ -445,6 +490,7 @@ void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad inflate with dict\n"); + exit(1); } else { printf("inflate with dictionary: %s\n", uncompr); } @@ -461,8 +507,9 @@ int main(argc, argv) Byte *compr, *uncompr; uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; - if (zlibVersion()[0] != ZLIB_VERSION[0]) { + if (zlibVersion()[0] != myVersion[0]) { fprintf(stderr, "incompatible zlib version\n"); exit(1); @@ -479,7 +526,6 @@ int main(argc, argv) printf("out of memory\n"); exit(1); } - test_compress(compr, comprLen, uncompr, uncomprLen); test_gzio((argc > 1 ? argv[1] : "foo.gz"), @@ -492,8 +538,9 @@ int main(argc, argv) test_large_deflate(compr, comprLen, uncompr, uncomprLen); test_large_inflate(compr, comprLen, uncompr, uncomprLen); - test_flush(compr, comprLen); + test_flush(compr, &comprLen); test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; test_dict_deflate(compr, comprLen); test_dict_inflate(compr, comprLen, uncompr, uncomprLen); diff --git a/lib/libz/gzio.c b/lib/libz/gzio.c index f62b125..e3782d5 100644 --- a/lib/libz/gzio.c +++ b/lib/libz/gzio.c @@ -1,6 +1,8 @@ /* gzio.c -- IO on .gz files - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. */ /* $FreeBSD$ */ @@ -11,7 +13,8 @@ struct internal_state {int dummy;}; /* for buggy compilers */ -#define Z_BUFSIZE 4096 +#define Z_BUFSIZE 16384 +#define Z_PRINTF_BUFSIZE 4096 #define ALLOC(size) malloc(size) #define TRYFREE(p) {if (p) free(p);} @@ -38,10 +41,12 @@ typedef struct gz_stream { char *path; /* path name for debugging only */ int transparent; /* 1 if input file is not a .gz file */ char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ } gz_stream; local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); local int get_byte OF((gz_stream *s)); local void check_header OF((gz_stream *s)); local int destroy OF((gz_stream *s)); @@ -64,6 +69,7 @@ local gzFile gz_open (path, mode, fd) { int err; int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ char *p = (char*)mode; gz_stream *s; char fmode[80]; /* copy of mode, without the compression level */ @@ -99,6 +105,10 @@ local gzFile gz_open (path, mode, fd) if (*p == 'w' || *p == 'a') s->mode = 'w'; if (*p >= '0' && *p <= '9') { level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; } else { *m++ = *p; /* copy the mode */ } @@ -106,19 +116,24 @@ local gzFile gz_open (path, mode, fd) if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else err = deflateInit2(&(s->stream), level, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); /* windowBits is passed < 0 to suppress zlib header */ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); - +#endif if (err != Z_OK || s->outbuf == Z_NULL) { return destroy(s), (gzFile)Z_NULL; } } else { - err = inflateInit2(&(s->stream), -MAX_WBITS); s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header */ + if (err != Z_OK || s->inbuf == Z_NULL) { return destroy(s), (gzFile)Z_NULL; } @@ -126,7 +141,7 @@ local gzFile gz_open (path, mode, fd) s->stream.avail_out = Z_BUFSIZE; errno = 0; - s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); if (s->file == NULL) { return destroy(s), (gzFile)Z_NULL; @@ -136,16 +151,24 @@ local gzFile gz_open (path, mode, fd) */ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ } else { check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); } + return (gzFile)s; } /* =========================================================================== Opens a gzip (.gz) file for reading or writing. */ -gzFile gzopen (path, mode) +gzFile ZEXPORT gzopen (path, mode) const char *path; const char *mode; { @@ -156,7 +179,7 @@ gzFile gzopen (path, mode) Associate a gzFile with the file descriptor fd. fd is not dup'ed here to mimic the behavio(u)r of fdopen. */ -gzFile gzdopen (fd, mode) +gzFile ZEXPORT gzdopen (fd, mode) int fd; const char *mode; { @@ -169,6 +192,31 @@ gzFile gzdopen (fd, mode) } /* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. @@ -212,8 +260,11 @@ local void check_header(s) for (len = 0; len < 2; len++) { c = get_byte(s); if (c != gz_magic[len]) { - s->transparent = 1; - if (c != EOF) s->stream.avail_in++, s->stream.next_in--; + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; return; } @@ -260,14 +311,21 @@ local int destroy (s) TRYFREE(s->msg); if (s->stream.state != NULL) { - if (s->mode == 'w') { - err = deflateEnd(&(s->stream)); - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } } if (s->file != NULL && fclose(s->file)) { - err = Z_ERRNO; +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; } if (s->z_err < 0) err = s->z_err; @@ -282,13 +340,13 @@ local int destroy (s) Reads the given number of uncompressed bytes from the compressed file. gzread returns the number of bytes actually read (0 for end of file). */ -int gzread (file, buf, len) +int ZEXPORT gzread (file, buf, len) gzFile file; voidp buf; unsigned len; { gz_stream *s = (gz_stream*)file; - Bytef *start = buf; /* starting point for crc computation */ + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; @@ -296,7 +354,8 @@ int gzread (file, buf, len) if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; if (s->z_err == Z_STREAM_END) return 0; /* EOF */ - s->stream.next_out = next_out = buf; + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; s->stream.avail_out = len; while (s->stream.avail_out != 0) { @@ -317,7 +376,10 @@ int gzread (file, buf, len) s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, s->file); } - return (int)(len - s->stream.avail_out); + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + return (int)len; } if (s->stream.avail_in == 0 && !s->z_eof) { @@ -345,7 +407,12 @@ int gzread (file, buf, len) /* Check for concatenated .gz files: */ check_header(s); if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; s->crc = crc32(0L, Z_NULL, 0); } } @@ -357,11 +424,49 @@ int gzread (file, buf, len) return (int)(len - s->stream.avail_out); } + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE /* =========================================================================== Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of bytes actually written (0 in case of error). */ -int gzwrite (file, buf, len) +int ZEXPORT gzwrite (file, buf, len) gzFile file; const voidp buf; unsigned len; @@ -370,7 +475,7 @@ int gzwrite (file, buf, len) if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - s->stream.next_in = buf; + s->stream.next_in = (Bytef*)buf; s->stream.avail_in = len; while (s->stream.avail_in != 0) { @@ -387,18 +492,95 @@ int gzwrite (file, buf, len) s->z_err = deflate(&(s->stream), Z_NO_FLUSH); if (s->z_err != Z_OK) break; } - s->crc = crc32(s->crc, buf, len); + s->crc = crc32(s->crc, (const Bytef *)buf, len); return (int)(len - s->stream.avail_in); } /* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include <stdarg.h> + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (const voidp)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. - gzflush should be called only when strictly necessary because it can - degrade compression. */ -int gzflush (file, flush) +local int do_flush (file, flush) gzFile file; int flush; { @@ -424,6 +606,9 @@ int gzflush (file, flush) if (done) break; s->z_err = deflate(&(s->stream), flush); + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + /* deflate has finished flushing only when it hasn't used up * all the available space in the output buffer: */ @@ -431,9 +616,154 @@ int gzflush (file, flush) if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; fflush(s->file); return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; } +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_out; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} /* =========================================================================== Outputs a long in LSB order to the given file @@ -470,7 +800,7 @@ local uLong getLong (s) Flushes all pending output if necessary, closes the compressed file and deallocates all the (de)compression state. */ -int gzclose (file) +int ZEXPORT gzclose (file) gzFile file; { int err; @@ -479,14 +809,17 @@ int gzclose (file) if (s == NULL) return Z_STREAM_ERROR; if (s->mode == 'w') { - err = gzflush (file, Z_FINISH); - if (err != Z_OK) return destroy(file); +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); putLong (s->file, s->crc); putLong (s->file, s->stream.total_in); - +#endif } - return destroy(file); + return destroy((gz_stream*)file); } /* =========================================================================== @@ -496,7 +829,7 @@ int gzclose (file) errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. */ -const char* gzerror (file, errnum) +const char* ZEXPORT gzerror (file, errnum) gzFile file; int *errnum; { diff --git a/lib/libz/minigzip.c b/lib/libz/minigzip.c index 9548ab8..7ba1666 100644 --- a/lib/libz/minigzip.c +++ b/lib/libz/minigzip.c @@ -1,5 +1,5 @@ /* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -25,6 +25,11 @@ extern void exit OF((int)); #endif +#ifdef USE_MMAP +# include <sys/types.h> +# include <sys/mman.h> +# include <sys/stat.h> +#endif #if defined(MSDOS) || defined(OS2) || defined(WIN32) # include <fcntl.h> @@ -44,30 +49,36 @@ # define fileno(file) file->__file #endif +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif + #ifndef GZ_SUFFIX # define GZ_SUFFIX ".gz" #endif -#define SUFFIX_LEN sizeof(GZ_SUFFIX) - -extern int unlink OF((const char *)); +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) -#define BUFLEN 4096 +#define BUFLEN 16384 #define MAX_NAME_LEN 1024 -#define local static -/* For MSDOS and other systems with limitation on stack size. For Unix, - #define local - works also. - */ +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif char *prog; -void error OF((const char *msg)); -void gz_compress OF((FILE *in, gzFile out)); -void gz_uncompress OF((gzFile in, FILE *out)); -void file_compress OF((char *file)); -void file_uncompress OF((char *file)); -int main OF((int argc, char *argv[])); +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); /* =========================================================================== * Display error message and exit @@ -82,6 +93,7 @@ void error(msg) /* =========================================================================== * Compress input to output then close both files. */ + void gz_compress(in, out) FILE *in; gzFile out; @@ -90,6 +102,12 @@ void gz_compress(in, out) int len; int err; +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif for (;;) { len = fread(buf, 1, sizeof(buf), in); if (ferror(in)) { @@ -104,6 +122,43 @@ void gz_compress(in, out) if (gzclose(out) != Z_OK) error("failed gzclose"); } +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + /* =========================================================================== * Uncompress input to output then close both files. */ @@ -134,8 +189,9 @@ void gz_uncompress(in, out) * Compress the given file: create a corresponding .gz file and remove the * original. */ -void file_compress(file) +void file_compress(file, mode) char *file; + char *mode; { local char outfile[MAX_NAME_LEN]; FILE *in; @@ -149,7 +205,7 @@ void file_compress(file) perror(file); exit(1); } - out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */ + out = gzopen(outfile, mode); if (out == NULL) { fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); exit(1); @@ -201,7 +257,11 @@ void file_uncompress(file) /* =========================================================================== - * Usage: minigzip [-d] [files...] + * Usage: minigzip [-d] [-f] [-h] [-1 to -9] [files...] + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -1 to -9 : compression level */ int main(argc, argv) @@ -210,15 +270,26 @@ int main(argc, argv) { int uncompr = 0; gzFile file; + char outmode[20]; + + strcpy(outmode, "wb6 "); prog = argv[0]; argc--, argv++; - if (argc > 0) { - uncompr = (strcmp(*argv, "-d") == 0); - if (uncompr) { - argc--, argv++; - } + while (argc > 0) { + if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; } if (argc == 0) { SET_BINARY_MODE(stdin); @@ -228,7 +299,7 @@ int main(argc, argv) if (file == NULL) error("can't gzdopen stdin"); gz_uncompress(file, stdout); } else { - file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */ + file = gzdopen(fileno(stdout), outmode); if (file == NULL) error("can't gzdopen stdout"); gz_compress(stdin, file); } @@ -237,7 +308,7 @@ int main(argc, argv) if (uncompr) { file_uncompress(*argv); } else { - file_compress(*argv); + file_compress(*argv, outmode); } } while (argv++, --argc); } diff --git a/lib/libz/trees.c b/lib/libz/trees.c index a5a8173..2497001 100644 --- a/lib/libz/trees.c +++ b/lib/libz/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-1996 Jean-loup Gailly + * Copyright (C) 1995-1998 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -31,6 +31,8 @@ /* $FreeBSD$ */ +/* #define GEN_TREES_H */ + #include "deflate.h" #ifdef DEBUG @@ -56,16 +58,16 @@ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ -local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; -local int extra_dbits[D_CODES] /* extra bits for each distance code */ +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; -local int extra_blbits[BL_CODES]/* extra bits for each bit length code */ +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; -local uch bl_order[BL_CODES] +local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. @@ -80,6 +82,11 @@ local uch bl_order[BL_CODES] * Local data. These are initialized only once. */ +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However @@ -92,13 +99,13 @@ local ct_data static_dtree[D_CODES]; * 5 bits.) */ -local uch dist_code[512]; -/* distance codes. The first 256 values correspond to the distances +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ -local uch length_code[MAX_MATCH-MIN_MATCH+1]; +uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; @@ -107,9 +114,13 @@ local int base_length[LENGTH_CODES]; local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + struct static_tree_desc_s { - ct_data *static_tree; /* static tree or NULL */ - intf *extra_bits; /* extra bits for each code or NULL */ + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ @@ -122,7 +133,7 @@ local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = -{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. @@ -148,23 +159,20 @@ local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ - { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif -#define d_code(dist) \ - ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. dist_code[256] and dist_code[257] are never - * used. - */ - /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. @@ -226,12 +234,11 @@ local void send_bits(s, value, length) /* the arguments must not have side effects */ /* =========================================================================== - * Initialize the various 'constant' tables. In a multi-threaded environment, - * this function may be called by two threads concurrently, but this is - * harmless since both invocations do exactly the same thing. + * Initialize the various 'constant' tables. */ local void tr_static_init() { +#if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ @@ -248,7 +255,7 @@ local void tr_static_init() for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1<<extra_lbits[code]); n++) { - length_code[length++] = (uch)code; + _length_code[length++] = (uch)code; } } Assert (length == 256, "tr_static_init: length != 256"); @@ -256,14 +263,14 @@ local void tr_static_init() * in two different ways: code 284 + 5 bits or code 285, so we * overwrite length_code[255] to use the best encoding: */ - length_code[length-1] = (uch)code; + _length_code[length-1] = (uch)code; /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<<extra_dbits[code]); n++) { - dist_code[dist++] = (uch)code; + _dist_code[dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: dist != 256"); @@ -271,7 +278,7 @@ local void tr_static_init() for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - dist_code[256 + dist++] = (uch)code; + _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); @@ -295,7 +302,73 @@ local void tr_static_init() static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); } +#endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. @@ -413,12 +486,12 @@ local void gen_bitlen(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - ct_data *stree = desc->stat_desc->static_tree; - intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ @@ -542,9 +615,9 @@ local void build_tree(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { - ct_data *tree = desc->dyn_tree; - ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ @@ -965,12 +1038,13 @@ int _tr_tally (s, dist, lc) (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++; + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } +#ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ - if (s->level > 2 && (s->last_lit & 0xfff) == 0) { + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); @@ -985,6 +1059,7 @@ int _tr_tally (s, dist, lc) 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } +#endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to @@ -1014,7 +1089,7 @@ local void compress_block(s, ltree, dtree) Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ - code = length_code[lc]; + code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { diff --git a/lib/libz/uncompr.c b/lib/libz/uncompr.c index 06cd6a8..b1bd9fc 100644 --- a/lib/libz/uncompr.c +++ b/lib/libz/uncompr.c @@ -1,5 +1,5 @@ /* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -22,7 +22,7 @@ enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ -int uncompress (dest, destLen, source, sourceLen) +int ZEXPORT uncompress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; @@ -49,7 +49,7 @@ int uncompress (dest, destLen, source, sourceLen) err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); - return err; + return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; diff --git a/lib/libz/zconf.h b/lib/libz/zconf.h index 858e0a0..5b71e4b 100644 --- a/lib/libz/zconf.h +++ b/lib/libz/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -27,8 +27,10 @@ # define inflateInit2_ z_inflateInit2_ # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint # define inflateReset z_inflateReset # define compress z_compress +# define compress2 z_compress2 # define uncompress z_uncompress # define adler32 z_adler32 # define crc32 z_crc32 @@ -72,8 +74,10 @@ #if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) # define STDC #endif -#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC) -# define STDC +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif #endif #ifndef STDC @@ -87,6 +91,12 @@ # define NO_DUMMY_DECL #endif +/* Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) +# define NEED_DUMMY_RETURN +#endif + + /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K @@ -96,13 +106,17 @@ # endif #endif -/* Maximum value for windowBits in deflateInit2 and inflateInit2 */ +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): - 1 << (windowBits+2) + 1 << (memLevel+9) + (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with @@ -145,6 +159,29 @@ # define FAR __far # endif #endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL) +# ifdef FAR +# undef FAR +# endif +# include <windows.h> +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +#else +# if defined (__BORLANDC__) && defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# else +# define ZEXPORT +# define ZEXPORTVA +# endif +#endif + #ifndef FAR # define FAR #endif @@ -172,13 +209,44 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif - -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL) -# include <windows.h> -# define EXPORT WINAPI -#else -# define EXPORT +#ifdef HAVE_UNISTD_H +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") #endif #endif /* _ZCONF_H */ diff --git a/lib/libz/zutil.c b/lib/libz/zutil.c index 5858792..0d12b55 100644 --- a/lib/libz/zutil.c +++ b/lib/libz/zutil.c @@ -1,12 +1,10 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* $FreeBSD$ */ -#include <stdio.h> - #include "zutil.h" struct internal_state {int dummy;}; /* for buggy compilers */ @@ -28,12 +26,18 @@ const char *z_errmsg[10] = { ""}; -const char *zlibVersion() +const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } #ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + void z_error (m) char *m; { @@ -42,6 +46,16 @@ void z_error (m) } #endif +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + #ifndef HAVE_MEMCPY void zmemcpy(dest, source, len) diff --git a/lib/libz/zutil.h b/lib/libz/zutil.h index 14b6f0a..3843e0d 100644 --- a/lib/libz/zutil.h +++ b/lib/libz/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-1996 Jean-loup Gailly. + * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -15,16 +15,16 @@ #include "zlib.h" -#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS) -# include <stddef.h> -# include <errno.h> -#else - extern int errno; -#endif #ifdef STDC +# include <stddef.h> # include <string.h> # include <stdlib.h> #endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif #ifndef local # define local static @@ -76,7 +76,13 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef MSDOS # define OS_CODE 0x00 # ifdef __TURBOC__ -# include <alloc.h> +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif # else /* MSC or DJGPP */ # include <malloc.h> # endif @@ -92,7 +98,7 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 -# define FOPEN(name, mode) \ +# define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif @@ -104,8 +110,16 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ # define OS_CODE 0x05 #endif -#ifdef MACOS +#if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +#endif +#if defined(__MWERKS__) && !defined(fdopen) +# if __dest_os != __be_os && __dest_os != __win32_os +# define fdopen(fd,mode) NULL +# endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ @@ -120,14 +134,19 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ # define fdopen(fd,mode) NULL /* No fdopen() */ #endif +#if (defined(_MSC_VER) && (_MSC_VER >= 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + /* Common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif -#ifndef FOPEN -# define FOPEN(name, mode) fopen((name), (mode)) +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ @@ -142,9 +161,10 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(pyr) # define NO_MEMCPY #endif -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER) +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif @@ -170,16 +190,14 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ /* Diagnostic functions */ #ifdef DEBUG # include <stdio.h> -# ifndef verbose -# define verbose 0 -# endif + extern int z_verbose; extern void z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) @@ -190,8 +208,8 @@ extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ #endif -typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len)); - +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void zcfree OF((voidpf opaque, voidpf ptr)); |