home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
c
/
btoa.arc
/
BTOA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-24
|
4KB
|
169 lines
/* btoa: version 4.0
* stream filter to change 8 bit bytes into printable ascii
* computes the number of bytes, and three kinds of simple checksums
* incoming bytes are collected into 32-bit words, then printed in base 85
* exp(85,5) > exp(2,32)
* the ASCII characters used are between '!' and 'u'
* 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
*
* original authors:
* Paul Rutter Joe Orost
* philabs!per petsd!joe
*
* This version PC-specific - MSC/TC compatible
* rj berry bellevue wa 1/21/89
* CS 73407,3152 uucp ...uw-beaver!tikal!ole!ray
*
/* TAB 4 */
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#ifdef ASM
#pragma inline
#endif
#define MAXPERLINE 78
char vers[]="[RJB 1/21/89]";
long unsigned Ceor = 0;
long unsigned Csum = 0;
long unsigned Crot = 0;
int ccount = 0;
int bcount = 3;
char tmp[5];
union {
unsigned long word;
unsigned char uchar[4];
} ublock;
encode(unsigned char c)
{
Ceor ^= c;
Csum += c;
Csum += 1;
if (Crot & 0x80000000) {
Crot <<= 1;
Crot += 1;
}
else
Crot <<= 1;
Crot += c;
ublock.uchar[bcount--] = c;
if (bcount < 0) {
wordout();
bcount = 3;
}
}
wordout()
{
if (ublock.word == 0L) {
putchar('z'); /* note: 'z' is outside mod-85 char set */
if (++ccount == MAXPERLINE) {
putchar('\n');
ccount=0;
}
}
else {
int i;
#ifndef ASM
for(i=0; i<5; i++ ,ublock.word /=85)
tmp[i] = ublock.word % 85 + '!';
#else
/* Woof. TC is abysmal on the 2 lines of code above ("abysmal"= 2-3X
* slower than MSC 5.1.), even if faster than the original shift/add method.
* However, the following ASM code fixes that :-). TC w/ASM is about 1.4X
* faster than MSC 5.1 /Ox without.
*/
asm mov cx, 85 /* CX holds divisor through conversion*/
asm mov si, "!!" /* added to remainder to make printable ascii*/
asm mov di, OFFSET tmp /* ptr to char array holding base-85 rep */
/* first, do two 32/16 divides assuming >16 bit quotients*/
asm mov ax, ublock.uchar[2] /* get top 16 bits of dividend*/
asm mov bx, ublock.uchar[0] /* BX used as swap register*/
asm xor dx, dx /* clear top of dividend*/
asm div cx /* div top half by 85 (pquo>AX, prem>DX)*/
asm xchg ax, bx /* get bottom half, save quotient*/
asm div cx /* BX:AX now holds first 32 bit quotient*/
asm add dx, si /* make modulus into printable ASCII*/
asm mov [di], dl /* store LS digit of result*/
asm inc di /* incr char ptr */
asm xchg ax, bx /* put top of new dividend in bottom half of DX:AX*/
asm xor dx, dx /* prepare for another division*/
asm div cx /* partial quo in AX, partial rem in DX*/
asm xchg ax, bx /* PREM:(BOT) into DX:AX, save partial quo*/
asm div cx /* BX:AX again holds 32 bit quotient*/
asm add dx, si /* process 2nd char of result*/
asm mov [di], dl
asm inc di
/* 2^32 / 85^3 < 2^16; i.e., next quo. will be < 16 bits*/
asm mov dx, bx
asm div cx /* quotient is in AX - no overflow possible*/
asm add dx, si
asm mov [di], dl /* 3rd digit of result*/
asm inc di
/* similarly, next digit will have byte quotient*/
/* and remainder will be final digit of answer*/
asm div cl /* quo in AL, rem in AH (2 final digits )*/
asm add ax, si /* make both into printable chars*/
asm xchg al, ah /* correct byte order */
asm mov [di], ax /* store both chars */
#endif
for(i=4; i>=0; i--) {
putchar(tmp[i]);
if (++ccount == MAXPERLINE) {
putchar('\n');
ccount = 0;
}
}
}
}
main(int argc, char *argv[])
{
int c;
long n=0;
if (argc != 1) {
fprintf(stderr,"bad args to %s\n", argv[0]);
exit(2);
}
/* MS-DOS: no translation on input or output */
setmode(fileno(stdin), O_BINARY);
setmode(fileno(stdout), O_BINARY);
printf("xbtoa Begin\n");
while ((c = getchar()) != EOF) {
encode(c);
n++;
}
while (bcount != 3)
encode(0);
/* n is written twice as crude cross check*/
printf("\nxbtoa End N %ld %lx E %lx S %lx R %lx\n", n, n, Ceor, Csum, Crot);
exit(0);
}