home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* 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);
- }
-
-