/* unlzh.c -- decompress files in SCO compress -H (LZH) format.
* The code in this file is directly derived from the public domain 'ar002'
* written by Haruhiko Okumura.
static char rcsid
[] = "$Id: unlzh.c,v 1.2 1993/06/24 10:59:01 jloup Exp $";
#include "lzw.h" /* just for consistency checking */
local
unsigned decode
OF((unsigned count
, uch buffer
[]));
local
void decode_start
OF((void));
local
void huf_decode_start
OF((void));
local
unsigned decode_c
OF((void));
local
unsigned decode_p
OF((void));
local
void read_pt_len
OF((int nn
, int nbit
, int i_special
));
local
void read_c_len
OF((void));
local
void fillbuf
OF((int n
));
local
unsigned getbits
OF((int n
));
local
void init_getbits
OF((void));
local
void make_table
OF((int nchar
, uch bitlen
[],
int tablebits
, ush table
[]));
#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
#define DICSIZ ((unsigned) 1 << DICBIT)
#define BITBUFSIZ (CHAR_BIT * 2 * sizeof(char))
/* Do not use CHAR_BIT * sizeof(bitbuf), does not work on machines
* for which short is not on 16 bits (Cray).
/* encode.c and decode.c */
#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */
#define THRESHOLD 3 /* choose optimal value */
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
/* alphabet = {0, 1, 2, ..., NC - 1} */
#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
#define CODE_BIT 16 /* codeword length */
#define NT (CODE_BIT + 3)
#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
/* local ush left[2 * NC - 1]; */
/* local ush right[2 * NC - 1]; */
error cannot overlay left
+right
and prev
/* local uch c_len[NC]; */
error cannot overlay c_len
and outbuf
local
unsigned blocksize
;
/* local ush c_table[4096]; */
#if (DIST_BUFSIZE-1) < 4095
error cannot overlay c_table
and d_buf
/***********************************************************
***********************************************************/
local
unsigned subbitbuf
;
local
void fillbuf(n
) /* Shift bitbuf n bits left, read n bits */
bitbuf
|= subbitbuf
<< (n
-= bitcount
);
subbitbuf
= (unsigned)try_byte();
if ((int)subbitbuf
== EOF
) subbitbuf
= 0;
bitbuf
|= subbitbuf
>> (bitcount
-= n
);
local
unsigned getbits(n
)
x
= bitbuf
>> (BITBUFSIZ
- n
); fillbuf(n
);
local
void init_getbits()
bitbuf
= 0; subbitbuf
= 0; bitcount
= 0;
/***********************************************************
maketbl.c -- make table for decoding
***********************************************************/
local
void make_table(nchar
, bitlen
, tablebits
, table
)
ush count
[17], weight
[17], start
[18], *p
;
unsigned i
, k
, len
, ch
, jutbits
, avail
, nextcode
, mask
;
for (i
= 1; i
<= 16; i
++) count
[i
] = 0;
for (i
= 0; i
< (unsigned)nchar
; i
++) count
[bitlen
[i
]]++;
for (i
= 1; i
<= 16; i
++)
start
[i
+ 1] = start
[i
] + (count
[i
] << (16 - i
));
if ((start
[17] & 0xffff) != 0)
jutbits
= 16 - tablebits
;
for (i
= 1; i
<= (unsigned)tablebits
; i
++) {
weight
[i
] = (unsigned) 1 << (tablebits
- i
);
weight
[i
] = (unsigned) 1 << (16 - i
);
i
= start
[tablebits
+ 1] >> jutbits
;
while (i
!= k
) table
[i
++] = 0;
mask
= (unsigned) 1 << (15 - tablebits
);
for (ch
= 0; ch
< (unsigned)nchar
; ch
++) {
if ((len
= bitlen
[ch
]) == 0) continue;
nextcode
= start
[len
] + weight
[len
];
if (len
<= (unsigned)tablebits
) {
for (i
= start
[len
]; i
< nextcode
; i
++) table
[i
] = ch
;
p
= &table
[k
>> jutbits
];
right
[avail
] = left
[avail
] = 0;
if (k
& mask
) p
= &right
[*p
];
/***********************************************************
***********************************************************/
local
void read_pt_len(nn
, nbit
, i_special
)
for (i
= 0; i
< nn
; i
++) pt_len
[i
] = 0;
for (i
= 0; i
< 256; i
++) pt_table
[i
] = c
;
c
= bitbuf
>> (BITBUFSIZ
- 3);
mask
= (unsigned) 1 << (BITBUFSIZ
- 1 - 3);
while (mask
& bitbuf
) { mask
>>= 1; c
++; }
fillbuf((c
< 7) ? 3 : c
- 3);
while (--c
>= 0) pt_len
[i
++] = 0;
while (i
< nn
) pt_len
[i
++] = 0;
make_table(nn
, pt_len
, 8, pt_table
);
for (i
= 0; i
< NC
; i
++) c_len
[i
] = 0;
for (i
= 0; i
< 4096; i
++) c_table
[i
] = c
;
c
= pt_table
[bitbuf
>> (BITBUFSIZ
- 8)];
mask
= (unsigned) 1 << (BITBUFSIZ
- 1 - 8);
if (bitbuf
& mask
) c
= right
[c
];
fillbuf((int) pt_len
[c
]);
else if (c
== 1) c
= getbits(4) + 3;
else c
= getbits(CBIT
) + 20;
while (--c
>= 0) c_len
[i
++] = 0;
} else c_len
[i
++] = c
- 2;
while (i
< NC
) c_len
[i
++] = 0;
make_table(NC
, c_len
, 12, c_table
);
local
unsigned decode_c()
return NC
; /* end of file */
read_pt_len(NT
, TBIT
, 3);
read_pt_len(NP
, PBIT
, -1);
j
= c_table
[bitbuf
>> (BITBUFSIZ
- 12)];
mask
= (unsigned) 1 << (BITBUFSIZ
- 1 - 12);
if (bitbuf
& mask
) j
= right
[j
];
local
unsigned decode_p()
j
= pt_table
[bitbuf
>> (BITBUFSIZ
- 8)];
mask
= (unsigned) 1 << (BITBUFSIZ
- 1 - 8);
if (bitbuf
& mask
) j
= right
[j
];
fillbuf((int) pt_len
[j
]);
if (j
!= 0) j
= ((unsigned) 1 << (j
- 1)) + getbits((int) (j
- 1));
local
void huf_decode_start()
init_getbits(); blocksize
= 0;
/***********************************************************
***********************************************************/
local
int j
; /* remaining bytes to copy */
local
int done
; /* set at end of input */
local
void decode_start()
/* Decode the input and return the number of decoded bytes put in buffer
local
unsigned decode(count
, buffer
)
/* The calling function must keep the number of
bytes to be processed. This function decodes
either 'count' bytes or 'DICSIZ' bytes, whichever
is smaller, into the array 'buffer[]' of size
Call decode_start() once for each new file
before calling this function.
i
= (i
+ 1) & (DICSIZ
- 1);
if (++r
== count
) return r
;
if (++r
== count
) return r
;
j
= c
- (UCHAR_MAX
+ 1 - THRESHOLD
);
i
= (r
- decode_p() - 1) & (DICSIZ
- 1);
i
= (i
+ 1) & (DICSIZ
- 1);
if (++r
== count
) return r
;
/* ===========================================================================
* Unlzh in to out. Return OK or ERROR.
n
= decode((unsigned) DICSIZ
, window
);
write_buf(out
, (char*)window
, n
);