www.pudn.com > tfs.rar > UNPACK.C


/* unpack.c:
 *  This code provides the monitor with huffman decompression used
 *  primarily by TFS, but also available as a command in the monitor.
 *
 *  General notice:
 *  This code is part of a boot-monitor package developed as a generic base
 *  platform for embedded system designs.  As such, it is likely to be
 *  distributed to various projects beyond the control of the original
 *  author.  Please notify the author of any enhancements made or bugs found
 *  so that all may benefit from the changes.  In addition, notification back
 *  to the author will allow the new user to pick up changes that may have
 *  been made by other users after this version of the code was distributed.
 *
 *  Note1: the majority of this code was edited with 4-space tabs.
 *  Note2: as more and more contributions are accepted, the term "author"
 *         is becoming a mis-representation of credit.
 *
 *  Original author:    Ed Sutter
 *  Email:              esutter@lucent.com
 *  Phone:              908-582-2351
 */

#include "config.h"
#include "genlib.h"
#if INCLUDE_UNPACK
#include "stddefs.h"
//#include "cli.h"
#define NAMELEN 80
#define SUF0    '.'
#define SUF1    'z'
#define US  037
#define RS  036

#define BUFSIZ  1024
#define BLKSIZE BUFSIZ

/* variables associated with i/o */
static char outbuff[BUFSIZ];

/* the dictionary */
static short    intnodes[25];
static char     *tree[25];
static char     characters[256];

static int      UnpackError;
static char     *lastwrite;

static char     *decode();
static char     *getdict();

/* getdict():
 *  Read in the dictionary portion and build decoding structures
 *  return decode() if successful, 0 otherwise
 */
static char *
getdict(char *readptr, char *writeptr)
{
    int c, i, nchildren;
    int maxlev, inleft;
    char    *inp, *eof;
    long    origsize;

    /*
     * check two-byte header
     * get size of original file,
     * get number of levels in maxlev,
     * get number of leaves on level i in intnodes[i],
     * set tree[i] to point to leaves for level i
     */
    eof = &characters[0];

    inleft = BUFSIZ;
    if (readptr[0] != US) {
        UnpackError = 1;
        return(0);
    }

    if (readptr[1] == US) { /* does not support old style packing */
        UnpackError = 2;
        return(0);
    }

    if (readptr[1] != RS) {
        UnpackError = 3;
        return(0);
    }

    inp = (char *)&readptr[2];
    origsize = 0;
    for (i=0; i<4; i++)
        origsize = origsize*256 + ((*inp++) & 0xff);
    maxlev = *inp++ & 0xff;
    if (maxlev > 24) {
        UnpackError = 4;
        return(0);
    }

    for (i=1; i<=maxlev; i++)
        intnodes[i] = *inp++ & 0377;

    for (i=1; i<=maxlev; i++) {
        tree[i] = eof;
        for (c=intnodes[i]; c>0; c--) {
            if (eof >= &characters[255]) {
                UnpackError = 5;
                return(0);
            }
            *eof++ = *inp++;
        }
    }
    *eof++ = *inp++;
    intnodes[maxlev] += 2;
    inleft -= inp - (char *)&readptr[0];
    if (inleft < 0) {
        UnpackError = 6;
        return(0);
    }

    /*
         * convert intnodes[i] to be number of
         * internal nodes possessed by level i
         */

    nchildren = 0;
    for (i=maxlev; i>=1; i--) {
        c = intnodes[i];
        intnodes[i] = nchildren /= 2;
        nchildren += c;
    }
    readptr += BUFSIZ;
    return(decode(readptr,writeptr,inleft,inp,eof,origsize));
}

/* decode():
 * unpack the file
 * return (readptr-inleft) if successful, 0 otherwise
 */
static char *
decode(uchar *rdptr,uchar *wrptr,int inleft,char *inp,char *eof,long origsize)
{
    int bitsleft, c, i, j, k, lev;
    char    *p, *outp;

    outp = &outbuff[0];
    lev = 1;
    i = 0;
    while (1) {
        if (inleft <= 0) {
            inleft = BUFSIZ;
            inp = (char *)rdptr;
            rdptr += BUFSIZ;
        }
        if (--inleft < 0) {
            if(origsize == 0) {
                lastwrite = (char *)wrptr;
                return((char *)(rdptr-inleft));
            }
            UnpackError = 7;
            return(0);
        }
        c = *inp++;
        bitsleft = 8;
        while (--bitsleft >= 0) {
            i *= 2;
            if (c & 0x80)
                i++;
            c <<= 1;
            if ((j = i - intnodes[lev]) >= 0) {
                p = &tree[lev][j];
                if (p == eof) {
                    c = outp - &outbuff[0];
                    for(k=0;k