home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / yabbawhap / part03 / unwhap.c < prev    next >
C/C++ Source or Header  |  1991-10-09  |  6KB  |  272 lines

  1. /* Placed into the public domain by Daniel J. Bernstein. */
  2.  
  3. static char whapwarning[] = "\
  4. WARNING! If you use AP coding except for instruction and amusement,\n\
  5. you may be infringing upon a patent.\n\
  6. ";
  7.  
  8. #include <stdio.h>
  9. extern long atol();
  10. extern int getopt();
  11. extern char *optarg;
  12. extern int optind;
  13. #include "percent.h"
  14. #include "texts.h"
  15.  
  16. static char progname[] = "unwhap";
  17. static char progged[] = "Unwhapped";
  18.  
  19. #ifndef TYPE
  20. #define TYPE short
  21. #endif
  22.  
  23. typedef TYPE bitnum;
  24. typedef unsigned TYPE bitword;
  25.  
  26. int twom1[9] = { 0,1,3,7,15,31,63,127,255 } ;
  27.  
  28. #ifndef NODEMAX
  29. #define NODEMAX (65533)
  30. #endif
  31. #ifndef NODENUM
  32. #define NODENUM NODEMAX
  33. #endif
  34. static char outarray[NODEMAX]; /* first 256 spots unused, boo hoo hoo */
  35. static bitword outstart[NODEMAX]; /* first 256 spots unused, boo hoo hoo */
  36.  
  37. #define MAXPLUS max++; oamax++; osmax++; \
  38. if (max == nextbits) { bits++; nextbits <<= 1; }
  39.  
  40. static unsigned long savein;
  41. static unsigned long saveout;
  42. static int flagverbose = 1;
  43. static int flagrandom = 0;
  44.  
  45. void goaheadandbeverbose()
  46. {
  47.  long per = percent(savein,saveout,10000L);
  48.  
  49.  if (per == 10000L) /* absolutely ridiculous */
  50.    fprintf(stderr,"In: %ld chars  Out: %ld chars  %s from: >9999%%\n",
  51.            savein,saveout,progged);
  52.  else
  53.    fprintf(stderr,"In: %ld chars  Out: %ld chars  %s from: %ld%%\n",
  54.        savein,saveout,progged,per);
  55. }
  56.  
  57. void fatalinfo(x,s)
  58. int x;
  59. char **s;
  60. {
  61.  if (flagverbose) while (*s)
  62.   {
  63.    fprintf(stderr,*(s++),NODENUM);
  64.    putc('\n',stderr);
  65.   }
  66.  (void) exit(x);
  67. }
  68.  
  69. #define PUTERR { if (flagverbose) fprintf(stderr,"%s: fatal: output error\n",progname); \
  70. savein = in; saveout = out; \
  71. if (flagverbose >= 2) goaheadandbeverbose(); (void) exit(2); }
  72.  
  73. main(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.  register bitword i;
  78.  register char *j;
  79.  register bitword outb;
  80.  register bitword max;
  81.  register bitword nextbits;
  82.  register bitnum bits;
  83.  register bitword curw = 0;
  84.  register bitnum curbb = 0;
  85.  register int ch;
  86.  register char *oamax;
  87.  register bitword *osmax;
  88.  register char *oai;
  89.  register bitword min = NODENUM - 1; /* maximum decompressor size - 1 */
  90.  register unsigned long in = 0;
  91.  register unsigned long out = 0;
  92.  
  93.   {
  94.    int opt;
  95.    bitword i;
  96.  
  97.    while ((opt = getopt(argc,argv,"m:vqQrRACHUVW")) != EOF)
  98.      switch(opt)
  99.       {
  100.        case '?': fatalinfo(1,unsqusage);
  101.        case 'm': i = atol(optarg);
  102.          if ((i < 512) || (i > NODEMAX))
  103.           {
  104.            if (flagverbose) fprintf(stderr,
  105.               "%s: fatal: mem size out of range: must be between 512 and %ld\n",
  106.               progname,(long) NODEMAX);
  107.            (void) exit(1);
  108.           }
  109.          min = i - 1;
  110.          break;
  111.        case 'v': flagverbose = 2; break;
  112.        case 'q': flagverbose = 0; break;
  113.        case 'Q': flagverbose = 1; break;
  114.        case 'r': flagrandom = 1; break;
  115.        case 'R': flagrandom = 0; break;
  116.        case 'A': fatalinfo(1,unsqauthor); break;
  117.        case 'C': fatalinfo(1,unsqcopyright); break;
  118.        case 'H': fatalinfo(1,unsqhelp); break;
  119.        case 'U': fatalinfo(1,unsqusage); break;
  120.        case 'V': fatalinfo(1,unsqversion); break;
  121.        case 'W': fatalinfo(1,unsqwarranty); break;
  122.       }
  123.    argv += optind;
  124.    argc -= optind;
  125.   }
  126.  
  127.  if (flagverbose)
  128.    fprintf(stderr,whapwarning);
  129.  
  130.  if (!flagrandom)
  131.   {
  132.    bitword i = 0;
  133.    int r;
  134.  
  135.    if ((getchar() != 23)
  136.      ||(getchar() != 8)
  137.      ||(getchar() != 1)
  138.      ||(getchar() != 16)
  139.      ||((r = getchar()) == EOF))
  140.     {
  141.      if (flagverbose) fprintf(stderr,"%s: fatal: input not in right format\n",progname);
  142.      (void) exit(3);
  143.     }
  144.    in += 5;
  145.    while (r)
  146.     {
  147.      if (((ch = getchar()) == EOF) || (ch < 48) || (ch > 57))
  148.       {
  149.        if (flagverbose) fprintf(stderr,"%s: fatal: input not in right format\n",progname);
  150.        (void) exit(3);
  151.       }
  152.      ++in;
  153.      i = i * 10 + (ch - 48);
  154.      --r;
  155.     }
  156.    if (i != min + 1)
  157.     {
  158.      if (flagverbose) fprintf(stderr,"%s: fatal: input has -m %ld, I have -m %ld\n"
  159.          ,progname,(long) i,(long) (min + 1));
  160.      (void) exit(4);
  161.     }
  162.   }
  163.  
  164. #define MINIT max = 256; oamax = outarray + 256; osmax = outstart + 256; \
  165. outb = 256; nextbits = 256; bits = 8; \
  166. while (max >= nextbits) { bits++; nextbits <<= 1; }
  167. /* of course, max = 255 plus one for table clearing */
  168.  
  169.  MINIT
  170.  
  171.  for (;;)
  172.   {
  173.    /* assumes bits >= 8 */
  174.    while (curbb + 8 < bits) /* could be an if, when bits is < 16 */
  175.      if ((ch = getchar()) != EOF)
  176.       {
  177.        curw += ch << curbb;
  178.        curbb += 8;
  179.        ++in; /* XXX: check for overflow */
  180.       }
  181.      else
  182.       {
  183.        savein = in; saveout = out;
  184.        if (flagverbose >= 2)
  185.      goaheadandbeverbose();
  186.        (void) exit(0);
  187.       }
  188.    if ((ch = getchar()) == EOF)
  189.     {
  190.      savein = in; saveout = out;
  191.      if (flagverbose >= 2)
  192.        goaheadandbeverbose();
  193.      (void) exit(0);
  194.     }
  195.    i = curw + ((ch & twom1[bits - curbb]) << curbb);
  196.    curw = ch >> (bits - curbb);
  197.    curbb = 8 - (bits - curbb);
  198.    ++in; /* XXX: check for overflow */
  199.  
  200.    /* XXX: flagpedantic to control whether we make this test? */
  201.    if (i > max)
  202.      if (flagrandom)
  203.        i -= max + 1;
  204.      else
  205.       {
  206.        if (flagverbose) fprintf(stderr,"%s: fatal: input corrupt at byte %ld\n",progname,in);
  207.        (void) exit(5);
  208.       }
  209.  
  210.    if (i < 257) /* 256 is special */
  211.      if (i != 256)
  212.       {
  213.        if (max != min)
  214.     {
  215.          MAXPLUS
  216.      *osmax = outb;
  217.      *oamax = i;
  218.          outb = max;
  219.     }
  220. #ifdef BRAINDAMAGED
  221.        if (i == 255)
  222.      putchar((char) i);
  223.        else
  224. #endif
  225.        if (putchar((char) i) == EOF)
  226.          PUTERR
  227.        ++out; /* XXX: check for overflow */
  228.       }
  229.      else
  230.       {
  231.        /* here's where blocking stuff should go */
  232.        MINIT
  233.        /* wow, that was easy */
  234.       }
  235.    else
  236.     {
  237.      oai = outarray + i;
  238.      j = outarray + outstart[i] - 1;
  239.      while ((j != oai) && (max != min))
  240.       {
  241.        MAXPLUS
  242.        *oamax = *++j;
  243. #ifdef BRAINDAMAGED
  244.        if (*oamax == (char) 255)
  245.      putchar(*oamax);
  246.        else
  247. #endif
  248.        if (putchar(*oamax) == EOF)
  249.      PUTERR
  250.        ++out; /* XXX: check for overflow */
  251.        *osmax = outb;
  252.       }
  253.      while (j != oai)
  254.       {
  255.        ++j;
  256. #ifdef BRAINDAMAGED
  257.        if (*j == (char) 255)
  258.      putchar(*j);
  259.        else
  260. #endif
  261.        if (putchar(*j) == EOF)
  262.      PUTERR
  263.        ++out; /* XXX: check for overflow */
  264.       }
  265.      outb = max - (i - outstart[i]);
  266.     }
  267. #ifdef notdef
  268. /*XXX: -d code */
  269. #endif
  270.   }
  271. }
  272.