home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c019 / 1.ddi / PZXXX / LZHUF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-11  |  14.5 KB  |  624 lines

  1. /**************************************************************
  2.     lzhuf.c
  3.     written by Haruyasu Yoshizaki 11/20/1988
  4.     some minor changes 4/6/1989
  5.     comments translated by Haruhiko Okumura 4/7/1989
  6. **************************************************************/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11.  
  12. #define    EXIT_FAILURE    -1    /* sgg */
  13. #define    EXIT_SUCCESS    0    /* sgg */
  14.  
  15.  
  16. FILE  *infile, *outfile;
  17. unsigned long int  textsize = 0, codesize = 0, printcount = 0;
  18.  
  19. char wterr[] = "Can't write.";
  20.  
  21. void Error(char *message)
  22. {
  23.     printf("\n%s\n", message);
  24.     exit(EXIT_FAILURE);
  25. }
  26.  
  27. /********** LZSS compression **********/
  28.  
  29. #define N        4096    /* buffer size */
  30. #define F        60    /* lookahead buffer size */
  31. #define THRESHOLD    2
  32. #define NIL        N    /* leaf of tree */
  33.  
  34. unsigned char
  35.         text_buf[N + F - 1];
  36. int        match_position, match_length,
  37.         lson[N + 1], rson[N + 257], dad[N + 1];
  38.  
  39. void InitTree(void)  /* initialize trees */
  40. {
  41.     int  i;
  42.  
  43.     for (i = N + 1; i <= N + 256; i++)
  44.         rson[i] = NIL;            /* root */
  45.     for (i = 0; i < N; i++)
  46.         dad[i] = NIL;            /* node */
  47. }
  48.  
  49. void InsertNode(int r)  /* insert to tree */
  50. {
  51.     int  i, p, cmp;
  52.     unsigned char  *key;
  53.     unsigned c;
  54.  
  55.     cmp = 1;
  56.     key = &text_buf[r];
  57.     p = N + 1 + key[0];
  58.     rson[r] = lson[r] = NIL;
  59.     match_length = 0;
  60.     for ( ; ; ) {
  61.         if (cmp >= 0) {
  62.             if (rson[p] != NIL)
  63.                 p = rson[p];
  64.             else {
  65.                 rson[p] = r;
  66.                 dad[r] = p;
  67.                 return;
  68.             }
  69.         } else {
  70.             if (lson[p] != NIL)
  71.                 p = lson[p];
  72.             else {
  73.                 lson[p] = r;
  74.                 dad[r] = p;
  75.                 return;
  76.             }
  77.         }
  78.         for (i = 1; i < F; i++)
  79.             if ((cmp = key[i] - text_buf[p + i]) != 0)
  80.                 break;
  81.         if (i > THRESHOLD) {
  82.             if (i > match_length) {
  83.                 match_position = ((r - p) & (N - 1)) - 1;
  84.                 if ((match_length = i) >= F)
  85.                     break;
  86.             }
  87.             if (i == match_length) {
  88.                 if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
  89.                     match_position = c;
  90.                 }
  91.             }
  92.         }
  93.     }
  94.     dad[r] = dad[p];
  95.     lson[r] = lson[p];
  96.     rson[r] = rson[p];
  97.     dad[lson[p]] = r;
  98.     dad[rson[p]] = r;
  99.     if (rson[dad[p]] == p)
  100.         rson[dad[p]] = r;
  101.     else
  102.         lson[dad[p]] = r;
  103.     dad[p] = NIL;  /* remove p */
  104. }
  105.  
  106. void DeleteNode(int p)  /* remove from tree */
  107. {
  108.     int  q;
  109.  
  110.     if (dad[p] == NIL)
  111.         return;            /* not registered */
  112.     if (rson[p] == NIL)
  113.         q = lson[p];
  114.     else
  115.     if (lson[p] == NIL)
  116.         q = rson[p];
  117.     else {
  118.         q = lson[p];
  119.         if (rson[q] != NIL) {
  120.             do {
  121.                 q = rson[q];
  122.             } while (rson[q] != NIL);
  123.             rson[dad[q]] = lson[q];
  124.             dad[lson[q]] = dad[q];
  125.             lson[q] = lson[p];
  126.             dad[lson[p]] = q;
  127.         }
  128.         rson[q] = rson[p];
  129.         dad[rson[p]] = q;
  130.     }
  131.     dad[q] = dad[p];
  132.     if (rson[dad[p]] == p)
  133.         rson[dad[p]] = q;
  134.     else
  135.         lson[dad[p]] = q;
  136.     dad[p] = NIL;
  137. }
  138.  
  139. /* Huffman coding */
  140.  
  141. #define N_CHAR      (256 - THRESHOLD + F)
  142.                 /* kinds of characters (character code = 0..N_CHAR-1) */
  143. #define T         (N_CHAR * 2 - 1)    /* size of table */
  144. #define R         (T - 1)            /* position of root */
  145. #define MAX_FREQ    0x8000        /* updates tree when the */
  146.                     /* root frequency comes to this value. */
  147. typedef unsigned char uchar;
  148.  
  149.  
  150. /* table for encoding and decoding the upper 6 bits of position */
  151.  
  152. /* for encoding */
  153. uchar p_len[64] = {
  154.     0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
  155.     0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
  156.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  157.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  158.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  159.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  160.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  161.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
  162. };
  163.  
  164. uchar p_code[64] = {
  165.     0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
  166.     0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
  167.     0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
  168.     0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
  169.     0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
  170.     0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
  171.     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  172.     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
  173. };
  174.  
  175. /* for decoding */
  176. uchar d_code[256] = {
  177.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  178.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  179.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  180.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  181.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  182.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  183.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  184.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  185.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  186.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  187.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  188.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  189.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  190.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  191.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  192.     0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  193.     0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
  194.     0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
  195.     0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
  196.     0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
  197.     0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
  198.     0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
  199.     0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
  200.     0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
  201.     0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
  202.     0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
  203.     0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
  204.     0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
  205.     0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
  206.     0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
  207.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  208.     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  209. };
  210.  
  211. uchar d_len[256] = {
  212.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  213.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  214.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  215.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  216.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  217.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  218.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  219.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  220.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  221.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  222.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  223.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  224.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  225.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  226.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  227.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  228.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  229.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  230.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  231.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  232.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  233.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  234.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  235.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  236.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  237.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  238.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  239.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  240.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  241.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  242.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  243.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  244. };
  245.  
  246. unsigned freq[T + 1];    /* frequency table */
  247.  
  248. int prnt[T + N_CHAR];    /* pointers to parent nodes, except for the */
  249.             /* elements [T..T + N_CHAR - 1] which are used to get */
  250.             /* the positions of leaves corresponding to the codes. */
  251.  
  252. int son[T];        /* pointers to child nodes (son[], son[] + 1) */
  253.  
  254. unsigned getbuf = 0;
  255. uchar getlen = 0;
  256.  
  257. int GetBit(void)    /* get one bit */
  258. {
  259.     int i;
  260.  
  261.     while (getlen <= 8) {
  262.         if ((i = getc(infile)) < 0) i = 0;
  263.         getbuf |= i << (8 - getlen);
  264.         getlen += 8;
  265.     }
  266.     i = getbuf;
  267.     getbuf <<= 1;
  268.     getlen--;
  269.     return (i < 0);
  270. }
  271.  
  272. int GetByte(void)    /* get one byte */
  273. {
  274.     unsigned i;
  275.  
  276.     while (getlen <= 8) {
  277.         if ((i = getc(infile)) < 0) i = 0;
  278.         getbuf |= i << (8 - getlen);
  279.         getlen += 8;
  280.     }
  281.     i = getbuf;
  282.     getbuf <<= 8;
  283.     getlen -= 8;
  284.     return i >> 8;
  285. }
  286.  
  287. unsigned putbuf = 0;
  288. uchar putlen = 0;
  289.  
  290. void Putcode(int l, unsigned c)        /* output c bits of code */
  291. {
  292.     putbuf |= c >> putlen;
  293.     if ((putlen += l) >= 8) {
  294.         if (putc(putbuf >> 8, outfile) == EOF) {
  295.             Error(wterr);
  296.         }
  297.         if ((putlen -= 8) >= 8) {
  298.             if (putc(putbuf, outfile) == EOF) {
  299.                 Error(wterr);
  300.             }
  301.             codesize += 2;
  302.             putlen -= 8;
  303.             putbuf = c << (l - putlen);
  304.         } else {
  305.             putbuf <<= 8;
  306.             codesize++;
  307.         }
  308.     }
  309. }
  310.  
  311.  
  312. /* initialization of tree */
  313.  
  314. void StartHuff(void)
  315. {
  316.     int i, j;
  317.  
  318.     for (i = 0; i < N_CHAR; i++) {
  319.         freq[i] = 1;
  320.         son[i] = i + T;
  321.         prnt[i + T] = i;
  322.     }
  323.     i = 0; j = N_CHAR;
  324.     while (j <= R) {
  325.         freq[j] = freq[i] + freq[i + 1];
  326.         son[j] = i;
  327.         prnt[i] = prnt[i + 1] = j;
  328.         i += 2; j++;
  329.     }
  330.     freq[T] = 0xffff;
  331.     prnt[R] = 0;
  332. }
  333.  
  334.  
  335. /* reconstruction of tree */
  336.  
  337. void reconst(void)
  338. {
  339.     int i, j, k;
  340.     unsigned f, l;
  341.  
  342.     /* collect leaf nodes in the first half of the table */
  343.     /* and replace the freq by (freq + 1) / 2. */
  344.     j = 0;
  345.     for (i = 0; i < T; i++) {
  346.         if (son[i] >= T) {
  347.             freq[j] = (freq[i] + 1) / 2;
  348.             son[j] = son[i];
  349.             j++;
  350.         }
  351.     }
  352.     /* begin constructing tree by connecting sons */
  353.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  354.         k = i + 1;
  355.         f = freq[j] = freq[i] + freq[k];
  356.         for (k = j - 1; f < freq[k]; k--);
  357.         k++;
  358.         l = (j - k) * 2;
  359.         memmove(&freq[k + 1], &freq[k], l);
  360.         freq[k] = f;
  361.         memmove(&son[k + 1], &son[k], l);
  362.         son[k] = i;
  363.     }
  364.     /* connect prnt */
  365.     for (i = 0; i < T; i++) {
  366.         if ((k = son[i]) >= T) {
  367.             prnt[k] = i;
  368.         } else {
  369.             prnt[k] = prnt[k + 1] = i;
  370.         }
  371.     }
  372. }
  373.  
  374.  
  375. /* increment frequency of given code by one, and update tree */
  376.  
  377. void update(int c)
  378. {
  379.     int i, j, k, l;
  380.  
  381.     if (freq[R] == MAX_FREQ) {
  382.         reconst();
  383.     }
  384.     c = prnt[c + T];
  385.     do {
  386.         k = ++freq[c];
  387.  
  388.         /* if the order is disturbed, exchange nodes */
  389.         if (k > freq[l = c + 1]) {
  390.             while (k > freq[++l]);
  391.             l--;
  392.             freq[c] = freq[l];
  393.             freq[l] = k;
  394.  
  395.             i = son[c];
  396.             prnt[i] = l;
  397.             if (i < T) prnt[i + 1] = l;
  398.  
  399.             j = son[l];
  400.             son[l] = i;
  401.  
  402.             prnt[j] = c;
  403.             if (j < T) prnt[j + 1] = c;
  404.             son[c] = j;
  405.  
  406.             c = l;
  407.         }
  408.     } while ((c = prnt[c]) != 0);    /* repeat up to root */
  409. }
  410.  
  411. unsigned code, len;
  412.  
  413. void EncodeChar(unsigned c)
  414. {
  415.     unsigned i;
  416.     int j, k;
  417.  
  418.     i = 0;
  419.     j = 0;
  420.     k = prnt[c + T];
  421.  
  422.     /* travel from leaf to root */
  423.     do {
  424.         i >>= 1;
  425.  
  426.         /* if node's address is odd-numbered, choose bigger brother node */
  427.         if (k & 1) i += 0x8000;
  428.  
  429.         j++;
  430.     } while ((k = prnt[k]) != R);
  431.     Putcode(j, i);
  432.     code = i;
  433.     len = j;
  434.     update(c);
  435. }
  436.  
  437. void EncodePosition(unsigned c)
  438. {
  439.     unsigned i;
  440.  
  441.     /* output upper 6 bits by table lookup */
  442.     i = c >> 6;
  443.     Putcode(p_len[i], (unsigned)p_code[i] << 8);
  444.  
  445.     /* output lower 6 bits verbatim */
  446.     Putcode(6, (c & 0x3f) << 10);
  447. }
  448.  
  449. void EncodeEnd(void)
  450. {
  451.     if (putlen) {
  452.         if (putc(putbuf >> 8, outfile) == EOF) {
  453.             Error(wterr);
  454.         }
  455.         codesize++;
  456.     }
  457. }
  458.  
  459. int DecodeChar(void)
  460. {
  461.     unsigned c;
  462.  
  463.     c = son[R];
  464.  
  465.     /* travel from root to leaf, */
  466.     /* choosing the smaller child node (son[]) if the read bit is 0, */
  467.     /* the bigger (son[]+1} if 1 */
  468.     while (c < T) {
  469.         c += GetBit();
  470.         c = son[c];
  471.     }
  472.     c -= T;
  473.     update(c);
  474.     return c;
  475. }
  476.  
  477. int DecodePosition(void)
  478. {
  479.     unsigned i, j, c;
  480.  
  481.     /* recover upper 6 bits from table */
  482.     i = GetByte();
  483.     c = (unsigned)d_code[i] << 6;
  484.     j = d_len[i];
  485.  
  486.     /* read lower 6 bits verbatim */
  487.     j -= 2;
  488.     while (j--) {
  489.         i = (i << 1) + GetBit();
  490.     }
  491.     return c | (i & 0x3f);
  492. }
  493.  
  494. /* compression */
  495.  
  496. void Encode(void)  /* compression */
  497. {
  498.     int  i, c, len, r, s, last_match_length;
  499.  
  500.     fseek(infile, 0L, 2);
  501.     textsize = ftell(infile);
  502.     if (fwrite(&textsize, sizeof textsize, 1, outfile) < 1)
  503.         Error(wterr);    /* output size of text */
  504.     if (textsize == 0)
  505.         return;
  506.     rewind(infile);
  507.     textsize = 0;            /* rewind and re-read */
  508.     StartHuff();
  509.     InitTree();
  510.     s = 0;
  511.     r = N - F;
  512.     for (i = s; i < r; i++)
  513.         text_buf[i] = ' ';
  514.     for (len = 0; len < F && (c = getc(infile)) != EOF; len++)
  515.         text_buf[r + len] = c;
  516.     textsize = len;
  517.     for (i = 1; i <= F; i++)
  518.         InsertNode(r - i);
  519.     InsertNode(r);
  520.     do {
  521.         if (match_length > len)
  522.             match_length = len;
  523.         if (match_length <= THRESHOLD) {
  524.             match_length = 1;
  525.             EncodeChar(text_buf[r]);
  526.         } else {
  527.             EncodeChar(255 - THRESHOLD + match_length);
  528.             EncodePosition(match_position);
  529.         }
  530.         last_match_length = match_length;
  531.         for (i = 0; i < last_match_length &&
  532.                 (c = getc(infile)) != EOF; i++) {
  533.             DeleteNode(s);
  534.             text_buf[s] = c;
  535.             if (s < F - 1)
  536.                 text_buf[s + N] = c;
  537.             s = (s + 1) & (N - 1);
  538.             r = (r + 1) & (N - 1);
  539.             InsertNode(r);
  540.         }
  541.         if ((textsize += i) > printcount) {
  542.             printf("%12ld\r", textsize);
  543.             printcount += 1024;
  544.         }
  545.         while (i++ < last_match_length) {
  546.             DeleteNode(s);
  547.             s = (s + 1) & (N - 1);
  548.             r = (r + 1) & (N - 1);
  549.             if (--len) InsertNode(r);
  550.         }
  551.     } while (len > 0);
  552.     EncodeEnd();
  553.     printf("In : %ld bytes\n", textsize);
  554.     printf("Out: %ld bytes\n", codesize);
  555.     printf("Out/In: %.3f\n", (double)codesize / textsize);
  556. }
  557.  
  558. void Decode(void)  /* recover */
  559. {
  560.     int  i, j, k, r, c;
  561.     unsigned long int  count;
  562.  
  563.     if (fread(&textsize, sizeof textsize, 1, infile) < 1)
  564.         Error("Can't read");  /* read size of text */
  565.     if (textsize == 0)
  566.         return;
  567.     StartHuff();
  568.     for (i = 0; i < N - F; i++)
  569.         text_buf[i] = ' ';
  570.     r = N - F;
  571.     for (count = 0; count < textsize; ) {
  572.         c = DecodeChar();
  573.         if (c < 256) {
  574.             if (putc(c, outfile) == EOF) {
  575.                 Error(wterr);
  576.             }
  577.             text_buf[r++] = c;
  578.             r &= (N - 1);
  579.             count++;
  580.         } else {
  581.             i = (r - DecodePosition() - 1) & (N - 1);
  582.             j = c - 255 + THRESHOLD;
  583.             for (k = 0; k < j; k++) {
  584.                 c = text_buf[(i + k) & (N - 1)];
  585.                 if (putc(c, outfile) == EOF) {
  586.                     Error(wterr);
  587.                 }
  588.                 text_buf[r++] = c;
  589.                 r &= (N - 1);
  590.                 count++;
  591.             }
  592.         }
  593.         if (count > printcount) {
  594.             printf("%12ld\r", count);
  595.             printcount += 1024;
  596.         }
  597.     }
  598.     printf("%12ld\n", count);
  599. }
  600.  
  601. int main(int argc, char *argv[])
  602. {
  603.     char  *s;
  604.  
  605.     if (argc != 4) {
  606.         printf("'lzhuf e file1 file2' encodes file1 into file2.\n"
  607.                "'lzhuf d file2 file1' decodes file2 into file1.\n");
  608.         return EXIT_FAILURE;
  609.     }
  610.     if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
  611.      || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
  612.      || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
  613.         printf("??? %s\n", s);
  614.         return EXIT_FAILURE;
  615.     }
  616.     if (toupper(*argv[1]) == 'E')
  617.         Encode();
  618.     else
  619.         Decode();
  620.     fclose(infile);
  621.     fclose(outfile);
  622.     return EXIT_SUCCESS;
  623. }
  624.