home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / OS2ARC_S.ZIP / ARCUNP.C < prev    next >
C/C++ Source or Header  |  1987-10-14  |  6KB  |  182 lines

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