home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / ARC521-2.ZIP / ARCUNP.C < prev    next >
C/C++ Source or Header  |  1989-12-29  |  6KB  |  227 lines

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