home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / uucplib / compress.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  20.6 KB  |  752 lines

  1. /*
  2.    compress.c
  3.  
  4.    EnthΣlt Routine zum Komprimieren und Dekomprimieren, die kompatibel
  5.    zum UN*X compress sind.
  6.  
  7.    Copyright (C) 1991 Ingo Feulner.
  8.    Alle Rechte vorbehalten.
  9. */
  10.  
  11. #include <string.h>
  12. #include "uucpbase.h"
  13. #include "uucpproto.h"
  14. #include "buffer.h"
  15.  
  16. #define EOF (-1)
  17.  
  18. /* Defines for third byte of header */
  19. #define BIT_MASK    0x1f
  20. #define BLOCK_MASK  0x80
  21.  
  22. #define INIT_BITS 9     /* initial number of bits/code */
  23.  
  24.  
  25. #define MAXCODE(n_bits)   ((1 << (n_bits)) - 1)
  26.  
  27. #define htabof(i)       (CompInfo->htab[i])
  28. #define codetabof(i)    (CompInfo->codetab[i])
  29.  
  30. #define tab_prefixof(i) codetabof(i)
  31. #define tab_suffixof(i) ((char_type *)(CompInfo->htab))[i]
  32. #define de_stack        ((char_type *)&tab_suffixof(1<<CompInfo->maxbits))
  33.  
  34. #define CHECK_GAP 10000 /* ratio check interval */
  35.  
  36. #define FIRST   257 /* first free entry */
  37. #define CLEAR   256 /* table clear output code */
  38.  
  39.  
  40. typedef long int      code_int;
  41. typedef long int      count_int;
  42. typedef unsigned char char_type;
  43.  
  44.  
  45. // Prototypes
  46. STATIC BOOL __asm AllocCompMem(register __a6 struct UUCPBase *UUCPBase,
  47.                                register __a0 struct CompressInfo **CompInfo,
  48.                                register __d1 UWORD bits,
  49.                                register __d2 BOOL decomp_flag);
  50.  
  51. STATIC VOID __asm FreeCompMem(register __a6 struct UUCPBase *UUCPBase,
  52.                               register __a0 struct CompressInfo *CompInfo);
  53.  
  54. STATIC VOID __asm compress(register __a6 struct UUCPBase *UUCPBase,
  55.                            register __a0 struct CompressInfo *CompInfo);
  56.  
  57. STATIC VOID __asm output(register __a6 struct UUCPBase *UUCPBase,
  58.                         register __a0 struct CompressInfo *CompInfo,
  59.                         register __d1 code_int code);
  60.  
  61. STATIC VOID __asm decompress(register __a6 struct UUCPBase *UUCPBase,
  62.                              register __a0 struct CompressInfo *CompInfo);
  63.  
  64. STATIC code_int __asm getcode(register __a6 struct UUCPBase *UUCPBase,
  65.                               register __a0 struct CompressInfo *CompInfo);
  66.  
  67. STATIC VOID __asm cl_block(register __a6 struct UUCPBase *UUCPBase,
  68.                            register __a0 struct CompressInfo *CompInfo);
  69.  
  70. STATIC VOID __asm cl_hash(register __a0 struct CompressInfo *CompInfo);
  71.  
  72.  
  73. STATIC const char_type magic_header[] = { "\x1F\x9D" };
  74. STATIC const char_type lmask[9] =
  75.   {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  76.  
  77. STATIC const char_type rmask[9] =
  78.   {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  79.  
  80.  
  81. struct CompressInfo
  82. {
  83.   struct datei    *infile;                       /* File to read from */
  84.   struct datei    *outfile;                      /* File to write to  */
  85.   count_int       *htab;
  86.   unsigned short  *codetab;
  87.   int             n_bits;                       /* number of bits/code */
  88.   int             maxbits;                      /* user settable max # bits/code */
  89.   code_int        maxcode;                      /* maximum code, given n_bits */
  90.   code_int        maxmaxcode;                   /* should NEVER generate this code */
  91.   code_int        hsize;                        /* for dynamic table sizing */
  92.   code_int        free_ent;                     /* first unused entry */
  93.   int             exit_stat;
  94.   int             block_compress;
  95.   int             clear_flg;
  96.   long            int ratio;
  97.   count_int       checkpoint;
  98.   int             offset;
  99.   int             size;
  100.   long int        in_count;                     /* length of input */
  101.   long int        bytes_out;                    /* length of compressed output */
  102.   char            *buf;
  103. };
  104.   
  105.  
  106. /*
  107.  *  CompressFile(name, maxbits);
  108.  *
  109.  *  Komprimiert das File, das durch den BPTR angegeben ist unter Verwendung
  110.  *  des UN*X Compress Algorithmus. Das komprimierte File wird in T: unter
  111.  *  einem einzigartigen Namen abgelegt.
  112.  *  Maxbits gibt die Anzahl der Bits an, die verwendet werden sollen.
  113.  *  Die Gr÷▀e des ben÷tigten Speichers richtet sich nach dieser Bitanzahl.
  114.  *
  115.  *  Folgende Rⁿckgabewerte sind m÷glich:
  116.  *       - AUUCP_ERROR_OK:         Kein Fehler aufgetreten
  117.  *       - AUUCP_ERROR_OUTOFMEM:   Nicht ausreichend Arbeitsspeicher
  118.  *       - AUUCP_ERROR_COMPRESSED: Angegebenes File bereits komprimiert.
  119.  *
  120.  */
  121. UWORD __asm _CompressFile(register __a6 struct UUCPBase *UUCPBase,
  122.                           register __a0 UBYTE *name,
  123.                           register __d2 UWORD maxbits)
  124. {
  125.   struct CompressInfo *CompInfo;
  126.   UWORD error = AUUCP_ERROR_OK;
  127.  
  128.   if((AllocCompMem(UUCPBase, &CompInfo, maxbits, FALSE)) != FALSE)
  129.   {
  130.     if((CompInfo->infile = oeffne_datei(UUCPBase, name, MODE_OLDFILE)) != NULL)
  131.     {
  132.       if((CompInfo->outfile =
  133.         oeffne_datei(UUCPBase, TempFileName(), MODE_NEWFILE)) != NULL)
  134.       {
  135.         compress(UUCPBase, CompInfo);
  136.         schliesse_datei(UUCPBase, CompInfo->outfile);
  137.       }
  138.       schliesse_datei(UUCPBase, CompInfo->infile);
  139.     }
  140.     FreeCompMem(UUCPBase, CompInfo);
  141.   }
  142.   else
  143.   {
  144.     error = AUUCP_ERROR_OUTOFMEM;
  145.   }
  146.   return error;
  147. }
  148.  
  149. /*
  150.  *  DeCompressFile(name);
  151.  *
  152.  *  Entkomprimiert das angegebene File, und schreibt die entkomprimierten
  153.  *  Daten in eine temporΣre Datei, die in T: mit einem einzigartigen Namen
  154.  *  angelegt wird.
  155.  *
  156.  *  Folgende Rⁿckgabewerte sind m÷glich:
  157.  *       - AUUCP_ERROR_OK:            Kein Fehler aufgetreten
  158.  *       - AUUCP_ERROR_OUTOFMEM:      Nicht ausreichend Arbeitsspeicher
  159.  *       - AUUCP_ERROR_NOTCOMPRESSED: Angegebene Datei ist nicht komprimiert.
  160.  *
  161.  */
  162. UWORD __asm _DeCompressFile(register __a6 struct UUCPBase *UUCPBase,
  163.                             register __a0 UBYTE *name)
  164. {
  165.   struct CompressInfo *CompInfo;
  166.   struct datei *infile;
  167.   UWORD maxbits, bits;
  168.   UWORD error = AUUCP_ERROR_OK;
  169.  
  170.   if((infile = oeffne_datei(UUCPBase, name, MODE_OLDFILE)) != NULL)
  171.   {
  172.     if( (hole_byte(UUCPBase, infile) == (magic_header[0] & 0xFF))
  173.      && (hole_byte(UUCPBase, infile) == (magic_header[1] & 0xFF)) )
  174.     {
  175.       // Mit wieviel Bits compressed?
  176.       bits = hole_byte(UUCPBase, infile);
  177.       maxbits = bits & BIT_MASK;
  178.  
  179.       if((AllocCompMem(UUCPBase, &CompInfo, maxbits, TRUE)) != FALSE)
  180.       {
  181.         CompInfo->infile = infile;
  182.         CompInfo->block_compress = bits & BLOCK_MASK;
  183.  
  184.         if((CompInfo->outfile =
  185.           oeffne_datei(UUCPBase, TempFileName(), MODE_NEWFILE)) != NULL)
  186.         {
  187.           decompress(UUCPBase, CompInfo);
  188.           schliesse_datei(UUCPBase, CompInfo->outfile);
  189.         }  
  190.         FreeCompMem(UUCPBase, CompInfo);
  191.       }
  192.       else
  193.       {
  194.         error = AUUCP_ERROR_OUTOFMEM;
  195.       }
  196.     }
  197.     else
  198.     {
  199.       error = AUUCP_ERROR_NOTCOMPRESSED;
  200.     }
  201.     schliesse_datei(UUCPBase, CompInfo->infile);
  202.   }
  203.   return error;
  204. }
  205.  
  206.  
  207. STATIC BOOL __asm AllocCompMem(register __a6 struct UUCPBase *UUCPBase,
  208.                                register __a0 struct CompressInfo **CompInfo,
  209.                                register __d1 UWORD bits,
  210.                                register __d2 BOOL decomp_flag)
  211. {
  212.   ULONG hsize;
  213.  
  214.   switch(bits)
  215.   {
  216.     case 16: hsize = 69001; break;
  217.     case 15: hsize = 35023; break;
  218.     case 14: hsize = 18013; break;
  219.     case 13: hsize =  9001; break;
  220.     case 12:
  221.     default: hsize =  5003; break;
  222.   }
  223.  
  224.   if((*CompInfo =
  225.     UUAllocMem((ULONG)sizeof(struct CompressInfo), MEMF_CLEAR | MEMF_PUBLIC)) != NULL)
  226.   {
  227.     if(((*CompInfo)->codetab =
  228.       UUAllocMem(hsize * sizeof(unsigned short), MEMF_PUBLIC)) != NULL)
  229.     {
  230.       // Nicht von  DeCompressFile() aus aufgerufen
  231.       if(decomp_flag != TRUE)
  232.       {
  233.         (*CompInfo)->htab =
  234.            UUAllocMem((ULONG)(hsize * sizeof(count_int)), MEMF_PUBLIC);
  235.       }
  236.       else
  237.       {
  238.         (*CompInfo)->htab = UUAllocMem((ULONG)((1L << 16) + 8000), MEMF_PUBLIC);
  239.       }
  240.  
  241.       if((*CompInfo)->htab != NULL)
  242.       {
  243.         if(((*CompInfo)->buf = UUAllocMem(bits, MEMF_CLEAR | MEMF_PUBLIC)) != NULL)
  244.         {
  245.           // StartWerte setzen
  246.           (*CompInfo)->maxbits        = bits;
  247.           (*CompInfo)->maxmaxcode     = 1 << bits;
  248.           (*CompInfo)->hsize          = hsize;
  249.           (*CompInfo)->block_compress = BLOCK_MASK;
  250.           (*CompInfo)->checkpoint     = CHECK_GAP;
  251.           (*CompInfo)->in_count       = 1;
  252.  
  253.           return TRUE;
  254.         }
  255.         UUFreeMem((*CompInfo)->htab);
  256.       }
  257.       UUFreeMem((*CompInfo)->codetab);
  258.     }
  259.     UUFreeMem((*CompInfo));
  260.   }
  261.   return FALSE;
  262. }
  263.  
  264. STATIC VOID __asm FreeCompMem(register __a6 struct UUCPBase *UUCPBase,
  265.                               register __a0 struct CompressInfo *CompInfo)
  266. {
  267.   UUFreeMem(CompInfo->buf);
  268.   UUFreeMem(CompInfo->codetab);
  269.   UUFreeMem(CompInfo->htab);
  270.   UUFreeMem(CompInfo);
  271. }
  272.  
  273. /*
  274.  * compress stdin to stdout
  275.  *
  276.  * Algorithm:  use open addressing double hashing (no chaining) on the
  277.  * prefix code / next character combination.  We do a variant of Knuth's
  278.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  279.  * secondary probe.  Here, the modular division first probe is gives way
  280.  * to a faster exclusive-or manipulation.  Also do block compression with
  281.  * an adaptive reset, whereby the code table is cleared when the compression
  282.  * ratio decreases, but after the table fills.    The variable-length output
  283.  * codes are re-sized at this point, and a special CLEAR code is generated
  284.  * for the decompressor.  Late addition:  construct the table according to
  285.  * file size for noticeable speed improvement on small files.  Please direct
  286.  * questions about this implementation to ames!jaw.
  287.  */
  288.  
  289. STATIC VOID __asm compress(register __a6 struct UUCPBase *UUCPBase,
  290.                            register __a0 struct CompressInfo *CompInfo)
  291. {
  292.   long fcode;
  293.   code_int i;
  294.   int c;
  295.   code_int ent;
  296.   int disp;
  297.   code_int hsize_reg;
  298.   int hshift;
  299.  
  300.  
  301.   schreibe_byte(UUCPBase, CompInfo->outfile, magic_header[0]);
  302.   schreibe_byte(UUCPBase, CompInfo->outfile, magic_header[1]);
  303.  
  304.   schreibe_byte(UUCPBase, CompInfo->outfile, (CompInfo->maxbits | CompInfo->block_compress));
  305.  
  306. //  if(ferror(stdout))
  307. //    writeerr();
  308.  
  309.   CompInfo->offset = 0;
  310.   CompInfo->bytes_out = 3;    /* includes 3-byte header mojo */
  311.   CompInfo->clear_flg = 0;
  312.   CompInfo->ratio = 0;
  313.   CompInfo->in_count = 1;
  314.   CompInfo->checkpoint = CHECK_GAP;
  315.   CompInfo->maxcode = MAXCODE(CompInfo->n_bits = INIT_BITS);
  316.   CompInfo->free_ent = ((CompInfo->block_compress) ? FIRST : 256 );
  317.  
  318.   ent = hole_byte(UUCPBase, CompInfo->infile);
  319.  
  320.   hshift = 0;
  321.   for ( fcode = (long) CompInfo->hsize;  fcode < 65536L; fcode *= 2L )
  322.     hshift++;
  323.  
  324.   hshift = 8 - hshift;    /* set hash code range bound */
  325.  
  326.   hsize_reg = CompInfo->hsize;
  327.   cl_hash(CompInfo);            /* clear hash table */
  328.  
  329.   while ( (c = hole_byte(UUCPBase, CompInfo->infile)) != EOF )
  330.   {
  331.     CompInfo->in_count++;
  332.     fcode = (long) (((long) c << CompInfo->maxbits) + ent);
  333.     i = ((c << hshift) ^ ent);      /* xor hashing */
  334.  
  335.     if ( htabof (i) == fcode )
  336.     {
  337.       ent = codetabof (i);
  338.       continue;
  339.     }
  340.     else if ( (long)htabof (i) < 0 )      /* empty slot */
  341.       goto nomatch;
  342.  
  343.     disp = hsize_reg - i;        /* secondary hash (after G. Knott) */
  344.     if ( i == 0 )
  345.       disp = 1;
  346.  
  347. probe:
  348.     if ( (i -= disp) < 0 )
  349.       i += hsize_reg;
  350.  
  351.     if ( htabof (i) == fcode )
  352.     {
  353.       ent = codetabof (i);
  354.       continue;
  355.     }
  356.     if ( (long)htabof (i) > 0 )
  357.       goto probe;
  358. nomatch:
  359.     output (UUCPBase, CompInfo, (code_int) ent );
  360.     ent = c;
  361.  
  362.     if ( CompInfo->free_ent < CompInfo->maxmaxcode )
  363.     {
  364.       codetabof (i) = CompInfo->free_ent++; /* code -> hashtable */
  365.       htabof (i) = fcode;
  366.     }
  367.     else if ( (count_int)CompInfo->in_count >= CompInfo->checkpoint && CompInfo->block_compress )
  368.       cl_block(UUCPBase, CompInfo);
  369.   }
  370.   /*
  371.    * Put out the final code.
  372.    */
  373.   output(UUCPBase, CompInfo, (code_int)ent);
  374.   output(UUCPBase, CompInfo, (code_int)-1);
  375.  
  376.   if(CompInfo->bytes_out > CompInfo->in_count)    /* exit(2) if no savings */
  377.     CompInfo->exit_stat = 2;
  378.   return;
  379. }
  380.  
  381.  
  382. /*****************************************************************
  383.  * TAG( output )
  384.  *
  385.  * Output the given code.
  386.  * Inputs:
  387.  *   code:  A n_bits-bit integer.  If == -1, then EOF.  This assumes
  388.  *          that n_bits =< (long)wordsize - 1.
  389.  * Outputs:
  390.  *   Outputs code to the file.
  391.  * Assumptions:
  392.  *   Chars are 8 bits long.
  393.  * Algorithm:
  394.  *   Maintain a BITS character long buffer (so that 8 codes will
  395.  *   fit in it exactly). Use the VAX insv instruction to insert each
  396.  *   code in turn.  When the buffer fills up empty it and start over.
  397.  */
  398.  
  399.  
  400. STATIC VOID __asm output(register __a6 struct UUCPBase *UUCPBase,
  401.                          register __a0 struct CompressInfo *CompInfo,
  402.                          register __d1 code_int code)
  403. {
  404.   int r_off = CompInfo->offset,
  405.       bits  = CompInfo->n_bits;
  406.  
  407.   char *bp  = CompInfo->buf;
  408.  
  409.   if ( code >= 0 )
  410.   {
  411.     /*
  412.      * Get to the first byte.
  413.      */
  414.  
  415.     bp += (r_off >> 3);
  416.     r_off &= 7;
  417.  
  418.     /*
  419.      * Since code is always >= 8 bits, only need to mask the first
  420.      * hunk on the left.
  421.      */
  422.  
  423.     *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
  424.     bp++;
  425.     bits -= (8 - r_off);
  426.     code >>=(8 - r_off);
  427.  
  428.     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  429.     if ( bits >= 8 )
  430.     {
  431.       *bp++ = code;
  432.       code >>= 8;
  433.       bits -= 8;
  434.     }
  435.     /* Last bits. */
  436.     if(bits)
  437.       *bp = code;
  438.  
  439.     CompInfo->offset += CompInfo->n_bits;
  440.     if ( CompInfo->offset == (CompInfo->n_bits << 3) )
  441.     {
  442.       bp = CompInfo->buf;
  443.       bits = CompInfo->n_bits;
  444.       CompInfo->bytes_out += bits;
  445.       do
  446.         schreibe_byte(UUCPBase, CompInfo->outfile, *bp++);
  447.       while(--bits);
  448.       CompInfo->offset = 0;
  449.     }
  450.  
  451.     /*
  452.      * If the next entry is going to be too big for the code size,
  453.      * then increase it, if possible.
  454.      */
  455.     if ( CompInfo->free_ent > CompInfo->maxcode || (CompInfo->clear_flg > 0))
  456.     {
  457.       /*
  458.        * Write the whole buffer, because the input side won't
  459.        * discover the size increase until after it has read it.
  460.        */
  461.       if ( CompInfo->offset > 0 )
  462.       {
  463.         // Fehlerⁿberprⁿfung machen!
  464.         schreibe_zeichen(UUCPBase, CompInfo->outfile, CompInfo->buf, CompInfo->n_bits);
  465.         CompInfo->bytes_out += CompInfo->n_bits;
  466.       }
  467.       CompInfo->offset = 0;
  468.  
  469.       if ( CompInfo->clear_flg )
  470.       {
  471.         CompInfo->maxcode = MAXCODE (CompInfo->n_bits = INIT_BITS);
  472.         CompInfo->clear_flg = 0;
  473.       }
  474.       else
  475.       {
  476.         CompInfo->n_bits++;
  477.         if ( CompInfo->n_bits == CompInfo->maxbits )
  478.           CompInfo->maxcode = CompInfo->maxmaxcode;
  479.         else
  480.           CompInfo->maxcode = MAXCODE(CompInfo->n_bits);
  481.       }
  482.     }
  483.   }
  484.   else
  485.   {
  486.     /*
  487.      * At EOF, write the rest of the buffer.
  488.      */
  489.     if ( CompInfo->offset > 0 )
  490.       schreibe_zeichen(UUCPBase, 
  491.         CompInfo->outfile, CompInfo->buf, (CompInfo->offset + 7) / 8);
  492.  
  493.     CompInfo->bytes_out += (CompInfo->offset + 7) / 8;
  494.     CompInfo->offset = 0;
  495.  
  496. //    fflush( stdout );
  497.  
  498.  
  499. //    if( ferror( stdout ) )
  500. //      writeerr();
  501.   }
  502. }
  503.  
  504. /*
  505.  * Decompress stdin to stdout.    This routine adapts to the codes in the
  506.  * file building the "string" table on-the-fly; requiring no table to
  507.  * be stored in the compressed file.  The tables used herein are shared
  508.  * with those of the compress() routine.  See the definitions above.
  509.  */
  510.  
  511. STATIC VOID __asm decompress(register __a6 struct UUCPBase *UUCPBase,
  512.                              register __a0 struct CompressInfo *CompInfo)
  513. {
  514.   char_type *stackp;
  515.   int finchar;
  516.   code_int code, oldcode, incode;
  517.  
  518.   CompInfo->offset = 0;
  519.   CompInfo->size   = 0;
  520.  
  521.   /*
  522.    * As above, initialize the first 256 entries in the table.
  523.    */
  524.   CompInfo->maxcode = MAXCODE(CompInfo->n_bits = INIT_BITS);
  525.   for ( code = 255; code >= 0; code-- )
  526.   {
  527.     tab_prefixof(code) = 0;
  528.     tab_suffixof(code) = (char_type)code;
  529.   }
  530.   CompInfo->free_ent = ((CompInfo->block_compress) ? FIRST : 256 );
  531.  
  532.   finchar = oldcode = getcode(UUCPBase, CompInfo);
  533.   if(oldcode == -1)   /* EOF already? */
  534.     return;     /* Get out of here */
  535.   schreibe_byte(UUCPBase, CompInfo->outfile, finchar ); /* first code must be 8 bits = char */
  536.  
  537. //  if(ferror(stdout))                         /* Crash if can't write */
  538. //    writeerr();
  539.  
  540.   stackp = de_stack;
  541.  
  542.   while ( (code = getcode(UUCPBase, CompInfo)) > -1 )
  543.   {
  544.     if ( (code == CLEAR) && CompInfo->block_compress )
  545.     {
  546.       for ( code = 255; code >= 0; code-- )
  547.         tab_prefixof(code) = 0;
  548.       CompInfo->clear_flg = 1;
  549.       CompInfo->free_ent = FIRST - 1;
  550.       if ( (code = getcode (UUCPBase, CompInfo)) == -1 )    /* O, untimely death! */
  551.         break;
  552.     }
  553.     incode = code;
  554.  
  555.     /*
  556.      * Special case for KwKwK string.
  557.      */
  558.  
  559.     if ( code >= CompInfo->free_ent )
  560.     {
  561.       *stackp++ = finchar;
  562.       code = oldcode;
  563.     }
  564.  
  565.    /*
  566.     * Generate output characters in reverse order
  567.     */
  568.  
  569.     while ( code >= 256 )
  570.     {
  571.       *stackp++ = tab_suffixof(code);
  572.       code = tab_prefixof(code);
  573.     }
  574.     *stackp++ = finchar = tab_suffixof(code);
  575.  
  576.     /*
  577.      * And put them out in forward order
  578.      */
  579.     do
  580.       schreibe_byte(UUCPBase, CompInfo->outfile, *--stackp );
  581.     while ( stackp > de_stack );
  582.  
  583.     /*
  584.      * Generate the new entry.
  585.      */
  586.     if((code = CompInfo->free_ent) < CompInfo->maxmaxcode)
  587.     {
  588.       tab_prefixof(code) = (unsigned short)oldcode;
  589.       tab_suffixof(code) = finchar;
  590.       CompInfo->free_ent = code+1;
  591.     }
  592.     /*
  593.      * Remember previous code.
  594.      */
  595.     oldcode = incode;
  596.   }
  597.  
  598. //  fflush(stdout);
  599. //  if(ferror(stdout))
  600. //    writeerr();
  601. }
  602.  
  603. /*****************************************************************
  604.  * TAG( getcode )
  605.  *
  606.  * Read one code from the standard input.  If EOF, return -1.
  607.  * Inputs:
  608.  *  stdin
  609.  * Outputs:
  610.  *  code or -1 is returned.
  611.  */
  612.  
  613. STATIC code_int __asm getcode(register __a6 struct UUCPBase *UUCPBase,
  614.                               register __a0 struct CompressInfo *CompInfo)
  615. {
  616.   code_int code;
  617.   int r_off, bits;
  618.   char_type *bp = CompInfo->buf;
  619.  
  620.   if ( CompInfo->clear_flg > 0 || CompInfo->offset >= CompInfo->size || CompInfo->free_ent > CompInfo->maxcode )
  621.   {
  622.     /*
  623.      * If the next entry will be too big for the current code
  624.      * size, then we must increase the size.  This implies reading
  625.      * a new buffer full, too.
  626.      */
  627.     if ( CompInfo->free_ent > CompInfo->maxcode )
  628.     {
  629.       CompInfo->n_bits++;
  630.       if ( CompInfo->n_bits == CompInfo->maxbits )
  631.         CompInfo->maxcode = CompInfo->maxmaxcode;    /* won't get any bigger now */
  632.       else
  633.         CompInfo->maxcode = MAXCODE(CompInfo->n_bits);
  634.     }
  635.     if ( CompInfo->clear_flg > 0)
  636.     {
  637.       CompInfo->maxcode = MAXCODE (CompInfo->n_bits = INIT_BITS);
  638.       CompInfo->clear_flg = 0;
  639.     }
  640.  
  641.     CompInfo->size =
  642.       hole_zeichen(UUCPBase, CompInfo->infile, CompInfo->buf, CompInfo->n_bits);
  643.     if ( CompInfo->size <= 0 )
  644.       return -1;      /* end of file */
  645.     CompInfo->offset = 0;
  646.     /* Round size down to integral number of codes */
  647.     CompInfo->size = (CompInfo->size << 3) - (CompInfo->n_bits - 1);
  648.   }
  649.   r_off = CompInfo->offset;
  650.   bits = CompInfo->n_bits;
  651.  
  652.   /*
  653.    * Get to the first byte.
  654.    */
  655.   bp += (r_off >> 3);
  656.   r_off &= 7;
  657.  
  658.   /* Get first part (low order bits) */
  659.   code = (*bp++ >> r_off);
  660.  
  661.   bits -= (8 - r_off);
  662.   r_off = 8 - r_off;    /* now, offset into code word */
  663.  
  664.   /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  665.   if ( bits >= 8 )
  666.   {
  667.     code |= *bp++ << r_off;
  668.     r_off += 8;
  669.     bits -= 8;
  670.   }
  671.  
  672.   /* high order bits. */
  673.   code |= (*bp & rmask[bits]) << r_off;
  674.   CompInfo->offset += CompInfo->n_bits;
  675.  
  676.   return code;
  677. }
  678.  
  679. /* table clear for block compress */
  680. STATIC VOID __asm cl_block(register __a6 struct UUCPBase *UUCPBase,
  681.                            register __a0 struct CompressInfo *CompInfo)
  682. {
  683.   long int rat;
  684.  
  685.   CompInfo->checkpoint = CompInfo->in_count + CHECK_GAP;
  686.  
  687.   if(CompInfo->in_count > 0x007fffff)  /* shift will overflow */
  688.   {
  689.     rat = CompInfo->bytes_out >> 8;
  690.     if(rat == 0)          /* Don't divide by zero */
  691.     {
  692.       rat = 0x7fffffff;
  693.     }
  694.     else
  695.     {
  696.       rat = CompInfo->in_count / rat;
  697.     }
  698.   }
  699.   else
  700.   {
  701.     rat = (CompInfo->in_count << 8) / CompInfo->bytes_out;      /* 8 fractional bits */
  702.   }
  703.  
  704.   if ( rat > CompInfo->ratio )
  705.   {
  706.     CompInfo->ratio = rat;
  707.   }
  708.   else
  709.   {
  710.     CompInfo->ratio = 0;
  711.  
  712.     cl_hash(CompInfo);
  713.     CompInfo->free_ent = FIRST;
  714.     CompInfo->clear_flg = 1;
  715.     output(UUCPBase, CompInfo, (code_int) CLEAR);
  716.   }
  717. }
  718.  
  719. /* reset code table */
  720. STATIC VOID __asm cl_hash(register __a0 struct CompressInfo *CompInfo)
  721. {
  722.   count_int *htab_p = CompInfo->htab + CompInfo->hsize;
  723.   const long m1 = -1;
  724.   long i;
  725.  
  726.   i = CompInfo->hsize - 16;
  727.   do
  728.   {
  729.     *(htab_p - 16) = m1;
  730.     *(htab_p - 15) = m1;
  731.     *(htab_p - 14) = m1;
  732.     *(htab_p - 13) = m1;
  733.     *(htab_p - 12) = m1;
  734.     *(htab_p - 11) = m1;
  735.     *(htab_p - 10) = m1;
  736.     *(htab_p -  9) = m1;
  737.     *(htab_p -  8) = m1;
  738.     *(htab_p -  7) = m1;
  739.     *(htab_p -  6) = m1;
  740.     *(htab_p -  5) = m1;
  741.     *(htab_p -  4) = m1;
  742.     *(htab_p -  3) = m1;
  743.     *(htab_p -  2) = m1;
  744.     *(htab_p -  1) = m1;
  745.  
  746.     htab_p -= 16;
  747.   } while ((i -= 16) >= 0);
  748.  
  749.   for(i += 16; i > 0; i--)
  750.     *--htab_p = m1;
  751. }
  752.