home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / COMPRESS / ARC520S.ZIP / ARCPACK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-10-23  |  7.7 KB  |  207 lines

  1. /*  ARC - Archive utility - ARCPACK
  2.  
  3.     Version 3.46, created on 10/23/86 at 17:47:06
  4.  
  5. (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
  6.  
  7.     By:  Thom Henderson
  8.  
  9.     Description:
  10.          This file contains the routines used to compress a file
  11.          when placing it in an archive.
  12.  
  13.     Language:
  14.          Computer Innovations Optimizing C86
  15. */
  16. #include <stdio.h>
  17. #include "arc.h"
  18.  
  19. /* stuff for non-repeat packing */
  20.  
  21. #define DLE 0x90                       /* repeat sequence marker */
  22.  
  23. static unsigned char state;            /* current packing state */
  24.  
  25. /* non-repeat packing states */
  26.  
  27. #define NOHIST  0                      /* don't consider previous input*/
  28. #define SENTCHAR 1                     /* lastchar set, no lookahead yet */
  29. #define SENDNEWC 2                     /* run over, send new char next */
  30. #define SENDCNT 3                      /* newchar set, send count next */
  31.  
  32. /* packing results */
  33.  
  34. static long stdlen;                    /* length for standard packing */
  35. static int crcval;                     /* CRC check value */
  36.  
  37. pack(f,t,hdr)                          /* pack file into an archive */
  38. FILE *f, *t;                           /* source, destination */
  39. struct heads *hdr;                     /* pointer to header data */
  40. {
  41.     int c;                             /* one character of stream */
  42.     long ncrlen;                       /* length after packing */
  43.     long lzwlen;                       /* length after crunching */
  44.     long pred_cm();                    /* dynamic crunching cleanup */
  45.     long tloc, ftell();                /* start of output */
  46.  
  47.     /* first pass - see which method is best */
  48.  
  49.     tloc = ftell(t);                   /* note start of output */
  50.  
  51.     if(!nocomp)                        /* if storage kludge not active */
  52.     {    if(note)
  53.               printf(" analyzing, ");
  54.  
  55.          state = NOHIST;               /* initialize ncr packing */
  56.          stdlen =  ncrlen = 0;         /* reset size counters */
  57.          crcval = 0;                   /* initialize CRC check value */
  58.          setcode();                    /* initialize encryption */
  59.  
  60.          init_cm(f,t);                 /* initialize for crunching */
  61.  
  62.          while((c=getc_ncr(f))!=EOF)   /* for each byte of file */
  63.          {    ncrlen++;                /* one more packed byte */
  64.               putc_cm(c,t);            /* see what crunching can do */
  65.          }
  66.          lzwlen = pred_cm(t);          /* finish up after crunching */
  67.     }
  68.     else                               /* else kludge the method */
  69.     {    stdlen = 0;                   /* make standard look best */
  70.          ncrlen = lzwlen = 1;
  71.     }
  72.  
  73.     /* standard set-ups common to all methods */
  74.  
  75.     fseek(f,0L,0);                     /* rewind input */
  76.     hdr->crc = crcval;                 /* note CRC check value */
  77.     hdr->length = stdlen;              /* set actual file length */
  78.     state = NOHIST;                    /* reinitialize ncr packing */
  79.     setcode();                         /* reinitialize encryption */
  80.  
  81.     /* choose and use the shortest method */
  82.  
  83.     if(kludge && note)
  84.          printf("\n\tS:%ld  P:%ld  C:%ld,\t ",stdlen,ncrlen,lzwlen);
  85.  
  86.     if(stdlen<=ncrlen && stdlen<=lzwlen)
  87.     {    if(note)
  88.               printf("storing, ");     /* store without compression */
  89.          hdrver = 2;                   /* note packing method */
  90.          fseek(t,tloc,0);              /* reset output for new method */
  91.          if(nocomp)                    /* store only kludge skips things */
  92.          {    stdlen = crcval = 0;     /* recalc these for kludge */
  93.               while((c=getch(f))!=EOF) /* store it straight */
  94.                    putc_pak(c,t);
  95.          }
  96.          else filecopy(f,t,stdlen);    /* else use fast file copier */
  97.          hdr->crc = crcval;
  98.          hdr->length = hdr->size = stdlen;
  99.     }
  100.  
  101.     else if(ncrlen<lzwlen)
  102.     {    if(note)
  103.               printf("packing, ");     /* pack with repeat suppression */
  104.          hdrver = 3;                   /* note packing method */
  105.          hdr->size = ncrlen;           /* set data length */
  106.          fseek(t,tloc,0);              /* reset output for new method */
  107.          while((c=getc_ncr(f))!=EOF)
  108.               putc_pak(c,t);
  109.     }
  110.  
  111.     else
  112.     {    if(note)
  113.               printf("crunched, ");
  114.          hdrver = 8;
  115.          hdr->size = lzwlen;           /* size should not change */
  116.     }
  117.  
  118.     /* standard cleanups common to all methods */
  119.  
  120.     if(note)
  121.          printf("done.\n");
  122. }
  123.  
  124. /*  Non-repeat compression - text is passed through normally, except that
  125.     a run of more than two is encoded as:
  126.  
  127.          <char> <DLE> <count>
  128.  
  129.     Special case: a count of zero indicates that the DLE is really a DLE,
  130.     not a repeat marker.
  131. */
  132.  
  133. int getc_ncr(f)                        /* get bytes with collapsed runs */
  134. FILE *f;                               /* file to get from */
  135. {
  136.     static int lastc;                  /* value returned on last call */
  137.     static int repcnt;                 /* repetition counter */
  138.     static int c;                      /* latest value seen */
  139.  
  140.     switch(state)                      /* depends on our state */
  141.     {
  142.     case NOHIST:                       /* no relevant history */
  143.          state = SENTCHAR;
  144.          return lastc = getch(f);      /* remember the value next time */
  145.  
  146.     case SENTCHAR:                     /* char was sent. look ahead */
  147.          switch(lastc)                 /* action depends on char */
  148.          {
  149.          case DLE:                     /* if we sent a real DLE */
  150.               state = NOHIST;          /* then start over again */
  151.               return 0;                /* but note that the DLE was real */
  152.  
  153.          case EOF:                     /* EOF is always a special case */
  154.               return EOF;
  155.  
  156.          default:                      /* else test for a repeat */
  157.               for(repcnt=1; (c=getch(f))==lastc && repcnt<255; repcnt++)
  158.                    ;                   /* find end of run */
  159.  
  160.               switch(repcnt)           /* action depends on run size */
  161.               {
  162.               case 1:                  /* not a repeat */
  163.                    return lastc = c;   /* but remember value next time */
  164.  
  165.               case 2:                  /* a repeat, but too short */
  166.                    state = SENDNEWC;   /* send the second one next time */
  167.                    return lastc;
  168.  
  169.               default:                 /* a run - compress it */
  170.                    state = SENDCNT;    /* send repeat count next time */
  171.                    return DLE;         /* send repeat marker this time */
  172.               }
  173.          }
  174.  
  175.     case SENDNEWC:                     /* send second char of short run */
  176.          state = SENTCHAR;
  177.          return lastc = c;
  178.  
  179.     case SENDCNT:                      /* sent DLE, now send count */
  180.          state = SENDNEWC;
  181.          return repcnt;
  182.  
  183.     default:
  184.          abort("Bug - bad ncr state\n");
  185.     }
  186. }
  187.  
  188. static int getch(f)                    /* special get char for packing */
  189. FILE *f;                               /* file to get from */
  190. {
  191.     int c;                             /* a char from the file */
  192.  
  193.     if((c=fgetc(f))!=EOF)              /* if not the end of file */
  194.     {    crcval = addcrc(crcval,c);    /* then update CRC check value */
  195.          stdlen++;                     /* and bump length counter */
  196.     }
  197.  
  198.     return c;
  199. }
  200.  
  201. putc_pak(c,f)                          /* put a packed byte into archive */
  202. char c;                                /* byte to put */
  203. FILE *f;                               /* archive to put it in */
  204. {
  205.     putc_tst(code(c),f);               /* put encoded byte, with checks */
  206. }
  207.