[comp.binaries.ibm.pc] Patches to ARC-BSD

boneill@hawk.ulowell.edu (SoftXc Coordinator) (04/03/88)

Here are the appropriate patches to make the ARC-BSD program
squash-compatible. These patches only apply to the BSD version, not the SYS
V version. Save this posting, delete all lines up to and including "CUT
HERE", and feed the file to sh. It will unpack two files: arcpatch and
squash.c. Feed arcpatch to 'patch' via 'patch <arcpatch', and then
recompile.

============================================================================
Brian O'Neill, MS-DOS Software Exchange Coordinator
ArpaNet: boneill@hawk.ulowell.edu 
UUCP   : {(backbones),harvard,rutgers,et. al.}!ulowell!hawk!boneill

-----CUT HERE-----
# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	./arcpatch
#	./squash.c
#
if `test ! -s ./arcpatch`
then
echo "writing ./arcpatch"
cat > ./arcpatch << '\Rogue\Monster\'
Only in oldarc: BugsEtc
diff -c oldarc/Makefile newarc/Makefile
*** oldarc/Makefile	Sat Apr  2 15:44:36 1988
--- newarc/Makefile	Sat Apr  2 15:47:05 1988
***************
*** 6,17 ****
  
  OBJS = arc.o arcadd.o arccode.o arccvt.o arcdel.o arcdir.o \
  arcdos.o arcext.o arcio.o arclst.o arclzw.o arcmatch.o arcpack.o arcrun.o \
! arcsq.o arcsvc.o arctst.o arcunp.o arcusq.o arcvax.o arcmisc.o
  
  
  SRCS = arc.c arcadd.c arccode.c arccvt.c arcdel.c arcdir.c \
  arcdos.c arcext.c arcio.c arclst.c arclzw.c arcmatch.c arcpack.c arcrun.c \
! arcs.c arcsq.c arcsvc.c arctst.c arcunp.c arcusq.c arcvax.c arcmisc.c
  
  arc:		${OBJS}
  	cc  -O -o arc ${OBJS}
--- 6,17 ----
  
  OBJS = arc.o arcadd.o arccode.o arccvt.o arcdel.o arcdir.o \
  arcdos.o arcext.o arcio.o arclst.o arclzw.o arcmatch.o arcpack.o arcrun.o \
! arcsq.o arcsvc.o arctst.o arcunp.o arcusq.o arcvax.o arcmisc.o squash.o
  
  
  SRCS = arc.c arcadd.c arccode.c arccvt.c arcdel.c arcdir.c \
  arcdos.c arcext.c arcio.c arclst.c arclzw.c arcmatch.c arcpack.c arcrun.c \
! arcs.c arcsq.c arcsvc.c arctst.c arcunp.c arcusq.c arcvax.c arcmisc.c squash.c
  
  arc:		${OBJS}
  	cc  -O -o arc ${OBJS}
***************
*** 59,63 ****
--- 59,65 ----
  	cc -O -c arcusq.c
  arcvax.o:	arc.h
  	cc -O -c arcvax.c
+ squash.o:	arc.h
+ 	cc -O -c squash.c
  arc.h:		arcm.h arcs.h
  	touch arc.h
diff -c oldarc/arc.c newarc/arc.c
*** oldarc/arc.c	Sat Apr  2 15:44:42 1988
--- newarc/arc.c	Sat Apr  2 15:47:08 1988
***************
*** 53,58 ****
--- 53,59 ----
           6 = Lempel-Zev packing of repeated strings (new style)
           7 = Lempel-Zev Williams packing with improved has function
           8 = Dynamic Lempel-Zev packing with adaptive reset
+ 	 9 = Squashing
  
           Type 5, Lempel-Zev packing, was added as of version 4.0
  
***************
*** 145,151 ****
           printf("         s   = suppress compression (store only)\n");
           printf("         w   = suppress warning messages\n");
           printf("         n   = suppress notes and comments\n");
!          printf("         g   = Encrypt/decrypt archive entry\n\n");
  /*       printf("\nPlease refer to the program documentation for");          */
  /*       printf(" complete instructions.\n");                                */
           return 1;
--- 146,153 ----
           printf("         s   = suppress compression (store only)\n");
           printf("         w   = suppress warning messages\n");
           printf("         n   = suppress notes and comments\n");
!          printf("         g   = Encrypt/decrypt archive entry\n");
!          printf("         q   = squash instead of crunching\n\n");
  /*       printf("\nPlease refer to the program documentation for");          */
  /*       printf(" complete instructions.\n");                                */
           return 1;
***************
*** 214,219 ****
--- 216,224 ----
  
           else if(*a=='K')              /* special kludge */
                kludge = 1;
+ 
+ 	 else if(*a=='Q')
+ 	      dosquash = 1;
  
           else if(*a=='-' || *a=='/')   /* UNIX and PC-DOS option markers */
                ;
diff -c oldarc/arc.h newarc/arc.h
*** oldarc/arc.h	Sat Apr  2 15:44:44 1988
--- newarc/arc.h	Sat Apr  2 15:47:10 1988
***************
*** 82,84 ****
--- 82,85 ----
  EXTERN char newname[STRLEN];           /* storage for new archive name */
  EXTERN unsigned INT arcdate;    /* archive date stamp */
  EXTERN unsigned INT arctime;    /* archive time stamp */
+ EXTERN int dosquash;
diff -c oldarc/arclst.c newarc/arclst.c
*** oldarc/arclst.c	Sat Apr  2 15:45:02 1988
--- newarc/arclst.c	Sat Apr  2 15:47:31 1988
***************
*** 175,180 ****
--- 175,183 ----
           case 8:
                printf("Crunched");
                break;
+ 	 case 9:
+ 	      printf("Squashed");
+ 	      break;
           default:
                printf("Unknown!");
           }
diff -c oldarc/arclzw.c newarc/arclzw.c
*** oldarc/arclzw.c	Sat Apr  2 15:45:06 1988
--- newarc/arclzw.c	Sat Apr  2 15:47:38 1988
***************
*** 106,112 ****
   * in parallel.
   */
  
! #if MSODS
  static long *htab = string_tab;        /* hash code table   (crunch) */
  #endif
  #if BSD | ST
--- 106,112 ----
   * in parallel.
   */
  
! #if MSDOS
  static long *htab = string_tab;        /* hash code table   (crunch) */
  #endif
  #if BSD | ST
***************
*** 562,568 ****
  {
      long local;                        /* local hash value */
  
!     local = (pred + foll) | 0x0800;    /* create the hash key */
      local *= local;                    /* square it */
      return (local >> 6) & 0x0FFF;      /* return the middle 12 bits */
  }
--- 562,569 ----
  {
      long local;                        /* local hash value */
  
!     local = ((pred + foll) | 0x0800) & 0xffff;    /* create the hash key */
!     /*local = (pred + foll) | 0x0800;    /* create the hash key */
      local *= local;                    /* square it */
      return (local >> 6) & 0x0FFF;      /* return the middle 12 bits */
  }
***************
*** 571,577 ****
  unsigned INT pred;                     /* code for preceeding string */
  unsigned char foll;                    /* value of following char */
  {
!     return ((pred+foll)*15073)&0xFFF;  /* faster hash */
  }
  
  /*  The eolist() function is used to trace down a list of entries with
--- 572,579 ----
  unsigned INT pred;                     /* code for preceeding string */
  unsigned char foll;                    /* value of following char */
  {
!     return (((pred+foll)&0xffff)*15073)&0xFFF;  /* faster hash */
!     /*return ((pred+foll)*15073)&0xFFF;  /* faster hash */
  }
  
  /*  The eolist() function is used to trace down a list of entries with
diff -c oldarc/arcm.h newarc/arcm.h
*** oldarc/arcm.h	Sat Apr  2 15:45:08 1988
--- newarc/arcm.h	Sat Apr  2 15:49:49 1988
***************
*** 22,28 ****
   */
  
  #define ARCMARK 26 /*                   special archive marker        */
! #define ARCVER 8   /*                   archive header version code   */
  #define STRLEN 100 /*                   system standard string length */
  #define FNLEN 13   /*                   file name length              */
  #define MAXARG 25  /*                   maximum number of arguments   */
--- 22,28 ----
   */
  
  #define ARCMARK 26 /*                   special archive marker        */
! #define ARCVER 9   /*                   archive header version code   */
  #define STRLEN 100 /*                   system standard string length */
  #define FNLEN 13   /*                   file name length              */
  #define MAXARG 25  /*                   maximum number of arguments   */
diff -c oldarc/arcpack.c newarc/arcpack.c
*** oldarc/arcpack.c	Sat Apr  2 15:45:16 1988
--- newarc/arcpack.c	Sat Apr  2 15:47:46 1988
***************
*** 66,72 ****
      long huflen;                       /* length after squeezing */
      long lzwlen;                       /* length after crunching */
      long pred_sq(), file_sq();         /* stuff for squeezing */
!     long pred_cm();                    /* dynamic crunching cleanup */
      char tnam[STRLEN];                /* temporary name buffer */
      char *makefnam();                  /* filename fixer upper */
      FILE *crn = NULL;                  /* temporary crunch file */
--- 66,72 ----
      long huflen;                       /* length after squeezing */
      long lzwlen;                       /* length after crunching */
      long pred_sq(), file_sq();         /* stuff for squeezing */
!     long pred_cm(), sqpred_cm();       /* dynamic crunching cleanup */
      char tnam[STRLEN];                /* temporary name buffer */
      char *makefnam();                  /* filename fixer upper */
      FILE *crn = NULL;                  /* temporary crunch file */
***************
*** 94,102 ****
--- 94,112 ----
           crcval = 0;                   /* initialize CRC check value */
           setcode();                    /* initialize encryption */
  
+ 	 if(dosquash)
+          sqinit_cm(f,crn);
+ 	 else
           init_cm(f,crn);               /* initialize for crunching */
           init_sq();                    /* initialize for squeeze scan */
  
+ 	 if(dosquash)
+          while((c=getch(f))!=EOF)   /* for each byte of file */
+          {    ncrlen++;                /* one more packed byte */
+               scan_sq(c);              /* see what squeezing can do */
+               sqputc_cm(c,crn);          /* see what crunching can do */
+          }
+          else
           while((c=getc_ncr(f))!=EOF)   /* for each byte of file */
           {    ncrlen++;                /* one more packed byte */
                scan_sq(c);              /* see what squeezing can do */
***************
*** 103,108 ****
--- 113,121 ----
                putc_cm(c,crn);          /* see what crunching can do */
           }
           huflen = pred_sq();           /* finish up after squeezing */
+ 	 if(dosquash)
+          lzwlen = sqpred_cm(crn);
+ 	 else
           lzwlen = pred_cm(crn);        /* finish up after crunching */
      }
      else                               /* else kludge the method */
***************
*** 158,165 ****
      {    if(kludge)                    /*DEBUG*/
                printf("(%ld) ",huflen-lzwlen);
           if(note)
!             { printf("crunching, "); fflush(stdout);}
!          hdrver = 8;
           hdr->size = lzwlen;           /* size should not change */
           if(crn)                       /* if temp was created */
           {    fseek(crn,0L,0);         /* then copy over crunched temp */
--- 171,178 ----
      {    if(kludge)                    /*DEBUG*/
                printf("(%ld) ",huflen-lzwlen);
           if(note)
!             { printf(dosquash ? "squashing, " : "crunching, "); fflush(stdout);}
!          hdrver = dosquash ? 9 : 8;
           hdr->size = lzwlen;           /* size should not change */
           if(crn)                       /* if temp was created */
           {    fseek(crn,0L,0);         /* then copy over crunched temp */
***************
*** 167,176 ****
                     putc_tst(c,t);
           }
           else                          /* else re-crunch */
!          {    init_cm(f,t);
                while((c=getc_ncr(f))!=EOF)
!                    putc_cm(c,t);
!               pred_cm(t);              /* finish up after crunching */
           }
      }
  
--- 180,199 ----
                     putc_tst(c,t);
           }
           else                          /* else re-crunch */
!          {    if(dosquash)
! 		sqinit_cm(f, t);
! 	      else
! 		init_cm(f,t);
! 	   if(dosquash)
                while((c=getc_ncr(f))!=EOF)
! 			putc_cm(c,t);
! 	   else
!               while((c=getch(f))!=EOF)
! 			sqputc_cm(c,t);
! 	      if(dosquash)
! 		sqpred_cm(t);
! 	      else
! 		pred_cm(t);              /* finish up after crunching */
           }
      }
  
diff -c oldarc/arcunp.c newarc/arcunp.c
*** oldarc/arcunp.c	Sat Apr  2 15:45:35 1988
--- newarc/arcunp.c	Sat Apr  2 15:49:59 1988
***************
*** 112,117 ****
--- 112,121 ----
           decomp(f,t);
           break;
  
+     case 9:
+ 	 sqdecomp(f,t);
+ 	 break;
+ 
      default:                           /* unknown method */
           if(warn)
           {    printf("I don't know how to unpack file %s\n",hdr->name);
***************
*** 139,145 ****
      CRC check value.
  */
  
! static INT putc_unp(c,t)                   /* output an unpacked byte */
  char c;                                /* byte to output */
  FILE *t;                               /* file to output to */
  {
--- 143,149 ----
      CRC check value.
  */
  
! INT putc_unp(c,t)                   /* output an unpacked byte */
  char c;                                /* byte to output */
  FILE *t;                               /* file to output to */
  {
\Rogue\Monster\
else
  echo "will not over write ./arcpatch"
fi
if `test ! -s ./squash.c`
then
echo "writing ./squash.c"
cat > ./squash.c << '\Rogue\Monster\'
/*  ARC - Archive utility - SQUASH

(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED

	This is a quick hack to ARCLZW to make it handle squashed archives.
	Dan Lanciani (ddl@harvard.*) July 87

*/
#include <stdio.h>
#include "arc.h"

/* definitions for the new dynamic Lempel-Zev crunching */

#define BITS   13                      /* maximum bits per code */
#define HSIZE  10007                    /* 80% occupancy */
#define INIT_BITS 9                    /* initial number of bits/code */

static INT n_bits;                     /* number of bits/code */
static INT maxcode;                    /* maximum code, given n_bits */
#define MAXCODE(n)      ((1<<(n)) - 1) /* maximum code calculation */
static INT maxcodemax =  1 << BITS;    /* largest possible code (+1) */

static unsigned char buf[BITS];        /* input/output buffer */

static unsigned char lmask[9] =        /* left side masks */
{   0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
static unsigned char rmask[9] =        /* right side masks */
{   0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

static INT offset;                     /* byte offset for code output */
static long in_count;                  /* length of input */
static long bytes_out;                 /* length of compressed output */
static unsigned INT ent;

static long htab[HSIZE];               /* hash code table   (crunch) */
static unsigned INT codetab[HSIZE];    /* string code table (crunch) */

static unsigned INT *prefix = codetab; /* prefix code table (uncrunch) */

static unsigned char suffix[HSIZE];    /* suffix table (uncrunch) */
static INT free_ent;                   /* first unused entry */
static INT firstcmp;                   /* true at start of compression */
static unsigned char stack[HSIZE];     /* local push/pop stack */

/*
 * block compression parameters -- after all codes are used up,
 * and compression rate changes, start over.
 */

static INT clear_flg;
static long ratio;
#define CHECK_GAP 10000                /* ratio check interval */
static long checkpoint;

/*
 * the next two codes should not be changed lightly, as they must not
 * lie within the contiguous general code space.
 */
#define FIRST   257                    /* first free entry */
#define CLEAR   256                    /* table clear output code */

static INT cl_block(t)                     /* table clear for block compress */
FILE *t;                               /* our output file */
{
    long rat;
    INT putcode();

    checkpoint = in_count + CHECK_GAP;

    if(in_count > 0x007fffff)          /* shift will overflow */
    {    rat = bytes_out >> 8;
         if(rat == 0)                  /* Don't divide by zero */
              rat = 0x7fffffff;
         else rat = in_count / rat;
    }
    else rat = (in_count<<8)/bytes_out;/* 8 fractional bits */

    if(rat > ratio)
         ratio = rat;
    else
    {    ratio = 0;
         setmem	(htab,HSIZE*sizeof(long),0xff);
         free_ent = FIRST;
         clear_flg = 1;
         putcode(CLEAR,t);
    }
}

/*****************************************************************
 *
 * Output a given code.
 * Inputs:
 *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
 *              that n_bits =< (long)wordsize - 1.
 * Outputs:
 *      Outputs code to the file.
 * Assumptions:
 *      Chars are 8 bits long.
 * Algorithm:
 *      Maintain a BITS character long buffer (so that 8 codes will
 * fit in it exactly).  When the buffer fills up empty it and start over.
 */

static INT putcode(code,t)                 /* output a code */
INT code;                              /* code to output */
FILE *t;                               /* where to put it */
{
 INT r_off = offset;                /* right offset */
 INT bits = n_bits;                 /* bits to go */
 unsigned char *bp = buf;           /* buffer pointer */
 INT n;                             /* index */

    if(code >= 0)                      /* if a real code */
    {    /*
          * Get to the first byte.
          */
         bp += (r_off >> 3);
         r_off &= 7;

         /*
          * Since code is always >= 8 bits, only need to mask the first
          * hunk on the left.
          */
         *bp = (*bp&rmask[r_off]) | (code<<r_off) & lmask[r_off];
         bp++;
         bits -= (8 - r_off);
         code >>= (8 - r_off);

         /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
         if(bits >= 8)
         {    *bp++ = code;
              code >>= 8;
              bits -= 8;
         }

         /* Last bits. */
         if(bits)
              *bp = code;

         offset += n_bits;

         if(offset == (n_bits << 3))
         {    bp = buf;
              bits = n_bits;
              bytes_out += bits;
              do
                   putc_pak(*bp++,t);
              while(--bits);
              offset = 0;
         }

         /*
          * If the next entry is going to be too big for the code size,
          * then increase it, if possible.
          */
         if(free_ent>maxcode || clear_flg>0)
         {    /*
               * Write the whole buffer, because the input side won't
               * discover the size increase until after it has read it.
               */
              if(offset > 0)
              {    bp = buf;           /* reset pointer for writing */
                   bytes_out += n = n_bits;
                   while(n--)
                        putc_pak(*bp++,t);
              }
              offset = 0;

              if(clear_flg)            /* reset if clearing */
              {    maxcode = MAXCODE(n_bits = INIT_BITS);
                   clear_flg = 0;
              }
              else                     /* else use more bits */
              {    n_bits++;
                   if(n_bits == BITS)
                        maxcode = maxcodemax;
                   else
                        maxcode = MAXCODE(n_bits);
              }
         }
    }

    else                               /* dump the buffer on EOF */
    {    bytes_out += n = (offset+7) / 8;

         if(offset > 0)
              while(n--)
                   putc_pak(*bp++,t);
         offset = 0;
    }
}

/*****************************************************************
 *
 * Read one code from the standard input.  If EOF, return -1.
 * Inputs:
 *      cmpin
 * Outputs:
 *      code or -1 is returned.
 */

static INT getcode(f)                  /* get a code */
FILE *f;                               /* file to get from */
{
 INT code;
    static INT offset = 0, size = 0;
 INT r_off, bits;
    unsigned char *bp = buf;

    if(clear_flg > 0 || offset >= size || free_ent > maxcode)
    {    /*
          * If the next entry will be too big for the current code
          * size, then we must increase the size.  This implies reading
          * a new buffer full, too.
          */
         if(free_ent > maxcode)
         {    n_bits++;
              if(n_bits == BITS)
                   maxcode = maxcodemax;    /* won't get any bigger now */
              else maxcode = MAXCODE(n_bits);
         }
         if(clear_flg > 0)
         {    maxcode = MAXCODE(n_bits = INIT_BITS);
              clear_flg = 0;
         }

         for(size=0; size<n_bits; size++)
         {    if((code=getc_unp(f))==EOF)
                   break;
              else buf[size] = code;
         }
         if(size <= 0)
              return -1;               /* end of file */

         offset = 0;
         /* Round size down to integral number of codes */
         size = (size << 3)-(n_bits - 1);
    }
    r_off = offset;
    bits = n_bits;

    /*
     * Get to the first byte.
     */
    bp +=(r_off >> 3);
    r_off &= 7;

    /* Get first part (low order bits) */
    code = (*bp++ >> r_off);
    bits -= 8 - r_off;
    r_off = 8 - r_off;                 /* now, offset into code word */

    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
    if(bits >= 8)
    {    code |= *bp++ << r_off;
         r_off += 8;
         bits -= 8;
    }
    /* high order bits. */
    code |= (*bp & rmask[bits]) << r_off;
    offset += n_bits;

    return code;
}

/*
 * compress a file
 *
 * Algorithm:  use open addressing double hashing (no chaining) on the
 * prefix code / next character combination.  We do a variant of Knuth's
 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 * secondary probe.  Here, the modular division first probe is gives way
 * to a faster exclusive-or manipulation.  Also do block compression with
 * an adaptive reset, where the code table is cleared when the compression
 * ratio decreases, but after the table fills.  The variable-length output
 * codes are re-sized at this point, and a special CLEAR code is generated
 * for the decompressor.
 */

INT sqinit_cm(f,t)                           /* initialize for compression */
FILE *f;                               /* file we will be compressing */
FILE *t;                               /* where we will put it */
{
    offset = 0;
    bytes_out = 0;
    clear_flg = 0;
    ratio = 0;
    in_count = 1;
    checkpoint = CHECK_GAP;
    maxcode = MAXCODE(n_bits = INIT_BITS);
    free_ent = FIRST;
    setmem(htab,HSIZE*sizeof(long),0xff);
    n_bits = INIT_BITS;                /* set starting code size */

    firstcmp = 1;                      /* next byte will be first */
}

INT sqputc_cm(c,t)                           /* compress a character */
unsigned char c;                       /* character to compress */
FILE *t;                               /* where to put it */
{
    static long fcode;
    static INT hshift;
 INT i;
 INT disp;

    if(firstcmp)                       /* special case for first byte */
    {    ent = c;                      /* remember first byte */

         hshift = 0;
         for(fcode=(long)HSIZE;  fcode<65536L; fcode*=2L)
              hshift++;
         hshift = 8 - hshift;          /* set hash code range bund */

         firstcmp = 0;                 /* no longer first */
         return;
    }

    in_count++;
    fcode =(long)(((long)c << BITS)+ent);
    i = (c<<hshift)^ent;               /* xor hashing */

    if(htab[i]==fcode)
    {    ent = codetab[i];
         return;
    }
    else if(htab[i]<0)                 /* empty slot */
         goto nomatch;
    disp = HSIZE - i;                  /* secondary hash (after G.Knott) */
    if(i == 0)
         disp = 1;

probe:
    if((i -= disp) < 0)
         i += HSIZE;

    if(htab[i] == fcode)
    {    ent = codetab[i];
         return;
    }
    if(htab[i] > 0)
         goto probe;

nomatch:
    putcode(ent,t);
    ent = c;
    if(free_ent < maxcodemax)
    {    codetab[i] = free_ent++;      /* code -> hashtable */
         htab[i] = fcode;
    }
    else if((long)in_count >= checkpoint)
         cl_block(t);
}

long sqpred_cm(t)                        /* finish compressing a file */
FILE *t;                               /* where to put it */
{
    putcode(ent,t);                    /* put out the final code */
    putcode(-1,t);                     /* tell output we are done */

    return bytes_out;                  /* say how big it got */
}

/*
 * Decompress a file.  This routine adapts to the codes in the file
 * building the string table on-the-fly; requiring no table to be stored
 * in the compressed file.  The tables used herein are shared with those of
 * the compress() routine.  See the definitions above.
 */

INT sqdecomp(f,t)                            /* decompress a file */
FILE *f;                               /* file to read codes from */
FILE *t;                               /* file to write text to */
{
    unsigned char *stackp;
 INT finchar;
 INT code, oldcode, incode;

    n_bits = INIT_BITS;                /* set starting code size */
    clear_flg = 0;

    /*
     * As above, initialize the first 256 entries in the table.
     */
    maxcode = MAXCODE(n_bits=INIT_BITS);
    for(code = 255; code >= 0; code--)
    {    prefix[code] = 0;
         suffix[code] = (unsigned char)code;
    }
    free_ent = FIRST;

    finchar = oldcode = getcode(f);
    if(oldcode == -1)                  /* EOF already? */
         return;                       /* Get out of here */
    putc_unp((char)finchar,t);         /* first code must be 8 bits=char */
    stackp = stack;

    while((code = getcode(f))> -1)
    {    if(code==CLEAR)
         {    for(code = 255; code >= 0; code--)
                   prefix[code] = 0;
              clear_flg = 1;
              free_ent = FIRST - 1;
              if((code=getcode(f))==-1)/* O, untimely death! */
                   break;
         }
         incode = code;
         /*
          * Special case for KwKwK string.
          */
         if(code >= free_ent)
         {    *stackp++ = finchar;
              code = oldcode;
         }

         /*
          * Generate output characters in reverse order
          */
         while(code >= 256)
         {    *stackp++ = suffix[code];
              code = prefix[code];
         }
         *stackp++ = finchar = suffix[code];

         /*
          * And put them out in forward order
          */
         do
              putc_unp(*--stackp,t);
         while(stackp > stack);

         /*
          * Generate the new entry.
          */
         if((code=free_ent) < maxcodemax)
         {    prefix[code] = (unsigned short)oldcode;
              suffix[code] = finchar;
              free_ent = code+1;
         }
         /*
          * Remember previous code.
          */
         oldcode = incode;
    }
}
\Rogue\Monster\
else
  echo "will not over write ./squash.c"
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit

afc@i.cc.purdue.edu (Greg Flint) (04/05/88)

Sorry for the non-binary posting to comp.binaries.ibm.pc, but that is where
the original article appeared.

I believe that an if-test is reversed in arcpack.c.  This is the result of a
visual inspection of the patch file.  I have not attempted any validation of
the new ARC-BSD for compression, but I have used it to successfully uncompress
PKARC-ed, squashed files that have been posted to the net.

In article <5937@swan.ulowell.edu> boneill@hawk.ulowell.edu (SoftXc Coordinator) writes:
>Here are the appropriate patches to make the ARC-BSD program
>squash-compatible. These patches only apply to the BSD version, not the SYS

   <some original lines deleted>

>diff -c oldarc/arcpack.c newarc/arcpack.c
>*** oldarc/arcpack.c	Sat Apr  2 15:45:16 1988
>--- newarc/arcpack.c	Sat Apr  2 15:47:46 1988
>***************

   <some original lines deleted>

>--- 180,199 ----
>                     putc_tst(c,t);
>           }
>           else                          /* else re-crunch */
>!          {    if(dosquash)
>! 		sqinit_cm(f, t);
>! 	      else
>! 		init_cm(f,t);
>! 	   if(dosquash)

The if-test in the above line should be altered as follows (reverse if test):
>! 	   if(!dosquash)

   <remaining original lines deleted>

-------------------------------------------------------------------------------
Greg Flint 	  Math G-185	    (317) 494-1787  UUCP:  j.cc.purdue.edu!gdf
  Purdue Univ.	  Purdue University		    ARPA:  gdf@j.cc.purdue.edu
  Computing Ctr.  West Lafayette, IN 47907	  BITNET:  flint@purccvm.bitnet

boneill@hawk.ulowell.edu (SoftXc Coordinator) (04/14/88)

Someone just recently sent me mail about the patches I posted, since he had
a problem with the context diff format, and I said I would send him a normal
diff file. Unfortunately, the mailer croaked again and I lost his request
with the address. If this person would please e-mail me again, I'll send you
the diff file ASAP.

============================================================================
Brian O'Neill, MS-DOS Software Exchange Coordinator
ArpaNet: boneill@hawk.ulowell.edu 
UUCP   : {(backbones),harvard,rutgers,et. al.}!ulowell!hawk!boneill