diff options
-rw-r--r-- | toys/pending/compress.c | 78 |
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); } |