home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / squsq / lzw.lbr / COMMLZW.C next >
Text File  |  1986-04-24  |  5KB  |  208 lines

  1. /* COMMLZW - ROUTINES COMMON TO LZWCOM AND LZWUNC            */
  2. #include "stdio.h"
  3. #define FALSE    0
  4. #define TRUE     !FALSE
  5. #define TABSIZE  4096
  6. #define NO_PRED  -1
  7. #define EMPTY    -1
  8. #define NOT_FND  -1
  9. #define SECTSIZE 128
  10.  
  11. extern struct entry {
  12.   char used;
  13.   int next;                /* index of next in collision list */
  14.   int predecessor;            /* 12 bit code            */
  15.   char follower;
  16. } string_tab[TABSIZE];
  17.  
  18. extern char is_a_con;
  19. /* h uses the 'mid-square' algorithm. I.E. for a hash val of n bits    */
  20. /* hash = middle binary digits of (key * key).  Upon collision, hash     */
  21. /* searches down linked list of keys that hashed to that key already.    */
  22. /* It will NOT notice if the table is full. This must be handled     */
  23. /* elsewhere                                */
  24.  
  25. h(pred,foll)
  26. /* returns the mid square of pred + foll                */
  27. {
  28.   long temp, local;        /* 32 bit receiving field for local^2    */
  29.   local = (pred + foll) | 0x0800;
  30.   temp = local * local;
  31.   local = (temp >> 6) & 0x0FFF;
  32.   return local;            /* middle 12 bits of result        */
  33. }
  34.  
  35. eolist(index)
  36. /* return last element in a collision list                */
  37. int index;
  38. {
  39.   register int temp;
  40.   while ( 0 != (temp = string_tab[index].next) )
  41.     index = temp;
  42.   return index;
  43. }
  44.  
  45. hash(pred,foll,update)
  46. int pred, foll, update;
  47. {
  48.   register int local, tempnext;
  49.   register struct entry *ep;
  50.   local = h(pred,foll);
  51.   if ( !string_tab[local].used )
  52.     return local;
  53.   else {
  54.   /* if collision has occured                        */
  55.     local = eolist(local);
  56.  
  57.   /* search for free entry from local + 101 */
  58.     tempnext = (local + 101) & 0x0FFF; 
  59.     ep = &string_tab[tempnext];            /* initialize pointer    */
  60.     while ( ep->used ) {
  61.       ++tempnext;
  62.       if ( tempnext == TABSIZE ) {
  63.         tempnext = 0;        /* handle wrap to beginning of table    */
  64.         ep = string_tab;    /* address of first element of table    */
  65.       } else
  66.         ++ep;            /* point to next element in table    */
  67.     }
  68.     
  69.     /* put new tempnext into last element in collision list        */ 
  70.     if ( update )        /* if update requested            */
  71.       string_tab[local].next = tempnext;
  72.     return tempnext;
  73.   } 
  74. }
  75.  
  76. /* unhash uses the 'next' field to go down the collision tree to find    */
  77. /* the entry corresponding to the passed key                */
  78. /* passed key and returns either the matching entry # or NOT_FND    */
  79.  
  80. unhash(pred,foll)
  81. int pred, foll;
  82. {
  83.   register int local, offset;
  84.   register struct entry *ep;    /* pointer to current entry        */
  85.  
  86.   local = h(pred,foll);        /* initial hash                */
  87.   loop:
  88.     ep = &string_tab[local];
  89.     if ( (ep->predecessor == pred) && (ep->follower == foll) ) 
  90.       return local;
  91.     if ( ep->next == 0 )
  92.       return NOT_FND;
  93.     local = ep->next;
  94.   goto loop;
  95. }
  96.  
  97. init_tab() {
  98.   register int i;
  99.  
  100.   for (i = 0; i <= 255; i++) {
  101.     upd_tab(NO_PRED,i);
  102.   }
  103. }
  104.  
  105. #define UPDATE TRUE
  106.  
  107. upd_tab(pred,foll)
  108.   int pred, foll;
  109. {
  110.   register struct entry *ep;    /* pointer to current entry    */
  111.   /* calculate offset just once    */
  112.   ep = &string_tab[ hash(pred,foll,UPDATE) ];
  113.   ep->used = TRUE;
  114.   ep->next = 0;
  115.   ep->predecessor = pred;
  116.   ep->follower = foll;
  117. }
  118.  
  119.  
  120. int inbuf = EMPTY;
  121. int outbuf = EMPTY;
  122.  
  123. /* getcode and putcode 'gallop' through input and output - they either    */
  124. /* output two bytes or one depending on the contents of the buffer.    */
  125.  
  126. getcode(fd) 
  127. int fd;     {
  128.   register int localbuf, returnval;
  129.   if (EMPTY == inbuf) {        /* On code boundary            */
  130.     if (EOF == (localbuf = readc(fd)) ) {    
  131.                 /* H L1 byte - on code boundary        */
  132.       return EOF;
  133.     }
  134.     if (EOF == (inbuf = readc(fd)) ) {    /* L0 Hnext            */
  135.       return EOF;    /* The file should always end on code boundary    */
  136.     }
  137.     returnval = (localbuf << 4) + (inbuf >> 4);
  138.     inbuf &= 0x000F;
  139.   } else {            /* buffer contains nibble H        */
  140.     if (EOF == (localbuf = readc(fd)) )
  141.       return EOF;
  142.     returnval = localbuf + (inbuf << 8);
  143.     inbuf = EMPTY;
  144.   }
  145.   return returnval;
  146. }
  147.  
  148. putcode(fd,code)
  149. int fd,code;     {
  150.   register int localbuf;
  151.   if (EMPTY == outbuf) {
  152.     writec( fd,(code >> 4));    /* H L1                    */
  153.     outbuf = code & 0x000F;    /* L0                    */
  154.   } else {
  155.     writec( fd, ( (outbuf << 4) + (code >> 8) ) );
  156.                 /* L0prev H                */
  157.     writec( fd,(code & 0x00FF));    /* L1 L0            */
  158.     outbuf = EMPTY;
  159.   }
  160. }
  161.  
  162.  
  163.  
  164. char insector[SECTSIZE];
  165. int current = 0;
  166. int sector = 0;
  167. readc(fd)
  168. int fd;
  169. {
  170.   register int returnval;
  171.   if (current == 0) {
  172.     if ( 0 == read(fd,insector,SECTSIZE) ) {
  173.       return (EOF);
  174.     } else {
  175.       if (!is_a_con)
  176.         if ( (++sector % 80) )
  177.           putchar('.');
  178.         else {
  179.           putchar('.');
  180.           putchar('\n');
  181.         }
  182.     }
  183.   }
  184.   returnval = (insector[current++]);
  185.   if (current == SECTSIZE) {
  186.     current = 0;
  187.   }
  188.   return returnval;
  189. }
  190.  
  191. char outsector[SECTSIZE];
  192. int outcurrent = 0;
  193.  
  194. writec(fd,c)
  195. int fd,c;   {
  196.   outsector[outcurrent++] = ( (char) c);
  197.   if (outcurrent == SECTSIZE) {
  198.     outcurrent = 0;
  199.     write(fd,outsector,SECTSIZE);
  200.   }   
  201. }
  202.  
  203. /* flushout makes sure fractional output buffer gets written */
  204. flushout(fd)
  205. int fd; {
  206.   write(fd,outsector,(outcurrent + 1));
  207. }
  208.