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
(_)
========""======