home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c019 / 1.ddi / ARC521_C / ARCPACK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-01  |  7.2 KB  |  275 lines

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