home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cpm68k / arc68k.arc / ARCUNP.C < prev    next >
Text File  |  1987-11-27  |  7KB  |  183 lines

  1.  
  2. /*
  3.  *      arcunp.c        1.1
  4.  *
  5.  *      Author: Thom Henderson
  6.  *      Original System V port: Mike Stump
  7.  *      Enhancements, Bug fixes, and cleanup: Chris Seaman
  8.  *      Date: Fri Mar 20 09:57:02 1987
  9.  *      Last Mod.       3/21/87
  10.  *
  11.  */
  12.  
  13. /*
  14.  * ARC - Archive utility - ARCUNP
  15.  * 
  16.  * Version 3.16, created on 02/03/86 at 23:01:16
  17.  * 
  18.  * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  19.  * 
  20.  *     Description:
  21.  *          This file contains the routines used to expand a file
  22.  *          when taking it out of an archive.
  23.  */
  24.  
  25. #include "arc.h"
  26.  
  27. /* stuff for repeat unpacking */
  28.  
  29. #define DLE 0x90                       /* repeat byte flag */
  30.  
  31. static INT state;                      /* repeat unpacking state */
  32.  
  33. /* repeat unpacking states */
  34.  
  35. #define NOHIST 0                       /* no relevant history */
  36. #define INREP 1                        /* sending a repeated value */
  37.  
  38. static unsigned crcval;                     /* CRC check value */
  39. static long size;                      /* bytes to read */
  40.  
  41. INT unpack(f,t,hdr)                    /* unpack an archive entry */
  42. FILE *f, *t;                           /* source, destination */
  43. struct heads *hdr;                     /* pointer to file header data */
  44. {
  45.     INT c;                             /* one char of stream */
  46.     INT putc_unp();
  47.     INT putc_ncr();
  48.     INT getc_unp();
  49.  
  50.     /* setups common to all methods */
  51.  
  52.     crcval = 0;                        /* reset CRC check value */
  53.     size = hdr->size;                  /* set input byte counter */
  54.     state = NOHIST;                    /* initial repeat unpacking state */
  55.     setcode();                         /* set up for decoding */
  56.  
  57.     /* use whatever method is appropriate */
  58.  
  59.     switch(hdrver) {                    /* choose proper unpack method */
  60.     case 1:                            /* standard packing */
  61.     case 2:
  62.         while ((c = getc_unp(f)) != EOF)
  63.             putc_unp(c,t);
  64.         break;
  65.     case 3:                            /* non-repeat packing */
  66.         while ((c = getc_unp(f)) != EOF)
  67.             putc_ncr(c,t);
  68.         break;
  69.     case 4:                            /* Huffman squeezing */
  70.         init_usq(f);
  71.         while ((c = getc_usq(f)) != EOF)
  72.             putc_ncr(c,t);
  73.         break;
  74.     case 5:                            /* Lempel-Zev compression */
  75.         init_ucr(0);
  76.         while ((c = getc_ucr(f)) != EOF)
  77.             putc_unp(c,t);
  78.         break;
  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.     case 7:                            /* L-Z plus ncr with new hash */
  85.         init_ucr(1);
  86.         while ((c = getc_ucr(f)) != EOF)
  87.             putc_ncr(c,t);
  88.         break;
  89.     case 8:                            /* dynamic Lempel-Zev */
  90.         decomp(f,t);
  91.         break;
  92.     default:                           /* unknown method */
  93.         if (warn)
  94.         {
  95.             printf("I don't know how to unpack file %s\n",hdr->name);
  96.             printf("I think you need a newer version of ARC\n");
  97.             nerrs++;
  98.         }
  99.         fseek(f,hdr->size,1);          /* skip over bad file */
  100.         return(1);                     /* note defective file */
  101.     }
  102.  
  103.     /* cleanups common to all methods */
  104.     if ((crcval & 0xffff) != (hdr->crc & 0x0000ffff)) {
  105.         if (warn) {
  106.             printf("WARNING: File %s fails CRC check\n",hdr->name);
  107.         printf("expected %04.4x got %04.4x\n",crcval,hdr->crc);
  108.             nerrs++;
  109.         }
  110.         return(1);                     /* note defective file */
  111.     }
  112.     return(0);                         /* file is okay */
  113. }
  114.  
  115. /*
  116.  *  This routine is used to put bytes in the output file.  It also
  117.  *  performs various housekeeping functions, such as maintaining the
  118.  *  CRC check value.
  119.  */
  120.  
  121. static INT putc_unp(c,t)               /* output an unpacked byte */
  122. char c;                                /* byte to output */
  123. FILE *t;                               /* file to output to */
  124. {
  125.     crcval = addcrc(crcval,(c & 255));       /* update the CRC check value */
  126.     putc_tst(c,t);
  127. }
  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. INT putc_ncr(c,t)                      /* put NCR coded bytes */
  142. 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
  153.             putc_unp(lastc=(c&0x00ff),t);       /* else nothing unusual */
  154.         return;
  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
  160.             putc_unp(DLE,t);           /* else output DLE as data */
  161.         state = NOHIST;                /* back to no history */
  162.         return;
  163.     default:
  164.         abort("Bad NCR unpacking state (%d)",state);
  165.     }
  166. }
  167.  
  168. /*
  169.  *  This routine provides low-level byte input from an archive.  This
  170.  *  routine MUST be used, as end-of-file is simulated at the end of
  171.  *  the archive entry.
  172.  */
  173.  
  174. INT getc_unp(f)                        /* get a byte from an archive */
  175. FILE *f;                               /* archive file to read */
  176. {
  177.     if (!size)                         /* if no data left */
  178.         return(EOF);                   /* then pretend end of file */
  179.  
  180.     size--;                            /* deduct from input counter */
  181.     return(code(fgetc(f)));            /* and return next decoded byte */
  182. }
  183.