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