/*********************************************************** crcio.c -- input/output ***********************************************************/ #ifdef __STDC__ #include #include #endif #include #include "slidehuf.h" #include "intrface.h" extern int text_mode; extern int prev_char; extern int verify_mode; #ifdef EUC extern int euc_mode; extern int generic_format; #endif long reading_size; #define CRCPOLY 0xA001 /* CRC-16 */ #define UPDATE_CRC(c) \ crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT) FILE *infile, *outfile; unsigned short crc, bitbuf; static unsigned short crctable[UCHAR_MAX + 1]; static unsigned char subbitbuf, bitcount; #ifdef EUC static int putc_euc_cache; #endif static int getc_euc_cache; void make_crctable(void) { unsigned int i, j, r; for (i = 0; i <= UCHAR_MAX; i++) { r = i; for (j = 0; j < CHAR_BIT; j++) if (r & 1) r = (r >> 1) ^ CRCPOLY; else r >>= 1; crctable[i] = r; } } #ifdef NEED_INCREMENTAL_INDICATOR extern int quiet; extern int indicator_count; extern int indicator_threshold; static void put_indicator( count ) long int count; { if (!quiet && indicator_threshold) { while ( count > indicator_count) { putchar ('o'); fflush (stdout); indicator_count += indicator_threshold; } } } #endif unsigned short calccrc( p , n ) unsigned char *p; unsigned int n; { reading_size += n; #ifdef NEED_INCREMENTAL_INDICATOR put_indicator( reading_size ); #endif while (n-- > 0) UPDATE_CRC(*p++); return crc; } void fillbuf(n) /* Shift bitbuf n bits left, read n bits */ unsigned char n; { while (n > bitcount) { n -= bitcount; bitbuf = (bitbuf << bitcount) + (subbitbuf >> (CHAR_BIT - bitcount)); if (compsize != 0) { compsize--; subbitbuf = (unsigned char) getc(infile); } else subbitbuf = 0; bitcount = CHAR_BIT; } bitcount -= n; bitbuf = (bitbuf << n) + (subbitbuf >> (CHAR_BIT - n)); subbitbuf <<= n; } unsigned short getbits(n) unsigned char n; { unsigned short x; x = bitbuf >> (2 * CHAR_BIT - n); fillbuf(n); return x; } void putcode( n , x ) /* Write rightmost n bits of x */ unsigned char n; unsigned short x; { while (n >= bitcount) { n -= bitcount; subbitbuf += x >> (USHRT_BIT - bitcount); x <<= bitcount; if (compsize < origsize) { if (fwrite(&subbitbuf, 1, 1, outfile) == 0) /* fileerror(WTERR, outfile); */ exit( errno ); compsize++; } else unpackable = 1; subbitbuf = 0; bitcount = CHAR_BIT; } subbitbuf += x >> (USHRT_BIT - bitcount); bitcount -= n; } void putbits( n , x ) /* Write rightmost n bits of x */ unsigned char n; unsigned short x; { x <<= USHRT_BIT - n; while (n >= bitcount) { n -= bitcount; subbitbuf += x >> (USHRT_BIT - bitcount); x <<= bitcount; if (compsize < origsize) { if (fwrite(&subbitbuf, 1, 1, outfile) == 0) /* fileerror(WTERR, outfile); */ exit( errno ); compsize++; } else unpackable = 1; subbitbuf = 0; bitcount = CHAR_BIT; } subbitbuf += x >> (USHRT_BIT - bitcount); bitcount -= n; } int fread_crc( p, n, fp ) unsigned char *p; int n; FILE *fp; { if ( text_mode ) n = fread_txt(p, n, fp); else n = fread(p, 1, n, fp); calccrc(p, n); return n; } void fwrite_crc( p, n, fp ) unsigned char *p; int n; FILE *fp; { calccrc(p,n); if ( verify_mode ) return; if ( fp ) { if ( text_mode ) { if ( fwrite_txt(p , n , fp) ) fatal_error("File write error\n"); } else { if (fwrite(p, 1, n, fp) < n) fatal_error("File write error\n"); } } } void init_code_cache(void) /* called from copyfile() in util.c */ { #ifdef EUC putc_euc_cache = EOF; #endif getc_euc_cache = EOF; } void init_getbits(void) { bitbuf = 0; subbitbuf = 0; bitcount = 0; fillbuf(2 * CHAR_BIT); #ifdef EUC putc_euc_cache = EOF; #endif } void init_putbits(void) { bitcount = CHAR_BIT; subbitbuf = 0; getc_euc_cache = EOF; } #ifdef EUC void putc_euc(c, fd) int c; FILE *fd; { int d; if (putc_euc_cache == EOF) { if (!euc_mode || c < 0x81 || c > 0xFC) { putc(c, fd); return; } if (c >= 0xA0 && c < 0xE0) { putc(0x8E, fd); /* single shift */ putc(c, fd); return; } putc_euc_cache = c; /* save first byte */ return; } d = putc_euc_cache; putc_euc_cache = EOF; if (d >= 0xA0) d -= 0xE0 - 0xA0; if (c > 0x9E) { c = c - 0x9F + 0x21; d = (d - 0x81) * 2 + 0x22; } else { if (c > 0x7E) c --; c -= 0x1F; d = (d - 0x81) * 2 + 0x21; } putc(0x80 | d, fd); putc(0x80 | c, fd); } #endif int fwrite_txt( p , n , fp ) unsigned char *p; int n; FILE *fp; { while ( --n>=0 ) { if ( *p!='\015' && *p!='\032' ) { #ifdef EUC putc_euc( *p , fp ); #else putc( *p , fp ); #endif } prev_char = *p++; } return ( ferror( fp ) ); } int fread_txt( p , n , fp ) unsigned char *p; int n; FILE *fp; { int c; int cnt = 0; while (cnt < n) { if (getc_euc_cache != EOF) { c = getc_euc_cache; getc_euc_cache = EOF; } else { if ((c = fgetc(fp)) == EOF) break; if (c == '\n') { getc_euc_cache = c; c = '\r'; } #ifdef EUC else if (euc_mode && (c == 0x8E || 0xA0 < c && c < 0xFF)) { int d = fgetc(fp); if (d == EOF) { *p++ = c; cnt ++; break; } if (c == 0x8E) /* single shift (KANA) */ { if ((0x20 < d && d < 0x7F) || (0xA0 < d && d < 0xFF)) c = d | 0x80; else getc_euc_cache = d; } else { if (0xA0 < d && d < 0xFF) /* if GR */ { c &= 0x7F; /* convert to MS-kanji */ d &= 0x7F; if (!(c & 1)) { c --; d += 0x7F - 0x21; } if ((d += 0x40 - 0x21) > 0x7E) d ++; if ((c = (c >> 1) + 0x71) >= 0xA0) c += 0xE0 - 0xA0; } getc_euc_cache = d; } } #endif } *p++ = c; cnt ++; } return cnt; }