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 >
C/C++ Source or Header  |  1989-05-26  |  8KB  |  368 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /* Copyright 1989, Doug Boone.  FidoNet 119/5                               */
  4. /*                              (916) 893-9019 Data                         */
  5. /*                              (916) 891-0748 voice                        */
  6. /*                              P.O. Box 5108, Chico, CA. 95928             */
  7. /*                                                                          */
  8. /* This program is not for sale. It is for the free use with Opus systems.  */
  9. /* You may not sell it in ANY way. If you have an access charge to your     */
  10. /* Bulletin Board, consider this to be like Opus, you can ONLY make it      */
  11. /* available for download in an open area, where non-members can get access */
  12. /*                                                                          */
  13. /* If you need to modify this source code, please send me a copy of the     */
  14. /* changes you've made so that everyone can share in the updates.           */
  15. /*                                                                          */
  16. /* "Don't rip me off!" -- Tom Jennings, FidoNet's founder                   */
  17. /*                                                                          */
  18. /*--------------------------------------------------------------------------*/
  19.  
  20.  
  21. #include    <stdio.h>
  22. #include    <stdlib.h>
  23. #include    <string.h>
  24. #include    <ctype.h>
  25. #include    <fcntl.h>
  26. #include    <sys\types.h>
  27. #include    <sys\stat.h>
  28. #include    <io.h>
  29. #include    "archdr.h"
  30. #include    "unlzh.h"
  31.  
  32. extern  unpack(int,int,long);
  33.  
  34. int     GetBit(void);
  35. int     GetByte(void);
  36. void    StartHuff(void);
  37. void    reconst(void);
  38. void    update(int);
  39. int     DecodeChar(void);
  40. int     DecodePosition(void);
  41. void    Decode(void);
  42. void    load_inbuf(void);
  43. int     unlzh(char *,char *);
  44.  
  45. int GetBit(void)    /* get one bit */
  46. {
  47.     int i;
  48.  
  49.     while (getlen <= 8) {
  50.         if ((++inpos >= insize) && (insize > 0))
  51.             load_inbuf();
  52.         if ((i = *inptr++) < 0)
  53.             i = 0;
  54.         getbuf |= i << (8 - getlen);
  55.         getlen += 8;
  56.         }
  57.     i = getbuf;
  58.     getbuf <<= 1;
  59.     getlen--;
  60.     return (i < 0);
  61. }
  62.  
  63. int GetByte(void)    /* get a byte */
  64. {
  65.     unsigned i;
  66.  
  67.     while (getlen <= 8) {
  68.         if ((++inpos >= insize) && (insize >0))
  69.             load_inbuf();
  70.         if ((i = *inptr++) < 0)
  71.             i = 0;
  72.         getbuf |= i << (8 - getlen);
  73.         getlen += 8;
  74.     }
  75.     i = getbuf;
  76.     getbuf <<= 8;
  77.     getlen -= 8;
  78.     return(i >> 8);
  79. }
  80.  
  81. /* initialize freq tree */
  82.  
  83. void StartHuff(void)
  84. {
  85.     int i, j;
  86.  
  87.     for (i = 0;i < T+N_CHAR;i++)
  88.         prnt[i] = 0;
  89.  
  90.     for (i = 0;i < T;i++)
  91.         son[i] = 0;
  92.  
  93.     for (i = 0; i < N_CHAR; i++) {
  94.         freq[i] = 1;
  95.         son[i] = i + T;
  96.         prnt[i + T] = i;
  97.         }
  98.  
  99.     for (i = N_CHAR;i<T+1;i++)
  100.         freq[i] = 0;
  101.  
  102.     i = 0;
  103.     j = N_CHAR;
  104.     while (j <= R) {
  105.         freq[j] = freq[i] + freq[i + 1];
  106.         son[j] = i;
  107.         prnt[i] = prnt[i + 1] = j;
  108.         i += 2;
  109.         j++;
  110.         }
  111.  
  112.     freq[T] = 0xffff;
  113.     prnt[R] = 0;
  114. }
  115.  
  116.  
  117. /* reconstruct freq tree */
  118.  
  119. void reconst(void)
  120. {
  121.     int i, j, k;
  122.     unsigned f, l;
  123.  
  124.     /* halven cumulative freq for leaf nodes */
  125.     j = 0;
  126.     for (i = 0; i < T; i++) {
  127.         if (son[i] >= T) {
  128.             freq[j] = (freq[i] + 1) / 2;
  129.             son[j] = son[i];
  130.             j++;
  131.             }
  132.         }
  133.     /* make a tree : first, connect children nodes */
  134.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  135.         k = i + 1;
  136.         f = freq[j] = freq[i] + freq[k];
  137.         for (k = j - 1; f < freq[k]; k--);
  138.         k++;
  139.         l = (j - k) * 2;
  140.         
  141.         /* movmem() is Turbo-C dependent
  142.            rewritten to memmove() by Kenji */
  143.         
  144.         /* movmem(&freq[k], &freq[k + 1], l); */
  145.         (void)memmove(&freq[k + 1], &freq[k], l);
  146.         freq[k] = f;
  147.         /* movmem(&son[k], &son[k + 1], l); */
  148.         (void)memmove(&son[k + 1], &son[k], l);
  149.         son[k] = i;
  150.     }
  151.     /* connect parent nodes */
  152.     for (i = 0; i < T; i++) {
  153.         if ((k = son[i]) >= T) {
  154.             prnt[k] = i;
  155.             }
  156.         else 
  157.             prnt[k] = prnt[k + 1] = i;
  158.         }
  159. }
  160.  
  161.  
  162. /* update freq tree */
  163.  
  164. void update(int c)
  165. {
  166.     int i;
  167.     int j;
  168.     int k;
  169.     int l;
  170.  
  171.     if (freq[R] == MAX_FREQ) 
  172.         reconst();
  173.     c = prnt[c + T];
  174.     do {
  175.         k = ++freq[c];
  176.  
  177.         /* swap nodes to keep the tree freq-ordered */
  178.         if (k > freq[l = c + 1]) {
  179.             while (k > freq[++l]);
  180.             l--;
  181.             freq[c] = freq[l];
  182.             freq[l] = k;
  183.  
  184.             i = son[c];
  185.             prnt[i] = l;
  186.             if (i < T)
  187.                 prnt[i + 1] = l;
  188.  
  189.             j = son[l];
  190.             son[l] = i;
  191.  
  192.             prnt[j] = c;
  193.             if (j < T)
  194.                 prnt[j + 1] = c;
  195.             son[c] = j;
  196.  
  197.             c = l;
  198.         }
  199.     } while ((c = prnt[c]) != 0);    /* do it until reaching the root */
  200. }
  201.  
  202. int DecodeChar(void)
  203. {
  204.     unsigned c;
  205.  
  206.     c = son[R];
  207.  
  208.     /*
  209.      * start searching tree from the root to leaves.
  210.      * choose node #(son[]) if input bit == 0
  211.      * else choose #(son[]+1) (input bit == 1)
  212.      */
  213.     while (c < T) {
  214.         c += GetBit();
  215.         c = son[c];
  216.         }
  217.     c -= T;
  218.     update(c);
  219.     return(c);
  220. }
  221.  
  222. int DecodePosition(void)
  223. {
  224.     unsigned i, j, c;
  225.     unsigned    temp;
  226.  
  227.     /* decode upper 6 bits from given table */
  228.     i = GetByte();
  229.     c = (unsigned)d_code[i] << 6;
  230.     j = d_len[i];
  231.  
  232.     /* input lower 6 bits directly */
  233.     j -= 2;
  234.     while (j--) 
  235.         i = (i << 1) + GetBit();
  236.     temp = c|(i&0x3f);
  237.     return (temp);
  238. }
  239.  
  240. void Decode(void)  /* Decoding/Uncompressing */
  241. {
  242.     int  i, j, k, r, c;
  243.     unsigned long int  count;
  244.  
  245.     load_inbuf();
  246.     StartHuff();
  247.  
  248.     for (i = 0; i < N - F; i++)
  249.         text_buf[i] = ' ';
  250.     r = N - F;
  251.     for (count = 0; count < unpacked; ) {
  252.         c = DecodeChar();
  253.         if (c < 256) {
  254.             *outptr++ = (byte) c;
  255.             if (++outpos > outsize) {
  256.                 write(outfile,outbuf,outpos);
  257.                 outptr = outbuf;
  258.                 outpos = 0;
  259.                 }
  260.             text_buf[r++] = (byte) c;
  261.             r &= (N - 1);
  262.             count++;
  263.             }
  264.         else {
  265.             i = (r - DecodePosition() - 1) & (N - 1);
  266.             j = c - 255 + THRESHOLD;
  267.             for (k = 0; k < j; k++) {
  268.                 c = text_buf[(i + k) & (N - 1)];
  269.                 *outptr++ = (byte) c;
  270.                 if (++outpos > outsize) {
  271.                     write(outfile,outbuf,outpos);
  272.                     outptr = outbuf;
  273.                     outpos = 0;
  274.                     }
  275.                 text_buf[r++] = (byte) c;
  276.                 r &= (N - 1);
  277.                 count++;
  278.                 }
  279.             }
  280.         }
  281. }
  282.  
  283. void    load_inbuf(void)
  284. {
  285.     inptr = inbuf;
  286.     inpos = 0;
  287.     if (insize > ((unsigned) packed))
  288.         insize = (unsigned) packed;
  289.     read(infile,inbuf,insize);
  290.     packed -= (long) insize;
  291.     if (insize > ((unsigned) packed))
  292.         insize = (unsigned) packed;
  293.     return;
  294. }
  295.  
  296. int unlzh(char *in_name,char *out_name)
  297. {
  298.     struct  Lharc_Hdr   *local;
  299.     char    *mbrname;
  300.     char    *s;
  301.     int     check;
  302.  
  303.     getbuf = 0;
  304.     getlen = 0;
  305.     insize = 16384;
  306.     outsize = 16384;
  307.  
  308.     if ((s = strrchr(out_name,'\\')) == NULL)
  309.         s = out_name;
  310.     else
  311.         s++;        /* Grab the member name */
  312.  
  313.     local = (struct Lharc_Hdr *) malloc(sizeof(struct Lharc_Hdr));
  314.     mbrname = (char *) malloc(80);
  315.  
  316.     infile = open(in_name,O_BINARY|O_RDONLY);
  317.     outfile = open(out_name,O_BINARY|O_CREAT|O_WRONLY,S_IREAD|S_IWRITE);
  318.  
  319.     do {
  320.         if ((outbuf = (char *) malloc(outsize)) == NULL)
  321.             outsize /= 2;
  322.         } while (outbuf == NULL);
  323.     outptr = outbuf;
  324.  
  325.     do {
  326.         if ((inbuf = (char *) malloc(insize)) == NULL)
  327.             insize /= 2;
  328.         } while (inbuf == NULL);
  329.     inptr = inbuf;
  330.  
  331.  
  332.     do {
  333.         if ((check = read(infile,(void *)local,sizeof(struct Lharc_Hdr))) ==
  334.             sizeof(struct Lharc_Hdr)) {
  335.             memset(mbrname,EOS,80);
  336.             check = read(infile,mbrname,local->name_len);
  337.             if (stricmp(mbrname,s) == 0) {
  338.                 unpacked = local->orig_size;
  339.                 lseek(infile,2L,SEEK_CUR);
  340.                 packed = local->size_now;
  341.                 inpos = 0;
  342.                 outpos = 0;
  343.                 if (strnicmp(local->type,"-lh1-",5) == 0)
  344.                     Decode();
  345.                 else if (strnicmp(local->type,"-lh0-",5) == 0) 
  346.                     unpack(infile,outfile,unpacked);
  347.  
  348.                 write(outfile,outbuf,outpos);
  349.                 free(mbrname);
  350.                 free(local);
  351.                 check = close(infile);
  352.                 check = close(outfile);
  353.                 free(inbuf);
  354.                 free(outbuf);
  355.                 check = 0;
  356.                 return(0);
  357.                 }
  358.             lseek(infile,local->size_now + 2L,SEEK_CUR);
  359.             }
  360.         } while(check > 0 && !eof(infile));        /* End of file */
  361.     free(mbrname);
  362.     free(local);
  363.     close(infile);
  364.     close(outfile);
  365.     return(-1);
  366. }
  367.  
  368.