home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume1 / 8707 / 66 / arcpack.c < prev    next >
C/C++ Source or Header  |  1990-07-13  |  11KB  |  294 lines

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