home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / lha100bt.zip / lha-1.00 / src / crcio.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  6KB  |  341 lines

  1. /***********************************************************
  2.     crcio.c -- input/output
  3. ***********************************************************/
  4. #ifdef __STDC__
  5. #include <stdlib.h>
  6. #include <stdarg.h>
  7. #endif
  8.  
  9. #include <errno.h>
  10. #include "slidehuf.h"
  11. #include "intrface.h"
  12.  
  13. extern int text_mode;
  14. extern int prev_char;
  15. extern int verify_mode;
  16. #ifdef EUC
  17. extern int euc_mode;
  18. extern int generic_format;
  19. #endif
  20.  
  21. long reading_size;
  22.  
  23. #define CRCPOLY  0xA001  /* CRC-16 */
  24. #define UPDATE_CRC(c) \
  25.     crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT)
  26.  
  27. FILE *infile, *outfile;
  28. unsigned short crc, bitbuf;
  29.  
  30. static unsigned short crctable[UCHAR_MAX + 1];
  31. static unsigned char  subbitbuf, bitcount;
  32. #ifdef EUC
  33. static int putc_euc_cache;
  34. #endif
  35. static int getc_euc_cache;
  36.  
  37. void make_crctable(void)
  38. {
  39.     unsigned int i, j, r;
  40.  
  41.     for (i = 0; i <= UCHAR_MAX; i++) {
  42.         r = i;
  43.         for (j = 0; j < CHAR_BIT; j++)
  44.             if (r & 1) r = (r >> 1) ^ CRCPOLY;
  45.             else       r >>= 1;
  46.         crctable[i] = r;
  47.     }
  48. }
  49.  
  50.  
  51. #ifdef NEED_INCREMENTAL_INDICATOR
  52. extern int quiet;
  53. extern int indicator_count;
  54. extern int indicator_threshold;
  55. static void
  56. put_indicator( count )
  57. long int count;
  58. {
  59.     if (!quiet && indicator_threshold)
  60.     {
  61.         while ( count > indicator_count) {
  62.             putchar ('o');
  63.             fflush (stdout);
  64.             indicator_count += indicator_threshold;
  65.         }
  66.     }
  67. }
  68. #endif
  69.  
  70. unsigned short calccrc( p , n )
  71. unsigned char *p;
  72. unsigned int n;
  73. {
  74.     reading_size += n;
  75. #ifdef NEED_INCREMENTAL_INDICATOR
  76.     put_indicator( reading_size );
  77. #endif
  78.     while (n-- > 0) UPDATE_CRC(*p++);
  79.     return crc;
  80. }
  81.  
  82. void fillbuf(n)  /* Shift bitbuf n bits left, read n bits */
  83. unsigned char n;
  84. {
  85.   while (n > bitcount) {
  86.     n -= bitcount;
  87.     bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount));
  88.     if (compsize != 0) {
  89.       compsize--;  subbitbuf = (unsigned char) getc(infile);
  90.     } else subbitbuf = 0;
  91.     bitcount = CHAR_BIT;
  92.   }
  93.   bitcount -= n;
  94.   bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n));
  95.   subbitbuf <<= n;
  96. }
  97.  
  98. unsigned short getbits(n)
  99. unsigned char n;
  100. {
  101.     unsigned short x;
  102.  
  103.     x = bitbuf >> (2 * CHAR_BIT - n);  fillbuf(n);
  104.     return x;
  105. }
  106.  
  107. void putcode( n , x )  /* Write rightmost n bits of x */
  108. unsigned char n;
  109. unsigned short x;
  110. {
  111.   while (n >= bitcount) {
  112.     n -= bitcount;
  113.     subbitbuf += x >> (USHRT_BIT - bitcount);
  114.     x <<= bitcount;
  115.     if (compsize < origsize) {
  116.       if (fwrite(&subbitbuf, 1, 1, outfile) == 0)
  117.     /*    fileerror(WTERR, outfile); */
  118.     exit( errno );
  119.       compsize++;
  120.     } else unpackable = 1;
  121.     subbitbuf = 0;  bitcount = CHAR_BIT;
  122.   }
  123.   subbitbuf += x >> (USHRT_BIT - bitcount);
  124.   bitcount -= n;
  125. }
  126.  
  127. void putbits( n , x )  /* Write rightmost n bits of x */
  128. unsigned char n;
  129. unsigned short x;
  130. {
  131.     x <<= USHRT_BIT - n;
  132.     while (n >= bitcount) {
  133.         n -= bitcount;
  134.         subbitbuf += x >> (USHRT_BIT - bitcount);
  135.         x <<= bitcount;
  136.         if (compsize < origsize) {
  137.             if (fwrite(&subbitbuf, 1, 1, outfile) == 0)
  138.                 /* fileerror(WTERR, outfile); */
  139.                 exit( errno );
  140.             compsize++;
  141.         } else unpackable = 1;
  142.         subbitbuf = 0;  bitcount = CHAR_BIT;
  143.     }
  144.     subbitbuf += x >> (USHRT_BIT - bitcount);
  145.     bitcount -= n;
  146. }
  147.  
  148. int fread_crc( p, n, fp )
  149. unsigned char *p;
  150. int n;
  151. FILE *fp;
  152. {
  153.     if ( text_mode )
  154.       n = fread_txt(p, n, fp);
  155.     else
  156.       n = fread(p, 1, n, fp);
  157.     calccrc(p, n);
  158.     return n;
  159. }
  160.  
  161. void fwrite_crc( p, n, fp )
  162. unsigned char *p;
  163. int n;
  164. FILE *fp;
  165. {
  166.   calccrc(p,n);
  167.   if ( verify_mode ) return;
  168.  
  169.   if ( fp )
  170.     {
  171.       if ( text_mode )
  172.     {
  173.       if ( fwrite_txt(p , n , fp) )
  174.         fatal_error("File write error\n");
  175.     }
  176.       else
  177.     {
  178.       if (fwrite(p, 1, n, fp) < n)
  179.         fatal_error("File write error\n");
  180.     }
  181.     }
  182. }
  183.  
  184. void init_code_cache(void)    /* called from copyfile() in util.c */
  185. {
  186. #ifdef EUC
  187.     putc_euc_cache = EOF;
  188. #endif
  189.     getc_euc_cache = EOF;
  190. }
  191.  
  192. void init_getbits(void)
  193. {
  194.     bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
  195.     fillbuf(2 * CHAR_BIT);
  196. #ifdef EUC
  197.     putc_euc_cache = EOF;
  198. #endif
  199. }
  200.  
  201. void init_putbits(void)
  202. {
  203.     bitcount = CHAR_BIT;  subbitbuf = 0;
  204.     getc_euc_cache = EOF;
  205. }
  206.  
  207. #ifdef EUC
  208. void
  209. putc_euc(c, fd)
  210. int c;
  211. FILE *fd;
  212. {
  213.   int d;
  214.  
  215.   if (putc_euc_cache == EOF)
  216.     {
  217.       if (!euc_mode || c < 0x81 || c > 0xFC)
  218.         {
  219.           putc(c, fd);
  220.           return;
  221.         }
  222.       if (c >= 0xA0 && c < 0xE0)
  223.         {
  224.           putc(0x8E, fd);      /* single shift */
  225.           putc(c, fd);
  226.           return;
  227.         }
  228.       putc_euc_cache = c;      /* save first byte */
  229.       return;
  230.     }
  231.   d = putc_euc_cache;
  232.   putc_euc_cache = EOF;
  233.   if (d >= 0xA0)
  234.     d -= 0xE0 - 0xA0;
  235.   if (c > 0x9E)
  236.     {
  237.       c = c - 0x9F + 0x21;
  238.       d = (d - 0x81) * 2 + 0x22;
  239.     }
  240.   else
  241.     {
  242.       if (c > 0x7E)
  243.         c --;
  244.       c -= 0x1F;
  245.       d = (d - 0x81) * 2 + 0x21;
  246.     }
  247.   putc(0x80 | d, fd);
  248.   putc(0x80 | c, fd);
  249. }
  250. #endif
  251.  
  252. int
  253. fwrite_txt( p , n , fp )
  254. unsigned char *p;
  255. int n;
  256. FILE *fp;
  257. {
  258.   while ( --n>=0 )
  259.     {
  260.       if ( *p!='\015' && *p!='\032' )
  261.     {
  262. #ifdef EUC
  263.       putc_euc( *p , fp );
  264. #else
  265.       putc( *p , fp );
  266. #endif
  267.     }
  268.  
  269.       prev_char = *p++;
  270.     }
  271.   return ( ferror( fp ) );
  272. }
  273.  
  274. int
  275. fread_txt( p , n , fp )
  276. unsigned char *p;
  277. int n;
  278. FILE *fp;
  279. {
  280.   int c;
  281.   int cnt = 0;
  282.  
  283.   while (cnt < n)
  284.     {
  285.       if (getc_euc_cache != EOF)
  286.         {
  287.           c = getc_euc_cache;
  288.           getc_euc_cache = EOF;
  289.         }
  290.       else
  291.         {
  292.           if ((c = fgetc(fp)) == EOF)
  293.             break;
  294.           if (c == '\n') {
  295.             getc_euc_cache = c;
  296.             c = '\r';
  297.       }
  298. #ifdef EUC
  299.       else if (euc_mode && (c == 0x8E || 0xA0 < c && c < 0xFF))
  300.         {
  301.           int d = fgetc(fp);
  302.           if (d == EOF)
  303.             {
  304.           *p++ = c;
  305.               cnt ++;
  306.               break;
  307.             }
  308.           if (c == 0x8E)    /* single shift (KANA) */
  309.             {
  310.           if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF))
  311.             c = d | 0x80;
  312.           else
  313.             getc_euc_cache = d;
  314.             }
  315.           else
  316.               {
  317.                 if (0xA0 < d && d < 0xFF)    /* if GR */
  318.                   {
  319.                     c &= 0x7F;    /* convert to MS-kanji */
  320.                     d &= 0x7F;
  321.                     if (!(c & 1))
  322.                       {
  323.                         c --;
  324.                         d += 0x7F - 0x21;
  325.                       }
  326.               if ((d += 0x40 - 0x21) > 0x7E)
  327.             d ++;
  328.               if ((c = (c >> 1) + 0x71) >= 0xA0)
  329.                 c += 0xE0 - 0xA0;
  330.                   }
  331.           getc_euc_cache = d;
  332.               }
  333.         }
  334. #endif
  335.         }
  336.       *p++ = c;
  337.       cnt ++;
  338.     }
  339.   return cnt;
  340. }
  341.