📄 compress.c
字号:
/*@H************************ < COMPRESS utility> ****************************
* $@(#) compress.c,v 4.3d 90/01/18 03:00:00 don Release ^ *
* *
* compress : compress.c *
* Main and Operating System Independent support functions *
* *
* port by : Donald J. Gloistein *
* *
* Source, Documentation, Object Code: *
* released to Public Domain. This code is ported from compress v4.0 *
* release joe. *
*--------------------------- Module Description --------------------------*
* The compress program is compatible with the compression/decompression *
* used on the Unix systems compress programs. This is version 4 and *
* supports up to 16 bits compression. The porting retained the Unix *
* meanings of all options, added a couple for MsDos and modified the *
* file name conventions to make more sense. *
* *
*--------------------------- Implementation Notes --------------------------*
* *
* compiled with : compress.h compress.fns *
* linked with : compapi.obj compusi.obj *
* problems: *
* See notes in compress.h for defines needed. *
* It should work now with Xenix *
* *
* Check the signal() handler functions in your compiler *
* documentation. This code assumes ANSI SYS V compatible *
* header and return values. Change as appropriate for your *
* compiler and operating system. *
* *
* This source compiles properly with Microsoft C compiler *
* version 5.1. *
* *
* CAUTION: because the program is in modules, make sure you recompile *
* all modules if you change the header or a define in the *
* compress.c file *
* *
* Algorithm from "A Technique for High Performance Data Compression", *
* Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. *
* *
* Assumptions: *
* When filenames are given, replaces with the compressed version *
* (.Z suffix) only if the file decreases in size. *
* Algorithm: *
* Modified Lempel-Ziv method (LZW). Basically finds common *
* substrings and replaces them with a variable size code. This is *
* deterministic, and can be done on the fly. Thus, the decompression *
* procedure needs no input table, but tracks the way the table was built. *
* *
* *
*--------------------------- Author(s) -------------------------*
* Initials ---- Name --------------------------------- *
* DjG Donald J. Gloistein *
* Plus many others, see rev.hst file for full list *
* Dal Dale A. Schumacher (Sozobon C port) *
* LvR Lyle V. Rains, many thanks for improved implementation *
*************************************************************************@H*/
/*@R************************< Revision History >*****************************
* *
* version -- date -- init ---Notes---------------------- *
* 4.01 08-29-88 DjG first cut for 16 bit MsDos version *
* 09-04-88 DjG fixed unlink on zcat if interupted. *
* added msdos filename logic and functions *
* 4.10 10-27-88 DjG revised API with coding changes by LvR. *
* 4.10a 10-30-88 DjG cleaned up code and fixed bug in freeing ptr. *
* 4.10b 11-01-88 DjG cleaned up the logic for inpath/outpath *
* Changed the logic to finding the file name *
* Fixed the allocation bug in the api *
* Added some more portability macros *
* 4.10c 11-04-88 DjG Changed maxcode from global to static in api. *
* Supplied some library functions for those who *
* don't have them, changed dos usi to use the *
* strrpbrk(). Checked casts in api again. Compiles*
* without warnings at pick level 3. *
* 4.10d 11-25-88 DjG revised some memory allocation, put more in the *
* header file. Corrected some typos. *
* Changed prog_name() to force lower case *
* Corrected bug, no longer unlinks existing file *
* if not enough memory to compress or decompress *
* 12-06-88 DjG VERY minor changes for casts and header defines *
* 12-08-88 DjG Adjusted path separator check in main function *
* Amiga uses split seg because of compiler *
* 12-09-88 DjG Debugging done, all defaults now Unix compress *
* defaults, including unlinking input file and *
* acting as a filter. Must use -h option to get *
* help screen. *
* 4.10e 12-11-88 DjG Fixed more casts, prototypes and header file. *
* 4.10f 12-12-88 DjG Fixed unlinking open files on error. This fails *
* on shared or os/2 platforms. *
* 12-15-88 DjG Fixed SIGTYPE for function passed to signal *
* Fixed problems with Xenix 2.2.1 *
* 4.2 12-19-88 DjG Replaced adaptive reset as an option. *
* 4.3 12-26-88 DjG Fixed long file name bug, fixed bug with *
* compressdir. -B option added, same as -b option *
* 05-06-89 Dal Ported to Sozobon/Alcyon C for Atari ST. Also, *
* created get_one() for console prompting. *
* 05-08-89 Dal Ported to Minix-ST *
* 4.3a 05-29-89 DjG Combined source code changes and now compiles *
* on Minix. *
* 4.3b 08-20-89 DjG Changed the version() to simplify it. Changed *
* the order of testing for linked files *
* 10-02-89 DjG Changed the double negative #ifndef NDEBUG *
* to a more logical coding. *
* 4.3c 12-25-89 DjG Fixed pointer bug in error message code *
* 01-06-90 LvR Fixed signed expansion on 68000 cpu's *
* 4.3d 01-18-90 LvR Fixed problem with token[] overrunning on some *
* files with large amounts of repeating characters*
*************************************************************************@R*/
#include <stdio.h>
#define MAIN /* header has defining instances of globals */
#include "compress.h" /* contains the rest of the include file declarations */
#define ARGVAL() (*++(*argv) || (--argc && *++argv))
char suffix[] = SUFFIX ; /* only used in this file */
void main( argc, argv )
register int argc; char **argv;
{
char **filelist, **fileptr,*temp;
char response;
struct stat statbuf;
#ifndef NOSIGNAL
if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
/* ANSI/SYS V compatible */
/* the following test checks for error on setting signals */
/* check your documentation on the value to test */
/* if your signal.h doesn't support the return, it is */
/* essentially a no-op test */
if (bgnd_flag == SIG_ERR){
exit_stat = SIGNAL_ERROR;
check_error();
}
if( (signal(SIGINT,onintr) == SIG_ERR)
|| (signal(SIGSEGV,oops) == SIG_ERR)) {/* check your compiler docs. */
exit_stat = SIGNAL_ERROR;
check_error();
}
}
#endif
/* set up array for files to be converted */
#ifdef ALLOC
filelist = fileptr = (char **)(alloc(argc * sizeof(char *)));
#else
filelist = fileptr = (char **)(malloc(argc * sizeof(char *)));
#endif
*filelist = NULL;
/* gets name, compares and sets defaults */
prog_name = get_program_name(argv[0]);
/* now parse command line and get file list */
for (argc--, argv++; argc > 0; argc--, argv++) {
if (**argv == '-') { /* A flag argument */
while (*++(*argv)) { /* Process all flags in this arg */
switch (**argv) {
#ifdef DEBUG
case 'D':
debug = TRUE;
keep_error = TRUE;
break;
case 'V':
verbose = TRUE;
version();
break;
#else
case 'V':
version();
break;
#endif /*DEBUG */
case 'v':
quiet = FALSE;
break;
case 'd':
do_decomp = TRUE;
break;
case 'f':
force = overwrite = TRUE;
break;
case 'n':
nomagic = TRUE;
break;
case 'C':
block_compress = FALSE;
break;
case 'b': case 'B':
if (!ARGVAL()) {
fprintf(stderr, "Missing maxbits\n");
Usage(1);
exit(ERROR);
}
maxbits = atoi(*argv);
goto nextarg;
case 'I':
if (!ARGVAL()) {
fprintf(stderr, "Missing in_path name\n");
Usage(1);
exit(ERROR);
}
strcpy(inpath,*argv);
temp = &inpath[strlen(inpath)-1];
#ifdef MSDOS
if (*temp != '\\' && *temp != '/')
#else
if (*temp != separator[0])
#endif
strcat(inpath,separator);
goto nextarg;
case 'O':
if (!ARGVAL()){
fprintf(stderr, "Missing out_path name\n");
Usage(1);
exit(ERROR);
}
strcpy(outpath,*argv);
temp = &outpath[strlen(outpath)-1];
#ifdef MSDOS
if (*temp != '\\' && *temp != '/')
#else
if (*temp != separator[0])
#endif
strcat(outpath,separator);
goto nextarg;
case 'c':
keep = zcat_flg = TRUE;
break;
case 'K':
keep_error = TRUE;
break;
case 'k':
keep = !keep;
break;
case '?':case 'h':case 'H':
Usage(0);
exit(NORMAL);
break;
case 'q':
quiet = TRUE;
break;
default:
fprintf(stderr, "%s : Unknown flag: '%c'\n",prog_name, **argv);
Usage(1);
exit(ERROR);
} /* end switch */
} /* end while processing this argument */
} /* end if option parameter */
else { /* must be input file name */
*fileptr++ = *argv; /* Build input file list */
*fileptr = NULL;
} /* end else */
nextarg: continue; /* process nextarg */
} /* end command line processing */
/* adjust for possible errors or conflicts */
if(maxbits < MINBITS || maxbits > MAXBITS){
fprintf(stderr,"\n%s: illegal bit value, range = %d to %d\n",prog_name,MINBITS,MAXBITS);
exit(NORMAL);
}
if (zcat_flg && *outpath) /* can't have an out path and zcat */
*outpath = '\0';
/* to make the error messages make sense */
strcpy(ifname,"stdin");
strcpy(ofname,"stdout");
if (*filelist) { /* Check if there are files specified */
/* *fileptr must continue to specify */
/* command line in/out file name */
is_list = TRUE;
for (fileptr = filelist; *fileptr; fileptr++) {
exit_stat = 0;
endchar[0] = '\0';
if (do_decomp) { /* DECOMPRESSION */
if (*inpath){ /* adjust for inpath name */
strcpy(ifname,inpath); /* and copy into ifname */
strcat(ifname,name_index(*fileptr));
}
else
strcpy(ifname,*fileptr);
if(!is_z_name(ifname)) /* Check for .Z suffix */
if(!(make_z_name(ifname))) /* No .Z: tack one on */
continue;
/* Open input file */
if ((freopen(ifname, READ_FILE_TYPE, stdin)) == NULL) {
perror(ifname);
continue;
}
else
setvbuf(stdin,zbuf,_IOFBF,ZBUFSIZE);
if (!nomagic) { /* Check the magic number */
if ((getchar() != (magic_header[0] & 0xFF))
|| (getchar() != (magic_header[1] & 0xFF))) {
fprintf(stderr, "%s: not in compressed format\n",
ifname);
continue;
}
maxbits = getchar(); /* set -b from file */
block_compress = maxbits & BLOCK_MASK;
maxbits &= BIT_MASK;
if(maxbits > MAXBITS) {
fprintf(stderr,
"%s: compressed with %d bits, can only handle %d bits\n",
ifname, maxbits, MAXBITS);
continue;
}
} /* end if nomagic */
/* Generate output filename */
if (*outpath){ /* adjust for outpath name */
strcpy(ofname,outpath); /* and copy into ofname */
strcat(ofname,name_index(ifname));
}
else
strcpy(ofname,ifname); /* DjG may screw up the placement */
/* of the outfile */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -