home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8707 / 67 / arcunp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  6.4 KB  |  206 lines

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