home *** CD-ROM | disk | FTP | other *** search
- long __regargs memwrite(char *,long);
- void compexit(void);
- long compinit(void);
- long __regargs compfiles(unsigned char *,long,unsigned char *,long);
- long compress(void);
- void __regargs output(long);
- void cl_block(void);
- void cl_hash(long);
-
- #define BITS 12
-
- #if BITS == 16
- # define HSIZE 69001
- #endif
- #if BITS == 15
- # define HSIZE 35023
- #endif
- #if BITS == 14
- # define HSIZE 18013
- #endif
- #if BITS == 13
- # define HSIZE 9001
- #endif
- #if BITS <= 12
- # define HSIZE 5003
- #endif
-
- #define BLOCK_MASK 0x80
- #define INIT_BITS 9
- #define htabof(i) htab[i]
- #define codetabof(i) codetab[i]
- #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
- #define CHECK_GAP 10000
- #define FIRST 257
- #define CLEAR 256
-
- #define myfgetc() (reallyread++ >= watermark) ? EOF : *sect++
- #define absmin(a,b) ((a > b) ? b : a)
-
- long n_bits,maxcode,*htab,hsize,free_ent,clear_flg,ratio,checkpoint,offset,in_count,bytes_out,reallywritten,watermark,buffsize,reallyread;
-
- unsigned char *buffstart,*sect;
- unsigned short *codetab;
-
- char buf[BITS];
-
- const unsigned char lmask[9] = {0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00};
- const unsigned char rmask[9] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
-
- long __regargs
- memwrite(mem,size)
- register char *mem;
- register long size;
- {
- register long byteswritten = 0;
-
- while(size-- > 0)
- {
- if(reallywritten++ < buffsize)
- {
- *buffstart++ = *mem++;
- byteswritten++;
- }
- else
- return(byteswritten);
- }
-
- return(byteswritten);
- }
-
- void
- compexit()
- {
- if(htab)
- FreeMem(htab,HSIZE * sizeof(long));
-
- if(codetab)
- FreeMem(codetab,HSIZE * sizeof(unsigned short));
-
- htab = NULL;
- codetab = NULL;
- }
-
- long
- compinit()
- {
- if(!(htab = (long *)AllocMem(HSIZE * sizeof(long),0)))
- return(FALSE);
-
- if(!(codetab = (unsigned short *)AllocMem(HSIZE * sizeof(unsigned short),0)))
- {
- FreeMem(htab,HSIZE * sizeof(long));
-
- htab = NULL;
-
- return(FALSE);
- }
-
- return(TRUE);
- }
-
- void __regargs
- output(code)
- long code;
- {
- long r_off = offset, bits = n_bits;
- register char *bp = buf;
-
- if(code >= 0)
- {
- bp += (r_off >> 3);
- r_off &= 7;
-
- *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
- bp++;
-
- bits -= (8 - r_off);
- code >>= 8 - r_off;
-
- if(bits >= 8)
- {
- *bp++ = code;
- code >>= 8;
- bits -= 8;
- }
-
- if(bits)
- *bp = code;
-
- offset += n_bits;
-
- if(offset == (n_bits << 3))
- {
- bp = buf;
- bits = n_bits;
- bytes_out += bits;
-
- do
- {
- if(reallywritten++ < buffsize)
- *buffstart++ = *bp++;
- }
- while(--bits);
-
- offset = 0;
- }
-
- if(free_ent > maxcode || (clear_flg > 0))
- {
- if(offset > 0)
- {
- memwrite(buf,n_bits);
- bytes_out += n_bits;
- }
-
- offset = 0;
-
- if(clear_flg)
- {
- maxcode = MAXCODE(n_bits = INIT_BITS);
- clear_flg = 0;
- }
- else
- {
- n_bits++;
-
- if(n_bits == BITS)
- maxcode = (1 << BITS);
- else
- maxcode = MAXCODE(n_bits);
- }
- }
- }
- else
- {
- if(offset > 0)
- memwrite(buf,(offset + 7) / 8);
-
- bytes_out += (offset + 7) / 8;
- offset = 0;
- }
- }
-
- void
- cl_block()
- {
- register long rat;
-
- checkpoint = in_count + CHECK_GAP;
-
- if(in_count > 0x007FFFFF)
- {
- rat = bytes_out >> 8;
-
- if(rat == 0)
- rat = 0x7FFFFFFF;
- else
- rat = in_count /rat;
- }
- else
- rat = (in_count << 8) / bytes_out;
-
- if(rat > ratio)
- ratio = rat;
- else
- {
- ratio = 0;
-
- cl_hash((long)hsize);
-
- free_ent = FIRST;
- clear_flg = 1;
-
- output((long)CLEAR);
- }
- }
-
- void
- cl_hash(hashsize)
- long hashsize;
- {
- register long *htab_p = &htab[hashsize],i;
- register unsigned short j;
-
- i = hashsize - 16;
-
- do
- {
- for(j = 16 ; j > 0 ; j--)
- *(htab_p - j) = -1;
-
- htab_p -= 16;
- }
- while((i -= 16) >= 0);
-
- for(i += 16 ; i > 0 ; i--)
- *--htab_p = -1;
- }
-
- long __regargs
- compfiles(from,sectsize,to,maxsize)
- unsigned char *from,*to;
- long sectsize,maxsize;
- {
- sect = from;
- watermark = sectsize;
- buffstart = to;
- buffsize = maxsize;
- reallywritten = 0;
- reallyread = 0;
-
- hsize = HSIZE;
- free_ent = 0;
- clear_flg = 0;
- ratio = 0;
- checkpoint = CHECK_GAP;
- in_count = 1;
-
- if(sectsize < (1 << 12))
- hsize = absmin(5003, HSIZE);
- else if(sectsize < (1 << 13))
- hsize = absmin(9001, HSIZE);
- else if(sectsize < (1 << 14))
- hsize = absmin(18013, HSIZE);
- else if(sectsize < (1 << 15))
- hsize = absmin(35023, HSIZE);
- else if(sectsize < 47000)
- hsize = absmin(50021, HSIZE);
-
- compress();
-
- return(reallywritten);
- }
-
- long
- compress()
- {
- long fcode,i = 0,c,ent,disp,hsize_reg,hshift = 0;
-
- offset = 0;
- bytes_out = 3;
- clear_flg = 0;
- ratio = 0;
- in_count = 1;
-
- checkpoint = CHECK_GAP;
- maxcode = MAXCODE(n_bits = INIT_BITS);
-
- free_ent = ((BLOCK_MASK) ? FIRST : 256);
-
- ent = myfgetc();
-
- for(fcode = (long)hsize ; fcode < 65536L ; fcode *= 2L)
- hshift++;
-
- hshift = 8 - hshift;
- hsize_reg = hsize;
-
- cl_hash((long)hsize_reg);
-
- while((c = myfgetc()) != EOF)
- {
- in_count++;
-
- fcode = (long)(((long) c << BITS) + ent);
-
- i = ((c << hshift) ^ ent);
-
- if(htabof(i) == fcode)
- {
- ent = codetabof(i);
- continue;
- }
- else
- if((long)htabof(i) < 0)
- goto nomatch;
-
- disp = hsize_reg - i;
-
- if(i == 0)
- disp = 1;
-
- probe: if((i -= disp) < 0)
- i += hsize_reg;
-
- if(htabof(i) == fcode)
- {
- ent = codetabof(i);
- continue;
- }
-
- if((long)htabof(i) > 0)
- goto probe;
-
- nomatch: output((long)ent);
-
- ent = c;
-
- if(free_ent < (1 << BITS))
- {
- codetabof(i) = free_ent++;
- htabof(i) = fcode;
- }
- else
- if((long)in_count >= checkpoint && BLOCK_MASK)
- cl_block();
- }
-
- output((long)ent);
- output((long)-1);
-
- return(bytes_out);
- }
-