home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 28
/
amigaformatcd28.iso
/
-seriously_amiga-
/
archivers
/
yacoder
/
encode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-09
|
5KB
|
216 lines
/*
* $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);
}