ASCIIFY and BINAFY... programs for exchanging binary files...
John T. Nelson
jtn at potomac.ads.com
Fri Jun 8 03:22:23 AEST 1990
Asciify and binafy are a pair of programs for converting arbitrary
format files into ASCII representation for later transmission through
network mailers. These programs are superior to Binhex, Mcvert, xbin,
et al in that no assumptions are made concerning the type of file being
encoded. Also, Asciify and Binafy were written with ease of protability
in mind. A Macintosh port is now underway.
I welcome bug reports and suggestions for future improvement of this
program. I may be reached at kzin!speaker at mimsy.umd.edu or
jtn at potomac.ads.com.
unzip here [O ]-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-8-
echo x - asciify
mkdir asciify
echo x - asciify/asciify.1
sed 's/^x//' >asciify/asciify.1 <<'!Funky!Stuff!'
x.\" @(#)asciify.1 1.0 90/06/1 SMI;
x.TH ASCIIFY 1 "01 June 1990"
x.SH NAME
x.LP
xasciify \- convert file contents into asciified format
x.LP
xbinafy \- convert asciified file back to original format
x.SH SYNOPSIS
x.LP
x.B asciify
x[
x.IR -c
x]
x.IR file
x[
x.IR asciified_file
x]
x.LP
x.B binafy
x.IR asciified_file
x[
x.IR file
x]
x
x.SH DESCRIPTION
x.LP
x.B Asciify
xand
x.B binafy
xare a pair of programs for converting arbitrary format files into
xASCII representation for later transmission through network mailers.
xThis program is superior to Binhex, Mcvert, xbin, et al in that
xno assumptions have been made concerning the type of file being encoded.
xAlso, asciify and binafy were written for ease of porting
xbetween different machine architectures and thus facilitating
xa common interchange standard for files of any format.
x
xI believe this calls for some diabolical laughter... MWWAHHA HAH HAW
xHA HA HA HA!!!
x
x.nf
x.LP
xHere's what an asciified file looks like:
x
x(This file must be decoded with Binafy)
x!Asciify Version 1.00!File t!Chk!
x7)GI;9*N*'3[;X7T*(+W>H[K=H>B:I+K;XCV$BK+=D#V<(6B;H_T;9/V*(_H*)3J!4327!
x;4#P<8?J?"J,7XCC?$#K=8WQ>I3C=$#J:8[F*(_T*(7[;2J,2X_W=(2B;I+C=86B!4161!
x .
x .
x .
x?(C[*(;G:9+H?8RB>YGO=87V>IFa$d!2125!
x!!
x.fi
x
xAnything outside the parenthetical line and the final bangs are ignored.
xAnything following the bang on each line is a checksum, used for error
xdetection. Unlike Binhex, the binafy program will tell you which line
xhad a checksum error if one occurs, although there isn't much that the
xprogram can do to correct the error.
x
x.SH USING ASCIIFY
x.LP
xThe command line...
x.IP
x.B
xexample% asciify binary_file asciified_file
x.LP
xconverts binary_file into the
x.B
xasciify
xformat and puts it into file
x.B
xasciified_file.
xIf no target file is specified then the output is placed onto
xstandard output.
x
xThe command line...
x.IP
x.B
xexample% binafy asciified_file file
x.LP
xconverts the asciified format file into its original format
xand places it in
x.B
xfile.
x
xIf no target file is specified then the output is placed onto
xstandard output so in the case of binafy you'll want to redirect output
xsomeplace. For example:
x.IP
x.B
xexample% binafy asciified_file > file
x
x.SH "SEE ALSO"
x.BR binafy (1),
x
x.SH HOW IT WORKS
x.LP
xThree bytes of the original file are read and converted into 4
xcharacters representing 6 bits each of the original 3 bytes. Note that
x6 divides into 12 ( 3 bytes times 8 bits per byte) quite evenly. The 64
xcharacters of the ASCII character set starting with the double quote
x(hex 22) character are used. The exclamation point character is
xreserved as a special delimeter.
x
xNote that we have used only 64 of the 94 some printable characters.
x
xIn case the number of bytes in a file is not evenly divisible by 3, a
xspecial encoding is used to represent the remaining piece of the byte.
xThe remaining pieces can be either 2 bits or 4 bits and thus consume 20
xmore ASCII printable characters. Because these characters are unique in
xthe encoding we will know when the end of a file has arrived and, more
ximportantly, we will know what these characters represent because they
xare outside of the main encoding scheme.
x
xThis encoding scheme yields a 4 for 3 decompression which I consider to
xbe fairly effecient.
x
x.SH INSTALLATION
x.LP
xJust type
x.B make asciify
xto build
x.B asciify
xand
x.B make binafy
xto build
x.B binafy
x
xBoth should compile and generate binaries called
x.B asciify
xand
x.B binafy
xrespectively.
x
x.SH FUTURE ENHANCEMENTS
x.LP
xSupport binafying of multipart files. It's simple enough
xto split files apart with the Unix "split" program. It would
xbe nice if asciify and binafy split and assembled multiple files
xautomagically. Note that the above example has a "part of" spec in the
xheader. That's how binafy will know what order to assemble the files
xin.
x
xThe file format is incompatible with Binhex and uuencode/uudecode
xformats. I should probably provide compatibility and cross-conversion
xfor these too, but since I can't find their source code you'll just
xhave to use
x.B asciify
xformat for now.
x
xMagic strings.
x
x.SH BUGS
x.LP
xThe ANSI C standard actually makes no assumptions concerning
xthe size of a character or byte, therefore this program will
xprobably do the wrong thing on machines with 13-bit bytes.
xThis should not be an immediate concern as most machines use 8 bit
xbytes.
x
xAlso note that I have avoided the use of the fscanf/sscanf whenever
xpossible. This is because the behavior of these library routines
xvaries from implementation to implementation.
x
x.SH AUTHOR
x.LP
x.nf
x=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
xORGANIZATION: Kzinti Embassy GEOGRAPHIC: McLean, VA
xUUCP: kzin!speaker at mimsy.umd.edu INTERNET: jtn at potomac.ads.com
xSPOKEN: Hey Stupid Cat! PHONE: (703) 356-6514
xPROJECT: The Conrail Locomotive/Harpsichord Fusion Program
x=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
x.fi
!Funky!Stuff!
echo x - asciify/DOC
cat >asciify/DOC <<'!Funky!Stuff!'
ASCIIFY(1) USER COMMANDS ASCIIFY(1)
NAME
asciify - convert file contents into asciified format
binafy - convert asciified file back to original format
SYNOPSIS
asciify [ -_c ] _f_i_l_e [ _a_s_c_i_i_f_i_e_d__f_i_l_e ]
binafy _a_s_c_i_i_f_i_e_d__f_i_l_e [ _f_i_l_e ]
DESCRIPTION
Asciify and binafy are a pair of programs for converting
arbitrary format files into ASCII representation for later
transmission through network mailers. This program is supe-
rior to Binhex, Mcvert, xbin, et al in that no assumptions
have been made concerning the type of file being encoded.
Also, asciify and binafy were written for ease of porting
between different machine architectures and thus facilitat-
ing a common interchange standard for files of any format.
I believe this calls for some diabolical laughter...
MWWAHHA HAH HAW HA HA HA HA!!!
Here's what an asciified file looks like:
(This file must be decoded with Binafy)
!Asciify Version 1.00!File t!Chk!
7)GI;9*N*'3[;X7T*(+W>H[K=H>B:I+K;XCV$BK+=D#V<(6B;H_T;9/V*(_H*)3J!4327!
;4#P<8?J?"J,7XCC?$#K=8WQ>I3C=$#J:8[F*(_T*(7[;2J,2X_W=(2B;I+C=86B!4161!
.
.
.
?(C[*(;G:9+H?8RB>YGO=87V>IFa$d!2125!
!!
Anything outside the parenthetical line and the final bangs
are ignored. Anything following the bang on each line is a
checksum, used for error detection. Unlike Binhex, the
binafy program will tell you which line had a checksum error
if one occurs, although there isn't much that the program
can do to correct the error.
USING ASCIIFY
The command line...
example% asciify binary_file asciified_file
converts binary_file into the asciify format and puts it
into file asciified_file. If no target file is specified
Sun Release 4.0 Last change: 01 June 1990 1
ASCIIFY(1) USER COMMANDS ASCIIFY(1)
then the output is placed onto standard output.
The command line...
example% binafy asciified_file file
converts the asciified format file into its original format
and places it in file.
If no target file is specified then the output is placed
onto standard output so in the case of binafy you'll want to
redirect output someplace. For example:
example% binafy asciified_file > file
SEE ALSO
binafy(1),
HOW IT WORKS
Three bytes of the original file are read and converted into
4 characters representing 6 bits each of the original 3
bytes. Note that 6 divides into 12 ( 3 bytes times 8 bits
per byte) quite evenly. The 64 characters of the ASCII
character set starting with the double quote (hex 22) char-
acter are used. The exclamation point character is reserved
as a special delimeter.
Note that we have used only 64 of the 94 some printable
characters.
In case the number of bytes in a file is not evenly divisi-
ble by 3, a special encoding is used to represent the
remaining piece of the byte. The remaining pieces can be
either 2 bits or 4 bits and thus consume 20 more ASCII
printable characters. Because these characters are unique
in the encoding we will know when the end of a file has
arrived and, more importantly, we will know what these char-
acters represent because they are outside of the main encod-
ing scheme.
This encoding scheme yields a 4 for 3 decompression which I
consider to be fairly effecient.
INSTALLATION
Just type make asciify to build asciify and make binafy to
build binafy
Both should compile and generate binaries called asciify and
binafy respectively.
Sun Release 4.0 Last change: 01 June 1990 2
ASCIIFY(1) USER COMMANDS ASCIIFY(1)
FUTURE ENHANCEMENTS
Support binafying of multipart files. It's simple enough to
split files apart with the Unix "split" program. It would
be nice if asciify could assemble multiple files automagi-
cally. Note that the above example has a "part of" spec in
the header. That's how binafy will know what order to
assemble the files in.
The file format is incompatible with Binhex and
uuencode/uudecode formats. I should probably provide compa-
tibility and cross-conversion for these too, but since I
can't find their source code you'll just have to use asciify
format for now.
Magic strings.
BUGS
The ANSI C standard actually makes no assumptions concerning
the size of a character or byte, therefore this program will
probably do the wrong thing on machines with 13-bit bytes.
This should not be an immediate concern as most machines use
8 bit bytes.
Also note that I have avoided the use of the fscanf/sscanf
whenever possible. This is because the behavior of these
library routines varies from implementation to implementa-
tion.
AUTHOR
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ORGANIZATION: Kzinti Embassy GEOGRAPHIC: McLean, VA
UUCP: kzin!speaker at mimsy.umd.edu INTERNET: jtn at potomac.ads.com
SPOKEN: Hey Stupid Cat! PHONE: (703) 356-6514
PROJECT: The Conrail Locomotive/Harpsichord Fusion Program
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Sun Release 4.0 Last change: 01 June 1990 3
!Funky!Stuff!
echo x - asciify/Makefile
cat >asciify/Makefile <<'!Funky!Stuff!'
all: asciify binafy
asciify: asciify.c globals.c asciifyCore.c definitions.h globals.h Makefile
cc asciify.c globals.c asciifyCore.c -o asciify
binafy: binafy.c globals.c binafyCore.c definitions.h globals.h Makefile
cc binafy.c globals.c binafyCore.c -o binafy
clean:
rm -f *.o asciify binafy core #*
!Funky!Stuff!
echo x - asciify/README
cat >asciify/README <<'!Funky!Stuff!'
Asciify and binafy are a pair of programs for converting arbitrary
format files into ASCII representation for later transmission through
network mailers. These programs are superior to Binhex, Mcvert, xbin,
et al in that no assumptions are made concerning the type of file being
encoded. Also, Asciify and Binafy were written with ease of protability
in mind. A Macintosh port is now underway.
I welcome bug reports and suggestions for future improvement of this
program. I may be reached at kzin!speaker at mimsy.umd.edu or
jtn at potomac.ads.com.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ORGANIZATION: Advanced Decision Systems GEOGRAPHIC: Arlington, VA
UUCP: kzin!speaker at mimsy.umd.edu INTERNET: jtn at potomac.ads.com
SPOKEN: Yo... John! PHONE: (703) 243-1611
PROJECT: The Conrail Locomotive/Harpsichord Fusion Program
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
!Funky!Stuff!
echo x - asciify/asciify.c
cat >asciify/asciify.c <<'!Funky!Stuff!'
#include <stdio.h>
#include <fcntl.h>
#include "definitions.h"
#include "globals.h"
/*
This is "asciify", a program for converting files of arbitrary
format into an ASCII encoding for later transmission through network
mailers. The program "binafy" should be used to convert the ASCII
encoding back into the original file.
Usage: asciify [ -c ] <original file> [ <asciified file> ]
-- John T. Nelson (a.k.a. Speaker-To-Animals) mimsy!kzin!speaker
*/
BOOLEAN parseFlags(argv)
char *argv[];
{
char *s;
unsigned int k;
if ( *argv[0] == '-' ) {
k = 1;
header.useCheck = FALSE;
for ( s = argv[0] + 1; *s != '\0'; s++ ) {
switch ( *s ) {
case 'c':
header.useCheck = TRUE;
break;
}
k++;
}
return TRUE;
}
else
return FALSE;
}
main(argc, argv)
int argc;
char *argv[];
{
int fi;
FILE *fo;
unsigned int counter;
int status;
if ( argc == 1 ) {
printf("Usage: asciify [ -c ] <original file> <target file>\n");
return;
}
argv++;
if ( argc == 2 ) {
if ( *argv[0] == '-' ) {
printf("Usage: asciify [ -c ] <original file> <target file>\n");
return;
}
else {
fi = open( *argv, O_RDONLY);
fo = stdout;
strcpy(header.fileName, "stdout");
}
}
if ( argc == 3 )
if ( parseFlags(argv) ) {
argv++;
fi = open( *argv, O_RDONLY);
fo = stdout;
strcpy(header.fileName, "stdout");
}
else {
fi = open( *argv, O_RDONLY);
argv++;
fo = fopen(*argv, "w");
strcpy(header.fileName, *argv);
}
if ( argc == 4 )
if ( parseFlags(argv) ) {
argv++;
fi = open( *argv, O_RDONLY);
argv++;
fo = fopen(*argv, "w");
strcpy(header.fileName, *argv);
}
else {
printf("More than 2 file names - I'm quiting\n");
return;
}
if ( argc > 4 ) {
printf("More than 2 file names - I'm quiting\n");
return;
}
asciify(fi, fo);
}
!Funky!Stuff!
echo x - asciify/asciifyCore.c
cat >asciify/asciifyCore.c <<'!Funky!Stuff!'
#include <stdio.h>
#include <fcntl.h>
#include "definitions.h"
#include "globals.h"
asciify(fi, fo)
int fi;
FILE *fo;
{
unsigned int counter;
int status;
num = 0;
cur = buffer;
putHerald(fo);
counter = 0;
status = 0;
while ( status != EOF ) {
status = convertThree(fi, fo, header.useCheck);
fflush(fo);
}
fputc(DELIMETER, fo);
fputc(DELIMETER, fo);
fprintf(fo, "\n");
fflush(fo);
close(fi);
fclose(fo);
}
errorCleanup(fi, fo)
int fi;
FILE *fo;
{
close(fi);
fclose(fo);
}
/* No... don't look! It's EVIL! */
convertThree(fi, fo, check)
int fi;
FILE *fo;
BOOLEAN check;
{
int status;
unsigned int i;
char byte1, byte2, byte3;
char c;
unsigned int checksum;
i = 1;
checksum = 0;
status = SUCCESS;
while (i < LINE_LENGTH && status != EOF) {
status = getAbyte(fi, &byte1);
if ( status == EOF ) {
break;
}
checksum = checksum + (unsigned char) byte1;
convert1(&byte1, &c);
fputc(c, fo);
i++;
status = getAbyte(fi, &byte2);
if ( status == EOF ) {
putShortTwo(fo, byte1);
break;
}
checksum = checksum + (unsigned char) byte2;
convert2(&byte1, &byte2, &c);
fputc(c, fo);
i++;
status = getAbyte(fi, &byte3);
if ( status == EOF ) {
putShortFour(fo, byte2);
break;
}
checksum = checksum + (unsigned char) byte3;
convert3(&byte2, &byte3, &c);
fputc(c, fo);
i++;
convert4(&byte3, &c);
fputc(c, fo);
i++;
byte1 = 0;
byte2 = 0;
byte3 = 0;
}
if ( i == 1 )
return EOF;
putCheckSum(fo, checksum, check);
return status;
}
putCheckSum(fo, checksum, check)
FILE *fo;
unsigned int checksum;
BOOLEAN check;
{
if ( checksum < 0 )
check = check;
if ( check == YES )
fprintf(fo,"%c%u%c\n", DELIMETER, checksum, DELIMETER);
else {
fputc(DELIMETER, fo);
fputc('\n', fo);
}
}
convert1(b1, c)
char *c;
char *b1;
{
char byte;
byte = *b1;
byte &= UPPER_SIX_BITS;
byte = byte >> 2;
byte &= LOWER_SIX_BITS;
byte += CODING_START;
*c = byte;
return SUCCESS;
}
convert2(b1, b2, c)
char *c;
char *b1, *b2;
{
char byte1;
char byte2;
byte1 = *b1;
byte2 = *b2;
byte1 &= LOWER_TWO_BITS;
byte2 &= UPPER_FOUR_BITS;
byte1 = byte1 << 4;
byte2 = byte2 >> 4;
byte1 &= 0x30;
byte2 &= LOWER_FOUR_BITS;
byte1 |= byte2;
byte1 &= LOWER_SIX_BITS;
byte1 += CODING_START;
*c = byte1;
return SUCCESS;
}
convert3(b2, b3, c)
char *c;
char *b2, *b3;
{
char byte2;
char byte3;
byte2 = *b2;
byte3 = *b3;
byte2 &= LOWER_FOUR_BITS;
byte3 &= UPPER_TWO_BITS;
byte2 = byte2 << 2;
byte3 = byte3 >> 6;
byte2 &= 0x3C;
byte3 &= LOWER_TWO_BITS;
byte2 |= byte3;
byte2 &= LOWER_SIX_BITS;
byte2 += CODING_START;
*c = byte2;
return SUCCESS;
}
convert4(b3, c)
char *c;
char *b3;
{
char byte3;
byte3 = *b3;
byte3 &= LOWER_SIX_BITS;
byte3 += CODING_START;
*c = byte3;
return SUCCESS;
}
processChecksum()
{
}
getAbyte(fi, c)
int fi;
char *c;
{
if ( num == 0 ) {
num = read(fi, buffer, BUFFER_SIZE);
if ( num == 0 || num == EOF )
return EOF;
cur = buffer;
}
*c = *cur;
cur += 1;
num -= 1;
return SUCCESS;
}
putShortTwo(fo, b)
FILE *fo;
char b;
{
char byte;
byte = b;
byte &= LOWER_TWO_BITS;
byte += START_TWO;
fputc(byte, fo);
}
putShortFour(fo, b)
FILE *fo;
char b;
{
char byte;
byte = b;
byte &= LOWER_FOUR_BITS;
byte += START_FOUR;
fputc(byte, fo);
}
putHerald(fo)
FILE *fo;
{
fprintf(fo, "\n%s", HERALD);
fputc(DELIMETER, fo);
fprintf(fo, VERSION_STRING, VERSION_NUM);
fputc(DELIMETER, fo);
fprintf(fo, FILE_STRING, header.fileName);
if ( header.useCheck == YES ) {
fputc(DELIMETER, fo);
fprintf(fo, CHECKSUM_STRING);
}
fputc(DELIMETER, fo);
fprintf(fo, "\n");
}
!Funky!Stuff!
echo x - asciify/binafy.c
cat >asciify/binafy.c <<'!Funky!Stuff!'
#include <stdio.h>
#include <fcntl.h>
#include "definitions.h"
#include "globals.h"
/*
This is "binafy", a program for converting "asciified" files
back into their original file formats.
Usage: binafy <asciified file> <original file>
-- John T. Nelson (a.k.a. Speaker-To-Animals) mimsy!kzin!speaker
*/
main(argc, argv)
int argc;
char *argv[];
{
FILE *fi;
int fo;
if ( argc == 1 ) {
printf("Usage: binafy <asciify'd file> <original file>\n");
return;
}
if ( argc == 2 ) {
fo = STANDARD_OUTPUT_FD; /* Assume the shmuck knows what he wants */
}
if ( argc == 2 || argc == 3) {
argv++;
fi = fopen( *argv, "r");
}
if ( argc == 3 ) {
argv++;
#ifndef THINK_C
fo = open(*argv, O_WRONLY | O_CREAT, 0640);
#else
fo = open(*argv, O_WRONLY | O_CREAT);
#endif
}
if ( argc > 3 ) {
printf("More than 2 arguments - I'm quiting\n");
return;
}
binafy(fi, fo);
}
!Funky!Stuff!
echo x - asciify/binafyCore.c
cat >asciify/binafyCore.c <<'!Funky!Stuff!'
#include <stdio.h>
#include <fcntl.h>
#include "definitions.h"
#include "globals.h"
binafy(fi, fo)
FILE *fi;
int fo;
{
num = -1;
header.line = 1;
if ( flushHerald(fi) == FAILURE ) {
fclose(fi);
close(fo);
exit();
}
if ( readHeader(fi, header.header) == FAILURE ) {
fclose(fi);
close(fo);
exit();
}
parseHeader(&header);
if ( header.useCheck == YES )
processWithChecksums(fi, fo);
else
processWithoutChecksums(fi, fo);
fclose(fi);
flushBuffer(fo);
close(fo);
}
processWithChecksums(fi, fo)
int fi;
FILE *fo;
{
int status;
status = SUCCESS;
while ( status != EOF ) {
status = processLine(fi, fo, &header);
if ( status == FAILURE )
return;
if ( checkChecksum(header) == FAILURE ) {
printf("Checksum error detected on line %d!\n", header.line);
return;
}
header.line += 1;
}
}
processWithoutChecksums(fi, fo)
int fi;
FILE *fo;
{
int status;
status = SUCCESS;
while ( status != EOF ) {
status = processLine(fi, fo, &header);
if ( status == FAILURE )
return;
header.line += 1;
}
}
processLine(fi, fo, header)
FILE *fi;
int fo;
struct HEADER_STRUCT *header;
{
char string[NUM_DATA_CHARS];
char errorChars[NUM_CHECKSUM_CHARS];
unsigned int i;
unsigned int lastChar;
unsigned int checksum;
char byte1;
char byte2;
char byte3;
int status;
switch ( collectStrings(fi, string, errorChars) ) {
case SUCCESS:
break;
case FAILURE:
return FAILURE;
case DOUBLE_DELIMS:
return EOF;
default:
return FAILURE;
};
i = 0;
checksum = 0;
lastChar = strlen(string) - 1;
convertToNumber(errorChars, &(header -> checksumRead));
while( i <= lastChar ) {
if ( string[i] == DELIMETER ) {
header -> checksum = checksum;
return SUCCESS;
}
status = SUCCESS;
status = convert1(string[i], &byte1);
if ( status == TRAILING_CHARS ) {
printf("Byte 1 started with a short byte!\n");
return FAILURE;
}
i++;
status = convert2(string[i], &byte1, &byte2);
if ( status == TRAILING_FOUR ) {
printf("Byte 1 decoded 4 bits not 2!\n");
return FAILURE;
}
checksum += (unsigned char) byte1;
if ( status == TRAILING_TWO ) {
putAchar(byte1, fo);
status = EOF;
break;
}
putAchar(byte1, fo);
i++;
status = convert3(string[i], &byte2, &byte3);
if ( status == TRAILING_TWO ) {
printf("Byte 2 decoded 2 bits not 4!\n");
return FAILURE;
}
checksum += (unsigned char) byte2;
if ( status == TRAILING_FOUR ) {
putAchar(byte2, fo);
status = EOF;
break;
}
putAchar(byte2, fo);
i++;
status = convert4(string[i], &byte3);
if ( status == TRAILING_CHARS ) {
printf("Byte 3 had a short byte!\n");
return FAILURE;
}
putAchar(byte3, fo);
checksum += (unsigned char) byte3;
i++;
byte1 = 0;
byte2 = 0;
byte3 = 0;
}
header -> checksum = checksum;
return SUCCESS;
}
convert1(c, b1)
char c;
char *b1;
{
char byte;
if ( c >= SHORT_START )
return TRAILING_CHARS;
byte = c - CODING_START;
byte = byte << 2;
byte &= UPPER_SIX_BITS;
*b1 = byte;
return SUCCESS;
}
convert2(c, b1, b2)
char c;
char *b1, *b2;
{
char byte1;
char byte2;
char byte;
char cc;
if ( c >= START_FOUR )
return TRAILING_FOUR;
byte1 = *b1;
if ( c >= START_TWO && c < START_FOUR ) {
byte = c - SHORT_START;
byte1 |= byte;
*b1 = byte1;
return TRAILING_TWO;
}
cc = c - CODING_START;
byte = cc >> 4; /* Extract the upper 2 bits */
byte &= LOWER_TWO_BITS;
byte1 |= byte;
byte = cc << 4; /* The lower 4 bits */
byte2 = byte & UPPER_FOUR_BITS;
*b1 = byte1;
*b2 = byte2;
return SUCCESS;
}
convert3(c, b2, b3)
char c;
char *b2, *b3;
{
char byte2;
char byte3;
char byte;
char cc;
if ( c < START_FOUR && c >= SHORT_START )
return TRAILING_TWO;
byte2 = *b2;
if ( c >= START_FOUR && c <= SHORT_STOP ) {
byte = c - (SHORT_START + MASK_TWO);
byte2 |= byte;
*b2 = byte2;
return TRAILING_FOUR;
}
cc = c - CODING_START;
byte = cc >> 2; /* Extract the upper 4 bits */
byte &= LOWER_FOUR_BITS;
byte2 |= byte;
byte = cc << 6; /* The lower 2 bits */
byte3 = byte & UPPER_TWO_BITS;
*b2 = byte2;
*b3 = byte3;
return SUCCESS;
}
convert4(c, b3)
char c;
char *b3;
{
char byte3;
char byte;
byte3 = SHORT_START;
if ( c >= SHORT_START )
return TRAILING_CHARS;
byte3 = *b3;
byte = c - CODING_START;
byte &= LOWER_SIX_BITS;
byte3 |= byte;
*b3 = byte3;
return SUCCESS;
}
flushHerald(fi)
FILE *fi;
{
char string[MAX_LINE_LENGTH];
while ( fgets(string, MAX_LINE_LENGTH, fi) != NULL ) {
header.line++;
if ( strcmp(string, HERALD) == 0 )
return SUCCESS;
}
printf("Geeze... I didn't even get to the herald!\n");
return FAILURE;
}
readHeader(fi, h)
FILE *fi;
char *h;
{
while ( fgets(h, MAX_LINE_LENGTH, fi) != NULL ) {
header.line++;
if ( h[0] == DELIMETER )
return SUCCESS;
}
printf("Couldn't find the header!\n");
return FAILURE;
}
putAchar(byte, fo)
char byte;
int fo;
{
num++;
if ( num > BUFFER_SIZE - 1 ) {
write(fo, buffer, BUFFER_SIZE);
num = 0;
}
buffer[num] = byte;
}
flushBuffer(fo)
int fo;
{
int n;
if ( num > BUFFER_SIZE - 1 )
num = BUFFER_SIZE;
else
num++;
while ( num > 0 ) {
n = write(fo, buffer, num);
num -= n;
}
}
parseHeader(header)
struct HEADER_STRUCT *header;
{
char *s;
char h[MAX_LINE_LENGTH];
s = header -> header;
header -> useCheck = FALSE;
if ( *s != DELIMETER ) {
printf("Bad header format!\n");
return FAILURE;
}
s++;
while ( *s != '\n' && *s != '\0' ) {
if ( headerExtract(&s, h) == FAILURE )
return FAILURE;
if ( strcmp(h, CHECKSUM_STRING) == 0 )
header -> useCheck = TRUE;
}
}
headerExtract(s, h)
char **s;
char *h;
{
while ( **s == DELIMETER || **s == '\n' ) (*s)++;
while ( **s != DELIMETER ) {
if ( **s == '\0' )
return FAILURE;
*h = **s;
h++;
(*s)++;
}
*h = '\0';
return SUCCESS;
}
collectStrings(fi, s, e)
FILE *fi;
char *s;
char *e;
{
char c;
if ( getAchar(fi, &c) == EOF )
return FAILURE;
while ( c != DELIMETER ) {
*s = c;
s++;
if ( getAchar(fi, &c) == EOF )
return FAILURE;
}
*s = '\0';
if ( getAchar(fi, &c) == EOF )
return FAILURE;
if ( c == DELIMETER && *s == '\0' )
return DOUBLE_DELIMS;
if ( header.useCheck == NO ) {
while ( c != '\n' ) {
if ( getAchar(fi, &c) == EOF )
return FAILURE;
}
}
else {
if ( c == DELIMETER || c == '\n' ) {
printf("So where's the checksum?\n");
return FAILURE;
}
while ( c != DELIMETER ) {
*e = c;
if ( getAchar(fi, &c) == EOF )
return FAILURE;
e++;
}
if ( getAchar(fi, &c) == EOF )
return FAILURE;
if ( c != '\n' ) {
printf("Expected a new-line here\n");
return FAILURE;
}
}
*e = '\0';
return SUCCESS;
}
checkChecksum(header)
struct HEADER_STRUCT header;
{
if ( header.checksum != header.checksumRead )
return FAILURE;
else
return SUCCESS;
}
getAchar(fi, c)
FILE *fi;
char *c;
{
if ( (*c = fgetc(fi)) == EOF ) {
printf("Premature EOF encountered\n");
return EOF;
}
}
convertToNumber(errorChars, number)
char *errorChars;
unsigned int *number;
{
int s;
int sum, n;
unsigned int i;
char c;
s = strlen(errorChars) - 1;
sum = 0;
i = 0;
while ( s >= 0 ) {
c = errorChars[s];
n = atoi(&c);
if ( i == 0 )
sum += n;
else
sum += (n * power(10, i));
s--;
i++;
}
*number = (unsigned int) sum;
}
power(base, n)
int base, n;
{
int i, p;
p = 1;
for ( i = 1; i <= n; ++i )
p = p * base;
return p;
}
!Funky!Stuff!
echo x - asciify/definitions.h
cat >asciify/definitions.h <<'!Funky!Stuff!'
#ifndef DEFINITIONS_DEFINED
#define DEFINITIONS_DEFINED
#define TRUE 1
#define FALSE 0
#define YES TRUE
#define NO FALSE
#define VERSION_NUM 1.0
#define VERSION_STRING "Asciify Version %1.2f"
#define FILE_STRING "File %s"
#define CHECKSUM_STRING "Chk"
#define DELIMETER 0x21
#define CODING_START 0x22
#define BIT_SPAN 0x3F /* 6 bits worth */
#define SHORT_START (CODING_START + BIT_SPAN + 1)
#define MASK_TWO 0x0003
#define MASK_FOUR 0x000F
#define START_TWO SHORT_START
#define START_FOUR (SHORT_START + MASK_TWO + 1)
#define SHORT_STOP 0x7E
#define LOWER_CHAR 0x00FF
#define UPPER_CHAR 0xFF00
#define UPPER_TWO_BITS 0xC0
#define UPPER_FOUR_BITS 0xF0
#define UPPER_SIX_BITS 0xFC
#define LOWER_TWO_BITS 0x03
#define LOWER_FOUR_BITS 0x0F;
#define LOWER_SIX_BITS 0x3F
#define FAILURE 0
#define SUCCESS 1
#define NO_TRAILING 1
#define TRAILING_CHARS 2
#define TRAILING_TWO 3
#define TRAILING_FOUR 4
#define DOUBLE_DELIMS 5
#define CHECKSUM 10
#define NO_CHECKSUM 11
#define BUFFER_SIZE 1024
#define MAX_LINE_LENGTH 80
#define LINE_LENGTH 64
#define NUM_CHECKSUM_CHARS 10
#define NUM_DATA_CHARS 80
#define HERALD "(This file must be decoded with Binafy)\n"
typedef short BOOLEAN;
typedef struct HEADER_STRUCT {
char fileName[MAX_LINE_LENGTH];
char header[MAX_LINE_LENGTH];
BOOLEAN useCheck;
unsigned int checksum;
unsigned int checksumRead;
unsigned int line;
};
#define STANDARD_OUTPUT_FD 1
#endif
!Funky!Stuff!
echo x - asciify/globals.c
cat >asciify/globals.c <<'!Funky!Stuff!'
#include "definitions.h"
char buffer[BUFFER_SIZE];
int num = 0;
char *cur;
struct HEADER_STRUCT header = {
"", /* The file we are processing */
"", /* The line read */
NO, /* Perform checksums? */
0, /* CHecksum calculated */
0, /* Checksum read */
0 /* Line */
};
!Funky!Stuff!
echo x - asciify/globals.h
cat >asciify/globals.h <<'!Funky!Stuff!'
#include "definitions.h"
extern char buffer[BUFFER_SIZE];
extern int num;
extern char *cur;
extern struct HEADER_STRUCT header;
!Funky!Stuff!
echo x - asciify/tyger
cat >asciify/tyger <<'!Funky!Stuff!'
Tyger, Tyger burning bright
In the forest of the night
What immortal hand or eye
Could frame thy fearful symmetry?
!Funky!Stuff!
More information about the Alt.sources
mailing list