home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
msdos
/
opus
/
fvsrc620.arc
/
UNLZH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-05-26
|
8KB
|
368 lines
/*--------------------------------------------------------------------------*/
/* */
/* Copyright 1989, Doug Boone. FidoNet 119/5 */
/* (916) 893-9019 Data */
/* (916) 891-0748 voice */
/* P.O. Box 5108, Chico, CA. 95928 */
/* */
/* This program is not for sale. It is for the free use with Opus systems. */
/* You may not sell it in ANY way. If you have an access charge to your */
/* Bulletin Board, consider this to be like Opus, you can ONLY make it */
/* available for download in an open area, where non-members can get access */
/* */
/* If you need to modify this source code, please send me a copy of the */
/* changes you've made so that everyone can share in the updates. */
/* */
/* "Don't rip me off!" -- Tom Jennings, FidoNet's founder */
/* */
/*--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include "archdr.h"
#include "unlzh.h"
extern unpack(int,int,long);
int GetBit(void);
int GetByte(void);
void StartHuff(void);
void reconst(void);
void update(int);
int DecodeChar(void);
int DecodePosition(void);
void Decode(void);
void load_inbuf(void);
int unlzh(char *,char *);
int GetBit(void) /* get one bit */
{
int i;
while (getlen <= 8) {
if ((++inpos >= insize) && (insize > 0))
load_inbuf();
if ((i = *inptr++) < 0)
i = 0;
getbuf |= i << (8 - getlen);
getlen += 8;
}
i = getbuf;
getbuf <<= 1;
getlen--;
return (i < 0);
}
int GetByte(void) /* get a byte */
{
unsigned i;
while (getlen <= 8) {
if ((++inpos >= insize) && (insize >0))
load_inbuf();
if ((i = *inptr++) < 0)
i = 0;
getbuf |= i << (8 - getlen);
getlen += 8;
}
i = getbuf;
getbuf <<= 8;
getlen -= 8;
return(i >> 8);
}
/* initialize freq tree */
void StartHuff(void)
{
int i, j;
for (i = 0;i < T+N_CHAR;i++)
prnt[i] = 0;
for (i = 0;i < T;i++)
son[i] = 0;
for (i = 0; i < N_CHAR; i++) {
freq[i] = 1;
son[i] = i + T;
prnt[i + T] = i;
}
for (i = N_CHAR;i<T+1;i++)
freq[i] = 0;
i = 0;
j = N_CHAR;
while (j <= R) {
freq[j] = freq[i] + freq[i + 1];
son[j] = i;
prnt[i] = prnt[i + 1] = j;
i += 2;
j++;
}
freq[T] = 0xffff;
prnt[R] = 0;
}
/* reconstruct freq tree */
void reconst(void)
{
int i, j, k;
unsigned f, l;
/* halven cumulative freq for leaf nodes */
j = 0;
for (i = 0; i < T; i++) {
if (son[i] >= T) {
freq[j] = (freq[i] + 1) / 2;
son[j] = son[i];
j++;
}
}
/* make a tree : first, connect children nodes */
for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
k = i + 1;
f = freq[j] = freq[i] + freq[k];
for (k = j - 1; f < freq[k]; k--);
k++;
l = (j - k) * 2;
/* movmem() is Turbo-C dependent
rewritten to memmove() by Kenji */
/* movmem(&freq[k], &freq[k + 1], l); */
(void)memmove(&freq[k + 1], &freq[k], l);
freq[k] = f;
/* movmem(&son[k], &son[k + 1], l); */
(void)memmove(&son[k + 1], &son[k], l);
son[k] = i;
}
/* connect parent nodes */
for (i = 0; i < T; i++) {
if ((k = son[i]) >= T) {
prnt[k] = i;
}
else
prnt[k] = prnt[k + 1] = i;
}
}
/* update freq tree */
void update(int c)
{
int i;
int j;
int k;
int l;
if (freq[R] == MAX_FREQ)
reconst();
c = prnt[c + T];
do {
k = ++freq[c];
/* swap nodes to keep the tree freq-ordered */
if (k > freq[l = c + 1]) {
while (k > freq[++l]);
l--;
freq[c] = freq[l];
freq[l] = k;
i = son[c];
prnt[i] = l;
if (i < T)
prnt[i + 1] = l;
j = son[l];
son[l] = i;
prnt[j] = c;
if (j < T)
prnt[j + 1] = c;
son[c] = j;
c = l;
}
} while ((c = prnt[c]) != 0); /* do it until reaching the root */
}
int DecodeChar(void)
{
unsigned c;
c = son[R];
/*
* start searching tree from the root to leaves.
* choose node #(son[]) if input bit == 0
* else choose #(son[]+1) (input bit == 1)
*/
while (c < T) {
c += GetBit();
c = son[c];
}
c -= T;
update(c);
return(c);
}
int DecodePosition(void)
{
unsigned i, j, c;
unsigned temp;
/* decode upper 6 bits from given table */
i = GetByte();
c = (unsigned)d_code[i] << 6;
j = d_len[i];
/* input lower 6 bits directly */
j -= 2;
while (j--)
i = (i << 1) + GetBit();
temp = c|(i&0x3f);
return (temp);
}
void Decode(void) /* Decoding/Uncompressing */
{
int i, j, k, r, c;
unsigned long int count;
load_inbuf();
StartHuff();
for (i = 0; i < N - F; i++)
text_buf[i] = ' ';
r = N - F;
for (count = 0; count < unpacked; ) {
c = DecodeChar();
if (c < 256) {
*outptr++ = (byte) c;
if (++outpos > outsize) {
write(outfile,outbuf,outpos);
outptr = outbuf;
outpos = 0;
}
text_buf[r++] = (byte) c;
r &= (N - 1);
count++;
}
else {
i = (r - DecodePosition() - 1) & (N - 1);
j = c - 255 + THRESHOLD;
for (k = 0; k < j; k++) {
c = text_buf[(i + k) & (N - 1)];
*outptr++ = (byte) c;
if (++outpos > outsize) {
write(outfile,outbuf,outpos);
outptr = outbuf;
outpos = 0;
}
text_buf[r++] = (byte) c;
r &= (N - 1);
count++;
}
}
}
}
void load_inbuf(void)
{
inptr = inbuf;
inpos = 0;
if (insize > ((unsigned) packed))
insize = (unsigned) packed;
read(infile,inbuf,insize);
packed -= (long) insize;
if (insize > ((unsigned) packed))
insize = (unsigned) packed;
return;
}
int unlzh(char *in_name,char *out_name)
{
struct Lharc_Hdr *local;
char *mbrname;
char *s;
int check;
getbuf = 0;
getlen = 0;
insize = 16384;
outsize = 16384;
if ((s = strrchr(out_name,'\\')) == NULL)
s = out_name;
else
s++; /* Grab the member name */
local = (struct Lharc_Hdr *) malloc(sizeof(struct Lharc_Hdr));
mbrname = (char *) malloc(80);
infile = open(in_name,O_BINARY|O_RDONLY);
outfile = open(out_name,O_BINARY|O_CREAT|O_WRONLY,S_IREAD|S_IWRITE);
do {
if ((outbuf = (char *) malloc(outsize)) == NULL)
outsize /= 2;
} while (outbuf == NULL);
outptr = outbuf;
do {
if ((inbuf = (char *) malloc(insize)) == NULL)
insize /= 2;
} while (inbuf == NULL);
inptr = inbuf;
do {
if ((check = read(infile,(void *)local,sizeof(struct Lharc_Hdr))) ==
sizeof(struct Lharc_Hdr)) {
memset(mbrname,EOS,80);
check = read(infile,mbrname,local->name_len);
if (stricmp(mbrname,s) == 0) {
unpacked = local->orig_size;
lseek(infile,2L,SEEK_CUR);
packed = local->size_now;
inpos = 0;
outpos = 0;
if (strnicmp(local->type,"-lh1-",5) == 0)
Decode();
else if (strnicmp(local->type,"-lh0-",5) == 0)
unpack(infile,outfile,unpacked);
write(outfile,outbuf,outpos);
free(mbrname);
free(local);
check = close(infile);
check = close(outfile);
free(inbuf);
free(outbuf);
check = 0;
return(0);
}
lseek(infile,local->size_now + 2L,SEEK_CUR);
}
} while(check > 0 && !eof(infile)); /* End of file */
free(mbrname);
free(local);
close(infile);
close(outfile);
return(-1);
}