Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / miscellany / compress-4.0 / btoa.c
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  *  Paul Rutter         Joe Orost
10  *  philabs!per         petsd!joe
11  *
12  *  WARNING: this version is not compatible with the original as sent out
13  *  on the net.  The original encoded from ' ' to 't'; which cause problems
14  *  with some mailers (stripping off trailing blanks).
15  */
16
17 #include <stdio.h>
18
19 #define reg register
20
21 #define MAXPERLINE 78
22
23 long int Ceor = 0;
24 long int Csum = 0;
25 long int Crot = 0;
26
27 long int ccount = 0;
28 long int bcount = 0;
29 long int word;
30
31 #define EN(c)   (int) ((c) + '!')
32
33 encode(c) 
34   reg c;
35 {
36   Ceor ^= c;
37   Csum += c;
38   Csum += 1;
39   if ((Crot & 0x80000000)) {
40     Crot <<= 1;
41     Crot += 1;
42   } else {
43     Crot <<= 1;
44   }
45   Crot += c;
46
47   word <<= 8;
48   word |= c;
49   if (bcount == 3) {
50     wordout(word);
51     bcount = 0;
52   } else {
53     bcount += 1;
54   }
55 }
56
57 wordout(word) 
58   reg long int word;
59 {
60   if (word == 0) {
61     charout('z');
62   } else {
63     reg int tmp = 0;
64     
65     if(word < 0) {      /* Because some don't support unsigned long */
66       tmp = 32;
67       word = word - (long)(85 * 85 * 85 * 85 * 32);
68     }
69     if(word < 0) {
70       tmp = 64;
71       word = word - (long)(85 * 85 * 85 * 85 * 32);
72     }
73     charout(EN((word / (long)(85 * 85 * 85 * 85)) + tmp));
74     word %= (long)(85 * 85 * 85 * 85);
75     charout(EN(word / (85 * 85 * 85)));
76     word %= (85 * 85 * 85);
77     charout(EN(word / (85 * 85)));
78     word %= (85 * 85);
79     charout(EN(word / 85));
80     word %= 85;
81     charout(EN(word));
82   }
83 }
84
85 charout(c) {
86   putchar(c);
87   ccount += 1;
88   if (ccount == MAXPERLINE) {
89     putchar('\n');
90     ccount = 0;
91   }
92 }
93
94 main(argc,argv) 
95   char **argv;
96 {
97   reg c;
98   reg long int n;
99
100   if (argc != 1) {
101     fprintf(stderr,"bad args to %s\n", argv[0]);
102     exit(2);
103   }
104   printf("xbtoa Begin\n");
105   n = 0;
106   while ((c = getchar()) != EOF) {
107     encode(c);
108     n += 1;
109   }
110   while (bcount != 0) {
111     encode(0);
112   }
113   /* n is written twice as crude cross check*/
114   printf("\nxbtoa End N %ld %lx E %lx S %lx R %lx\n", n, n, Ceor, Csum, Crot);
115   exit(0);
116 }