💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › games › chessengines › crafty › tbdecode.… captured on 2021-12-17 at 13:26:06.

View Raw

More Information

-=-=-=-=-=-=-

#ifndef TBDECODE
/* *INDENT-OFF* */
#  define	TBDECODE
#  include <stdio.h>
#  include <stdlib.h>
#  include <string.h>
#  include <time.h>
#  ifndef CLOCKS_PER_SEC
#    define CLOCKS_PER_SEC CLK_TCK
#  endif
/* ---------------------------- Error codes --------------------------- */
/*				-----------				*/
#  define COMP_ERR_NONE     0	/* everything is OK			*/
#  define COMP_ERR_READ     2	/* input file read error		*/
#  define COMP_ERR_NOMEM    5	/* no enough memory			*/
#  define COMP_ERR_BROKEN   6	/* damaged compressed data		*/
#  define COMP_ERR_PARAM    7	/* incorrect function parameter 	*/
#  define COMP_ERR_INTERNAL 9	/* everything else is internal error	*/
				/* hopefully it should never happen	*/
/* Almost all  functions listed further return one as  its result on of */
/* codes given	above: if no  error occured then COMP_ERR_NONE (i.e. 0) */
/* is returned, otherwise functions return  error  code  plus number of */
/* line in "comp.c"  where the error  was detected multiplied  by  256; */
/* line number may  be	used for exact specification  of  a place where */
/* error was detected thus making debugging slightly simpler.		*/
/*									*/
/* Thus, "(code &  0xff)"  gives proper error code,  and  "(code >> 8)" */
/* gives number of line where the error was raised.			*/
/* -------------------------------------------------------------------- */
/*									*/
/*		  Compress/decompress some chess tables 		*/
/*									*/
/*		 Copyright (c) 1991--1998 Andrew Kadatch		*/
/*									*/
/* The Limited-Reference  variant  of  Lempel-Ziv algorithm implemented */
/* here was first described in	my  B.Sc.  thesis "Efficient algorithms */
/* for image  compression",  Novosibirsk  State  University,  1992, and */
/* cannot be  used in any product distributed in  Russia or CIS without */
/* written permission from the author.					*/
/*									*/
/* Most of the code listed below is significantly  simplified code from */
/* the PRS data compression library and therefore it should not be used */
/* in any product (software or hardware, commercial or not, and  so on) */
/* without written permission from the author.				*/
/*									*/
/* -------------------------------------------------------------------- */
/* ---------------------------- Debugging ----------------------------- */
/*				---------				*/
#  ifndef DEBUG
#    define DEBUG	0
#  endif
#  if DEBUG
#    undef assert
#    define assert(cond) ((cond) ? (void) 0 : _local_assert (__LINE__))
static void _local_assert(int lineno)
{
  fprintf(stderr, "assertion at line %u failed\n", lineno);
  exit(33);
}

#    define debug(x) x
#    define dprintf(x) printf x
#  else
#    if !defined (assert)
#      define assert(cond) ((void) 0)
#    endif
#    define debug(x)	 ((void) 0)
#    define dprintf(x)	 ((void) 0)
#  endif
/* mob_pach */
#  ifndef  __cplusplus
int cbEGTBCompBytes = 0;
#  else
extern "C" {
  int cbEGTBCompBytes = 0;
}
#  endif
/* --------------------- Constants, types, etc. ----------------------- */
/*			 ---------------------- 			*/
#  define MIN_BLOCK_BITS	8
/* LOG2 (min size of block to compress) */
#  define MAX_BLOCK_BITS	16
/* LOG2 (max size of block to compress) */
/* max. integer we can take LOG2 by table	*/
#  define MAX_BITS_HALF ((MAX_BLOCK_BITS + 1) >> 1)
#  define MAX_BITS	(MAX_BITS_HALF * 2)
/* assume that integer is at least 32 bits wide */
#  ifndef uchar
#    define uchar unsigned char
#  endif
#  define HEADER_SIZE		80	/* number of reserved bytes	*/
#  define STOP_SEARCH_LENGTH	256	/* terminate search if match	*/
					/* length exceeds that value	*/
#  define MAX_LENGTH_BITS		5
#  define MAX_LENGTH		  (1 << MAX_LENGTH_BITS)
#  define LONG_BITS		  1
#  define LONG_LENGTH		(MAX_BLOCK_BITS - LONG_BITS)
#  define LONG_QUICK		(MAX_LENGTH - LONG_LENGTH)
#  if LONG_LENGTH > (MAX_BLOCK_BITS - LONG_BITS)
#    undef LONG_LENGTH
#    define LONG_LENGTH 	(MAX_BLOCK_BITS - LONG_BITS)
#  endif
#  if LONG_LENGTH >= MAX_LENGTH || LONG_LENGTH <= 0
#    error LONG_LENGTH is out of range
#  endif
#  if LONG_BITS <= 0
#    error LONG_BITS must be positive
#  endif
#  define DELTA (LONG_BITS + LONG_QUICK - 1)
#  if (MAX_LENGTH - 1) - (LONG_LENGTH - LONG_BITS) != DELTA
#    error Hmmm
#  endif
#  define MAX_DISTANCES 	24
#  define LOG_MAX_DISTANCES	6	/* see check below	*/
#  if MAX_DISTANCES > (1 << LOG_MAX_DISTANCES)
#    error MAX_DISTANCES should not exceed (1 << LOG_MAX_DISTANCES)
#  endif
#  define ALPHABET_SIZE 	(256 + (MAX_DISTANCES << MAX_LENGTH_BITS))
#  define MAX_ALPHABET	ALPHABET_SIZE	/* max. alphabet handled by	*/
					/* Huffman coding routines	*/
#  define USE_CRC32		1
/* 0 - use Fletcher's checksum, != 0 - use proper CRC32 		*/
    static uchar header_title[64] =
    "Compressed by DATACOMP v 1.0 (c) 1991--1998 Andrew Kadatch\r\n\0";

#  define RET(n) ((n) + __LINE__ * 256)
/* ------------------------- CRC32 routines --------------------------- */
/*			     --------------				*/
#  if USE_CRC32
static unsigned CRC32_table[256];
static int CRC32_initialized = 0;
static void CRC32_init(void)
{
  int i, j;
  unsigned k, m = (unsigned) 0xedb88320L;

  if (CRC32_initialized)
    return;
  for (i = 0; i < 256; ++i) {
    k = i;
    j = 8;
    do {
      if ((k & 1) != 0)
	k >>= 1;
      else {
	k >>= 1;
	k ^= m;
      };
    } while (--j);
    CRC32_table[i] = k;
  }
  CRC32_initialized = 1;
}
static unsigned CRC32(uchar * p, int n, unsigned k)
{
  unsigned *table = CRC32_table;
  uchar *e = p + n;

  while (p + 16 < e) {
#    define X(i) k = table[((uchar) k) ^ p[i]] ^ (k >> 8)
    X(0);
    X(1);
    X(2);
    X(3);
    X(4);
    X(5);
    X(6);
    X(7);
    X(8);
    X(9);
    X(10);
    X(11);
    X(12);
    X(13);
    X(14);
    X(15);
#    undef X
    p += 16;
  }
  while (p < e)
    k = table[((uchar) k) ^ *p++] ^ (k >> 8);
  return (k);
}
#  else
#    define CRC32_init()
static unsigned CRC32(uchar * p, int n, unsigned k1)
{
  unsigned k0 = k1 & 0xffff;
  uchar *e = p + n;

  k1 = (k1 >> 16) & 0xffff;
  while (p + 16 < e) {
#    define X(i) k0 += p[i]; k1 += k0;
    X(0);
    X(1);
    X(2);
    X(3);
    X(4);
    X(5);
    X(6);
    X(7);
    X(8);
    X(9);
    X(10);
    X(11);
    X(12);
    X(13);
    X(14);
    X(15);
#    undef X
    k0 = (k0 & 0xffff) + (k0 >> 16);
    k1 = (k1 & 0xffff) + (k1 >> 16);
    p += 16;
  }
  while (p < e) {
    k0 += *p++;
    k1 += k0;
  }
  k0 = (k0 & 0xffff) + (k0 >> 16);
  k1 = (k1 & 0xffff) + (k1 >> 16);
  k0 = (k0 & 0xffff) + (k0 >> 16);
  k1 = (k1 & 0xffff) + (k1 >> 16);
  assert(((k0 | k1) >> 16) == 0);
  return (k0 + (k1 << 16));
}
#  endif			/* USE_CRC32	*/
/* ------------------------ Bit IO interface -------------------------- */
/*			    ----------------				*/
#  define BITIO_LOCALS	\
  unsigned int _mask;	\
  int	 _bits; 	\
  uchar *_ptr
typedef struct {
  BITIO_LOCALS;
} bitio_t;

#  define BITIO_ENTER(p) do {	\
  _mask = (p)._mask;		\
  _bits = (p)._bits;		\
  _ptr	= (p)._ptr;		\
} while (0)
#  define BITIO_LEAVE(p) do {	\
  (p)._mask = _mask;		\
  (p)._bits = _bits;		\
  (p)._ptr  = _ptr;		\
} while (0)
#  define BIORD_START(from) do {	\
  _ptr = (uchar *) (from);		\
  _bits = sizeof (_mask);		\
  _mask = 0;				\
  do					\
    _mask = (_mask << 8) | *_ptr++;	\
  while (--_bits != 0); 		\
  _bits = 16;				\
} while (0)
/* read [1, 17] bits at once */
#  define BIORD(bits)	   \
  (_mask >> (8 * sizeof (_mask) - (bits)))
#  define BIORD_MORE(bits) do { 	\
  _mask <<= (bits);			\
  if ((_bits -= (bits)) <= 0)		\
  {					\
    _mask |= ((_ptr[0] << 8) + _ptr[1]) << (-_bits);	\
    _ptr += 2; _bits += 16;		\
  }					\
} while (0)
/* ------------------------ Huffman coding ---------------------------- */
/*			    --------------				*/
#  if MAX_ALPHABET <= 0xffff
#    if MAX_ALPHABET <= 1024
/* positive value takes 15 bits => symbol number occupies <= 10 bits	*/
#      define huffman_decode_t	short
#    else
#      define huffman_decode_t	int
#    endif
#  else
#    define huffman_decode_t	int
#  endif
#  define HUFFMAN_DECODE(ch,table,start_bits) do {	\
  (ch) = table[BIORD (start_bits)];			\
  if (((int) (ch)) >= 0)				\
  {							\
    BIORD_MORE ((ch) & 31);				\
    (ch) >>= 5; 					\
    break;						\
  }							\
  BIORD_MORE (start_bits);				\
  do							\
  {							\
    (ch) = table[BIORD (1) - (ch)];			\
    BIORD_MORE (1);					\
  }							\
  while (((int) (ch)) < 0);				\
} while (0)
#  define HUFFMAN_TABLE_SIZE(n,start_bits) \
  ((1 << (start_bits)) + ((n) << 1))
static int huffman_decode_create(huffman_decode_t * table, uchar * length,
    int n, int start_bits)
{
  int i, j, k, last, freq[32], sum[32];

/* calculate number of codewords				      */
  memset(freq, 0, sizeof(freq));
  for (i = 0; i < n; ++i) {
    if ((k = length[i]) > 31)
      return RET(COMP_ERR_BROKEN);
    ++freq[k];
  }
/* handle special case(s) -- 0 and 1 symbols in alphabet	      */
  if (freq[0] == n) {
    memset(table, 0, sizeof(table[0]) << start_bits);
    return (0);
  }
  if (freq[0] == n - 1) {
    if (freq[1] != 1)
      return RET(COMP_ERR_BROKEN);
    for (i = 0; length[i] == 0;)
      ++i;
    i <<= 5;
    for (k = 1 << start_bits; --k >= 0;)
      *table++ = (huffman_decode_t) i;
    return (0);
  }
/* save frequences		      */
  memcpy(sum, freq, sizeof(sum));
/* check code correctness	      */
  k = 0;
  for (i = 32; --i != 0;) {
    if ((k += freq[i]) & 1)
      return RET(COMP_ERR_BROKEN);
    k >>= 1;
  }
  if (k != 1)
    return RET(COMP_ERR_BROKEN);
/* sort symbols 	      */
  k = 0;
  for (i = 1; i < 32; ++i)
    freq[i] = (k += freq[i]);
  last = freq[31];	/* preserve number of symbols in alphabet	*/
  for (i = n; --i >= 0;) {
    if ((k = length[i]) != 0)
      table[--freq[k]] = (huffman_decode_t) i;
  }
/* now create decoding table  */
  k = i = (1 << start_bits) + (n << 1);
  for (n = 32; --n > start_bits;) {
    j = i;
    while (k > j)
      table[--i] = (huffman_decode_t) - (k -= 2);
    for (k = sum[n]; --k >= 0;)
      table[--i] = table[--last];
    k = j;
  }
  j = i;
  i = 1 << start_bits;
  while (k > j)
    table[--i] = (huffman_decode_t) - (k -= 2);
  for (; n > 0; --n) {
    for (k = sum[n]; --k >= 0;) {
      assert(last <= i && last > 0);
      j = i - (1 << (start_bits - n));
      n |= table[--last] << 5;
      do
	table[--i] = (huffman_decode_t) n;
      while (i != j);
      n &= 31;
    }
  }
  assert((i | last) == 0);
  return (0);
}

/* -------------------- Read/write Huffman code ----------------------- */
/*			----------------------- 			*/
#  define MIN_REPT	2
#  if MIN_REPT <= 1
#    error MIN_REPT must exceed 1
#  endif
#  define TEMP_TABLE_BITS 8
static int huffman_read_length(bitio_t * bitio, uchar * length, int n)
{
  BITIO_LOCALS;
  huffman_decode_t table[2][HUFFMAN_TABLE_SIZE(64, TEMP_TABLE_BITS)];
  uchar bits[128];
  int i, j, k;

  BITIO_ENTER(*bitio);
  k = BIORD(1);
  BIORD_MORE(1);
  if (k != 0) {
    memset(length, 0, n);
    goto ret;
  }
  if (n <= 128) {
    k = BIORD(5);
    BIORD_MORE(5);
    for (i = 0; i < n;) {
      length[i] = (uchar) BIORD(k);
      BIORD_MORE(k);
      if (length[i++] == 0) {
	j = i + BIORD(4);
	BIORD_MORE(4);
	if (j > n)
	  return RET(COMP_ERR_BROKEN);
	while (i != j)
	  length[i++] = 0;
      }
    }
    goto ret;
  }
  BITIO_LEAVE(*bitio);
  i = huffman_read_length(bitio, bits, 128);
  if (i != 0)
    return (i);
  i = huffman_decode_create(table[0], bits, 64, TEMP_TABLE_BITS);
  if (i != 0)
    return (i);
  i = huffman_decode_create(table[1], bits + 64, 64, TEMP_TABLE_BITS);
  if (i != 0)
    return (i);
  BITIO_ENTER(*bitio);
  for (i = 0; i < n;) {
    HUFFMAN_DECODE(k, table[0], TEMP_TABLE_BITS);
    if (k <= 31) {
      length[i++] = (uchar) k;
      continue;
    }
    k &= 31;
    HUFFMAN_DECODE(j, table[1], TEMP_TABLE_BITS);
    if (j > 31) {
      int jj = j - 32;

      j = 1 << jj;
      if (jj != 0) {
	if (jj > 16) {
	  j += BIORD(16) << (jj - 16);
	  BIORD_MORE(16);
	}
	j += BIORD(jj);
	BIORD_MORE(jj);
      }
      j += 31;
    }
    j += MIN_REPT + i;
    if (j > n)
      return RET(COMP_ERR_BROKEN);
    do
      length[i] = (uchar) k;
    while (++i != j);
  }
ret:
  BITIO_LEAVE(*bitio);
  return (0);
}

/* ----------------------- Proper compression ------------------------- */
/*			   ------------------				*/
#  if MIN_BLOCK_BITS > MAX_BLOCK_BITS || MAX_BLOCK_BITS > MAX_BITS_HALF*2
#    error condition MIN_BLOCK_BITS <= MAX_BLOCK_BITS <= MAX_BITS_HALF*2 failed
#  endif
#  define DECODE_MAGIC	  ((int) 0x5abc947fL)
#  define BLOCK_MAGIC	  ((int) 0x79a3f29dL)
#  define START_BITS	  13
#  define SHORT_INDEX	  8u
typedef struct {
  huffman_decode_t table[HUFFMAN_TABLE_SIZE(ALPHABET_SIZE, START_BITS)];
  int distance[MAX_DISTANCES];
  unsigned *crc, *blk_u;
  unsigned short *blk_s;
  int block_size_log,		/* block_size is integral power of 2	*/
   block_size,			/* 1 << block_size_log			*/
   last_block_size,		/* [original] size of last block	*/
   n_blk,			/* total number of blocks		*/
   comp_block_size,		/* size of largest compressed block+32	*/
   check_crc;			/* check CRC32? 			*/
  uchar *comp;
  int magic;
} decode_info;
typedef struct {
  unsigned char *ptr;		/* pointer to the first decoded byte */
  int decoded;			/* number of bytes decoded so far    */
  int total;			/* total number of bytes in block    */
  int number;			/* number of this block 	     */
} COMP_BLOCK_T;

/* Pointer to compressed data block					*/
typedef struct {
  COMP_BLOCK_T b;
  struct {
    uchar *first;
    int size;
  } orig, comp;
  struct {
    uchar *ptr, *src;
    int rept;
  } emit;
  bitio_t bitio;
  int n;
  int magic;
} decode_block;
static int calculate_offset(decode_info * info, unsigned n)
{
  unsigned i;

  i = n / (2 * SHORT_INDEX);
  if (n & SHORT_INDEX)
    return info->blk_u[i + 1] - info->blk_s[n];
  else
    return info->blk_u[i] + info->blk_s[n];
}
static void do_decode(decode_info * info, decode_block * block, uchar * e)
{
  BITIO_LOCALS;
  uchar *p, *s = 0;
  int ch;

  if ((p = block->emit.ptr) >= e)
    return;
  if (p == block->orig.first) {
    BIORD_START(block->comp.first);
    block->emit.rept = 0;
  } else {
    BITIO_ENTER(block->bitio);
    if ((ch = block->emit.rept) != 0) {
      block->emit.rept = 0;
      s = block->emit.src;
      goto copy;
    }
  }
#  define OVER if (p < e) goto over; break
  do {
  over:
    HUFFMAN_DECODE(ch, info->table, START_BITS);
    if ((ch -= 256) < 0) {
      *p++ = (uchar) ch;
      OVER;
    }
    s = p + info->distance[ch >> MAX_LENGTH_BITS];
    ch &= MAX_LENGTH - 1;
    if (ch <= 3) {
      p[0] = s[0];
      p[1] = s[1];
      p[2] = s[2];
      p[3] = s[3];
      p += ch + 1;
      OVER;
    } else if (ch >= LONG_LENGTH) {
      ch -= LONG_LENGTH - LONG_BITS;
#  if (MAX_BLOCK_BITS - 1) + (LONG_LENGTH - LONG_BITS) >= MAX_LENGTH
      if (ch == DELTA) {
	ch = BIORD(5);
	BIORD_MORE(5);
	ch += DELTA;
      }
#  endif
      {
	int n = 1 << ch;

	if (ch > 16) {
	  n += BIORD(16) << (ch -= 16);
	  BIORD_MORE(16);
	}
	n += BIORD(ch);
	BIORD_MORE(ch);
	ch = n;
      }
      ch += LONG_LENGTH - (1 << LONG_BITS);
    }
    ++ch;
  copy:
    if (ch > 16) {
      if (p + ch > e) {
	block->emit.rept = ch - (int) (e - p);
	ch = (int) (e - p);
	goto copy;
      }
      do {
#  define X(i) p[i] = s[i]
	X(0);
	X(1);
	X(2);
	X(3);
	X(4);
	X(5);
	X(6);
	X(7);
	X(8);
	X(9);
	X(10);
	X(11);
	X(12);
	X(13);
	X(14);
	X(15);
#  undef X
	p += 16;
	s += 16;
      } while ((ch -= 16) > 16);
    }
    p += ch;
    s += ch;
    switch (ch) {
#  define X(i) case i: p[-i] = s[-i]
      X(16);
      X(15);
      X(14);
      X(13);
      X(12);
      X(11);
      X(10);
      X(9);
      X(8);
      X(7);
      X(6);
      X(5);
      X(4);
      X(3);
      X(2);
#  undef X
    }
    p[-1] = s[-1];
  } while (p < e);
#  undef OVER
  block->emit.ptr = p;
  block->emit.src = s;
  BITIO_LEAVE(block->bitio);
}

/* pretty ugly */
static int comp_open_file(decode_info ** res, FILE * fd, int check_crc)
{
  BITIO_LOCALS;
  bitio_t Bitio;
  uchar temp[ALPHABET_SIZE >= HEADER_SIZE ? ALPHABET_SIZE : HEADER_SIZE];
  uchar *ptr;
  int header_size, block_size, block_size_log, n_blk, i, n, n_s, n_u;
  unsigned *blk_u, *blk;
  unsigned short *blk_s;
  decode_info *info;

  if (res == 0)
    return RET(COMP_ERR_PARAM);
  CRC32_init();
  *res = 0;
  if (fread(temp, 1, HEADER_SIZE, fd) != HEADER_SIZE)
    return RET(COMP_ERR_READ);
  if (memcmp(temp, header_title, 64) != 0)
    return RET(COMP_ERR_READ);
  ptr = temp;
#  define R4(i) \
  ((ptr[i] << 24) + (ptr[(i) + 1] << 16) + (ptr[(i) + 2] << 8) + (ptr[(i) + 3]))
  header_size = R4(64);
  block_size_log = ptr[70];
  if (block_size_log > MAX_BITS || header_size < 84)
    return RET(COMP_ERR_BROKEN);
  block_size = 1 << block_size_log;
  if (ptr[71] != MAX_DISTANCES)
    return RET(COMP_ERR_BROKEN);
  n_blk = R4(72);
  if (R4(76) !=
      (ALPHABET_SIZE << 12) + (LONG_BITS << 8) + (LONG_LENGTH << 4) +
      MAX_LENGTH_BITS)
    return RET(COMP_ERR_BROKEN);
  if ((ptr = (uchar *) malloc(header_size)) == 0)
    return RET(COMP_ERR_NOMEM);
  if (fread(ptr + HEADER_SIZE, 1, header_size - HEADER_SIZE,
	  fd) != (size_t) (header_size - HEADER_SIZE)) {
    free(ptr);
    return RET(COMP_ERR_NOMEM);
  }
  memcpy(ptr, temp, HEADER_SIZE);
  header_size -= 4;
  if (CRC32(ptr, header_size, 0) != (unsigned) R4(header_size)) {
    free(ptr);
    return RET(COMP_ERR_BROKEN);
  }
  header_size += 4;
/*
   blk = (unsigned *) malloc (sizeof (unsigned) * (1 + n_blk));
 */
  n = sizeof(unsigned) * (1 + n_blk);
  if (n < 4 * 1024 * 1024)
    n = 4 * 1024 * 1024;
  blk = (unsigned *) malloc(n);
  if (blk == 0) {
    free(ptr);
    return RET(COMP_ERR_NOMEM);
  }
  n = sizeof(info->crc[0]) * (1 + (check_crc ? (2 * n_blk) : 0));
  n_u = sizeof(unsigned) * (2 + n_blk / (2 * SHORT_INDEX));
  n_s = sizeof(unsigned short) * (1 + n_blk);
  if ((info = (decode_info *) malloc(sizeof(*info) + n + n_u + n_s)) == 0) {
    free(ptr);
    free(blk);
    return RET(COMP_ERR_NOMEM);
  }
  cbEGTBCompBytes += sizeof(*info) + n + n_s + n_u;
  info->crc = (unsigned *) (info + 1);
  if (check_crc)
    blk_u = info->blk_u = info->crc + 2 * n_blk;
  else
    blk_u = info->blk_u = info->crc;
  blk_s = info->blk_s =
      (unsigned short *) (blk_u + 2 + n_blk / (2 * SHORT_INDEX));
  info->check_crc = check_crc;
  info->block_size_log = block_size_log;
  info->block_size = block_size;
  info->n_blk = n_blk;
  if (check_crc) {
    n_blk <<= 1;
    i = HEADER_SIZE;
    for (n = 0; n < n_blk; ++n) {
      info->crc[n] = R4(i);
      i += 4;
    }
    n_blk >>= 1;
  }
  i = HEADER_SIZE + (n_blk << 3);
  BIORD_START(ptr + i);
  info->comp_block_size = 0;
  for (n = 0; n <= n_blk; ++n) {
    if ((blk[n] = BIORD(block_size_log)) == 0)
      blk[n] = block_size;
    if (info->comp_block_size < (int) (blk[n]))
      info->comp_block_size = (int) (blk[n]);
    BIORD_MORE(block_size_log);
  }
  info->comp_block_size += 32;
  for (n = 0; n < MAX_DISTANCES; ++n) {
    info->distance[n] = -((int) BIORD(block_size_log));
    BIORD_MORE(block_size_log);
  }
  i += ((n_blk + 1 + MAX_DISTANCES) * block_size_log + 7) >> 3;
  BIORD_START(ptr + i);
  BITIO_LEAVE(Bitio);
  if (huffman_read_length(&Bitio, temp, ALPHABET_SIZE) != 0) {
    free(blk);
    free(info);
    free(ptr);
    return RET(COMP_ERR_BROKEN);
  }
  if (huffman_decode_create(info->table, temp, ALPHABET_SIZE, START_BITS) != 0) {
    free(blk);
    free(info);
    free(ptr);
    return RET(COMP_ERR_BROKEN);
  }
  info->last_block_size = blk[n_blk];
  blk[n_blk] = 0;
  for (n = 0; n <= n_blk; ++n) {
    i = blk[n];
    blk[n] = header_size;
    header_size += i;
    if (0 == n % (2 * SHORT_INDEX))
      blk_u[n / (2 * SHORT_INDEX)] = blk[n];
  }
  blk_u[n_blk / (2 * SHORT_INDEX) + 1] = blk[n_blk];
  for (n = 0; n <= n_blk; ++n) {
    i = n / (2 * SHORT_INDEX);
    if (n & SHORT_INDEX)
      blk_s[n] = blk_u[i + 1] - blk[n];
    else
      blk_s[n] = blk[n] - blk_u[i];
  }
  free(blk);
  free(ptr);
  info->comp = 0;
  info->magic = DECODE_MAGIC;
  *res = info;
  return (COMP_ERR_NONE);
}
static int comp_init_block(decode_block * block, int block_size, uchar * orig)
{
  if (block == 0)
    return RET(COMP_ERR_PARAM);
  block->orig.first = orig;
  block->comp.first = (uchar *) (block + 1);
  block->b.ptr = 0;
  block->b.decoded = -1;
  block->b.total = -1;
  block->b.number = -1;
  block->n = -1;
  block->magic = BLOCK_MAGIC;
  return (COMP_ERR_NONE);
}
static int comp_alloc_block(decode_block ** ret_block, int block_size)
{
  decode_block *block;

  if (ret_block == 0)
    return RET(COMP_ERR_PARAM);
  *ret_block = 0;
  if ((block = (decode_block *) malloc(sizeof(*block) + block_size)) == 0)
    return RET(COMP_ERR_NOMEM);
  cbEGTBCompBytes += sizeof(*block) + block_size;
  if (0 != comp_init_block(block, block_size, NULL))
    return RET(COMP_ERR_PARAM);
  *ret_block = block;
  return (COMP_ERR_NONE);
}

#  define RETURN(n) \
  return ((n) == COMP_ERR_NONE ? COMP_ERR_NONE : RET (n));
static int comp_read_block(decode_block * block, decode_info * info, FILE * fd,
    int n)
{
  int comp_size, orig_size, comp_start;
  uchar *comp, *orig;

  if (block == 0 || block->magic != BLOCK_MAGIC)
    return RET(COMP_ERR_PARAM);
  assert(info->magic == DECODE_MAGIC);
  if ((unsigned) n >= (unsigned) info->n_blk)
    RETURN(COMP_ERR_PARAM);
  comp = block->comp.first;
  block->n = n;
  orig = block->orig.first;
  orig_size = info->block_size;
  if (n == info->n_blk - 1)
    orig_size = info->last_block_size;
  block->orig.size = orig_size;
  comp_start = calculate_offset(info, n);
  block->comp.size = comp_size = calculate_offset(info, n + 1) - comp_start;
  if (fseek(fd, comp_start, SEEK_SET) != 0)
    RETURN(COMP_ERR_READ);
  if (fread(comp, 1, comp_size, fd) != (size_t) comp_size)
    RETURN(COMP_ERR_READ);
  if (info->check_crc &&
      info->crc[(n << 1) + 1] != CRC32(block->comp.first, comp_size, 0))
    RETURN(COMP_ERR_BROKEN);
  block->emit.rept = 0;
  if (comp_size == orig_size) {
    memcpy(orig, comp, comp_size);
    block->emit.ptr = orig + comp_size;
    block->b.decoded = comp_size;
  } else {
    block->emit.ptr = orig;
    block->b.decoded = 0;
  }
  block->b.number = n;
  block->b.ptr = orig;
  block->b.total = orig_size;
  RETURN(COMP_ERR_NONE);
}
static int comp_decode_and_check_crc(decode_block * block, decode_info * info,
    int n, int check_crc)
{
  if (block == 0 || block->magic != BLOCK_MAGIC)
    return RET(COMP_ERR_PARAM);
  assert(info->magic == DECODE_MAGIC);
  if ((unsigned) (n - 1) > (unsigned) (block->orig.size - 1))
    RETURN(COMP_ERR_PARAM);
  if (check_crc)
    n = block->orig.size;
  do_decode(info, block, block->orig.first + n);
  block->b.ptr = block->orig.first;
  block->b.total = block->orig.size;
  if (block->b.decoded >= block->b.total) {
    if (block->b.decoded > block->b.total)
      RETURN(COMP_ERR_BROKEN);
    if (block->emit.rept != 0)
      RETURN(COMP_ERR_BROKEN);
  }
  if (check_crc && info->check_crc &&
      info->crc[block->n << 1] != CRC32(block->orig.first, block->orig.size, 0))
    RETURN(COMP_ERR_BROKEN);
  RETURN(COMP_ERR_NONE);
}

#  if !defined (COLOR_DECLARED)
/*
   Test driver
 */
#    define	CRC_CHECK	1
int main(int argc, char *argv[])
{
  int i;
  int size;
  int result;
  FILE *fp;
  decode_info *comp_info;
  decode_block *comp_block;
  clock_t tStart, tEnd;
  double dSeconds;
  uchar rgbBuf[8192 + 32];

  if (2 != argc) {
    printf("Invalid arguments\n");
    exit(1);
  }
  fp = fopen(argv[1], "rb");
  if (0 == fp) {
    printf("Unable to open file\n");
    exit(1);
  }
  result = comp_open_file(&comp_info, fp, CRC_CHECK);
  if (0 != result) {
    printf("Unable to read file (1): %d\n", result);
    exit(1);
  }
  if (8192 != comp_info->block_size) {
    printf("Invalid block size: %d\n", comp_info->block_size);
    exit(1);
  }
  result = comp_alloc_block(&comp_block, comp_info->block_size);
  if (0 != result) {
    printf("Unable to allocate block: %d\n", result);
    exit(1);
  }
  size = 0;
  tStart = clock();
  for (i = 0; i < comp_info->n_blk; i++) {
    if (0 != (result =
	    comp_init_block(comp_block, comp_info->block_size, rgbBuf))) {
      printf("Unable to init block: %d\n", result);
      exit(1);
    }
    if (0 != (result = comp_read_block(comp_block, comp_info, fp, i))) {
      printf("Unable to read block: %d\n", result);
      exit(1);
    }
    size += comp_block->orig.size;
    if (0 != (result =
	    comp_decode_and_check_crc(comp_block, comp_info,
		comp_block->orig.size, CRC_CHECK))) {
      printf("Unable to decode block: %d\n", result);
      exit(1);
    }
  }
  tEnd = clock();
  dSeconds = (double) (tEnd - tStart) / CLOCKS_PER_SEC;
  printf("Total memory allocated: %dKb\n", (cbEGTBCompBytes + 1023) / 1024);
  printf("%g seconds, %dMb, %gMb/sec)\n", dSeconds, size / (1024 * 1024),
      size / (1024 * 1024) / dSeconds);
  return 0;
}
#  endif
/* *INDENT-ON* */
#endif