home *** CD-ROM | disk | FTP | other *** search
- /*
- * $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 <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <string.h>
- #include "codes.h"
-
- static FILE *infp, *outfp;
- static char *name, *charset;
- static mode_t inmode;
-
- static void
- usage()
- {
- printf("options:\n");
- printf("-i <inputfile>\n");
- printf("-o <outputfile>\n");
- printf("-n <name>\n");
- printf("-c <charset>\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);
- }
-