/* atob: version 4.0jp * stream filter to change printable ascii from "btoa" back into 8 bit bytes * if bad chars, or Csums do not match: exit(1) [and NO output] * * Paul Rutter Joe Orost * philabs!per petsd!joe * * Modified by Jef Poskanzer to get rid of the annoying * and wasteful no-output stuff. This makes it run twice as fast. Still * does exit(1), of course. */ #include #define reg register #define streq(s0, s1) strcmp(s0, s1) == 0 #define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x) long int Ceor = 0; long int Csum = 0; long int Crot = 0; long int word = 0; int bcount = 0; long int prevword; int prevfull = 0; fatal() { fprintf(stderr, "bad format or Csum to atob\n"); exit(1); } #define DE(c) ((c) - '!') decode(c) reg c; { if (c == 'z') { if (bcount != 0) fatal(); word = 0; wordout(); } else if ((c >= '!') && (c < ('!' + 85))) { if (bcount == 0) { word = DE(c); ++bcount; } else if (bcount < 4) { word = times85(word); word += DE(c); ++bcount; } else { word = times85(word) + DE(c); wordout(); word = 0; bcount = 0; } } else fatal(); } wordout() { /*write out previous word, if any*/ if (prevfull) { byteout((int)((prevword >> 24) & 255), 1); byteout((int)((prevword >> 16) & 255), 1); byteout((int)((prevword >> 8) & 255), 1); byteout((int)(prevword & 255), 1); } /*save word for later output*/ prevword = word; prevfull = 1; } byteout(c, really) reg c; int really; { Ceor ^= c; Csum += c; Csum += 1; if ((Crot & 0x80000000)) { Crot <<= 1; Crot += 1; } else Crot <<= 1; Crot += c; if (really) putc(c, stdout); } main(argc, argv) char **argv; { reg c; reg long int i; char buf[100]; long int n1, n2, oeor, osum, orot; if (argc != 1) { fprintf(stderr,"bad args to %s\n", argv[0]); exit(2); } /*search for header line*/ for (;;) { if (fgets(buf, sizeof buf, stdin) == NULL) fatal(); if (streq(buf, "xbtoa Begin\n")) break; } while ((c = getchar()) != EOF) { if (c == '\n') continue; if (c == 'x') break; decode(c); } if(scanf("btoa End N %ld %lx E %lx S %lx R %lx\n", &n1, &n2, &oeor, &osum, &orot) != 5) fatal(); if (n1 != n2) fatal(); if (prevfull) { switch (n1 % 4) { case 0: byteout((int)((prevword >> 24) & 255), 1); byteout((int)((prevword >> 16) & 255), 1); byteout((int)((prevword >> 8) & 255), 1); byteout((int)(prevword & 255), 1); break; case 1: byteout((int)((prevword >> 24) & 255), 1); byteout((int)((prevword >> 16) & 255), 0); byteout((int)((prevword >> 8) & 255), 0); byteout((int)(prevword & 255), 0); break; case 2: byteout((int)((prevword >> 24) & 255), 1); byteout((int)((prevword >> 16) & 255), 1); byteout((int)((prevword >> 8) & 255), 0); byteout((int)(prevword & 255), 0); break; case 3: byteout((int)((prevword >> 24) & 255), 1); byteout((int)((prevword >> 16) & 255), 1); byteout((int)((prevword >> 8) & 255), 1); byteout((int)(prevword & 255), 0); break; } } if (oeor != Ceor || osum != Csum || orot != Crot) fatal(); exit(0); }