2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: decompress.c /main/4 1995/10/26 12:36:44 rswiston $ */
25 * decompress - cat a compressed file
27 * (c) Copyright 1993, 1994 Hewlett-Packard Company
28 * (c) Copyright 1993, 1994 International Business Machines Corp.
29 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
30 * (c) Copyright 1993, 1994 Novell, Inc.
33 /* #include "fontmisc.h" */
43 * a code_int must be able to hold 2**BITS values of type int, and also -1
46 typedef long int code_int;
51 typedef long int count_int;
54 typedef char char_type;
56 typedef unsigned char char_type;
59 static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
61 /* Defines for third byte of header */
63 #define BLOCK_MASK 0x80
64 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
65 a fourth header byte (for expansion).
68 #define INIT_BITS 9 /* initial number of bits/code */
70 #ifdef COMPATIBLE /* But wrong! */
71 # define MAXCODE(n_bits) (1 << (n_bits) - 1)
73 # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
74 #endif /* COMPATIBLE */
76 static code_int getcode();
79 * the next two codes should not be changed lightly, as they must not
80 * lie within the contiguous general code space.
82 #define FIRST 257 /* first free entry */
83 #define CLEAR 256 /* table clear output code */
85 #define STACK_SIZE 8192
87 typedef struct _compressedFILE {
96 code_int maxcode, maxmaxcode;
106 char_type de_stack[STACK_SIZE];
107 char_type *tab_suffix;
108 unsigned short *tab_prefix;
112 static int hsize_table[] = {
113 5003, /* 12 bits - 80% occupancy */
114 9001, /* 13 bits - 91% occupancy */
115 18013, /* 14 bits - 91% occupancy */
116 35023, /* 15 bits - 94% occupancy */
117 69001 /* 16 bits - 95% occupancy */
120 static int BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();
123 _DtHelpCeBufFilePushZ (BufFilePtr f)
128 CompressedFile *file;
131 if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
132 (BufFileGet(f) != (magic_header[1] & 0xFF)))
136 code = BufFileGet (f);
137 maxbits = code & BIT_MASK;
138 if (maxbits > BITS || maxbits < 12)
140 hsize = hsize_table[maxbits - 12];
141 extra = (1 << maxbits) * sizeof (char_type) +
142 hsize * sizeof (unsigned short);
143 file = (CompressedFile *) malloc (sizeof (CompressedFile) + extra);
147 file->maxbits = maxbits;
148 file->block_compress = code & BLOCK_MASK;
149 file->maxmaxcode = 1 << file->maxbits;
150 file->tab_suffix = (char_type *) &file[1];
151 file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
153 * As above, initialize the first 256 entries in the table.
155 file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
156 for ( code = 255; code >= 0; code-- ) {
157 file->tab_prefix[code] = 0;
158 file->tab_suffix[code] = (char_type) code;
160 file->free_ent = ((file->block_compress) ? FIRST : 256 );
164 file->stackp = file->de_stack;
165 file->finchar = file->oldcode = getcode (file);
166 if (file->oldcode != -1)
167 *file->stackp++ = file->finchar;
168 return _DtHelpCeBufFileCreate ((char *) file,
179 CompressedFile *file;
182 file = (CompressedFile *) f->hidden;
185 _DtHelpCeBufFileClose (raw, doClose);
190 BufCompressedFill (BufFilePtr f)
192 CompressedFile *file;
193 register char_type *stackp, *de_stack;
194 register char_type finchar;
195 register code_int code, oldcode, incode;
196 BufChar *buf, *bufend;
198 file = (CompressedFile *) f->hidden;
201 bufend = buf + BUFFILESIZE;
202 stackp = file->stackp;
203 de_stack = file->de_stack;
204 finchar = file->finchar;
205 oldcode = file->oldcode;
206 while (buf < bufend) {
207 while (stackp > de_stack && buf < bufend)
216 code = getcode (file);
220 if ( (code == CLEAR) && file->block_compress ) {
221 for ( code = 255; code >= 0; code-- )
222 file->tab_prefix[code] = 0;
224 file->free_ent = FIRST - 1;
225 if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
230 * Special case for KwKwK string.
232 if ( code >= file->free_ent ) {
238 * Generate output characters in reverse order
240 while ( code >= 256 )
242 *stackp++ = file->tab_suffix[code];
243 code = file->tab_prefix[code];
245 finchar = file->tab_suffix[code];
249 * Generate the new entry.
251 if ( (code=file->free_ent) < file->maxmaxcode ) {
252 file->tab_prefix[code] = (unsigned short)oldcode;
253 file->tab_suffix[code] = finchar;
254 file->free_ent = code+1;
257 * Remember previous code.
261 file->oldcode = oldcode;
262 file->stackp = stackp;
263 file->finchar = finchar;
264 if (buf == f->buffer) {
268 f->bufp = f->buffer + 1;
269 f->left = (buf - f->buffer) - 1;
273 /*****************************************************************
276 * Read one code from the standard input. If BUFFILEEOF, return -1.
280 * code or -1 is returned.
283 static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
286 getcode(CompressedFile *file)
288 register code_int code;
289 register int r_off, bits;
290 register char_type *bp = file->buf;
291 register BufFilePtr raw;
293 if ( file->clear_flg > 0 || file->offset >= file->size ||
294 file->free_ent > file->maxcode )
297 * If the next entry will be too big for the current code
298 * size, then we must increase the size. This implies reading
299 * a new buffer full, too.
301 if ( file->free_ent > file->maxcode ) {
303 if ( file->n_bits == file->maxbits )
304 file->maxcode = file->maxmaxcode; /* won't get any bigger now */
306 file->maxcode = MAXCODE(file->n_bits);
308 if ( file->clear_flg > 0) {
309 file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
314 while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
320 if (bits == file->n_bits)
321 return -1; /* end of file */
322 file->size = file->n_bits - bits;
324 /* Round size down to integral number of codes */
325 file->size = (file->size << 3) - (file->n_bits - 1);
327 r_off = file->offset;
330 * Get to the first byte.
334 /* Get first part (low order bits) */
336 code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
338 code = (*bp++ >> r_off);
339 #endif /* NO_UCHAR */
341 r_off = 8 - r_off; /* now, offset into code word */
342 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
345 code |= (*bp++ & 0xff) << r_off;
347 code |= *bp++ << r_off;
348 #endif /* NO_UCHAR */
352 /* high order bits. */
353 code |= (*bp & rmask[bits]) << r_off;
354 file->offset += file->n_bits;
365 while (bytes-- && ((c = BufFileGet(f)) != BUFFILEEOF))
371 _DtHelpCeUncompressFile(
375 BufFilePtr inputraw, input, output;
379 CECompressInfoPtr myInfo;
382 inFd = open(infile, O_RDONLY);
383 if (inFd < 0) return -1;
385 if (fstat(inFd, &statBuf) < 0)
391 outFd = open(outfile, O_CREAT | O_WRONLY, 0666);
398 myInfo = (CECompressInfoPtr) malloc (sizeof(CECompressInfo));
407 myInfo->size = statBuf.st_size;
409 inputraw = _DtHelpCeBufFileRdRawZ (myInfo);
410 input = _DtHelpCeBufFilePushZ (inputraw);
411 output = _DtHelpCeBufFileOpenWr (outFd);
412 while ((c = BufFileGet (input)) != -1)
413 BufFilePut (c, output);
417 _DtHelpCeBufFileClose (input, TRUE);
418 _DtHelpCeBufFileClose (output, TRUE);
420 if (c != 0) /* didn't consume all the bytes in the file */