home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / unix / arcunx11 / arc.sh2 / arcpack.c < prev   
Encoding:
C/C++ Source or Header  |  1987-04-01  |  9.0 KB  |  257 lines

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