aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/compress.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-02-21 22:21:59 -0600
committerRob Landley <rob@landley.net>2014-02-21 22:21:59 -0600
commitc5dabf136495a69e9226eaa8316332de57ad481e (patch)
tree9123fa578ee516e1885267d054c98edbeb533232 /toys/pending/compress.c
parenta2359011a808463b86b3b7477a7c0d06f8445df6 (diff)
downloadtoybox-c5dabf136495a69e9226eaa8316332de57ad481e.tar.gz
Update inflate code: fixed tables, bugfixes, zcat alias.
Diffstat (limited to 'toys/pending/compress.c')
-rw-r--r--toys/pending/compress.c78
1 files changed, 52 insertions, 26 deletions
diff --git a/toys/pending/compress.c b/toys/pending/compress.c
index acc7d62b..9c9ae2ea 100644
--- a/toys/pending/compress.c
+++ b/toys/pending/compress.c
@@ -11,9 +11,11 @@
* LSB 4.1 has gzip, gunzip, and zcat
* TODO: zip -d DIR -x LIST -list -quiet -no overwrite -overwrite -p to stdout
-// Accept many different kinds of command line argument:
+// Accept many different kinds of command line argument.
+// Leave Lrg at end so flag values line up.
-USE_COMPRESS(NEWTOY(compress, "zglrcd9[-cd][!zglr]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_COMPRESS(NEWTOY(compress, "zcd9Lrg[-cd][!zgLr]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_COMPRESS(NEWTOY(zcat, "aLrg[!aLrg]", TOYFLAG_USR|TOYFLAG_BIN))
//zip unzip gzip gunzip zcat
@@ -25,12 +27,17 @@ config COMPRESS
Compress or decompress file (or stdin) using "deflate" algorithm.
- -c compress
- -d decompress
- -g gzip
- -l zlib
- -r raw (default)
- -z zip
+ -c compress with -g gzip (default) -L zlib -r raw -z zip
+ -d decompress (autodetects type)
+
+config ZCAT
+ bool "zcat"
+ default n
+ depends on COMPRESS
+ help
+ usage: zcat [FILE...]
+
+ Decompress deflated file(s) to stdout
*/
#define FOR_compress
@@ -40,6 +47,7 @@ GLOBALS(
// base offset and extra bits tables (length and distance)
char lenbits[29], distbits[30];
unsigned short lenbase[29], distbase[30];
+ void *fixdisthuff, *fixlithuff;
unsigned (*crcfunc)(char *data, int len);
unsigned crc;
@@ -102,7 +110,7 @@ int bitbuf_get(struct bitbuf *bb, int bits)
int click = bb->bitpos >> 3, blow, blen;
// Load more data if buffer empty
- if (click == bb->len) bitbuf_skip(bb, 0);
+ if (click == bb->len) bitbuf_skip(bb, click = 0);
// grab bits from next byte
blow = bb->bitpos & 7;
@@ -123,7 +131,7 @@ static void outbuf_crc(char sym)
if (!(TT.outlen & 32767)) {
xwrite(TT.outfd, TT.outbuf, 32768);
- if (TT.crcfunc) TT.crcfunc(0, 32768);
+ TT.crcfunc(0, 32768);
}
}
@@ -180,11 +188,6 @@ static unsigned huff_and_puff(struct bitbuf *bb, struct huff *huff)
// Decompress deflated data from bitbuf to filehandle.
static void inflate(struct bitbuf *bb)
{
- struct huff *disthuff, *lithuff, *fixdisthuff = (struct huff *)(toybuf+2048),
- *fixlithuff = (struct huff *)(toybuf+2560);
-
-// len2huff(
-
TT.crc = ~0;
// repeat until spanked
for (;;) {
@@ -195,17 +198,17 @@ static void inflate(struct bitbuf *bb)
if (type == 3) error_exit("bad type");
- // no compression?
+ // Uncompressed block?
if (!type) {
int len, nlen;
// Align to byte, read length
- bitbuf_skip(bb, bb->bitpos & 7);
+ bitbuf_skip(bb, (8-bb->bitpos)&7);
len = bitbuf_get(bb, 16);
nlen = bitbuf_get(bb, 16);
if (len != (0xffff & ~nlen)) error_exit("bad len");
- // Dump output data
+ // Dump literal output data
while (len) {
int pos = bb->bitpos >> 3, bblen = bb->len - pos;
char *p = bb->buf+pos;
@@ -220,10 +223,11 @@ static void inflate(struct bitbuf *bb)
// Compressed block
} else {
+ struct huff *disthuff, *lithuff;
// Dynamic huffman codes?
if (type == 2) {
- struct huff *h2 = (struct huff *)(toybuf+512);
+ struct huff *h2 = ((struct huff *)toybuf)+1;
int i, litlen, distlen, hufflen;
char *hufflen_order = "\x10\x11\x12\0\x08\x07\x09\x06\x0a\x05\x0b"
"\x04\x0c\x03\x0d\x02\x0e\x01\x0f", *bits;
@@ -258,19 +262,23 @@ static void inflate(struct bitbuf *bb)
}
if (i > litlen+distlen) error_exit("bad tree");
- len2huff(lithuff = (struct huff *)(toybuf+1024), bits, litlen);
- len2huff(disthuff = (struct huff *)(toybuf+1536), bits+litlen, distlen);
+ len2huff(lithuff = ((struct huff *)toybuf)+2, bits, litlen);
+ len2huff(disthuff = ((struct huff *)toybuf)+3, bits+litlen, distlen);
// Static huffman codes
} else {
- lithuff = fixlithuff;
- disthuff = fixdisthuff;
-error_exit("todo static huffman init");
+ lithuff = TT.fixlithuff;
+ disthuff = TT.fixdisthuff;
}
+
+ // Use huffman tables to decode block of compressed symbols
for (;;) {
int sym = huff_and_puff(bb, lithuff);
+ // Literal?
if (sym < 256) outbuf_crc(sym);
+
+ // Copy range?
else if (sym > 256) {
int len, dist;
@@ -281,10 +289,13 @@ error_exit("todo static huffman init");
sym = TT.outlen & 32767;
while (len--) outbuf_crc(TT.outbuf[(TT.outlen-dist) & 32767]);
+
+ // End of block
} else break;
}
}
+ // Was that the last block?
if (final) break;
}
if (TT.outlen & 32767) xwrite(TT.outfd, TT.outbuf, TT.outlen & 32767);
@@ -317,6 +328,12 @@ static void init_deflate(void)
if (i>3 && !(i&1)) n++;
TT.distbits[i] = n;
}
+
+ // Init fixed huffman tables
+ for (i=0; i<288; i++) toybuf[i] = 8 + (i>143) - ((i>255)<<1) + (i>279);
+ len2huff(TT.fixlithuff = ((struct huff *)toybuf)+4, toybuf, 288);
+ memset(toybuf, 5, 30);
+ len2huff(TT.fixdisthuff = ((struct huff *)toybuf)+5, toybuf, 30);
}
// Return true/false whether we consumed a gzip header.
@@ -338,7 +355,7 @@ static int is_gzip(struct bitbuf *bb)
return 1;
}
-static void do_gzip(int fd, char *name)
+static void do_zcat(int fd, char *name)
{
struct bitbuf *bb = bitbuf_init(fd, sizeof(toybuf));
@@ -355,7 +372,16 @@ static void do_gzip(int fd, char *name)
void compress_main(void)
{
+ zcat_main();
+}
+
+//#define CLEANUP_compress
+//#define FOR_zcat
+//#include "generated/flags.h"
+
+void zcat_main(void)
+{
init_deflate();
- loopfiles(toys.optargs, do_gzip);
+ loopfiles(toys.optargs, do_zcat);
}