123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: decompress.c /main/4 1995/10/26 12:36:44 rswiston $ */
- /*
- * decompress - cat a compressed file
- *
- * (c) Copyright 1993, 1994 Hewlett-Packard Company
- * (c) Copyright 1993, 1994 International Business Machines Corp.
- * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- * (c) Copyright 1993, 1994 Novell, Inc.
- */
- /* #include "fontmisc.h" */
- #include <unistd.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/stat.h>
- #include "bufioI.h"
- #define BITS 16
- /*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
- #if BITS > 15
- typedef long int code_int;
- #else
- typedef int code_int;
- #endif
- typedef long int count_int;
- #ifdef NO_UCHAR
- typedef char char_type;
- #else
- typedef unsigned char char_type;
- #endif /* UCHAR */
- static int magic_header[] = { 0x1F, 0x9D };
- /* Defines for third byte of header */
- #define BIT_MASK 0x1f
- #define BLOCK_MASK 0x80
- /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- a fourth header byte (for expansion).
- */
- #define INIT_BITS 9 /* initial number of bits/code */
- #ifdef COMPATIBLE /* But wrong! */
- # define MAXCODE(n_bits) (1 << (n_bits) - 1)
- #else
- # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
- #endif /* COMPATIBLE */
- static code_int getcode();
- /*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
- #define FIRST 257 /* first free entry */
- #define CLEAR 256 /* table clear output code */
- #define STACK_SIZE 8192
- typedef struct _compressedFILE {
- BufFilePtr file;
- char_type *stackp;
- code_int oldcode;
- char_type finchar;
- int block_compress;
- int maxbits;
- code_int maxcode, maxmaxcode;
- code_int free_ent;
- int clear_flg;
- int n_bits;
- /* bit buffer */
- int offset, size;
- char_type buf[BITS];
- char_type de_stack[STACK_SIZE];
- char_type *tab_suffix;
- unsigned short *tab_prefix;
- } CompressedFile;
- static int hsize_table[] = {
- 5003, /* 12 bits - 80% occupancy */
- 9001, /* 13 bits - 91% occupancy */
- 18013, /* 14 bits - 91% occupancy */
- 35023, /* 15 bits - 94% occupancy */
- 69001 /* 16 bits - 95% occupancy */
- };
- static int BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();
- BufFilePtr
- _DtHelpCeBufFilePushZ (BufFilePtr f)
- {
- int code;
- int maxbits;
- int hsize;
- CompressedFile *file;
- int extra;
- if ((BufFileGet(f) != magic_header[0]) ||
- (BufFileGet(f) != magic_header[1]))
- {
- return 0;
- }
- code = BufFileGet (f);
- maxbits = code & BIT_MASK;
- if (maxbits > BITS || maxbits < 12)
- return 0;
- hsize = hsize_table[maxbits - 12];
- extra = (1 << maxbits) * sizeof (char_type) +
- hsize * sizeof (unsigned short);
- file = (CompressedFile *) malloc (sizeof (CompressedFile) + extra);
- if (!file)
- return 0;
- file->file = f;
- file->maxbits = maxbits;
- file->block_compress = code & BLOCK_MASK;
- file->maxmaxcode = 1 << file->maxbits;
- file->tab_suffix = (char_type *) &file[1];
- file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
- /*
- * As above, initialize the first 256 entries in the table.
- */
- file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
- for ( code = 255; code >= 0; code-- ) {
- file->tab_prefix[code] = 0;
- file->tab_suffix[code] = (char_type) code;
- }
- file->free_ent = ((file->block_compress) ? FIRST : 256 );
- file->clear_flg = 0;
- file->offset = 0;
- file->size = 0;
- file->stackp = file->de_stack;
- file->finchar = file->oldcode = getcode (file);
- if (file->oldcode != -1)
- *file->stackp++ = file->finchar;
- return _DtHelpCeBufFileCreate ((char *) file,
- BufCompressedFill,
- BufCompressedSkip,
- BufCompressedClose);
- }
- static int
- BufCompressedClose (
- BufFilePtr f,
- int doClose )
- {
- CompressedFile *file;
- BufFilePtr raw;
- file = (CompressedFile *) f->hidden;
- raw = file->file;
- free (file);
- _DtHelpCeBufFileClose (raw, doClose);
- return 1;
- }
- static int
- BufCompressedFill (BufFilePtr f)
- {
- CompressedFile *file;
- char_type *stackp, *de_stack;
- char_type finchar;
- code_int code, oldcode, incode;
- BufChar *buf, *bufend;
- file = (CompressedFile *) f->hidden;
- buf = f->buffer;
- bufend = buf + BUFFILESIZE;
- stackp = file->stackp;
- de_stack = file->de_stack;
- finchar = file->finchar;
- oldcode = file->oldcode;
- while (buf < bufend) {
- while (stackp > de_stack && buf < bufend)
- *buf++ = *--stackp;
- if (buf == bufend)
- break;
- if (oldcode == -1)
- break;
- code = getcode (file);
- if (code == -1)
- break;
-
- if ( (code == CLEAR) && file->block_compress ) {
- for ( code = 255; code >= 0; code-- )
- file->tab_prefix[code] = 0;
- file->clear_flg = 1;
- file->free_ent = FIRST - 1;
- if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
- break;
- }
- incode = code;
- /*
- * Special case for KwKwK string.
- */
- if ( code >= file->free_ent ) {
- *stackp++ = finchar;
- code = oldcode;
- }
-
- /*
- * Generate output characters in reverse order
- */
- while ( code >= 256 )
- {
- *stackp++ = file->tab_suffix[code];
- code = file->tab_prefix[code];
- }
- finchar = file->tab_suffix[code];
- *stackp++ = finchar;
-
- /*
- * Generate the new entry.
- */
- if ( (code=file->free_ent) < file->maxmaxcode ) {
- file->tab_prefix[code] = (unsigned short)oldcode;
- file->tab_suffix[code] = finchar;
- file->free_ent = code+1;
- }
- /*
- * Remember previous code.
- */
- oldcode = incode;
- }
- file->oldcode = oldcode;
- file->stackp = stackp;
- file->finchar = finchar;
- if (buf == f->buffer) {
- f->left = 0;
- return BUFFILEEOF;
- }
- f->bufp = f->buffer + 1;
- f->left = (buf - f->buffer) - 1;
- return f->buffer[0];
- }
- /*****************************************************************
- * TAG( getcode )
- *
- * Read one code from the standard input. If BUFFILEEOF, return -1.
- * Inputs:
- * stdin
- * Outputs:
- * code or -1 is returned.
- */
- static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
- static code_int
- getcode(CompressedFile *file)
- {
- code_int code;
- int r_off, bits;
- char_type *bp = file->buf;
- BufFilePtr raw;
- if ( file->clear_flg > 0 || file->offset >= file->size ||
- file->free_ent > file->maxcode )
- {
- /*
- * If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
- * a new buffer full, too.
- */
- if ( file->free_ent > file->maxcode ) {
- file->n_bits++;
- if ( file->n_bits == file->maxbits )
- file->maxcode = file->maxmaxcode; /* won't get any bigger now */
- else
- file->maxcode = MAXCODE(file->n_bits);
- }
- if ( file->clear_flg > 0) {
- file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
- file->clear_flg = 0;
- }
- bits = file->n_bits;
- raw = file->file;
- while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
- {
- *bp++ = code;
- --bits;
- }
- bp = file->buf;
- if (bits == file->n_bits)
- return -1; /* end of file */
- file->size = file->n_bits - bits;
- file->offset = 0;
- /* Round size down to integral number of codes */
- file->size = (file->size << 3) - (file->n_bits - 1);
- }
- r_off = file->offset;
- bits = file->n_bits;
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /* Get first part (low order bits) */
- #ifdef NO_UCHAR
- code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
- #else
- code = (*bp++ >> r_off);
- #endif /* NO_UCHAR */
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- #ifdef NO_UCHAR
- code |= (*bp++ & 0xff) << r_off;
- #else
- code |= *bp++ << r_off;
- #endif /* NO_UCHAR */
- r_off += 8;
- bits -= 8;
- }
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
- file->offset += file->n_bits;
- return code;
- }
- static int
- BufCompressedSkip (
- BufFilePtr f,
- int bytes)
- {
- int c = 0;
- while (bytes-- && ((c = BufFileGet(f)) != BUFFILEEOF))
- ;
- return c;
- }
- int
- _DtHelpCeUncompressFile(
- char *infile,
- char *outfile )
- {
- BufFilePtr inputraw, input, output;
- int c;
- int inFd, outFd;
- struct stat statBuf;
- CECompressInfoPtr myInfo;
-
- inFd = open(infile, O_RDONLY);
- if (inFd < 0) return -1;
- if (fstat(inFd, &statBuf) < 0)
- {
- close(inFd);
- return -1;
- }
- outFd = open(outfile, O_CREAT | O_WRONLY, 0666);
- if (outFd < 0)
- {
- close(inFd);
- return -1;
- }
- myInfo = (CECompressInfoPtr) malloc (sizeof(CECompressInfo));
- if (myInfo == NULL)
- {
- close(inFd);
- close(outFd);
- return -1;
- }
- myInfo->fd = inFd;
- myInfo->size = statBuf.st_size;
- inputraw = _DtHelpCeBufFileRdRawZ (myInfo);
- input = _DtHelpCeBufFilePushZ (inputraw);
- output = _DtHelpCeBufFileOpenWr (outFd);
- while ((c = BufFileGet (input)) != -1)
- BufFilePut (c, output);
- c = myInfo->size;
- _DtHelpCeBufFileClose (input, TRUE);
- _DtHelpCeBufFileClose (output, TRUE);
- if (c != 0) /* didn't consume all the bytes in the file */
- return -1;
- return 0;
- }
|