home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 157.lha / Arc_Src / arcunp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-27  |  5.8 KB  |  176 lines

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