diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | INSTALL | 11 | ||||
-rw-r--r-- | Makefile.in | 21 | ||||
-rw-r--r-- | NEWS | 14 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | carg_parser.c | 2 | ||||
-rwxr-xr-x | configure | 37 | ||||
-rw-r--r-- | decoder.c | 103 | ||||
-rw-r--r-- | decoder.h | 168 | ||||
-rw-r--r-- | doc/lunzip.1 | 4 | ||||
-rw-r--r-- | lunzip.h | 87 | ||||
-rw-r--r-- | main.c | 161 | ||||
-rwxr-xr-x | testsuite/check.sh | 21 | ||||
-rw-r--r-- | testsuite/test.txt.lz | bin | 0 -> 11518 bytes | |||
-rw-r--r-- | testsuite/test_sync.lz | bin | 11658 -> 0 bytes | |||
-rw-r--r-- | testsuite/test_v0.lz | bin | 11540 -> 0 bytes | |||
-rw-r--r-- | testsuite/test_v1.lz | bin | 11548 -> 0 bytes |
17 files changed, 302 insertions, 339 deletions
@@ -1,3 +1,11 @@ +2013-02-18 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.2 released. + * Decompression time has been reduced by 12%. + * Makefile.in: Added new target 'install-as-lzip'. + * Makefile.in: Added new target 'install-bin'. + * main.c: Use 'setmode' instead of '_setmode' on Windows and OS/2. + 2012-02-26 Antonio Diaz Diaz <ant_diaz@teleline.es> * Version 1.1 released. @@ -15,7 +23,7 @@ * Created from the decompression code of clzip 1.1. -Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This file is a collection of facts, and thus it is not copyrightable, but just in case, you have unlimited permission to copy, distribute and @@ -1,7 +1,7 @@ Requirements ------------ You will need a C compiler. -I use gcc 4.3.5 and 3.3.6, but the code should compile with any +I use gcc 4.7.2 and 3.3.6, but the code should compile with any standards compliant compiler. Gcc is available at http://gcc.gnu.org. @@ -32,6 +32,13 @@ the main archive. 5. Type 'make install' to install the program and any data files and documentation. + You can install only the program, the info manual or the man page + typing 'make install-bin', 'make install-info' or 'make install-man' + respectively. + +5a. Type 'make install-as-lzip' to install the program and any data + files and documentation, and link the program to the name 'lzip'. + Another way ----------- @@ -50,7 +57,7 @@ After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/Makefile.in b/Makefile.in index cde25d8..378f626 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,8 +9,8 @@ SHELL = /bin/sh objs = carg_parser.o decoder.o main.o -.PHONY : all install install-info install-man install-strip \ - uninstall uninstall-info uninstall-man \ +.PHONY : all install install-bin install-info install-man install-strip \ + install-as-lzip uninstall uninstall-bin uninstall-info uninstall-man \ doc info man check dist clean distclean all : $(progname) @@ -52,14 +52,16 @@ Makefile : $(VPATH)/configure $(VPATH)/Makefile.in check : all @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) -install : all install-man +install : install-bin install-man + +install-bin : all if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi $(INSTALL_PROGRAM) ./$(progname) "$(DESTDIR)$(bindir)/$(progname)" install-info : if [ ! -d "$(DESTDIR)$(infodir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(infodir)" ; fi $(INSTALL_DATA) $(VPATH)/doc/$(pkgname).info "$(DESTDIR)$(infodir)/$(pkgname).info" - -install-info --info-dir="$(DESTDIR)$(infodir)" $(DESTDIR)$(infodir)/$(pkgname).info + -install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$(pkgname).info" install-man : if [ ! -d "$(DESTDIR)$(mandir)/man1" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" ; fi @@ -68,7 +70,13 @@ install-man : install-strip : all $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install -uninstall : uninstall-man +install-as-lzip : install + -rm -f "$(DESTDIR)$(bindir)/lzip" + cd "$(DESTDIR)$(bindir)" && ln -s $(progname) lzip + +uninstall : uninstall-bin uninstall-man + +uninstall-bin : -rm -f "$(DESTDIR)$(bindir)/$(progname)" uninstall-info : @@ -92,8 +100,7 @@ dist : doc $(DISTNAME)/doc/$(progname).1 \ $(DISTNAME)/testsuite/check.sh \ $(DISTNAME)/testsuite/test.txt \ - $(DISTNAME)/testsuite/test_sync.lz \ - $(DISTNAME)/testsuite/test_v[01].lz \ + $(DISTNAME)/testsuite/test.txt.lz \ $(DISTNAME)/*.h \ $(DISTNAME)/*.c rm -f $(DISTNAME) @@ -1,13 +1,7 @@ -Changes in version 1.1: +Changes in version 1.2: -Print only one status line for each multimember file when only one "-v" -is specified. +Decompression time has been reduced by 12%. -Inability to change output file attributes has been downgraded from -error to warning. +The target "install-as-lzip" has been added to the Makefile. -Quote characters in messages have been changed as advised by GNU Coding -Standards. - -Configure option "--datadir" has been renamed to "--datarootdir" to -follow GNU Standards. +The target "install-bin" has been added to the Makefile. @@ -35,7 +35,7 @@ few tens of KiB larger than the dictionary size used to compress that file. -Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/carg_parser.c b/carg_parser.c index 326bd41..973bb7e 100644 --- a/carg_parser.c +++ b/carg_parser.c @@ -88,7 +88,7 @@ static char parse_long_option( struct Arg_parser * const ap, const struct ap_Option options[], int * const argindp ) { - unsigned int len; + unsigned len; int index = -1; int i; char exact = 0, ambig = 0; @@ -1,6 +1,6 @@ #! /bin/sh # configure script for Lunzip - Decompressor for lzip files -# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -8,7 +8,7 @@ args= no_create= pkgname=lunzip -pkgversion=1.1 +pkgversion=1.2 progname=lunzip srctrigger=lunzip.h @@ -22,11 +22,19 @@ bindir='$(exec_prefix)/bin' datarootdir='$(prefix)/share' infodir='$(datarootdir)/info' mandir='$(datarootdir)/man' -CC= +CC=gcc CPPFLAGS= CFLAGS='-Wall -W -O2' LDFLAGS= +# checking whether we are using GNU C. +if [ ! -x /bin/gcc ] && + [ ! -x /usr/bin/gcc ] && + [ ! -x /usr/local/bin/gcc ] ; then + CC=cc + CFLAGS='-W -O2' +fi + # Loop over all args while [ -n "$1" ] ; do @@ -91,14 +99,14 @@ done srcdirtext= if [ -z "${srcdir}" ] ; then srcdirtext="or . or .." ; srcdir=. - if [ ! -r ${srcdir}/${srctrigger} ] ; then srcdir=.. ; fi - if [ ! -r ${srcdir}/${srctrigger} ] ; then + if [ ! -r "${srcdir}/${srctrigger}" ] ; then srcdir=.. ; fi + if [ ! -r "${srcdir}/${srctrigger}" ] ; then ## the sed command below emulates the dirname command srcdir=`echo $0 | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` fi fi -if [ ! -r ${srcdir}/${srctrigger} ] ; then +if [ ! -r "${srcdir}/${srctrigger}" ] ; then exec 1>&2 echo echo "configure: Can't find sources in ${srcdir} ${srcdirtext}" @@ -107,18 +115,7 @@ if [ ! -r ${srcdir}/${srctrigger} ] ; then fi # Set srcdir to . if that's what it is. -if [ "`pwd`" = "`cd ${srcdir} ; pwd`" ] ; then srcdir=. ; fi - -# checking whether we are using GNU C. -if [ -z "${CC}" ] ; then # Let the user override the test. - if [ -x /bin/gcc ] || - [ -x /usr/bin/gcc ] || - [ -x /usr/local/bin/gcc ] ; then - CC="gcc" - else - CC="cc" - fi -fi +if [ "`pwd`" = "`cd "${srcdir}" ; pwd`" ] ; then srcdir=. ; fi echo if [ -z "${no_create}" ] ; then @@ -152,7 +149,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Lunzip - Decompressor for lzip files -# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. # This file was generated automatically by configure. Do not edit. # # This Makefile is free software: you have unlimited permission @@ -173,6 +170,6 @@ CPPFLAGS = ${CPPFLAGS} CFLAGS = ${CFLAGS} LDFLAGS = ${LDFLAGS} EOF -cat ${srcdir}/Makefile.in >> Makefile +cat "${srcdir}/Makefile.in" >> Makefile echo "OK. Now you can run make." @@ -1,5 +1,5 @@ /* Lunzip - Decompressor for lzip files - Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,23 +32,40 @@ CRC32 crc32; +void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) + { + if( pp->verbosity >= 0 ) + { + if( pp->first_post ) + { + int i, len; + pp->first_post = false; + fprintf( stderr, " %s: ", pp->name ); + len = pp->longest_name - strlen( pp->name ); + for( i = 0; i < len; ++i ) fprintf( stderr, " " ); + if( !msg ) fflush( stderr ); + } + if( msg ) fprintf( stderr, "%s.\n", msg ); + } + } + + /* Returns the number of bytes really read. If (returned value < size) and (errno == 0), means EOF was reached. */ static int readblock( const int fd, uint8_t * const buf, const int size ) { int rest = size; - while( true ) + errno = 0; + while( rest > 0 ) { - int n; - errno = 0; - if( rest <= 0 ) break; - n = read( fd, buf + size - rest, rest ); + const int n = read( fd, buf + size - rest, rest ); if( n > 0 ) rest -= n; - else if( n == 0 ) break; + else if( n == 0 ) break; /* EOF */ else if( errno != EINTR && errno != EAGAIN ) break; + errno = 0; } - return ( rest > 0 ) ? size - rest : size; + return size - rest; } @@ -58,16 +75,15 @@ static int readblock( const int fd, uint8_t * const buf, const int size ) static int writeblock( const int fd, const uint8_t * const buf, const int size ) { int rest = size; - while( true ) + errno = 0; + while( rest > 0 ) { - int n; - errno = 0; - if( rest <= 0 ) break; - n = write( fd, buf + size - rest, rest ); + const int n = write( fd, buf + size - rest, rest ); if( n > 0 ) rest -= n; else if( n < 0 && errno != EINTR && errno != EAGAIN ) break; + errno = 0; } - return ( rest > 0 ) ? size - rest : size; + return size - rest; } @@ -107,7 +123,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, { File_trailer trailer; const int trailer_size = Ft_versioned_size( decoder->member_version ); - const long long member_size = + const unsigned long long member_size = Rd_member_position( decoder->range_decoder ) + trailer_size; bool error = false; @@ -136,8 +152,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, { Pp_show_msg( pp, 0 ); fprintf( stderr, "CRC mismatch; trailer says %08X, data CRC is %08X.\n", - (unsigned int)Ft_get_data_crc( trailer ), - (unsigned int)LZd_crc( decoder ) ); + Ft_get_data_crc( trailer ), LZd_crc( decoder ) ); } } if( Ft_get_data_size( trailer ) != LZd_data_position( decoder ) ) @@ -146,7 +161,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, if( pp->verbosity >= 0 ) { Pp_show_msg( pp, 0 ); - fprintf( stderr, "Data size mismatch; trailer says %lld, data size is %lld (0x%llX).\n", + fprintf( stderr, "Data size mismatch; trailer says %llu, data size is %llu (0x%llX).\n", Ft_get_data_size( trailer ), LZd_data_position( decoder ), LZd_data_position( decoder ) ); } } @@ -156,7 +171,7 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, if( pp->verbosity >= 0 ) { Pp_show_msg( pp, 0 ); - fprintf( stderr, "Member size mismatch; trailer says %lld, member size is %lld (0x%llX).\n", + fprintf( stderr, "Member size mismatch; trailer says %llu, member size is %llu (0x%llX).\n", Ft_get_member_size( trailer ), member_size, member_size ); } } @@ -166,8 +181,8 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, ( 8.0 * member_size ) / LZd_data_position( decoder ), 100.0 * ( 1.0 - ( (double)member_size / LZd_data_position( decoder ) ) ) ); if( !error && pp->verbosity >= 4 ) - fprintf( stderr, "data CRC %08X, data size %9lld, member size %8lld. ", - (unsigned int)Ft_get_data_crc( trailer ), + fprintf( stderr, "data CRC %08X, data size %9llu, member size %8llu. ", + Ft_get_data_crc( trailer ), Ft_get_data_size( trailer ), Ft_get_member_size( trailer ) ); return !error; } @@ -178,10 +193,11 @@ bool LZd_verify_trailer( struct LZ_decoder * const decoder, int LZd_decode_member( struct LZ_decoder * const decoder, struct Pretty_print * const pp ) { - unsigned int rep0 = 0; /* rep[0-3] latest four distances */ - unsigned int rep1 = 0; /* used for efficient coding of */ - unsigned int rep2 = 0; /* repeated distances */ - unsigned int rep3 = 0; + unsigned rep0 = 0; /* rep[0-3] latest four distances */ + unsigned rep1 = 0; /* used for efficient coding of */ + unsigned rep2 = 0; /* repeated distances */ + unsigned rep3 = 0; + State state = 0; Rd_load( decoder->range_decoder ); @@ -192,12 +208,17 @@ int LZd_decode_member( struct LZ_decoder * const decoder, { const uint8_t prev_byte = LZd_get_prev_byte( decoder ); if( St_is_char( state ) ) - LZd_put_byte( decoder, Lid_decode( &decoder->literal_decoder, - decoder->range_decoder, prev_byte ) ); + { + state -= ( state < 4 ) ? state : 3; + LZd_put_byte( decoder, Rd_decode_tree( decoder->range_decoder, + decoder->bm_literal[get_lit_state(prev_byte)], 8 ) ); + } else - LZd_put_byte( decoder, Lid_decode_matched( &decoder->literal_decoder, - decoder->range_decoder, prev_byte, LZd_get_byte( decoder, rep0 ) ) ); - St_set_char( &state ); + { + state -= ( state < 10 ) ? 3 : 6; + LZd_put_byte( decoder, Rd_decode_matched( decoder->range_decoder, + decoder->bm_literal[get_lit_state(prev_byte)], LZd_get_byte( decoder, rep0 ) ) ); + } } else { @@ -207,7 +228,7 @@ int LZd_decode_member( struct LZ_decoder * const decoder, len = 0; if( Rd_decode_bit( decoder->range_decoder, &decoder->bm_rep0[state] ) == 1 ) { - unsigned int distance; + unsigned distance; if( Rd_decode_bit( decoder->range_decoder, &decoder->bm_rep1[state] ) == 0 ) distance = rep1; else @@ -223,31 +244,33 @@ int LZd_decode_member( struct LZ_decoder * const decoder, else { if( Rd_decode_bit( decoder->range_decoder, &decoder->bm_len[state][pos_state] ) == 0 ) - { St_set_short_rep( &state ); len = 1; } + { state = St_set_short_rep( state ); len = 1; } } if( len == 0 ) { - St_set_rep( &state ); + state = St_set_rep( state ); len = min_match_len + Led_decode( &decoder->rep_match_len_decoder, decoder->range_decoder, pos_state ); } } else { int dis_slot; - const unsigned int rep0_saved = rep0; + const unsigned rep0_saved = rep0; len = min_match_len + Led_decode( &decoder->len_decoder, decoder->range_decoder, pos_state ); - dis_slot = Rd_decode_tree( decoder->range_decoder, decoder->bm_dis_slot[get_dis_state(len)], dis_slot_bits ); + dis_slot = Rd_decode_tree6( decoder->range_decoder, decoder->bm_dis_slot[get_dis_state(len)] ); if( dis_slot < start_dis_model ) rep0 = dis_slot; else { const int direct_bits = ( dis_slot >> 1 ) - 1; rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits; if( dis_slot < end_dis_model ) - rep0 += Rd_decode_tree_reversed( decoder->range_decoder, decoder->bm_dis + rep0 - dis_slot, direct_bits ); + rep0 += Rd_decode_tree_reversed( decoder->range_decoder, + decoder->bm_dis + rep0 - dis_slot - 1, + direct_bits ); else { rep0 += Rd_decode( decoder->range_decoder, direct_bits - dis_align_bits ) << dis_align_bits; - rep0 += Rd_decode_tree_reversed( decoder->range_decoder, decoder->bm_align, dis_align_bits ); + rep0 += Rd_decode_tree_reversed4( decoder->range_decoder, decoder->bm_align ); if( rep0 == 0xFFFFFFFFU ) /* Marker found */ { rep0 = rep0_saved; @@ -271,9 +294,9 @@ int LZd_decode_member( struct LZ_decoder * const decoder, } } rep3 = rep2; rep2 = rep1; rep1 = rep0_saved; - St_set_match( &state ); - if( rep0 >= (unsigned int)decoder->dictionary_size || - ( rep0 >= (unsigned int)decoder->pos && !decoder->partial_data_pos ) ) + state = St_set_match( state ); + if( rep0 >= (unsigned)decoder->dictionary_size || + ( rep0 >= (unsigned)decoder->pos && !decoder->partial_data_pos ) ) { LZd_flush_data( decoder ); return 1; } } LZd_copy_block( decoder, rep0, len ); @@ -1,5 +1,5 @@ /* Lunzip - Decompressor for lzip files - Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ enum { rd_buffer_size = 16384 }; struct Range_decoder { - long long partial_member_pos; + unsigned long long partial_member_pos; uint8_t * buffer; /* input buffer */ int pos; /* current pos in buffer */ int stream_pos; /* when reached, a new block must be read */ @@ -51,7 +51,8 @@ static inline void Rd_free( struct Range_decoder * const rdec ) static inline bool Rd_finished( struct Range_decoder * const rdec ) { return rdec->pos >= rdec->stream_pos && !Rd_read_block( rdec ); } -static inline long long Rd_member_position( const struct Range_decoder * const rdec ) +static inline unsigned long long +Rd_member_position( const struct Range_decoder * const rdec ) { return rdec->partial_member_pos + rdec->pos; } static inline void Rd_reset_member_position( struct Range_decoder * const rdec ) @@ -59,7 +60,7 @@ static inline void Rd_reset_member_position( struct Range_decoder * const rdec ) static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec ) { - if( Rd_finished( rdec ) ) return 0x55; /* make code != 0 */ + if( Rd_finished( rdec ) ) return 0xAA; /* make code != 0 */ return rdec->buffer[rdec->pos++]; } @@ -74,16 +75,16 @@ static inline int Rd_read_data( struct Range_decoder * const rdec, rdec->pos += rd; rest -= rd; } - return ( rest > 0 ) ? size - rest : size; + return size - rest; } static inline void Rd_load( struct Range_decoder * const rdec ) { int i; rdec->code = 0; - rdec->range = 0xFFFFFFFFU; for( i = 0; i < 5; ++i ) rdec->code = (rdec->code << 8) | Rd_get_byte( rdec ); + rdec->range = 0xFFFFFFFFU; } static inline void Rd_normalize( struct Range_decoder * const rdec ) @@ -102,20 +103,15 @@ static inline int Rd_decode( struct Range_decoder * const rdec, int i; for( i = num_bits; i > 0; --i ) { - symbol <<= 1; - if( rdec->range <= 0x00FFFFFFU ) - { - rdec->range <<= 7; - rdec->code = (rdec->code << 8) | Rd_get_byte( rdec ); - if( rdec->code >= rdec->range ) - { rdec->code -= rdec->range; symbol |= 1; } - } - else - { - rdec->range >>= 1; - if( rdec->code >= rdec->range ) - { rdec->code -= rdec->range; symbol |= 1; } - } + uint32_t mask; + Rd_normalize( rdec ); + rdec->range >>= 1; +/* symbol <<= 1; */ +/* if( rdec->code >= rdec->range ) { rdec->code -= rdec->range; symbol |= 1; } */ + mask = 0U - (rdec->code < rdec->range); + rdec->code -= rdec->range; + rdec->code += rdec->range & mask; + symbol = (symbol << 1) + (mask + 1); } return symbol; } @@ -151,6 +147,19 @@ static inline int Rd_decode_tree( struct Range_decoder * const rdec, return model - (1 << num_bits); } +static inline int Rd_decode_tree6( struct Range_decoder * const rdec, + Bit_model bm[] ) + { + int model = 1; + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + model = ( model << 1 ) | Rd_decode_bit( rdec, &bm[model] ); + return model - (1 << 6); + } + static inline int Rd_decode_tree_reversed( struct Range_decoder * const rdec, Bit_model bm[], const int num_bits ) { @@ -159,32 +168,49 @@ static inline int Rd_decode_tree_reversed( struct Range_decoder * const rdec, int i; for( i = 0; i < num_bits; ++i ) { - const int bit = Rd_decode_bit( rdec, &bm[model] ); + const bool bit = Rd_decode_bit( rdec, &bm[model] ); model <<= 1; - if( bit ) { model |= 1; symbol |= (1 << i); } + if( bit ) { ++model; symbol |= (1 << i); } } return symbol; } +static inline int Rd_decode_tree_reversed4( struct Range_decoder * const rdec, + Bit_model bm[] ) + { + int model = 1; + int symbol = 0; + int bit = Rd_decode_bit( rdec, &bm[model] ); + model = (model << 1) + bit; symbol |= bit; + bit = Rd_decode_bit( rdec, &bm[model] ); + model = (model << 1) + bit; symbol |= (bit << 1); + bit = Rd_decode_bit( rdec, &bm[model] ); + model = (model << 1) + bit; symbol |= (bit << 2); + if( Rd_decode_bit( rdec, &bm[model] ) ) symbol |= 8; + return symbol; + } + static inline int Rd_decode_matched( struct Range_decoder * const rdec, - Bit_model bm[], const int match_byte ) + Bit_model bm[], int match_byte ) { Bit_model * const bm1 = bm + 0x100; int symbol = 1; int i; for( i = 7; i >= 0; --i ) { - const int match_bit = ( match_byte >> i ) & 1; - const int bit = Rd_decode_bit( rdec, &bm1[(match_bit<<8)+symbol] ); + int match_bit, bit; + match_byte <<= 1; + match_bit = match_byte & 0x100; + bit = Rd_decode_bit( rdec, &bm1[match_bit+symbol] ); symbol = ( symbol << 1 ) | bit; - if( match_bit != bit ) + if( match_bit != bit << 8 ) { - while( --i >= 0 ) + while( symbol < 0x100 ) symbol = ( symbol << 1 ) | Rd_decode_bit( rdec, &bm[symbol] ); break; } } - return symbol & 0xFF; + return symbol - 0x100; } @@ -199,17 +225,11 @@ struct Len_decoder static inline void Led_init( struct Len_decoder * const len_decoder ) { - int i, j; Bm_init( &len_decoder->choice1 ); Bm_init( &len_decoder->choice2 ); - for( i = 0; i < pos_states; ++i ) - for( j = 0; j < len_low_symbols; ++j ) - Bm_init( &len_decoder->bm_low[i][j] ); - for( i = 0; i < pos_states; ++i ) - for( j = 0; j < len_mid_symbols; ++j ) - Bm_init( &len_decoder->bm_mid[i][j] ); - for( i = 0; i < len_high_symbols; ++i ) - Bm_init( &len_decoder->bm_high[i] ); + Bm_array_init( len_decoder->bm_low[0], pos_states * len_low_symbols ); + Bm_array_init( len_decoder->bm_mid[0], pos_states * len_mid_symbols ); + Bm_array_init( len_decoder->bm_high, len_high_symbols ); } static inline int Led_decode( struct Len_decoder * const len_decoder, @@ -226,37 +246,9 @@ static inline int Led_decode( struct Len_decoder * const len_decoder, } -struct Literal_decoder - { - Bit_model bm_literal[1<<literal_context_bits][0x300]; - }; - -static inline void Lid_init( struct Literal_decoder * const lidec ) - { - int i, j; - for( i = 0; i < 1<<literal_context_bits; ++i ) - for( j = 0; j < 0x300; ++j ) - Bm_init( &lidec->bm_literal[i][j] ); - } - -static inline int Lid_state( const uint8_t prev_byte ) - { return ( prev_byte >> ( 8 - literal_context_bits ) ); } - -static inline uint8_t Lid_decode( struct Literal_decoder * const lidec, - struct Range_decoder * const rdec, - const uint8_t prev_byte ) - { return Rd_decode_tree( rdec, lidec->bm_literal[Lid_state(prev_byte)], 8 ); } - -static inline uint8_t Lid_decode_matched( struct Literal_decoder * const lidec, - struct Range_decoder * const rdec, - const uint8_t prev_byte, - const uint8_t match_byte ) - { return Rd_decode_matched( rdec, lidec->bm_literal[Lid_state(prev_byte)], match_byte ); } - - struct LZ_decoder { - long long partial_data_pos; + unsigned long long partial_data_pos; int dictionary_size; int buffer_size; uint8_t * buffer; /* output buffer */ @@ -266,6 +258,7 @@ struct LZ_decoder int outfd; /* output file descriptor */ int member_version; + Bit_model bm_literal[1<<literal_context_bits][0x300]; Bit_model bm_match[states][pos_states]; Bit_model bm_rep[states]; Bit_model bm_rep0[states]; @@ -273,13 +266,12 @@ struct LZ_decoder Bit_model bm_rep2[states]; Bit_model bm_len[states][pos_states]; Bit_model bm_dis_slot[max_dis_states][1<<dis_slot_bits]; - Bit_model bm_dis[modeled_distances-end_dis_model+1]; + Bit_model bm_dis[modeled_distances-end_dis_model]; Bit_model bm_align[dis_align_size]; struct Range_decoder * range_decoder; struct Len_decoder len_decoder; struct Len_decoder rep_match_len_decoder; - struct Literal_decoder literal_decoder; }; void LZd_flush_data( struct LZ_decoder * const decoder ); @@ -315,12 +307,12 @@ static inline void LZd_copy_block( struct LZ_decoder * const decoder, int i = decoder->pos - distance - 1; if( i < 0 ) i += decoder->buffer_size; if( len < decoder->buffer_size - max( decoder->pos, i ) && - len <= abs( decoder->pos - i ) ) + len <= abs( decoder->pos - i ) ) /* no wrap, no overlap */ { memcpy( decoder->buffer + decoder->pos, decoder->buffer + i, len ); decoder->pos += len; } - else for( ; len > 0 ; --len ) + else for( ; len > 0; --len ) { decoder->buffer[decoder->pos] = decoder->buffer[i]; if( ++decoder->pos >= decoder->buffer_size ) LZd_flush_data( decoder ); @@ -332,7 +324,6 @@ static inline bool LZd_init( struct LZ_decoder * const decoder, const File_header header, struct Range_decoder * const rdec, const int ofd ) { - int i, j; decoder->partial_data_pos = 0; decoder->dictionary_size = Fh_get_dictionary_size( header ); decoder->buffer_size = max( 65536, decoder->dictionary_size ); @@ -344,30 +335,20 @@ static inline bool LZd_init( struct LZ_decoder * const decoder, decoder->outfd = ofd; decoder->member_version = Fh_version( header ); - for( i = 0; i < states; ++i ) - { - for( j = 0; j < pos_states; ++j ) - { - Bm_init( &decoder->bm_match[i][j] ); - Bm_init( &decoder->bm_len[i][j] ); - } - Bm_init( &decoder->bm_rep[i] ); - Bm_init( &decoder->bm_rep0[i] ); - Bm_init( &decoder->bm_rep1[i] ); - Bm_init( &decoder->bm_rep2[i] ); - } - for( i = 0; i < max_dis_states; ++i ) - for( j = 0; j < 1<<dis_slot_bits; ++j ) - Bm_init( &decoder->bm_dis_slot[i][j] ); - for( i = 0; i < modeled_distances-end_dis_model+1; ++i ) - Bm_init( &decoder->bm_dis[i] ); - for( i = 0; i < dis_align_size; ++i ) - Bm_init( &decoder->bm_align[i] ); + Bm_array_init( decoder->bm_literal[0], (1 << literal_context_bits) * 0x300 ); + Bm_array_init( decoder->bm_match[0], states * pos_states ); + Bm_array_init( decoder->bm_rep, states ); + Bm_array_init( decoder->bm_rep0, states ); + Bm_array_init( decoder->bm_rep1, states ); + Bm_array_init( decoder->bm_rep2, states ); + Bm_array_init( decoder->bm_len[0], states * pos_states ); + Bm_array_init( decoder->bm_dis_slot[0], max_dis_states * (1 << dis_slot_bits) ); + Bm_array_init( decoder->bm_dis, modeled_distances - end_dis_model ); + Bm_array_init( decoder->bm_align, dis_align_size ); decoder->range_decoder = rdec; Led_init( &decoder->len_decoder ); Led_init( &decoder->rep_match_len_decoder ); - Lid_init( &decoder->literal_decoder ); decoder->buffer[decoder->buffer_size-1] = 0; /* prev_byte of first_byte */ return true; } @@ -375,10 +356,11 @@ static inline bool LZd_init( struct LZ_decoder * const decoder, static inline void LZd_free( struct LZ_decoder * const decoder ) { free( decoder->buffer ); } -static inline uint32_t LZd_crc( const struct LZ_decoder * const decoder ) +static inline unsigned LZd_crc( const struct LZ_decoder * const decoder ) { return decoder->crc ^ 0xFFFFFFFFU; } -static inline long long LZd_data_position( const struct LZ_decoder * const decoder ) +static inline unsigned long long +LZd_data_position( const struct LZ_decoder * const decoder ) { return decoder->partial_data_pos + decoder->pos; } int LZd_decode_member( struct LZ_decoder * const decoder, diff --git a/doc/lunzip.1 b/doc/lunzip.1 index ac3625d..820aa8b 100644 --- a/doc/lunzip.1 +++ b/doc/lunzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. -.TH LUNZIP "1" "February 2012" "Lunzip 1.1" "User Commands" +.TH LUNZIP "1" "February 2013" "Lunzip 1.2" "User Commands" .SH NAME Lunzip \- small decompressor for lzip files .SH SYNOPSIS @@ -46,7 +46,7 @@ Report bugs to lzip\-bug@nongnu.org .br Lunzip home page: http://www.nongnu.org/lzip/lunzip.html .SH COPYRIGHT -Copyright \(co 2012 Antonio Diaz Diaz. +Copyright \(co 2013 Antonio Diaz Diaz. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> .br This is free software: you are free to change and redistribute it. @@ -1,5 +1,5 @@ /* Lunzip - Decompressor for lzip files - Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,39 +22,26 @@ #define min(x,y) ((x) <= (y) ? (x) : (y)) #endif -typedef unsigned char State; +typedef int State; enum { states = 12 }; static inline bool St_is_char( const State st ) { return st < 7; } -static inline void St_set_char( State * const st ) +static inline State St_set_char( const State st ) { - static const unsigned char next[states] = - { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; - *st = next[*st]; + static const State next[states] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; + return next[st]; } -static inline void St_set_match( State * const st ) - { - static const unsigned char next[states] = - { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; - *st = next[*st]; - } +static inline State St_set_match( const State st ) + { return ( ( st < 7 ) ? 7 : 10 ); } -static inline void St_set_rep( State * const st ) - { - static const unsigned char next[states] = - { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 }; - *st = next[*st]; - } +static inline State St_set_rep( const State st ) + { return ( ( st < 7 ) ? 8 : 11 ); } -static inline void St_set_short_rep( State * const st ) - { - static const unsigned char next[states] = - { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 }; - *st = next[*st]; - } +static inline State St_set_short_rep( const State st ) + { return ( ( st < 7 ) ? 9 : 11 ); } enum { @@ -88,23 +75,25 @@ enum { max_dis_states = 4 }; -static inline int get_dis_state( int len ) - { - len -= min_match_len; - if( len >= max_dis_states ) len = max_dis_states - 1; - return len; - } +static inline int get_dis_state( const int len ) + { return min( len - min_match_len, max_dis_states - 1 ); } + +static inline int get_lit_state( const uint8_t prev_byte ) + { return ( prev_byte >> ( 8 - literal_context_bits ) ); } enum { bit_model_move_bits = 5, bit_model_total_bits = 11, bit_model_total = 1 << bit_model_total_bits }; -typedef unsigned int Bit_model; +typedef int Bit_model; static inline void Bm_init( Bit_model * const probability ) { *probability = bit_model_total / 2; } +static inline void Bm_array_init( Bit_model * const p, const int size ) + { int i = 0; while( i < size ) p[i++] = bit_model_total / 2; } + struct Pretty_print { @@ -121,7 +110,7 @@ void Pp_init( struct Pretty_print * const pp, const char * const filenames[], static inline void Pp_set_name( struct Pretty_print * const pp, const char * const filename ) { - if( filename && filename[0] && strcmp( filename, "-" ) ) + if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) pp->name = filename; else pp->name = pp->stdin_name; pp->first_post = true; @@ -136,12 +125,12 @@ typedef uint32_t CRC32[256]; /* Table of CRCs of all 8-bit messages. */ extern CRC32 crc32; -static inline void CRC32_init() +static inline void CRC32_init( void ) { - unsigned int n; + unsigned n; for( n = 0; n < 256; ++n ) { - unsigned int c = n; + unsigned c = n; int k; for( k = 0; k < 8; ++k ) { if( c & 1 ) c = 0xEDB88320U ^ ( c >> 1 ); else c >>= 1; } @@ -151,6 +140,7 @@ static inline void CRC32_init() static inline void CRC32_update_byte( uint32_t * crc, const uint8_t byte ) { *crc = crc32[(*crc^byte)&0xFF] ^ ( *crc >> 8 ); } + static inline void CRC32_update_buf( uint32_t * crc, const uint8_t * const buffer, const int size ) { @@ -160,16 +150,15 @@ static inline void CRC32_update_buf( uint32_t * crc, const uint8_t * const buffe } -static inline int real_bits( const unsigned int value ) +static inline int real_bits( unsigned value ) { - int bits = 0, i = 1; - unsigned int mask = 1; - for( ; mask > 0; ++i, mask <<= 1 ) if( value & mask ) bits = i; + int bits = 0; + while( value > 0 ) { value >>= 1; ++bits; } return bits; } -static const uint8_t magic_string[4] = { 'L', 'Z', 'I', 'P' }; +static const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */ typedef uint8_t File_header[6]; /* 0-3 magic bytes */ /* 4 version */ @@ -226,43 +215,43 @@ enum { Ft_size = 20 }; static inline int Ft_versioned_size( const int version ) { return ( ( version >= 1 ) ? 20 : 12 ); } -static inline uint32_t Ft_get_data_crc( const File_trailer data ) +static inline unsigned Ft_get_data_crc( const File_trailer data ) { - uint32_t tmp = 0; + unsigned tmp = 0; int i; for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_data_crc( File_trailer data, uint32_t crc ) +static inline void Ft_set_data_crc( File_trailer data, unsigned crc ) { int i; for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } -static inline long long Ft_get_data_size( const File_trailer data ) +static inline unsigned long long Ft_get_data_size( const File_trailer data ) { - long long tmp = 0; + unsigned long long tmp = 0; int i; for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_data_size( File_trailer data, long long sz ) +static inline void Ft_set_data_size( File_trailer data, unsigned long long sz ) { int i; for( i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } -static inline long long Ft_get_member_size( const File_trailer data ) +static inline unsigned long long Ft_get_member_size( const File_trailer data ) { - long long tmp = 0; + unsigned long long tmp = 0; int i; for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_member_size( File_trailer data, long long sz ) +static inline void Ft_set_member_size( File_trailer data, unsigned long long sz ) { int i; for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } @@ -1,5 +1,5 @@ /* Lunzip - Decompressor for lzip files - Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,12 +58,10 @@ #error "Environments where CHAR_BIT != 8 are not supported." #endif -long long int llabs( long long int number ); - const char * const Program_name = "Lunzip"; const char * const program_name = "lunzip"; -const char * const program_year = "2012"; +const char * const program_year = "2013"; const char * invocation_name = 0; #ifdef O_BINARY @@ -86,21 +84,7 @@ mode_t outfd_mode = S_IRUSR | S_IWUSR; bool delete_output_on_interrupt = false; -/* assure at least a minimum size for buffer 'buf' */ -static void * resize_buffer( void * buf, const int min_size ) - { - if( buf ) buf = realloc( buf, min_size ); - else buf = malloc( min_size ); - if( !buf ) - { - show_error( "Not enough memory.", 0, false ); - cleanup_and_fail( 1 ); - } - return buf; - } - - -static void show_help() +static void show_help( void ) { printf( "%s - Decompressor for lzip files.\n", Program_name ); printf( "\nUsage: %s [options] [files]\n", invocation_name ); @@ -122,7 +106,7 @@ static void show_help() } -static void show_version() +static void show_version( void ) { printf( "%s %s\n", Program_name, PROGVERSION ); printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); @@ -132,21 +116,35 @@ static void show_version() } -static const char * format_num( long long num ) +void show_header( const File_header header ) { const char * const prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - enum { buf_size = 16, factor = 1024 }; - static char buf[buf_size]; - const char *p = ""; + enum { factor = 1024 }; + const char * p = ""; + const char * np = " "; + unsigned num = Fh_get_dictionary_size( header ), i; bool exact = ( num % factor == 0 ); - int i; - for( i = 0; i < 8 && ( llabs( num ) > 9999 || - ( exact && llabs( num ) >= factor ) ); ++i ) - { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; } - snprintf( buf, buf_size, "%lld %s", num, p ); - return buf; + for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) + { num /= factor; if( num % factor != 0 ) exact = false; + p = prefix[i]; np = ""; } + fprintf( stderr, "version %d, dictionary size %s%4u %sB. ", + Fh_version( header ), np, num, p ); + } + + +static int extension_index( const char * const name ) + { + int i; + for( i = 0; known_extensions[i].from; ++i ) + { + const char * const ext = known_extensions[i].from; + if( strlen( name ) > strlen( ext ) && + strncmp( name + strlen( name ) - strlen( ext ), ext, strlen( ext ) ) == 0 ) + return i; + } + return -1; } @@ -183,23 +181,22 @@ static int open_instream( const char * const name, } -static int extension_index( const char * const name ) +/* assure at least a minimum size for buffer 'buf' */ +static void * resize_buffer( void * buf, const int min_size ) { - int i; - for( i = 0; known_extensions[i].from; ++i ) + if( buf ) buf = realloc( buf, min_size ); + else buf = malloc( min_size ); + if( !buf ) { - const char * const ext = known_extensions[i].from; - if( strlen( name ) > strlen( ext ) && - strncmp( name + strlen( name ) - strlen( ext ), ext, strlen( ext ) ) == 0 ) - return i; + show_error( "Not enough memory.", 0, false ); + cleanup_and_fail( 1 ); } - return -1; + return buf; } -static void set_d_outname( const char * const name ) +static void set_d_outname( const char * const name, const int i ) { - const int i = extension_index( name ); if( i >= 0 ) { const char * const from = known_extensions[i].from; @@ -286,9 +283,9 @@ static void close_and_set_permissions( const struct stat * const in_statsp ) static int decompress( const int infd, struct Pretty_print * const pp, const bool testing ) { - long long partial_file_pos = 0; + unsigned long long partial_file_pos = 0; struct Range_decoder rdec; - int retval = 0, result; + int retval = 0; bool first_member; if( !Rd_init( &rdec, infd ) ) { @@ -296,13 +293,14 @@ static int decompress( const int infd, struct Pretty_print * const pp, cleanup_and_fail( 1 ); } - for( first_member = true; ; first_member = false, Pp_reset( pp ) ) + for( first_member = true; ; first_member = false ) { + int result; File_header header; struct LZ_decoder decoder; Rd_reset_member_position( &rdec ); Rd_read_data( &rdec, header, Fh_size ); - if( Rd_finished( &rdec ) ) /* End Of File */ + if( Rd_finished( &rdec ) ) /* End Of File */ { if( first_member ) { Pp_show_msg( pp, "Error reading member header" ); retval = 1; } @@ -328,13 +326,7 @@ static int decompress( const int infd, struct Pretty_print * const pp, retval = 2; break; } if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) - { - Pp_show_msg( pp, 0 ); - if( verbosity >= 2 ) - fprintf( stderr, "version %d, dictionary size %7sB. ", - Fh_version( header ), - format_num( Fh_get_dictionary_size( header ) ) ); - } + { Pp_show_msg( pp, 0 ); if( verbosity >= 2 ) show_header( header ); } if( !LZd_init( &decoder, header, &rdec, outfd ) ) { @@ -350,16 +342,16 @@ static int decompress( const int infd, struct Pretty_print * const pp, { Pp_show_msg( pp, 0 ); if( result == 2 ) - fprintf( stderr, "File ends unexpectedly at pos %lld\n", + fprintf( stderr, "File ends unexpectedly at pos %llu\n", partial_file_pos ); else - fprintf( stderr, "Decoder error at pos %lld\n", partial_file_pos ); + fprintf( stderr, "Decoder error at pos %llu\n", partial_file_pos ); } retval = 2; break; } if( verbosity >= 2 ) { if( testing ) fprintf( stderr, "ok\n" ); - else fprintf( stderr, "done\n" ); } + else fprintf( stderr, "done\n" ); Pp_reset( pp ); } } Rd_free( &rdec ); if( verbosity == 1 && retval == 0 ) @@ -371,13 +363,13 @@ static int decompress( const int infd, struct Pretty_print * const pp, void signal_handler( int sig ) { - sig = 0; /* keep compiler happy */ + if( sig ) {} /* keep compiler happy */ show_error( "Control-C or similar caught, quitting.", 0, false ); cleanup_and_fail( 1 ); } -static void set_signals() +static void set_signals( void ) { signal( SIGHUP, signal_handler ); signal( SIGINT, signal_handler ); @@ -388,7 +380,7 @@ static void set_signals() void Pp_init( struct Pretty_print * const pp, const char * const filenames[], const int num_filenames, const int v ) { - unsigned int stdin_name_len; + unsigned stdin_name_len; int i; pp->name = 0; pp->stdin_name = "(stdin)"; @@ -400,31 +392,13 @@ void Pp_init( struct Pretty_print * const pp, const char * const filenames[], for( i = 0; i < num_filenames; ++i ) { const char * const s = filenames[i]; - const int len = ( !strcmp( s, "-" ) ? stdin_name_len : strlen( s ) ); + const int len = ( (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ) ); if( len > pp->longest_name ) pp->longest_name = len; } if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; } -void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) - { - if( verbosity >= 0 ) - { - if( pp->first_post ) - { - int i, len; - pp->first_post = false; - fprintf( stderr, " %s: ", pp->name ); - len = pp->longest_name - strlen( pp->name ); - for( i = 0; i < len; ++i ) fprintf( stderr, " " ); - if( !msg ) fflush( stderr ); - } - if( msg ) fprintf( stderr, "%s.\n", msg ); - } - } - - void show_error( const char * const msg, const int errcode, const bool help ) { if( verbosity >= 0 ) @@ -435,7 +409,7 @@ void show_error( const char * const msg, const int errcode, const bool help ) if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) ); fprintf( stderr, "\n" ); } - if( help && invocation_name && invocation_name[0] ) + if( help ) fprintf( stderr, "Try '%s --help' for more information.\n", invocation_name ); } @@ -495,7 +469,7 @@ int main( const int argc, const char * const argv[] ) { const int code = ap_code( &parser, argind ); const char * const arg = ap_argument( &parser, argind ); - if( !code ) break; /* no more options */ + if( !code ) break; /* no more options */ switch( code ) { case 'c': to_stdout = true; break; @@ -513,28 +487,23 @@ int main( const int argc, const char * const argv[] ) } /* end process options */ #if defined(__MSVCRT__) || defined(__OS2__) - _fsetmode( stdin, "b" ); - _fsetmode( stdout, "b" ); + setmode( STDIN_FILENO, O_BINARY ); + setmode( STDOUT_FILENO, O_BINARY ); #endif if( testing ) outfd = -1; - for( ; argind < ap_arguments( &parser ); ++argind ) - { - if( strcmp( ap_argument( &parser, argind ), "-" ) ) - filenames_given = true; - ++num_filenames; - filenames = resize_buffer( filenames, num_filenames * sizeof (char *) ); - filenames[num_filenames-1] = ap_argument( &parser, argind ); - } + num_filenames = max( 1, ap_arguments( &parser ) - argind ); + filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); + filenames[0] = "-"; - if( num_filenames == 0 ) + for( i = 0; argind + i < ap_arguments( &parser ); ++i ) { - ++num_filenames; - filenames = resize_buffer( filenames, sizeof (char *) ); - filenames[num_filenames-1] = "-"; + filenames[i] = ap_argument( &parser, argind + i ); + if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true; } + if( !to_stdout && !testing && ( filenames_given || default_output_filename[0] ) ) set_signals(); @@ -549,7 +518,7 @@ int main( const int argc, const char * const argv[] ) const struct stat * in_statsp; output_filename[0] = 0; - if( !filenames[i][0] || !strcmp( filenames[i], "-" ) ) + if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) { input_filename = ""; infd = STDIN_FILENO; @@ -565,7 +534,7 @@ int main( const int argc, const char * const argv[] ) outfd_mode = all_rw; if( !open_outstream( force ) ) { - if( outfd == -1 && retval < 1 ) retval = 1; + if( retval < 1 ) retval = 1; close( infd ); infd = -1; continue; } @@ -582,11 +551,11 @@ int main( const int argc, const char * const argv[] ) if( to_stdout ) outfd = STDOUT_FILENO; else { - set_d_outname( input_filename ); + set_d_outname( input_filename, extension_index( input_filename ) ); outfd_mode = usr_rw; if( !open_outstream( force ) ) { - if( outfd == -1 && retval < 1 ) retval = 1; + if( retval < 1 ) retval = 1; close( infd ); infd = -1; continue; } diff --git a/testsuite/check.sh b/testsuite/check.sh index fea9d0a..8408109 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Lunzip - Decompressor for lzip files -# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -23,27 +23,14 @@ cd "${objdir}"/tmp cat "${testdir}"/test.txt > in || framework_failure cat in in > in2 || framework_failure -cat "${testdir}"/test_v1.lz > in.lz || framework_failure +cat "${testdir}"/test.txt.lz > in.lz || framework_failure cat in.lz in.lz > in2.lz || framework_failure fail=0 printf "testing lunzip-%s..." "$2" -"${LZIP}" -t "${testdir}"/test_v0.lz || fail=1 -printf . -"${LZIP}" -cd "${testdir}"/test_v0.lz > copy || fail=1 -cmp in copy || fail=1 -printf . - -"${LZIP}" -t "${testdir}"/test_v1.lz || fail=1 -printf . -"${LZIP}" -cd "${testdir}"/test_v1.lz > copy || fail=1 -cmp in copy || fail=1 -printf . - -"${LZIP}" -t "${testdir}"/test_sync.lz || fail=1 -printf . -"${LZIP}" -cd "${testdir}"/test_sync.lz > copy || fail=1 +"${LZIP}" -t "${testdir}"/test.txt.lz || fail=1 +"${LZIP}" -cd "${testdir}"/test.txt.lz > copy || fail=1 cmp in copy || fail=1 printf . diff --git a/testsuite/test.txt.lz b/testsuite/test.txt.lz Binary files differnew file mode 100644 index 0000000..4db881a --- /dev/null +++ b/testsuite/test.txt.lz diff --git a/testsuite/test_sync.lz b/testsuite/test_sync.lz Binary files differdeleted file mode 100644 index 419fa97..0000000 --- a/testsuite/test_sync.lz +++ /dev/null diff --git a/testsuite/test_v0.lz b/testsuite/test_v0.lz Binary files differdeleted file mode 100644 index a09b1e8..0000000 --- a/testsuite/test_v0.lz +++ /dev/null diff --git a/testsuite/test_v1.lz b/testsuite/test_v1.lz Binary files differdeleted file mode 100644 index f1c79eb..0000000 --- a/testsuite/test_v1.lz +++ /dev/null |