home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / c / btoa.arc / BTOA.C < prev    next >
C/C++ Source or Header  |  1989-01-24  |  4KB  |  169 lines

  1. /* btoa: version 4.0
  2.  * stream filter to change 8 bit bytes into printable ascii
  3.  * computes the number of bytes, and three kinds of simple checksums
  4.  * incoming bytes are collected into 32-bit words, then printed in base 85
  5.  *  exp(85,5) > exp(2,32)
  6.  * the ASCII characters used are between '!' and 'u'
  7.  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
  8.  *
  9.  *  original authors:
  10.  *  Paul Rutter        Joe Orost
  11.  *  philabs!per        petsd!joe
  12.  *
  13.  *  This version PC-specific - MSC/TC compatible
  14.  *  rj berry bellevue wa 1/21/89 
  15.  *  CS 73407,3152  uucp ...uw-beaver!tikal!ole!ray
  16.  *
  17.  /* TAB 4 */
  18.  
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <io.h>
  22.  
  23. #ifdef ASM
  24. #pragma inline
  25. #endif
  26.  
  27. #define MAXPERLINE 78
  28.  
  29. char vers[]="[RJB 1/21/89]";
  30.  
  31. long unsigned Ceor = 0;
  32. long unsigned Csum = 0;
  33. long unsigned Crot = 0;
  34.  
  35. int ccount = 0;
  36. int bcount = 3;
  37. char tmp[5];
  38.  
  39. union {
  40.     unsigned long word;
  41.     unsigned char uchar[4];
  42.       } ublock;
  43.  
  44. encode(unsigned char c)
  45. {
  46.     Ceor ^= c;
  47.     Csum += c;
  48.     Csum += 1;
  49.     if (Crot & 0x80000000) {
  50.         Crot <<= 1;
  51.         Crot += 1;
  52.     }
  53.     else 
  54.         Crot <<= 1;
  55.     Crot += c;
  56.     ublock.uchar[bcount--] = c;
  57.     if (bcount < 0) {
  58.         wordout();
  59.         bcount = 3;
  60.     }
  61. }
  62.  
  63. wordout()
  64.  
  65. {
  66.     
  67.     if (ublock.word == 0L) {
  68.         putchar('z');        /* note: 'z' is outside mod-85 char set */
  69.         if (++ccount == MAXPERLINE) {
  70.             putchar('\n');
  71.             ccount=0;
  72.         }
  73.     }
  74.     else {
  75.         int i;
  76.  
  77. #ifndef ASM
  78.  
  79.         for(i=0; i<5; i++ ,ublock.word /=85)
  80.             tmp[i] = ublock.word % 85 + '!';
  81. #else
  82.  
  83. /* Woof.  TC is abysmal on the 2 lines of code above ("abysmal"= 2-3X
  84.  * slower than MSC 5.1.), even if faster than the original shift/add method.
  85.  * However, the following ASM code fixes that :-).  TC w/ASM is about 1.4X 
  86.  * faster than MSC 5.1 /Ox without.
  87.  */
  88.  
  89. asm    mov    cx, 85            /* CX holds divisor through conversion*/
  90. asm    mov    si, "!!"        /* added to remainder to make printable ascii*/
  91. asm mov di, OFFSET tmp    /* ptr to char array holding base-85 rep */
  92.  
  93.         /*    first, do two 32/16 divides assuming >16 bit quotients*/
  94.  
  95. asm    mov    ax, ublock.uchar[2]    /* get top 16 bits of dividend*/
  96. asm    mov    bx, ublock.uchar[0]    /* BX used as swap register*/
  97. asm    xor        dx, dx        /* clear top of dividend*/
  98. asm    div        cx            /* div top half by 85 (pquo>AX, prem>DX)*/
  99. asm    xchg    ax, bx        /* get bottom half, save quotient*/
  100. asm    div        cx            /* BX:AX now holds first 32 bit quotient*/
  101. asm    add        dx, si        /* make modulus into printable ASCII*/
  102. asm    mov        [di], dl    /* store LS digit of result*/
  103. asm    inc        di            /* incr char ptr */
  104. asm    xchg    ax, bx        /* put top of new dividend in bottom half of DX:AX*/
  105. asm    xor        dx, dx        /* prepare for another division*/
  106. asm    div        cx            /* partial quo in AX, partial rem in DX*/
  107. asm    xchg    ax, bx        /* PREM:(BOT) into DX:AX, save partial quo*/
  108. asm    div        cx            /* BX:AX again holds 32 bit quotient*/
  109. asm    add        dx, si        /* process 2nd char of result*/
  110. asm    mov        [di], dl
  111. asm    inc        di
  112.  
  113.         /* 2^32 / 85^3 < 2^16; i.e., next quo. will be < 16 bits*/
  114.  
  115. asm    mov        dx, bx
  116. asm    div        cx            /* quotient is in AX - no overflow possible*/
  117. asm    add        dx, si
  118. asm    mov        [di], dl    /* 3rd digit of result*/
  119. asm    inc        di
  120.  
  121.         /* similarly, next digit will have byte quotient*/
  122.         /* and remainder will be final digit of answer*/
  123.  
  124. asm    div        cl            /* quo in AL, rem in AH (2 final digits )*/
  125. asm    add        ax, si        /* make both into printable chars*/
  126. asm    xchg    al, ah        /* correct byte order */
  127. asm    mov        [di], ax    /* store both chars */
  128.  
  129. #endif
  130.  
  131.         for(i=4; i>=0; i--) {
  132.             putchar(tmp[i]);
  133.             if (++ccount == MAXPERLINE) {
  134.                 putchar('\n');
  135.                 ccount = 0;
  136.             }
  137.         }
  138.     }
  139. }
  140.  
  141. main(int argc, char *argv[])
  142. {
  143.     int c;
  144.     long n=0;
  145.  
  146.     if (argc != 1) {
  147.         fprintf(stderr,"bad args to %s\n", argv[0]);
  148.         exit(2);
  149.     }
  150.     /* MS-DOS: no translation on input or output */
  151.     setmode(fileno(stdin), O_BINARY);
  152.     setmode(fileno(stdout), O_BINARY);
  153.     
  154.     printf("xbtoa Begin\n");
  155.     
  156.     while ((c = getchar()) != EOF) {
  157.         encode(c);
  158.         n++;
  159.     }
  160.     while (bcount != 3)
  161.         encode(0);
  162.  
  163.     /* n is written twice as crude cross check*/
  164.     printf("\nxbtoa End N %ld %lx E %lx S %lx R %lx\n", n, n, Ceor, Csum, Crot);
  165.  
  166.     exit(0);
  167. }
  168.  
  169.