home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d0xx / d050 / unixarc.lha / UnixArc / arcunp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-01-17  |  5.7 KB  |  174 lines

  1. /*  ARC - Archive utility - ARCUNP
  2.  
  3. (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  4.  
  5.     By:  Thom Henderson
  6.  
  7.     Description:
  8.          This file contains the routines used to expand a file
  9.          when taking it out of an archive.
  10.  
  11.     Language:
  12.          Computer Innovations Optimizing C86
  13. */
  14. #include <stdio.h>
  15. #include "arc.h"
  16.  
  17. /* stuff for repeat unpacking */
  18.  
  19. #define DLE 0x90                       /* repeat byte flag */
  20.  
  21. static int state;                      /* repeat unpacking state */
  22.  
  23. /* repeat unpacking states */
  24.  
  25. #define NOHIST 0                       /* no relevant history */
  26. #define INREP 1                        /* sending a repeated value */
  27.  
  28. static int crcval;                     /* CRC check value */
  29. static long size;                      /* bytes to read */
  30.  
  31. int unpack(f,t,hdr)                    /* unpack an archive entry */
  32. FILE *f, *t;                           /* source, destination */
  33. struct heads *hdr;                     /* pointer to file header data */
  34. {
  35.     int c;                             /* one char of stream */
  36.  
  37.     /* setups common to all methods */
  38.  
  39.     crcval = 0;                        /* reset CRC check value */
  40.     size = hdr->size;                  /* set input byte counter */
  41.     state = NOHIST;                    /* initial repeat unpacking state */
  42.     setcode();                         /* set up for decoding */
  43.  
  44.     /* use whatever method is appropriate */
  45.  
  46.     switch(hdrver)                     /* choose proper unpack method */
  47.     {
  48.     case 1:                            /* standard packing */
  49.     case 2:
  50.          while((c=getc_unp(f))!=EOF)
  51.               putc_unp(c,t);
  52.          break;
  53.  
  54.     case 3:                            /* non-repeat packing */
  55.          while((c=getc_unp(f))!=EOF)
  56.               putc_ncr(c,t);
  57.          break;
  58.  
  59.     case 4:                            /* Huffman squeezing */
  60.          init_usq(f);
  61.          while((c=getc_usq(f))!=EOF)
  62.               putc_ncr(c,t);
  63.          break;
  64.  
  65.     case 5:                            /* Lempel-Zev compression */
  66.          init_ucr(0);
  67.          while((c=getc_ucr(f))!=EOF)
  68.               putc_unp(c,t);
  69.          break;
  70.  
  71.     case 6:                            /* Lempel-Zev plus non-repeat */
  72.          init_ucr(0);
  73.          while((c=getc_ucr(f))!=EOF)
  74.               putc_ncr(c,t);
  75.          break;
  76.  
  77.     case 7:                            /* L-Z plus ncr with new hash */
  78.          init_ucr(1);
  79.          while((c=getc_ucr(f))!=EOF)
  80.               putc_ncr(c,t);
  81.          break;
  82.  
  83.     case 8:                            /* dynamic Lempel-Zev */
  84.          decomp(f,t);
  85.          break;
  86.  
  87.     default:                           /* unknown method */
  88.          if(warn)
  89.          {    printf("I don't know how to unpack file %s\n",hdr->name);
  90.               printf("I think you need a newer version of ARC\n");
  91.               nerrs++;
  92.          }
  93.          fseek(f,hdr->size,1);         /* skip over bad file */
  94.          return 1;                     /* note defective file */
  95.     }
  96.  
  97.     /* cleanups common to all methods */
  98.  
  99.     if(crcval!=hdr->crc)
  100.     {    if(warn)
  101.          {    printf("WARNING: File %s fails CRC check\n",hdr->name);
  102.               nerrs++;
  103.          }
  104.          return 1;                     /* note defective file */
  105.     }
  106.     return 0;                          /* file is okay */
  107. }
  108.  
  109. /*  This routine is used to put bytes in the output file.  It also
  110.     performs various housekeeping functions, such as maintaining the
  111.     CRC check value.
  112. */
  113.  
  114. static putc_unp(c,t)                   /* output an unpacked byte */
  115. char c;                                /* byte to output */
  116. FILE *t;                               /* file to output to */
  117. {
  118.     crcval = addcrc(crcval,c);         /* update the CRC check value */
  119.     putc_tst(c,t);
  120. }
  121.  
  122. /*  This routine is used to decode non-repeat compression.  Bytes are
  123.     passed one at a time in coded format, and are written out uncoded.
  124.     The data is stored normally, except that runs of more than two
  125.     characters are represented as:
  126.  
  127.          <char> <DLE> <count>
  128.  
  129.     With a special case that a count of zero indicates a DLE as data,
  130.     not as a repeat marker.
  131. */
  132.  
  133. putc_ncr(c,t)                          /* put NCR coded bytes */
  134. unsigned char c;                       /* next byte of stream */
  135. FILE *t;                               /* file to receive data */
  136. {
  137.     static int lastc;                  /* last character seen */
  138.  
  139.     switch(state)                      /* action depends on our state */
  140.     {
  141.     case NOHIST:                       /* no previous history */
  142.          if(c==DLE)                    /* if starting a series */
  143.               state = INREP;           /* then remember it next time */
  144.          else putc_unp(lastc=c,t);     /* else nothing unusual */
  145.          return;
  146.  
  147.     case INREP:                        /* in a repeat */
  148.          if(c)                         /* if count is nonzero */
  149.               while(--c)               /* then repeatedly ... */
  150.                    putc_unp(lastc,t);  /* ... output the byte */
  151.          else putc_unp(DLE,t);         /* else output DLE as data */
  152.          state = NOHIST;               /* back to no history */
  153.          return;
  154.  
  155.     default:
  156.          abort("Bad NCR unpacking state (%d)",state);
  157.     }
  158. }
  159.  
  160. /*  This routine provides low-level byte input from an archive.  This
  161.     routine MUST be used, as end-of-file is simulated at the end of
  162.     the archive entry.
  163. */
  164.  
  165. int getc_unp(f)                        /* get a byte from an archive */
  166. FILE *f;                               /* archive file to read */
  167. {
  168.     if(!size)                          /* if no data left */
  169.          return EOF;                   /* then pretend end of file */
  170.  
  171.     size--;                            /* deduct from input counter */
  172.     return code(fgetc(f));             /* and return next decoded byte */
  173. }
  174.