home *** CD-ROM | disk | FTP | other *** search
- /* 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);
- }
-
-