[comp.os.minix] COMIC 1.0

jms@cs.vu.nl (Jan-Mark Wams) (08/01/90)

This is version 1.0 of COMIC. It supports DOS (TCC) and it's a little
faster. (Getinput() is the bad thing now. 8-)

Endjoy........

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'bits.c'
sed 's/^X//' > 'bits.c' << '+ END-OF-FILE ''bits.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Bits.c: Read and write bits on stdin and out.
X**
X**	Just define DEBUG to get characters '1' and '0'.
X**	The bits are put on a file, first bit in the high bit of the
X**	first byte. `Flus_bits ()' will add a `1' and padd the byte
X**	up to a full byte with zero's. When reading back the last bit
X**	in the last byte is the eof indicator.
X*/
X
X#include <errno.h>
X#include "comic.h"
X#include "bits.h"
X
X#ifdef DEBUG		/* Use characters '1' and '0'. */
X
X/*
X** Putbit: put a bit on stdout.
X*/
Xvoid putbit (bit)
Xint bit;
X{
X  assert (bit == 1 || bit == 0);
X
X  Nout += 1;
X  putchar ('0' + bit);
X}
X
X/*
X** Getbit: get a bit from stdin.
X*/
Xint getbit ()
X{
X  switch (getchar ()) {
X    case '0' : return 0;
X    case '1' : return 1;
X    case EOF : return EOF;
X    default : return 2;
X  }
X}    
X
X/*
X** Init_bits: Init the bit package.
X*/
Xvoid init_bits ()
X{
X  /* Noting to do in DEBUG mode. */
X}
X
X
X/*
X** Flush_bits: Flush the buffered bits to stdout.
X*/
Xvoid flush_bits ()
X{
X  fflush (stdout);
X}
X
X
X#else			/* No debug, so use 8 bits per byte. */
X
X#define IO_BUFF_SIZE	1024
Xstatic char io_buff [IO_BUFF_SIZE];
X#define eo_buff (io_buff + IO_BUFF_SIZE)
Xstatic char *io_index = io_buff;
Xstatic char *eof_index = io_buff;
Xstatic int put_bits = 1;
Xstatic int get_bits = 0;
X
X#define next()		(io_index++)		/* The next char. */
X#define nonext()	(io_index == eof_index)	/* There is no next. */
X#define io_buff_full	(io_index == eo_buff)	/* Buffer full. */
X
X
X/*
X** fatal: Print a error on stderr, and exit.
X*/
Xstatic void fatal (failed)
Xchar *failed;
X{
X  fprintf (stderr, "\r%s: Fatal couldn't %s", pname, failed);
X  if (errno != 0)
X	perror("");	/* Prints EOLN to ;-( */
X  else
X	printf ("\n");
X  exit (-1);
X}
X
X
X/*
X** Write_io_buff: to stdout.
X*/
Xstatic void write_io_buff ()
X{
X  if (write (1, io_buff, io_index - io_buff) != io_index - io_buff)
X	fatal ("write");
X  Nout += io_index - io_buff;
X  io_index = io_buff;
X}
X
X/*
X** Read_io_buff: from stdin.
X*/
Xstatic void read_io_buff ()
X{
X  if ((eof_index = io_buff + read (0, io_buff, IO_BUFF_SIZE)) < io_buff)
X	fatal ("read");
X
X  Nin += eof_index - io_buff;
X
X  io_index = io_buff;
X}
X
X
X/*
X** Putbit: put a bit on stdout.
X*/
Xvoid putbit (bit)
Xint bit;
X{
X  assert (bit == 1 || bit == 0);
X
X  put_bits = (put_bits << 1) | bit;
X
X  if (put_bits > 0xFF) {
X	*next() = put_bits;
X	if (io_buff_full)
X		write_io_buff ();
X	put_bits = 1;		/* Flag. */
X  }
X}
X
X
X/*
X** Getbit: get a bit from stdin.
X*/
Xint getbit ()
X{
X  if ((get_bits & 0x7F) == 0) {
X	if (get_bits == 0) {		/* First time only. */
X		read_io_buff ();
X		if (nonext ()) {
X			fprintf (stderr, "\r%s: Warning empty file.\n", pname);
X			fflush (stderr);
X			return EOF;
X		}
X	}
X
X	if (nonext ()) return EOF;
X	get_bits = (0xFF & (int)*next ()) << 1;
X	if (nonext ()) read_io_buff ();
X	if (nonext ()) {
X		if (get_bits == 0x100) return EOF;/* Bad luck, think ;-) */
X	}
X	else
X		get_bits |= 1;	/* Last byte has own EOF marker. */
X  }
X  else
X	get_bits <<= 1;
X
X  return (get_bits >> 8) & 1;
X}    
X
X/*
X** Init_bits: Init the bits package.
X*/
Xvoid init_bits ()
X{
X  io_index = io_buff;		/* Not ness, but nice. */
X  eof_index = io_buff;
X  put_bits = 1;		/* Very ness. */
X  get_bits = 0;
X}
X
X
X/*
X** Flush_bits: Flush the buffered bits to stdout.
X*/
Xvoid flush_bits ()
X{
X  int i;
X  putbit (1);				/* Eof marker. */
X  for (i = 0; i < 7; i++) putbit (0);	/* Fillup byte. */
X  write_io_buff ();
X}
X
X#endif /* DEBUG */		/* Next routines just call get/putbit(). */
X
X/*
X** Putnbit: put low `n' bits from code on stream.
X*/
Xvoid putnbit (code, n)
Xlong code;
Xint  n;
X{
X  int uggy_buggy;	/* The C compiler doesn't handle longs properly */
X
X  assert (n >= 0 && n < sizeof (long) * 8);
X
X  while (n -- > 0) {
X	uggy_buggy = (int)(code >> n) & 1;
X	putbit (uggy_buggy);
X  }
X}
X
X/*
X** Getnbit: Get `n' bits form stdin.
X*/
Xint getnbit (n)
Xint n;
X{
X  int ret = 0;		/* Return value. */
X
X  assert (n > 0 && n < sizeof (int) * 8);
X
X  while (n -- > 0) {
X	ret <<= 1;
X	switch (getbit ()) {
X	  case 1:
X		ret |= 1;
X		break;
X	  case 0:
X		break;
X	  case EOF:
X		fprintf (stderr, "\r%s: Unexpected EOF\n", pname);
X		exit (-1);
X	  default:
X		fprintf (stderr, "\r%s: funny bit\n", pname);
X		exit (-1);
X	}
X  }
X  return ret;
X}
X
X/* That's all folks. */
+ END-OF-FILE bits.c
chmod 'u=rw,g=r,o=r' 'bits.c'
set `wc -c 'bits.c'`
count=$1
case $count in
4233)	:;;
*)	echo 'Bad character count in ''bits.c' >&2
		echo 'Count should be 4233' >&2
esac
echo Extracting 'comic.c'
sed 's/^X//' > 'comic.c' << '+ END-OF-FILE ''comic.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Comic.c: COmpress MInix C (main routine)
X**
X** `Comic' is tuned to compress the minix source (kernel, fs, mm, commands)
X** it might be usable for other minix c programs, it might even be usable
X** for c programs or plain text, but it will not be optimal for other data.
X*/
X
X#define VERSION	"1.0"
X
X#include <string.h>		/* Included for strxxx (). */
X#include <ctype.h>		/* For isupper() and tolower (). */
X#include "comic.h"
X#include "buffer.h"
X#include "hash.h"		/* So we can print the hash sizes. */
X
X#ifdef DOS
X# define TTY	"CON"		/* The console device under SM-DOS. */
X# include <dir.h>		/* For find first/next. *//
X  static int index = 0;
X  static struct ffblk ffblk;
X
X  /*
X  ** Bug: findnext() returns the basename of the filename ;-(
X  */
X# define nextarg()						\
X  (                                                             \
X    argc >= 0                                                   \
X    ? (index == 0 || findnext (&ffblk) != 0)			\
X      && findfirst (argv [index ++], &ffblk, 0) != 0		\
X	  ? argv [index - 1]		                        \
X	  : ffblk.ff_name                                       \
X    : (char *) NULL						\
X  )
X#else	/* DOS */
X# define TTY	"/dev/tty"
X# define nextarg()\
X    (argc-- <= 0 ? (char *) NULL : *(argv++))
X#endif /* DOS */
X
X#define streq(s1,s2)	(strcmp (s1, s2) == 0)
X/*
X** Max length for file names.
X*/
X#define NAMELEN_MAX	30	/* 30 Sould be einnough. */
X#define FILE_SUFFIX	"-X"	/* Suffix for comiced files. */
X
Xchar *COMIC   = "comic";
Xchar *XCAT    = "xcat";		/* Names for the executable. */
Xchar *DECOMIC = "decomic";
X
Xchar *STDIN  = "stdin";		/* Names for in en output files. */
Xchar *STDOUT = "stdout";
X
X/*
X** Global variables.
X*/
Xchar *pname;				/* Name of program. */
Xstatic pair_t pairs [2];		/* Buffer for pair descriptors. */
Xpair_p p0 = &(pairs [0]);		/* Short hands. */
Xpair_p p1 = &(pairs [1]);
Xchar Buff  [BUFF_SIZE];			/* The Buffer. */
Xchar *Bend;				/* Pointer to the last char in Buff. */
Xchar *Bp = Buff;			/* Pointer to unproccessed char. */
Xchar *Binputend = Buff;			/* End of read ahead input. */
Xint  Bsize;
Xlong Nin, Nout;				/* Total # of bytes read/written. */
Xint v_flag = 0;				/* Verbose flag given. */
X#ifdef DOS
Xint a_flag = 0;				/* Ascii option, cast \r\n to \n. */
X#endif
X
Xstatic int c_flag = 0;			/* Cat (output to stdout) flag. */
Xstatic int f_flag = 0;			/* Force flag. */
Xstatic int d_flag = 0;			/* Decomic flag. */
X
X#ifdef DOS
X
X/*
X** Stoupper: Convert the string to upper case.
X*/
Xvoid stoupper (s)
Xchar *s;
X{
X  while (*s != '\0') {
X	if (isalpha (*s))
X		*s = toupper (*s);
X	s++;
X  }
X}
X
X/*
X** Stolower: Convert the string to lower case.
X*/
Xvoid stolower (s)
Xchar *s;
X{
X  while (*s != '\0') {
X	if (isalpha (*s))
X		*s = tolower (*s);
X	s++;
X  }
X}
X
X#endif /* DOS */
X
X/*
X** Basename: Do a check on name, only comic and decomic are allowed.
X*/
Xstatic char *basename (name)
Xchar *name;
X{
X  char *p;
X#ifdef DOS
X  /*
X  ** DOS needs special atention. Upercase letters and leading path
X  ** must be removed. Also .com or .exe suffixes have to be removed.
X  */
X  p = strrchr (name, '\\');
X  if (p != (char *) NULL)
X	name = p + 1;			/* Kill path prefix. */
X
X  stolower (p);				/* Make name lower case. */
X
X  p = strrchr (name, '.');
X  if (p != (char *) NULL) {
X	if (! streq (p, ".exe") && ! streq (p, ".com")) {
X		fprintf (stderr, "\r%s: Warning funny suffix %s\n", pname, p);
X	}
X	*p = '\0';			/* Kill the .exe or .com suffix. */
X  }
X  else
X	fprintf (stderr, "\r%s: Warning no DOS suffix\n", pname);
X
X#else /* Non DOS. */
X  p = strrchr (name, '/');
X  if (p != (char *) NULL)
X	name = p + 1;			/* Kill path prefix. */
X#endif
X  if (strncmp (name, "[de]comic", 9) == 0) {
X	printf ("\rWHOEHAHAHAHAHAHAHAHAHAHAHAHA.\n");
X	exit (-99);
X  }
X  if (! streq (name, COMIC)
X   && ! streq (name, DECOMIC)
X   && ! streq (name, XCAT)) {
X	fprintf (stderr, "\rThis program must be called [de]comic ");
X	fprintf (stderr, "or xcat, not %s.\n", name);
X#ifndef DEBUG
X	exit (1);		/* In debug mode, allow other names. */
X#endif
X  }
X  return name;
X}
X
X
X/*
X** Newname: generate new output name according to the given name.
X*/
Xstatic char *newname (fname)
Xchar *fname;
X{
X  static char ret_name [NAMELEN_MAX];	/* Buffer for return value. */
X  char *p;
X
X  /*
X  ** Check the tail. If the suffix is presend, just return it.
X  */
X  if ((p = strrchr (fname, FILE_SUFFIX [0])) != (char *)NULL
X  && streq (p, FILE_SUFFIX))
X	return fname;
X
X  strncpy (ret_name, fname, NAMELEN_MAX);
X  ret_name [(NAMELEN_MAX - 1) - strlen (FILE_SUFFIX)] = '\0'; /* Truckate. */
X#ifdef DOS
X  /*
X  ** Truncate suffix to be able to hold the FILE_SUFFIX.
X  ** If there is no suffix, add a "." string.
X  */
X  if ((p = strrchr (ret_name, '.')) != (char *)NULL)
X	p [4 - strlen (FILE_SUFFIX)] = '\0';	/* truncate. */
X  else
X	strcat (ret_name, ".");
X#endif /* DOS */
X  strcat (ret_name, FILE_SUFFIX);
X
X  return ret_name;
X}
X
X/*
X** Orgname: generate original name according to the given name.
X*/
Xstatic char *orgname (fname)
Xchar *fname;
X{
X  static char ret_name [NAMELEN_MAX];	/* Buffer for return value. */
X  char *p;
X
X  strncpy (ret_name, fname, NAMELEN_MAX);       /* Make private copy. */
X  ret_name [NAMELEN_MAX - 1] = '\0';		/* Terminate. */
X
X  /*
X  ** If the suffix is there delete it.
X  ** If this is a DOS machine, and the file name has no suffix, kill the dot.
X  */
X  if ((p = strrchr (ret_name, FILE_SUFFIX [0])) != (char *)NULL
X  && streq (p, FILE_SUFFIX)) {
X	*p = '\0';
X#ifdef DOS
X	if (*--p == '.')
X		*p = '\0';
X#endif /* DOS */
X  }
X  return ret_name;
X}
X
X/*
X** Stdin_out: Set stdin and stdout to newin and newout.
X**	Return succes or fail.
X*/
Xstatic int stdin_out (newin, newout)
Xchar *newin, *newout;
X{
X  FILE *tty;			/* File pointer for "/dev/tty" */
X  static char buf [2];
X  char *ans = buf;		/* To contain the answer, "y" or "n" */
X
X  /*
X  ** Reopen stdin.
X  */
X  if (freopen (newin, "r", stdin) == (FILE *)NULL) {
X	fprintf (stderr, "\r%s: Can't open \"%s\" for reading", pname, newin);
X	perror ("");
X	fflush (stderr);
X	return 0;		/* Report error. */
X  }
X  STDIN = newin;
X
X  /*
X  ** If the cat flag is set, don't reopen stdout.
X  */
X  if (c_flag)
X	  return 1;		/* Return success. */
X
X  /*
X  ** Check if we will overwrite a file. (Unless the -f flag was given.)
X  */
X  if (! f_flag && access (newout, 0) == 0) {
X	if (! isatty (2) || (tty = fopen (TTY, "r")) == (FILE *)NULL) {
X		fprintf (stderr, "\r%s: Won't overwrite %s\n", pname, newout);
X		fflush (stderr);
X		return 0;
X	}
X	fprintf (stderr, "\r%s: Overwrite %s (y/n)? ", pname, newout);
X	fflush (stderr);
X	ans = fgets (ans, 2, tty);
X	fclose (tty);
X	if (ans == (char *)NULL || *ans != 'y')
X		return 0;
X  }
X
X  /*
X  ** Reopen stdout.
X  */
X  if (freopen (newout, "w", stdout) == (FILE *)NULL) {
X	fprintf (stderr, "\r%s: Can't open \"%s\" for writing", pname, newout);
X	perror ("");
X	fflush (stderr);
X	return 0;		/* Report fail. */
X  }
X  STDOUT = newout;
X  return 1;		/* Return success. */
X}
X
X/*
X** Pr_ratio: print the compression ratio if its negative, or the
X**	verbose flag (v_flag) is TRUE.
X**	Divide Nin and Nout by 2 as long as they are to big, to
X**	prevent overflowing the rat variable.
X*/
Xstatic void pr_ratio ()
X{
X  long rat;
X
X  if (Nin == 0) {
X	if (! v_flag)
X		fprintf (stderr, "\r%s: Warning %s ", pname, STDIN);
X	fprintf (stderr, "is empty\n");
X	return;
X  }
X
X  while (Nin > 10000 || Nout > 10000) { /* Get smaller value. */
X	Nin >>= 1;
X	Nout >>= 1;
X  }
X  rat = ((Nin - Nout) * 10000) / Nin;
X
X  if (rat < 0L) {
X	if (! v_flag)
X		fprintf (stderr, "\r%s: ", pname);
X	fprintf (stderr, "Warning ");
X	if (! v_flag)
X		fprintf (stderr, "%s ", STDIN);
X  }
X
X  if (rat < 0L || v_flag) {
X	fprintf (stderr, "compression: %d", (int)(rat / 100));
X	fprintf (stderr, ".%02d%%\n", abs ((int)(rat % 100)));
X  }
X}
X
X
X/*
X** Vinfo: Give verbose information about this program.
X*/
Xstatic void vinfo ()
X{
X  fprintf (stderr, "\rThis is comic Version %s\t  ", VERSION);
X  fprintf (stderr, "(p) Jan-Mark Wams (email: jms@cs.vu.nl)\n");
X#ifdef __DATE__
X  fprintf (stderr, "Compiled on: %s\t  ", __DATE__);
X#endif
X  fprintf (stderr, "Flags: ");
X#ifdef DEBUG
X  fprintf (stderr, "DEBUG ");
X#endif
X#ifdef NDEBUG
X  fprintf (stderr, "NDEBUG ");
X#endif
X#ifdef C89
X  fprintf (stderr, "C89 ");
X#endif
X#ifdef MINIX
X  fprintf (stderr, "MINIX ");
X#endif
X#ifdef UNIX
X  fprintf (stderr, "UNIX ");
X#endif
X#ifdef AMOEBA
X  fprintf (stderr, "AMOEBA ");
X#endif
X#ifdef M68
X  fprintf (stderr, "M68 ");
X#endif
X#ifdef GCC
X  fprintf (stderr, "GCC ");
X#endif
X#ifdef DOS
X  fprintf (stderr, "DOS ");
X#endif
X#ifdef __TURBOC__
X  fprintf (stderr, "__TURBOC__ ");
X#else
X# ifdef __STDC__
X#  if ! __STDC__
X  fprintf (stderr, "!");
X#  endif
X  fprintf (stderr, "__STDC__ ");
X# endif
X#endif
X#ifdef _POSIX_SOURCE
X  fprintf (stderr, "_POSIX_SOURCE ");
X#endif
X  fprintf (stderr, "Hash table: %d.%d\n", H1_SIZE, H2_SIZE);
X}
X
X/*
X** Usage: print the usage of comic.
X*/
Xstatic void usage ()
X{
X  fprintf (stderr, "Usage: %s [-", pname);
X#ifdef DOS
X  fprintf (stderr, "a");			/* Dos has ascii flag. */
X#endif
X  if (! streq (pname, XCAT))
X	fprintf (stderr, "cf");
X  if (streq (pname, COMIC))			/* Comic has an extra flag. */
X	fprintf (stderr, "v");
X#ifdef DEBUG
X  fprintf (stderr, "v");			/* Debug mode has extra v. */
X#endif
X  fprintf (stderr, "vV?] [<file>[-X]...]\n");
X
X#ifdef DOS		/* DOS has no manual pages. */
X  fprintf (stderr, "  -a:   Ascii; %ss ascii files only.\n", pname);
X  if (! streq (pname, XCAT)) {
X	fprintf (stderr, "  -c:   Cat; generate ouput on stdout.\n");
X	fprintf (stderr, "  -f:   Force; overwrite output files without asking.\n");
X  }
X  fprintf (stderr, "  -v:   Verbose; give extra info while %sing.\n", pname);
X  if (streq (pname, COMIC))
X	fprintf (stderr, "  -vv:  Ver-verbose; extra verbose option.\n");
X# ifdef DEBUG
X  if (streq (pname, COMIC))
X	fprintf (stderr, "  -vvv: Ver-v");
X  else
X	fprintf (stderr, "  -vv:  V");
X  fprintf (stderr, "er-verbose; generate debug output.\n");
X# endif
X  fprintf (stderr, "  -V:   Version; give %ss version.\n", pname);
X  fprintf (stderr, "  -?:   What; give usage of %s.\n", pname);
X#endif
X}
X
X
X/*
X** File_start: Print a message if verbose option.
X*/
Xvoid file_start ()
X{
X  if (v_flag) {
X	fprintf (stderr, "%s: ", STDIN);
X	if (d_flag)
X		fprintf (stderr, "decomicing");
X  }
X  fflush (stderr);
X}
X
X/*
X** File_done: Print a message if verbose option.
X*/
Xvoid file_done ()
X{
X  if (v_flag && d_flag)
X	fprintf (stderr, "\b\b\bed to %s\n", STDOUT);
X  if (! d_flag)
X	pr_ratio ();
X  fflush (stderr);
X}
X
X
X/*
X** main: Parce arguments, call propper (en/de) code routine.
X*/
Xvoid main (argc, argv)
Xint argc;
Xchar **argv;
X{
X  char *p;		/* Used for flag processing etc. */
X  char *fname;
X
X  pname = basename (*argv);
X
X  argc --;
X  argv ++;	/* Skip pname. */
X
X  if (streq (pname, DECOMIC))	/* If this program is called */
X	d_flag = -1;		/* decomic set the decode flag. */
X
X  if (streq (pname, "xcat")) {	/* If this program is called */
X	d_flag = -1;		/* xcat set the decode */
X	c_flag = -1;		/* and cat flag. */
X  }
X
X  while (argc > 0 && (*argv) [0] == '-' && (*argv) [1] != '\0') {
X	for (p = *argv + 1; *p != '\0'; p++) {
X		switch (*p) {
X		case 'd': d_flag = 1; break;	/* decode flag on. */
X		case 'v': v_flag ++; break;	/* Verbose flag inc. */
X		case 'f': f_flag = 1; break;	/* Force flag on. */
X#ifdef DOS
X		case 'a': a_flag = 1; break;	/* Ascii mode. */
X#endif
X		case 'c': c_flag = 1; break;	/* Cat flag on. */
X		case '?': usage (); exit (0);	/* Usage and exit. */
X		case 'V': vinfo (); exit (0);	/* Give verbose info. */
X		default :
X		    fprintf (stderr, "\r%s: -%c ignored\n", pname, *p);
X		    fflush (stderr);
X		}
X	}
X	argc --; argv ++;	/* Next please. */
X  }
X
X#ifndef DEBUG
X  if (v_flag				/* Don't allow vv flag if stderr */
X  && ! (isatty (2) && isatty (1)))	/* and stdin are not the tty. */
X	v_flag = 1;
X#endif
X
X  if (argc == 0) {			/* No args, do stin to stout. */
X	if (c_flag == 1 || f_flag) {	/* Silly flags. */
X		fprintf (stderr, "\r%s: -", pname);
X		if (c_flag == 1) putc ('c', stderr);
X		if (f_flag) putc ('f', stderr);
X		fprintf (stderr, " ignored\n");
X	}
X	c_flag = 1;		/* Cat mode. */
X	file_start ();
X	if (d_flag)
X		decode ();
X	else
X		encode ();
X	file_done ();
X  }
X  else {
X	if (c_flag && f_flag) {		/* -c makes -f silly ;-) */
X		fprintf (stderr, "\r%s: -f ignored\n", pname);
X		fflush (stderr);
X	}
X#ifdef DOS			/* DOS-file names are in UPPER case. */
X	stoupper (FILE_SUFFIX);
X#endif /* DOS */
X  }
X
X  while ((fname = nextarg ()) != (char *)NULL) {
X	if (d_flag) {	/* Decode. */
X		if ( ! stdin_out (newname (fname), orgname (fname)))
X			continue;	/* If not reopened, do next file. */
X		file_start ();
X		decode ();	/* Decode stdin. */
X		file_done ();
X	}
X	else /* No d_flag */ {	/* Encode. */
X		if (streq (fname, newname (fname))) {
X			if (v_flag) {
X				fprintf (stderr, "\r%s: ", pname);
X				fprintf (stderr, "%s already has ", fname);
X				fprintf (stderr, "%s suffix\n", FILE_SUFFIX);
X				fflush (stderr);
X			}
X			continue;
X		}
X		if ( ! stdin_out (orgname (fname), newname (fname)))
X			continue;	/* If not reopened, do next file. */
X		file_start ();
X		encode ();		/* Put data on stdout. */
X		file_done ();
X	}
X  }
X}
+ END-OF-FILE comic.c
chmod 'u=rw,g=r,o=r' 'comic.c'
set `wc -c 'comic.c'`
count=$1
case $count in
13070)	:;;
*)	echo 'Bad character count in ''comic.c' >&2
		echo 'Count should be 13070' >&2
esac
echo Extracting 'decode.c'
sed 's/^X//' > 'decode.c' << '+ END-OF-FILE ''decode.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Decode.c: decode stdin to stdout.
X**	Get a bit, if it's a 0, decode a pair, if it's a 1, decode a char.
X**	If it's no 1 nor a 0, fly the broomstick. *8-)
X*/
X
X#include "comic.h"
X#include "buffer.h"
X#include "huffman.h"	/* Data structures of huffman trees and codes. */
X#include "bits.h"
X#include "header.h"
X
X/*
X** De_pair: Read offset and length, and put substring on stout.
X*/
Xstatic void de_pair ()
X{
X  int len, off = Hdecode (Hoff);
X  char *p;
X
X  off = off << LOW_OFFSET_BITS;
X  off |= getnbit (LOW_OFFSET_BITS);
X  off += OFFSET_MIN;
X  len = Hdecode (Hlen) + LENGTH_MIN;
X#ifdef DEBUG
X  if (v_flag > 1)
X	printf ("<%d,%d>\"", off, len);
X#endif
X  p = Bsub (Bp, off);
X  while (len --) {
X	putchar (*p);
X	*Bp = *p;
X	p = Bsucc (p);
X	Bp = Bsucc (Bp);
X  }
X#ifdef DEBUG
X  if (v_flag > 1)
X# ifdef DOS
X	printf ("\"\r\n");
X# else
X	printf ("\"\n");
X# endif
X#endif
X}
X
X/*
X** De_char: Get a huffman encoded char and put in on stdout.
X*/
Xstatic void de_char ()
X{
X  int c = Hdecode (Hchar);
X  putchar (c);
X#ifdef DEBUG
X  if (v_flag > 1) {
X# ifdef DOS
X	putchar ('\r');
X# endif
X	putchar ('\n');
X  }
X#endif
X  *Bp = c;
X  Bp = Bsucc (Bp);
X}
X
X
X/*
X** Decode: decode stdin. Read a bit from stdin, if it's a 0, decode a pair,
X**	if it's a 1 decode a char, if it's EOF, return.
X*/
Xvoid decode ()
X{
X  Bsize = OFFSET_SIZE + OFFSET_MIN;
X  Bend = &(Buff [OFFSET_MAX]);
X  Bp = Binputend = Buff;	/* Not ness, but.. */
X  Nin = 0; Nout = 0;
X  Binit ();			/* Init the buffer. */
X  Hinit ();			/* Init the huffman tables. */
X  init_bits ();			/* Init the bit package. */
X
X#ifdef DOS
X	setmode (0, O_BINARY);	/* And you wonder why they call it SM_DOS. */
X  if (a_flag)
X	setmode (1, O_TEXT);
X  else
X	setmode (1, O_BINARY);
X#endif
X
X  if (! magic_ok ()) {
X	fprintf (stderr, "\r%s: Wrong magic in header\n", pname);
X	exit (-1);
X  }
X
X  for (;;) {
X	switch (getbit ()) {
X	  case 0:
X		de_pair();
X		break;
X	  case 1:
X		de_char();
X		break;
X	  case EOF:
X		fflush (stdout);
X		return;			/* EOF, were done. */
X	  default:
X		fprintf (stderr, "\r%s: Funny bit\n", pname);
X		exit (-1);
X	}
X  }
X}
+ END-OF-FILE decode.c
chmod 'u=rw,g=r,o=r' 'decode.c'
set `wc -c 'decode.c'`
count=$1
case $count in
2119)	:;;
*)	echo 'Bad character count in ''decode.c' >&2
		echo 'Count should be 2119' >&2
esac
echo Extracting 'encode.c'
sed 's/^X//' > 'encode.c' << '+ END-OF-FILE ''encode.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Encode.c: parce stdin, write huffman codes and bits on stdout.
X**	Get next two longest strings, if the second one is longer,
X**	or the first one isn't long innough, encode a char, else
X**	encode a pair, (offset, lenght).
X*/
X
X#include "comic.h"
X#include "buffer.h"
X#include "huffman.h"
X#include "bits.h"
X#include "header.h"
X#include "hash.h"
X
X/*
X** Outpair: Output part p0's length and offset.
X*/
Xstatic void outpair (done)
Xint *done;	/* Set to False if pair codes are longer than char codes. */
X{
X  int offset = Bdelta (Bp, p0-> start) - OFFSET_MIN;
X  int length = p0-> length;
X
X  assert (offset >= 0);
X  assert (offset < OFFSET_SIZE);
X  assert (length >= LENGTH_MIN);
X  assert (length - LENGTH_MIN < HUFFMAN_SIZE);
X
X#if LENGTH_MIN <= 2
X  if (length == 2
X  &&
X      Hcodelen (Hoff, offset >> LOW_OFFSET_BITS) + LOW_OFFSET_BITS
X    + Hcodelen (Hlen, 2 - LENGTH_MIN)
X    >
X      Hcodelen (Hchar, *Bp) + Hcodelen (Hchar, *Bsucc (Bp))) {
X	*done = 0;
X	return;
X  }
X#endif
X
X  putbit (0);						/* Put a 0. */
X  Hencode (Hoff, offset >> LOW_OFFSET_BITS);		/* Put offset high. */
X  putnbit ((long)offset, LOW_OFFSET_BITS);		/* Put offset low. */
X  Hencode (Hlen, length - LENGTH_MIN);	/* Put index length. */
X
X#ifdef DEBUG
X  if (v_flag > 2) {
X	fprintf (stderr, "(%d,%d)", offset + OFFSET_MIN, length);
X	putc ('"', stderr);
X  }
X#endif
X	while (length -- > 0) {
X#ifdef DEBUG
X		if (v_flag > 2)	putc (*Bp, stderr);
X#endif
X		hash_update ();		/* Update hash tables. */
X		Bp = Bsucc (Bp);
X	}
X#ifdef DEBUG
X	if (v_flag > 2) {
X		fprintf (stderr, "\"\n");
X		fflush (stderr);
X	}
X#endif /* DEBUG */
X  assert (done);
X}
X
X/*
X** Outchar: Output char *Bp.
X*/
Xstatic void outchar ()
X{
X  putbit (1);					/* Put a 1. */
X  Hencode (Hchar, (0xFF & (int)*Bp));	/* Put this char. */
X#ifdef DEBUG
X  if (v_flag > 2) {
X	putc ('`', stderr);
X	putc (*Bp, stderr);
X	putc ('\'', stderr);
X	putc ('\n', stderr);
X  }
X#endif /* DEBUG */
X  hash_update ();
X  Bp = Bsucc (Bp); 			/* Increase Bp. */
X}
X
X
X/*
X** Encode: parce stdin, write huffman codes and bits on stdout.
X*/
Xvoid encode ()
X{
X  /*
X  ** Pairout indicates the pair p0 will be outputed, not just char *Bp.
X  */
X  int pairout = 1;
X  Bsize = BUFF_SIZE;
X  Bend = &(Buff [BUFF_MAX]);
X  Bp = Binputend = Buff;	/* Not ness, but.. */
X  Nin = 0; Nout = 0;
X  Binit ();			/* Init the buffer. */
X  Hinit ();			/* Init the huffman tables. */
X  init_bits ();			/* Init the bit package. */
X  hash_init ();			/* Init the hash tables. */
X
X#ifdef DOS
X  if (a_flag)
X	setmode (0, O_TEXT);
X  else
X	setmode (0, O_BINARY);	/* And you wonder why they call it SM_DOS. */
X
X  setmode (1, O_BINARY);
X#endif
X
X  put_magic ();		/* Put magic on stdout. */
X
X  while (getinput () != EOF) {
X	gettoken (pairout);			/* Find matching strings. */
X	pairout =  p0-> length >= LENGTH_MIN
X		&& p0-> length >= p1-> length;	/* See if it's long innough. */
X	if (pairout)
X		outpair (&pairout);		/* If so, ouput it's pair. */
X	if (! pairout)
X		outchar ();			/* Else do one char. */
X  }
X  flush_bits ();		/* Flush buffered bits. */
X}
+ END-OF-FILE encode.c
chmod 'u=rw,g=r,o=r' 'encode.c'
set `wc -c 'encode.c'`
count=$1
case $count in
3076)	:;;
*)	echo 'Bad character count in ''encode.c' >&2
		echo 'Count should be 3076' >&2
esac
echo Extracting 'getinput.c'
sed 's/^X//' > 'getinput.c' << '+ END-OF-FILE ''getinput.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Getinput.c: Get input into the buffer.
X**	Read stdin till Blookupend. This code look's complicated, but it
X**	isn't; Most of it is about printing.
X*/
X
X#include <sys/types.h>          /* Included for stat (). */
X#include <sys/stat.h>           /* Idem. */
X
X#include "comic.h"
X#include "buffer.h"
X
X/*
X** getinput: Get input buffer full, return EOF if end of file, SPC other wise.
X*/
Xint getinput ()
X{
X  static unsigned long fsize = 0L;
X  static struct stat st [1];
X  static int printed = -1;		/* -1 Means don't print. */
X  int percent, c;
X  char *stop = Blookupstart (), *Oinputend = Binputend;
X
X  if (v_flag > 1 && Nin == 0 && ! isatty (0) && fstat (0, st) == 0) {
X        fsize = (unsigned long) (st [0].st_size);
X	fprintf (stderr, "  0%%");
X	fflush (stderr);
X	printed = 0;
X  }
X
X  while (Binputend != stop && (c = getchar ()) != EOF) {
X	*Binputend = c;
X#ifdef DOS
X	if (a_flag && c == '\n')	/* Size of file is including \r. */
X		Nin += 1;               /* But we don't read it, so adjust. */
X#endif
X	Binputend = Bsucc (Binputend);	/* Increase the input end marker. */
X  }
X  Nin += Bdelta (Binputend, Oinputend);	/* Count the number of char's read. */
X
X  if (Nin < fsize) {	/* Note 0 <=  Nin < fsize A thus 0 < fsize */
X	percent = 100 - (int)((fsize - Nin) / (fsize / 100));
X	if (percent > printed) {
X		fprintf (stderr, "\b\b\b\b%3d%%", percent);
X		fflush (stderr);
X		printed = percent;
X	}
X  }
X
X  if (Bp == Binputend) {
X	assert (Oinputend == Binputend);
X#ifdef DOS
X	/*
X	** This assertion will fail if one comics a binary file.
X	*/
X	assert (fsize == 0 || Nin == fsize || Nin == fsize - 1); /* ^Z */
X#else
X	assert (fsize == 0 || Nin == fsize);
X#endif /* DOS */
X	if (printed != -1) {
X		fprintf (stderr, "\b\b\b\b");
X		fflush (stderr);
X	}
X	return EOF;
X  }
X  else
X	return (int) ' ';
X}
+ END-OF-FILE getinput.c
chmod 'u=rw,g=r,o=r' 'getinput.c'
set `wc -c 'getinput.c'`
count=$1
case $count in
1858)	:;;
*)	echo 'Bad character count in ''getinput.c' >&2
		echo 'Count should be 1858' >&2
esac
echo Extracting 'gettoken.c'
sed 's/^X//' > 'gettoken.c' << '+ END-OF-FILE ''gettoken.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Gettoken.c: Find the best (logest) part to output.
X**	We try to find the longest part in the lookup buffer, matching the
X**	input. Well actually, we look for two srings, one, matching the
X**	current input, starting at the current buffer start, and one
X**	matching the string starting at the next input byte, (asif we
X**	decoded a char.) This just incase decoding two pairs could have
X**	been done, using one char and pair. (This will save some %s extra.)
X**	To show what I mean, consider;
X**
X**					xxxxx.AxAxxxxx
X**	This would be parced 		x xxxx . A x Ax xxxx
X**	but xxxx costs (about) as
X**	mutch as xxxxx. So 		x xxxx . A x A xxxxx
X**	will be better.
X**
X*/
X
X#include "comic.h"
X#include "buffer.h"
X#include "hash.h"
X
X/*
X** Eqlen: Return the number of bytes, p[i] en q[i] are the same.
X*/
Xstatic int eqlen (p, q, count)
Xchar *p;
Xchar *q;
Xint count;
X{
X  char *r = p;
X  char *stop = Badd (p, count);
X
X  assert (p != q);
X
X  while (*r == *q && r != stop) {
X	r = Bsucc (r);
X	q = Bsucc (q);
X  }
X  assert (Bdelta (r, p) <= count);
X  return Bdelta (r, p);
X}
X
X
X/*
X** gettoken: Find the best (logest) part to output.
X*/
Xvoid gettoken (p0used)
Xint p0used;		/* Indicate if p0 was used. */
X{
X
X  index_t i, itail = Bindex (Bsub (Bp, OFFSET_MAX));
X  int len;
X  int maxlen = Bdelta (Binputend, Bp);
X  char *Bp1 = Bsucc (Bp);	/* Succesort of Bp. */
X  char *Bp2 = Bsucc (Bp1);	/* Gess... */
X  char *Bp_1 = Bpred (Bp);
X
X  if (maxlen < LENGTH_MIN) {
X	p0-> length = 0;
X	return;
X  }
X
X  if (maxlen > LENGTH_MAX) {
X	assert (maxlen <= LENGTH_MAX + PAIR_MAX + 1);
X	maxlen = LENGTH_MAX;
X  }
X
X  if (! p0used) {				/* If p0 wasn't used, p1 */
X	p0-> start = p1-> start;                /* will be the new p0. */
X	p0-> length = p1-> length;
X	if (p0-> length > maxlen) {		/* Check p0's length. */
X		assert (p0-> length - 1 == maxlen);
X		p0-> length = maxlen;
X	}
X  }
X  else {
X	if (*Bp_1 == *Bp && *Bp == *Bp1) {	/* Bp - 1 isn't in the hash */
X		p0-> start = Bp_1;              /* So try it athoc. */
X		p0-> length = eqlen (Bp_1, Bp, maxlen);
X	}
X	else
X		p0-> length = 0;
X
X	i = hash_entry (*Bp, *Bp1);
X
X	while (i != INDEX_END && p0-> length != maxlen) {
X		if ((len = eqlen (Buff + i, Bp, maxlen)) > p0-> length) {
X			p0-> start = Buff + i;
X			p0-> length = len;
X		}
X		i = next_list [i];
X	}
X  }
X
X  /*
X  ** We should adjust maxlen here, but we get faster code if we
X  ** just check if p1-> length is (one) to long whilst copying
X  ** p1 to p0 if ! p0used.
X  */
X
X  if (*Bp == *Bp1 && *Bp1 == *Bp2) {	/* Bp1 - 1 isn't in the hash. */
X	p1-> start = Bp;
X	p1-> length = eqlen (Bp, Bp1, maxlen);
X  }
X  else if (*Bp_1 == *Bp1) {		/* Bp1 - 2 neighter. */
X	p1-> start = Bp_1;
X	p1-> length = eqlen (Bp_1, Bp1, maxlen);
X  }
X  else
X	p1-> length = 0;
X
X  i = hash_entry (*Bp1, *Bp2);		/* Do p1. */
X  while (i != INDEX_END && p1-> length != maxlen && i != itail) {
X	if (*Bp != Buff [Ipred (i)]
X	&&  (len = eqlen (Buff + i, Bp1, maxlen)) > p1-> length) {
X		p1-> start = Buff + i;
X		p1-> length = len;
X	}
X	i = next_list [i];
X  }
X  assert (p0-> length <= maxlen);
X  assert (p1-> length <= maxlen);
X}
X
+ END-OF-FILE gettoken.c
chmod 'u=rw,g=r,o=r' 'gettoken.c'
set `wc -c 'gettoken.c'`
count=$1
case $count in
3126)	:;;
*)	echo 'Bad character count in ''gettoken.c' >&2
		echo 'Count should be 3126' >&2
esac
echo Extracting 'hash.c'
sed 's/^X//' > 'hash.c' << '+ END-OF-FILE ''hash.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Hash.c: For speed sake, a (two dimensional) hash table is implemented
X** 	on top of the existing structure. Ugly, bad, but faster. ;-(
X*/
X
X#include "comic.h"		/* For hash.h etc. */
X#include "buffer.h"		/* For Bp etc. */
X#include "hash.h"
X
X/* index_t hash_tbl [H1_SIZE] [H2_SIZE];		/* The hash table. */
Xindex_t *hash_tbl = (index_t *) NULL;
Xindex_t	next_list [BUFF_SIZE];			/* The index list. */
Xindex_t back_list [BUFF_SIZE];			/* The back list. */
X
X/*
X** Hash_init: Initialise the hash table.
X** 	Pre filling the buffer might give better compression, but
X**	would enlarge the compress program. '-) Perhaps a pseudo
X**	random generator, filling the buffer with the most likely
X**	(lowest number of bits in their huffman code) characters.
X**	Note: the buffer (Buff) must be filled.
X*/
Xvoid hash_init ()
X{
X  int i;
X
X  if (hash_tbl == (index_t *) NULL) {		/* Malloc the hast table. */
X	hash_tbl = (index_t *) malloc (H1_SIZE * H2_SIZE * sizeof (index_t));
X	if (hash_tbl == (index_t *) NULL) {
X		fprintf (stderr, "\r%s: Out of memory\n", pname);
X		exit (-1);
X	}
X  }
X
X  i = 0;
X  do						/* Init the hash table. */
X	hash_tbl [i++] = INDEX_END;
X  while (i != H1_SIZE * H2_SIZE);
X
X  next_list [0] = BUFF_SIZE - 1;
X  for (i = 1; i < BUFF_SIZE; i++)               /* Fill next_list. */
X	next_list [i] = i - 1;
X
X  back_list [BUFF_SIZE - 1] = 0;
X  for (i = 0; i < BUFF_SIZE; i++)               /* Fill back_list. */
X	back_list [i] = i + 1;
X
X  hash_entry ('\0', '\0') = i = Bindex (Bsub (Bp, 2));
X
X  back_list [i] = INDEX_END;
X  next_list [Bindex (Bsub (Bp, OFFSET_MAX))] = INDEX_END;
X}
X
X
X/*
X** Hash_update: Update the hash table. (Using the char at Bp)
X*/
Xvoid hash_update ()
X{
X  char p = *Bpred (Bp);				/* Previous char. */
X  char c = *Bp;					/* Current char. */
X  index_t icur = Bindex (Bp);			/* Current index. */
X  index_t ipre = Ipred (icur);			/* Previouse index. */
X  char *  tail = Bsub (Bp, OFFSET_MAX);		/* Tail of offset buff. */
X  index_t new_tail = back_list [Bindex (tail)]; /* New tail of next list. */
X  index_t ipc = hash_entry (p, c);		/* Index of hash (p,c). */
X
X  if (next_list [Bindex (tail)] != INDEX_END)
X	*Bp = *Bp;
X/*
X**  This assertion fails sometimes, but it should never fail, so
X**  this is a potentially dangerous sitiation.
X**
X**  assert (next_list [Bindex (tail)] == INDEX_END);
X*/
X
X  if ((next_list [ipre] = ipc) != INDEX_END)
X  back_list [ipc] = ipre;
X  hash_entry (p, c) = ipre;		/* Update list at head of buffer. */
X  back_list [ipre] = INDEX_END;
X
X  if (new_tail == INDEX_END) {		/* Idem tail. */
X	hash_entry (*tail, *Bsucc (tail)) = INDEX_END;
X  }
X  else {
X	next_list [new_tail] = INDEX_END;
X  }
X}
X
+ END-OF-FILE hash.c
chmod 'u=rw,g=r,o=r' 'hash.c'
set `wc -c 'hash.c'`
count=$1
case $count in
2708)	:;;
*)	echo 'Bad character count in ''hash.c' >&2
		echo 'Count should be 2708' >&2
esac
echo Extracting 'header.c'
sed 's/^X//' > 'header.c' << '+ END-OF-FILE ''header.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Header.c: header handeling routines.
X**	Magic routines only, but for 2.0 the header will become
X**	more inportante.
X*/
X
X#include "comic.h"
X#include "header.h"
X
X/*
X** Magic_ok: Check the first bytes on stdin. They should be ok.
X**	Return True if magic is ok, else False.
X*/
Xint magic_ok ()
X{
X  char c;
X
X  if (read (0, &c, 1) != 1) {
X	fprintf (stderr, "\r%s: Can't read header\n", pname);
X	exit (-1);
X  }
X  if (c != MAGIC1) return 0;	/* First byte has to be ok. */
X
X  if (read (0, &c, 1) != 1) {
X	fprintf (stderr, "\r%s: Can't read headers 2nd byte\n", pname);
X	exit (-1);
X  }
X
X  if ((c & SUFFIX_BIT) != 0) {
X	fprintf (stderr, "\r%s: Version 1.0 can't handle dos suffix\n", pname);
X	exit (-1);
X  }
X  if ((c & DYNAMIC_BIT) != 0) {
X	fprintf (stderr, "\r%s: Version 1.0 can't handle dynamic bit\n", pname);
X	exit (-1);
X  }
X  if ((c & EXTEND_BIT) != 0) {
X	fprintf (stderr, "\r%s: Version 1.0 can't handle extend bit\n", pname);
X	exit (-1);
X  }
X
X  if (c != (MAGIC2 | STATIC_BIT)) return 0;	/* 1.0 static only ;-) */
X
X  return 1;
X}
X
X/*
X** Put_magic: Write magic header on stdout.
X*/
Xvoid put_magic ()
X{
X  char c1 = MAGIC1, c2 = (MAGIC2 | STATIC_BIT);
X  if (write (1, &c1, 1) != 1 || write (1, &c2, 1) != 1) {
X	fprintf (stderr, "\r%s: Can't write header\n", pname);
X	exit (-1);
X  }
X  Nout += 2;
X}
+ END-OF-FILE header.c
chmod 'u=rw,g=r,o=r' 'header.c'
set `wc -c 'header.c'`
count=$1
case $count in
1368)	:;;
*)	echo 'Bad character count in ''header.c' >&2
		echo 'Count should be 1368' >&2
esac
echo Extracting 'huffman.c'
sed 's/^X//' > 'huffman.c' << '+ END-OF-FILE ''huffman.c'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Huffman.c: huffman routines to get and put huffman codes.
X**	Note: If the Hencode is called for SWITCH codes with a codelength >
X**  	HUFFMAN_BITS, the actual code is used. This is mainly an optimalisation
X**  	for binary chunck's in the text. This could be replaced by dynamic
X**	huffman code. (See "Data Compression" AMC computing Surveys,
X**	Vol.19 No. 3 September 1987). I tryed modified BSTW, but that wasn't
X**	to good.
X*/
X
X#include "comic.h"
X#include "huffman.h"
X
X#define SWITCH 8		/* 4 Might do very well to. */
X
X/*
X** Include the auto generated tables.
X**	There is a big redundency in tables.h, Both encode and decode
X**	tables are included. (But the bit length per code would be innough
X**	but this would mean initializing a lot.)
X**	Ctab tables, have code, length pairs. The low length bits of code
X**	are the huffman code. Tree tables, have 0, 1 pairs. They point
X**	to the next pair or the code.
X*/
X#if OFFSET_BITS == 13
X# include "tables.h"
X#else 
X  error No tables.h for other than 13 bits.
X#endif
X
Xstatic struct ctab_s * ctab_tab [] = { ctab_char, ctab_off, ctab_len };
Xstatic struct tree_s * tree_tab [] = { tree_char, tree_off, tree_len };
Xstatic int Ntolong [3];		/* Ntolong for each table. */
X
X/*
X** Decend: decend down he tree.
X*/
Xstatic int decend (tree)
Xstruct tree_s *tree;
X{
X  int i = (HUFFMAN_SIZE * 2) - 2;
X
X  while (i >= HUFFMAN_SIZE) {
X	switch (getbit ()) {
X	  case EOF: 
X		fprintf (stderr, "\r%s: Unexpected EOF\n", pname);
X		exit (-1);
X	  case 0:
X		i = tree[i - HUFFMAN_SIZE]._0;
X		break;
X	  case 1:
X		i = tree[i - HUFFMAN_SIZE]._1;
X		break;
X	  default:
X		fprintf (stderr, "\r%s: Funny bit\n", pname);
X		exit (-1);
X	}
X  }
X  return i;
X}
X
X
X/*
X** Hinit: Get the propper huffman code tables.
X*/
Xvoid Hinit ()
X{
X  Ntolong [0] = 0;
X  Ntolong [1] = 0;
X  Ntolong [2] = 0;
X
X  /*
X  ** Read in tables if ness. (Version to come.)
X  */
X}
X
X
X/*
X** Hdecode: Get a int using a huffman tree.
X*/
Xint Hdecode (index)
Xint index;
X{
X  struct tree_s *tree = tree_tab [index];
X  struct ctab_s *ctab = ctab_tab [index];
X  int i;
X
X  if (Ntolong [index] > SWITCH) {
X	i = (int) getnbit (HUFFMAN_BITS);
X	if (ctab [i].length > HUFFMAN_BITS)
X		Ntolong [index] = SWITCH << 1;
X	else
X		Ntolong [index] -= 1;
X  }
X  else {
X	i = decend (tree);
X	if (ctab [i].length > HUFFMAN_BITS)
X		Ntolong [index] += 1;
X	else
X		Ntolong [index] = 0;
X  }
X  return i;
X}
X
X
X/*
X** Hcodelen: Return the length of the encoded word in bits.
X*/
Xint Hcodelen (index, c)
Xint index;
Xint c;
X{
X  return Ntolong [index] > SWITCH ? HUFFMAN_BITS : ctab_tab [index] [c].length;
X}
X
X/*
X** Hencode: ouput code i from code table ctab
X*/
Xvoid Hencode (index, i)
Xint index, i;
X{
X  struct ctab_s *ctab = ctab_tab [index];
X  int len = ctab [i].length;
X
X  if (Ntolong [index] > SWITCH) {
X	putnbit ((long)i, HUFFMAN_BITS);
X	if (len > HUFFMAN_BITS)
X		Ntolong [index] = SWITCH << 1;
X	else
X		Ntolong [index] -= 1;
X  }
X  else {
X	putnbit ((long)(ctab [i].code), len);
X	if (len > HUFFMAN_BITS)
X		Ntolong [index] += 1;
X	else
X		Ntolong [index] = 0;
X  }
X}
+ END-OF-FILE huffman.c
chmod 'u=rw,g=r,o=r' 'huffman.c'
set `wc -c 'huffman.c'`
count=$1
case $count in
3076)	:;;
*)	echo 'Bad character count in ''huffman.c' >&2
		echo 'Count should be 3076' >&2
esac
echo Extracting 'bits.h'
sed 's/^X//' > 'bits.h' << '+ END-OF-FILE ''bits.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Bits.h: Bit operations header file.
X*/
X
X/* Needs "comic.h" for _PROTOTYPE() */
X
Xvoid _PROTOTYPE( putnbit, (long __code, int __n)	);
Xint  _PROTOTYPE( getnbit, (int __n)			);
Xvoid _PROTOTYPE( putbit, (int __bit)			);
Xint  _PROTOTYPE( getbit, ()				);
Xvoid _PROTOTYPE( flush_bits, ()				);
Xvoid _PROTOTYPE( init_bits, ()				);
+ END-OF-FILE bits.h
chmod 'u=rw,g=r,o=r' 'bits.h'
set `wc -c 'bits.h'`
count=$1
case $count in
404)	:;;
*)	echo 'Bad character count in ''bits.h' >&2
		echo 'Count should be 404' >&2
esac
echo Extracting 'buffer.h'
sed 's/^X//' > 'buffer.h' << '+ END-OF-FILE ''buffer.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Buffer.h: functions for circular buffer menagement.
X*/
X
X/*
X** Global variables. Declared in `comic.c'
X*/
Xextern char Buff [BUFF_SIZE];	/* The circular Buffer. */
Xextern char *Bend;		/* Pointer to the last char in Buff. */
Xextern char *Blow_sent;		/* Pointer to the char befor Buff. */
Xextern char *Bp;		/* Pointer to unproccessed char. */
Xextern char *Binputend;		/* End of read ahead input. */
Xextern int  Bsize;		/* Size of the used part of the buffer. */
X#ifdef LINT
Xextern char *memset();		/* To shut up lint, a bit ;-( */
X#endif
X
X#define	Bsucc(p)                        /* pointer after p */\
X	((p) == Bend ? Buff : (p) + 1)
X
X#define	Bpred(p)                        /* pointer before p */\
X	((p) == Buff ? Bend : (p) - 1)
X
X#define Badd(p, n)			/* Add n to p, circular. */\
X	((p) + (n) - ((p) + (n) > Bend ? Bsize : 0))
X
X#define Bsub(p, n)			/* Substract n from p, circular. */\
X	((p) - (n) + ((p) < Buff + (n) ? Bsize : 0))
X
X#define Bdelta(p, q)			/* Return p - q circular. */\
X	(int)((p) - (q) + ((p) < (q) ? Bsize : 0))
X
X#define Blookupstart()			/* End of the lookup pair. */\
X	Bsub (Bp, NON_INPUT_SIZE)
X
X#define Bindex(p)			/* Index of pointer. */\
X	(index_t)((p) - Buff)
X
X#define Binit()				/* Clear the buffer. */\
X	(void)memset (Buff, '\0', Bsize)
+ END-OF-FILE buffer.h
chmod 'u=rw,g=r,o=r' 'buffer.h'
set `wc -c 'buffer.h'`
count=$1
case $count in
1339)	:;;
*)	echo 'Bad character count in ''buffer.h' >&2
		echo 'Count should be 1339' >&2
esac
echo Extracting 'comic.h'
sed 's/^X//' > 'comic.h' << '+ END-OF-FILE ''comic.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Comic.h: General include file for comic source files.
X*/
X
X#ifndef COMIC_H
X#define COMIC_H
X
X#ifdef DOS
X# include <fcntl.h>     /* Use O_BINARY by `setmode ()' in SM-DOS. */
X# include <io.h>	/* For `setmode()' to. */
X#endif
X#if __STDC__ && ! GCC
X# include <stdlib.h>
X#endif
X#include <assert.h>
X#include <stdio.h>
X
X/*
X** Compress constands.
X*/
X#define HUFFMAN_BITS	8	/* Huffman codes are 8 bits. */
X#define LENGTH_BITS	8	/* # of bits in length info. */
X#define OFFSET_BITS	13	/* # of bits in offset info. */
X#define PAIR_MAX	1	/* There are two pairs. */
X
X/*
X** If above are chainged, chainge these to!
X*/
X#define HUFFMAN_SIZE	256	/* Max for 8 bits. */
X#define LENGTH_SIZE	256	/* Max for 8 bits. */
X#define OFFSET_SIZE	8192	/* Max for 13 bits. */
X#define OFFSET_MIN	1	/* Minimum offset. */
X#define LENGTH_MIN	2	/* Minimum length. */
X#define OFFSET_MAX	(OFFSET_SIZE + OFFSET_MIN - 1)
X#define LENGTH_MAX	(LENGTH_SIZE + LENGTH_MIN - 1)
X#define INPUT_SIZE	(LENGTH_SIZE + PAIR_MAX + LENGTH_MIN)
X#define	BUFF_SIZE	(INPUT_SIZE + OFFSET_SIZE + OFFSET_MIN)
X#define BUFF_MAX	(BUFF_SIZE - 1)
X#define NON_INPUT_SIZE	(BUFF_SIZE - INPUT_SIZE)
X#define LOW_OFFSET_BITS	(OFFSET_BITS - HUFFMAN_BITS)
X
X/*
X** Index type is used for indexing the buffer and the hash tables.
X**
X** This type is added laters, so some int declarations should be index_t.
X*/
Xtypedef unsigned short index_t;
X#define INDEX_END	((index_t) BUFF_SIZE + 1)
X
X
X/*
X** Pairs are build of a start pointer and a length pointer.
X*/
Xtypedef struct pair {			/* Part descriptor type. */
X	char * start;			/* Pointer in the circular Buffer. */
X	int length;			/* Length of part. */
X} pair_t, *pair_p;
X
X/*
X** Global variables. Declared in `comic.c'
X*/
Xextern char *pname;		/* Name of the program. */
Xextern pair_p p0, p1;		/* Short hands. */
Xextern long Nin;		/* Total # of bytes read. */
Xextern long Nout;
Xextern int  v_flag;		/* Verbose flag == 1 if -v was given. */
X#ifdef DOS
Xextern int  a_flag;		/* Ascii flag == 1 if -a was given. */
X#endif
X
X/*
X** All global function prototypes.
X*/
X#ifndef _PROTOTYPE
X#  define _PROTOTYPE(func, args)	func ()
X#endif /* _PROTOTYPE */
X
Xvoid	_PROTOTYPE( putnbit, (long __code, int __n)		);
Xint	_PROTOTYPE( getinput, ()				);
Xvoid 	_PROTOTYPE( gettoken, (int __p0used)			);
Xvoid 	_PROTOTYPE( encode, ()					);
Xvoid 	_PROTOTYPE( decode, ()					);
X
X#endif /* COMIC_H */
+ END-OF-FILE comic.h
chmod 'u=rw,g=r,o=r' 'comic.h'
set `wc -c 'comic.h'`
count=$1
case $count in
2418)	:;;
*)	echo 'Bad character count in ''comic.h' >&2
		echo 'Count should be 2418' >&2
esac
echo Extracting 'hash.h'
sed 's/^X//' > 'hash.h' << '+ END-OF-FILE ''hash.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Hash.h: For speed sake, a (two dimensional) hash table is implemented
X** 	on top of the existing structure.
X**	The hashing goes as follows. For each character pair {c1, c2}
X**	there exists an index (at hash_tbl [H1 (c1), H2 (c2)]) containing
X**	the index of the first pair {d1, d2} in the buffer so that
X**	H1 (c1) == H1 (d1) and H2 (c2) == H2 (d2). Both Hs are functions
X**	ie. if H (c) != H (d) than c != d. The same index is used as an
X**	index to the index list, to find the next index. Again this index
X**	is used in both the buffer and the index list (next_list) etc. etc.
X**	The final index is INDEX_END. Defined in comic.h. There is alsow a
X**	index list pointing back, so the index list can be quickly updated.
X**	This leaves us with a double linked list like construction.
X*/
X
X/*
X** Hash.h needs comic.h for the index type (index_t) and some constands.
X*/
X
X#ifdef MINIX 
X# define H1_SIZE	64		/* Hash table size first char. */
X# define H2_SIZE	32		/* They have to be powers of 2! */
X#else
X# ifdef C89
X#  define H1_SIZE	64
X#  define H2_SIZE	32
X# else
X#  ifdef DOS
X#   define H1_SIZE	64
X#   define H2_SIZE	64
X#  else
X#   define H1_SIZE	256
X#   define H2_SIZE	256
X#  endif
X# endif
X#endif
X
X#define H1(i)	((index_t)(i) & (H1_SIZE -1))         /* Hash functions. */
X#define H2(i)	((index_t)(i) & (H2_SIZE -1))
X
X/*
X** The buffer index macros. (Look like the buffer pointer macros. ;-)
X*/
X
X#define Ipred(i)	/* Dec i circular. */\
X	(((i) == 0 ? BUFF_SIZE : (i)) - 1)
X
X#define Isucc(i)	/* Inc i circular. */\
X	((i) == BUFF_SIZE - 1 ? 0 : (i) + 1)
X
Xextern index_t *hash_tbl;			/* See hash.c. */
Xextern index_t next_list [BUFF_SIZE];
Xextern index_t back_list [BUFF_SIZE];
X
X#define hash_entry(i,j)	hash_tbl [H1 (i) + H1_SIZE * H2 (j)]
X
Xvoid _PROTOTYPE( hash_init, (void)			);
Xvoid _PROTOTYPE( hash_update, (void)			);
+ END-OF-FILE hash.h
chmod 'u=rw,g=r,o=r' 'hash.h'
set `wc -c 'hash.h'`
count=$1
case $count in
1894)	:;;
*)	echo 'Bad character count in ''hash.h' >&2
		echo 'Count should be 1894' >&2
esac
echo Extracting 'header.h'
sed 's/^X//' > 'header.h' << '+ END-OF-FILE ''header.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Header.h: Defines for the comic header bytes and file suffix.
X**	The first byte is a normal magic byte.
X**	The second byte is eighter 0xAX
X**	The X nibble (1/2byte) contains extra info.
X*/
X
X/*
X** First byte is plane magic.
X*/
X#define MAGIC1		(char)0x69	/* Magic number. */
X
X/*
X** Second bytes is half magic half flag.
X*/
X#define MAGIC2		(char)0x60	/* High part of 2d byte. */
X
X#define STATIC_BIT	(char)0x8	/* Use buildin Huffman tables. */
X#define DYNAMIC_BIT	(char)0x4	/* H. tables precead data. */
X#define SUFFIX_BIT	(char)0x2	/* Next three bytes are old suffix. */
X#define EXTEND_BIT	(char)0x1	/* More header data. */
X
X/*
X** Third byte indicates extra i/o-processing. EXTEND_BIT has to be set.
X*/
X#define EXTRA_EXTEND	(char)0x0	/* Extra extension bytes. */
X#define TRANSLATE	(char)0x1	/* Input was xlated. */
X
X/*
X** Note to assist dos, the first three chars after the header can be
X** the original suffix. The suffix bit indicates this.
X*/
X
X
X/*
X** Prototypes.
X*/
Xvoid _PROTOTYPE( put_magic, ()			);
Xint  _PROTOTYPE( magic_ok, ()			);
+ END-OF-FILE header.h
chmod 'u=rw,g=r,o=r' 'header.h'
set `wc -c 'header.h'`
count=$1
case $count in
1117)	:;;
*)	echo 'Bad character count in ''header.h' >&2
		echo 'Count should be 1117' >&2
esac
echo Extracting 'huffman.h'
sed 's/^X//' > 'huffman.h' << '+ END-OF-FILE ''huffman.h'
X/*
X** Part of the comic package. (p) Jan-Mark Wams 	(email: jms@cs.vu.nl)
X**
X** Huffman.h: types and routines for the huffman tables.
X*/
X
X/* Needs "comic.h" for _PROTOTYPE() */
X
X/*
X** Tree and code types.
X*/
Xtypedef long bitstr_t;
X
Xtypedef struct tree_s {
X	int _0, _1;
X} tree_t [];
X
Xtypedef struct ctab_s {
X	bitstr_t code;
X	char	 length; /* Hast to hold upto sizeof (bitstr_t) * 8 bits. */
X} ctab_t [];
X
X#define Hchar 0
X#define Hoff 1 
X#define Hlen 2
X
Xint	_PROTOTYPE( Hdecode, (int __treei)		);
Xvoid	_PROTOTYPE( Hencode, (int __ctabi, int __i)	);
Xint	_PROTOTYPE( Hcodelen, (int __ctabi, int __i)	);
Xvoid	_PROTOTYPE( Hinit,  ()                       	);
+ END-OF-FILE huffman.h
chmod 'u=rw,g=r,o=r' 'huffman.h'
set `wc -c 'huffman.h'`
count=$1
case $count in
653)	:;;
*)	echo 'Bad character count in ''huffman.h' >&2
		echo 'Count should be 653' >&2
esac
echo Extracting 'tables.h'
sed 's/^X//' > 'tables.h' << '+ END-OF-FILE ''tables.h'
X/*
X** Part of the comic package.
X**
X** Tables.h: Auto generated by comicgen.
X*/
X
Xctab_t ctab_char = {		/* {code, length} pairs */
X	{0x000054L,  9}, {0x0003B6L, 10}, {0x00067AL, 11}, {0x000242L, 10}, 
X	{0x0033DCL, 14}, {0x000D99L, 13}, {0x000D98L, 13}, {0x00076BL, 11}, 
X	{0x000CF6L, 12}, {0x000017L,  5}, {0x00002CL,  6}, {0x001977L, 14}, 
X	{0x0CF749L, 20}, {0x0001B6L, 10}, {0x0000AAL, 10}, {0x00013BL,  9}, 
X	{0x0006DEL, 12}, {0x0CF748L, 20}, {0x0006CFL, 12}, {0x001976L, 14}, 
X	{0x001975L, 14}, {0x000D97L, 13}, {0x00076AL, 11}, {0x000B4DL, 12}, 
X	{0x000D96L, 13}, {0x000B4CL, 12}, {0x001974L, 14}, {0x001973L, 14}, 
X	{0x000B4BL, 12}, {0x000B4AL, 12}, {0x000B49L, 12}, {0x001972L, 14}, 
X	{0x000008L,  5}, {0x00004FL,  7}, {0x00001CL,  6}, {0x000120L,  9}, 
X	{0x0003B4L, 10}, {0x000031L,  8}, {0x000075L,  7}, {0x000028L,  6}, 
X	{0x00001AL,  5}, {0x000010L,  5}, {0x00001CL,  7}, {0x000030L,  8}, 
X	{0x000003L,  6}, {0x000026L,  6}, {0x000031L,  6}, {0x00003AL,  7}, 
X	{0x000015L,  6}, {0x000002L,  6}, {0x00000BL,  6}, {0x000001L,  7}, 
X	{0x00003EL,  7}, {0x000054L,  7}, {0x000074L,  7}, {0x000061L,  7}, 
X	{0x000055L,  7}, {0x000013L,  8}, {0x00001DL,  7}, {0x00000FL,  6}, 
X	{0x000077L,  7}, {0x000029L,  7}, {0x000056L,  7}, {0x000038L,  9}, 
X	{0x000012L,  8}, {0x000014L,  7}, {0x00002BL,  8}, {0x00002FL,  7}, 
X	{0x00006EL,  7}, {0x000013L,  7}, {0x000066L,  7}, {0x000051L,  8}, 
X	{0x0000B5L,  8}, {0x000045L,  7}, {0x00019FL,  9}, {0x0000A1L,  9}, 
X	{0x000037L,  7}, {0x00006FL,  7}, {0x000057L,  7}, {0x00003DL,  7}, 
X	{0x000060L,  7}, {0x000156L, 11}, {0x000044L,  7}, {0x00000FL,  7}, 
X	{0x00002EL,  7}, {0x00005BL,  7}, {0x0000C9L,  9}, {0x00009CL,  8}, 
X	{0x0000DAL,  9}, {0x0000C8L,  9}, {0x00013AL,  9}, {0x00003CL,  7}, 
X	{0x000039L,  9}, {0x000019L,  7}, {0x00033CL, 10}, {0x000036L,  6}, 
X	{0x000D95L, 13}, {0x00000DL,  6}, {0x000032L,  6}, {0x00001CL,  5}, 
X	{0x000008L,  6}, {0x00001FL,  5}, {0x000016L,  6}, {0x000008L,  7}, 
X	{0x000033L,  7}, {0x000006L,  6}, {0x0000CEL,  8}, {0x00003BL,  7}, 
X	{0x000025L,  6}, {0x000023L,  6}, {0x000005L,  6}, {0x000001L,  6}, 
X	{0x000018L,  6}, {0x000168L,  9}, {0x00001AL,  6}, {0x000009L,  5}, 
X	{0x00001EL,  5}, {0x000029L,  6}, {0x00003FL,  7}, {0x000012L,  7}, 
X	{0x00001DL,  8}, {0x000000L,  7}, {0x0000ECL,  8}, {0x000091L,  8}, 
X	{0x0000A0L,  9}, {0x000049L,  7}, {0x0005A7L, 11}, {0x0CF747L, 20}, 
X	{0x000B48L, 12}, {0x0CF746L, 20}, {0x001971L, 14}, {0x0CF745L, 20}, 
X	{0x001970L, 14}, {0x0CF744L, 20}, {0x00196FL, 14}, {0x0CF743L, 20}, 
X	{0x000D94L, 13}, {0x0CF742L, 20}, {0x0CF741L, 20}, {0x0CF740L, 20}, 
X	{0x067BBFL, 19}, {0x00196EL, 14}, {0x067BBEL, 19}, {0x067BBDL, 19}, 
X	{0x00196DL, 14}, {0x067BBCL, 19}, {0x067BBBL, 19}, {0x067BBAL, 19}, 
X	{0x000D93L, 13}, {0x067BB9L, 19}, {0x00196CL, 14}, {0x067BB8L, 19}, 
X	{0x067BB7L, 19}, {0x00196BL, 14}, {0x000D92L, 13}, {0x00196AL, 14}, 
X	{0x001969L, 14}, {0x001968L, 14}, {0x001967L, 14}, {0x001966L, 14}, 
X	{0x001965L, 14}, {0x000D91L, 13}, {0x000D90L, 13}, {0x000D8FL, 13}, 
X	{0x0003B7L, 10}, {0x000D8EL, 13}, {0x000D8DL, 13}, {0x001964L, 14}, 
X	{0x001963L, 14}, {0x000D8CL, 13}, {0x001962L, 14}, {0x000D8BL, 13}, 
X	{0x001961L, 14}, {0x000D8AL, 13}, {0x001960L, 14}, {0x00195FL, 14}, 
X	{0x00090FL, 12}, {0x000D89L, 13}, {0x00195EL, 14}, {0x000D88L, 13}, 
X	{0x00195DL, 14}, {0x00090EL, 12}, {0x00195CL, 14}, {0x000D87L, 13}, 
X	{0x00195BL, 14}, {0x00195AL, 14}, {0x001959L, 14}, {0x000D86L, 13}, 
X	{0x067BB6L, 19}, {0x000D85L, 13}, {0x067BB5L, 19}, {0x001958L, 14}, 
X	{0x001957L, 14}, {0x00036EL, 11}, {0x000D84L, 13}, {0x001956L, 14}, 
X	{0x001955L, 14}, {0x000D83L, 13}, {0x001954L, 14}, {0x001953L, 14}, 
X	{0x067BB4L, 19}, {0x001952L, 14}, {0x001951L, 14}, {0x001950L, 14}, 
X	{0x00194FL, 14}, {0x00194EL, 14}, {0x067BB3L, 19}, {0x00194DL, 14}, 
X	{0x067BB2L, 19}, {0x00194CL, 14}, {0x067BB1L, 19}, {0x000D82L, 13}, 
X	{0x067BB0L, 19}, {0x00194BL, 14}, {0x067BAFL, 19}, {0x00194AL, 14}, 
X	{0x067BAEL, 19}, {0x001949L, 14}, {0x067BADL, 19}, {0x001948L, 14}, 
X	{0x067BACL, 19}, {0x001947L, 14}, {0x067BABL, 19}, {0x001946L, 14}, 
X	{0x067BAAL, 19}, {0x001945L, 14}, {0x001944L, 14}, {0x001943L, 14}, 
X	{0x001942L, 14}, {0x001941L, 14}, {0x067BA9L, 19}, {0x001940L, 14}, 
X	{0x067BA8L, 19}, {0x000D81L, 13}, {0x067BA7L, 19}, {0x000D80L, 13}, 
X	{0x067BA6L, 19}, {0x0006CEL, 12}, {0x000ABFL, 14}, {0x000ABEL, 14}, 
X	{0x000ABDL, 14}, {0x00090DL, 12}, {0x000ABCL, 14}, {0x0006CDL, 12}, 
X	{0x067BA5L, 19}, {0x000CBFL, 13}, {0x000ABBL, 14}, {0x000CBEL, 13}, 
X	{0x000ABAL, 14}, {0x000CBDL, 13}, {0x000AB9L, 14}, {0x00090CL, 12}, 
X	{0x000AB8L, 14}, {0x000CBCL, 13}, {0x0019EFL, 13}, {0x0006DFL, 12}
X};
X
Xtree_t tree_char = {		/* {link 0, link 1} pairs. */
X	{17 ,  12}, {129, 127}, {133, 131}, {137, 135}, 
X	{139, 138}, {142, 140}, {145, 143}, {147, 146}, 
X	{151, 149}, {188, 152}, {200, 190}, {208, 206}, 
X	{212, 210}, {216, 214}, {220, 218}, {224, 222}, 
X	{232, 230}, {236, 234}, {256, 244}, {258, 257}, 
X	{260, 259}, {262, 261}, {264, 263}, {266, 265}, 
X	{268, 267}, {270, 269}, {272, 271}, {274, 273}, 
X	{276, 275}, {278, 277}, {280, 279}, {282, 281}, 
X	{284, 283}, {286, 285}, {288, 287}, {290, 289}, 
X	{4  , 291}, {19 ,  11}, {26 ,  20}, {31 ,  27}, 
X	{132, 130}, {141, 134}, {150, 144}, {155, 153}, 
X	{157, 156}, {159, 158}, {167, 160}, {170, 168}, 
X	{174, 172}, {178, 175}, {182, 180}, {185, 184}, 
X	{191, 186}, {195, 192}, {198, 196}, {201, 199}, 
X	{203, 202}, {205, 204}, {209, 207}, {215, 213}, 
X	{219, 217}, {223, 221}, {226, 225}, {228, 227}, 
X	{231, 229}, {239, 238}, {242, 240}, {248, 246}, 
X	{252, 250}, {292, 254}, {6  ,   5}, {24 ,  21}, 
X	{136,  96}, {154, 148}, {162, 161}, {165, 163}, 
X	{169, 166}, {173, 171}, {179, 177}, {187, 183}, 
X	{194, 189}, {211, 197}, {235, 233}, {247, 245}, 
X	{253, 249}, {294, 293}, {296, 295}, {298, 297}, 
X	{300, 299}, {302, 301}, {304, 303}, {306, 305}, 
X	{308, 307}, {310, 309}, {312, 311}, {314, 313}, 
X	{316, 315}, {318, 317}, {320, 319}, {322, 321}, 
X	{324, 323}, {8  , 325}, {25 ,  23}, {29 ,  28}, 
X	{128,  30}, {181, 176}, {251, 241}, {16 , 255}, 
X	{237,  18}, {326, 243}, {328, 327}, {330, 329}, 
X	{332, 331}, {334, 333}, {336, 335}, {338, 337}, 
X	{340, 339}, {342, 341}, {344, 343}, {346, 345}, 
X	{348, 347}, {350, 349}, {352, 351}, {354, 353}, 
X	{356, 355}, {22 ,   7}, {2  , 357}, {358, 126}, 
X	{360, 359}, {362, 361}, {193, 363}, {365, 364}, 
X	{367, 366}, {369, 368}, {371, 370}, {373, 372}, 
X	{375, 374}, {377, 376}, {379, 378}, {81 , 380}, 
X	{1  , 164}, {36 , 381}, {94 , 382}, {384, 383}, 
X	{3  , 385}, {13 , 386}, {388, 387}, {390, 389}, 
X	{392, 391}, {394, 393}, {14 , 395}, {397, 396}, 
X	{398,  74}, {113, 399}, {90 ,  15}, {35 , 400}, 
X	{88 , 401}, {403, 402}, {405, 404}, {89 ,  86}, 
X	{124,  75}, {0  , 406}, {63 ,  92}, {122, 407}, 
X	{106, 408}, {409,  72}, {87 , 410}, {411, 123}, 
X	{413, 412}, {415, 414}, {416,  71}, {43 ,  37}, 
X	{417,  66}, {418, 120}, {64 ,  57}, {419,  60}, 
X	{54 ,  38}, {68 ,  77}, {70 , 420}, {80 ,  55}, 
X	{421,  85}, {62 ,  78}, {53 ,  56}, {422,  33}, 
X	{423, 125}, {82 ,  73}, {52 , 118}, {91 ,  79}, 
X	{47 , 107}, {424,  76}, {425, 104}, {84 ,  67}, 
X	{426,  61}, {42 ,  58}, {427,  93}, {65 , 428}, 
X	{119,  69}, {429,  83}, {103, 430}, {121,  51}, 
X	{432, 431}, {95 , 433}, {98 , 434}, {435,  46}, 
X	{10 , 436}, {438, 437}, {39 , 117}, {45 , 439}, 
X	{440, 108}, {441, 109}, {443, 442}, {34 , 444}, 
X	{114, 445}, {112, 446}, {102, 447}, {448,  48}, 
X	{449,  59}, {450,  97}, {451,  50}, {100, 452}, 
X	{105, 453}, {454, 110}, {49 ,  44}, {455, 111}, 
X	{116, 101}, {99 , 456}, {40 , 457}, {459, 458}, 
X	{460,   9}, {462, 461}, {464, 463}, {41 , 465}, 
X	{467, 466}, {469, 468}, {471, 470}, {32 , 115}, 
X	{473, 472}, {475, 474}, {477, 476}, {479, 478}, 
X	{481, 480}, {483, 482}, {485, 484}, {487, 486}, 
X	{489, 488}, {491, 490}, {493, 492}, {495, 494}, 
X	{497, 496}, {499, 498}, {501, 500}, {503, 502}, 
X	{505, 504}, {507, 506}, {509, 508}
X};
X
Xctab_t ctab_len = {		/* {code, length} pairs */
X	{0x000002L,  3}, {0x000000L,  3}, {0x000003L,  3}, {0x000005L,  3}, 
X	{0x000006L,  3}, {0x000003L,  4}, {0x000009L,  4}, {0x00000FL,  4}, 
X	{0x000005L,  5}, {0x00001CL,  5}, {0x000008L,  6}, {0x000021L,  6}, 
X	{0x00003AL,  6}, {0x000013L,  7}, {0x000041L,  7}, {0x000045L,  7}, 
X	{0x000076L,  7}, {0x000024L,  8}, {0x00008CL,  8}, {0x000088L,  8}, 
X	{0x00008EL,  8}, {0x0000EEL,  8}, {0x00004AL,  9}, {0x000100L,  9}, 
X	{0x000102L,  9}, {0x000101L,  9}, {0x00011EL,  9}, {0x000206L, 10}, 
X	{0x000225L, 10}, {0x000207L, 10}, {0x000235L, 10}, {0x0001DFL,  9}, 
X	{0x000237L, 10}, {0x00047DL, 11}, {0x0003BDL, 10}, {0x000448L, 11}, 
X	{0x000234L, 10}, {0x00044CL, 11}, {0x00012EL, 11}, {0x00047CL, 11}, 
X	{0x00046DL, 11}, {0x000258L, 12}, {0x000779L, 11}, {0x000778L, 11}, 
X	{0x00025EL, 12}, {0x0008D9L, 12}, {0x259D41L, 24}, {0x0004BEL, 13}, 
X	{0x000892L, 12}, {0x0008D8L, 12}, {0x00089FL, 12}, {0x000966L, 14}, 
X	{0x0008FCL, 12}, {0x0004B7L, 13}, {0x0004B6L, 13}, {0x0011FFL, 13}, 
X	{0x00113DL, 13}, {0x0011FEL, 13}, {0x259D40L, 24}, {0x0011FDL, 13}, 
X	{0x0004B5L, 13}, {0x002275L, 14}, {0x0011FCL, 13}, {0x00259CL, 16}, 
X	{0x002274L, 14}, {0x259D3FL, 24}, {0x002273L, 14}, {0x002272L, 14}, 
X	{0x002271L, 14}, {0x002270L, 14}, {0x00226FL, 14}, {0x0004B4L, 13}, 
X	{0x00226EL, 14}, {0x00226DL, 14}, {0x259D3EL, 24}, {0x0044D1L, 15}, 
X	{0x00226CL, 14}, {0x0004B2L, 13}, {0x00113CL, 13}, {0x00113BL, 13}, 
X	{0x0044D0L, 15}, {0x00449FL, 15}, {0x00449EL, 15}, {0x0011FBL, 13}, 
X	{0x259D3DL, 24}, {0x259D3CL, 24}, {0x259D3BL, 24}, {0x259D3AL, 24}, 
X	{0x00226BL, 14}, {0x259D39L, 24}, {0x00449DL, 15}, {0x00449CL, 15}, 
X	{0x00449BL, 15}, {0x00449AL, 15}, {0x259D38L, 24}, {0x00226AL, 14}, 
X	{0x0011FAL, 13}, {0x004499L, 15}, {0x259D37L, 24}, {0x259D36L, 24}, 
X	{0x004498L, 15}, {0x002269L, 14}, {0x259D35L, 24}, {0x259D34L, 24}, 
X	{0x259D33L, 24}, {0x259D32L, 24}, {0x259D31L, 24}, {0x259D30L, 24}, 
X	{0x259D2FL, 24}, {0x259D2EL, 24}, {0x259D2DL, 24}, {0x259D2CL, 24}, 
X	{0x259D2BL, 24}, {0x259D2AL, 24}, {0x259D29L, 24}, {0x0012FFL, 15}, 
X	{0x259D28L, 24}, {0x259D27L, 24}, {0x259D26L, 24}, {0x259D25L, 24}, 
X	{0x259D24L, 24}, {0x259D23L, 24}, {0x259D22L, 24}, {0x259D21L, 24}, 
X	{0x259D20L, 24}, {0x259D1FL, 24}, {0x0012FEL, 15}, {0x259D1EL, 24}, 
X	{0x259D1DL, 24}, {0x259D1CL, 24}, {0x259D1BL, 24}, {0x259D1AL, 24}, 
X	{0x259D19L, 24}, {0x259D18L, 24}, {0x259D17L, 24}, {0x259D16L, 24}, 
X	{0x259D15L, 24}, {0x0012FDL, 15}, {0x259D14L, 24}, {0x259D13L, 24}, 
X	{0x259D12L, 24}, {0x259D11L, 24}, {0x259D10L, 24}, {0x259D0FL, 24}, 
X	{0x259D0EL, 24}, {0x259D0DL, 24}, {0x259D0CL, 24}, {0x259D0BL, 24}, 
X	{0x259D0AL, 24}, {0x259D09L, 24}, {0x259D08L, 24}, {0x259D07L, 24}, 
X	{0x259D06L, 24}, {0x259D05L, 24}, {0x0012FCL, 15}, {0x259D04L, 24}, 
X	{0x259D03L, 24}, {0x259D02L, 24}, {0x259D01L, 24}, {0x259D00L, 24}, 
X	{0x12CEFFL, 23}, {0x12CEFEL, 23}, {0x12CEFDL, 23}, {0x12CEFCL, 23}, 
X	{0x12CEFBL, 23}, {0x12CEFAL, 23}, {0x12CEF9L, 23}, {0x12CEF8L, 23}, 
X	{0x12CEF7L, 23}, {0x12CEF6L, 23}, {0x12CEF5L, 23}, {0x0012CFL, 15}, 
X	{0x12CEF4L, 23}, {0x12CEF3L, 23}, {0x12CEF2L, 23}, {0x12CEF1L, 23}, 
X	{0x12CEF0L, 23}, {0x12CEEFL, 23}, {0x12CEEEL, 23}, {0x12CEEDL, 23}, 
X	{0x12CEECL, 23}, {0x12CEEBL, 23}, {0x12CEEAL, 23}, {0x12CEE9L, 23}, 
X	{0x12CEE8L, 23}, {0x12CEE7L, 23}, {0x12CEE6L, 23}, {0x12CEE5L, 23}, 
X	{0x12CEE4L, 23}, {0x12CEE3L, 23}, {0x12CEE2L, 23}, {0x12CEE1L, 23}, 
X	{0x12CEE0L, 23}, {0x12CEDFL, 23}, {0x12CEDEL, 23}, {0x12CEDDL, 23}, 
X	{0x12CEDCL, 23}, {0x12CEDBL, 23}, {0x12CEDAL, 23}, {0x12CED9L, 23}, 
X	{0x12CED8L, 23}, {0x12CED7L, 23}, {0x12CED6L, 23}, {0x12CED5L, 23}, 
X	{0x12CED4L, 23}, {0x12CED3L, 23}, {0x12CED2L, 23}, {0x12CED1L, 23}, 
X	{0x12CED0L, 23}, {0x12CECFL, 23}, {0x12CECEL, 23}, {0x12CECDL, 23}, 
X	{0x12CECCL, 23}, {0x12CECBL, 23}, {0x12CECAL, 23}, {0x12CEC9L, 23}, 
X	{0x12CEC8L, 23}, {0x12CEC7L, 23}, {0x12CEC6L, 23}, {0x12CEC5L, 23}, 
X	{0x12CEC4L, 23}, {0x12CEC3L, 23}, {0x12CEC2L, 23}, {0x12CEC1L, 23}, 
X	{0x12CEC0L, 23}, {0x12CEBFL, 23}, {0x12CEBEL, 23}, {0x12CEBDL, 23}, 
X	{0x12CEBCL, 23}, {0x12CEBBL, 23}, {0x12CEBAL, 23}, {0x12CEB9L, 23}, 
X	{0x12CEB8L, 23}, {0x12CEB7L, 23}, {0x12CEB6L, 23}, {0x12CEB5L, 23}, 
X	{0x12CEB4L, 23}, {0x12CEB3L, 23}, {0x12CEB2L, 23}, {0x12CEB1L, 23}, 
X	{0x12CEB0L, 23}, {0x12CEAFL, 23}, {0x12CEAEL, 23}, {0x12CEADL, 23}, 
X	{0x12CEACL, 23}, {0x12CEABL, 23}, {0x12CEAAL, 23}, {0x12CEA9L, 23}, 
X	{0x12CEA8L, 23}, {0x12CEA7L, 23}, {0x12CEA6L, 23}, {0x12CEA5L, 23}, 
X	{0x12CEA4L, 23}, {0x12CEA3L, 23}, {0x12CEA2L, 23}, {0x12CEA1L, 23}
X};
X
Xtree_t tree_len = {		/* {link 0, link 1} pairs. */
X	{58 ,  46}, {74 ,  65}, {85 ,  84}, {87 ,  86}, 
X	{94 ,  89}, {99 ,  98}, {103, 102}, {105, 104}, 
X	{107, 106}, {109, 108}, {111, 110}, {113, 112}, 
X	{116, 114}, {118, 117}, {120, 119}, {122, 121}, 
X	{124, 123}, {127, 125}, {129, 128}, {131, 130}, 
X	{133, 132}, {135, 134}, {138, 136}, {140, 139}, 
X	{142, 141}, {144, 143}, {146, 145}, {148, 147}, 
X	{150, 149}, {152, 151}, {155, 153}, {157, 156}, 
X	{159, 158}, {161, 160}, {163, 162}, {165, 164}, 
X	{167, 166}, {169, 168}, {172, 170}, {174, 173}, 
X	{176, 175}, {178, 177}, {180, 179}, {182, 181}, 
X	{184, 183}, {186, 185}, {188, 187}, {190, 189}, 
X	{192, 191}, {194, 193}, {196, 195}, {198, 197}, 
X	{200, 199}, {202, 201}, {204, 203}, {206, 205}, 
X	{208, 207}, {210, 209}, {212, 211}, {214, 213}, 
X	{216, 215}, {218, 217}, {220, 219}, {222, 221}, 
X	{224, 223}, {226, 225}, {228, 227}, {230, 229}, 
X	{232, 231}, {234, 233}, {236, 235}, {238, 237}, 
X	{240, 239}, {242, 241}, {244, 243}, {246, 245}, 
X	{248, 247}, {250, 249}, {252, 251}, {254, 253}, 
X	{256, 255}, {258, 257}, {260, 259}, {262, 261}, 
X	{264, 263}, {266, 265}, {268, 267}, {270, 269}, 
X	{272, 271}, {274, 273}, {276, 275}, {278, 277}, 
X	{280, 279}, {282, 281}, {284, 283}, {286, 285}, 
X	{288, 287}, {290, 289}, {292, 291}, {294, 293}, 
X	{296, 295}, {298, 297}, {300, 299}, {302, 301}, 
X	{304, 303}, {306, 305}, {308, 307}, {310, 309}, 
X	{312, 311}, {314, 313}, {316, 315}, {318, 317}, 
X	{320, 319}, {322, 321}, {324, 323}, {326, 325}, 
X	{328, 327}, {330, 329}, {332, 331}, {334, 333}, 
X	{336, 335}, {338, 337}, {340, 339}, {342, 341}, 
X	{344, 343}, {346, 345}, {348, 347}, {350, 349}, 
X	{352, 351}, {354, 353}, {356, 355}, {358, 357}, 
X	{360, 359}, {362, 361}, {364, 363}, {366, 365}, 
X	{368, 367}, {370, 369}, {372, 371}, {374, 373}, 
X	{376, 375}, {378, 377}, {380, 379}, {382, 381}, 
X	{384, 383}, {386, 385}, {388, 387}, {390, 389}, 
X	{392, 391}, {394, 393}, {396, 395}, {398, 397}, 
X	{400, 399}, {402, 401}, {404, 403}, {406, 405}, 
X	{408, 407}, {410, 409}, {412, 411}, {414, 413}, 
X	{63 , 415}, {80 ,  75}, {82 ,  81}, {91 ,  90}, 
X	{93 ,  92}, {100,  97}, {126, 115}, {154, 137}, 
X	{416, 171}, {64 ,  61}, {67 ,  66}, {69 ,  68}, 
X	{72 ,  70}, {76 ,  73}, {95 ,  88}, {417, 101}, 
X	{419, 418}, {421, 420}, {423, 422}, {51 , 424}, 
X	{57 ,  55}, {62 ,  59}, {96 ,  83}, {78 ,  56}, 
X	{425,  79}, {427, 426}, {429, 428}, {431, 430}, 
X	{433, 432}, {47 , 434}, {54 ,  53}, {71 ,  60}, 
X	{77 , 435}, {437, 436}, {52 , 438}, {49 ,  45}, 
X	{439,  50}, {441, 440}, {443, 442}, {48 , 444}, 
X	{44 , 445}, {447, 446}, {41 , 448}, {43 ,  42}, 
X	{450, 449}, {39 ,  33}, {451,  40}, {453, 452}, 
X	{37 , 454}, {35 , 455}, {38 , 456}, {458, 457}, 
X	{459,  34}, {461, 460}, {462,  32}, {36 ,  30}, 
X	{464, 463}, {465,  28}, {27 ,  29}, {467, 466}, 
X	{468,  31}, {26 , 469}, {471, 470}, {473, 472}, 
X	{24 , 474}, {23 ,  25}, {22 , 475}, {21 , 476}, 
X	{20 , 477}, {18 , 478}, {19 , 479}, {481, 480}, 
X	{17 , 482}, {16 , 483}, {485, 484}, {486,  15}, 
X	{487,  14}, {488,  13}, {12 , 489}, {491, 490}, 
X	{492,  11}, {10 , 493}, {9  , 494}, {496, 495}, 
X	{497,   8}, {498,   7}, {499,   6}, {500,   5}, 
X	{4  , 501}, {502,   3}, {0  ,   2}, {1  , 503}, 
X	{505, 504}, {507, 506}, {509, 508}
X};
X
Xctab_t ctab_off = {		/* {code, length} pairs */
X	{0x000007L,  3}, {0x000003L,  4}, {0x00000CL,  4}, {0x00000AL,  5}, 
X	{0x000012L,  5}, {0x00001BL,  5}, {0x000008L,  6}, {0x000010L,  6}, 
X	{0x00001CL,  6}, {0x00001FL,  6}, {0x000028L,  6}, {0x000008L,  7}, 
X	{0x000035L,  6}, {0x000003L,  7}, {0x00000BL,  7}, {0x00002FL,  6}, 
X	{0x00000EL,  7}, {0x000024L,  7}, {0x000026L,  7}, {0x00003AL,  7}, 
X	{0x00003CL,  7}, {0x000040L,  7}, {0x00004EL,  7}, {0x000045L,  7}, 
X	{0x000005L,  8}, {0x000057L,  7}, {0x00005AL,  7}, {0x000003L,  8}, 
X	{0x00000CL,  8}, {0x00002AL,  8}, {0x00001FL,  8}, {0x000002L,  8}, 
X	{0x00000AL,  8}, {0x00004CL,  7}, {0x000009L,  8}, {0x00002CL,  8}, 
X	{0x00004FL,  8}, {0x000019L,  8}, {0x000065L,  8}, {0x000089L,  8}, 
X	{0x000087L,  8}, {0x000029L,  8}, {0x00002FL,  8}, {0x00008DL,  8}, 
X	{0x00006BL,  8}, {0x000063L,  8}, {0x00006DL,  8}, {0x00005AL,  8}, 
X	{0x000085L,  8}, {0x000060L,  8}, {0x00005CL,  8}, {0x00009BL,  8}, 
X	{0x0000A5L,  8}, {0x00006FL,  8}, {0x0000A4L,  8}, {0x000083L,  8}, 
X	{0x0000ACL,  8}, {0x000084L,  8}, {0x00008EL,  8}, {0x00009AL,  8}, 
X	{0x0000D2L,  8}, {0x0000BBL,  8}, {0x00002BL,  9}, {0x0000ABL,  8}, 
X	{0x000017L,  9}, {0x0000BAL,  8}, {0x0000AAL,  8}, {0x000035L,  9}, 
X	{0x0000A8L,  8}, {0x000016L,  9}, {0x0000B9L,  8}, {0x000008L,  9}, 
X	{0x00003DL,  9}, {0x00008AL,  9}, {0x000026L,  9}, {0x000009L,  9}, 
X	{0x0000B8L,  8}, {0x00001DL,  9}, {0x000000L,  9}, {0x0000B7L,  8}, 
X	{0x00002AL,  9}, {0x00005DL,  9}, {0x000095L,  9}, {0x000050L,  9}, 
X	{0x00004AL,  9}, {0x0000BFL,  9}, {0x00004FL,  9}, {0x0000BBL,  9}, 
X	{0x00008DL,  9}, {0x00004EL,  9}, {0x00003CL,  9}, {0x00009CL,  9}, 
X	{0x0000CFL,  9}, {0x0000C5L,  9}, {0x000057L,  9}, {0x000088L,  9}, 
X	{0x0000D8L,  9}, {0x000037L,  9}, {0x00014FL,  9}, {0x000056L,  9}, 
X	{0x000094L,  9}, {0x000051L,  9}, {0x0000B0L,  9}, {0x0000CEL,  9}, 
X	{0x00005CL,  9}, {0x0000F7L,  9}, {0x000097L,  9}, {0x0000DDL,  9}, 
X	{0x0000D5L,  9}, {0x0000D4L,  9}, {0x00008CL,  9}, {0x0000B6L,  9}, 
X	{0x0000F6L,  9}, {0x0000D3L,  9}, {0x0000BEL,  9}, {0x000118L,  9}, 
X	{0x00016CL,  9}, {0x0000D2L,  9}, {0x0000BDL,  9}, {0x000023L, 10}, 
X	{0x0000DCL,  9}, {0x000105L,  9}, {0x000167L,  9}, {0x0000F5L,  9}, 
X	{0x000111L,  9}, {0x00004BL, 10}, {0x0000F4L,  9}, {0x0000C4L,  9}, 
X	{0x00013EL,  9}, {0x0000C9L,  9}, {0x0000CDL,  9}, {0x00004AL, 10}, 
X	{0x0000C3L,  9}, {0x00011FL,  9}, {0x00014EL,  9}, {0x000167L, 10}, 
X	{0x0001A1L,  9}, {0x000153L,  9}, {0x000119L,  9}, {0x0000EDL,  9}, 
X	{0x000039L, 10}, {0x00009BL, 10}, {0x0000D1L,  9}, {0x000163L,  9}, 
X	{0x0000B7L, 10}, {0x000162L,  9}, {0x000052L, 10}, {0x000152L,  9}, 
X	{0x000051L, 10}, {0x000068L, 10}, {0x000038L, 10}, {0x0000BCL,  9}, 
X	{0x000037L, 10}, {0x00014DL,  9}, {0x00013DL,  9}, {0x000007L, 10}, 
X	{0x00010CL,  9}, {0x000161L,  9}, {0x000049L, 10}, {0x000006L, 10}, 
X	{0x00011EL,  9}, {0x00006DL, 10}, {0x000160L,  9}, {0x0001A6L,  9}, 
X	{0x000104L,  9}, {0x000166L,  9}, {0x000048L, 10}, {0x0001A3L,  9}, 
X	{0x00014CL,  9}, {0x00015BL,  9}, {0x000165L,  9}, {0x000036L, 10}, 
X	{0x000063L, 10}, {0x0001A0L,  9}, {0x000005L, 10}, {0x000164L,  9}, 
X	{0x000093L, 10}, {0x000022L, 10}, {0x000110L,  9}, {0x00006CL, 10}, 
X	{0x000004L, 10}, {0x00013CL,  9}, {0x000003L, 10}, {0x00003FL, 10}, 
X	{0x000002L, 10}, {0x0001A2L,  9}, {0x00009AL, 10}, {0x000035L, 10}, 
X	{0x000116L, 10}, {0x0001A7L,  9}, {0x00013FL,  9}, {0x000050L, 10}, 
X	{0x00004FL, 10}, {0x000113L, 10}, {0x00012CL, 10}, {0x000092L, 10}, 
X	{0x000034L, 10}, {0x000175L, 10}, {0x000166L, 10}, {0x000091L, 10}, 
X	{0x000099L, 10}, {0x0001D8L, 10}, {0x00003EL, 10}, {0x000112L, 10}, 
X	{0x0000B6L, 10}, {0x000190L, 10}, {0x0001A0L, 10}, {0x00004EL, 10}, 
X	{0x00013AL, 10}, {0x00015AL,  9}, {0x0001B3L, 10}, {0x00021BL, 10}, 
X	{0x000165L, 10}, {0x000062L, 10}, {0x000098L, 10}, {0x000097L, 10}, 
X	{0x000021L, 10}, {0x000069L, 10}, {0x000061L, 10}, {0x000164L, 10}, 
X	{0x00011FL, 10}, {0x000163L, 10}, {0x000174L, 10}, {0x00012DL, 10}, 
X	{0x0001B2L, 10}, {0x000096L, 10}, {0x00011EL, 10}, {0x00011DL, 10}, 
X	{0x0001A1L, 10}, {0x000090L, 10}, {0x000199L, 10}, {0x00003DL, 10}, 
X	{0x0000B5L, 10}, {0x000162L, 10}, {0x0001DFL, 10}, {0x00016FL, 10}, 
X	{0x000185L, 10}, {0x00003CL, 10}, {0x0001DEL, 10}, {0x00011CL, 10}, 
X	{0x00013BL, 10}, {0x000184L, 10}, {0x0002DBL, 10}, {0x000198L, 10}, 
X	{0x00021AL, 10}, {0x0000B4L, 10}, {0x0002DAL, 10}, {0x000060L, 10}, 
X	{0x0001DDL, 10}, {0x0001DCL, 10}, {0x0001D9L, 10}, {0x000053L, 10}, 
X	{0x000117L, 10}, {0x000020L, 10}, {0x000191L, 10}, {0x00016EL, 10}
X};
X
Xtree_t tree_off = {		/* {link 0, link 1} pairs. */
X	{246, 242}, {244, 211}, {238, 234}, {249, 248}, 
X	{201, 250}, {224, 210}, {206, 228}, {243, 230}, 
X	{205, 254}, {241, 236}, {222, 197}, {255, 235}, 
X	{198, 135}, {219, 212}, {233, 221}, {208, 240}, 
X	{194, 223}, {226, 220}, {239, 227}, {188, 252}, 
X	{203, 193}, {204, 144}, {245, 232}, {186, 141}, 
X	{214, 200}, {225, 215}, {195, 176}, {229, 199}, 
X	{179, 161}, {149, 217}, {213, 172}, {247, 218}, 
X	{146, 251}, {191, 148}, {207, 192}, {131, 125}, 
X	{166, 158}, {202, 183}, {237, 231}, {150, 140}, 
X	{171, 152}, {196, 187}, {177, 119}, {253, 216}, 
X	{159, 155}, {180, 174}, {184, 182}, {163, 189}, 
X	{185, 167}, {173, 136}, {116, 256}, {165, 122}, 
X	{175, 170}, {145, 143}, {162, 157}, {209, 169}, 
X	{147, 137}, {134,  98}, {168, 153}, {128, 190}, 
X	{181, 154}, {160, 133}, {115, 138}, {178, 124}, 
X	{156, 257}, {164, 121}, {112, 105}, {126, 123}, 
X	{259, 258}, {260, 139}, {120, 107}, {96 , 261}, 
X	{109, 108}, {117, 113}, {262, 142}, {103,  92}, 
X	{263, 130}, {264, 129}, {127,  93}, {265, 132}, 
X	{114,  85}, {151, 118}, {266,  87}, {111, 267}, 
X	{269, 268}, {102, 270}, {91 , 271}, {272, 106}, 
X	{100,  82}, {274, 273}, {110,  88}, {73 , 275}, 
X	{95 , 276}, {104,  81}, {278, 277}, {99 ,  94}, 
X	{83 , 101}, {89 ,  86}, {280, 279}, {84 , 281}, 
X	{283, 282}, {90 ,  72}, {284,  97}, {285,  67}, 
X	{287, 286}, {80 ,  62}, {289, 288}, {74 , 290}, 
X	{292, 291}, {294, 293}, {295,  77}, {297, 296}, 
X	{69 ,  64}, {299, 298}, {71 ,  75}, {301, 300}, 
X	{78 , 302}, {60 , 303}, {305, 304}, {65 ,  61}, 
X	{76 ,  70}, {306,  79}, {308, 307}, {310, 309}, 
X	{56 , 311}, {66 ,  63}, {68 , 312}, {314, 313}, 
X	{54 ,  52}, {316, 315}, {59 ,  51}, {58 , 317}, 
X	{318,  43}, {319,  39}, {320,  40}, {57 ,  48}, 
X	{321,  55}, {323, 322}, {325, 324}, {326,  53}, 
X	{327,  46}, {328,  44}, {330, 329}, {332, 331}, 
X	{333,  38}, {334,  45}, {49 , 335}, {337, 336}, 
X	{50 , 338}, {47 , 339}, {341, 340}, {342,  36}, 
X	{344, 343}, {346, 345}, {348, 347}, {349,  42}, 
X	{35 , 350}, {29 , 351}, {352,  41}, {354, 353}, 
X	{356, 355}, {357,  30}, {359, 358}, {360,  37}, 
X	{362, 361}, {364, 363}, {366, 365}, {28 , 367}, 
X	{32 , 368}, {369,  34}, {370,  24}, {31 ,  27}, 
X	{372, 371}, {374, 373}, {376, 375}, {26 , 377}, 
X	{379, 378}, {380,  25}, {382, 381}, {384, 383}, 
X	{22 , 385}, {33 , 386}, {388, 387}, {389,  23}, 
X	{391, 390}, {21 , 392}, {20 , 393}, {19 , 394}, 
X	{396, 395}, {398, 397}, {400, 399}, {402, 401}, 
X	{404, 403}, {406, 405}, {18 , 407}, {17 , 408}, 
X	{410, 409}, {412, 411}, {414, 413}, {416, 415}, 
X	{16 , 417}, {419, 418}, {420,  14}, {11 , 421}, 
X	{423, 422}, {425, 424}, {426,  13}, {428, 427}, 
X	{429,  12}, {430,  15}, {432, 431}, {434, 433}, 
X	{10 , 435}, {437, 436}, {439, 438}, {441, 440}, 
X	{442,   9}, {8  , 443}, {445, 444}, {447, 446}, 
X	{449, 448}, {451, 450}, {7  , 452}, {454, 453}, 
X	{6  , 455}, {457, 456}, {459, 458}, {461, 460}, 
X	{463, 462}, {464,   5}, {466, 465}, {468, 467}, 
X	{4  , 469}, {471, 470}, {473, 472}, {475, 474}, 
X	{3  , 476}, {478, 477}, {480, 479}, {482, 481}, 
X	{484, 483}, {2  , 485}, {487, 486}, {489, 488}, 
X	{491, 490}, {493, 492}, {494,   1}, {496, 495}, 
X	{497,   0}, {499, 498}, {501, 500}, {503, 502}, 
X	{505, 504}, {507, 506}, {509, 508}
X};
+ END-OF-FILE tables.h
chmod 'u=rw,g=r,o=r' 'tables.h'
set `wc -c 'tables.h'`
count=$1
case $count in
23395)	:;;
*)	echo 'Bad character count in ''tables.h' >&2
		echo 'Count should be 23395' >&2
esac
echo Extracting 'Makefile'
sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile'
X#
X# Makefile for comic
X#
X# (p) Jan-Mark Wams 					(email: jms@cs.vu.nl)
X#
X
XCFLAGS=-O
Xo=s
X
XOBJS=bits.$o \
X	comic.$o \
X	decode.$o \
X	encode.$o \
X	getinput.$o \
X	gettoken.$o \
X	header.$o \
X	hash.$o \
X	huffman.$o
X
XCOMIC=comic
XCOMIC.SH=comic.sh
X
X# For speed or mem savage, use exec below
XRM=rm
XMAKE=make
XECHO=echo
X
Xcomic: minix
X	@$(ECHO) comic done...
X
Xclean:
X	@$(RM) -f core a.out *.o *.obj $(OBJS) $(COMIC.SH) *.?-X *.-X *-X
X
Xshar:
X	shar *.c *.h [A-Z]* comic.prj > $(COMIC.SH)
X
Xgcc:
X	@$(MAKE) _GCC CC='gcc' 'CFLAGS=-DGCC $(CFLAGS)' 'o=o'
X
Xminix:
X	@$(MAKE) _MINIX 'CFLAGS=-i -DMINIX $(CFLAGS)' 'o=s'
X
Xpro: # profileing under some U*ix boxes.
X	@$(MAKE) _UNIX 'CFLAGS=-DUNIX -p $(CFLAGS)' 'o=o'
X
Xunix:
X	@$(MAKE) _UNIX 'CFLAGS=-DUNIX $(CFLAGS)' 'o=o'
X
Xamoeba:
X	@$(MAKE) _AMOEBA CC='amcc' 'CFLAGS=-DAMOEBA $(CFLAGS)' 'o=o'
X
Xc89:
X	@$(MAKE) _C89 CC='c89' 'CFLAGS=-i -wo -DC89 $(CFLAGS)' 'o=o'
X
Xm68:
X	@$(MAKE) _M68 'CFLAGS=-DM68 $(CFLAGS)' 'o=o'
X
Xtcc:    # Turbo make is a bit unintel, not allowing commandline defines.
X	TCC -G -O -Z -DDOS -L\c\lib -I\c\inc \
X		comic bits decode encode getinput hash gettoken huffman header
X	@del *.obj
X
Xdos:
X	@$(MAKE) _DOS CC='CC' 'CFLAGS=-DDOS' 'o=OBJ' 'COMIC=comic.exe' 
X
X
X_MINIX _C89 _GCC _M68 _UNIX _AMOEBA _DOS: $(OBJS)
X	$(CC) $(CFLAGS) -o $(COMIC) $(OBJS)
X
Xbits.$o: bits.h comic.h bits.c
X	$(CC) $(CFLAGS) -c bits.c
X
Xcomic.$o: buffer.h comic.h hash.h comic.c
X	$(CC) $(CFLAGS) -c comic.c
X
Xdecode.$o: bits.h buffer.h comic.h huffman.h decode.c header.h
X	$(CC) $(CFLAGS) -c decode.c
X
Xencode.$o: hash.h bits.h buffer.h comic.h huffman.h encode.c header.h
X	$(CC) $(CFLAGS) -c encode.c
X
Xgetinput.$o: buffer.h comic.h getinput.c
X	$(CC) $(CFLAGS) -c getinput.c
X
Xgettoken.$o: hash.h buffer.h comic.h gettoken.c
X	$(CC) $(CFLAGS) -c gettoken.c
X
Xhuffman.$o: comic.h huffman.h tables.h huffman.c
X	$(CC) $(CFLAGS) -c huffman.c
X
Xhash.$o: hash.h buffer.h comic.h hash.c
X	$(CC) $(CFLAGS) -c hash.c
X
Xheader.$o: comic.h header.h header.c
X	$(CC) $(CFLAGS) -c header.c
+ END-OF-FILE Makefile
chmod 'u=rw,g=r,o=r' 'Makefile'
set `wc -c 'Makefile'`
count=$1
case $count in
1977)	:;;
*)	echo 'Bad character count in ''Makefile' >&2
		echo 'Count should be 1977' >&2
esac
echo Extracting 'READ_ME'
sed 's/^X//' > 'READ_ME' << '+ END-OF-FILE ''READ_ME'
X
XThis dir contains the source files for COMIC 1.0
X
X		COMIC stands for COmpress MInix C.
X
XIt contains huffman tables (tables.h) that are tuned to the tippical MINIX
XC-program source.
X
XUsage: comic [-cfvvV?] [<file>[-X]...]
XUsage: decomic [-cfvV?] [<file>[-X]...]
XUsage: xcat [-vV?] [<file>[-X]...]
X
XEg.:
X	comic -V		# print the version number of comic.
X	comic -vv <file>	# compress the file, and print the savings.
X	comic -df <file>	# decomic the file overwriting <file>.
X	comic -c <file>		# comic the file to stout.
X	decomic			# decomic stdin.
X	xcat foo		# decomic foo-X to stout.
X
XLink comic to decomic, and decomic will act like comic -d.
XLink comic to xcat, and decomic will act like comic -cd.
X
XTo make comic type 'make unix' or 'make gcc' or 'make minix' etc.
X
XNote: COMIC 1.0 is slightly incompatible with COMIC 1.0B, this 
Xmeans you will have to decomic all files before installing the
Xnew COMIC.
X
XThe DOS version has an additional flag, -a this will convert \r\n to
X\n and is usable to gain extra compression, or to make UN*X compatible
Xfiles. To be able to decomic a text file under UN*X that was comiced
Xon a DOS machine, use the -a flag with comic on the DOS machine.
X
XEg.:
X	comic -fvva PIPO.DOC		# creat a PIPO.D-X on a DOS machine
X	comic -dc PIPO.D-X > pipo.doc	# decomic it on a UN*X machine.
X	xcat PIPO.D-X > pipo.doc	# same.
X
XNote: binary DOS files can't be comiced using the -a flag. (An assertion
Xwill fail, this might be an error message in next versions.)
XNote: DOS files with 2 or 3 char suffixes will lose 1 or 2 suffix chars. 
XEg. PIPO.DOC will become PIPO.D-X. Next versions will remember the OC,
Xand restore it.
X
X
XQuestions: email jms@cs.vu.nl
X
+ END-OF-FILE READ_ME
chmod 'u=rw,g=r,o=r' 'READ_ME'
set `wc -c 'READ_ME'`
count=$1
case $count in
1669)	:;;
*)	echo 'Bad character count in ''READ_ME' >&2
		echo 'Count should be 1669' >&2
esac
echo Extracting 'READ_ME2'
sed 's/^X//' > 'READ_ME2' << '+ END-OF-FILE ''READ_ME2'
X
XWhere should COMIC go to? (And in what order.)
X
X	0) Faster getinput routine.
X	1) Full path names.	
X	2) Dynamic Huffman tables.
X	3) Prefill of buffer.
X	4) Pointer matching (faster) searching.
X	5) General speedup.
X	6) MSC port.
X	7) Cleanup.
X
X
XQuestions: email jms@cs.vu.nl
X
+ END-OF-FILE READ_ME2
chmod 'u=rw,g=r,o=r' 'READ_ME2'
set `wc -c 'READ_ME2'`
count=$1
case $count in
273)	:;;
*)	echo 'Bad character count in ''READ_ME2' >&2
		echo 'Count should be 273' >&2
esac
echo Extracting 'comic.prj'
sed 's/^X//' > 'comic.prj' << '+ END-OF-FILE ''comic.prj'
Xcomic    (buffer.h; comic.h)
Xbits     (bits.h; comic.h)
Xdecode   (bits.h; buffer.h; comic.h; huffman.h; header.h)
Xencode   (hash.h; bits.h; buffer.h; comic.h; huffman.h; header.h)
Xgetinput (buffer.h; comic.h)
Xgettoken (hash.h; buffer.h; comic.h)
Xhuffman  (comic.h; huffman.h; tables.h)
Xhash     (hash.h; buffer.h; comic.h)
Xheader   (comic.h; header.h)
+ END-OF-FILE comic.prj
chmod 'u=rw,g=r,o=r' 'comic.prj'
set `wc -c 'comic.prj'`
count=$1
case $count in
352)	:;;
*)	echo 'Bad character count in ''comic.prj' >&2
		echo 'Count should be 352' >&2
esac
exit 0
--

				 (:>	jms
				(_)
			========""======