⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
/* *	Huffman encoding program  *	Usage:	pack [[ - ] filename ... ] filename ... *		- option: enable/disable listing of statistics */#ifndef	lintstatic char sccsid[] = "@(#)pack.c	4.1	ULTRIX	7/17/90";#endif#include  <stdio.h>#include <sys/types.h>#include <sys/stat.h>#define	END	256#if defined(u370) || defined(vax) || defined(mips)#define	BLKSIZE	4096#else#define	BLKSIZE	512#endif#define NAMELEN 80#define PACKED 017436 /* <US><RS> - Unlikely value */#define	SUF0	'.'#define	SUF1	'z'struct stat status, ostatus;/* union for overlaying a long int with a set of four characters */union FOUR {	struct { long int lng; } l_int;	struct { char c0, c1, c2, c3; } chars;};/* character counters */long	count [END+1];union	FOUR insize;long	outsize;long	dictsize;int	diffbytes;/* i/o stuff */char	vflag = 0;int	force = 0;	/* allow forced packing for consistency in directory */char	filename [NAMELEN];int	infile;		/* unpacked file */int	outfile;	/* packed file */char	inbuff [BLKSIZE];char	outbuff [BLKSIZE+4];/* variables associated with the tree */int	maxlev;int	levcount [25];int	lastnode;int	parent [2*END+1];/* variables associated with the encoding process */char	length [END+1];long	bits [END+1];union	FOUR mask;long	inc;#if defined(vax) || defined(mips)char	*maskshuff[4]  = {&(mask.chars.c3), &(mask.chars.c2), &(mask.chars.c1), &(mask.chars.c0)};#else#ifdef pdp11char	*maskshuff[4]  = {&(mask.chars.c1), &(mask.chars.c0), &(mask.chars.c3), &(mask.chars.c2)};#else	/* u370 or 3b20 */char	*maskshuff[4]  = {&(mask.chars.c0), &(mask.chars.c1), &(mask.chars.c2), &(mask.chars.c3)};#endif#endif/* the heap */int	n;struct	heap {	long int count;	int node;} heap [END+2];#define hmove(a,b) {(b).count = (a).count; (b).node = (a).node;}/* gather character frequency statistics *//* return 1 if successful, 0 otherwise */input (){	register int i;	for (i=0; i<END; i++)		count[i] = 0;	while ((i = read(infile, inbuff, BLKSIZE)) > 0)		while (i > 0)			count[inbuff[--i]&0377] += 2;	if (i == 0)		return (1);	(void) printf (": read error");	return (0);}/* encode the current file *//* return 1 if successful, 0 otherwise */output (){	int c, i, inleft;	char *inp;	register char **q, *outp;	register int bitsleft;	long temp;	long lseek();	/* output ``PACKED'' header */	outbuff[0] = 037; 	/* ascii US */	outbuff[1] = 036; 	/* ascii RS */	/* output the length and the dictionary */	temp = insize.l_int.lng;	for (i=5; i>=2; i--) {		outbuff[i] =  (char) (temp & 0377);		temp >>= 8;	}	outp = &outbuff[6];	*outp++ = maxlev;	for (i=1; i<maxlev; i++)		*outp++ = levcount[i];	*outp++ = levcount[maxlev]-2;	for (i=1; i<=maxlev; i++)		for (c=0; c<END; c++)			if (length[c] == i)				*outp++ = c;	dictsize = outp-&outbuff[0];	/* output the text */	if (lseek(infile, 0L, 0) == -1L) {		(void) printf (": input seek error\n");		return(0);	}	outsize = 0;	bitsleft = 8;	inleft = 0;	do {		if (inleft <= 0) {			inleft = read(infile, inp = &inbuff[0], BLKSIZE);			if (inleft < 0) {				(void) printf (": read error");				return (0);			}		}		c = (--inleft < 0) ? END : (*inp++ & 0377);		mask.l_int.lng = bits[c]<<bitsleft;		q = &maskshuff[0];		if (bitsleft == 8)			*outp = **q++;		else			*outp |= **q++;		bitsleft -= length[c];		while (bitsleft < 0) {			*++outp = **q++;			bitsleft += 8;		}		if (outp >= &outbuff[BLKSIZE]) {			if (write(outfile, outbuff, BLKSIZE) != BLKSIZE) {wrerr:				(void) printf (".z: write error");				return (0);			}			((union FOUR *) outbuff)->l_int.lng = ((union FOUR *) &outbuff[BLKSIZE])->l_int.lng;			outp -= BLKSIZE;			outsize += BLKSIZE;		}	} while (c != END);	if (bitsleft < 8)		outp++;	c = outp-outbuff;	if (write(outfile, outbuff, c) != c)		goto wrerr;	outsize += c;	return (1);}/* makes a heap out of heap[i],...,heap[n] */heapify (i){	register int k;	int lastparent;	struct heap heapsubi;	hmove (heap[i], heapsubi);	lastparent = n/2;	while (i <= lastparent) {		k = 2*i;		if (heap[k].count > heap[k+1].count && k < n)			k++;		if (heapsubi.count < heap[k].count)			break;		hmove (heap[k], heap[i]);		i = k;	}	hmove (heapsubi, heap[i]);}/* return 1 after successful packing, 0 otherwise */int packfile (){	register int c, i, p;	long bitsout;	/* gather frequency statistics */	if (input() == 0)		return (0);	/* put occurring chars in heap with their counts */	diffbytes = -1;	count[END] = 1;	insize.l_int.lng = n = 0;	for (i=END; i>=0; i--) {		parent[i] = 0;		if (count[i] > 0) {			diffbytes++;			insize.l_int.lng += count[i];			heap[++n].count = count[i];			heap[n].node = i;		}	}	if (diffbytes == 1) {		(void) printf (": trivial file");		return (0);	}	insize.l_int.lng >>= 1;	for (i=n/2; i>=1; i--)		heapify(i);	/* build Huffman tree */	lastnode = END;	while (n > 1) {		parent[heap[1].node] = ++lastnode;		inc = heap[1].count;		hmove (heap[n], heap[1]);		n--;		heapify(1);		parent[heap[1].node] = lastnode;		heap[1].node = lastnode;		heap[1].count += inc;		heapify(1);	}	parent[lastnode] = 0;	/* assign lengths to encoding for each character */	bitsout = maxlev = 0;	for (i=1; i<=24; i++)		levcount[i] = 0;	for (i=0; i<=END; i++) {		c = 0;		for (p=parent[i]; p!=0; p=parent[p])			c++;		levcount[c]++;		length[i] = c;		if (c > maxlev)			maxlev = c;		bitsout += c*(count[i]>>1);	}	if (maxlev > 24) {		/* can't occur unless insize.l_int.lng >= 2**24 */		(void) printf (": Huffman tree has too many levels");		return(0);	}	/* don't bother if no compression results */	outsize = ((bitsout+7)>>3)+6+maxlev+diffbytes;	if ((insize.l_int.lng+BLKSIZE-1)/BLKSIZE <= (outsize+BLKSIZE-1)/BLKSIZE	    && !force) {		(void) printf (": no saving");		return(0);	}	/* compute bit patterns for each character */	inc = 1L << 24;	inc >>= maxlev;	mask.l_int.lng = 0;	for (i=maxlev; i>0; i--) {		for (c=0; c<=END; c++)			if (length[c] == i) {				bits[c] = mask.l_int.lng;				mask.l_int.lng += inc;			}		mask.l_int.lng &= ~inc;		inc <<= 1;	}	return (output());}main(argc, argv)int argc; char *argv[];{	register int i;	register char *cp;	int k, sep;	int fcount =0; /* count failures */	time_t	ftimes[2];	for (k=1; k<argc; k++) {		if (argv[k][0] == '-' && argv[k][1] == '\0') {			vflag = 1 - vflag;			continue;		}		if (argv[k][0] == '-' && argv[k][1] == 'f') {			force++;			continue;		}		fcount++; /* increase failure count - expect the worst */		(void) printf ("%s: %s", argv[0], argv[k]);		sep = -1;  cp = filename;		for (i=0; i < (NAMELEN-3) && (*cp = argv[k][i]); i++)			if (*cp++ == '/') sep = i;		if (cp[-1]==SUF1 && cp[-2]==SUF0) {			(void) printf (": already packed\n");			continue;		}		if (i >= (NAMELEN-3) || (i-sep) > 13) {			(void) printf (": file name too long\n");			continue;		}		if ((infile = open (filename, 0)) < 0) {			(void) printf (": cannot open\n");			continue;		}		if (fstat(infile,&status) == -1) {			(void) printf(": cannot stat\n");			goto closein;		}		if (status.st_mode&040000) {			(void) printf (": cannot pack a directory\n");			goto closein;		}		if( status.st_nlink != 1 ) {			(void) printf(": has links\n");			goto closein;		}		*cp++ = SUF0;  *cp++ = SUF1;  *cp = '\0';		if( stat(filename, &ostatus) != -1) {			(void) printf(".z: already exists\n");			goto closein;		}		if ((outfile = creat (filename, (int) status.st_mode&07777)) < 0) {			(void) printf (".z: cannot create\n");			goto closein;		}		if (chmod (filename, (int) status.st_mode) != 0)			(void) printf("can't change mode to %o\n", status.st_mode);/*	We can't do this indiscriminately like System V can, so try it,	but ignore failures. */		if (chown (filename, status.st_uid, status.st_gid) != 0)/*			(void) printf("can't change owner\n") */			;		if (packfile()) {			if (unlink(argv[k]) != 0)				(void) fprintf(stderr, "%s: can't unlink %s\n",					argv[0], argv[k]);			fcount--;  /* success after all */			(void) printf (": %.1f%% Compression\n",				((double)(-outsize+(insize.l_int.lng))/(double)insize.l_int.lng)*100);			/* output statistics */			if (vflag) {				(void) printf("	from %ld to %ld bytes\n",  insize.l_int.lng, outsize);				(void) printf("	Huffman tree has %d levels below root\n", maxlev);				(void) printf("	%d distinct bytes in input\n", diffbytes);				(void) printf("	dictionary overhead = %ld bytes\n", dictsize);				(void) printf("	effective  entropy  = %.2f bits/byte\n", 					((double) outsize / (double) insize.l_int.lng) * 8 );				(void) printf("	asymptotic entropy  = %.2f bits/byte\n", 					((double) (outsize-dictsize) / (double) insize.l_int.lng) * 8 );			}		}		else		{       (void) printf (" - file unchanged\n");			(void) unlink(filename);		}      closein:	(void) close (outfile);		(void) close (infile);		ftimes[0] = status.st_atime;		ftimes[1] = status.st_mtime;		(void) utime(filename, ftimes);/* preserve acc & mod times */	}	return (fcount);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -