00001
00002
00003
00004
00005
00006 #ifdef RCSID
00007 static char rcsid[] = "$Id: unlzh.c,v 1.4 2006/11/20 08:40:34 eggert Exp $";
00008 #endif
00009
00010 #include <config.h>
00011 #include <stdio.h>
00012
00013 #include "tailor.h"
00014 #include "gzip.h"
00015 #include "lzw.h"
00016
00017
00018
00019 local unsigned decode OF((unsigned count, uch buffer[]));
00020 local void decode_start OF((void));
00021
00022
00023 local void huf_decode_start OF((void));
00024 local unsigned decode_c OF((void));
00025 local unsigned decode_p OF((void));
00026 local void read_pt_len OF((int nn, int nbit, int i_special));
00027 local void read_c_len OF((void));
00028
00029
00030 local void fillbuf OF((int n));
00031 local unsigned getbits OF((int n));
00032 local void init_getbits OF((void));
00033
00034
00035
00036 local void make_table OF((int nchar, uch bitlen[],
00037 int tablebits, ush table[]));
00038
00039
00040 #define DICBIT 13
00041 #define DICSIZ ((unsigned) 1 << DICBIT)
00042
00043 #ifndef CHAR_BIT
00044 # define CHAR_BIT 8
00045 #endif
00046
00047 #ifndef UCHAR_MAX
00048 # define UCHAR_MAX 255
00049 #endif
00050
00051 #define BITBUFSIZ (CHAR_BIT * 2 * sizeof(char))
00052
00053
00054
00055
00056
00057
00058 #define MAXMATCH 256
00059 #define THRESHOLD 3
00060
00061
00062
00063 #define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
00064
00065 #define CBIT 9
00066 #define CODE_BIT 16
00067
00068 #define NP (DICBIT + 1)
00069 #define NT (CODE_BIT + 3)
00070 #define PBIT 4
00071 #define TBIT 5
00072 #define NPT (1 << TBIT)
00073
00074
00075
00076 #define left prev
00077 #define right head
00078 #if NC > (1<<(BITS-2))
00079 error cannot overlay left+right and prev
00080 #endif
00081
00082
00083 #define c_len outbuf
00084 #if NC > OUTBUFSIZ
00085 error cannot overlay c_len and outbuf
00086 #endif
00087
00088 local uch pt_len[NPT];
00089 local unsigned blocksize;
00090 local ush pt_table[256];
00091
00092
00093 #define c_table d_buf
00094 #if (DIST_BUFSIZE-1) < 4095
00095 error cannot overlay c_table and d_buf
00096 #endif
00097
00098
00099
00100
00101
00102 local ush bitbuf;
00103 local unsigned subbitbuf;
00104 local int bitcount;
00105
00106 local void fillbuf(n)
00107 int n;
00108 {
00109 bitbuf <<= n;
00110 while (n > bitcount) {
00111 bitbuf |= subbitbuf << (n -= bitcount);
00112 subbitbuf = (unsigned)try_byte();
00113 if ((int)subbitbuf == EOF) subbitbuf = 0;
00114 bitcount = CHAR_BIT;
00115 }
00116 bitbuf |= subbitbuf >> (bitcount -= n);
00117 }
00118
00119 local unsigned getbits(n)
00120 int n;
00121 {
00122 unsigned x;
00123
00124 x = bitbuf >> (BITBUFSIZ - n); fillbuf(n);
00125 return x;
00126 }
00127
00128 local void init_getbits()
00129 {
00130 bitbuf = 0; subbitbuf = 0; bitcount = 0;
00131 fillbuf(BITBUFSIZ);
00132 }
00133
00134
00135
00136
00137
00138 local void make_table(nchar, bitlen, tablebits, table)
00139 int nchar;
00140 uch bitlen[];
00141 int tablebits;
00142 ush table[];
00143 {
00144 ush count[17], weight[17], start[18], *p;
00145 unsigned i, k, len, ch, jutbits, avail, nextcode, mask;
00146
00147 for (i = 1; i <= 16; i++) count[i] = 0;
00148 for (i = 0; i < (unsigned)nchar; i++) count[bitlen[i]]++;
00149
00150 start[1] = 0;
00151 for (i = 1; i <= 16; i++)
00152 start[i + 1] = start[i] + (count[i] << (16 - i));
00153 if ((start[17] & 0xffff) != 0)
00154 gzip_error ("Bad table\n");
00155
00156 jutbits = 16 - tablebits;
00157 for (i = 1; i <= (unsigned)tablebits; i++) {
00158 start[i] >>= jutbits;
00159 weight[i] = (unsigned) 1 << (tablebits - i);
00160 }
00161 while (i <= 16) {
00162 weight[i] = (unsigned) 1 << (16 - i);
00163 i++;
00164 }
00165
00166 i = start[tablebits + 1] >> jutbits;
00167 if (i != 0) {
00168 k = 1 << tablebits;
00169 while (i != k) table[i++] = 0;
00170 }
00171
00172 avail = nchar;
00173 mask = (unsigned) 1 << (15 - tablebits);
00174 for (ch = 0; ch < (unsigned)nchar; ch++) {
00175 if ((len = bitlen[ch]) == 0) continue;
00176 nextcode = start[len] + weight[len];
00177 if (len <= (unsigned)tablebits) {
00178 if ((unsigned) 1 << tablebits < nextcode)
00179 gzip_error ("Bad table\n");
00180 for (i = start[len]; i < nextcode; i++) table[i] = ch;
00181 } else {
00182 k = start[len];
00183 p = &table[k >> jutbits];
00184 i = len - tablebits;
00185 while (i != 0) {
00186 if (*p == 0) {
00187 right[avail] = left[avail] = 0;
00188 *p = avail++;
00189 }
00190 if (k & mask) p = &right[*p];
00191 else p = &left[*p];
00192 k <<= 1; i--;
00193 }
00194 *p = ch;
00195 }
00196 start[len] = nextcode;
00197 }
00198 }
00199
00200
00201
00202
00203
00204 local void read_pt_len(nn, nbit, i_special)
00205 int nn;
00206 int nbit;
00207 int i_special;
00208 {
00209 int i, c, n;
00210 unsigned mask;
00211
00212 n = getbits(nbit);
00213 if (n == 0) {
00214 c = getbits(nbit);
00215 for (i = 0; i < nn; i++) pt_len[i] = 0;
00216 for (i = 0; i < 256; i++) pt_table[i] = c;
00217 } else {
00218 i = 0;
00219 while (i < n) {
00220 c = bitbuf >> (BITBUFSIZ - 3);
00221 if (c == 7) {
00222 mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3);
00223 while (mask & bitbuf) { mask >>= 1; c++; }
00224 if (16 < c)
00225 gzip_error ("Bad table\n");
00226 }
00227 fillbuf((c < 7) ? 3 : c - 3);
00228 pt_len[i++] = c;
00229 if (i == i_special) {
00230 c = getbits(2);
00231 while (--c >= 0) pt_len[i++] = 0;
00232 }
00233 }
00234 while (i < nn) pt_len[i++] = 0;
00235 make_table(nn, pt_len, 8, pt_table);
00236 }
00237 }
00238
00239 local void read_c_len()
00240 {
00241 int i, c, n;
00242 unsigned mask;
00243
00244 n = getbits(CBIT);
00245 if (n == 0) {
00246 c = getbits(CBIT);
00247 for (i = 0; i < NC; i++) c_len[i] = 0;
00248 for (i = 0; i < 4096; i++) c_table[i] = c;
00249 } else {
00250 i = 0;
00251 while (i < n) {
00252 c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
00253 if (c >= NT) {
00254 mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
00255 do {
00256 if (bitbuf & mask) c = right[c];
00257 else c = left [c];
00258 mask >>= 1;
00259 } while (c >= NT);
00260 }
00261 fillbuf((int) pt_len[c]);
00262 if (c <= 2) {
00263 if (c == 0) c = 1;
00264 else if (c == 1) c = getbits(4) + 3;
00265 else c = getbits(CBIT) + 20;
00266 while (--c >= 0) c_len[i++] = 0;
00267 } else c_len[i++] = c - 2;
00268 }
00269 while (i < NC) c_len[i++] = 0;
00270 make_table(NC, c_len, 12, c_table);
00271 }
00272 }
00273
00274 local unsigned decode_c()
00275 {
00276 unsigned j, mask;
00277
00278 if (blocksize == 0) {
00279 blocksize = getbits(16);
00280 if (blocksize == 0) {
00281 return NC;
00282 }
00283 read_pt_len(NT, TBIT, 3);
00284 read_c_len();
00285 read_pt_len(NP, PBIT, -1);
00286 }
00287 blocksize--;
00288 j = c_table[bitbuf >> (BITBUFSIZ - 12)];
00289 if (j >= NC) {
00290 mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12);
00291 do {
00292 if (bitbuf & mask) j = right[j];
00293 else j = left [j];
00294 mask >>= 1;
00295 } while (j >= NC);
00296 }
00297 fillbuf((int) c_len[j]);
00298 return j;
00299 }
00300
00301 local unsigned decode_p()
00302 {
00303 unsigned j, mask;
00304
00305 j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
00306 if (j >= NP) {
00307 mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
00308 do {
00309 if (bitbuf & mask) j = right[j];
00310 else j = left [j];
00311 mask >>= 1;
00312 } while (j >= NP);
00313 }
00314 fillbuf((int) pt_len[j]);
00315 if (j != 0) j = ((unsigned) 1 << (j - 1)) + getbits((int) (j - 1));
00316 return j;
00317 }
00318
00319 local void huf_decode_start()
00320 {
00321 init_getbits(); blocksize = 0;
00322 }
00323
00324
00325
00326
00327
00328 local int j;
00329 local int done;
00330
00331 local void decode_start()
00332 {
00333 huf_decode_start();
00334 j = 0;
00335 done = 0;
00336 }
00337
00338
00339
00340 local unsigned decode(count, buffer)
00341 unsigned count;
00342 uch buffer[];
00343
00344
00345
00346
00347
00348
00349
00350
00351 {
00352 local unsigned i;
00353 unsigned r, c;
00354
00355 r = 0;
00356 while (--j >= 0) {
00357 buffer[r] = buffer[i];
00358 i = (i + 1) & (DICSIZ - 1);
00359 if (++r == count) return r;
00360 }
00361 for ( ; ; ) {
00362 c = decode_c();
00363 if (c == NC) {
00364 done = 1;
00365 return r;
00366 }
00367 if (c <= UCHAR_MAX) {
00368 buffer[r] = c;
00369 if (++r == count) return r;
00370 } else {
00371 j = c - (UCHAR_MAX + 1 - THRESHOLD);
00372 i = (r - decode_p() - 1) & (DICSIZ - 1);
00373 while (--j >= 0) {
00374 buffer[r] = buffer[i];
00375 i = (i + 1) & (DICSIZ - 1);
00376 if (++r == count) return r;
00377 }
00378 }
00379 }
00380 }
00381
00382
00383
00384
00385
00386 int unlzh(in, out)
00387 int in;
00388 int out;
00389 {
00390 unsigned n;
00391 ifd = in;
00392 ofd = out;
00393
00394 decode_start();
00395 while (!done) {
00396 n = decode((unsigned) DICSIZ, window);
00397 if (!test && n > 0) {
00398 write_buf(out, (char*)window, n);
00399 }
00400 }
00401 return OK;
00402 }