|
|
1.1 root 1: /*---------------------------------------------------------------------------
2:
3: unshrink.c
4:
5: Shrinking is a Dynamic Lempel-Ziv-Welch compression algorithm with partial
6: clearing.
7:
8: ---------------------------------------------------------------------------*/
9:
10:
11: #include "unzip.h"
12:
13:
14: /*************************************/
15: /* UnShrink Defines, Globals, etc. */
16: /*************************************/
17:
18: /* MAX_BITS 13 (in unzip.h; defines size of global work area) */
19: #define INIT_BITS 9
20: #define FIRST_ENT 257
21: #define CLEAR 256
22: #define GetCode(dest) READBIT(codesize,dest)
23:
24: static void partial_clear __((void)); /* local prototype */
25:
26: int codesize, maxcode, maxcodemax, free_ent;
27:
28:
29:
30:
31: /*************************/
32: /* Function unShrink() */
33: /*************************/
34:
35: void unShrink()
36: {
37: register int code;
38: register int stackp;
39: int finchar;
40: int oldcode;
41: int incode;
42:
43:
44: /* decompress the file */
45: codesize = INIT_BITS;
46: maxcode = (1 << codesize) - 1;
47: maxcodemax = HSIZE; /* (1 << MAX_BITS) */
48: free_ent = FIRST_ENT;
49:
50: code = maxcodemax;
51: do {
52: prefix_of[code] = -1;
53: } while (--code > 255);
54: /*
55: OvdL: -Ox with SCO's 3.2.0 cc gives
56: a. warning: overflow in constant multiplication
57: b. segmentation fault (core dumped) when using the executable
58: for (code = maxcodemax; code > 255; code--)
59: prefix_of[code] = -1;
60: */
61:
62: for (code = 255; code >= 0; code--) {
63: prefix_of[code] = 0;
64: suffix_of[code] = (byte) code;
65: }
66:
67: GetCode(oldcode);
68: if (zipeof)
69: return;
70: finchar = oldcode;
71:
72: OUTB(finchar);
73:
74: stackp = HSIZE;
75:
76: while (!zipeof) {
77: GetCode(code);
78: if (zipeof)
79: return;
80:
81: while (code == CLEAR) {
82: GetCode(code);
83: switch (code) {
84: case 1:
85: codesize++;
86: if (codesize == MAX_BITS)
87: maxcode = maxcodemax;
88: else
89: maxcode = (1 << codesize) - 1;
90: break;
91:
92: case 2:
93: partial_clear();
94: break;
95: }
96:
97: GetCode(code);
98: if (zipeof)
99: return;
100: }
101:
102:
103: /* special case for KwKwK string */
104: incode = code;
105: if (prefix_of[code] == -1) {
106: stack[--stackp] = (byte) finchar;
107: code = oldcode;
108: }
109: /* generate output characters in reverse order */
110: while (code >= FIRST_ENT) {
111: if (prefix_of[code] == -1) {
112: stack[--stackp] = (byte) finchar;
113: code = oldcode;
114: } else {
115: stack[--stackp] = suffix_of[code];
116: code = prefix_of[code];
117: }
118: }
119:
120: finchar = suffix_of[code];
121: stack[--stackp] = (byte) finchar;
122:
123:
124: /* and put them out in forward order, block copy */
125: if ((HSIZE - stackp + outcnt) < OUTBUFSIZ) {
126: memcpy(outptr, &stack[stackp], HSIZE - stackp);
127: outptr += HSIZE - stackp;
128: outcnt += HSIZE - stackp;
129: stackp = HSIZE;
130: }
131: /* output byte by byte if we can't go by blocks */
132: else
133: while (stackp < HSIZE)
134: OUTB(stack[stackp++]);
135:
136:
137: /* generate new entry */
138: code = free_ent;
139: if (code < maxcodemax) {
140: prefix_of[code] = oldcode;
141: suffix_of[code] = (byte) finchar;
142:
143: do
144: code++;
145: while ((code < maxcodemax) && (prefix_of[code] != -1));
146:
147: free_ent = code;
148: }
149: /* remember previous code */
150: oldcode = incode;
151: }
152: }
153:
154:
155:
156: /******************************/
157: /* Function partial_clear() */
158: /******************************/
159:
160: static void partial_clear()
161: {
162: register int pr;
163: register int cd;
164:
165: /* mark all nodes as potentially unused */
166: for (cd = FIRST_ENT; cd < free_ent; cd++)
167: prefix_of[cd] |= 0x8000;
168:
169: /* unmark those that are used by other nodes */
170: for (cd = FIRST_ENT; cd < free_ent; cd++) {
171: pr = prefix_of[cd] & 0x7fff; /* reference to another node? */
172: if (pr >= FIRST_ENT) /* flag node as referenced */
173: prefix_of[pr] &= 0x7fff;
174: }
175:
176: /* clear the ones that are still marked */
177: for (cd = FIRST_ENT; cd < free_ent; cd++)
178: if ((prefix_of[cd] & 0x8000) != 0)
179: prefix_of[cd] = -1;
180:
181: /* find first cleared node as next free_ent */
182: cd = FIRST_ENT;
183: while ((cd < maxcodemax) && (prefix_of[cd] != -1))
184: cd++;
185: free_ent = cd;
186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.