nuttx/libs/libc/misc/lib_ncompress.c

1007 lines
30 KiB
C
Raw Normal View History

/****************************************************************************
* libs/libc/misc/lib_ncompress.c
* File compression ala IEEE Computer, Mar 1992.
*
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This is the file compress24.c extracted from the ncompress-4.2.4 release
* and adapted for NuttX. The original code was released into the public
* domain. This NuttX version is re-released under the standard NuttX
* BSD 3-clause license. The original authors are listed below:
*
* Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
* Ken Turkowski (decvax!decwrl!turtlevax!ken)
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
* Dave Mack (csu@alembic.acs.com)
* Peter Jannesen, Network Communication Systems
* (peter@ncs.nl)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define RECURSIVE 1
#ifdef __STDC__
# define ARGS(a) a
#else
# define ARGS(a) ()
#endif
#define LARGS(a) () /* Relay on include files for library func defs.
*/
#ifndef SIG_TYPE
# define SIG_TYPE void (*)()
#endif
#define MARK(a) { asm(" .globl M.a"); asm("M.a:"); }
#undef min
#define min(a,b) ((a>b) ? b : a)
#ifndef IBUFSIZ
# define IBUFSIZ BUFSIZ /* Defailt input buffer size */
#endif
#ifndef OBUFSIZ
# define OBUFSIZ BUFSIZ /* Default output buffer size */
#endif
#define MAXPATHLEN 1024 /* MAXPATHLEN - maximum length of a pathname we
* allow */
#define SIZE_INNER_LOOP 256 /* Size of the inter (fast) compress loop */
/* Defines for third byte of header */
#define MAGIC_1 (char_type)'\037' /* First byte of compressed file */
#define MAGIC_2 (char_type)'\235' /* Second byte of compressed file */
#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
/* Masks 0x20 and 0x40 are free. */
/* I think 0x20 should mean that there is */
/* a fourth header byte (for expansion). */
#define BLOCK_MODE 0x80 /* Block compression if table is full and */
/* compression rate is dropping flush tables */
/* the next two codes should not be changed lightly, as they must not
* lie within the contiguous general code space.
*/
#define FIRST 257 /* first free entry */
#define CLEAR 256 /* table clear output code */
#define INIT_BITS 9 /* initial number of bits/code */
#ifndef SACREDMEM
/* SACREDMEM is the amount of physical memory saved for others; compress
* will hog the rest.
*/
# define SACREDMEM 0
#endif
#ifndef USERMEM
/* Set USERMEM to the maximum amount of physical user memory available
* in bytes. USERMEM is used to determine the maximum BITS that can be used
* for compression.
*/
# define USERMEM 450000 /* default user memory */
#endif
#ifndef BYTEORDER
# define BYTEORDER 0000
#endif
#ifndef NOALLIGN
# define NOALLIGN 0
#endif
/* machine variants which require cc -Dmachine: pdp11, z8000, DOS */
#ifdef interdata /* Perkin-Elmer */
# define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */
#endif
#ifdef pdp11 /* PDP11: don't forget to compile with -i */
# define BITS 12 /* max bits/code for 16-bit machine */
# define NO_UCHAR /* also if "unsigned char" functions as signed
* char */
#endif /* pdp11 */
#ifdef z8000 /* Z8000: */
# define BITS 12 /* 16-bits processor max 12 bits */
# undef vax /* weird preprocessor */
#endif /* z8000 */
#ifdef DOS /* PC/XT/AT (8088) processor */
# define BITS 16 /* 16-bits processor max 12 bits */
# if BITS == 16
# define MAXSEG_64K
# endif
# undef BYTEORDER
# define BYTEORDER 4321
# undef NOALLIGN
# define NOALLIGN 1
#endif /* DOS */
#ifdef M_XENIX /* Stupid compiler can't handle arrays with */
# if BITS == 16 /* more than 65535 bytes - so we fake it */
# define MAXSEG_64K
# else
# if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */
# define BITS 13
# endif
# endif
#endif
#ifndef BITS /* General processor calculate BITS */
# if USERMEM >= (800000+SACREDMEM)
# define FAST
# else
# if USERMEM >= (433484+SACREDMEM)
# define BITS 16
# else
# if USERMEM >= (229600+SACREDMEM)
# define BITS 15
# else
# if USERMEM >= (127536+SACREDMEM)
# define BITS 14
# else
# if USERMEM >= (73464+SACREDMEM)
# define BITS 13
# else
# define BITS 12
# endif
# endif
# endif
# endif
# endif
#endif /* BITS */
#ifdef FAST
# define HBITS 17 /* 50% occupancy */
# define HSIZE (1<<HBITS)
# define HMASK (HSIZE-1)
# define HPRIME 9941
# define BITS 16
# undef MAXSEG_64K
#else
# if BITS == 16
# define HSIZE 69001 /* 95% occupancy */
# endif
# if BITS == 15
# define HSIZE 35023 /* 94% occupancy */
# endif
# if BITS == 14
# define HSIZE 18013 /* 91% occupancy */
# endif
# if BITS == 13
# define HSIZE 9001 /* 91% occupancy */
# endif
# if BITS <= 12
# define HSIZE 5003 /* 80% occupancy */
# endif
#endif
#define CHECK_GAP 10000
typedef long int code_int;
#ifdef SIGNED_COMPARE_SLOW
typedef unsigned long int count_int;
typedef unsigned short int count_short;
typedef unsigned long int cmp_code_int; /* Cast to make compare faster */
#else
typedef long int count_int;
typedef long int cmp_code_int;
#endif
typedef unsigned char char_type;
#define ARGVAL() (*++(*argv) || (--argc && *++argv))
#define MAXCODE(n) (1L << (n))
union bytes
{
long word;
struct
{
#if BYTEORDER == 4321
char_type b1;
char_type b2;
char_type b3;
char_type b4;
#else
# if BYTEORDER == 1234
char_type b4;
char_type b3;
char_type b2;
char_type b1;
# else
# undef BYTEORDER
int dummy;
# endif
#endif
} bytes;
};
#if BYTEORDER == 4321 && NOALLIGN == 1
# define output(b,o,c,n) { \
*(long *)&((b)[(o)>>3]) |= ((long)(c))<<((o)&0x7);\
(o) += (n); \
}
#else
# ifdef BYTEORDER
# define output(b,o,c,n) { char_type *p = &(b)[(o)>>3]; \
union bytes i; \
i.word = ((long)(c))<<((o)&0x7); \
p[0] |= i.bytes.b1; \
p[1] |= i.bytes.b2; \
p[2] |= i.bytes.b3; \
(o) += (n); \
}
# else
# define output(b,o,c,n) { char_type *p = &(b)[(o)>>3]; \
long i = ((long)(c))<<((o)&0x7); \
p[0] |= (char_type)(i); \
p[1] |= (char_type)(i>>8); \
p[2] |= (char_type)(i>>16); \
(o) += (n); \
}
# endif
#endif
#if BYTEORDER == 4321 && NOALLIGN == 1
# define input(b,o,c,n,m){ \
(c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
(o) += (n); \
}
#else
# define input(b,o,c,n,m){ char_type *p = &(b)[(o)>>3]; \
(c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
((long)(p[2])<<16))>>((o)&0x7))&(m); \
(o) += (n); \
}
#endif
char *progname; /* Program name */
int silent = 0; /* don't tell me about errors */
int quiet = 1; /* don't tell me about compression */
int do_decomp = 0; /* Decompress mode */
int force = 0; /* Force overwrite of files and links */
int nomagic = 0; /* Use a 3-byte magic number header, */
/* unless old file */
int block_mode = BLOCK_MODE; /* Block compress mode -C compatible with 2.0 */
int maxbits = BITS; /* user settable max # bits/code */
int zcat_flg = 0; /* Write output on stdout, suppress messages */
int recursive = 0; /* compress directories */
int exit_code = -1; /* Exitcode of compress (-1 no file compressed) */
char_type inbuf[IBUFSIZ + 64]; /* Input buffer */
char_type outbuf[OBUFSIZ + 2048]; /* Output buffer */
struct stat infstat; /* Input file status */
char *ifname; /* Input filename */
int remove_ofname = 0; /* Remove output file on a error */
char ofname[MAXPATHLEN]; /* Output filename */
int fgnd_flag = 0; /* Running in background (SIGINT=SIGIGN) */
long bytes_in; /* Total number of byte from input */
long bytes_out; /* Total number of byte to output */
/* To save much memory, we overlay the table used by compress() with those
* used by decompress(). The tab_prefix table is the same size and type
* as the codetab. The tab_suffix table needs 2**BITS characters. We
* get this from the beginning of htab. The output stack uses the rest
* of htab, and contains characters. There is plenty of room for any
* possible stack (stack used to be 8000 characters).
*/
#ifdef MAXSEG_64K
count_int htab0[8192];
count_int htab1[8192];
count_int htab2[8192];
count_int htab3[8192];
count_int htab4[8192];
count_int htab5[8192];
count_int htab6[8192];
count_int htab7[8192];
count_int htab8[HSIZE - 65536];
count_int *htab[9] =
{
htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8
};
unsigned short code0tab[16384];
unsigned short code1tab[16384];
unsigned short code2tab[16384];
unsigned short code3tab[16384];
unsigned short code4tab[16384];
unsigned short *codetab[5] =
{
code0tab, code1tab, code2tab, code3tab, code4tab
};
# define htabof(i) (htab[(i) >> 13][(i) & 0x1fff])
# define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff])
# define tab_prefixof(i) codetabof(i)
# define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
# define de_stack ((char_type *)(&htab2[8191]))
void clear_htab()
{
memset(htab0, -1, sizeof(htab0));
memset(htab1, -1, sizeof(htab1));
memset(htab2, -1, sizeof(htab2));
memset(htab3, -1, sizeof(htab3));
memset(htab4, -1, sizeof(htab4));
memset(htab5, -1, sizeof(htab5));
memset(htab6, -1, sizeof(htab6));
memset(htab7, -1, sizeof(htab7));
memset(htab8, -1, sizeof(htab8));
}
# define clear_tab_prefixof() memset(code0tab, 0, 256);
#else /* Normal machine */
count_int htab[HSIZE];
unsigned short codetab[HSIZE];
# define htabof(i) htab[i]
# define codetabof(i) codetab[i]
# define tab_prefixof(i) codetabof(i)
# define tab_suffixof(i) ((char_type *)(htab))[i]
# define de_stack ((char_type *)&(htab[HSIZE-1]))
# define clear_htab() memset(htab, -1, sizeof(htab))
# define clear_tab_prefixof() memset(codetab, 0, 256);
# ifdef FAST
int primetab[256] = /* Special secudary hash table. */
{
1013, -1061, 1109, -1181, 1231, -1291, 1361, -1429,
1481, -1531, 1583, -1627, 1699, -1759, 1831, -1889,
1973, -2017, 2083, -2137, 2213, -2273, 2339, -2383,
2441, -2531, 2593, -2663, 2707, -2753, 2819, -2887,
2957, -3023, 3089, -3181, 3251, -3313, 3361, -3449,
3511, -3557, 3617, -3677, 3739, -3821, 3881, -3931,
4013, -4079, 4139, -4219, 4271, -4349, 4423, -4493,
4561, -4639, 4691, -4783, 4831, -4931, 4973, -5023,
5101, -5179, 5261, -5333, 5413, -5471, 5521, -5591,
5659, -5737, 5807, -5857, 5923, -6029, 6089, -6151,
6221, -6287, 6343, -6397, 6491, -6571, 6659, -6709,
6791, -6857, 6917, -6983, 7043, -7129, 7213, -7297,
7369, -7477, 7529, -7577, 7643, -7703, 7789, -7873,
7933, -8017, 8093, -8171, 8237, -8297, 8387, -8461,
8543, -8627, 8689, -8741, 8819, -8867, 8963, -9029,
9109, -9181, 9241, -9323, 9397, -9439, 9511, -9613,
9677, -9743, 9811, -9871, 9941, -10061, 10111, -10177,
10259, -10321, 10399, -10477, 10567, -10639, 10711, -10789,
10867, -10949, 11047, -11113, 11173, -11261, 11329, -11423,
11491, -11587, 11681, -11777, 11827, -11903, 11959, -12041,
12109, -12197, 12263, -12343, 12413, -12487, 12541, -12611,
12671, -12757, 12829, -12917, 12979, -13043, 13127, -13187,
13291, -13367, 13451, -13523, 13619, -13691, 13751, -13829,
13901, -13967, 14057, -14153, 14249, -14341, 14419, -14489,
14557, -14633, 14717, -14767, 14831, -14897, 14983, -15083,
15149, -15233, 15289, -15359, 15427, -15497, 15583, -15649,
15733, -15791, 15881, -15937, 16057, -16097, 16189, -16267,
16363, -16447, 16529, -16619, 16691, -16763, 16879, -16937,
17021, -17093, 17183, -17257, 17341, -17401, 17477, -17551,
17623, -17713, 17791, -17891, 17957, -18041, 18097, -18169,
18233, -18307, 18379, -18451, 18523, -18637, 18731, -18803,
18919, -19031, 19121, -19211, 19273, -19381, 19429, -19477
};
# endif
/****************************************************************************
* Public Functions
****************************************************************************/
/* compress fdin to fdout
*
* Algorithm: use open addressing double hashing (no chaining) on the
* prefix code / next character combination. We do a variant of Knuth's
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
* secondary probe. Here, the modular division first probe is gives way
* to a faster exclusive-or manipulation. Also do block compression with
* an adaptive reset, whereby the code table is cleared when the compression
* ratio decreases, but after the table fills. The variable-length output
* codes are re-sized at this point, and a special CLEAR code is generated
* for the decompressor. Late addition: construct the table according to
* file size for noticeable speed improvement on small files. Please direct
* questions about this implementation to ames!jaw.
*/
void compress(int fdin, int fdout)
{
long hp;
int rpos;
long fc;
int outbits;
int rlop;
int rsize;
int stcode;
code_int free_ent;
int boff;
int n_bits;
int ratio;
long checkpoint;
code_int extcode;
union
{
long code;
struct
{
char_type c;
unsigned short ent;
} e;
} fcode;
ratio = 0;
checkpoint = CHECK_GAP;
extcode = MAXCODE(n_bits = INIT_BITS) + 1;
stcode = 1;
free_ent = FIRST;
memset(outbuf, 0, sizeof(outbuf));
bytes_out = 0;
bytes_in = 0;
outbuf[0] = MAGIC_1;
outbuf[1] = MAGIC_2;
outbuf[2] = (char)(maxbits | block_mode);
boff = outbits = (3 << 3);
fcode.code = 0;
clear_htab();
while ((rsize = read(fdin, inbuf, IBUFSIZ)) > 0)
{
if (bytes_in == 0)
{
fcode.e.ent = inbuf[0];
rpos = 1;
}
else
rpos = 0;
rlop = 0;
do
{
if (free_ent >= extcode && fcode.e.ent < FIRST)
{
if (n_bits < maxbits)
{
boff = outbits = (outbits - 1) + ((n_bits << 3) -
((outbits - boff - 1 +
(n_bits << 3)) %
(n_bits << 3)));
if (++n_bits < maxbits)
extcode = MAXCODE(n_bits) + 1;
else
extcode = MAXCODE(n_bits);
}
else
{
extcode = MAXCODE(16) + OBUFSIZ;
stcode = 0;
}
}
if (!stcode && bytes_in >= checkpoint && fcode.e.ent < FIRST)
{
long int rat;
checkpoint = bytes_in + CHECK_GAP;
if (bytes_in > 0x007fffff)
{
/* shift will overflow */
rat = (bytes_out + (outbits >> 3)) >> 8;
if (rat == 0) /* Don't divide by zero */
rat = 0x7fffffff;
else
rat = bytes_in / rat;
}
else
/* 8 fractional bits */
rat = (bytes_in << 8) / (bytes_out + (outbits >> 3));
if (rat >= ratio)
ratio = (int)rat;
else
{
ratio = 0;
clear_htab();
output(outbuf, outbits, CLEAR, n_bits);
boff = outbits = (outbits - 1) + ((n_bits << 3) -
((outbits - boff - 1 +
(n_bits << 3)) %
(n_bits << 3)));
extcode = MAXCODE(n_bits = INIT_BITS) + 1;
free_ent = FIRST;
stcode = 1;
}
}
if (outbits >= (OBUFSIZ << 3))
{
if (write(fdout, outbuf, OBUFSIZ) != OBUFSIZ)
write_error();
outbits -= (OBUFSIZ << 3);
boff = -(((OBUFSIZ << 3) - boff) % (n_bits << 3));
bytes_out += OBUFSIZ;
memcpy(outbuf, outbuf + OBUFSIZ, (outbits >> 3) + 1);
memset(outbuf + (outbits >> 3) + 1, '\0', OBUFSIZ);
}
{
int i;
i = rsize - rlop;
if ((code_int) i > extcode - free_ent)
i = (int)(extcode - free_ent);
if (i > ((sizeof(outbuf) - 32) * 8 - outbits) / n_bits)
i = ((sizeof(outbuf) - 32) * 8 - outbits) / n_bits;
if (!stcode && (long)i > checkpoint - bytes_in)
i = (int)(checkpoint - bytes_in);
rlop += i;
bytes_in += i;
}
goto next;
hfound:fcode.e.ent = codetabof(hp);
next:if (rpos >= rlop)
goto endlop;
next2:fcode.e.c = inbuf[rpos++];
# ifndef FAST
{
code_int i;
fc = fcode.code;
hp = (((long)(fcode.e.c)) << (BITS - 8)) ^ (long)(fcode.e.ent);
if ((i = htabof(hp)) == fc)
goto hfound;
if (i != -1)
{
long disp;
disp = (HSIZE - hp) - 1; /* secondary hash (after G.
* Knott) */
do
{
if ((hp -= disp) < 0)
hp += HSIZE;
if ((i = htabof(hp)) == fc)
goto hfound;
}
while (i != -1);
}
}
# else
{
long i;
long p;
fc = fcode.code;
hp = ((((long)(fcode.e.c)) << (HBITS - 8)) ^
(long)(fcode.e.ent));
if ((i = htabof(hp)) == fc)
goto hfound;
if (i == -1)
goto out;
p = primetab[fcode.e.c];
lookup:hp = (hp + p) & HMASK;
if ((i = htabof(hp)) == fc)
goto hfound;
if (i == -1)
goto out;
hp = (hp + p) & HMASK;
if ((i = htabof(hp)) == fc)
goto hfound;
if (i == -1)
goto out;
hp = (hp + p) & HMASK;
if ((i = htabof(hp)) == fc)
goto hfound;
if (i == -1)
goto out;
goto lookup;
}
out:;
# endif
output(outbuf, outbits, fcode.e.ent, n_bits);
{
long fc = fcode.code;
fcode.e.ent = fcode.e.c;
if (stcode)
{
codetabof(hp) = (unsigned short)free_ent++;
htabof(hp) = fc;
}
}
goto next;
endlop:if (fcode.e.ent >= FIRST && rpos < rsize)
goto next2;
if (rpos > rlop)
{
bytes_in += rpos - rlop;
rlop = rpos;
}
}
while (rlop < rsize);
}
if (rsize < 0)
read_error();
if (bytes_in > 0)
output(outbuf, outbits, fcode.e.ent, n_bits);
if (write(fdout, outbuf, (outbits + 7) >> 3) != (outbits + 7) >> 3)
write_error();
bytes_out += (outbits + 7) >> 3;
}
/* Decompress stdin to stdout. This routine adapts to the codes in the
* file building the "string" table on-the-fly; requiring no table to
* be stored in the compressed file. The tables used herein are shared
* with those of the compress() routine. See the definitions above.
*/
void decompress(int fdin, int fdout)
int fdin;
int fdout;
{
char_type *stackp;
code_int code;
int finchar;
code_int oldcode;
code_int incode;
int inbits;
int posbits;
int outpos;
int insize;
int bitmask;
code_int free_ent;
code_int maxcode;
code_int maxmaxcode;
int n_bits;
int rsize;
bytes_in = 0;
bytes_out = 0;
insize = 0;
while (insize < 3 && (rsize = read(fdin, inbuf + insize, IBUFSIZ)) > 0)
insize += rsize;
if (insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2)
{
if (rsize < 0)
read_error();
if (insize > 0)
{
fprintf(stderr, "%s: not in compressed format\n",
(ifname[0] != '\0' ? ifname : "stdin"));
exit_code = 1;
}
return;
}
maxbits = inbuf[2] & BIT_MASK;
block_mode = inbuf[2] & BLOCK_MODE;
if (maxbits > BITS)
{
fprintf(stderr,
"%s: compressed with %d bits, can only handle %d bits\n",
(*ifname != '\0' ? ifname : "stdin"), maxbits, BITS);
exit_code = 4;
return;
}
maxmaxcode = MAXCODE(maxbits);
bytes_in = insize;
maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
bitmask = (1 << n_bits) - 1;
oldcode = -1;
finchar = 0;
outpos = 0;
posbits = 3 << 3;
free_ent = ((block_mode) ? FIRST : 256);
clear_tab_prefixof(); /* As above, initialize the first 256 entries
* in the table. */
for (code = 255; code >= 0; --code)
tab_suffixof(code) = (char_type) code;
do
{
resetbuf:;
{
int i;
int e;
int o;
o = posbits >> 3;
e = o <= insize ? insize - o : 0;
for (i = 0; i < e; ++i)
inbuf[i] = inbuf[i + o];
insize = e;
posbits = 0;
}
if (insize < sizeof(inbuf) - IBUFSIZ)
{
if ((rsize = read(fdin, inbuf + insize, IBUFSIZ)) < 0)
read_error();
insize += rsize;
}
inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 :
(insize << 3) - (n_bits - 1));
while (inbits > posbits)
{
if (free_ent > maxcode)
{
posbits = ((posbits - 1) + ((n_bits << 3) -
(posbits - 1 +
(n_bits << 3)) % (n_bits << 3)));
++n_bits;
if (n_bits == maxbits)
maxcode = maxmaxcode;
else
maxcode = MAXCODE(n_bits) - 1;
bitmask = (1 << n_bits) - 1;
goto resetbuf;
}
input(inbuf, posbits, code, n_bits, bitmask);
if (oldcode == -1)
{
if (code >= 256)
{
fprintf(stderr, "oldcode:-1 code:%i\n", (int)(code));
fprintf(stderr, "uncompress: corrupt input\n");
abort_compress();
}
outbuf[outpos++] =
(char_type)(finchar = (int)(oldcode = code));
continue;
}
if (code == CLEAR && block_mode)
{
clear_tab_prefixof();
free_ent = FIRST - 1;
posbits = ((posbits - 1) + ((n_bits << 3) -
(posbits - 1 +
(n_bits << 3)) % (n_bits << 3)));
maxcode = MAXCODE(n_bits = INIT_BITS) - 1;
bitmask = (1 << n_bits) - 1;
goto resetbuf;
}
incode = code;
stackp = de_stack;
if (code >= free_ent) /* Special case for KwKwK string. */
{
if (code > free_ent)
{
char_type *p;
posbits -= n_bits;
p = &inbuf[posbits >> 3];
fprintf(stderr,
"insize:%d posbits:%d "
"inbuf:%02X %02X %02X %02X %02X (%d)\n",
insize, posbits, p[1], p[0], p[1], p[2], p[3],
(posbits & 07));
fprintf(stderr, "uncompress: corrupt input\n");
abort_compress();
}
*--stackp = (char_type) finchar;
code = oldcode;
}
/* Generate output characters in reverse order */
while ((cmp_code_int) code >= (cmp_code_int) 256)
{
*--stackp = tab_suffixof(code);
code = tab_prefixof(code);
}
*--stackp = (char_type) (finchar = tab_suffixof(code));
/* And put them out in forward order */
{
int i;
if (outpos + (i = (de_stack - stackp)) >= OBUFSIZ)
{
do
{
if (i > OBUFSIZ - outpos)
i = OBUFSIZ - outpos;
if (i > 0)
{
memcpy(outbuf + outpos, stackp, i);
outpos += i;
}
if (outpos >= OBUFSIZ)
{
if (write(fdout, outbuf, outpos) != outpos)
write_error();
outpos = 0;
}
stackp += i;
}
while ((i = (de_stack - stackp)) > 0);
}
else
{
memcpy(outbuf + outpos, stackp, i);
outpos += i;
}
}
if ((code = free_ent) < maxmaxcode) /* Generate the new entry. */
{
tab_prefixof(code) = (unsigned short)oldcode;
tab_suffixof(code) = (char_type) finchar;
free_ent = code + 1;
}
oldcode = incode; /* Remember previous code. */
}
bytes_in += rsize;
}
while (rsize > 0);
if (outpos > 0 && write(fdout, outbuf, outpos) != outpos)
write_error();
}
void read_error()
{
fprintf(stderr, "\nread error on");
perror((ifname[0] != '\0') ? ifname : "stdin");
abort_compress();
}
void write_error()
{
fprintf(stderr, "\nwrite error on");
perror((ofname[0] != '\0') ? ofname : "stdout");
abort_compress();
}
void abort_compress()
{
if (remove_ofname)
unlink(ofname);
exit(1);
}
void prratio(stream, num, den)
FILE *stream;
long int num;
long int den;
{
int q;
if (den > 0)
{
if (num > 214748L)
q = (int)(num / (den / 10000L)); /* 2147483647/10000 */
else
q = (int)(10000L * num / den); /* Long calculations, though */
}
else
q = 10000;
if (q < 0)
{
putc('-', stream);
q = -q;
}
fprintf(stream, "%d.%02d%%", q / 100, q % 100);
}