1 /*
2  * $Header: /cvsroot/arc/arc/arcusq.c,v 1.2 2003/10/31 02:22:36 highlandsun Exp $
3  */
4 
5 /*
6  * ARC - Archive utility - ARCUSQ
7  *
8  * Version 3.14, created on 07/25/86 at 13:04:19
9  *
10  * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
11  *
12  * By:	Thom Henderson
13  *
14  * Description: This file contains the routines used to expand a file which was
15  * packed using Huffman squeezing.
16  *
17  * Most of this code is taken from an USQ program by Richard Greenlaw, which was
18  * adapted to CI-C86 by Robert J. Beilstein.
19  *
20  * Language: Computer Innovations Optimizing C86
21  */
22 #include <stdio.h>
23 #include "arc.h"
24 
25 #include "proto.h"
26 
27 VOID		arcdie();
28 
29 /* stuff for Huffman unsqueezing */
30 
31 #define ERROR (-1)
32 
33 #define SPEOF 256		/* special endfile token */
34 #define NUMVALS 257		/* 256 data values plus SPEOF */
35 
36 extern struct nd {		/* decoding tree */
37 	int		child[2];	/* left, right */
38 }		node[NUMVALS];	/* use large buffer */
39 
40 extern char	*pinbuf;
41 extern u_char	*outbuf, *outbeg, *outend;
42 
43 static int	bpos;		/* last bit position read */
44 extern int	curin;		/* last byte value read */
45 static int	numnodes;	/* number of nodes in decode tree */
46 
47 extern char  *inbeg, *inend;
48 
49 /* get a 16bit integer */
50 #define GET_INT(x)	\
51 {	x = (u_char) (*inbeg++); \
52 	x |= *inbeg++ << 8;}
53 
54 VOID
init_usq(f)55 init_usq(f)			/* initialize Huffman unsqueezing */
56 	FILE	       *f;	/* file containing squeezed data */
57 {
58 	int		i;	/* node index */
59 	u_int		inlen;
60 
61 	bpos = 99;		/* force initial read */
62 
63 	inlen = getb_unp(f);
64 	inbeg = pinbuf;
65 	inend = &pinbuf[inlen];
66 
67 	GET_INT(numnodes);
68 
69 	if (numnodes < 0 || numnodes >= NUMVALS)
70 		arcdie("File has an invalid decode tree");
71 
72 	/* initialize for possible empty tree (SPEOF only) */
73 
74 	node[0].child[0] = -(SPEOF + 1);
75 	node[0].child[1] = -(SPEOF + 1);
76 
77 	for (i = 0; i < numnodes; ++i) {	/* get decoding tree from
78 						 * file */
79 		GET_INT(node[i].child[0]);
80 		GET_INT(node[i].child[1]);
81 	}
82 }
83 
84 u_int
getb_usq(f)85 getb_usq(f)			/* get byte from squeezed file */
86 	FILE	       *f;	/* file containing squeezed data */
87 {
88 	int		i;	/* tree index */
89 	u_int		j;
90 
91 	outbeg = outbuf;
92 	for (j = 0; j < MYBUF; j++) {
93 		/* follow bit stream in tree to a leaf */
94 
95 		for (i = 0; i >= 0;) {	/* work down(up?) from root */
96 			if (++bpos > 7) {
97 				if (inbeg >= inend) {
98 					inend = &pinbuf[getb_unp(f)];
99 					inbeg = pinbuf;
100 					if (inend == inbeg) {
101 						if (!curin)
102 							j--;
103 						return(j);
104 					}
105 				}
106 				curin = *inbeg++;
107 				bpos = 0;
108 
109 				/* move a level deeper in tree */
110 				i = node[i].child[1 & curin];
111 			} else
112 				i = node[i].child[1 & (curin >>= 1)];
113 		}
114 
115 		/* decode fake node index to original data value */
116 
117 		i = -(i + 1);
118 
119 		if (i != SPEOF)
120 			*outbeg++ = i;
121 		else
122 			break;
123 	}
124 	/*NOTREACHED*/
125 	return (j);
126 }
127