home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2141 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  32.8 KB

  1. From: apg@hq.demos.su (Paul G. Antonov)
  2. Newsgroups: alt.sources
  3. Subject: Freeze/Melt program
  4. Message-ID: <1990Nov24.184206.936@hq.demos.su>
  5. Date: 24 Nov 90 18:42:06 GMT
  6.  
  7.  
  8.      ___________________________________________________
  9.     / Please send the comments, bug fixes,              \
  10.     | compression/speed improvement patches DIRECTLY to |
  11.     \              <leo@s514.ipmce.su>.                 /
  12.      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13. This program is a "compilation" from compress - GNU FSF and
  14. lharc (lzhuf) - H. Yoshizaki & M. Tagawa.
  15. Two minor improvements were made - pipe facility and 20% speedup
  16. by moving the code of GetBit routine into DecodeChar routine.
  17.  
  18. ----------------------- cut here -------------------------
  19. /*
  20.  * Freeze - data freezing program
  21.  * Version 1.0:
  22.  * This program is made from GNU compress.c and Yoshizaki/Tagawa's
  23.  * lzhuf.c. (Thanks to all of them.)
  24.  * The algorithm is modified for using in pipe
  25.  * (added ENDOF symbol in Huffman table).
  26.  * Version 1.1:
  27.  * Check for lack of bytes in frozen file when melting.
  28.  * Put the GetBit routine into DecodeChar for reduce function-
  29.  * call overhead when melting.
  30.  *
  31.  * I think the code is portable, but it is presently working only
  32.  * under SCO XENIX and ix/386 (compiled with GNU C).
  33.  */
  34. char magic_header[] = { "\037\236" };      /* 1F 9E = compress + 1 */
  35.  
  36. static char ident[] = "@(#) freeze.c 1.1 11/24/90 leo@s514.ipmce.su";
  37.  
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <signal.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43.  
  44. #ifdef MSDOS
  45. #include <stdlib.h>
  46. #endif
  47.  
  48. #define ARGVAL() (*++(*argv) || (--argc && *++argv))
  49.  
  50.  
  51. int exit_stat = 0;
  52.  
  53. Usage() {
  54. #ifdef DEBUG
  55.  
  56. # ifdef MSDOS
  57.     fprintf(stderr,"Usage: freeze [-cdDfivV] [file ...]\n");
  58. # else
  59.     fprintf(stderr,"Usage: freeze [-cdDfvV] [file ...]\n");
  60. # endif /* MSDOS */
  61.  
  62. }
  63. int debug = 0;
  64. #else
  65.  
  66. # ifdef MSDOS
  67.     fprintf(stderr,"Usage: freeze [-cdfivV] [file ...]\n");
  68. # else
  69.     fprintf(stderr,"Usage: freeze [-cdfvV] [file ...]\n");
  70. # endif /* MSDOS */
  71.  
  72. }
  73. #endif /* DEBUG */
  74. int fcat_flg = 0;       /* Write output on stdout, suppress messages */
  75. int precious = 1;    /* Don't unlink output file on interrupt */
  76. int quiet = 1;      /* don't tell me about freezing */
  77.  
  78. /* Note indicator_threshold is triangle number of Kbytes (see below) */
  79.  
  80. long int indicator_threshold, indicator_count;
  81.  
  82. int force = 0;
  83. char ofname [100];
  84.  
  85. #ifdef MSDOS
  86. # define PATH_SEP '\\'
  87. int image = 2;        /* 1 <=> image (binary) mode; 2 <=> text mode */
  88. #else
  89. # define PATH_SEP '/'
  90. #endif
  91.  
  92. #ifdef DEBUG
  93. int verbose = 0;
  94. char * pr_char();
  95. long symbols_out = 0, refers_out = 0;
  96. #endif /* DEBUG */
  97. int (*bgnd_flag)();
  98.  
  99. int do_melt = 0;
  100.  
  101. /*****************************************************************
  102.  * TAG( main )
  103.  *
  104.  *
  105.  * Usage: freeze [-cdfivV] [file ...]
  106.  * Inputs:
  107.  *
  108.  *    -c:        Write output on stdout, don't remove original.
  109.  *
  110.  *      -d:     If given, melting is done instead.
  111.  *
  112.  *    -f:        Forces output file to be generated, even if one already
  113.  *          exists, and even if no space is saved by freezeing.
  114.  *            If -f is not used, the user will be prompted if stdin is
  115.  *            a tty, otherwise, the output file will not be overwritten.
  116.  *
  117.  *    -i:        Image mode (defined only under MS-DOS).  Prevents
  118.  *            conversion between UNIX text representation (LF line
  119.  *          termination) in frozen form and MS-DOS text
  120.  *          representation (CR-LF line termination) in melted
  121.  *            form.  Useful with non-text files.
  122.  *
  123.  *      -v:     Write freezing statistics
  124.  *
  125.  *    -V:        Write version and compilation options.
  126.  *
  127.  *      file ...:   Files to be frozen.  If none specified, stdin
  128.  *            is used.
  129.  * Outputs:
  130.  *      file.F:     Frozen form of file with same mode, owner, and utimes
  131.  *    or stdout   (if stdin used as input)
  132.  *
  133.  * Assumptions:
  134.  *      When filenames are given, replaces with the frozen version
  135.  *      (.F suffix) only if the file decreases in size.
  136.  * Algorithm:
  137.  *      Modified Lempel-Ziv-SS method (LZSS), adaptive Huffman coding
  138.  *      for literal symbols and length info.
  139.  *      Static Huffman coding for position info. (It is optimal ?)
  140.  *      Lower bits of position info are put in output
  141.  *      file without any coding because of their random distribution.
  142.  */
  143.  
  144. /* From compress.c. Replace .Z --> .F etc */
  145.  
  146. main( argc, argv )
  147. register int argc; char **argv;
  148. {
  149.     int overwrite = 0;    /* Do not overwrite unless given -f flag */
  150.     char tempname[100];
  151.     char **filelist, **fileptr;
  152.     char *cp, *rindex(), *malloc();
  153.     struct stat statbuf;
  154.     extern onintr();
  155.  
  156. #ifdef MSDOS
  157.     char *sufp;
  158. #else
  159.     extern oops();
  160. #endif
  161.  
  162. #ifndef MSDOS
  163. #ifdef __GNUC__
  164.     if ( (bgnd_flag = (int (*) ()) signal ( SIGINT, SIG_IGN )) != (int (*) ()) SIG_IGN )
  165. #else
  166.     if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN )
  167. #endif
  168. #endif
  169.     {
  170.     signal ( SIGINT, onintr );
  171. #ifndef MSDOS
  172.     signal ( SIGSEGV, oops );
  173. #endif
  174.     }
  175.  
  176.     filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
  177.     *filelist = NULL;
  178.  
  179.     if((cp = rindex(argv[0], PATH_SEP)) != 0) {
  180.     cp++;
  181.     } else {
  182.     cp = argv[0];
  183.     }
  184.  
  185. #ifdef MSDOS
  186.     if(strcmp(cp, "MELT.EXE") == 0) {
  187. #else
  188.     if(strcmp(cp, "melt") == 0) {
  189. #endif
  190.  
  191.     do_melt = 1;
  192.     
  193. #ifdef MSDOS
  194.     } else if(strcmp(cp, "FCAT.EXE") == 0) {
  195. #else
  196.     } else if(strcmp(cp, "fcat") == 0) {
  197. #endif
  198.  
  199.     do_melt = 1;
  200.     fcat_flg = 1;
  201.     }
  202.  
  203. #ifdef BSD4_2
  204.     /* 4.2BSD dependent - take it out if not */
  205.     setlinebuf( stderr );
  206. #endif /* BSD4_2 */
  207.  
  208.     /* Argument Processing
  209.      * All flags are optional.
  210.      * -D => debug
  211.      * -V => print Version; debug verbose
  212.      * -d => do_melt
  213.      * -v => unquiet
  214.      * -f => force overwrite of output file
  215.      * -c => cat all output to stdout
  216.      * if a string is left, must be an input filename.
  217.      */
  218.     for (argc--, argv++; argc > 0; argc--, argv++) {
  219.     if (**argv == '-') {    /* A flag argument */
  220.         while (*++(*argv)) {    /* Process all flags in this arg */
  221.         switch (**argv) {
  222. #ifdef DEBUG
  223.             case 'D':
  224.             debug = 1;
  225.             break;
  226.             case 'V':
  227.             verbose = 1;
  228.             version();
  229.             break;
  230. #else
  231.             case 'V':
  232.             version();
  233.             break;
  234. #endif /* DEBUG */
  235.  
  236. #ifdef MSDOS
  237.             case 'i':
  238.             image = 1;
  239.             break;
  240. #endif
  241.  
  242.             case 'v':
  243.             quiet = 0;
  244.             break;
  245.             case 'd':
  246.             do_melt = 1;
  247.             break;
  248.             case 'f':
  249.             case 'F':
  250.             overwrite = 1;
  251.             force = 1;
  252.             break;
  253.             case 'c':
  254.             fcat_flg = 1;
  255.             break;
  256.             case 'q':
  257.             quiet = 1;
  258.             break;
  259.             default:
  260.             fprintf(stderr, "Unknown flag: '%c'; ", **argv);
  261.             Usage();
  262.             exit(1);
  263.         }
  264.         }
  265.     }
  266.     else {        /* Input file name */
  267.         *fileptr++ = *argv; /* Build input file list */
  268.         *fileptr = NULL;
  269.     }
  270.     }
  271.  
  272.     if (*filelist != NULL) {
  273.     for (fileptr = filelist; *fileptr; fileptr++) {
  274.         exit_stat = 0;
  275.         if (do_melt != 0) {               /* MELTING */
  276.  
  277. #ifdef MSDOS
  278.         /* Check for .F or XF suffix; add one if necessary */
  279.         cp = *fileptr + strlen(*fileptr) - 2;
  280.         if ((*cp != '.' && *cp != 'X' && *cp != 'x') ||
  281.             (*(++cp) != 'F' && *cp != 'f')) {
  282.             strcpy(tempname, *fileptr);
  283.             if ((cp=rindex(tempname,'.')) == NULL)
  284.             strcat(tempname, ".F");
  285.             else if(*(++cp) == '\0') strcat(tempname, "F");
  286.             else {
  287.             *(++cp) = '\0';
  288.             strcat(tempname, "XF");
  289.             }
  290.             *fileptr = tempname;
  291.         }
  292. #else
  293.         /* Check for .F suffix */
  294.         if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") != 0) {
  295.             /* No .F: tack one on */
  296.             strcpy(tempname, *fileptr);
  297.             strcat(tempname, ".F");
  298.             *fileptr = tempname;
  299.         }
  300. #endif /*MSDOS */
  301.  
  302.         /* Open input file for melting */
  303.  
  304. #ifdef MSDOS
  305.         if ((freopen(*fileptr, "rb", stdin)) == NULL)
  306. #else
  307.         if ((freopen(*fileptr, "r", stdin)) == NULL)
  308. #endif
  309.         {
  310.             perror(*fileptr); continue;
  311.         }
  312.         /* Check the magic number */
  313.         if ((getchar() != (magic_header[0] & 0xFF))
  314.          || (getchar() != (magic_header[1] & 0xFF))) {
  315.             fprintf(stderr, "%s: not in frozen format\n",
  316.             *fileptr);
  317.         continue;
  318.         }
  319.         /* Generate output filename */
  320.         strcpy(ofname, *fileptr);
  321.         ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .F */
  322.         } else {                    /* FREEZING */
  323.  
  324. #ifdef MSDOS
  325.         cp = *fileptr + strlen(*fileptr) - 2;
  326.         if ((*cp == '.' || *cp == 'X' || *cp == 'x') &&
  327.             (*(++cp) == 'F' || *cp == 'f')) {
  328.             fprintf(stderr,"%s: already has %s suffix -- no change\n",
  329.             *fileptr,--cp); /* } */
  330. #else
  331.         if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") == 0) {
  332.             fprintf(stderr, "%s: already has .F suffix -- no change\n",
  333.             *fileptr);
  334. #endif /* MSDOS */
  335.  
  336.             continue;
  337.         }
  338.         /* Open input file for freezing */
  339.  
  340. #ifdef MSDOS
  341.         if ((freopen(*fileptr, image == 2 ? "rt" : "rb", stdin))
  342.             == NULL)
  343. #else
  344.         if ((freopen(*fileptr, "r", stdin)) == NULL)
  345. #endif
  346.         {
  347.             perror(*fileptr); continue;
  348.         }
  349.         stat ( *fileptr, &statbuf );
  350.  
  351.         /* Generate output filename */
  352.         strcpy(ofname, *fileptr);
  353. #ifndef BSD4_2        /* Short filenames */
  354.         if ((cp = rindex(ofname, PATH_SEP)) != NULL) cp++;
  355.         else                    cp = ofname;
  356. # ifdef MSDOS
  357.         if (fcat_flg == 0 && (sufp = rindex(cp, '.')) != NULL &&
  358.             strlen(sufp) > 2) fprintf(stderr,
  359.             "%s: part of filename extension will be replaced by XF\n",
  360.             cp);
  361. # else
  362.         if (strlen(cp) > 12) {
  363.             fprintf(stderr,"%s: filename too long to tack on .F\n",cp);
  364.             continue;
  365.         }
  366. # endif
  367. #endif    /* BSD4_2        Long filenames allowed */
  368.                              
  369. #ifdef MSDOS
  370.         if ((cp = rindex(ofname, '.')) == NULL) strcat(ofname, ".F");
  371.         else {
  372.            if(*(++cp) != '\0') *(++cp) = '\0';
  373.            strcat(ofname, "XF");
  374.         }
  375. #else
  376.         strcat(ofname, ".F");
  377. #endif /* MSDOS */
  378.  
  379.         }
  380.         precious = 0;
  381.         /* Check for overwrite of existing file */
  382.         if (overwrite == 0 && fcat_flg == 0) {
  383.         if (stat(ofname, &statbuf) == 0) {
  384.             char response[2];
  385.             response[0] = 'n';
  386.             fprintf(stderr, "%s already exists;", ofname);
  387. #ifndef MSDOS
  388.             if (foreground()) {
  389. #endif
  390.             fprintf(stderr,
  391.                 " do you wish to overwrite %s (y or n)? ", ofname);
  392.             fflush(stderr);
  393.             read(2, response, 2);
  394.             while (response[1] != '\n') {
  395.                 if (read(2, response+1, 1) < 0) {    /* Ack! */
  396.                 perror("stderr"); break;
  397.                 }
  398.             }
  399. #ifndef MSDOS
  400.             }
  401. #endif
  402.             if (response[0] != 'y') {
  403.             fprintf(stderr, "\tnot overwritten\n");
  404.             continue;
  405.             }
  406.         }
  407.         }
  408.         if(fcat_flg == 0) {     /* Open output file */
  409.  
  410. #ifdef DEBUG
  411.         if (do_melt == 0 || debug == 0) {
  412. #endif
  413. #ifdef MSDOS
  414.         if (freopen(ofname, do_melt && image == 2 ? "wt" : "wb",
  415.             stdout) == NULL)
  416. #else         
  417.         if (freopen(ofname, "w", stdout) == NULL)
  418. #endif
  419.         {
  420.             perror(ofname); continue;
  421.         }
  422. #ifdef DEBUG
  423.         }
  424. #endif
  425.         if(!quiet) {
  426.             fprintf(stderr, "%s:", *fileptr);
  427.             indicator_threshold = 2048;
  428.             indicator_count = 1024;
  429.         }
  430.         }
  431.         /* Actually do the freezing/melting */
  432.         if (do_melt == 0) freeze();
  433. #ifndef DEBUG
  434.         else            melt();
  435. #else
  436.         else if (debug == 0)    melt();
  437.         else            printcodes();
  438. #endif /* DEBUG */
  439.         if(fcat_flg == 0) {
  440.         copystat(*fileptr, ofname);    /* Copy stats */
  441.         if((exit_stat == 1) || (!quiet))
  442.             putc('\n', stderr);
  443.         }
  444.      }
  445.     } else {        /* Standard input */
  446.     if (do_melt == 0) {
  447.         freeze();
  448.         if(!quiet)
  449.             putc('\n', stderr);
  450.     } else {
  451.         /* Check the magic number */
  452.         if ((getchar()!=(magic_header[0] & 0xFF))
  453.          || (getchar()!=(magic_header[1] & 0xFF))) {
  454.         fprintf(stderr, "stdin: not in frozen format\n");
  455.         exit(1);
  456.         }
  457. #ifndef DEBUG
  458.         melt();
  459. #else
  460.         if (debug == 0)     melt();
  461.         else        printcodes();
  462. #endif /* DEBUG */
  463.     }
  464.     }
  465.     exit(exit_stat);
  466. }
  467.  
  468. long int in_count = 1;            /* length of input */
  469. long int bytes_out;             /* length of frozen output */
  470.  
  471. /*----------------------------------------------------------------------*/
  472. /*                                    */
  473. /*              LZSS ENCODING   (lzhuf.c)                               */
  474. /*                                    */
  475. /*----------------------------------------------------------------------*/
  476.  
  477. #ifdef  lint
  478. #define N               256
  479. #else
  480. #define N               4096    /* buffer size */
  481. #endif
  482.  
  483. #define F        60    /* pre-sence buffer size */
  484. #define THRESHOLD    2
  485. #define NIL        N    /* term of tree */
  486. /*
  487.  * Increasing of N and F ( N = 8192, F = 80) gives 1.2 - 1.5% of additional
  488.  * reducing, but 2 times slower.
  489.  */
  490. unsigned char    text_buf[N + F - 1];
  491. unsigned int     match_position, match_length;
  492. short            lson[N + 1], rson[N + 1 + N], dad[N + 1];
  493. unsigned char    same[N + 1];
  494.  
  495.  
  496. /* Initialize Tree */
  497. InitTree ()
  498. {
  499.     register short *p, *e;
  500.  
  501.     for (p = rson + N + 1, e = rson + N + N; p <= e; )
  502.         *p++ = NIL;
  503.     for (p = dad, e = dad + N; p < e; )
  504.         *p++ = NIL;
  505. }
  506.  
  507.  
  508. /* Insert to node */
  509. InsertNode (r)
  510.     register int r;
  511. {
  512.     register int        p;
  513.     int            cmp;
  514.     register unsigned char    *key;
  515.     register unsigned int    c;
  516.     register unsigned int    i, j;
  517.  
  518.     cmp = 1;
  519.     key = &text_buf[r];
  520.     i = key[1] ^ key[2];
  521.     i ^= i >> 4;
  522.     p = N + 1 + key[0] + ((i & 0x0f) << 8);
  523.     rson[r] = lson[r] = NIL;
  524.     match_length = 0;
  525.     i = j = 1;
  526.     for ( ; ; ) {
  527.         if (cmp >= 0) {
  528.             if (rson[p] != NIL) {
  529.                 p = rson[p];
  530.                 j = same[p];
  531.             } else {
  532.                 rson[p] = r;
  533.                 dad[r] = p;
  534.                 same[r] = i;
  535.                 return;
  536.             }
  537.         } else {
  538.             if (lson[p] != NIL) {
  539.                 p = lson[p];
  540.                 j = same[p];
  541.             } else {
  542.                 lson[p] = r;
  543.                 dad[r] = p;
  544.                 same[r] = i;
  545.                 return;
  546.             }
  547.         }
  548.  
  549.         if (i > j) {
  550.             i = j;
  551.             cmp = key[i] - text_buf[p + i];
  552.         } else
  553.         if (i == j) {
  554.             for (; i < F; i++)
  555.                 if ((cmp = key[i] - text_buf[p + i]) != 0)
  556.                     break;
  557.         }
  558.  
  559.         if (i > THRESHOLD) {
  560.             if (i > match_length) {
  561.                 match_position = ((r - p) & (N - 1)) - 1;
  562.                 if ((match_length = i) >= F)
  563.                     break;
  564.             } else
  565.             if (i == match_length) {
  566.                 if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
  567.                     match_position = c;
  568.                 }
  569.             }
  570.         }
  571.     }
  572.     same[r] = same[p];
  573.     dad[r] = dad[p];
  574.     lson[r] = lson[p];
  575.     rson[r] = rson[p];
  576.     dad[lson[p]] = r;
  577.     dad[rson[p]] = r;
  578.     if (rson[dad[p]] == p)
  579.         rson[dad[p]] = r;
  580.     else
  581.         lson[dad[p]] = r;
  582.     dad[p] = NIL;  /* remove p */
  583. }
  584.  
  585. static
  586. void
  587. link (n, p, q)
  588.     int n, p, q;
  589. {
  590.     register unsigned char *s1, *s2, *s3;
  591.     if (p >= NIL) {
  592.         same[q] = 1;
  593.         return;
  594.     }
  595.     s1 = text_buf + p + n;
  596.     s2 = text_buf + q + n;
  597.     s3 = text_buf + p + F;
  598.     while (s1 < s3) {
  599.         if (*s1++ != *s2++) {
  600. #ifdef __GNUC__         /* Not an ideal compiler !! */
  601.             n = s1 - text_buf;
  602.             same[q] = n - 1 - p;
  603. #else
  604.             same[q] = s1 - 1 - text_buf - p;
  605. #endif
  606.             return;
  607.         }
  608.     }
  609.     same[q] = F;
  610. }
  611.  
  612.  
  613. linknode (p, q, r)
  614.     int p, q, r;
  615. {
  616.     int cmp;
  617.  
  618.     if ((cmp = same[q] - same[r]) == 0) {
  619.         link((int)same[q], p, r);
  620.     } else if (cmp < 0) {
  621.         same[r] = same[q];
  622.     }
  623. }
  624.  
  625. DeleteNode (p)
  626.     register int p;
  627. {
  628.     register int  q;
  629.  
  630.     if (dad[p] == NIL)
  631.         return;            /* has no linked */
  632.     if (rson[p] == NIL) {
  633.         if ((q = lson[p]) != NIL)
  634.             linknode(dad[p], p, q);
  635.     } else
  636.     if (lson[p] == NIL) {
  637.         q = rson[p];
  638.         linknode(dad[p], p, q);
  639.     } else {
  640.         q = lson[p];
  641.         if (rson[q] != NIL) {
  642.             do {
  643.                 q = rson[q];
  644.             } while (rson[q] != NIL);
  645.             if (lson[q] != NIL)
  646.                 linknode(dad[q], q, lson[q]);
  647.             link(1, q, lson[p]);
  648.             rson[dad[q]] = lson[q];
  649.             dad[lson[q]] = dad[q];
  650.             lson[q] = lson[p];
  651.             dad[lson[p]] = q;
  652.         }
  653.         link(1, dad[p], q);
  654.         link(1, q, rson[p]);
  655.         rson[q] = rson[p];
  656.         dad[rson[p]] = q;
  657.     }
  658.     dad[q] = dad[p];
  659.     if (rson[dad[p]] == p)
  660.         rson[dad[p]] = q;
  661.     else
  662.         lson[dad[p]] = q;
  663.     dad[p] = NIL;
  664. }
  665.  
  666. /*----------------------------------------------------------------------*/
  667. /*                                    */
  668. /*        HUFFMAN ENCODING                    */
  669. /*                                    */
  670. /*----------------------------------------------------------------------*/
  671.  
  672. #define N_CHAR          (256 - THRESHOLD + F + 1) /* {code : 0 .. N_CHAR-1} */
  673. #define T         (N_CHAR * 2 - 1)    /* size of table */
  674. #define R         (T - 1)            /* root position */
  675.  
  676. #define MAX_FREQ        (unsigned)0x8000 /* tree update timing from frequency */
  677.  
  678. #define ENDOF           256
  679.  
  680. typedef unsigned char uchar;
  681.  
  682. /* TABLE OF ENCODE/DECODE for upper 6bits position information */
  683.  
  684. /* for encode */
  685. uchar p_len[64] = {
  686.     0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
  687.     0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
  688.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  689.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  690.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  691.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  692.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  693.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
  694. };
  695.  
  696. uchar p_code[64] = {
  697.     0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
  698.     0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
  699.     0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
  700.     0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
  701.     0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
  702.     0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
  703.     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
  704.     0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
  705. };
  706.  
  707. /* for decode */
  708. uchar d_code[256] = {
  709.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  710.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  711.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  712.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  713.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  714.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  715.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  716.     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
  717.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  718.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  719.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  720.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  721.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  722.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  723.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  724.     0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
  725.     0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
  726.     0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
  727.     0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
  728.     0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
  729.     0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
  730.     0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
  731.     0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
  732.     0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
  733.     0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
  734.     0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
  735.     0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
  736.     0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
  737.     0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
  738.     0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
  739.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  740.     0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  741. };
  742.  
  743. uchar d_len[256] = {
  744.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  745.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  746.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  747.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  748.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  749.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  750.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  751.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  752.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  753.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
  754.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  755.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  756.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  757.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  758.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  759.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  760.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  761.     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
  762.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  763.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  764.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  765.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  766.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  767.     0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
  768.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  769.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  770.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  771.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  772.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  773.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  774.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  775.     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
  776. };
  777.  
  778. unsigned short freq[T + 1];    /* frequency table */
  779.  
  780. short    prnt[T + N_CHAR];    /* points to parent node */
  781. /* notes :
  782.    prnt[T .. T + N_CHAR - 1] used by
  783.    indicates leaf position that corresponding to code */
  784.  
  785. short son[T];           /* points to son node (son[i],son[i+]) */
  786.  
  787. unsigned short getbuf = 0;
  788. uchar    getlen = 0;
  789.  
  790. uchar corrupt_flag = 0;         /* If a file is corrupt, use fcat */
  791.  
  792. /* get one byte */
  793. /* returning in Bit7...0 */
  794. int GetByte ()
  795. {
  796.     register unsigned short int dx = getbuf;
  797.     register unsigned int c;
  798.  
  799.     if (getlen <= 8) {
  800.         c = getchar ();
  801.         if ((int)c < 0) {
  802. /* Frozen file is too short. This is fatal error.
  803.  * Really the second absent byte indicates a error.
  804.  * ("Packed file is corrupt." :-) )
  805.  */
  806.             if (corrupt_flag)
  807.             oops();
  808.             corrupt_flag = 1;
  809.             c = 0;
  810.         }
  811.         dx |= c << (8 - getlen);
  812.         getlen += 8;
  813.     }
  814.     getbuf = dx << 8;
  815.     getlen -= 8;
  816.     return (dx >> 8) & 0xff;
  817. }
  818.  
  819. /* get N bit */
  820. /* returning in Bit(N-1)...Bit 0 */
  821. int GetNBits (n)
  822.     register unsigned int n;
  823. {
  824.     register unsigned int dx = getbuf;
  825.     register unsigned int c;
  826.     static int mask[17] = {
  827.         0x0000,
  828.         0x0001, 0x0003, 0x0007, 0x000f,
  829.         0x001f, 0x003f, 0x007f, 0x00ff,
  830.         0x01ff, 0x03ff, 0x07ff, 0x0fff,
  831.         0x1fff, 0x3fff, 0x7fff, 0xffff };
  832.     static int shift[17] = {
  833.         16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
  834.  
  835.     if (getlen <= 8)
  836.         {
  837.             c = getchar ();
  838.             if ((int)c < 0) {
  839.                 if (corrupt_flag)
  840.                 oops();
  841.                 corrupt_flag = 1;
  842.                 c = 0;
  843.             }
  844.             dx |= c << (8 - getlen);
  845.             getlen += 8;
  846.         }
  847.     getbuf = dx << n;
  848.     getlen -= n;
  849.     return (dx >> shift[n]) & mask[n];
  850. }
  851.  
  852. unsigned short putbuf = 0;
  853. uchar putlen = 0;
  854.  
  855. /* output C bits */
  856. Putcode (l, c)
  857.     register int l;
  858.     unsigned int c;
  859. {
  860.     register short len = putlen;
  861.     register unsigned short b = putbuf;
  862.     b |= c >> len;
  863.     if ((len += l) >= 8) {
  864.         if (putchar (b >> 8) == EOF) writeerr();
  865.         if ((len -= 8) >= 8) {
  866.             putchar (b);
  867.             bytes_out += 2;
  868.             len -= 8;
  869.             b = c << (l - len);
  870.         } else {
  871.             b <<= 8;
  872.             bytes_out++;
  873.         }
  874.     }
  875.     putbuf = b;
  876.     putlen = len;
  877. }
  878.  
  879.  
  880. /* Initialize tree */
  881.  
  882. StartHuff ()
  883. {
  884.     register int i, j;
  885.  
  886.     for (i = 0; i < N_CHAR; i++) {
  887.         freq[i] = 1;
  888.         son[i] = i + T;
  889.         prnt[i + T] = i;
  890.     }
  891.     i = 0; j = N_CHAR;
  892.     while (j <= R) {
  893.         freq[j] = freq[i] + freq[i + 1];
  894.         son[j] = i;
  895.         prnt[i] = prnt[i + 1] = j;
  896.         i += 2; j++;
  897.     }
  898.     freq[T] = 0xffff;
  899.     prnt[R] = 0;
  900.     in_count = 1;
  901.     bytes_out = 2;
  902. #ifdef DEBUG
  903.     symbols_out = refers_out = 0;
  904. #endif
  905.     putlen = getlen = 0;
  906.     putbuf = getbuf = 0;
  907.     corrupt_flag = 0;
  908. }
  909.  
  910.  
  911. /* reconstruct tree */
  912. reconst ()
  913. {
  914.     register int i, j, k;
  915.     register unsigned f;
  916. #ifdef DEBUG
  917.     if (!quiet)
  918.       fprintf(stderr,
  919.         "Reconstructing Huffman tree: symbols: %ld, references: %ld\n",
  920.         symbols_out, refers_out);
  921. #endif
  922.     /* correct leaf node into of first half,
  923.        and set these freqency to (freq+1)/2       */
  924.     j = 0;
  925.     for (i = 0; i < T; i++) {
  926.         if (son[i] >= T) {
  927.             freq[j] = (freq[i] + 1) / 2;
  928.             son[j] = son[i];
  929.             j++;
  930.         }
  931.     }
  932.     /* build tree.  Link sons first */
  933.     for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
  934.         k = i + 1;
  935.         f = freq[j] = freq[i] + freq[k];
  936.         for (k = j - 1; f < freq[k]; k--);
  937.         k++;
  938.         {       register unsigned short *p, *e;
  939.             for (p = &freq[j], e = &freq[k]; p > e; p--)
  940.                 p[0] = p[-1];
  941.             freq[k] = f;
  942.         }
  943.         {       register short *p, *e;
  944.             for (p = &son[j], e = &son[k]; p > e; p--)
  945.                 p[0] = p[-1];
  946.             son[k] = i;
  947.         }
  948.     }
  949.     /* link parents */
  950.     for (i = 0; i < T; i++) {
  951.         if ((k = son[i]) >= T) {
  952.             prnt[k] = i;
  953.         } else {
  954.             prnt[k] = prnt[k + 1] = i;
  955.         }
  956.     }
  957. }
  958.  
  959.  
  960. /* update given code's frequency, and update tree */
  961.  
  962. update (c)
  963.     unsigned int    c;
  964. {
  965.     register unsigned short *p;
  966.     register int i, j, k, l;
  967.  
  968.     if (freq[R] == MAX_FREQ) {
  969.         reconst();
  970.     }
  971.     c = prnt[c + T];
  972.     do {
  973.         k = ++freq[c];
  974.  
  975.         /* swap nodes when become wrong frequency order. */
  976.         if (k > freq[l = c + 1]) {
  977.             for (p = freq+l+1; k > *p++; ) ;
  978.             l = p - freq - 2;
  979.             freq[c] = p[-2];
  980.             p[-2] = k;
  981.  
  982.             i = son[c];
  983.             prnt[i] = l;
  984.             if (i < T) prnt[i + 1] = l;
  985.  
  986.             j = son[l];
  987.             son[l] = i;
  988.  
  989.             prnt[j] = c;
  990.             if (j < T) prnt[j + 1] = c;
  991.             son[c] = j;
  992.  
  993.             c = l;
  994.         }
  995.     } while ((c = prnt[c]) != 0);    /* loop until reach to root */
  996. }
  997.  
  998. /* unsigned code, len; */
  999.  
  1000. EncodeChar (c)
  1001.     unsigned c;
  1002. {
  1003.     register short *p;
  1004.     unsigned long i;
  1005.     register int j, k;
  1006.  
  1007.     i = 0;
  1008.     j = 0;
  1009.     p = prnt;
  1010.     k = p[c + T];
  1011.  
  1012.     /* trace links from leaf node to root */
  1013.     do {
  1014.         i >>= 1;
  1015.  
  1016.         /* if node index is odd, trace larger of sons */
  1017.         if (k & 1) i += 0x80000000;
  1018.  
  1019.         j++;
  1020.     } while ((k = p[k]) != R) ;
  1021.     if (j > 16) {
  1022.         Putcode(16, (unsigned int)(i >> 16));
  1023.         Putcode(j - 16, (unsigned int)i);
  1024.     } else {
  1025.         Putcode(j, (unsigned int)(i >> 16));
  1026.     }
  1027. /*    code = i; */
  1028. /*     len = j; */
  1029.     update(c);
  1030. }
  1031.  
  1032. EncodePosition (c)
  1033.     register unsigned c;
  1034. {
  1035.     register unsigned i;
  1036.  
  1037.     /* output upper 6bit from table */
  1038.     i = c >> 6;
  1039.     Putcode((int)(p_len[i]), (unsigned int)(p_code[i]) << 8);
  1040.  
  1041.     /* output lower 6 bit */
  1042.     Putcode(6, (unsigned int)(c & 0x3f) << 10);
  1043. }
  1044.  
  1045. EncodeEnd ()
  1046. {
  1047.     if (putlen) {
  1048.         putchar(putbuf >> 8);
  1049.         bytes_out++;
  1050.     }
  1051. }
  1052.  
  1053. int DecodeChar ()
  1054. {
  1055.     register unsigned c;
  1056.     register unsigned short dx;
  1057.     register unsigned short cc;
  1058.     c = son[R];
  1059.  
  1060.     /* trace from root to leaf,
  1061.        got bit is 0 to small(son[]), 1 to large (son[]+1) son node */
  1062.     while (c < T) {
  1063.         dx = getbuf;
  1064.         if (getlen <= 8) {
  1065.               if ((short)(cc = getchar()) < 0) {
  1066.                   if (corrupt_flag)
  1067.                       oops();
  1068.                   corrupt_flag = 1;
  1069.                   cc = 0;
  1070.               }
  1071.             dx |= cc << (8 - getlen);
  1072.             getlen += 8;
  1073.         }
  1074.         getbuf = dx << 1;
  1075.         getlen--;
  1076.         c += (dx >> 15) & 1;
  1077.         c = son[c];
  1078.     }
  1079.     c -= T;
  1080.     update(c);
  1081.     return c;
  1082. }
  1083.  
  1084. int DecodePosition ()
  1085. {
  1086.     register unsigned short i, j, c;
  1087.  
  1088.     /* decode upper 6bit from table */
  1089.     i = GetByte();
  1090.     c = (unsigned)d_code[i] << 6;
  1091.     j = d_len[i];
  1092.  
  1093.     /* get lower 6bit */
  1094.     j -= 2;
  1095.     return c | (((i << j) | GetNBits (j)) & 0x3f);
  1096. }
  1097.  
  1098. /*
  1099.  * freeze stdin to stdout (as in compress.c & lzhuf.c)
  1100.  */
  1101.  
  1102. freeze ()
  1103. {
  1104.     register int  i, c, len, r, s, last_match_length;
  1105.     putchar(magic_header[0]);
  1106.     putchar(magic_header[1]);
  1107.     StartHuff();
  1108.     InitTree();
  1109.     s = 0;
  1110.     r = N - F;
  1111.     for (i = s; i < r; i++)
  1112.         text_buf[i] = ' ';
  1113.     for (len = 0; len < F && (c = getchar()) != EOF; len++)
  1114.         text_buf[r + len] = c;
  1115.     in_count = len;
  1116.     for (i = 1; i <= F; i++)
  1117.         InsertNode(r - i);
  1118.     InsertNode(r);
  1119.     while (len > 0) {
  1120.         if (match_length > len)
  1121.             match_length = len;
  1122.         if (match_length <= THRESHOLD) {
  1123.             match_length = 1;
  1124.             EncodeChar(text_buf[r]);
  1125. #ifdef DEBUG
  1126.             symbols_out ++;
  1127.             if (verbose)
  1128.                 fprintf(stderr, "'%s'\n", pr_char(text_buf[r]));
  1129. #endif /* DEBUG */
  1130.         } else {
  1131.             EncodeChar(256 - THRESHOLD + match_length);
  1132.             EncodePosition(match_position);
  1133. #ifdef DEBUG
  1134.             refers_out ++;
  1135.             if (verbose) {
  1136.                 register int pos = (r - 1 - match_position) & (N - 1),
  1137.                 len = match_length;
  1138.                 fputc('"', stderr);
  1139.                 for(;len;len--, pos++)
  1140.                     fprintf(stderr, "%s", pr_char(text_buf[pos]));
  1141.                 fprintf(stderr, "\"\n");
  1142.             }
  1143. #endif /* DEBUG */
  1144.         }
  1145.         last_match_length = match_length;
  1146.         for (i = 0; i < last_match_length &&
  1147.                 (c = getchar()) != EOF; i++) {
  1148.             DeleteNode(s);
  1149.             text_buf[s] = c;
  1150.             if (s < F - 1)
  1151.                 text_buf[s + N] = c;
  1152.             s = (s + 1) & (N - 1);
  1153.             r = (r + 1) & (N - 1);
  1154.             InsertNode(r);
  1155.         }
  1156.  
  1157.         in_count += i;
  1158.         if ((in_count > indicator_count) && !quiet) {
  1159.             fprintf(stderr, "%5dK\b\b\b\b\b\b", in_count / 1024);
  1160.             fflush (stderr);
  1161.             indicator_count += indicator_threshold;
  1162.             indicator_threshold += 1024;
  1163.         }
  1164.         while (i++ < last_match_length) {
  1165.             DeleteNode(s);
  1166.             s = (s + 1) & (N - 1);
  1167.             r = (r + 1) & (N - 1);
  1168.             if (--len) InsertNode(r);
  1169.         }
  1170.     }
  1171.     EncodeChar(ENDOF);
  1172. #ifdef DEBUG
  1173.     symbols_out ++;
  1174. #endif
  1175.     EncodeEnd();
  1176.     /*
  1177.      * Print out stats on stderr
  1178.      */
  1179.     if(!quiet) {
  1180. #ifdef DEBUG
  1181.     fprintf( stderr,
  1182.         "%ld chars in, %ld codes (%ld bytes) out, freezing factor: ",
  1183.         in_count, symbols_out + refers_out, bytes_out);
  1184.     prratio( stderr, in_count, bytes_out );
  1185.     fprintf( stderr, "\n");
  1186.     fprintf( stderr, "\tFreezing as in compact: " );
  1187.     prratio( stderr, in_count-bytes_out, in_count );
  1188.     fprintf( stderr, "\n");
  1189.     fprintf( stderr, "\tSymbols: %ld; references: %ld.\n",
  1190.         symbols_out, refers_out);
  1191. #else /* !DEBUG */
  1192.     fprintf( stderr, "Freezing: " );
  1193.     prratio( stderr, in_count-bytes_out, in_count );
  1194. #endif /* DEBUG */
  1195.     }
  1196.     if(bytes_out > in_count)    /* exit(2) if no savings */
  1197.     exit_stat = 2;
  1198.     return;
  1199. }
  1200.  
  1201. /*
  1202.  * Melt stdin to stdout.
  1203.  * Works =~= 1.5 times faster than uncompress (relatively to decompressed
  1204.  * filesize) - on 16-bit machines.
  1205.  * !! DO NOT (!!) use arithmetic compression - it is extremely
  1206.  * slow when decompressing.
  1207.  */
  1208.  
  1209. melt ()
  1210. {
  1211.     register int    i, j, k, r, c;
  1212.     StartHuff();
  1213.     for (i = 0; i < N - F; i++)
  1214.         text_buf[i] = ' ';
  1215.     r = N - F;
  1216.     for (in_count = 0;; ) {
  1217.         c = DecodeChar();
  1218.         if (c == ENDOF)
  1219.             break;
  1220.         if (c < 256) {
  1221.             putchar (c);
  1222.             text_buf[r++] = c;
  1223.             r &= (N - 1);
  1224.             in_count++;
  1225.         } else {
  1226.             i = (r - DecodePosition() - 1) & (N - 1);
  1227.             j = c - 256 + THRESHOLD;
  1228.             for (k = 0; k < j; k++) {
  1229.                 c = text_buf[(i + k) & (N - 1)];
  1230.                 putchar (c);
  1231.                 text_buf[r++] = c;
  1232.                 r &= (N - 1);
  1233.                 in_count++;
  1234.             }
  1235.         }
  1236.  
  1237.         if (!quiet && (in_count > indicator_count)) {
  1238.             fprintf(stderr, "%5dK\b\b\b\b\b\b", in_count / 1024);
  1239.             fflush (stderr);
  1240.             indicator_count += indicator_threshold;
  1241.             indicator_threshold += 1024;
  1242.         }
  1243.     }
  1244. }
  1245.  
  1246. char *
  1247. rindex(s, c)        /* For those who don't have it in libc.a */
  1248. register char *s, c;
  1249. {
  1250.     char *p;
  1251.     for (p = NULL; *s; s++)
  1252.         if (*s == c)
  1253.         p = s;
  1254.     return(p);
  1255. }
  1256.  
  1257. #ifdef DEBUG
  1258. printcodes()
  1259. {
  1260.     /*
  1261.      * Just print out codes from input file.  For debugging.
  1262.      */
  1263.     register int    k, c, col = 0;
  1264.     StartHuff();
  1265.     for (;;) {
  1266.         c = DecodeChar();
  1267.         if (c == ENDOF)
  1268.             break;
  1269.         if (c < 256) {
  1270.         fprintf(stderr, "%5d%c", c, (col+=8) >= 74 ? (col = 0, '\n') : '\t' );
  1271.         } else {
  1272.         c = c - 256 + THRESHOLD;
  1273.         k = DecodePosition();
  1274.         fprintf(stderr, "%2d-%d%c", c, k, (col+=8) >= 74 ? (col = 0, '\n') : '\t' );
  1275.         }
  1276.     }
  1277.     putc( '\n', stderr );
  1278.     exit( 0 );
  1279. }
  1280.  
  1281. /* for pretty char printing */
  1282.  
  1283. char *
  1284. pr_char(c)
  1285.     register unsigned char c;
  1286. {
  1287.     static char buf[5];
  1288.     register i = 4;
  1289.     buf[4] = '\0';
  1290.     if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
  1291.         buf[--i] = c;
  1292.     } else {
  1293.         switch( c ) {
  1294.         case '\n': buf[--i] = 'n'; break;
  1295.         case '\t': buf[--i] = 't'; break;
  1296.         case '\b': buf[--i] = 'b'; break;
  1297.         case '\f': buf[--i] = 'f'; break;
  1298.         case '\r': buf[--i] = 'r'; break;
  1299.         case '\\': buf[--i] = '\\'; break;
  1300.         default:
  1301.         buf[--i] = '0' + c % 8;
  1302.         buf[--i] = '0' + (c / 8) % 8;
  1303.         buf[--i] = '0' + c / 64;
  1304.         break;
  1305.         }
  1306.         buf[--i] = '\\';
  1307.     }
  1308.     return &buf[i];
  1309. }
  1310. #endif /* DEBUG */
  1311.  
  1312. writeerr()
  1313. {
  1314.     perror ( ofname );
  1315.     unlink ( ofname );
  1316.     exit ( 1 );
  1317. }
  1318.  
  1319. copystat(ifname, ofname)
  1320. char *ifname, *ofname;
  1321. {
  1322.     struct stat statbuf;
  1323.     int mode;
  1324.     time_t timep[2];
  1325.  
  1326. #ifdef MSDOS
  1327.     if (_osmajor < 3) freopen("CON","at",stdout); else      /* MS-DOS 2.xx bug */
  1328. #endif
  1329.  
  1330.     fclose(stdout);
  1331.     if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1332.     perror(ifname);
  1333.     return;
  1334.     }
  1335.  
  1336. #ifndef MSDOS
  1337.     if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
  1338.     if(quiet)
  1339.         fprintf(stderr, "%s: ", ifname);
  1340.     fprintf(stderr, " not a regular file: unchanged");
  1341.     exit_stat = 1;
  1342.     } else if (statbuf.st_nlink > 1) {
  1343.     if(quiet)
  1344.         fprintf(stderr, "%s: ", ifname);
  1345.     fprintf(stderr, " has %d other links: unchanged",
  1346.         statbuf.st_nlink - 1);
  1347.     exit_stat = 1;
  1348.     } else if (exit_stat == 2 && (!force)) { /* No freezing: remove file.Z */
  1349. #else
  1350.     if (exit_stat == 2 && (!force)) { /* No freezing: remove file.Z */
  1351. #endif /* MSDOS */
  1352.  
  1353.     if(!quiet)
  1354.         fprintf(stderr, " file unchanged");
  1355.     } else {            /* ***** Successful Freezing ***** */
  1356.     exit_stat = 0;
  1357.     mode = statbuf.st_mode & 07777;
  1358.     if (chmod(ofname, mode))        /* Copy modes */
  1359.         perror(ofname);
  1360.  
  1361. #ifndef MSDOS
  1362.     chown(ofname, statbuf.st_uid, statbuf.st_gid);    /* Copy ownership */
  1363. #endif
  1364.  
  1365.     timep[0] = statbuf.st_atime;
  1366.     timep[1] = statbuf.st_mtime;
  1367.     utime(ofname, timep);    /* Update last accessed and modified times */
  1368.     precious = 1;
  1369.     if (unlink(ifname))    /* Remove input file */
  1370.         perror(ifname);
  1371.     if(!quiet)
  1372.         fprintf(stderr, " -- replaced with %s", ofname);
  1373.     return;        /* Successful return */
  1374.     }
  1375.  
  1376.     /* Unsuccessful return -- one of the tests failed */
  1377.     if (unlink(ofname))
  1378.     perror(ofname);
  1379. }
  1380.  
  1381. #ifndef MSDOS
  1382. /*
  1383.  * This routine returns 1 if we are running in the foreground and stderr
  1384.  * is a tty.
  1385.  */
  1386. foreground()
  1387. {
  1388. #ifdef __GNUC__
  1389.     if(bgnd_flag != (int (*) ()) SIG_DFL) /* background? */
  1390. #else
  1391.     if(bgnd_flag != SIG_DFL)  /* background? */
  1392. #endif
  1393.         return(0);
  1394.     else {                          /* foreground */
  1395.         if(isatty(2)) {        /* and stderr is a tty */
  1396.             return(1);
  1397.         } else {
  1398.             return(0);
  1399.         }
  1400.     }
  1401. }
  1402. #endif
  1403.  
  1404. onintr ( )
  1405. {
  1406.     if (!precious)
  1407.     unlink ( ofname );
  1408.     exit ( 1 );
  1409. }
  1410.  
  1411. oops ( )        /* wild index -- assume bad input (or file too short) */
  1412. {
  1413.     if ( do_melt == 1 )
  1414.     fprintf ( stderr, "melt: corrupt input\n" );
  1415.     if ( fcat_flg == 1)
  1416.     fflush(stdout); /* Something is better than nothing */
  1417.     else
  1418.     unlink ( ofname );
  1419.     exit ( 1 );
  1420. }
  1421.  
  1422.  
  1423. prratio(stream, num, den)
  1424. FILE *stream;
  1425. long int num, den;
  1426. {
  1427.  
  1428. #ifdef DEBUG
  1429.     register long q;        /* permits |result| > 655.36% */
  1430. #else
  1431.     register int q;            /* Doesn't need to be long */
  1432. #endif
  1433.     if (!den) den++;
  1434.  
  1435.     if(num > 214748L) {        /* 2147483647/10000 */
  1436.         q = num / (den / 10000L);
  1437.     } else {
  1438.         q = 10000L * num / den;        /* Long calculations, though */
  1439.     }
  1440.     if (q < 0) {
  1441.         putc('-', stream);
  1442.         q = -q;
  1443.     }
  1444.     fprintf(stream, "%d.%02d%%", (int)(q / 100), (int)(q % 100));
  1445. }
  1446.  
  1447. version()
  1448. {
  1449.     fprintf(stderr, "%s\n", ident);
  1450.     fprintf(stderr, "Options: ");
  1451. #ifdef DEBUG
  1452.     fprintf(stderr, "DEBUG, ");
  1453. #endif
  1454. #ifdef BSD4_2
  1455.     fprintf(stderr, "BSD4_2, ");
  1456. #endif
  1457. #ifdef  M_XENIX
  1458.     fprintf(stderr, "XENIX, ");
  1459. #endif
  1460.     fprintf(stderr, "LZSS: %d (table), %d (match length);\n", N, F);
  1461.     fprintf(stderr, "HUFFMAN: %ld (max frequency)\n", (long)MAX_FREQ);
  1462. }
  1463. ----------------------- cut here -------------------------
  1464.