/*********************************************************** io.c -- input/output ***********************************************************/ #include "ar.h" #include #include #define CRCPOLY 0xA001 /* ANSI CRC-16 */ /* CCITT: 0x8408 */ #define UPDATE_CRC(c) \ crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT) FILE *arcfile, *infile, *outfile; uint crc, bitbuf; static ushort crctable[UCHAR_MAX + 1]; static uint subbitbuf; static int bitcount; void error(char *fmt, ...) { va_list args; va_start(args, fmt); putc('\n', stderr); vfprintf(stderr, fmt, args); putc('\n', stderr); va_end(args); exit(EXIT_FAILURE); } void make_crctable(void) { uint 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; } } void fillbuf(int n) /* Shift bitbuf n bits left, read n bits */ { bitbuf <<= n; while (n > bitcount) { bitbuf |= subbitbuf << (n -= bitcount); if (compsize != 0) { compsize--; subbitbuf = (uchar) getc(arcfile); } else subbitbuf = 0; bitcount = CHAR_BIT; } bitbuf |= subbitbuf >> (bitcount -= n); } uint getbits(int n) { uint x; if (n == 0) return 0; /* The above line added 2003-03-02. unsigned bitbuf used to be 16 bits, but now it's 32 bits, and (bitbuf >> 32) is equivalent to (bitbuf >> 0) (at least for ix86 and SPARC). Thanks: CheMaRy. */ x = bitbuf >> (BITBUFSIZ - n); fillbuf(n); return x; } void putbits(int n, uint x) /* Write rightmost n bits of x */ { if (n < bitcount) { subbitbuf |= x << (bitcount -= n); } else { if (compsize < origsize) { putc(subbitbuf | (x >> (n -= bitcount)), outfile); compsize++; } else unpackable = 1; if (n < CHAR_BIT) { subbitbuf = x << (bitcount = CHAR_BIT - n); } else { if (compsize < origsize) { putc(x >> (n - CHAR_BIT), outfile); compsize++; } else unpackable = 1; subbitbuf = x << (bitcount = 2 * CHAR_BIT - n); } } } int fread_crc(uchar *p, int n, FILE *f) { int i; i = n = fread(p, 1, n, f); origsize += n; while (--i >= 0) UPDATE_CRC(*p++); return n; } void fwrite_crc(uchar *p, int n, FILE *f) { if (fwrite(p, 1, n, f) < n) error("Unable to write"); while (--n >= 0) UPDATE_CRC(*p++); } void init_getbits(void) { bitbuf = 0; subbitbuf = 0; bitcount = 0; fillbuf(BITBUFSIZ); } void init_putbits(void) { bitcount = CHAR_BIT; subbitbuf = 0; }