#define DEBUG
#define vax
/* #define OS_DEBUG_IO */
/*
 * Header file for all lz compression/decompression routines.
 */
#include <stdio.h>
#include <ctype.h>
#ifndef decus
# include <signal.h>
#endif

#ifndef	TRUE
# define FALSE		0
# define TRUE		1
#endif
#ifndef	EOS
# define EOS		'\0'
#endif
#define	streq(a, b)	(strcmp((a), (b)) == 0)

/* Set USERMEM to the maximum amount of physical user memory available
 * in bytes.  USERMEM is used to determine the maximum BITS that can be used
 * for compression.  If USERMEM is big enough, use fast compression algorithm.
 *
 * SACREDMEM is the amount of physical memory saved for others; compress
 * will hog the rest.
 */

#ifndef SACREDMEM
# define SACREDMEM	0
#endif

#ifdef vax
# ifdef unix
#  define vax_asm	TRUE
# endif
#endif
#ifndef	vax_asm
# define vax_asm	FALSE
#endif

#ifdef pdp11
# define IS_CACHE FALSE	/* Force no hash-cache				*/
# ifndef BITS
#  define BITS	12	/* max bits/code for 16-bit machine		*/
# endif
# define UCHAR	FALSE	/* TRUE if compiler supports unsigned char	*/
# define SHORT_INT	/* ints are short				*/
# ifndef MAXIO
#  define MAXIO 512	/* Buffer size for PDP-11 I/O buffers		*/
# endif
# define USERMEM 0	/* Force no user memory				*/
#else
/*
 * Not pdp11 -- assume large memory space
 */
# ifndef USERMEM
#  define USERMEM 750000	/* default user memory			*/
# endif
#endif

#ifndef	UCHAR
# define UCHAR		TRUE
#endif
#ifndef	IS_CACHE
# define IS_CACHE	TRUE
#endif

/* 
 * Define FBITS for machines with several MB of physical memory, to use
 * table lookup for (b <= FBITS).  If FBITS is made too large, performance
 * will decrease due to increased swapping/paging.  Since the program minus
 * the fast lookup table is about a half Meg, we can allocate the rest of
 * available physical memory to the fast lookup table.
 * 
 * If FBITS is set to 12, a 2 MB array is allocated, but only 1 MB is
 * addressed for parity-free input (i.e. text).
 *
 * FBITS=10 yields 1/2 meg lookup table + 4K code memory
 * FBITS=11 yields 1 meg lookup table + 8K code memory
 * FBITS=12 yields 2 meg lookup table + 16K code memory
 * FBITS=13 yields 4 meg lookup table + 32K code memory
 */

#ifdef USERMEM
#if USERMEM > 0
# if USERMEM >= (2621440+SACREDMEM)
#  if USERMEM >= (4718592+SACREDMEM)
#   define FBITS		13
#   define PBITS	16
#  else
#   define FBITS		12
#   define PBITS	16
#  endif
# else
#  if USERMEM >= (1572864+SACREDMEM)
#   define FBITS		11
#   define PBITS	16
#  else
#   if USERMEM >= (1048576+SACREDMEM)
#    define FBITS		10
#    define PBITS	16
#   else 
#    if USERMEM >= (631808+SACREDMEM)
#     define PBITS	16
#    else
#     if USERMEM >= (329728+SACREDMEM)
#      define PBITS	15
#     else
#      if USERMEM >= (178176+SACREDMEM)
#       define PBITS	14
#      else
#       if USERMEM >= (99328+SACREDMEM)
#        define PBITS	13
#       else
#        define PBITS	12
#       endif
#      endif
#     endif
#    endif
#    undef USERMEM
#    define USERMEM 0
#   endif
#  endif
# endif
#endif
#else
#define USERMEM	0
#endif

#ifdef PBITS		/* Preferred BITS for this memory size */
# ifndef BITS
#  define BITS PBITS
# endif
#endif

#if BITS == 16
# define HSIZE	69001		/* 95% occupancy */
#endif
#if BITS == 15
# define HSIZE	35023		/* 94% occupancy */
#endif
#if BITS == 14
# define HSIZE	18013		/* 91% occupancy */
#endif
#if BITS == 13
# define HSIZE	9001		/* 91% occupancy */
#endif
#if BITS == 12
# define HSIZE	5003		/* 80% occupancy */
#endif
#if BITS == 11
# define HSIZE	2591		/* 79% occupancy */
#endif
#if BITS == 10
# define HSIZE	1291		/* 79% occupancy */
#endif
#if BITS == 9
# define HSIZE	691		/* 74% occupancy */
#endif
/* BITS < 9 will cause an error */

/*
 * typedef's -- somewhat machine specific.
 */

/*
 * a code_int must be able to hold 2**BITS values of type int, and also -1
 */
#if BITS > 15
typedef long int	code_int;
#else
typedef int		code_int;
#endif

/*
 * count_int's hold counters.
 * count_short's hold small counters (for the interdata)
 * Some implementations don't support unsigned char (Decus C, for example)
 * Decus C is also brain damaged with regards to unsigned shorts.
 */
#ifdef interdata
typedef unsigned long int count_int;
typedef unsigned short int count_short;
#else
typedef long int	count_int;
#endif

#if UCHAR
typedef	unsigned char	char_type;
#else
typedef char		char_type;
#endif

#ifdef decus
typedef unsigned	U_short;
#else
typedef unsigned short	U_short;
#endif

typedef	char		flag;			/* Boolean flag		*/

/*
 * The following define the "magic cookie" header
 */
#define	HEAD1_MAGIC	0x1F
#define HEAD2_MAGIC	0x9D

/*
 * Defines for third byte of header
 */
#define BIT_MASK	0x1F
#define BLOCK_MASK	0x80
/*
 * Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
 * a fourth header byte (for expansion).
 */

#ifdef COMPATIBLE
					/* Compatible, but wrong!	*/
# define MAXCODE(n_bits)	(1 << (n_bits) - 1)
#else
# define MAXCODE(n_bits)	((1 << (n_bits)) - 1)
#endif

#define INIT_BITS 9			/* initial number of bits/code */

/*
 * One code could conceivably represent (1<<BITS) characters, but
 * to get a code of length N requires an input string of at least
 * N*(N-1)/2 characters.  With 5000 chars in the stack, an input
 * file would have to contain a 25Mb string of a single character.
 * This seems unlikely.
 */
#ifdef SHORT_INT
# define MAXSTACK    5000		/* size of output stack */
#else
# define MAXSTACK    8000		/* size of output stack */
#endif

#define CHECK_GAP 10000			/* ratio check interval */
/*
 * 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		*/

#ifdef	vms
#include		<ssdef.h>
#include		<stsdef.h>
#define	IO_SUCCESS	(SS$_NORMAL | STS$M_INHIB_MSG)
#define	IO_ERROR	(SS$_ABORT)
#endif

#ifndef	IO_SUCCESS
#define	IO_SUCCESS	0
#define	IO_ERROR	1
#endif

#ifndef OS_DEBUG_IO
/*
 * The LZ data structure is used to manage I/O
 */
#ifndef	MAXIO
# ifdef	vms
#  define MAXIO	512
# else
#  define MAXIO	2048
# endif
#endif

typedef struct LZ {
    char_type	*ip;		/* Next character to get		*/
    char_type	*iend;		/* -> end of input buffer		*/
    char_type	*op;		/* Free spot in output buffer		*/
    char_type	*oend;		/* -> end of output buffer		*/
    char_type	ibuf[MAXIO];
    char_type	obuf[MAXIO];
} LZ;

/*
 * You must define LZ_IO as the address of an LZ structure.
 * You must define LZ_FILL and LZ_FLUSH as functions to perform
 * buffer fill/empty processing.
 *
 * Note also that the compress routine uses PUTBUF(buf, count)
 * and the decompress routine uses GETBUF(buf, count) to (quickly)
 * transfer multiple bytes.
 */
#if UCHAR
#define	GET()		\
	((LZ_IO.ip < LZ_IO.iend) ? *LZ_IO.ip++ : LZ_FILL())
#else
#define	GET()		\
	((LZ_IO.ip < LZ_IO.iend) ? *LZ_IO.ip++ & 0xFF : LZ_FILL())
#endif
#define	PUT(c)		\
	((LZ_IO.op >= LZ_IO.oend) ? LZ_FLUSH() : 0, *LZ_IO.op++ = (c))

#define	LZ_IO		lz_buffer
#define	LZ_FILL		lz_fill
#define	LZ_FLUSH	lz_flush
#define PUTBUF		lz_putbuf
#define	GETBUF		lz_getbuf
extern LZ		LZ_IO;
#else
/*
 * We test the LZ IO package by calling the o.s. routines directly.
 */
#define	GET()			getchar()
#define PUT(c)			putchar(c)
#define GETBUF(buf, size)	fread(buf, 1, size, stdin)
#define PUTBUF(buf, size)	fwrite(buf, 1, size, stdout)
#define LZ_FLUSH()		fflush(stdout)
#endif

/*
 * Options
 */
extern flag	binary;		/* -b Readable text file if FALSE	*/
extern flag	nomagic;	/* -n No magic header if TRUE		*/
extern flag	quiet;		/* -q Don't talk about compression	*/
#ifdef	DEBUG
extern flag	debug;		/* -d debug level (zero == none)	*/
extern flag	verbose;	/* -v Verbose logging			*/
#endif
extern char	*infilename;	/* For error printouts			*/
extern char	*outfilename;	/* For more error printouts		*/
