📄 compress.c
字号:
writeerr();}/***************************************************************** * TAG( getcode ) * * Read one code from the standard input. If EOF, return -1. * Inputs: * stdin * Outputs: * code or -1 is returned. */code_intgetcode() { /* * 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;}#ifdef DEBUGprintcodes(){ /* * Just print out codes from input file. For debugging. */ code_int code; int col = 0, bits; bits = n_bits = INIT_BITS; maxcode = MAXCODE(n_bits); free_ent = ((block_compress) ? FIRST : 256 ); while ( ( code = getcode() ) >= 0 ) { if ( (code == CLEAR) && block_compress ) { free_ent = FIRST - 1; clear_flg = 1; } else if ( free_ent < maxmaxcode ) free_ent++; if ( bits != n_bits ) { fprintf(stderr, "\nChange to %d bits\n", n_bits ); bits = n_bits; col = 0; } fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' ); } putc( '\n', stderr ); exit( 0 );}code_int sorttab[1<<BITS]; /* sorted pointers into htab */dump_tab() /* dump string table */{ register int i, first; register ent;#define STACK_SIZE 15000 int stack_top = STACK_SIZE; register c; if(do_decomp == 0) { /* compressing */ register int flag = 1; for(i=0; i<hsize; i++) { /* build sort pointers */ if((long)htabof(i) >= 0) { sorttab[codetabof(i)] = i; } } first = block_compress ? FIRST : 256; for(i = first; i < free_ent; i++) { fprintf(stderr, "%5d: \"", i); de_stack[--stack_top] = '\n'; de_stack[--stack_top] = '"'; stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, stack_top); for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1); ent > 256; ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) { stack_top = in_stack(htabof(sorttab[ent]) >> maxbits, stack_top); } stack_top = in_stack(ent, stack_top); fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr); stack_top = STACK_SIZE; } } else if(!debug) { /* decompressing */ for ( i = 0; i < free_ent; i++ ) { ent = i; c = tab_suffixof(ent); if ( isascii(c) && isprint(c) ) fprintf( stderr, "%5d: %5d/'%c' \"", ent, tab_prefixof(ent), c ); else fprintf( stderr, "%5d: %5d/\\%03o \"", ent, tab_prefixof(ent), c ); de_stack[--stack_top] = '\n'; de_stack[--stack_top] = '"'; for ( ; ent != NULL; ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) { stack_top = in_stack(tab_suffixof(ent), stack_top); } fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr ); stack_top = STACK_SIZE; } }}intin_stack(c, stack_top) register c, stack_top;{ if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) { de_stack[--stack_top] = c; } else { switch( c ) { case '\n': de_stack[--stack_top] = 'n'; break; case '\t': de_stack[--stack_top] = 't'; break; case '\b': de_stack[--stack_top] = 'b'; break; case '\f': de_stack[--stack_top] = 'f'; break; case '\r': de_stack[--stack_top] = 'r'; break; case '\\': de_stack[--stack_top] = '\\'; break; default: de_stack[--stack_top] = '0' + c % 8; de_stack[--stack_top] = '0' + (c / 8) % 8; de_stack[--stack_top] = '0' + c / 64; break; } de_stack[--stack_top] = '\\'; } return stack_top;}#endif /* DEBUG */voidwriteerr(){ perror ( ofname ); unlink ( ofname ); exit ( 1 );}voidcopystat(ifname, ofname)char *ifname, *ofname;{ struct stat statbuf; mode_t mode; struct utimbuf timep; fclose(stdout); if (lstat(ifname, &statbuf)) { /* Get stat on input file */ perror(ifname); return; } if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) { if(quiet) fprintf(stderr, "%s: ", ifname); fprintf(stderr, " -- not a regular file: unchanged"); exit_stat = 1; perm_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; perm_stat = 1; } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */ fprintf(stderr, " -- file unchanged"); } else { /* ***** Successful Compression ***** */ exit_stat = 0; mode = statbuf.st_mode & 07777; if (chmod(ofname, mode)) /* Copy modes */ perror(ofname); chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ timep.actime = statbuf.st_atime; timep.modtime = statbuf.st_mtime; utime(ofname, &timep); /* Update last accessed and modified times */ 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);}voidonintr ( ){ if (!precious) unlink ( ofname ); if (Pflag) unlink ( ctmp ); exit ( 1 );}voidoops ( ) /* wild pointer -- assume bad input */{ if ( do_decomp ) fprintf ( stderr, "uncompress: corrupt input\n" ); unlink ( ofname ); if (Pflag) unlink ( ctmp ); exit ( 1 );}voidcl_block () /* table clear for block compress */{ register long int rat; checkpoint = in_count + CHECK_GAP;#ifdef DEBUG if ( debug ) { fprintf ( stderr, "count: %ld, ratio: ", in_count ); prratio ( stderr, in_count, bytes_out ); fprintf ( stderr, "\n"); }#endif /* DEBUG */ 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;#ifdef DEBUG if(verbose) dump_tab(); /* dump string table */#endif cl_hash ( (count_int) hsize ); free_ent = FIRST; clear_flg = 1; output ( (code_int) CLEAR );#ifdef DEBUG if(debug) fprintf ( stderr, "clear\n" );#endif /* DEBUG */ }}voidcl_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;}voidprratio(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);}/* do_Pflag *//* Read file names from the pipe and compress/decompress them *//* overwriting the original file. *//* Note: <stdio.h> defined BUFSIZ chunks are read from the pipe. *//* Programs using the -P option should write in BUFSIZ chunks. */voiddo_Pflag() { char namebuf[BUFSIZ]; /* Buffer for fnames passed through pipe. */ struct utimbuf timep; char lng_ctmp[100], *dirname(); struct stat statbuf; /* A NULL, EOF or broken pipe will break loop. */ while (read(rpipe, namebuf, sizeof(namebuf)) > 0) { if(namebuf[0] == '\0') break; /* Open input file */ if ((freopen(namebuf, "r", stdin)) == NULL) { perror(namebuf); continue; } if (stat( namebuf, &statbuf ) < 0) { perror(namebuf); continue; } if (do_decomp) { /* DECOMPRESSION */ /* Check the magic number */ if (nomagic == 0) { if ((getchar() != (magic_header[0] & 0xFF)) || (getchar() != (magic_header[1] & 0xFF))) { /* File not in compressed format. No problem. */ continue; } maxbits = getchar(); /* 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", namebuf, maxbits, BITS); continue; } } } else { /* COMPRESSION */ fsize = (long) statbuf.st_size; /* * tune hash table size for small files -- as below */ 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 ); } /* Add full path to ctmp. */ sprintf(lng_ctmp, "%s%s", dirname(namebuf), ctmp); /* Set output filename to ctmp. */ if (freopen(lng_ctmp, "w", stdout) == NULL) { perror(ctmp); continue; } /* Do actual compress/decompress. */ if (do_decomp) decompress(); else compress(); fflush(stdout); /* Remove input file. */ if (unlink(namebuf)) perror(namebuf); /* Link tmp file to input filename. */ if( (link(lng_ctmp, namebuf)) < 0) { perror(namebuf); fprintf(stderr, "Compress: Cannot link tmp to %s\n",namebuf); } /* Always unlink tmp file. */ unlink(lng_ctmp); /* Set time, mode and ownership for new file. */ timep.actime = time((long *) 0); timep.modtime = statbuf.st_mtime; utime(namebuf, &timep); chmod(namebuf, statbuf.st_mode); chown(namebuf, statbuf.st_uid, statbuf.st_gid); } /* Make sure tmp is gone. */ unlink(lng_ctmp); exit(0);}/* dirname *//* Return the directory portion of lname. *//* */char *dirname(lname)char *lname;{ char *cp, *end; static char buf[100]; if (lname[0] == '/' || lname[1] == '/') strcpy(buf, lname); else { strcpy(buf, "./"); strcat(buf, lname); } end = &buf[strlen(buf)]; for(cp = end; *cp != '/'; cp--); *(cp+1)='\0'; return(buf);}voidversion(){ fprintf(stderr, "%s, Berkeley 5.9 5/11/86\n", rcs_ident); fprintf(stderr, "Options: ");#ifdef DEBUG fprintf(stderr, "DEBUG, ");#endif fprintf(stderr, "BITS = %d\n", BITS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -