From 737720be9b1044b501bc5a86a9835b4b9fdeadd3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 7 Nov 2015 15:28:27 +0100 Subject: Merging upstream version 1.3. Signed-off-by: Daniel Baumann --- Alloc.c | 4 +- ChangeLog | 11 ++- INSTALL | 26 ++--- Makefile.in | 20 ++-- NEWS | 9 +- README | 8 +- carg_parser.c | 276 ---------------------------------------------------- carg_parser.h | 85 ---------------- configure | 8 +- doc/pdlzip.1 | 12 ++- main.c | 84 +++++++++------- pdarg_parser.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pdarg_parser.h | 85 ++++++++++++++++ pdlzip.h | 2 +- testsuite/check.sh | 9 +- 15 files changed, 471 insertions(+), 445 deletions(-) delete mode 100644 carg_parser.c delete mode 100644 carg_parser.h create mode 100644 pdarg_parser.c create mode 100644 pdarg_parser.h diff --git a/Alloc.c b/Alloc.c index f424e99..09a54c3 100644 --- a/Alloc.c +++ b/Alloc.c @@ -1,7 +1,5 @@ /* Alloc.c -- Memory allocation functions -2008-09-24 -Igor Pavlov -Public domain */ +2008-09-24 : Igor Pavlov : Public domain */ #define _FILE_OFFSET_BITS 64 diff --git a/ChangeLog b/ChangeLog index 286b061..1f19301 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-01-03 Antonio Diaz Diaz + + * Version 1.3 released. + * Small change in '--help' output and man page. + * Changed quote characters in messages as advised by GNU Standards. + * main.c: Set stdin/stdout in binary mode on OS2. + 2011-01-05 Antonio Diaz Diaz * Version 1.2 released. @@ -11,7 +18,7 @@ reduced to extend range of use towards gzip. Lower numbers now compress less but faster. (-1 now takes 43% less time for only 20% larger compressed size). - * Code has been converted to `C89 + long long' from C99. + * Code has been converted to 'C89 + long long' from C99. 2010-04-05 Antonio Diaz Diaz @@ -20,7 +27,7 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010, 2011 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012 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 diff --git a/INSTALL b/INSTALL index a9ca16e..ad5a756 100644 --- a/INSTALL +++ b/INSTALL @@ -18,7 +18,7 @@ This creates the directory ./pdlzip[version] containing the source from the main archive. 2. Change to pdlzip directory and run configure. - (Try `configure --help' for usage instructions). + (Try 'configure --help' for usage instructions). cd pdlzip[version] ./configure @@ -27,30 +27,30 @@ the main archive. make -4. Optionally, type `make check' to run the tests that come with pdlzip. +4. Optionally, type 'make check' to run the tests that come with pdlzip. -5. Type `make install' to install the program and any data files and +5. Type 'make install' to install the program and any data files and documentation. Another way ----------- You can also compile pdlzip into a separate directory. To do this, you -must use a version of `make' that supports the `VPATH' variable, such -as GNU `make'. `cd' to the directory where you want the object files -and executables to go and run the `configure' script. `configure' -automatically checks for the source code in `.', in `..' and in the -directory that `configure' is in. - -`configure' recognizes the option `--srcdir=DIR' to control where to -look for the sources. Usually `configure' can determine that directory +must use a version of 'make' that supports the 'VPATH' variable, such +as GNU 'make'. 'cd' to the directory where you want the object files +and executables to go and run the 'configure' script. 'configure' +automatically checks for the source code in '.', in '..' and in the +directory that 'configure' is in. + +'configure' recognizes the option '--srcdir=DIR' to control where to +look for the sources. Usually 'configure' can determine that directory automatically. -After running `configure', you can run `make' and `make install' as +After running 'configure', you can run 'make' and 'make install' as explained above. -Copyright (C) 2010, 2011 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012 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 be09e82..c20e0f2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh objs = 7zFile.o 7zStream.o Alloc.o LzFind.o LzmaDec.o LzmaEnc.o \ - carg_parser.o main.o + pdarg_parser.o main.o .PHONY : all install install-info install-man install-strip \ @@ -28,15 +28,15 @@ main.o : main.c %.o : %.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -$(objs) : Makefile -7zFile.o : 7zFile.h Types.h -7zStream.o : Types.h -Alloc.o : Alloc.h -LzFind.o : LzFind.h LzHash.h Types.h pdlzip.h -LzmaDec.o : LzmaDec.h Types.h -LzmaEnc.o : LzFind.h LzmaEnc.h Types.h pdlzip.h -carg_parser.o : carg_parser.h -main.o : 7zFile.h Alloc.h LzmaDec.h LzmaEnc.h carg_parser.h pdlzip.h +$(objs) : Makefile +7zFile.o : 7zFile.h Types.h +7zStream.o : Types.h +Alloc.o : Alloc.h +LzFind.o : LzFind.h LzHash.h Types.h pdlzip.h +LzmaDec.o : LzmaDec.h Types.h +LzmaEnc.o : LzFind.h LzmaEnc.h Types.h pdlzip.h +pdarg_parser.o : pdarg_parser.h +main.o : 7zFile.h Alloc.h LzmaDec.h LzmaEnc.h pdarg_parser.h pdlzip.h doc : man diff --git a/NEWS b/NEWS index 814471c..13a6da4 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ -Changes in version 1.2: +Changes in version 1.3: -Code cleanup. Minor fixes. +A small change has been made in the "--help" output and man page. + +Quote characters in messages have been changed as advised by GNU Coding +Standards. + +Standard input and standard output are now set in binary mode on OS2. diff --git a/README b/README index f3679e9..7841983 100644 --- a/README +++ b/README @@ -8,15 +8,15 @@ and data archiving. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. -Pdlzip is a public domain version of the lzip data compressor, intended -for those who can't distribute GPL licensed Free Software. Pdlzip is -written in C. +Pdlzip is a "public domain" version of the lzip data compressor, +intended for those who can't distribute GPL licensed Free Software. +Pdlzip is written in C. Pdlzip uses public domain compression code from the LZMA SDK written by Igor Pavlov. -Copyright (C) 2010, 2011 Antonio Diaz Diaz. +Copyright (C) 2010, 2011, 2012 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 deleted file mode 100644 index f797b75..0000000 --- a/carg_parser.c +++ /dev/null @@ -1,276 +0,0 @@ -/* Pdlzip - A data compressor based on the LZMA algorithm - Copyright (C) 2010 Antonio Diaz Diaz. - - This program is free software: you have unlimited permission - to copy, distribute and modify it. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#include -#include - -#include "carg_parser.h" - - -/* assure at least a minimum size for buffer `buf' */ -static void * ap_resize_buffer( void * buf, const int min_size ) - { - if( buf ) buf = realloc( buf, min_size ); - else buf = malloc( min_size ); - return buf; - } - - -static char push_back_record( struct Arg_parser * const ap, - const int code, const char * const argument ) - { - const int len = strlen( argument ); - struct ap_Record *p; - void * tmp = ap_resize_buffer( ap->data, ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); - if( !tmp ) return 0; - ap->data = (struct ap_Record *)tmp; - p = &(ap->data[ap->data_size]); - p->code = code; - p->argument = 0; - tmp = ap_resize_buffer( p->argument, len + 1 ); - if( !tmp ) return 0; - p->argument = (char *)tmp; - strncpy( p->argument, argument, len + 1 ); - ++ap->data_size; - return 1; - } - - -static char add_error( struct Arg_parser * const ap, const char * const msg ) - { - const int len = strlen( msg ); - void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); - if( !tmp ) return 0; - ap->error = (char *)tmp; - strncpy( ap->error + ap->error_size, msg, len + 1 ); - ap->error_size += len; - return 1; - } - - -static void free_data( struct Arg_parser * const ap ) - { - int i; - for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); - if( ap->data ) { free( ap->data ); ap->data = 0; } - ap->data_size = 0; - } - - -static char parse_long_option( struct Arg_parser * const ap, - const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) - { - unsigned int len; - int index = -1; - int i; - char exact = 0, ambig = 0; - - for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ; - - /* Test all long options for either exact match or abbreviated matches. */ - for( i = 0; options[i].code != 0; ++i ) - if( options[i].name && !strncmp( options[i].name, &opt[2], len ) ) - { - if( strlen( options[i].name ) == len ) /* Exact match found */ - { index = i; exact = 1; break; } - else if( index < 0 ) index = i; /* First nonexact match found */ - else if( options[index].code != options[i].code || - options[index].has_arg != options[i].has_arg ) - ambig = 1; /* Second or later nonexact match found */ - } - - if( ambig && !exact ) - { - add_error( ap, "option `" ); add_error( ap, opt ); - add_error( ap, "' is ambiguous" ); - return 1; - } - - if( index < 0 ) /* nothing found */ - { - add_error( ap, "unrecognized option `" ); add_error( ap, opt ); - add_error( ap, "'" ); - return 1; - } - - ++*argindp; - - if( opt[len+2] ) /* `--=' syntax */ - { - if( options[index].has_arg == ap_no ) - { - add_error( ap, "option `--" ); add_error( ap, options[index].name ); - add_error( ap, "' doesn't allow an argument" ); - return 1; - } - if( options[index].has_arg == ap_yes && !opt[len+3] ) - { - add_error( ap, "option `--" ); add_error( ap, options[index].name ); - add_error( ap, "' requires an argument" ); - return 1; - } - return push_back_record( ap, options[index].code, &opt[len+3] ); - } - - if( options[index].has_arg == ap_yes ) - { - if( !arg || !arg[0] ) - { - add_error( ap, "option `--" ); add_error( ap, options[index].name ); - add_error( ap, "' requires an argument" ); - return 1; - } - ++*argindp; - return push_back_record( ap, options[index].code, arg ); - } - - return push_back_record( ap, options[index].code, "" ); - } - - -static char parse_short_option( struct Arg_parser * const ap, - const char * const opt, const char * const arg, - const struct ap_Option options[], - int * const argindp ) - { - int cind = 1; /* character index in opt */ - - while( cind > 0 ) - { - int index = -1; - int i; - const unsigned char code = opt[cind]; - char code_str[2]; - code_str[0] = code; code_str[1] = 0; - - if( code != 0 ) - for( i = 0; options[i].code; ++i ) - if( code == options[i].code ) - { index = i; break; } - - if( index < 0 ) - { - add_error( ap, "invalid option -- " ); add_error( ap, code_str ); - return 1; - } - - if( opt[++cind] == 0 ) { ++*argindp; cind = 0; } /* opt finished */ - - if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) - { - if( !push_back_record( ap, code, &opt[cind] ) ) return 0; - ++*argindp; cind = 0; - } - else if( options[index].has_arg == ap_yes ) - { - if( !arg || !arg[0] ) - { - add_error( ap, "option requires an argument -- " ); - add_error( ap, code_str ); - return 1; - } - ++*argindp; cind = 0; - if( !push_back_record( ap, code, arg ) ) return 0; - } - else if( !push_back_record( ap, code, "" ) ) return 0; - } - return 1; - } - - -char ap_init( struct Arg_parser * const ap, - const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ) - { - const char ** non_options = 0; /* skipped non-options */ - int non_options_size = 0; /* number of skipped non-options */ - int argind = 1; /* index in argv */ - int i; - - ap->data = 0; - ap->error = 0; - ap->data_size = 0; - ap->error_size = 0; - if( argc < 2 || !argv || !options ) return 1; - - while( argind < argc ) - { - const unsigned char ch1 = argv[argind][0]; - const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 ); - - if( ch1 == '-' && ch2 ) /* we found an option */ - { - const char * const opt = argv[argind]; - const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0; - if( ch2 == '-' ) - { - if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ - else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; - } - else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; - if( ap->error ) break; - } - else - { - if( !in_order ) - { - void * tmp = ap_resize_buffer( non_options, - ( non_options_size + 1 ) * sizeof *non_options ); - if( !tmp ) return 0; - non_options = (const char **)tmp; - non_options[non_options_size++] = argv[argind++]; - } - else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; - } - } - if( ap->error ) free_data( ap ); - else - { - for( i = 0; i < non_options_size; ++i ) - if( !push_back_record( ap, 0, non_options[i] ) ) return 0; - while( argind < argc ) - if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; - } - if( non_options ) free( non_options ); - return 1; - } - - -void ap_free( struct Arg_parser * const ap ) - { - free_data( ap ); - if( ap->error ) { free( ap->error ); ap->error = 0; } - ap->error_size = 0; - } - - -const char * ap_error( const struct Arg_parser * const ap ) - { return ap->error; } - - -int ap_arguments( const struct Arg_parser * const ap ) - { return ap->data_size; } - - -int ap_code( const struct Arg_parser * const ap, const int i ) - { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; - else return 0; - } - - -const char * ap_argument( const struct Arg_parser * const ap, const int i ) - { - if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; - else return ""; - } diff --git a/carg_parser.h b/carg_parser.h deleted file mode 100644 index 2d5fd0f..0000000 --- a/carg_parser.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Pdlzip - A data compressor based on the LZMA algorithm - Copyright (C) 2010 Antonio Diaz Diaz. - - This program is free software: you have unlimited permission - to copy, distribute and modify it. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ - -/* Arg_parser reads the arguments in `argv' and creates a number of - option codes, option arguments and non-option arguments. - - In case of error, `ap_error' returns a non-null pointer to an error - message. - - `options' is an array of `struct ap_Option' terminated by an element - containing a code which is zero. A null name means a short-only - option. A code value outside the unsigned char range means a - long-only option. - - Arg_parser normally makes it appear as if all the option arguments - were specified before all the non-option arguments for the purposes - of parsing, even if the user of your program intermixed option and - non-option arguments. If you want the arguments in the exact order - the user typed them, call `ap_init' with `in_order' = true. - - The argument `--' terminates all options; any following arguments are - treated as non-option arguments, even if they begin with a hyphen. - - The syntax for optional option arguments is `-' - (without whitespace), or `--='. -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; - -struct ap_Option - { - int code; /* Short option letter or code ( code != 0 ) */ - const char * name; /* Long option name (maybe null) */ - enum ap_Has_arg has_arg; - }; - - -struct ap_Record - { - int code; - char * argument; - }; - - -struct Arg_parser - { - struct ap_Record * data; - char * error; - int data_size; - int error_size; - }; - - -char ap_init( struct Arg_parser * const ap, - const int argc, const char * const argv[], - const struct ap_Option options[], const char in_order ); - -void ap_free( struct Arg_parser * const ap ); - -const char * ap_error( const struct Arg_parser * const ap ); - - /* The number of arguments parsed (may be different from argc) */ -int ap_arguments( const struct Arg_parser * const ap ); - - /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. - Else ap_argument( i ) is the option's argument (or empty). */ -int ap_code( const struct Arg_parser * const ap, const int i ); - -const char * ap_argument( const struct Arg_parser * const ap, const int i ); - -#ifdef __cplusplus -} -#endif diff --git a/configure b/configure index 22353ed..889aff5 100755 --- a/configure +++ b/configure @@ -1,16 +1,14 @@ #! /bin/sh # configure script for Pdlzip - Data compressor based on the LZMA algorithm -# Copyright (C) 2010, 2011 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. -# -# Date of this version: 2011-01-05 args= no_create= pkgname=pdlzip -pkgversion=1.2 +pkgversion=1.3 progname=pdlzip srctrigger=pdlzip.h @@ -167,7 +165,7 @@ echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF # Makefile for Pdlzip - Data compressor based on the LZMA algorithm -# Copyright (C) 2010, 2011 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. # This file was generated automatically by configure. Do not edit. # # This Makefile is free software: you have unlimited permission diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 22b298d..153a618 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. -.TH PDLZIP "1" "January 2011" "Pdlzip 1.2" "User Commands" +.TH PDLZIP "1" "January 2012" "Pdlzip 1.3" "User Commands" .SH NAME Pdlzip \- reduces the size of files .SH SYNOPSIS @@ -22,13 +22,13 @@ send output to standard output \fB\-d\fR, \fB\-\-decompress\fR decompress .TP -\fB\-m\fR, \fB\-\-match\-length=\fR +\fB\-m\fR, \fB\-\-match\-length=\fR set match length limit in bytes [36] .TP \fB\-q\fR, \fB\-\-quiet\fR suppress all messages .TP -\fB\-s\fR, \fB\-\-dictionary\-size=\fR +\fB\-s\fR, \fB\-\-dictionary\-size=\fR set dictionary size limit in bytes [8MiB] .TP \fB\-t\fR, \fB\-\-test\fR @@ -50,12 +50,16 @@ If no file name is given, pdlzip compresses or decompresses from standard input to standard output. Numbers may be followed by a multiplier: k = kB = 10^3 = 1000, Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc... +The bidimensional parameter space of LZMA can't be mapped to a linear +scale optimal for all files. If your files are large, very repetitive, +etc, you may need to use the \fB\-\-match\-length\fR and \fB\-\-dictionary\-size\fR +options directly to achieve optimal performance. .SH "REPORTING BUGS" Report bugs to lzip\-bug@nongnu.org .br Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2011 Antonio Diaz Diaz. +Copyright \(co 2012 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. .br This is free software: you are free to change and redistribute it. diff --git a/main.c b/main.c index 3a75453..353a1d9 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ /* Pdlzip - Data compressor based on the LZMA algorithm 2009-08-14 : Igor Pavlov : Public domain - Copyright (C) 2010, 2011 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. This program is free software: you have unlimited permission to copy, distribute and modify it. @@ -19,8 +19,11 @@ #include #include #include +#if defined(__OS2__) +#include +#endif -#include "carg_parser.h" +#include "pdarg_parser.h" #include "pdlzip.h" #include "Alloc.h" #include "7zFile.h" @@ -50,7 +53,7 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree }; const char * const Program_name = "Pdlzip"; const char * const program_name = "pdlzip"; -const char * const program_year = "2011"; +const char * const program_year = "2012"; const char * invocation_name = 0; @@ -70,7 +73,7 @@ enum Mode { m_compress, m_decompress, m_test }; char * output_filename = 0; -/* assure at least a minimum size for buffer `buf' */ +/* assure at least a minimum size for buffer 'buf' */ inline void * resize_buffer( void * buf, const int min_size ) { if( buf ) buf = realloc( buf, min_size ); @@ -82,29 +85,33 @@ inline void * resize_buffer( void * buf, const int min_size ) static void show_help() { printf( "%s - A \"public domain\" version of the lzip data compressor\n", Program_name ); - printf( "also able to decompress legacy lzma-alone (.lzma) files.\n" ); - printf( "\nUsage: %s [options] [file]\n", invocation_name ); - printf( "\nOptions:\n" ); - printf( " -h, --help display this help and exit\n" ); - printf( " -V, --version output version information and exit\n" ); - printf( " -c, --stdout send output to standard output\n" ); - printf( " -d, --decompress decompress\n" ); -/* printf( " -f, --force overwrite existing output files\n" ); */ -/* printf( " -k, --keep keep (don't delete) input files\n" ); */ - printf( " -m, --match-length= set match length limit in bytes [36]\n" ); - printf( " -q, --quiet suppress all messages\n" ); - printf( " -s, --dictionary-size= set dictionary size limit in bytes [8MiB]\n" ); - printf( " -t, --test test compressed file integrity\n" ); - printf( " -v, --verbose be verbose (a 2nd -v gives more)\n" ); - printf( " -1 .. -9 set compression level [default 6]\n" ); - printf( " --fast alias for -1\n" ); - printf( " --best alias for -9\n" ); - printf( "If no file name is given, %s compresses or decompresses\n", program_name ); - printf( "from standard input to standard output.\n" ); - printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" ); - printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); - printf( "\nReport bugs to lzip-bug@nongnu.org\n" ); - printf( "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); + printf( "also able to decompress legacy lzma-alone (.lzma) files.\n" + "\nUsage: %s [options] [file]\n", invocation_name ); + printf( "\nOptions:\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n" + " -c, --stdout send output to standard output\n" + " -d, --decompress decompress\n" +/* " -f, --force overwrite existing output files\n" */ +/* " -k, --keep keep (don't delete) input files\n" */ + " -m, --match-length= set match length limit in bytes [36]\n" + " -q, --quiet suppress all messages\n" + " -s, --dictionary-size= set dictionary size limit in bytes [8MiB]\n" + " -t, --test test compressed file integrity\n" + " -v, --verbose be verbose (a 2nd -v gives more)\n" + " -1 .. -9 set compression level [default 6]\n" + " --fast alias for -1\n" + " --best alias for -9\n" + "If no file name is given, pdlzip compresses or decompresses\n" + "from standard input to standard output.\n" + "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" + "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" + "The bidimensional parameter space of LZMA can't be mapped to a linear\n" + "scale optimal for all files. If your files are large, very repetitive,\n" + "etc, you may need to use the --match-length and --dictionary-size\n" + "options directly to achieve optimal performance.\n" + "\nReport bugs to lzip-bug@nongnu.org\n" + "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); } @@ -112,9 +119,9 @@ static void show_version() { printf( "%s %s\n", Program_name, PROGVERSION ); printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); - printf( "Public Domain 2009 Igor Pavlov.\n" ); - printf( "This is free software: you are free to change and redistribute it.\n" ); - printf( "There is NO WARRANTY, to the extent permitted by law.\n" ); + printf( "Public Domain 2009 Igor Pavlov.\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n" ); } @@ -125,11 +132,12 @@ static const char * format_num( long long num ) enum { buf_size = 16, factor = 1024 }; static char buf[buf_size]; const char *p = ""; + bool exact = ( num % factor == 0 ); int i; for( i = 0; i < 8 && ( llabs( num ) > 9999 || - ( llabs( num ) >= factor && num % factor == 0 ) ); ++i ) - { num /= factor; p = prefix[i]; } + ( 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; } @@ -537,7 +545,7 @@ void show_error( const char * const msg, const int errcode, const bool help ) fprintf( stderr, "\n" ); } if( help && invocation_name && invocation_name[0] ) - fprintf( stderr, "Try `%s --help' for more information.\n", + fprintf( stderr, "Try '%s --help' for more information.\n", invocation_name ); } } @@ -593,8 +601,8 @@ static void set_d_outname( const char * const name ) output_filename = resize_buffer( output_filename, strlen( name ) + 4 + 1 ); strcpy( output_filename, name ); strcat( output_filename, ".out" ); - if( verbosity >= 0 ) - fprintf( stderr, "%s: can't guess original name for `%s' -- using `%s'.\n", + if( verbosity >= 1 ) + fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'.\n", program_name, name, output_filename ); } @@ -644,7 +652,6 @@ int main( const int argc, const char * const argv[] ) { 'b', "member-size", ap_yes }, { 'c', "stdout", ap_no }, { 'd', "decompress", ap_no }, - { 'e', "extreme", ap_no }, { 'f', "force", ap_no }, { 'h', "help", ap_no }, { 'k', "keep", ap_no }, @@ -699,6 +706,11 @@ int main( const int argc, const char * const argv[] ) } } /* end process options */ +#if defined(__OS2__) + _fsetmode( stdin, "b" ); + _fsetmode( stdout, "b" ); +#endif + if( ap_arguments( &parser ) > argind && strcmp( ap_argument( &parser, argind ), "-" ) ) input_filename = ap_argument( &parser, argind ); diff --git a/pdarg_parser.c b/pdarg_parser.c new file mode 100644 index 0000000..71dc5d0 --- /dev/null +++ b/pdarg_parser.c @@ -0,0 +1,277 @@ +/* Pdlzip - Data compressor based on the LZMA algorithm + Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + + This program is free software: you have unlimited permission + to copy, distribute and modify it. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include +#include + +#include "pdarg_parser.h" + + +/* assure at least a minimum size for buffer 'buf' */ +static void * ap_resize_buffer( void * buf, const int min_size ) + { + if( buf ) buf = realloc( buf, min_size ); + else buf = malloc( min_size ); + return buf; + } + + +static char push_back_record( struct Arg_parser * const ap, + const int code, const char * const argument ) + { + const int len = strlen( argument ); + struct ap_Record *p; + void * tmp = ap_resize_buffer( ap->data, + ( ap->data_size + 1 ) * sizeof (struct ap_Record) ); + if( !tmp ) return 0; + ap->data = (struct ap_Record *)tmp; + p = &(ap->data[ap->data_size]); + p->code = code; + p->argument = 0; + tmp = ap_resize_buffer( p->argument, len + 1 ); + if( !tmp ) return 0; + p->argument = (char *)tmp; + strncpy( p->argument, argument, len + 1 ); + ++ap->data_size; + return 1; + } + + +static char add_error( struct Arg_parser * const ap, const char * const msg ) + { + const int len = strlen( msg ); + void * tmp = ap_resize_buffer( ap->error, ap->error_size + len + 1 ); + if( !tmp ) return 0; + ap->error = (char *)tmp; + strncpy( ap->error + ap->error_size, msg, len + 1 ); + ap->error_size += len; + return 1; + } + + +static void free_data( struct Arg_parser * const ap ) + { + int i; + for( i = 0; i < ap->data_size; ++i ) free( ap->data[i].argument ); + if( ap->data ) { free( ap->data ); ap->data = 0; } + ap->data_size = 0; + } + + +static char parse_long_option( struct Arg_parser * const ap, + const char * const opt, const char * const arg, + const struct ap_Option options[], + int * const argindp ) + { + unsigned int len; + int index = -1; + int i; + char exact = 0, ambig = 0; + + for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ; + + /* Test all long options for either exact match or abbreviated matches. */ + for( i = 0; options[i].code != 0; ++i ) + if( options[i].name && !strncmp( options[i].name, &opt[2], len ) ) + { + if( strlen( options[i].name ) == len ) /* Exact match found */ + { index = i; exact = 1; break; } + else if( index < 0 ) index = i; /* First nonexact match found */ + else if( options[index].code != options[i].code || + options[index].has_arg != options[i].has_arg ) + ambig = 1; /* Second or later nonexact match found */ + } + + if( ambig && !exact ) + { + add_error( ap, "option '" ); add_error( ap, opt ); + add_error( ap, "' is ambiguous" ); + return 1; + } + + if( index < 0 ) /* nothing found */ + { + add_error( ap, "unrecognized option '" ); add_error( ap, opt ); + add_error( ap, "'" ); + return 1; + } + + ++*argindp; + + if( opt[len+2] ) /* '--=' syntax */ + { + if( options[index].has_arg == ap_no ) + { + add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "' doesn't allow an argument" ); + return 1; + } + if( options[index].has_arg == ap_yes && !opt[len+3] ) + { + add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "' requires an argument" ); + return 1; + } + return push_back_record( ap, options[index].code, &opt[len+3] ); + } + + if( options[index].has_arg == ap_yes ) + { + if( !arg || !arg[0] ) + { + add_error( ap, "option '--" ); add_error( ap, options[index].name ); + add_error( ap, "' requires an argument" ); + return 1; + } + ++*argindp; + return push_back_record( ap, options[index].code, arg ); + } + + return push_back_record( ap, options[index].code, "" ); + } + + +static char parse_short_option( struct Arg_parser * const ap, + const char * const opt, const char * const arg, + const struct ap_Option options[], + int * const argindp ) + { + int cind = 1; /* character index in opt */ + + while( cind > 0 ) + { + int index = -1; + int i; + const unsigned char code = opt[cind]; + char code_str[2]; + code_str[0] = code; code_str[1] = 0; + + if( code != 0 ) + for( i = 0; options[i].code; ++i ) + if( code == options[i].code ) + { index = i; break; } + + if( index < 0 ) + { + add_error( ap, "invalid option -- " ); add_error( ap, code_str ); + return 1; + } + + if( opt[++cind] == 0 ) { ++*argindp; cind = 0; } /* opt finished */ + + if( options[index].has_arg != ap_no && cind > 0 && opt[cind] ) + { + if( !push_back_record( ap, code, &opt[cind] ) ) return 0; + ++*argindp; cind = 0; + } + else if( options[index].has_arg == ap_yes ) + { + if( !arg || !arg[0] ) + { + add_error( ap, "option requires an argument -- " ); + add_error( ap, code_str ); + return 1; + } + ++*argindp; cind = 0; + if( !push_back_record( ap, code, arg ) ) return 0; + } + else if( !push_back_record( ap, code, "" ) ) return 0; + } + return 1; + } + + +char ap_init( struct Arg_parser * const ap, + const int argc, const char * const argv[], + const struct ap_Option options[], const char in_order ) + { + const char ** non_options = 0; /* skipped non-options */ + int non_options_size = 0; /* number of skipped non-options */ + int argind = 1; /* index in argv */ + int i; + + ap->data = 0; + ap->error = 0; + ap->data_size = 0; + ap->error_size = 0; + if( argc < 2 || !argv || !options ) return 1; + + while( argind < argc ) + { + const unsigned char ch1 = argv[argind][0]; + const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 ); + + if( ch1 == '-' && ch2 ) /* we found an option */ + { + const char * const opt = argv[argind]; + const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0; + if( ch2 == '-' ) + { + if( !argv[argind][2] ) { ++argind; break; } /* we found "--" */ + else if( !parse_long_option( ap, opt, arg, options, &argind ) ) return 0; + } + else if( !parse_short_option( ap, opt, arg, options, &argind ) ) return 0; + if( ap->error ) break; + } + else + { + if( !in_order ) + { + void * tmp = ap_resize_buffer( non_options, + ( non_options_size + 1 ) * sizeof *non_options ); + if( !tmp ) return 0; + non_options = (const char **)tmp; + non_options[non_options_size++] = argv[argind++]; + } + else if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; + } + } + if( ap->error ) free_data( ap ); + else + { + for( i = 0; i < non_options_size; ++i ) + if( !push_back_record( ap, 0, non_options[i] ) ) return 0; + while( argind < argc ) + if( !push_back_record( ap, 0, argv[argind++] ) ) return 0; + } + if( non_options ) free( non_options ); + return 1; + } + + +void ap_free( struct Arg_parser * const ap ) + { + free_data( ap ); + if( ap->error ) { free( ap->error ); ap->error = 0; } + ap->error_size = 0; + } + + +const char * ap_error( const struct Arg_parser * const ap ) + { return ap->error; } + + +int ap_arguments( const struct Arg_parser * const ap ) + { return ap->data_size; } + + +int ap_code( const struct Arg_parser * const ap, const int i ) + { + if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].code; + else return 0; + } + + +const char * ap_argument( const struct Arg_parser * const ap, const int i ) + { + if( i >= 0 && i < ap_arguments( ap ) ) return ap->data[i].argument; + else return ""; + } diff --git a/pdarg_parser.h b/pdarg_parser.h new file mode 100644 index 0000000..020c57c --- /dev/null +++ b/pdarg_parser.h @@ -0,0 +1,85 @@ +/* Pdlzip - Data compressor based on the LZMA algorithm + Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. + + This program is free software: you have unlimited permission + to copy, distribute and modify it. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +/* Arg_parser reads the arguments in 'argv' and creates a number of + option codes, option arguments and non-option arguments. + + In case of error, 'ap_error' returns a non-null pointer to an error + message. + + 'options' is an array of 'struct ap_Option' terminated by an element + containing a code which is zero. A null name means a short-only + option. A code value outside the unsigned char range means a + long-only option. + + Arg_parser normally makes it appear as if all the option arguments + were specified before all the non-option arguments for the purposes + of parsing, even if the user of your program intermixed option and + non-option arguments. If you want the arguments in the exact order + the user typed them, call 'ap_init' with 'in_order' = true. + + The argument '--' terminates all options; any following arguments are + treated as non-option arguments, even if they begin with a hyphen. + + The syntax for optional option arguments is '-' + (without whitespace), or '--='. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +enum ap_Has_arg { ap_no, ap_yes, ap_maybe }; + +struct ap_Option + { + int code; /* Short option letter or code ( code != 0 ) */ + const char * name; /* Long option name (maybe null) */ + enum ap_Has_arg has_arg; + }; + + +struct ap_Record + { + int code; + char * argument; + }; + + +struct Arg_parser + { + struct ap_Record * data; + char * error; + int data_size; + int error_size; + }; + + +char ap_init( struct Arg_parser * const ap, + const int argc, const char * const argv[], + const struct ap_Option options[], const char in_order ); + +void ap_free( struct Arg_parser * const ap ); + +const char * ap_error( const struct Arg_parser * const ap ); + + /* The number of arguments parsed (may be different from argc) */ +int ap_arguments( const struct Arg_parser * const ap ); + + /* If ap_code( i ) is 0, ap_argument( i ) is a non-option. + Else ap_argument( i ) is the option's argument (or empty). */ +int ap_code( const struct Arg_parser * const ap, const int i ); + +const char * ap_argument( const struct Arg_parser * const ap, const int i ); + +#ifdef __cplusplus +} +#endif diff --git a/pdlzip.h b/pdlzip.h index a54ef76..6229d7c 100644 --- a/pdlzip.h +++ b/pdlzip.h @@ -1,5 +1,5 @@ /* Pdlzip - Data compressor based on the LZMA algorithm - Copyright (C) 2010, 2011 Antonio Diaz Diaz. + Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. This program is free software: you have unlimited permission to copy, distribute and modify it. diff --git a/testsuite/check.sh b/testsuite/check.sh index 635a404..ea7a6cc 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh # check script for Pdlzip - Data compressor based on the LZMA algorithm -# Copyright (C) 2010, 2011 Antonio Diaz Diaz. +# Copyright (C) 2010, 2011, 2012 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -19,12 +19,13 @@ fi if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp -printf "testing pdlzip-%s..." "$2" cd "${objdir}"/tmp cat "${testdir}"/test.txt > in || framework_failure fail=0 +printf "testing pdlzip-%s..." "$2" + "${LZIP}" -t "${testdir}"/test.lz || fail=1 printf . "${LZIP}" -cd "${testdir}"/test.lz > copy || fail=1 @@ -61,8 +62,8 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8s16 9s16 ; do printf . done -"${LZIP}" -$i < in > anyothername || fail=1 -"${LZIP}" -dq anyothername || fail=1 +"${LZIP}" < in > anyothername || fail=1 +"${LZIP}" -d anyothername || fail=1 cmp in anyothername.out || fail=1 printf . -- cgit v1.2.3