1 /* gzcompress.h -- definitions for the .Z decompression routine used in CFITSIO */
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <ctype.h>
7
8 #define get_char() get_byte()
9
10 /* gzip.h -- common declarations for all gzip modules */
11
12 #define OF(args) args
13 typedef void *voidp;
14
15 #define memzero(s, n) memset ((voidp)(s), 0, (n))
16
17 typedef unsigned char uch;
18 typedef unsigned short ush;
19 typedef unsigned long ulg;
20
21 /* private version of MIN function */
22 #define MINZIP(a,b) ((a) <= (b) ? (a) : (b))
23
24 /* Return codes from gzip */
25 #define OK 0
26 #define ERROR 1
27 #define COMPRESSED 1
28 #define DEFLATED 8
29 #define INBUFSIZ 0x8000 /* input buffer size */
30 #define INBUF_EXTRA 64 /* required by unlzw() */
31 #define OUTBUFSIZ 16384 /* output buffer size */
32 #define OUTBUF_EXTRA 2048 /* required by unlzw() */
33 #define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
34 #define WSIZE 0x8000 /* window size--must be a power of two, and */
35 #define DECLARE(type, array, size) type array[size]
36 #define tab_suffix window
37 #define tab_prefix prev /* hash link (see deflate.c) */
38 #define head (prev+WSIZE) /* hash head (see deflate.c) */
39 #define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
40 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
41
42 /* Diagnostic functions */
43 # define Assert(cond,msg)
44 # define Trace(x)
45 # define Tracev(x)
46 # define Tracevv(x)
47 # define Tracec(c,x)
48 # define Tracecv(c,x)
49
50 /* lzw.h -- define the lzw functions. */
51
52 #ifndef BITS
53 # define BITS 16
54 #endif
55 #define INIT_BITS 9 /* Initial number of bits per code */
56 #define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
57 #define BLOCK_MODE 0x80
58 #define LZW_RESERVED 0x60 /* reserved bits */
59 #define CLEAR 256 /* flush the dictionary */
60 #define FIRST (CLEAR+1) /* first free entry */
61
62 /* prototypes */
63
64 #define local static
65 void ffpmsg(const char *err_message);
66
67 local int fill_inbuf OF((int eof_ok));
68 local void write_buf OF((voidp buf, unsigned cnt));
69 local void error OF((char *m));
70 local int unlzw OF((FILE *in, FILE *out));
71
72 typedef int file_t; /* Do not use stdio */
73
74 int (*work) OF((FILE *infile, FILE *outfile)) = unlzw; /* function to call */
75
76 local void error OF((char *m));
77
78 /* global buffers */
79
80 static DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
81 static DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
82 static DECLARE(ush, d_buf, DIST_BUFSIZE);
83 static DECLARE(uch, window, 2L*WSIZE);
84
85 #ifndef MAXSEG_64K
86 static DECLARE(ush, tab_prefix, 1L<<BITS);
87 #else
88 static DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
89 static DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
90 #endif
91
92 /* local variables */
93
94 /* 11/25/98: added 'static' to local variable definitions, to avoid */
95 /* conflict with external source files */
96
97 static int maxbits = BITS; /* max bits per code for LZW */
98 static int method = DEFLATED;/* compression method */
99 static int exit_code = OK; /* program exit code */
100 static int last_member; /* set for .zip and .Z files */
101 static long bytes_in; /* number of input bytes */
102 static long bytes_out; /* number of output bytes */
103 static char ifname[128]; /* input file name */
104 static FILE *ifd; /* input file descriptor */
105 static FILE *ofd; /* output file descriptor */
106 static void **memptr; /* memory location for uncompressed file */
107 static size_t *memsize; /* size (bytes) of memory allocated for file */
108 void *(*realloc_fn)(void *p, size_t newsize); /* reallocation function */
109 static unsigned insize; /* valid bytes in inbuf */
110 static unsigned inptr; /* index of next byte to be processed in inbuf */
111
112 /* prototype for the following functions */
113 int zuncompress2mem(char *filename,
114 FILE *diskfile,
115 char **buffptr,
116 size_t *buffsize,
117 void *(*mem_realloc)(void *p, size_t newsize),
118 size_t *filesize,
119 int *status);
120
121 /*--------------------------------------------------------------------------*/
zuncompress2mem(char * filename,FILE * indiskfile,char ** buffptr,size_t * buffsize,void * (* mem_realloc)(void * p,size_t newsize),size_t * filesize,int * status)122 int zuncompress2mem(char *filename, /* name of input file */
123 FILE *indiskfile, /* I - file pointer */
124 char **buffptr, /* IO - memory pointer */
125 size_t *buffsize, /* IO - size of buffer, in bytes */
126 void *(*mem_realloc)(void *p, size_t newsize), /* function */
127 size_t *filesize, /* O - size of file, in bytes */
128 int *status) /* IO - error status */
129
130 /*
131 Uncompress the file into memory. Fill whatever amount of memory has
132 already been allocated, then realloc more memory, using the supplied
133 input function, if necessary.
134 */
135 {
136 char magic[2]; /* magic header */
137
138 if (*status > 0)
139 return(*status);
140
141 /* save input parameters into global variables */
142 ifname[0] = '\0';
143 strncat(ifname, filename, 127);
144 ifd = indiskfile;
145 memptr = (void **) buffptr;
146 memsize = buffsize;
147 realloc_fn = mem_realloc;
148
149 /* clear input and output buffers */
150
151 insize = inptr = 0;
152 bytes_in = bytes_out = 0L;
153
154 magic[0] = (char)get_byte();
155 magic[1] = (char)get_byte();
156
157 if (memcmp(magic, LZW_MAGIC, 2) != 0) {
158 error("ERROR: input .Z file is in unrecognized compression format.\n");
159 return(-1);
160 }
161
162 work = unlzw;
163 method = COMPRESSED;
164 last_member = 1;
165
166 /* do the uncompression */
167 if ((*work)(ifd, ofd) != OK) {
168 method = -1; /* force cleanup */
169 *status = 414; /* report some sort of decompression error */
170 }
171
172 if (filesize) *filesize = bytes_out;
173
174 return(*status);
175 }
176 /*=========================================================================*/
177 /*=========================================================================*/
178 /* this marks the begining of the original file 'unlzw.c' */
179 /*=========================================================================*/
180 /*=========================================================================*/
181
182 /* unlzw.c -- decompress files in LZW format.
183 * The code in this file is directly derived from the public domain 'compress'
184 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
185 * Ken Turkowski, Dave Mack and Peter Jannesen.
186 */
187
188 typedef unsigned char char_type;
189 typedef long code_int;
190 typedef unsigned long count_int;
191 typedef unsigned short count_short;
192 typedef unsigned long cmp_code_int;
193
194 #define MAXCODE(n) (1L << (n))
195
196 #ifndef REGISTERS
197 # define REGISTERS 2
198 #endif
199 #define REG1
200 #define REG2
201 #define REG3
202 #define REG4
203 #define REG5
204 #define REG6
205 #define REG7
206 #define REG8
207 #define REG9
208 #define REG10
209 #define REG11
210 #define REG12
211 #define REG13
212 #define REG14
213 #define REG15
214 #define REG16
215 #if REGISTERS >= 1
216 # undef REG1
217 # define REG1 register
218 #endif
219 #if REGISTERS >= 2
220 # undef REG2
221 # define REG2 register
222 #endif
223 #if REGISTERS >= 3
224 # undef REG3
225 # define REG3 register
226 #endif
227 #if REGISTERS >= 4
228 # undef REG4
229 # define REG4 register
230 #endif
231 #if REGISTERS >= 5
232 # undef REG5
233 # define REG5 register
234 #endif
235 #if REGISTERS >= 6
236 # undef REG6
237 # define REG6 register
238 #endif
239 #if REGISTERS >= 7
240 # undef REG7
241 # define REG7 register
242 #endif
243 #if REGISTERS >= 8
244 # undef REG8
245 # define REG8 register
246 #endif
247 #if REGISTERS >= 9
248 # undef REG9
249 # define REG9 register
250 #endif
251 #if REGISTERS >= 10
252 # undef REG10
253 # define REG10 register
254 #endif
255 #if REGISTERS >= 11
256 # undef REG11
257 # define REG11 register
258 #endif
259 #if REGISTERS >= 12
260 # undef REG12
261 # define REG12 register
262 #endif
263 #if REGISTERS >= 13
264 # undef REG13
265 # define REG13 register
266 #endif
267 #if REGISTERS >= 14
268 # undef REG14
269 # define REG14 register
270 #endif
271 #if REGISTERS >= 15
272 # undef REG15
273 # define REG15 register
274 #endif
275 #if REGISTERS >= 16
276 # undef REG16
277 # define REG16 register
278 #endif
279
280 #ifndef BYTEORDER
281 # define BYTEORDER 0000
282 #endif
283
284 #ifndef NOALLIGN
285 # define NOALLIGN 0
286 #endif
287
288
289 union bytes {
290 long word;
291 struct {
292 #if BYTEORDER == 4321
293 char_type b1;
294 char_type b2;
295 char_type b3;
296 char_type b4;
297 #else
298 #if BYTEORDER == 1234
299 char_type b4;
300 char_type b3;
301 char_type b2;
302 char_type b1;
303 #else
304 # undef BYTEORDER
305 int dummy;
306 #endif
307 #endif
308 } bytes;
309 };
310
311 #if BYTEORDER == 4321 && NOALLIGN == 1
312 # define input(b,o,c,n,m){ \
313 (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
314 (o) += (n); \
315 }
316 #else
317 # define input(b,o,c,n,m){ \
318 REG1 char_type *p = &(b)[(o)>>3]; \
319 (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
320 ((long)(p[2])<<16))>>((o)&0x7))&(m); \
321 (o) += (n); \
322 }
323 #endif
324
325 #ifndef MAXSEG_64K
326 /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
327 # define tab_prefixof(i) tab_prefix[i]
328 # define clear_tab_prefixof() memzero(tab_prefix, 256);
329 #else
330 /* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
331 /* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd codes */
332 ush *tab_prefix[2];
333 # define tab_prefixof(i) tab_prefix[(i)&1][(i)>>1]
334 # define clear_tab_prefixof() \
335 memzero(tab_prefix0, 128), \
336 memzero(tab_prefix1, 128);
337 #endif
338 #define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
339 #define tab_suffixof(i) tab_suffix[i]
340
341 int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
342
343 /* ============================================================================
344 * Decompress in to out. This routine adapts to the codes in the
345 * file building the "string" table on-the-fly; requiring no table to
346 * be stored in the compressed file.
347 * IN assertions: the buffer inbuf contains already the beginning of
348 * the compressed data, from offsets iptr to insize-1 included.
349 * The magic header has already been checked and skipped.
350 * bytes_in and bytes_out have been initialized.
351 */
unlzw(FILE * in,FILE * out)352 local int unlzw(FILE *in, FILE *out)
353 /* input and output file descriptors */
354 {
355 REG2 char_type *stackp;
356 REG3 code_int code;
357 REG4 int finchar;
358 REG5 code_int oldcode;
359 REG6 code_int incode;
360 REG7 long inbits;
361 REG8 long posbits;
362 REG9 int outpos;
363 /* REG10 int insize; (global) */
364 REG11 unsigned bitmask;
365 REG12 code_int free_ent;
366 REG13 code_int maxcode;
367 REG14 code_int maxmaxcode;
368 REG15 int n_bits;
369 REG16 int rsize;
370
371 ofd = out;
372
373 #ifdef MAXSEG_64K
374 tab_prefix[0] = tab_prefix0;
375 tab_prefix[1] = tab_prefix1;
376 #endif
377 maxbits = get_byte();
378 block_mode = maxbits & BLOCK_MODE;
379 if ((maxbits & LZW_RESERVED) != 0) {
380 error( "warning, unknown flags in unlzw decompression");
381 }
382 maxbits &= BIT_MASK;
383 maxmaxcode = MAXCODE(maxbits);
384
385 if (maxbits > BITS) {
386 error("compressed with too many bits; cannot handle file");
387 exit_code = ERROR;
388 return ERROR;
389 }
390 rsize = insize;
391 maxcode = MAXCODE(n_bits = INIT_BITS)-1;
392 bitmask = (1<<n_bits)-1;
393 oldcode = -1;
394 finchar = 0;
395 outpos = 0;
396 posbits = inptr<<3;
397
398 free_ent = ((block_mode) ? FIRST : 256);
399
400 clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
401
402 for (code = 255 ; code >= 0 ; --code) {
403 tab_suffixof(code) = (char_type)code;
404 }
405 do {
406 REG1 int i;
407 int e;
408 int o;
409
410 resetbuf:
411 e = insize-(o = (posbits>>3));
412
413 for (i = 0 ; i < e ; ++i) {
414 inbuf[i] = inbuf[i+o];
415 }
416 insize = e;
417 posbits = 0;
418
419 if (insize < INBUF_EXTRA) {
420 /* modified to use fread instead of read - WDP 10/22/97 */
421 /* if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) { */
422
423 if ((rsize = fread((char*)inbuf+insize, 1, INBUFSIZ, in)) == EOF) {
424 error("unexpected end of file");
425 exit_code = ERROR;
426 return ERROR;
427 }
428 insize += rsize;
429 bytes_in += (ulg)rsize;
430 }
431 inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
432 ((long)insize<<3)-(n_bits-1));
433
434 while (inbits > posbits) {
435 if (free_ent > maxcode) {
436 posbits = ((posbits-1) +
437 ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
438 ++n_bits;
439 if (n_bits == maxbits) {
440 maxcode = maxmaxcode;
441 } else {
442 maxcode = MAXCODE(n_bits)-1;
443 }
444 bitmask = (1<<n_bits)-1;
445 goto resetbuf;
446 }
447 input(inbuf,posbits,code,n_bits,bitmask);
448 Tracev((stderr, "%d ", code));
449
450 if (oldcode == -1) {
451 if (code >= 256) {
452 error("corrupt input.");
453 exit_code = ERROR;
454 return ERROR;
455 }
456
457 outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
458 continue;
459 }
460 if (code == CLEAR && block_mode) {
461 clear_tab_prefixof();
462 free_ent = FIRST - 1;
463 posbits = ((posbits-1) +
464 ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
465 maxcode = MAXCODE(n_bits = INIT_BITS)-1;
466 bitmask = (1<<n_bits)-1;
467 goto resetbuf;
468 }
469 incode = code;
470 stackp = de_stack;
471
472 if (code >= free_ent) { /* Special case for KwKwK string. */
473 if (code > free_ent) {
474 if (outpos > 0) {
475 write_buf((char*)outbuf, outpos);
476 bytes_out += (ulg)outpos;
477 }
478 error("corrupt input.");
479 exit_code = ERROR;
480 return ERROR;
481
482 }
483 *--stackp = (char_type)finchar;
484 code = oldcode;
485 }
486
487 while ((cmp_code_int)code >= (cmp_code_int)256) {
488 /* Generate output characters in reverse order */
489 *--stackp = tab_suffixof(code);
490 code = tab_prefixof(code);
491 }
492 *--stackp = (char_type)(finchar = tab_suffixof(code));
493
494 /* And put them out in forward order */
495 {
496 /* REG1 int i; already defined above (WDP) */
497
498 if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
499 do {
500 if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
501
502 if (i > 0) {
503 memcpy(outbuf+outpos, stackp, i);
504 outpos += i;
505 }
506 if (outpos >= OUTBUFSIZ) {
507 write_buf((char*)outbuf, outpos);
508 bytes_out += (ulg)outpos;
509 outpos = 0;
510 }
511 stackp+= i;
512 } while ((i = (de_stack-stackp)) > 0);
513 } else {
514 memcpy(outbuf+outpos, stackp, i);
515 outpos += i;
516 }
517 }
518
519 if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
520
521 tab_prefixof(code) = (unsigned short)oldcode;
522 tab_suffixof(code) = (char_type)finchar;
523 free_ent = code+1;
524 }
525 oldcode = incode; /* Remember previous code. */
526 }
527 } while (rsize != 0);
528
529 if (outpos > 0) {
530 write_buf((char*)outbuf, outpos);
531 bytes_out += (ulg)outpos;
532 }
533 return OK;
534 }
535 /* ========================================================================*/
536 /* this marks the start of the code from 'util.c' */
537
fill_inbuf(int eof_ok)538 local int fill_inbuf(int eof_ok)
539 /* set if EOF acceptable as a result */
540 {
541 int len;
542
543 /* Read as much as possible from file */
544 insize = 0;
545 do {
546 len = fread((char*)inbuf+insize, 1, INBUFSIZ-insize, ifd);
547 if (len == 0 || len == EOF) break;
548 insize += len;
549 } while (insize < INBUFSIZ);
550
551 if (insize == 0) {
552 if (eof_ok) return EOF;
553 error("unexpected end of file");
554 exit_code = ERROR;
555 return ERROR;
556 }
557
558 bytes_in += (ulg)insize;
559 inptr = 1;
560 return inbuf[0];
561 }
562 /* =========================================================================== */
write_buf(voidp buf,unsigned cnt)563 local void write_buf(voidp buf, unsigned cnt)
564 /* copy buffer into memory; allocate more memory if required*/
565 {
566 if (!realloc_fn)
567 {
568 /* append buffer to file */
569 /* added 'unsigned' to get rid of compiler warning (WDP 1/1/99) */
570 if ((unsigned long) fwrite(buf, 1, cnt, ofd) != cnt)
571 {
572 error
573 ("failed to write buffer to uncompressed output file (write_buf)");
574 exit_code = ERROR;
575 return;
576 }
577 }
578 else
579 {
580 /* get more memory if current buffer is too small */
581 if (bytes_out + cnt > *memsize)
582 {
583 *memptr = realloc_fn(*memptr, bytes_out + cnt);
584 *memsize = bytes_out + cnt; /* new memory buffer size */
585
586 if (!(*memptr))
587 {
588 error("malloc failed while uncompressing (write_buf)");
589 exit_code = ERROR;
590 return;
591 }
592 }
593 /* copy into memory buffer */
594 memcpy((char *) *memptr + bytes_out, (char *) buf, cnt);
595 }
596 }
597 /* ======================================================================== */
error(char * m)598 local void error(char *m)
599 /* Error handler */
600 {
601 ffpmsg(ifname);
602 ffpmsg(m);
603 }
604