/* * $Header: /usr/people/tcl/src/uutar/RCS/encode.c,v 1.1.1.5 1993/09/11 22:42:56 tcl Exp $ * Tom Lawrence * tcl@sgi.com */ #include #include #include #include #include #include "codes.h" static FILE *infp, *outfp; static char *name, *charset; static mode_t inmode; static void usage() { printf("options:\n"); printf("-i \n"); printf("-o \n"); printf("-n \n"); printf("-c \n"); exit(1); } /* parse command line arguments */ static void parse(argc, argv) int argc; char **argv; { char *infile, *outfile; struct stat statbuf; infile = outfile = 0; name = charset = 0; while(--argc) { argv++; if (!strcmp(*argv, "-i")) { if (argc < 2) usage(); argc--; argv++; infile = *argv; } else if (!strcmp(*argv, "-o")) { if (argc < 2) usage(); argc--; argv++; outfile = *argv; } else if (!strcmp(*argv, "-n")) { if (argc < 2) usage(); argc--; argv++; name = *argv; } else if (!strcmp(*argv, "-c")) { if (argc < 2) usage(); argc--; argv++; charset = *argv; } else usage(); } /* open the input stream */ if (infile) { if ((infp = fopen(infile, "r")) == 0) { perror(infile); exit(1); } if (stat(infile, &statbuf) < 0) { perror(infile); exit(1); } inmode = statbuf.st_mode & 0777; } else { infp = stdin; inmode = 0666; } /* open the output stream */ if (outfile) { if ((outfp = fopen(outfile, "w")) == 0) { perror(outfile); exit(1); } } else outfp = stdout; /* get the filename to store in the encoded file */ if (name == 0) { if (infile == 0) name = "stdin"; else name = infile; } /* set default character set if none was specified */ if (charset == 0) charset = "32-126"; } main(argc, argv) int argc; char **argv; { int c; unsigned short buf; int buf_offset, inlen, cols = 0, pattern; unsigned int cksum; /* parse command line arguments */ parse(argc, argv); /* parse the supplied character set specification and initialize * tables based on that set */ parse_charval_list(charset); init_codes(ENCODE); fprintf(outfp, "BEGIN %o %s ", inmode, name); print_charval_list(outfp); putc('\n', outfp); /* clear the sliding input buffer */ buf = 0; buf_offset = 16; cksum = 0; /* read in the input file */ while((c = getc(infp)) != EOF) { /* compute a checksum on the input file */ cksum = ((cksum << 7) | (cksum >> 25)) ^ (unsigned)c; /* shift the byte just read in into our sliding buffer */ buf_offset -= 8; buf |= ((unsigned short)c << buf_offset); /* see if there are any complete variable length bitfields * in the input buffer. If so, output their corresponding * printable output character and advance the input buffer * by their length in bits */ while (1) { /* grab the next 8 bits in the input bitstream */ pattern = (int)(buf >> 8); /* determine how many of those bits we will need * to extract from the sliding buffer */ inlen = codes[pattern].len; /* if there are not enough bits in the sliding * buffer, stop for now. (interestingly, you don't need * to have all of the needed bits in order to determine * that you don't have all of the needed bits) */ if (inlen > (16 - buf_offset)) break; /* output the printable character associated with * the variable length bitfield recognized in the * input bitstream */ putc(codes[pattern].code, outfp); /* limit our width */ if (++cols == 79) { cols = 0; putc('\n', outfp); } /* advance the input bitstream by the length of the bitfield * just recognized */ buf_offset += inlen; buf <<= inlen; } } /* flush the buffer. The last byte read in may still have some * of its bits in the sliding buffer. If so, print out one more * output character. This will necessarily append some garbage * bits to the output but what can we do? we can't write files * at a finer granularity that the byte. The decoder will ignore * them so it's ok */ if (buf_offset < 16) { putc(codes[pattern].code, outfp); cols++; } /* indicate end of encoded data by 2 consecutive newlines followed * by the keyword END. This is necessary since the END line itself * is potentially valid encoded data */ if (cols) putc('\n', outfp); fprintf(outfp, "\nEND %X\n", cksum); }