/******************************************************************************* * 36to7.c * Convert 36-bit (5-byte) DEC-20 (TOPS-20) data files into 7-bit data. * * 1.00 04-13-1994 drt. First cut. Still doesn't work. * 1.01 07-08-1995 drt. Added setvbuf() to input and output streams for speed. * Fixed unitialized length bug. * Still doesn't work. */ /* Identification */ static const char * prog = "36to7"; static const char vers[] = "1.01"; static const char date[] = "07-08-1995"; static const char auth[] = "David R. Tribble"; /* System includes */ #include #include #include #include #include #include #include /* Manifest constants */ #define CVT_TYPE 0 #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif /* Private variables */ static int opt_printable; static int opt_algor = CVT_TYPE; /******************************************************************************* * read_chunk * Reads a single 36-bit (40-bit, 5-byte) chunk of data from file `in' * into buffer `buf'. * * Returns * Length of buffer (in bytes), and zero on end of file. */ static size_t read_chunk(unsigned char *buf, FILE *in) { size_t len; int ch; /* Read a single chunk of 5 bytes */ buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x00; buf[3] = 0x00; buf[4] = 0x00; len = 0; ch = getc(in); if (ch != EOF) { buf[len++] = ch; ch = getc(in); if (ch != EOF) { buf[len++] = ch; ch = getc(in); if (ch != EOF) { buf[len++] = ch; ch = getc(in); if (ch != EOF) { buf[len++] = ch; ch = getc(in); if (ch != EOF) { buf[len++] = ch; } } } } } return len; } /******************************************************************************* * write_chunk * Writes a single converted chunk of data from buffer `buf' of `len' bytes * to file `out'. * * Returns * Length of buffer written (in bytes). */ static size_t write_chunk(unsigned char *buf, size_t len, FILE *out) { int wlen; int ch; /* Write a single chunk */ if (opt_printable) { for (wlen = 0; wlen < len; wlen++, buf++) { ch = *buf; switch (ch) { case '\b': case '\n': case '\r': case '\v': case '\f': case '\t': break; default: if (!isprint(*buf)) ch = '.'; break; } putc(ch, out); } } else { #ifdef OLD wlen = fwrite(buf, 1, len, out); #else if (len == 1) putc(buf[0], out); else wlen = fwrite(buf, 1, len, out); #endif } return wlen; } /******************************************************************************* * convert_chunk * Converts a 36-bit (40-bit, 5-byte) chunk of data `ibuf' of `ilen' bytes * into a normal 7-bit chunk of data `obuf'. * * Returns * Length of buffer `obuf' (in bytes). */ static size_t convert_chunk(unsigned char *obuf, unsigned char *ibuf, size_t ilen) { size_t olen; /* Convert 36-bit chunk into chunk of 7-bit bytes */ switch (opt_algor) { case 0: obuf[4] = (ibuf[4]>>1)&0x07 | (ibuf[4]<<7)&0x80 | (ibuf[3]<<3)&0x78; obuf[3] = (ibuf[3]>>4)&0x0f | (ibuf[2]<<4)&0x70; obuf[2] = (ibuf[2]>>3)&0x1f | (ibuf[1]<<5)&0x60; obuf[1] = (ibuf[1]>>2)&0x3f | (ibuf[0]<<6)&0x40; obuf[0] = (ibuf[0]>>1); break; case 1: obuf[4] = ((ibuf[0]) & 0x7F); obuf[3] = ((ibuf[0] >> 7) & 0x01) + ((ibuf[1] << 1) & 0x7F); obuf[2] = ((ibuf[1] >> 6) & 0x03) + ((ibuf[2] << 2) & 0x7F); obuf[1] = ((ibuf[2] >> 5) & 0x07) + ((ibuf[3] << 3) & 0x7F); obuf[0] = ((ibuf[3] >> 4) & 0x0F) + ((ibuf[4] << 4) & 0x7F); break; case 2: obuf[0] = ((ibuf[0]) & 0x7F); obuf[1] = ((ibuf[0] >> 7) & 0x01) + ((ibuf[1] << 1) & 0x7F); obuf[2] = ((ibuf[1] >> 6) & 0x03) + ((ibuf[2] << 2) & 0x7F); obuf[3] = ((ibuf[2] >> 5) & 0x07) + ((ibuf[3] << 3) & 0x7F); obuf[4] = ((ibuf[3] >> 4) & 0x0F) + ((ibuf[4] << 4) & 0x7F); break; case 3: obuf[4] = ((ibuf[4]) & 0x7F); obuf[3] = ((ibuf[4] >> 7) & 0x01) + ((ibuf[3] << 1) & 0x7F); obuf[2] = ((ibuf[3] >> 6) & 0x03) + ((ibuf[2] << 2) & 0x7F); obuf[1] = ((ibuf[2] >> 5) & 0x07) + ((ibuf[1] << 3) & 0x7F); obuf[0] = ((ibuf[1] >> 4) & 0x0F) + ((ibuf[0] << 4) & 0x7F); break; case 4: obuf[0] = ((ibuf[4]) & 0x7F); obuf[1] = ((ibuf[4] >> 7) & 0x01) + ((ibuf[3] << 1) & 0x7F); obuf[2] = ((ibuf[3] >> 6) & 0x03) + ((ibuf[2] << 2) & 0x7F); obuf[3] = ((ibuf[2] >> 5) & 0x07) + ((ibuf[1] << 3) & 0x7F); obuf[4] = ((ibuf[1] >> 4) & 0x0F) + ((ibuf[0] << 4) & 0x7F); break; default: fprintf(stderr, "Undefined conversion type %d\n", opt_algor); exit(3); break; } if ((ibuf[4] & 0xF0) != 0x00) fprintf(stderr, "leftover 0x%.2X\n", ibuf[4] & 0xF0); /* Determine output length */ olen = 0; switch (ilen) { case 0: olen = 0; break; case 1: olen = 2; break; case 2: olen = 3; break; case 3: olen = 4; break; case 4: olen = 5; break; case 5: olen = 5; break; } return olen; } /******************************************************************************* * usage * Print usage message, then bail. */ static void usage(void) { fprintf(stderr, "[%s, %s %s]\n\n", vers, date, auth); fprintf(stderr, "usage: %s [-p] [infile [outfile]]\n", prog); fprintf(stderr, "\n"); fprintf(stderr, " -N Conversion algorithm `N'\n"); fprintf(stderr, " -p Show unprintable characters as \".\"\n"); exit(255); } /******************************************************************************* * main */ static char ivbuf[20*1024]; static char ovbuf[20*1024]; static unsigned char ibuf[80]; static unsigned char obuf[80]; int main(int argc, char **argv) { int err; FILE * in; FILE * out; size_t len; unsigned long count, lcount; /* Get options */ while (argc > 1 && argv[1][0] == '-') { if (strcmp(argv[1], "-p") == 0) opt_printable = TRUE; else if (isdigit(argv[1][1])) opt_algor = atoi(argv[1]+1); else usage(); argc--, argv++; } /* Check usage */ if (argc < 2 && isatty(fileno(stdin))) usage(); /* Get input file */ if (argc > 1) { in = fopen(argv[1], "rb"); if (in == NULL) { err = errno; fprintf(stderr, "%s: can't read `%s': %s\n", prog, argv[1], strerror(errno)); exit(err); } } else { in = stdin; #ifdef O_BINARY setmode(fileno(in), O_BINARY); #endif } setvbuf(in, ivbuf, _IOFBF, sizeof(ivbuf)); /* Get output file */ if (argc > 2) { out = fopen(argv[2], "wb"); if (out == NULL) { err = errno; fprintf(stderr, "%s: can't read `%s': %s\n", prog, argv[2], strerror(errno)); exit(err); } } else { out = stdout; #ifdef O_BINARY setmode(fileno(out), O_BINARY); #endif } setvbuf(out, ovbuf, _IOFBF, sizeof(ovbuf)); fprintf(stderr, "Conversion type %d\n", opt_algor); /* Convert input file into output file */ err = 0; count = lcount = 0; while (len = read_chunk(ibuf, in), len > 0) { count += len; if (count-lcount >= 1000) { lcount = count; fprintf(stderr, "%lu \r", count); } len = convert_chunk(obuf, ibuf, len); write_chunk(obuf, len, out); } fprintf(stderr, "%lu \n", count); return err; } /* End 36to7.c */