home *** CD-ROM | disk | FTP | other *** search
- From: apg@hq.demos.su (Paul G. Antonov)
- Newsgroups: alt.sources
- Subject: Freeze/Melt program
- Message-ID: <1990Nov24.184206.936@hq.demos.su>
- Date: 24 Nov 90 18:42:06 GMT
-
-
- ___________________________________________________
- / Please send the comments, bug fixes, \
- | compression/speed improvement patches DIRECTLY to |
- \ <leo@s514.ipmce.su>. /
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- This program is a "compilation" from compress - GNU FSF and
- lharc (lzhuf) - H. Yoshizaki & M. Tagawa.
- Two minor improvements were made - pipe facility and 20% speedup
- by moving the code of GetBit routine into DecodeChar routine.
-
- ----------------------- cut here -------------------------
- /*
- * Freeze - data freezing program
- * Version 1.0:
- * This program is made from GNU compress.c and Yoshizaki/Tagawa's
- * lzhuf.c. (Thanks to all of them.)
- * The algorithm is modified for using in pipe
- * (added ENDOF symbol in Huffman table).
- * Version 1.1:
- * Check for lack of bytes in frozen file when melting.
- * Put the GetBit routine into DecodeChar for reduce function-
- * call overhead when melting.
- *
- * I think the code is portable, but it is presently working only
- * under SCO XENIX and ix/386 (compiled with GNU C).
- */
- char magic_header[] = { "\037\236" }; /* 1F 9E = compress + 1 */
-
- static char ident[] = "@(#) freeze.c 1.1 11/24/90 leo@s514.ipmce.su";
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef MSDOS
- #include <stdlib.h>
- #endif
-
- #define ARGVAL() (*++(*argv) || (--argc && *++argv))
-
-
- int exit_stat = 0;
-
- Usage() {
- #ifdef DEBUG
-
- # ifdef MSDOS
- fprintf(stderr,"Usage: freeze [-cdDfivV] [file ...]\n");
- # else
- fprintf(stderr,"Usage: freeze [-cdDfvV] [file ...]\n");
- # endif /* MSDOS */
-
- }
- int debug = 0;
- #else
-
- # ifdef MSDOS
- fprintf(stderr,"Usage: freeze [-cdfivV] [file ...]\n");
- # else
- fprintf(stderr,"Usage: freeze [-cdfvV] [file ...]\n");
- # endif /* MSDOS */
-
- }
- #endif /* DEBUG */
- int fcat_flg = 0; /* Write output on stdout, suppress messages */
- int precious = 1; /* Don't unlink output file on interrupt */
- int quiet = 1; /* don't tell me about freezing */
-
- /* Note indicator_threshold is triangle number of Kbytes (see below) */
-
- long int indicator_threshold, indicator_count;
-
- int force = 0;
- char ofname [100];
-
- #ifdef MSDOS
- # define PATH_SEP '\\'
- int image = 2; /* 1 <=> image (binary) mode; 2 <=> text mode */
- #else
- # define PATH_SEP '/'
- #endif
-
- #ifdef DEBUG
- int verbose = 0;
- char * pr_char();
- long symbols_out = 0, refers_out = 0;
- #endif /* DEBUG */
- int (*bgnd_flag)();
-
- int do_melt = 0;
-
- /*****************************************************************
- * TAG( main )
- *
- *
- * Usage: freeze [-cdfivV] [file ...]
- * Inputs:
- *
- * -c: Write output on stdout, don't remove original.
- *
- * -d: If given, melting is done instead.
- *
- * -f: Forces output file to be generated, even if one already
- * exists, and even if no space is saved by freezeing.
- * If -f is not used, the user will be prompted if stdin is
- * a tty, otherwise, the output file will not be overwritten.
- *
- * -i: Image mode (defined only under MS-DOS). Prevents
- * conversion between UNIX text representation (LF line
- * termination) in frozen form and MS-DOS text
- * representation (CR-LF line termination) in melted
- * form. Useful with non-text files.
- *
- * -v: Write freezing statistics
- *
- * -V: Write version and compilation options.
- *
- * file ...: Files to be frozen. If none specified, stdin
- * is used.
- * Outputs:
- * file.F: Frozen form of file with same mode, owner, and utimes
- * or stdout (if stdin used as input)
- *
- * Assumptions:
- * When filenames are given, replaces with the frozen version
- * (.F suffix) only if the file decreases in size.
- * Algorithm:
- * Modified Lempel-Ziv-SS method (LZSS), adaptive Huffman coding
- * for literal symbols and length info.
- * Static Huffman coding for position info. (It is optimal ?)
- * Lower bits of position info are put in output
- * file without any coding because of their random distribution.
- */
-
- /* From compress.c. Replace .Z --> .F etc */
-
- main( argc, argv )
- register int argc; char **argv;
- {
- int overwrite = 0; /* Do not overwrite unless given -f flag */
- char tempname[100];
- char **filelist, **fileptr;
- char *cp, *rindex(), *malloc();
- struct stat statbuf;
- extern onintr();
-
- #ifdef MSDOS
- char *sufp;
- #else
- extern oops();
- #endif
-
- #ifndef MSDOS
- #ifdef __GNUC__
- if ( (bgnd_flag = (int (*) ()) signal ( SIGINT, SIG_IGN )) != (int (*) ()) SIG_IGN )
- #else
- if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN )
- #endif
- #endif
- {
- signal ( SIGINT, onintr );
- #ifndef MSDOS
- signal ( SIGSEGV, oops );
- #endif
- }
-
- filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
- *filelist = NULL;
-
- if((cp = rindex(argv[0], PATH_SEP)) != 0) {
- cp++;
- } else {
- cp = argv[0];
- }
-
- #ifdef MSDOS
- if(strcmp(cp, "MELT.EXE") == 0) {
- #else
- if(strcmp(cp, "melt") == 0) {
- #endif
-
- do_melt = 1;
-
- #ifdef MSDOS
- } else if(strcmp(cp, "FCAT.EXE") == 0) {
- #else
- } else if(strcmp(cp, "fcat") == 0) {
- #endif
-
- do_melt = 1;
- fcat_flg = 1;
- }
-
- #ifdef BSD4_2
- /* 4.2BSD dependent - take it out if not */
- setlinebuf( stderr );
- #endif /* BSD4_2 */
-
- /* Argument Processing
- * All flags are optional.
- * -D => debug
- * -V => print Version; debug verbose
- * -d => do_melt
- * -v => unquiet
- * -f => force overwrite of output file
- * -c => cat all output to stdout
- * if a string is left, must be an input filename.
- */
- 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 = 1;
- break;
- case 'V':
- verbose = 1;
- version();
- break;
- #else
- case 'V':
- version();
- break;
- #endif /* DEBUG */
-
- #ifdef MSDOS
- case 'i':
- image = 1;
- break;
- #endif
-
- case 'v':
- quiet = 0;
- break;
- case 'd':
- do_melt = 1;
- break;
- case 'f':
- case 'F':
- overwrite = 1;
- force = 1;
- break;
- case 'c':
- fcat_flg = 1;
- break;
- case 'q':
- quiet = 1;
- break;
- default:
- fprintf(stderr, "Unknown flag: '%c'; ", **argv);
- Usage();
- exit(1);
- }
- }
- }
- else { /* Input file name */
- *fileptr++ = *argv; /* Build input file list */
- *fileptr = NULL;
- }
- }
-
- if (*filelist != NULL) {
- for (fileptr = filelist; *fileptr; fileptr++) {
- exit_stat = 0;
- if (do_melt != 0) { /* MELTING */
-
- #ifdef MSDOS
- /* Check for .F or XF suffix; add one if necessary */
- cp = *fileptr + strlen(*fileptr) - 2;
- if ((*cp != '.' && *cp != 'X' && *cp != 'x') ||
- (*(++cp) != 'F' && *cp != 'f')) {
- strcpy(tempname, *fileptr);
- if ((cp=rindex(tempname,'.')) == NULL)
- strcat(tempname, ".F");
- else if(*(++cp) == '\0') strcat(tempname, "F");
- else {
- *(++cp) = '\0';
- strcat(tempname, "XF");
- }
- *fileptr = tempname;
- }
- #else
- /* Check for .F suffix */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") != 0) {
- /* No .F: tack one on */
- strcpy(tempname, *fileptr);
- strcat(tempname, ".F");
- *fileptr = tempname;
- }
- #endif /*MSDOS */
-
- /* Open input file for melting */
-
- #ifdef MSDOS
- if ((freopen(*fileptr, "rb", stdin)) == NULL)
- #else
- if ((freopen(*fileptr, "r", stdin)) == NULL)
- #endif
- {
- perror(*fileptr); continue;
- }
- /* Check the magic number */
- if ((getchar() != (magic_header[0] & 0xFF))
- || (getchar() != (magic_header[1] & 0xFF))) {
- fprintf(stderr, "%s: not in frozen format\n",
- *fileptr);
- continue;
- }
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .F */
- } else { /* FREEZING */
-
- #ifdef MSDOS
- cp = *fileptr + strlen(*fileptr) - 2;
- if ((*cp == '.' || *cp == 'X' || *cp == 'x') &&
- (*(++cp) == 'F' || *cp == 'f')) {
- fprintf(stderr,"%s: already has %s suffix -- no change\n",
- *fileptr,--cp); /* } */
- #else
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") == 0) {
- fprintf(stderr, "%s: already has .F suffix -- no change\n",
- *fileptr);
- #endif /* MSDOS */
-
- continue;
- }
- /* Open input file for freezing */
-
- #ifdef MSDOS
- if ((freopen(*fileptr, image == 2 ? "rt" : "rb", stdin))
- == NULL)
- #else
- if ((freopen(*fileptr, "r", stdin)) == NULL)
- #endif
- {
- perror(*fileptr); continue;
- }
- stat ( *fileptr, &statbuf );
-
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- #ifndef BSD4_2 /* Short filenames */
- if ((cp = rindex(ofname, PATH_SEP)) != NULL) cp++;
- else cp = ofname;
- # ifdef MSDOS
- if (fcat_flg == 0 && (sufp = rindex(cp, '.')) != NULL &&
- strlen(sufp) > 2) fprintf(stderr,
- "%s: part of filename extension will be replaced by XF\n",
- cp);
- # else
- if (strlen(cp) > 12) {
- fprintf(stderr,"%s: filename too long to tack on .F\n",cp);
- continue;
- }
- # endif
- #endif /* BSD4_2 Long filenames allowed */
-
- #ifdef MSDOS
- if ((cp = rindex(ofname, '.')) == NULL) strcat(ofname, ".F");
- else {
- if(*(++cp) != '\0') *(++cp) = '\0';
- strcat(ofname, "XF");
- }
- #else
- strcat(ofname, ".F");
- #endif /* MSDOS */
-
- }
- precious = 0;
- /* Check for overwrite of existing file */
- if (overwrite == 0 && fcat_flg == 0) {
- if (stat(ofname, &statbuf) == 0) {
- char response[2];
- response[0] = 'n';
- fprintf(stderr, "%s already exists;", ofname);
- #ifndef MSDOS
- if (foreground()) {
- #endif
- fprintf(stderr,
- " do you wish to overwrite %s (y or n)? ", ofname);
- fflush(stderr);
- read(2, response, 2);
- while (response[1] != '\n') {
- if (read(2, response+1, 1) < 0) { /* Ack! */
- perror("stderr"); break;
- }
- }
- #ifndef MSDOS
- }
- #endif
- if (response[0] != 'y') {
- fprintf(stderr, "\tnot overwritten\n");
- continue;
- }
- }
- }
- if(fcat_flg == 0) { /* Open output file */
-
- #ifdef DEBUG
- if (do_melt == 0 || debug == 0) {
- #endif
- #ifdef MSDOS
- if (freopen(ofname, do_melt && image == 2 ? "wt" : "wb",
- stdout) == NULL)
- #else
- if (freopen(ofname, "w", stdout) == NULL)
- #endif
- {
- perror(ofname); continue;
- }
- #ifdef DEBUG
- }
- #endif
- if(!quiet) {
- fprintf(stderr, "%s:", *fileptr);
- indicator_threshold = 2048;
- indicator_count = 1024;
- }
- }
- /* Actually do the freezing/melting */
- if (do_melt == 0) freeze();
- #ifndef DEBUG
- else melt();
- #else
- else if (debug == 0) melt();
- else printcodes();
- #endif /* DEBUG */
- if(fcat_flg == 0) {
- copystat(*fileptr, ofname); /* Copy stats */
- if((exit_stat == 1) || (!quiet))
- putc('\n', stderr);
- }
- }
- } else { /* Standard input */
- if (do_melt == 0) {
- freeze();
- if(!quiet)
- putc('\n', stderr);
- } else {
- /* Check the magic number */
- if ((getchar()!=(magic_header[0] & 0xFF))
- || (getchar()!=(magic_header[1] & 0xFF))) {
- fprintf(stderr, "stdin: not in frozen format\n");
- exit(1);
- }
- #ifndef DEBUG
- melt();
- #else
- if (debug == 0) melt();
- else printcodes();
- #endif /* DEBUG */
- }
- }
- exit(exit_stat);
- }
-
- long int in_count = 1; /* length of input */
- long int bytes_out; /* length of frozen output */
-
- /*----------------------------------------------------------------------*/
- /* */
- /* LZSS ENCODING (lzhuf.c) */
- /* */
- /*----------------------------------------------------------------------*/
-
- #ifdef lint
- #define N 256
- #else
- #define N 4096 /* buffer size */
- #endif
-
- #define F 60 /* pre-sence buffer size */
- #define THRESHOLD 2
- #define NIL N /* term of tree */
- /*
- * Increasing of N and F ( N = 8192, F = 80) gives 1.2 - 1.5% of additional
- * reducing, but 2 times slower.
- */
- unsigned char text_buf[N + F - 1];
- unsigned int match_position, match_length;
- short lson[N + 1], rson[N + 1 + N], dad[N + 1];
- unsigned char same[N + 1];
-
-
- /* Initialize Tree */
- InitTree ()
- {
- register short *p, *e;
-
- for (p = rson + N + 1, e = rson + N + N; p <= e; )
- *p++ = NIL;
- for (p = dad, e = dad + N; p < e; )
- *p++ = NIL;
- }
-
-
- /* Insert to node */
- InsertNode (r)
- register int r;
- {
- register int p;
- int cmp;
- register unsigned char *key;
- register unsigned int c;
- register unsigned int i, j;
-
- cmp = 1;
- key = &text_buf[r];
- i = key[1] ^ key[2];
- i ^= i >> 4;
- p = N + 1 + key[0] + ((i & 0x0f) << 8);
- rson[r] = lson[r] = NIL;
- match_length = 0;
- i = j = 1;
- for ( ; ; ) {
- if (cmp >= 0) {
- if (rson[p] != NIL) {
- p = rson[p];
- j = same[p];
- } else {
- rson[p] = r;
- dad[r] = p;
- same[r] = i;
- return;
- }
- } else {
- if (lson[p] != NIL) {
- p = lson[p];
- j = same[p];
- } else {
- lson[p] = r;
- dad[r] = p;
- same[r] = i;
- return;
- }
- }
-
- if (i > j) {
- i = j;
- cmp = key[i] - text_buf[p + i];
- } else
- if (i == j) {
- for (; i < F; i++)
- if ((cmp = key[i] - text_buf[p + i]) != 0)
- break;
- }
-
- if (i > THRESHOLD) {
- if (i > match_length) {
- match_position = ((r - p) & (N - 1)) - 1;
- if ((match_length = i) >= F)
- break;
- } else
- if (i == match_length) {
- if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
- match_position = c;
- }
- }
- }
- }
- same[r] = same[p];
- dad[r] = dad[p];
- lson[r] = lson[p];
- rson[r] = rson[p];
- dad[lson[p]] = r;
- dad[rson[p]] = r;
- if (rson[dad[p]] == p)
- rson[dad[p]] = r;
- else
- lson[dad[p]] = r;
- dad[p] = NIL; /* remove p */
- }
-
- static
- void
- link (n, p, q)
- int n, p, q;
- {
- register unsigned char *s1, *s2, *s3;
- if (p >= NIL) {
- same[q] = 1;
- return;
- }
- s1 = text_buf + p + n;
- s2 = text_buf + q + n;
- s3 = text_buf + p + F;
- while (s1 < s3) {
- if (*s1++ != *s2++) {
- #ifdef __GNUC__ /* Not an ideal compiler !! */
- n = s1 - text_buf;
- same[q] = n - 1 - p;
- #else
- same[q] = s1 - 1 - text_buf - p;
- #endif
- return;
- }
- }
- same[q] = F;
- }
-
-
- linknode (p, q, r)
- int p, q, r;
- {
- int cmp;
-
- if ((cmp = same[q] - same[r]) == 0) {
- link((int)same[q], p, r);
- } else if (cmp < 0) {
- same[r] = same[q];
- }
- }
-
- DeleteNode (p)
- register int p;
- {
- register int q;
-
- if (dad[p] == NIL)
- return; /* has no linked */
- if (rson[p] == NIL) {
- if ((q = lson[p]) != NIL)
- linknode(dad[p], p, q);
- } else
- if (lson[p] == NIL) {
- q = rson[p];
- linknode(dad[p], p, q);
- } else {
- q = lson[p];
- if (rson[q] != NIL) {
- do {
- q = rson[q];
- } while (rson[q] != NIL);
- if (lson[q] != NIL)
- linknode(dad[q], q, lson[q]);
- link(1, q, lson[p]);
- rson[dad[q]] = lson[q];
- dad[lson[q]] = dad[q];
- lson[q] = lson[p];
- dad[lson[p]] = q;
- }
- link(1, dad[p], q);
- link(1, q, rson[p]);
- rson[q] = rson[p];
- dad[rson[p]] = q;
- }
- dad[q] = dad[p];
- if (rson[dad[p]] == p)
- rson[dad[p]] = q;
- else
- lson[dad[p]] = q;
- dad[p] = NIL;
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /* HUFFMAN ENCODING */
- /* */
- /*----------------------------------------------------------------------*/
-
- #define N_CHAR (256 - THRESHOLD + F + 1) /* {code : 0 .. N_CHAR-1} */
- #define T (N_CHAR * 2 - 1) /* size of table */
- #define R (T - 1) /* root position */
-
- #define MAX_FREQ (unsigned)0x8000 /* tree update timing from frequency */
-
- #define ENDOF 256
-
- typedef unsigned char uchar;
-
- /* TABLE OF ENCODE/DECODE for upper 6bits position information */
-
- /* for encode */
- uchar p_len[64] = {
- 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
- };
-
- uchar p_code[64] = {
- 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
- 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
- 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
- 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
- 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
- 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
- 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
- };
-
- /* for decode */
- uchar d_code[256] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
- 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
- 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
- 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
- 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
- 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
- 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
- 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
- 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
- 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
- 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
- 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- };
-
- uchar d_len[256] = {
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- };
-
- unsigned short freq[T + 1]; /* frequency table */
-
- short prnt[T + N_CHAR]; /* points to parent node */
- /* notes :
- prnt[T .. T + N_CHAR - 1] used by
- indicates leaf position that corresponding to code */
-
- short son[T]; /* points to son node (son[i],son[i+]) */
-
- unsigned short getbuf = 0;
- uchar getlen = 0;
-
- uchar corrupt_flag = 0; /* If a file is corrupt, use fcat */
-
- /* get one byte */
- /* returning in Bit7...0 */
- int GetByte ()
- {
- register unsigned short int dx = getbuf;
- register unsigned int c;
-
- if (getlen <= 8) {
- c = getchar ();
- if ((int)c < 0) {
- /* Frozen file is too short. This is fatal error.
- * Really the second absent byte indicates a error.
- * ("Packed file is corrupt." :-) )
- */
- if (corrupt_flag)
- oops();
- corrupt_flag = 1;
- c = 0;
- }
- dx |= c << (8 - getlen);
- getlen += 8;
- }
- getbuf = dx << 8;
- getlen -= 8;
- return (dx >> 8) & 0xff;
- }
-
- /* get N bit */
- /* returning in Bit(N-1)...Bit 0 */
- int GetNBits (n)
- register unsigned int n;
- {
- register unsigned int dx = getbuf;
- register unsigned int c;
- static int mask[17] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f,
- 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff,
- 0x1fff, 0x3fff, 0x7fff, 0xffff };
- static int shift[17] = {
- 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
-
- if (getlen <= 8)
- {
- c = getchar ();
- if ((int)c < 0) {
- if (corrupt_flag)
- oops();
- corrupt_flag = 1;
- c = 0;
- }
- dx |= c << (8 - getlen);
- getlen += 8;
- }
- getbuf = dx << n;
- getlen -= n;
- return (dx >> shift[n]) & mask[n];
- }
-
- unsigned short putbuf = 0;
- uchar putlen = 0;
-
- /* output C bits */
- Putcode (l, c)
- register int l;
- unsigned int c;
- {
- register short len = putlen;
- register unsigned short b = putbuf;
- b |= c >> len;
- if ((len += l) >= 8) {
- if (putchar (b >> 8) == EOF) writeerr();
- if ((len -= 8) >= 8) {
- putchar (b);
- bytes_out += 2;
- len -= 8;
- b = c << (l - len);
- } else {
- b <<= 8;
- bytes_out++;
- }
- }
- putbuf = b;
- putlen = len;
- }
-
-
- /* Initialize tree */
-
- StartHuff ()
- {
- register int i, j;
-
- for (i = 0; i < N_CHAR; i++) {
- freq[i] = 1;
- son[i] = i + T;
- prnt[i + T] = i;
- }
- i = 0; j = N_CHAR;
- while (j <= R) {
- freq[j] = freq[i] + freq[i + 1];
- son[j] = i;
- prnt[i] = prnt[i + 1] = j;
- i += 2; j++;
- }
- freq[T] = 0xffff;
- prnt[R] = 0;
- in_count = 1;
- bytes_out = 2;
- #ifdef DEBUG
- symbols_out = refers_out = 0;
- #endif
- putlen = getlen = 0;
- putbuf = getbuf = 0;
- corrupt_flag = 0;
- }
-
-
- /* reconstruct tree */
- reconst ()
- {
- register int i, j, k;
- register unsigned f;
- #ifdef DEBUG
- if (!quiet)
- fprintf(stderr,
- "Reconstructing Huffman tree: symbols: %ld, references: %ld\n",
- symbols_out, refers_out);
- #endif
- /* correct leaf node into of first half,
- and set these freqency to (freq+1)/2 */
- j = 0;
- for (i = 0; i < T; i++) {
- if (son[i] >= T) {
- freq[j] = (freq[i] + 1) / 2;
- son[j] = son[i];
- j++;
- }
- }
- /* build tree. Link sons first */
- for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
- k = i + 1;
- f = freq[j] = freq[i] + freq[k];
- for (k = j - 1; f < freq[k]; k--);
- k++;
- { register unsigned short *p, *e;
- for (p = &freq[j], e = &freq[k]; p > e; p--)
- p[0] = p[-1];
- freq[k] = f;
- }
- { register short *p, *e;
- for (p = &son[j], e = &son[k]; p > e; p--)
- p[0] = p[-1];
- son[k] = i;
- }
- }
- /* link parents */
- for (i = 0; i < T; i++) {
- if ((k = son[i]) >= T) {
- prnt[k] = i;
- } else {
- prnt[k] = prnt[k + 1] = i;
- }
- }
- }
-
-
- /* update given code's frequency, and update tree */
-
- update (c)
- unsigned int c;
- {
- register unsigned short *p;
- register int i, j, k, l;
-
- if (freq[R] == MAX_FREQ) {
- reconst();
- }
- c = prnt[c + T];
- do {
- k = ++freq[c];
-
- /* swap nodes when become wrong frequency order. */
- if (k > freq[l = c + 1]) {
- for (p = freq+l+1; k > *p++; ) ;
- l = p - freq - 2;
- freq[c] = p[-2];
- p[-2] = k;
-
- i = son[c];
- prnt[i] = l;
- if (i < T) prnt[i + 1] = l;
-
- j = son[l];
- son[l] = i;
-
- prnt[j] = c;
- if (j < T) prnt[j + 1] = c;
- son[c] = j;
-
- c = l;
- }
- } while ((c = prnt[c]) != 0); /* loop until reach to root */
- }
-
- /* unsigned code, len; */
-
- EncodeChar (c)
- unsigned c;
- {
- register short *p;
- unsigned long i;
- register int j, k;
-
- i = 0;
- j = 0;
- p = prnt;
- k = p[c + T];
-
- /* trace links from leaf node to root */
- do {
- i >>= 1;
-
- /* if node index is odd, trace larger of sons */
- if (k & 1) i += 0x80000000;
-
- j++;
- } while ((k = p[k]) != R) ;
- if (j > 16) {
- Putcode(16, (unsigned int)(i >> 16));
- Putcode(j - 16, (unsigned int)i);
- } else {
- Putcode(j, (unsigned int)(i >> 16));
- }
- /* code = i; */
- /* len = j; */
- update(c);
- }
-
- EncodePosition (c)
- register unsigned c;
- {
- register unsigned i;
-
- /* output upper 6bit from table */
- i = c >> 6;
- Putcode((int)(p_len[i]), (unsigned int)(p_code[i]) << 8);
-
- /* output lower 6 bit */
- Putcode(6, (unsigned int)(c & 0x3f) << 10);
- }
-
- EncodeEnd ()
- {
- if (putlen) {
- putchar(putbuf >> 8);
- bytes_out++;
- }
- }
-
- int DecodeChar ()
- {
- register unsigned c;
- register unsigned short dx;
- register unsigned short cc;
- c = son[R];
-
- /* trace from root to leaf,
- got bit is 0 to small(son[]), 1 to large (son[]+1) son node */
- while (c < T) {
- dx = getbuf;
- if (getlen <= 8) {
- if ((short)(cc = getchar()) < 0) {
- if (corrupt_flag)
- oops();
- corrupt_flag = 1;
- cc = 0;
- }
- dx |= cc << (8 - getlen);
- getlen += 8;
- }
- getbuf = dx << 1;
- getlen--;
- c += (dx >> 15) & 1;
- c = son[c];
- }
- c -= T;
- update(c);
- return c;
- }
-
- int DecodePosition ()
- {
- register unsigned short i, j, c;
-
- /* decode upper 6bit from table */
- i = GetByte();
- c = (unsigned)d_code[i] << 6;
- j = d_len[i];
-
- /* get lower 6bit */
- j -= 2;
- return c | (((i << j) | GetNBits (j)) & 0x3f);
- }
-
- /*
- * freeze stdin to stdout (as in compress.c & lzhuf.c)
- */
-
- freeze ()
- {
- register int i, c, len, r, s, last_match_length;
- putchar(magic_header[0]);
- putchar(magic_header[1]);
- StartHuff();
- InitTree();
- s = 0;
- r = N - F;
- for (i = s; i < r; i++)
- text_buf[i] = ' ';
- for (len = 0; len < F && (c = getchar()) != EOF; len++)
- text_buf[r + len] = c;
- in_count = len;
- for (i = 1; i <= F; i++)
- InsertNode(r - i);
- InsertNode(r);
- while (len > 0) {
- if (match_length > len)
- match_length = len;
- if (match_length <= THRESHOLD) {
- match_length = 1;
- EncodeChar(text_buf[r]);
- #ifdef DEBUG
- symbols_out ++;
- if (verbose)
- fprintf(stderr, "'%s'\n", pr_char(text_buf[r]));
- #endif /* DEBUG */
- } else {
- EncodeChar(256 - THRESHOLD + match_length);
- EncodePosition(match_position);
- #ifdef DEBUG
- refers_out ++;
- if (verbose) {
- register int pos = (r - 1 - match_position) & (N - 1),
- len = match_length;
- fputc('"', stderr);
- for(;len;len--, pos++)
- fprintf(stderr, "%s", pr_char(text_buf[pos]));
- fprintf(stderr, "\"\n");
- }
- #endif /* DEBUG */
- }
- last_match_length = match_length;
- for (i = 0; i < last_match_length &&
- (c = getchar()) != EOF; i++) {
- DeleteNode(s);
- text_buf[s] = c;
- if (s < F - 1)
- text_buf[s + N] = c;
- s = (s + 1) & (N - 1);
- r = (r + 1) & (N - 1);
- InsertNode(r);
- }
-
- in_count += i;
- if ((in_count > indicator_count) && !quiet) {
- fprintf(stderr, "%5dK\b\b\b\b\b\b", in_count / 1024);
- fflush (stderr);
- indicator_count += indicator_threshold;
- indicator_threshold += 1024;
- }
- while (i++ < last_match_length) {
- DeleteNode(s);
- s = (s + 1) & (N - 1);
- r = (r + 1) & (N - 1);
- if (--len) InsertNode(r);
- }
- }
- EncodeChar(ENDOF);
- #ifdef DEBUG
- symbols_out ++;
- #endif
- EncodeEnd();
- /*
- * Print out stats on stderr
- */
- if(!quiet) {
- #ifdef DEBUG
- fprintf( stderr,
- "%ld chars in, %ld codes (%ld bytes) out, freezing factor: ",
- in_count, symbols_out + refers_out, bytes_out);
- prratio( stderr, in_count, bytes_out );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tFreezing as in compact: " );
- prratio( stderr, in_count-bytes_out, in_count );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tSymbols: %ld; references: %ld.\n",
- symbols_out, refers_out);
- #else /* !DEBUG */
- fprintf( stderr, "Freezing: " );
- prratio( stderr, in_count-bytes_out, in_count );
- #endif /* DEBUG */
- }
- if(bytes_out > in_count) /* exit(2) if no savings */
- exit_stat = 2;
- return;
- }
-
- /*
- * Melt stdin to stdout.
- * Works =~= 1.5 times faster than uncompress (relatively to decompressed
- * filesize) - on 16-bit machines.
- * !! DO NOT (!!) use arithmetic compression - it is extremely
- * slow when decompressing.
- */
-
- melt ()
- {
- register int i, j, k, r, c;
- StartHuff();
- for (i = 0; i < N - F; i++)
- text_buf[i] = ' ';
- r = N - F;
- for (in_count = 0;; ) {
- c = DecodeChar();
- if (c == ENDOF)
- break;
- if (c < 256) {
- putchar (c);
- text_buf[r++] = c;
- r &= (N - 1);
- in_count++;
- } else {
- i = (r - DecodePosition() - 1) & (N - 1);
- j = c - 256 + THRESHOLD;
- for (k = 0; k < j; k++) {
- c = text_buf[(i + k) & (N - 1)];
- putchar (c);
- text_buf[r++] = c;
- r &= (N - 1);
- in_count++;
- }
- }
-
- if (!quiet && (in_count > indicator_count)) {
- fprintf(stderr, "%5dK\b\b\b\b\b\b", in_count / 1024);
- fflush (stderr);
- indicator_count += indicator_threshold;
- indicator_threshold += 1024;
- }
- }
- }
-
- char *
- rindex(s, c) /* For those who don't have it in libc.a */
- register char *s, c;
- {
- char *p;
- for (p = NULL; *s; s++)
- if (*s == c)
- p = s;
- return(p);
- }
-
- #ifdef DEBUG
- printcodes()
- {
- /*
- * Just print out codes from input file. For debugging.
- */
- register int k, c, col = 0;
- StartHuff();
- for (;;) {
- c = DecodeChar();
- if (c == ENDOF)
- break;
- if (c < 256) {
- fprintf(stderr, "%5d%c", c, (col+=8) >= 74 ? (col = 0, '\n') : '\t' );
- } else {
- c = c - 256 + THRESHOLD;
- k = DecodePosition();
- fprintf(stderr, "%2d-%d%c", c, k, (col+=8) >= 74 ? (col = 0, '\n') : '\t' );
- }
- }
- putc( '\n', stderr );
- exit( 0 );
- }
-
- /* for pretty char printing */
-
- char *
- pr_char(c)
- register unsigned char c;
- {
- static char buf[5];
- register i = 4;
- buf[4] = '\0';
- if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
- buf[--i] = c;
- } else {
- switch( c ) {
- case '\n': buf[--i] = 'n'; break;
- case '\t': buf[--i] = 't'; break;
- case '\b': buf[--i] = 'b'; break;
- case '\f': buf[--i] = 'f'; break;
- case '\r': buf[--i] = 'r'; break;
- case '\\': buf[--i] = '\\'; break;
- default:
- buf[--i] = '0' + c % 8;
- buf[--i] = '0' + (c / 8) % 8;
- buf[--i] = '0' + c / 64;
- break;
- }
- buf[--i] = '\\';
- }
- return &buf[i];
- }
- #endif /* DEBUG */
-
- writeerr()
- {
- perror ( ofname );
- unlink ( ofname );
- exit ( 1 );
- }
-
- copystat(ifname, ofname)
- char *ifname, *ofname;
- {
- struct stat statbuf;
- int mode;
- time_t timep[2];
-
- #ifdef MSDOS
- if (_osmajor < 3) freopen("CON","at",stdout); else /* MS-DOS 2.xx bug */
- #endif
-
- fclose(stdout);
- if (stat(ifname, &statbuf)) { /* Get stat on input file */
- perror(ifname);
- return;
- }
-
- #ifndef MSDOS
- if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
- if(quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " not a regular file: unchanged");
- exit_stat = 1;
- } else if (statbuf.st_nlink > 1) {
- if(quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " has %d other links: unchanged",
- statbuf.st_nlink - 1);
- exit_stat = 1;
- } else if (exit_stat == 2 && (!force)) { /* No freezing: remove file.Z */
- #else
- if (exit_stat == 2 && (!force)) { /* No freezing: remove file.Z */
- #endif /* MSDOS */
-
- if(!quiet)
- fprintf(stderr, " file unchanged");
- } else { /* ***** Successful Freezing ***** */
- exit_stat = 0;
- mode = statbuf.st_mode & 07777;
- if (chmod(ofname, mode)) /* Copy modes */
- perror(ofname);
-
- #ifndef MSDOS
- chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */
- #endif
-
- timep[0] = statbuf.st_atime;
- timep[1] = statbuf.st_mtime;
- utime(ofname, timep); /* Update last accessed and modified times */
- precious = 1;
- if (unlink(ifname)) /* Remove input file */
- perror(ifname);
- if(!quiet)
- fprintf(stderr, " -- replaced with %s", ofname);
- return; /* Successful return */
- }
-
- /* Unsuccessful return -- one of the tests failed */
- if (unlink(ofname))
- perror(ofname);
- }
-
- #ifndef MSDOS
- /*
- * This routine returns 1 if we are running in the foreground and stderr
- * is a tty.
- */
- foreground()
- {
- #ifdef __GNUC__
- if(bgnd_flag != (int (*) ()) SIG_DFL) /* background? */
- #else
- if(bgnd_flag != SIG_DFL) /* background? */
- #endif
- return(0);
- else { /* foreground */
- if(isatty(2)) { /* and stderr is a tty */
- return(1);
- } else {
- return(0);
- }
- }
- }
- #endif
-
- onintr ( )
- {
- if (!precious)
- unlink ( ofname );
- exit ( 1 );
- }
-
- oops ( ) /* wild index -- assume bad input (or file too short) */
- {
- if ( do_melt == 1 )
- fprintf ( stderr, "melt: corrupt input\n" );
- if ( fcat_flg == 1)
- fflush(stdout); /* Something is better than nothing */
- else
- unlink ( ofname );
- exit ( 1 );
- }
-
-
- prratio(stream, num, den)
- FILE *stream;
- long int num, den;
- {
-
- #ifdef DEBUG
- register long q; /* permits |result| > 655.36% */
- #else
- register int q; /* Doesn't need to be long */
- #endif
- if (!den) den++;
-
- if(num > 214748L) { /* 2147483647/10000 */
- q = num / (den / 10000L);
- } else {
- q = 10000L * num / den; /* Long calculations, though */
- }
- if (q < 0) {
- putc('-', stream);
- q = -q;
- }
- fprintf(stream, "%d.%02d%%", (int)(q / 100), (int)(q % 100));
- }
-
- version()
- {
- fprintf(stderr, "%s\n", ident);
- fprintf(stderr, "Options: ");
- #ifdef DEBUG
- fprintf(stderr, "DEBUG, ");
- #endif
- #ifdef BSD4_2
- fprintf(stderr, "BSD4_2, ");
- #endif
- #ifdef M_XENIX
- fprintf(stderr, "XENIX, ");
- #endif
- fprintf(stderr, "LZSS: %d (table), %d (match length);\n", N, F);
- fprintf(stderr, "HUFFMAN: %ld (max frequency)\n", (long)MAX_FREQ);
- }
- ----------------------- cut here -------------------------
-