home *** CD-ROM | disk | FTP | other *** search
- static char sccsid[] = "@(#)compress.c @(#)compress.c 5.9 (Berkeley) 5/11/86";
-
- /*
- * Compress - data compression program
- */
- #define min(a,b) ((a>b) ? b : a)
-
- #define HSIZE 69001 /* 95% occupancy */
-
- /*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
- typedef long int code_int;
- typedef long int count_int;
-
- typedef unsigned char char_type;
- char_type magic_header[] = { "\037\235" }; /* 1F 9D */
-
- /* Defines for third byte of header */
- #define BIT_MASK 0x1f
- #define BLOCK_MASK 0x80
- /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- a fourth header byte (for expansion).
- */
- #define INIT_BITS 9 /* initial number of bits/code */
-
- static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
-
- #include <stdio.h>
- #include <ctype.h>
- #include <stat.h>
- #include <time.h>
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/ports.h>
- #include <exec/io.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <functions.h>
-
-
- #define ARGVAL() (*++(*argv) || (--argc && *++argv))
-
- int n_bits; /* number of bits/code */
- int maxbits = BITS; /* user settable max # bits/code */
- code_int maxcode; /* maximum code, given n_bits */
- code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */
- #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
-
- /* extern int errno; */
-
- count_int *htab;
- unsigned short *codetab;
-
- #define htabof(i) htab[i]
- #define codetabof(i) codetab[i]
-
- code_int hsize = HSIZE; /* for dynamic table sizing */
- count_int fsize;
-
- /*
- * To save much memory, we overlay the table used by compress() with those
- * used by decompress(). The tab_prefix table is the same size and type
- * as the codetab. The tab_suffix table needs 2**BITS characters. We
- * get this from the beginning of htab. The output stack uses the rest
- * of htab, and contains characters. There is plenty of room for any
- * possible stack (stack used to be 8000 characters).
- */
-
- #define tab_prefixof(i) codetabof(i)
- #define tab_suffixof(i) ((char_type *)(htab))[i]
- #define de_stack ((char_type *)&tab_suffixof(1<<BITS))
-
- code_int free_ent = 0; /* first unused entry */
- int exit_stat = 0; /* per-file status */
- int perm_stat = 0; /* permanent status */
-
- code_int getcode();
-
- Usage() {
- fprintf(stderr,"Usage: compress [-fvc] [-b maxbits] [file ...]\n");
- }
- int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
- int zcat_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 compression */
-
- /*
- * block compression parameters -- after all codes are used up,
- * and compression rate changes, start over.
- */
- int block_compress = BLOCK_MASK;
- int clear_flg = 0;
- long int ratio = 0;
- #define CHECK_GAP 10000 /* ratio check interval */
- count_int checkpoint = CHECK_GAP;
- /*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
- #define FIRST 257 /* first free entry */
- #define CLEAR 256 /* table clear output code */
-
- int force = 0;
- char ofname [100];
- int (*oldint)();
-
- int do_decomp = 0;
-
- /*****************************************************************
- * TAG( main )
- *
- * Algorithm from "A Technique for High Performance Data Compression",
- * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
- *
- * Usage: compress [-dfvc] [-b bits] [file ...]
- * Inputs:
- * -d: If given, decompression is done instead.
- *
- * -c: Write output on stdout, don't remove original.
- *
- * -b: Parameter limits the max number of bits/code.
- *
- * -f: Forces output file to be generated, even if one already
- * exists, and even if no space is saved by compressing.
- * If -f is not used, the user will be prompted if stdin is
- * a tty, otherwise, the output file will not be overwritten.
- *
- * -v: Write compression statistics
- *
- * file ...: Files to be compressed. If none specified, stdin
- * is used.
- * Outputs:
- * file.Z: Compressed form of file with same mode, owner, and utimes
- * or stdout (if stdin used as input)
- *
- * 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.
- */
-
- 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(), *strcpy(), *malloc();
- struct stat statbuf;
- extern onintr(), oops();
-
- freopen("*","r+", stderr);
-
- htab = (count_int *)malloc(HSIZE * sizeof(count_int));
- codetab = (unsigned short *)malloc(HSIZE * sizeof(unsigned short));
- if (htab == NULL || codetab == NULL) {
- fprintf(stderr,"compress: out of memory\n");
- exit(1);
- }
- filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
- *filelist = NULL;
-
- if((cp = rindex(argv[0], '/')) != 0) {
- cp++;
- } else {
- cp = argv[0];
- }
- if(strcmp(cp, "uncompress") == 0) {
- do_decomp = 1;
- } else if(strcmp(cp, "zcat") == 0) {
- do_decomp = 1;
- zcat_flg = 1;
- }
-
- /* Argument Processing
- * All flags are optional.
- * -D => debug
- * -V => print Version; debug verbose
- * -d => do_decomp
- * -v => unquiet
- * -f => force overwrite of output file
- * -n => no header: useful to uncompress old files
- * -b maxbits => maxbits. If -b is specified, then maxbits MUST be
- * given also.
- * -c => cat all output to stdout
- * -C => generate output compatible with compress 2.0.
- * 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) {
- case 'V':
- version();
- break;
- case 'v':
- quiet = 0;
- break;
- case 'd':
- do_decomp = 1;
- break;
- case 'f':
- case 'F':
- overwrite = 1;
- force = 1;
- break;
- case 'n':
- nomagic = 1;
- break;
- case 'C':
- block_compress = 0;
- break;
- case 'b':
- if (!ARGVAL()) {
- fprintf(stderr, "Missing maxbits\n");
- Usage();
- exit(1);
- }
- maxbits = atoi(*argv);
- goto nextarg;
- case 'c':
- zcat_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;
- /* process nextarg; */
- }
- nextarg: continue;
- }
-
- if (maxbits < INIT_BITS) maxbits = INIT_BITS;
- if (maxbits > BITS) maxbits = BITS;
- maxmaxcode = 1 << maxbits;
-
- if (*filelist != NULL) {
- for (fileptr = filelist; *fileptr; fileptr++) {
- exit_stat = 0;
- if (do_decomp) { /* DECOMPRESSION */
- /* Check for .Z suffix */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
- /* No .Z: tack one on */
- strcpy(tempname, *fileptr);
- strcat(tempname, ".Z");
- *fileptr = tempname;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr);
- perm_stat = 1;
- continue;
- }
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getc(stdin) != (magic_header[0] & 0xFF))
- || (getc(stdin) != (magic_header[1] & 0xFF))) {
- fprintf(stderr, "%s: not in compressed format\n",
- *fileptr);
- continue;
- }
- maxbits = getc(stdin); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1 << maxbits;
- if(maxbits > BITS) {
- fprintf(stderr,
- "%s: compressed with %d bits, can only handle %d bits\n",
- *fileptr, maxbits, BITS);
- continue;
- }
- }
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */
- } else { /* COMPRESSION */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
- fprintf(stderr, "%s: already has .Z suffix -- no change\n",
- *fileptr);
- continue;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr);
- perm_stat = 1;
- continue;
- }
- stat ( *fileptr, &statbuf );
- fsize = (long) statbuf.st_size;
- /*
- * tune hash table size for small files -- ad hoc,
- * but the sizes match earlier #defines, which
- * serve as upper bounds on the number of output codes.
- */
- hsize = HSIZE;
- if ( fsize < (1 << 12) )
- hsize = min ( 5003, HSIZE );
- else if ( fsize < (1 << 13) )
- hsize = min ( 9001, HSIZE );
- else if ( fsize < (1 << 14) )
- hsize = min ( 18013, HSIZE );
- else if ( fsize < (1 << 15) )
- hsize = min ( 35023, HSIZE );
- else if ( fsize < 47000 )
- hsize = min ( 50021, HSIZE );
-
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- strcat(ofname, ".Z");
- }
- /* Check for overwrite of existing file */
- if (overwrite == 0 && zcat_flg == 0) {
- if (stat(ofname, &statbuf) == 0) {
- char response[2];
- response[0] = 'n';
- fprintf(stderr, "%s already exists;", ofname);
- if (isatty(2)) {
- 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;
- }
- }
- }
- if (response[0] != 'y') {
- fprintf(stderr, "\tnot overwritten\n");
- continue;
- }
- }
- }
- if(zcat_flg == 0) { /* Open output file */
- if (freopen(ofname, "w", stdout) == NULL) {
- perror(ofname);
- perm_stat = 1;
- continue;
- }
- precious = 0;
- if(!quiet)
- fprintf(stderr, "%s: ", *fileptr);
- }
-
- /* Actually do the compression/decompression */
- if (do_decomp == 0)
- compress();
- else
- decompress();
- if(zcat_flg == 0) {
- copystat(*fileptr, ofname); /* Copy stats */
- precious = 1;
- if((exit_stat == 1) || (!quiet))
- putc('\n', stderr);
- }
- }
- } else { /* Standard input */
- if (do_decomp == 0) {
- compress();
- if(!quiet)
- putc('\n', stderr);
- } else {
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getc(stdin)!=(magic_header[0] & 0xFF))
- || (getc(stdin)!=(magic_header[1] & 0xFF))) {
- fprintf(stderr, "stdin: not in compressed format\n");
- exit(1);
- }
- maxbits = getc(stdin); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1 << maxbits;
- fsize = 100000; /* assume stdin large for USERMEM */
- if(maxbits > BITS) {
- fprintf(stderr,
- "stdin: compressed with %d bits, can only handle %d bits\n",
- maxbits, BITS);
- exit(1);
- }
- }
- decompress();
- }
- }
- exit(perm_stat ? perm_stat : exit_stat);
- }
-
- static int offset;
- long int in_count = 1; /* length of input */
- long int bytes_out; /* length of compressed output */
- long int out_count = 0; /* # of codes output (for debugging) */
-
- /*
- * compress stdin to stdout
- *
- * Algorithm: use open addressing double hashing (no chaining) on the
- * prefix code / next character combination. We do a variant of Knuth's
- * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- * secondary probe. Here, the modular division first probe is gives way
- * to a faster exclusive-or manipulation. Also do block compression with
- * an adaptive reset, whereby the code table is cleared when the compression
- * ratio decreases, but after the table fills. The variable-length output
- * codes are re-sized at this point, and a special CLEAR code is generated
- * for the decompressor. Late addition: construct the table according to
- * file size for noticeable speed improvement on small files. Please direct
- * questions about this implementation to ames!jaw.
- */
-
- compress() {
- register long fcode;
- register code_int i = 0;
- register int c;
- register code_int ent;
- register int disp;
- register code_int hsize_reg;
- register int hshift;
-
- if (nomagic == 0) {
- putc(magic_header[0], stdout); putc(magic_header[1], stdout);
- putc((char)(maxbits | block_compress), stdout);
- if(ferror(stdout))
- writeerr();
- }
-
- offset = 0;
- bytes_out = 3; /* includes 3-byte header mojo */
- out_count = 0;
- clear_flg = 0;
- ratio = 0;
- in_count = 1;
- checkpoint = CHECK_GAP;
- maxcode = MAXCODE(n_bits = INIT_BITS);
- free_ent = ((block_compress) ? FIRST : 256 );
-
- ent = getc(stdin);
-
- hshift = 0;
- for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
- hshift++;
- hshift = 8 - hshift; /* set hash code range bound */
-
- hsize_reg = hsize;
- cl_hash( (count_int) hsize_reg); /* clear hash table */
-
- while ((c = getc(stdin)) != EOF) {
- in_count++;
- fcode = (long) (((long) c << maxbits) + ent);
- i = ((c << hshift) ^ ent); /* xor hashing */
-
- if ( htabof (i) == fcode ) {
- ent = codetabof (i);
- continue;
- } else if ((long)htabof (i) < 0) /* empty slot */
- goto nomatch;
- disp = hsize_reg - i; /* secondary hash (after G. Knott) */
- if ( i == 0 )
- disp = 1;
- probe:
- if ((i -= disp) < 0)
- i += hsize_reg;
-
- if (htabof (i) == fcode) {
- ent = codetabof (i);
- continue;
- }
- if ((long)htabof (i) > 0)
- goto probe;
- nomatch:
- output ((code_int) ent);
- out_count++;
- ent = c;
- if ( free_ent < maxmaxcode ) {
- codetabof (i) = free_ent++; /* code -> hashtable */
- htabof (i) = fcode;
- }
- else if ( (count_int)in_count >= checkpoint && block_compress )
- cl_block ();
- }
- /*
- * Put out the final code.
- */
- output((code_int)ent);
- out_count++;
- output((code_int)-1);
-
- /*
- * Print out stats on stderr
- */
- if(zcat_flg == 0 && !quiet) {
- fprintf( stderr, "Compression: " );
- prratio( stderr, in_count-bytes_out, in_count );
- }
- if(bytes_out > in_count) /* exit(2) if no savings */
- exit_stat = 2;
- return;
- }
-
- /*****************************************************************
- * TAG(output)
- *
- * Output the given code.
- * Inputs:
- * code: A n_bits-bit integer. If == -1, then EOF. This assumes
- * that n_bits =< (long)wordsize - 1.
- * Outputs:
- * Outputs code to the file.
- * Assumptions:
- * Chars are 8 bits long.
- * Algorithm:
- * Maintain a BITS character long buffer (so that 8 codes will
- * fit in it exactly). Use the VAX insv instruction to insert each
- * code in turn. When the buffer fills up empty it and start over.
- */
-
- static char buf[BITS];
-
- char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
- char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-
- output( code )
- code_int code;
- {
-
- /*
- * On the VAX, it is important to have the register declarations
- * in exactly the order given, or the asm will break.
- */
- register int r_off = offset, bits= n_bits;
- register char * bp = buf;
-
- if (code >= 0) {
- /*
- * byte/bit numbering on the VAX is simulated by the following code
- */
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /*
- * Since code is always >= 8 bits, only need to mask the first
- * hunk on the left.
- */
- *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
- bp++;
- bits -= (8 - r_off);
- code >>= 8 - r_off;
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- *bp++ = code;
- code >>= 8;
- bits -= 8;
- }
- /* Last bits. */
- if(bits)
- *bp = code;
- offset += n_bits;
- if (offset == (n_bits << 3)) {
- bp = buf;
- bits = n_bits;
- bytes_out += bits;
- do
- putc(*bp++, stdout);
- while(--bits);
- offset = 0;
- }
-
- /*
- * If the next entry is going to be too big for the code size,
- * then increase it, if possible.
- */
- if (free_ent > maxcode || (clear_flg > 0))
- {
- /*
- * Write the whole buffer, because the input side won't
- * discover the size increase until after it has read it.
- */
- if (offset > 0) {
- if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
- writeerr();
- bytes_out += n_bits;
- }
- offset = 0;
-
- if ( clear_flg ) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- }
- else {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode;
- else
- maxcode = MAXCODE(n_bits);
- }
- }
- } else {
- /*
- * At EOF, write the rest of the buffer.
- */
- if ( offset > 0 )
- fwrite( buf, 1, (offset + 7) / 8, stdout );
- bytes_out += (offset + 7) / 8;
- offset = 0;
- fflush( stdout );
- if(ferror(stdout))
- writeerr();
- }
- }
-
- /*
- * Decompress stdin to stdout. This routine adapts to the codes in the
- * file building the "string" table on-the-fly; requiring no table to
- * be stored in the compressed file. The tables used herein are shared
- * with those of the compress() routine. See the definitions above.
- */
-
- decompress() {
- register char_type *stackp;
- register int finchar;
- register code_int code, oldcode, incode;
-
- /*
- * As above, initialize the first 256 entries in the table.
- */
- maxcode = MAXCODE(n_bits = INIT_BITS);
- for ( code = 255; code >= 0; code-- ) {
- tab_prefixof(code) = 0;
- tab_suffixof(code) = (char_type)code;
- }
- free_ent = ((block_compress) ? FIRST : 256 );
-
- finchar = oldcode = getcode();
- if(oldcode == -1) /* EOF already? */
- return; /* Get out of here */
- putc((char)finchar, stdout); /* first code must be 8 bits = char */
- if(ferror(stdout)) /* Crash if can't write */
- writeerr();
- stackp = de_stack;
-
- while ((code = getcode()) > -1) {
-
- if ((code == CLEAR) && block_compress) {
- for ( code = 255; code >= 0; code-- )
- tab_prefixof(code) = 0;
- clear_flg = 1;
- free_ent = FIRST - 1;
- if ( (code = getcode ()) == -1 ) /* O, untimely death! */
- break;
- }
- incode = code;
- /*
- * Special case for KwKwK string.
- */
- if ( code >= free_ent ) {
- *stackp++ = finchar;
- code = oldcode;
- }
-
- /*
- * Generate output characters in reverse order
- */
- while ( code >= 256 ) {
- *stackp++ = tab_suffixof(code);
- code = tab_prefixof(code);
- }
- *stackp++ = finchar = tab_suffixof(code);
-
- /*
- * And put them out in forward order
- */
- do
- putc(*--stackp, stdout);
- while ( stackp > de_stack );
-
- /*
- * Generate the new entry.
- */
- if ( (code=free_ent) < maxmaxcode ) {
- tab_prefixof(code) = (unsigned short)oldcode;
- tab_suffixof(code) = finchar;
- free_ent = code+1;
- }
- /*
- * Remember previous code.
- */
- oldcode = incode;
- }
- fflush( stdout );
- if(ferror(stdout))
- writeerr();
- }
-
- /*****************************************************************
- * TAG( getcode )
- *
- * Read one code from the standard input. If EOF, return -1.
- * Inputs:
- * stdin
- * Outputs:
- * code or -1 is returned.
- */
-
- code_int
- getcode() {
- /*
- * On the VAX, it is important to have the register declarations
- * in exactly the order given, or the asm will break.
- */
- register code_int code;
- static int offset = 0, size = 0;
- static char_type buf[BITS];
- register int r_off, bits;
- register char_type *bp = buf;
-
- if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- /*
- * If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
- * a new buffer full, too.
- */
- if ( free_ent > maxcode ) {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode; /* won't get any bigger now */
- else
- maxcode = MAXCODE(n_bits);
- }
- if ( clear_flg > 0) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- }
- size = fread( buf, 1, n_bits, stdin );
- if ( size <= 0 )
- return -1; /* end of file */
- offset = 0;
- /* Round size down to integral number of codes */
- size = (size << 3) - (n_bits - 1);
- }
- r_off = offset;
- bits = n_bits;
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /* Get first part (low order bits) */
- code = (*bp++ >> r_off);
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- code |= *bp++ << r_off;
- r_off += 8;
- bits -= 8;
- }
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
- offset += n_bits;
-
- return code;
- }
-
-
- writeerr()
- {
- perror ( ofname );
- unlink ( ofname );
- exit ( 1 );
- }
-
- copystat(ifname, ofname)
- char *ifname, *ofname;
- {
- BOOL CopyFileDate();
-
- fclose(stdout);
- fclose(stdin);
- if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
- if(!quiet)
- fprintf(stderr, " -- file unchanged"), fflush(stderr);
- } else { /* ***** Successful Compression ***** */
- exit_stat = 0;
- if (CopyFileAttr(ifname, ofname) || CopyFileDate(ifname, ofname))
- fprintf(stderr, " -- couldn't copy file attributes"), fflush(stderr);
- if (unlink(ifname)) /* Remove input file */
- perror(ifname), fflush(stderr);
- else if(!quiet)
- fprintf(stderr, " -- replaced with %s", ofname), fflush(stderr);
- return; /* Successful return */
- }
-
- /* Unsuccessful return -- one of the tests failed */
- if (unlink(ofname))
- perror(ofname), fflush(stderr);
- }
-
- onintr ( )
- {
- if (!precious)
- unlink ( ofname );
- exit ( 1 );
- }
-
- oops ( ) /* wild pointer -- assume bad input */
- {
- if ( do_decomp )
- fprintf ( stderr, "uncompress: corrupt input\n" );
- unlink ( ofname );
- exit ( 1 );
- }
-
- cl_block () /* table clear for block compress */
- {
- register long int rat;
-
- checkpoint = in_count + CHECK_GAP;
-
- if(in_count > 0x007fffff) { /* shift will overflow */
- rat = bytes_out >> 8;
- if(rat == 0) { /* Don't divide by zero */
- rat = 0x7fffffff;
- } else {
- rat = in_count / rat;
- }
- } else {
- rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- }
- if ( rat > ratio ) {
- ratio = rat;
- } else {
- ratio = 0;
- cl_hash ( (count_int) hsize );
- free_ent = FIRST;
- clear_flg = 1;
- output ( (code_int) CLEAR );
- }
- }
-
- cl_hash(hsize) /* reset code table */
- register count_int hsize;
- {
- register count_int *htab_p = &htab[hsize];
- register long i;
- register long m1 = -1;
-
- i = hsize - 16;
- do { /* might use Sys V memset(3) here */
- *(htab_p-16) = m1;
- *(htab_p-15) = m1;
- *(htab_p-14) = m1;
- *(htab_p-13) = m1;
- *(htab_p-12) = m1;
- *(htab_p-11) = m1;
- *(htab_p-10) = m1;
- *(htab_p-9) = m1;
- *(htab_p-8) = m1;
- *(htab_p-7) = m1;
- *(htab_p-6) = m1;
- *(htab_p-5) = m1;
- *(htab_p-4) = m1;
- *(htab_p-3) = m1;
- *(htab_p-2) = m1;
- *(htab_p-1) = m1;
- htab_p -= 16;
- } while ((i -= 16) >= 0);
- for ( i += 16; i > 0; i-- )
- *--htab_p = m1;
- }
-
- prratio(stream, num, den)
- FILE *stream;
- long int num, den;
- {
- register int q; /* Doesn't need to be long */
-
- 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%%", q / 100, q % 100);
- }
-
- version()
- {
- fprintf(stderr, "%s, Berkeley 5.9 5/11/86\n", rcs_ident);
- fprintf(stderr, "Options: ");
- fprintf(stderr, "AMIGA, ");
- fprintf(stderr, "BITS = %d\n", BITS);
- }
-
-
-
-
- /* Function:
- * GetFileDate
- *
- * Called with:
- * name: file name
- * date: pointer to DateStamp structure
- *
- * Returns:
- * result: 1 => got a date, 0 => didn't
- *
- * Description:
- * GetFileDate attempts to get the creation/modification date
- * of a file (unfortunately, they're one and the same) and stores
- * it into the location pointed to by <date>. If the file doesn't
- * exist or for some reason the date can't be obtained, <date>
- * is set to zeros and a zero is returned. Otherwise, <date> is set
- * to the file date and a 1 is returned.
- */
-
- BOOL
- GetFileDate(name, date)
- char *name; struct DateStamp *date;
- {
- struct FileInfoBlock *Fib;
- ULONG FLock;
- int result = FALSE;
- register struct DateStamp *d;
-
- if ((FLock = (ULONG) Lock(name,(long)(ACCESS_READ)))== NULL)
- goto exit1;
-
- Fib = (struct FileInfoBlock *)
- AllocMem((long)sizeof(struct FileInfoBlock),
- (long)(MEMF_CHIP|MEMF_PUBLIC));
-
- if (Fib == NULL )
- result = FALSE;
- else{
- if (!Examine(FLock, Fib )) {
- result = FALSE;
- }
- else
- if (Fib->fib_DirEntryType > 0 )
- result = FALSE; /* It's a directory */
- else{
- d = &Fib->fib_Date;
- date->ds_Days = d->ds_Days;
- date->ds_Minute = d->ds_Minute;
- date->ds_Tick = d->ds_Tick;
- result = TRUE;
- }
- FreeMem((void *)Fib,(long)sizeof(struct FileInfoBlock));
- }
-
- UnLock(FLock);
- exit1:
- if (! result ) {
- date->ds_Days = 0;
- date->ds_Minute = 0;
- date->ds_Tick = 0;
- }
- return result;
- }
-
-
- /*---------------------------------------------------------------------*/
- /* SetFileDate: datestamp the given file with the given date. */
- /*---------------------------------------------------------------------*/
-
- #define ACTION_SETDATE_MODE 34L /* Set creation date on file */
-
- BOOL
- SetFileDate( name, date )
- char *name; struct DateStamp *date;
- {
- struct MsgPort *task; /* for process id handler */
- ULONG arg[4]; /* array of arguments */
- int nameleng;
- char *bstr, *strcpy(); /* of file to be set */
- long rc;
- char *strchr();
- int strlen();
-
- rc = 0;
-
- nameleng = strlen(name);
- if (!(bstr = (char *)AllocMem((long) (nameleng + 2),MEMF_PUBLIC)))
- goto exit2;
-
- if (!(task = (struct MsgPort *)DeviceProc(name )))
- goto exit1;
-
- /* Dos Packet needs the filename in Bstring format */
-
- (void) strcpy(bstr+1, name );
- *bstr = nameleng;
-
- arg[0]= (ULONG)NULL;
- arg[1]= (ULONG)IoErr(); /* lock on parent director set by
- DeviceProc() */
- arg[2]= (ULONG)bstr >> 2;
- arg[3]= (ULONG)date;
- rc = sendpkt(task,ACTION_SETDATE_MODE,arg,4L );
-
- exit1: if (bstr )
- FreeMem((void *)bstr, (long) (nameleng + 2));
- exit2: if (rc == DOSTRUE )
- return TRUE;
- else
- return FALSE;
- }
-
-
-
-
- /* Copy the last modified date from one file to another.
- * Called with:
- * from: name of source file
- * to: name of destination file
- * Returns:
- * 0 => success, 1 => failure
- * Note:
- * Dynamic memory allocation of the DateStamp struction is
- * necessary to insure longword alignment.
- */
-
- BOOL
- CopyFileDate(from,to)
- char *from, *to;
- {
- struct DateStamp *date;
- int status = 1; /* default is fail code */
-
- if (date = (struct DateStamp *)
- AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC)) {
- if (GetFileDate(from,date))
- if (SetFileDate(to,date))
- status = 0;
- FreeMem(date, (long) sizeof(struct DateStamp));
- }
- return status;
- }
-
-
- /****************************************************************************/
- /* Function:
- * CopyFileAttr - Copy File Attributes
- *
- * Called with:
- * srcName: source file name
- * dstName: destination file name
- *
- * Returns:
- * status where 0 => success
- *
- * Description:
- * CopyFileAttr is used by file copying functions to assign the
- * attributes of the source file to the destination file.
- */
- int
- CopyFileAttr(srcName, dstName)
- char *srcName, *dstName;
- {
- struct Lock *srcLock = NULL;
- struct FileInfoBlock *srcFIB = NULL;
- int status = 0;
-
- if (! (srcFIB = AllocMem( (long) sizeof(*srcFIB), MEMF_FAST) ) ) {
- nomem:
- status = ERROR_NO_FREE_STORE;
- goto done;
- }
-
- if (! (srcLock = (struct Lock *) Lock(srcName, ACCESS_READ) ) ) {
- err:
- status = IoErr();
- goto done;
- }
-
- if (!Examine(srcLock, srcFIB)) goto err;
- SetFileDate(dstName, &srcFIB->fib_Date);
- if (srcFIB->fib_Comment[0])
- SetComment(dstName, srcFIB->fib_Comment);
- SetProtection(dstName, srcFIB->fib_Protection);
-
- done:
- if (srcLock) UnLock(srcLock);
- if (srcFIB) FreeMem(srcFIB, (long) sizeof(*srcFIB));
- return status;
- }
-
-
- LONG
- sendpkt(id,type,args,nargs)
- struct MsgPort *id; /* process indentifier ... (handler's
- message port ) */
- LONG type, /* packet type ... (what you want
- handler to do ) */
- args[], /* a pointer to argument list */
- nargs; /* number of arguments in list */
- {
-
- struct MsgPort *replyport;
- struct StandardPacket *packet;
-
- LONG count,*pargs,res1=NULL;
-
- if (!(replyport = (struct MsgPort *) CreatePort(NULL,NULL)))
- return(NULL);
-
- packet = (struct StandardPacket *)
- AllocMem((LONG)sizeof(*packet),MEMF_PUBLIC|MEMF_CLEAR);
-
- if (packet) {
- packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);/* link packet */
- packet->sp_Pkt.dp_Link = &(packet->sp_Msg);/* to message */
- packet->sp_Pkt.dp_Port = replyport;/* set-up reply port */
- packet->sp_Pkt.dp_Type = type;/* what to do... */
-
- /* move all the arguments to the packet */
- pargs = &(packet->sp_Pkt.dp_Arg1);/* address of first argument */
- for (count=0; (count < nargs) && (count < 7); count++)
- pargs[count] = args[count];
-
- PutMsg(id,packet); /* send packet */
- WaitPort(replyport); /* wait for packet to come back */
- GetMsg(replyport); /* pull message */
-
- res1 = packet->sp_Pkt.dp_Res1;/* get result */
- FreeMem(packet,(LONG)sizeof(*packet));
-
- }
- DeletePort(replyport);
- return(res1);
- }
-
-