Submitted-by: Dan Bernstein <brns...@stealth.acf.nyu.edu>
Posting-number: Volume 21, Issue 1
Archive-name: squeeze1.711

squeeze, unsqueeze -- compress data with Miller-Wegman encoding.

Edit the options in Makefile and type make. squeeze and unsqueeze will be
the executable programs; the nroff'ed man files will go into squeeze.1,
unsqueeze.1, etc. squeeze and unsqueeze are filters only; sqz, sqzdir,
unsqz, unsqzdir, and mwcat apply them to files.  Note that the shell
scripts need filterfile version 1.2 or later.

I don't pretend to know your machine's setup so there's no make install.

Read CHANGES for a list of changes. Type squeeze -C and squeeze -W for
copyright and warranty information, squeeze -H for help; similarly for
unsqueeze.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README CHANGES mwcat.man squeeze.man sqz.man sqzdir.man
#   unsqueeze.man squeeze.c unsqueeze.c sqz sqzdir unsqz unsqzdir
#   mwcat Makefile
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1543 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Xsqueeze, unsqueeze - compress data with Miller-Wegman encoding
X
Xsqueeze version 1.711, October 28, 1989.
XCopyright (c) 1989, Daniel J. Bernstein.
XAll rights reserved.
X
XThis distribution packaged October 28, 1989.
X
XFiles:
XCHANGES         Description of changes since first distributed version
XREADME          This document
XMakefile        Installation commands
Xsqueeze.c       The squeeze program
Xunsqueeze.c     The unsqueeze program
Xsqz             A shell script to apply squeeze to files
Xsqzdir          A shell script to apply squeeze to a directory hierarchy
Xunsqz           A shell script to apply unsqueeze to files
Xunsqzdir        A shell script to apply unsqueeze to a directory unhierary
Xmwcat           A shell script to apply cat to squeezed files
Xsqueeze.man     Documentation for squeeze
Xunsqueeze.man   Documentation for unsqueeze
Xsqz.man         Documentation for sqz, unsqz
Xsqzdir.man      Documentation for sqzdir, unsqzdir
Xmwcat.man       Documentation for mwcat
X
XEdit the options in Makefile and type make. squeeze and unsqueeze
Xwill be the executable programs; the nroff'ed man files will go into
Xsqueeze.1, unsqueeze.1, etc. squeeze and unsqueeze are filters only; 
Xsqz, sqzdir, unsqz, unsqzdir, and mwcat apply them to files.
XNote that the shell scripts need filterfile version 1.2 or later.
X
XI don't pretend to know your machine's setup so there's no make install.
X
XRead CHANGES for a list of changes. Type squeeze -C and squeeze -W
Xfor copyright and warranty information, squeeze -H for help; similarly
Xfor unsqueeze.
END_OF_FILE
if test 1543 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(261 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
XVersion 1.711, 10/28/89. (Can't wait for 1.7111, 1.71111111, ... :-) )
X
XPut in new copyright notice and warranty.
X
XVersion 1.71, 9/27/89.
X
Xsqueeze and unsqueeze now complain about being given a filename.
XAdded sqz, sqzdir, unsqz, unsqzdir, mwcat.
X
XVersion 1.7.
END_OF_FILE
if test 261 -ne `wc -c <'CHANGES'`; then
    echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'mwcat.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mwcat.man'\"
else
echo shar: Extracting \"'mwcat.man'\" \(1122 characters\)
sed "s/^X//" >'mwcat.man' <<'END_OF_FILE'
X.TH mwcat 1
X.SH NAME
Xmwcat \- print the contents of
X\fIsqueeze\fBd
Xfiles
X.SH SYNTAX
Xmwcat
X[ options and files ]
X.SH DESCRIPTION
X.I mwcat
Xapplies
X.I unsqueeze
Xto one or more files,
Xprinting the result.
XIt passes all options through to
X.I unsqueeze.
X.PP
XRead the
X.I squeeze
Xand
X.I unsqueeze
Xdocumentation for a description of options and
Xof the compression method.
X.SH EXAMPLES
XTo view foo.MW:
X.PP
X.EX
Xmwcat foo | more
X.EE
X.PP
XFor a display revealing common substrings (try it):
X.PP
X.EX
Xmwcat -d~ foo | more
X.EE
X.SH DIAGNOSTICS
X.TP
X\fIfatal: must specify filenames; use unsqueeze for a filter\fB
XSelf-explanatory.
X.PP
X.I unsqueeze
Xwill print compression statistics if you specify
X.B\-v.
X.SH MACHINES
X.I mwcat
Xhas been tested on an Astronautics ZS-2
Xrunning ZSUnix,
Xa Convex C1 running Convex UNIX,
Xand an HP9000 running HP-UX.
X.SH FILES
XNone.
X.SH BUGS
XNone known.
X.SH RESTRICTIONS
X.I mwcat
Xis truly obnoxious in insisting upon a single MW suffix
Xfor
X\fIsqueeze\fBd
Xfiles.
X.SH VERSION
Xmwcat, dated September 27, 1989.
X.SH AUTHOR
XCopyright 1989, Daniel J. Bernstein.
X.SH "SEE ALSO"
Xsqueeze(1),
Xunsqueeze(1),
Xsqz(1),
Xsqzdir(1)
END_OF_FILE
if test 1122 -ne `wc -c <'mwcat.man'`; then
    echo shar: \"'mwcat.man'\" unpacked with wrong size!
fi
# end of 'mwcat.man'
fi
if test -f 'squeeze.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'squeeze.man'\"
else
echo shar: Extracting \"'squeeze.man'\" \(4581 characters\)
sed "s/^X//" >'squeeze.man' <<'END_OF_FILE'
X.TH squeeze 1
X.SH NAME
Xsqueeze \- compress data with Miller\-Wegman encoding
X.SH SYNTAX
Xsqueeze
X[
X\fB\-eErRbBv\fI
X] [
X\fB\-ACHUVW\fI
X]
X.SH DESCRIPTION
X.I squeeze
Xcompresses its standard input
Xand writes the result to its standard output.
X\fIsqueeze\fBd
Xfiles can be restored
Xwith
X\fIunsqueeze\fB.
X.PP
XOptions
X.B ACHUVW
Xprint the authorship notice,
Xcopyright notice,
Xhelp notice,
Xshort usage summary,
Xversion number,
Xand warranty information respectively.
X.PP
X.I squeeze
Xhas several flags:
X.TP 12
X.B -e
XLeave an explicit end-of-file marker in the output.
XIf you use this flag, you can add any
Xsort of random garbage onto the end of the compressed data
Xwithout affecting the decompressed form.
X.TP
X.B -E
XDo not leave an end-of-file marker. This is the default.
X.TP
X.B -r
XProduce ``randomized'' output.
X.I squeeze
Xwill use the time of day to introduce
Xrandom bits of information
Xinto the output.
XNormally, for efficiency and so that
X.I squeeze
Xcan produce output before seeing the end of the input,
Xthere must be slight output redundancy.
XUnder
X.B -r,
Xthis redundancy disappears
Xand almost all
X\fIsqueeze\fBd
Xtexts are possible.
XSince
X.I squeeze
Xdoes not output a recognizable header,
Xand since Miller-Wegman encoding is so good at removing
Xredundancy,
X.I squeeze -r
Xis a very useful step before encryption.
X(Caveat: the beginning of the output depends only
Xon the beginning of the input, so you should make sure
Xto
X.I precede the uncompressed input
X.I by unpredictable data
Xbefore feeding it to
X.I squeeze.)
X.TP
X.B -R
XDo not randomize output. This is the default.
X.TP
X.B -b
X.I squeeze
Xmaintains a
X``dictionary''
Xof strings
Xadapted to the data seen so far.
XWhen
X.I squeeze
Xruns out of memory,
Xit will adapt to the next
X``block'' of the file
Xby throwing out the dictionary and starting over.
XThis is the default behavior and is given explicitly as
X.B -b.
X.TP
X.B -B
XGiven this flag,
X.I squeeze
Xwill simply freeze its old dictionary
Xwhen it runs out of memory,
Xrather than hope to do better on the
Xsucceeding data.
XThis will produce better (and faster) results
Xif the first ``block'' of the file
Xhas similar characteristics to the rest of the file.
X.TP
X.B -v
X.I squeeze
Xwill be ``verbose'' and report compression statistics
Xto standard error.
X.PP
X.I squeeze
Xuses Miller-Wegman encoding,
Xa variant on Ziv-Lempel encoding.
XThe amount of compression obtained depends on the size of the
Xinput, the amount of memory
X.I squeeze
Xuses,
Xand the distribution of common substrings.
XTypically, text such as source code or English
Xis reduced by 70\-80%.
X.PP
XIt is natural to compare
X.I squeeze
Xto
X.I compress,
Xwhich uses straightforward Ziv-Lempel encoding.
XIn the author's experience,
XMiller-Wegman encoding produces output
X10\-40%
Xsmaller than the corresponding Ziv-Lempel output;
Xand the best case is much better.
XOn the other hand,
XMiller-Wegman encoding fares slightly worse
Xon patternless data,
Xand since it requires general string matching
Xwhile Ziv-Lempel requires only a restricted type
Xof string matching,
X.I squeeze
Xhas been somewhat slower than
X.I compress
Xin the author's tests.
X.PP
XFor files longer than a megabyte,
X.I squeeze
Xoften produces output under one third the size of the output from
X.I compress,
Xbut may do twice as much computation.
XIt should also be noted that
X.I squeeze
Xis much more of a memory hog than
X.I compress,
Xsince it uses a more complex algorithm.
X.PP
XThe choices between
X.B -e
Xand
X.B -E,
Xand between
X.B -b
Xand
X.B -B,
Xchange the structure of the compressed file.
XBe careful to select the same flags for
X.I unsqueeze.
X.SH DIAGNOSTICS
X.TP
X\fIIn:\fB xxx \fIchars  Out:\fB xxx \fIchars  Squeezed to:\fB xx%
XThe utilizer of the computational machinery
Xhas specified the ``verbose'' option
Xto
X.I squeeze
Xvia the
Xestablishment of the character v
Xwithin an argument
Xpreceded by a hyphen.
X.TP
X\fII am a filter, try sqz for squeezing files\fB
XSelf-explanatory.
X.SH MACHINES
X.I squeeze
Xhas been tested on an Astronautics ZS-2
Xrunning ZSUnix,
Xa Convex C1 running Convex UNIX,
Xand an HP9000 running HP-UX.
X.SH FILES
XNone.
X.SH BUGS
XNone known.
X.SH RESTRICTIONS
X.I squeeze
Xdoes not adapt to the amount of memory available;
Xits memory use is set at compile time.
X.PP
X.I squeeze
Xdoes not provide a more advanced blocking method.
X.SH VERSION
Xsqueeze version 1.711, dated October 28, 1989.
X.SH AUTHOR
XCopyright 1989, Daniel J. Bernstein.
X.SH REFERENCES
XVictor S. Miller,
X"Data Compression Algorithms"
Xin Proceedings of Symposia in Applied Mathematics
XVolume 34, 1986.
XA readable summary of major coding methods.
X.SH "SEE ALSO"
Xunsqueeze(1),
Xsqz(1),
Xsqzdir(1),
Xmwcat(1),
Xcompress(1)
END_OF_FILE
if test 4581 -ne `wc -c <'squeeze.man'`; then
    echo shar: \"'squeeze.man'\" unpacked with wrong size!
fi
# end of 'squeeze.man'
fi
if test -f 'sqz.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sqz.man'\"
else
echo shar: Extracting \"'sqz.man'\" \(1777 characters\)
sed "s/^X//" >'sqz.man' <<'END_OF_FILE'
X.TH sqz 1
X.SH NAME
Xsqz \- apply
X.I squeeze
Xto a file
X.PP
Xunsqz \- apply
X.I unsqueeze
Xto a file
X.SH SYNTAX
Xsqz
X[ options and files ]
X.PP
Xunsqz
X[ options and files ]
X.SH DESCRIPTION
X.I sqz
Xuses
X.I filterfile
Xto apply
X.I squeeze
Xto one or more files.
XIt passes all options through to
X.I squeeze.
X.I unsqz
Xbears the same relation to
X.I unsqeeze.
X.PP
XEach original file is removed;
Xthe
X\fIsqueeze\fBd
Xdata is placed into a file having the same name
Xwith a suffix of
X\fIMW\fB.
X.I sqz
Xstrips this suffix from its input file names.
X.PP
XFile protections and access/modification times are preserved.
X.PP
X.I unsqz
Xsimply reverses the operations of
X.I sqz.
X.PP
XRead the
X.I squeeze
Xand
X.I unsqueeze
Xdocumentation for a description of options and
Xof the compression method.
X.SH DIAGNOSTICS
X.TP
X\fIfatal: must specify filenames; use squeeze for a filter\fB
XSelf-explanatory.
X.PP
X.I squeeze
Xand
X.I unsqueeze
Xwill print compression statistics if you specify
X.B\-v.
X.PP
X.I filterfile
Xmay produce error messages if
Xa file does not exist or has more than one link,
Xor if you move the file during
Xthe operation.
X.SH MACHINES
X.I sqz
Xand 
X.I unsqz
Xhave been tested on an Astronautics ZS-2
Xrunning ZSUnix,
Xa Convex C1 running Convex UNIX,
Xand an HP9000 running HP-UX.
X.SH FILES
XNone.
X.SH BUGS
XNone known.
X.SH RESTRICTIONS
X.I sqz
Xand
X.I unsqz
Xare truly obnoxious in insisting upon a single MW suffix
Xfor
X\fIsqueeze\fBd
Xfiles.
X.PP
X.I sqz
Xand
X.I unsqz
Xdo not provide for overwriting an existing file.
X.PP
XBecause
Xthese programs are not integrated,
Xthe error messages may seem a bit strange at times.
X.SH VERSION
Xsqz, dated September 27, 1989.
X.PP
Xunsqz, dated September 27, 1989.
X.SH AUTHOR
XCopyright 1989, Daniel J. Bernstein.
X.SH "SEE ALSO"
Xsqueeze(1),
Xunsqueeze(1),
Xsqzdir(1),
Xmwcat(1),
Xfilterfile(1)
END_OF_FILE
if test 1777 -ne `wc -c <'sqz.man'`; then
    echo shar: \"'sqz.man'\" unpacked with wrong size!
fi
# end of 'sqz.man'
fi
if test -f 'sqzdir.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sqzdir.man'\"
else
echo shar: Extracting \"'sqzdir.man'\" \(1964 characters\)
sed "s/^X//" >'sqzdir.man' <<'END_OF_FILE'
X.TH sqz 1
X.SH NAME
Xsqzdir \- apply
X.I squeeze
Xto a directory hierarchy
X.PP
Xunsqzdir \- apply
X.I unsqueeze
Xto a directory hierarchy
X.SH SYNTAX
Xsqzdir
X[ options and directories ]
X.PP
Xunsqzdir
X[ options and directories ]
X.SH DESCRIPTION
X.I sqzdir
Xuses
X.I find
Xand
X.I filterfile
Xto apply
X.I squeeze
Xto one or more directories,
Xpassing down through the entire tree beneath each directory.
XIt passes all options through to
X.I squeeze.
X.I unsqzdir
Xbears the same relation to
X.I unsqeeze.
X.PP
XEach original file is removed;
Xthe
X\fIsqueeze\fBd
Xdata is placed into a file having the same name
Xwith a suffix of
X\fIMW\fB.
X.I sqzdir
Xstrips this suffix from its input file names.
X.PP
XFile protections and access/modification times are preserved.
X.PP
X.I unsqzdir
Xsimply reverses the operations of
X.I sqzdir.
X.PP
XIf you do not specify a filename,
X.I sqzdir
Xand
X.I unsqzdir
Xassume the current directory.
X.PP
XRead the
X.I squeeze
Xand
X.I unsqueeze
Xdocumentation for a description of options and
Xof the compression method.
X.SH DIAGNOSTICS
X.PP
X.I squeeze
Xand
X.I unsqueeze
Xwill print compression statistics if you specify
X.B\-v.
X.PP
X.I filterfile
Xmay produce error messages if
Xa file does not exist or has more than one link,
Xor if you move the file during
Xthe operation.
X.SH MACHINES
X.I sqzdir
Xand
X.I unsqzdir
Xhave been tested on an Astronautics ZS-2
Xrunning ZSUnix,
Xa Convex C1 running Convex UNIX,
Xand an HP9000 running HP-UX.
X.SH FILES
XNone.
X.SH BUGS
XNone known.
X.SH RESTRICTIONS
X.I sqzdir
Xand
X.I unsqzdir
Xare truly obnoxious in insisting upon a single MW suffix
Xfor
X\fIsqueeze\fBd
Xfiles.
X.PP
X.I sqzdir
Xand
X.I unsqzdir
Xdo not provide for overwriting an existing file.
X.PP
XBecause
Xthese programs are not integrated,
Xthe error messages may seem a bit strange at times.
X.SH VERSION
Xsqzdir, dated September 27, 1989.
X.PP
Xunsqzdir, dated September 27, 1989.
X.SH AUTHOR
XCopyright 1989, Daniel J. Bernstein.
X.SH "SEE ALSO"
Xsqueeze(1),
Xunsqueeze(1),
Xsqz(1),
Xmwcat(1),
Xfilterfile(1),
Xfind(1)
END_OF_FILE
if test 1964 -ne `wc -c <'sqzdir.man'`; then
    echo shar: \"'sqzdir.man'\" unpacked with wrong size!
fi
# end of 'sqzdir.man'
fi
if test -f 'unsqueeze.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unsqueeze.man'\"
else
echo shar: Extracting \"'unsqueeze.man'\" \(3588 characters\)
sed "s/^X//" >'unsqueeze.man' <<'END_OF_FILE'
X.TH unsqueeze 1
X.SH NAME
Xunsqueeze \- decompress data squeezed with Miller\-Wegman encoding
X.SH SYNTAX
Xunsqueeze
X[
X\fB\-eErRbBv\fI
X] [
X\fB\-d\fIstring
X] [
X\fB\-ACHUVW\fI
X]
X.SH DESCRIPTION
X.I unsqueeze
Xdecompresses its standard input
Xand writes the result to its standard output.
XThe input should be a file compressed with
X.I squeeze.
X.PP
XOptions
X.B ACHUVW
Xprint the authorship notice,
Xcopyright notice,
Xhelp notice,
Xshort usage summary,
Xversion number,
Xand warranty information respectively.
X.PP
X.I unsqueeze
Xhas several flags:
X.TP 12
X.B -e
XExpect an explicit end-of-file marker in the output.
X.TP
X.B -E
XDo not expect an explicit end-of-file marker. This is the default.
X.TP
X.B -r
XAccept any input string, including
X``randomized'' output from
X.I squeeze.
XThis is the default.
X.TP
X.B -R
XComplain about randomized inputs.
XThis will catch most inputs that come from
X\fIsqueeze\fB -r;
Xit will also tend to catch inputs that don't come
Xfrom
X.I squeeze
Xat all.
X.TP
X.B -b
XExpect ``blocked'' input and accept ``next block'' codes.
XThis is the default.
X.TP
X.B -B
XExpect unblocked input.
X.TP
X\fB-d\fIstring
XInsert
X.I string
Xbetween output bunches.
XIf you want to get a feel for the workings
Xof Miller-Wegman compression, try this.
X.TP
X.B -v
X.I unsqueeze
Xwill be ``verbose'' and report compression statistics
Xto standard error.
X.PP
XSee
X.I squeeze(1)
Xfor a discussion of the time-space tradeoff
Xinvolved in using Miller-Wegman encoding rather than
XZiv-Lempel encoding.
XNote that
X.I unsqueeze
Xruns nearly as quickly as
X.I uncompress,
Xfor the same size decompressed text,
Xand can run faster for huge texts.
X.PP
XThe choices between
X.B -e
Xand
X.B -E,
Xand between
X.B -b
Xand
X.B -B,
Xchange the structure of the compressed file.
XBe careful to select the same flags as
X.I squeeze
Xwas given.
X.SH DIAGNOSTICS
X.TP 1.5i
X.I bad (randomized) input
XYou gave the flag
X.B -R
Xand the input cannot have come from
X.I squeeze
Xwith the same flags.
X.TP
X.I out of memory
XThe file was
X\fIsqueeze\fBd
Xin much more memory than
X.I unsqueeze
Xhas available.
X.TP
X.I EOF not signalled?
XYou gave the flag
X.B -e
Xbut the input did not signal end-of-file.
X.TP
X\fIIn:\fB xxx \fIchars  Out:\fB xxx \fIchars  Squeezed to:\fB xx%
XThe utilizer of the computational machinery
Xhas specified the ``verbose'' option
Xto
X.I unsqueeze
Xvia the
Xestablishment of the character v
Xwithin an argument
Xpreceded by a hyphen.
X.TP
X\fII am a filter, try unsqz for unsqueezing files\fB
XSelf-explanatory.
X.SH MACHINES
X.I unsqueeze
Xhas been tested on an Astronautics ZS-2
Xrunning ZSUnix,
Xa Convex C-1 running Convex UNIX,
Xand an HP9000 running HP-UX.
X.SH FILES
XNone.
X.SH BUGS
XNone known.
X.SH RESTRICTIONS
X.I unsqueeze
Xdoes not adapt to the amount of memory available;
Xits memory use is set at compile time.
X.PP
XUnlike
X.I uncompress,
X.I unsqueeze
Xcarefully checks bounds on its variables
Xand cannot be made to loop.
X(\fIuncompress\fB
Xdepends upon receiving signal SEGV when it uses out-of-bounds
Xvariables.)
XFor efficiency,
X.I unsqueeze
Xmakes one exception
Xthat could, conceivably, cause a segmentation fault.
XThis exception can only happen for certain
Xspecially constructed files of length at least
Xhalf a billion bytes.
XOf course, that doesn't excuse the author,
Xwho begs forgiveness for this lapse of judgment.
X.SH VERSION
Xunsqueeze version 1.711, dated October 28, 1989.
X.SH AUTHOR
XCopyright 1989, Daniel J. Bernstein.
X.SH REFERENCES
XVictor S. Miller,
X"Data Compression Algorithms"
Xin Proceedings of Symposia in Applied Mathematics
XVolume 34, 1986.
XA readable summary of major coding methods.
X.SH "SEE ALSO"
Xsqueeze(1),
Xsqz(1),
Xsqzdir(1),
Xmwcat(1),
Xcompress(1)
END_OF_FILE
if test 3588 -ne `wc -c <'unsqueeze.man'`; then
    echo shar: \"'unsqueeze.man'\" unpacked with wrong size!
fi
# end of 'unsqueeze.man'
fi
if test -f 'squeeze.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'squeeze.c'\"
else
echo shar: Extracting \"'squeeze.c'\" \(11779 characters\)
sed "s/^X//" >'squeeze.c' <<'END_OF_FILE'
X/*
Xsqueeze.c: Adaptive data compression with Miller-Wegman method.
X*/
X
X/* explicit blocking char? <-- */
X/* go from file to file and delete old file... .M? .W? .S? */
X/* alloc() instead of huge array? less obnoxious? */
X/* maybe stick to shorts for codes? half the memory */
X/* how else to reduce memory requirement? */
X/* signals? */
X/* LRU? I think not */
X/* option to decompress instead? I think not */
X/* needs option for not searching dictionary after memory freeze? no */
X/* is transition through clearing table ok? yes */
X/* other blocking methods? not yet */
X/* trie at top levels? like first version? hmmm */
X
Xstatic char squeezeauthor[] =
X"squeeze was written by Daniel J. Bernstein.\n\
XInternet address: brns...@acf10.nyu.edu.\n\
XThanks to Herbert J. Bernstein for suggesting the data structures used.\n";
X
Xstatic char squeezeversion[] = 
X"squeeze version 1.711, October 28, 1989.\n\
XCopyright (c) 1989, Daniel J. Bernstein.\n\
XAll rights reserved.\n";
X
Xstatic char squeezecopyright[] =
X"squeeze version 1.711, October 28, 1989.\n\
XCopyright (c) 1989, Daniel J. Bernstein.\n\
XAll rights reserved.\n\
X\n\
XYou are granted the following rights: A. To make copies of this work in\n\
Xoriginal form, so long as (1) the copies are exact and complete; (2) the\n\
Xcopies include the copyright notice, this paragraph, and the disclaimer\n\
Xof warranty in their entirety. B. To distribute this work, or copies made\n\
Xunder the provisions above, so long as (1) this is the original work and\n\
Xnot a derivative form; (2) you do not charge a fee for copying or for\n\
Xdistribution; (3) you ensure that the distributed form includes the\n\
Xcopyright notice, this paragraph, and the disclaimer of warranty in their\n\
Xentirety. These rights are temporary and revocable upon written, oral, or\n\
Xother notice by Daniel J. Bernstein. This copyright notice shall be\n\
Xgoverned by the laws of the state of New York.\n\
X\n\
XIf you have questions about squeeze or about this copyright notice,\n\
Xor if you would like additional rights beyond those granted above,\n\
Xplease feel free to contact the author at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
Xstatic char squeezewarranty[] =
X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
Xall warranties, explicit or implied, including but not limited to the\n\
Ximplied warranties of merchantability and fitness for a particular purpose.\n\
XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
Xincidental or consequential, arising from the use of this program, even\n\
Xif you inform him of the possibility of such damages. This disclaimer\n\
Xshall be governed by the laws of the state of New York.\n\
X\n\
XIn other words, use this program at your own risk.\n\
X\n\
XIf you have questions about squeeze or about this disclaimer of warranty,\n\
Xplease feel free to contact the author at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
Xstatic char squeezeusage[] =
X"Usage: squeeze [ -eErRbBvACHUVW ]\n\
XHelp:  squeeze -H\n";
X
Xstatic char squeezehelp[] =
X"squeeze compresses its input and prints the result, using adaptive Miller-\n\
XWegman encoding, a variation on Ziv-Lempel encoding. It usually produces\n\
Xfiles 10-40%% shorter than compress does. To decompress, use unsqueeze.\n\
X\n\
Xsqueeze -A: print authorship notice\n\
Xsqueeze -C: print copyright notice\n\
Xsqueeze -H: print this notice\n\
Xsqueeze -U: print short usage summary\n\
Xsqueeze -V: print version number\n\
Xsqueeze -W: print disclaimer of warranty\n\
X\n\
Xsqueeze [ -eErRbBv ]: compress\n\
X  -e: explicitly indicate EOF\n\
X  -E: do not explicitly indicate EOF (default)\n\
X  -r: ``randomize'' output; useful before encryption\n\
X  -R: do not randomize output (default)\n\
X  -b: readapt to next block when out of memory (default)\n\
X  -B: freeze working adaptation when out of memory\n\
X  -v: announce compression results (``verbose'')\n\
X\n\
XIf you have questions about or suggestions for squeeze, please feel free\n\
Xto contact the author, Daniel J. Bernstein, at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
X#include <stdio.h>
X#include <sys/time.h>
X
X#define ALPHABET 256
X#define BUFSIZE 300000
X#define DICTSIZE BUFSIZE
X#define MOD 354621
X#define OUTBUFSIZE 2000
X
Xint flagrandom = 0;
Xint flageof = 0;
Xint flagblocking = 1; /* sigh */
Xint flagverbose = 0;
X
Xint numberin = 0;
Xint numberout = 0;
X
Xint table[MOD];
X
Xint parent[DICTSIZE];
Xint num[DICTSIZE];
Xint next[DICTSIZE];
X
X#define morehash(curhash,ch) ( ( curhash * 256 + ch + 1) % MOD )
X/* Rules on hash: For same curhash and different ch, must produce
Xdifferent hash. Must produce values between 0 and MOD - 1.
X*/
X
Xcleartable()
X{
X register int h;
X
X for (h = 0;h < MOD;)
X   table[h++] = 0;
X}
X
Xgoaheadandbeverbose()
X{
X fprintf(stderr,"In: %d chars  Out: %d chars  Squeezed to: %d%%\n",
X numberin,numberout,(100 * numberout + numberin / 2) / numberin);
X}
X
Xinitdictionary()
X{
X register int ch;
X
X for (ch = 0;ch < ALPHABET;ch++)
X  {
X   parent[ch + 1] = 0;
X   num[ch + 1] = ch;
X   next[ch + 1] = 0;
X   table[morehash(0,ch)] = ch + 1;
X  }
X}
X
Xint y[55];
Xint j;
Xint k;
X
Xinitrandom()
X{
X struct timeval t;
X
X gettimeofday(&t,(struct timezone *) NULL);
X for (j = 0;j < 20;j++)
X   y[j] = ((t.tv_usec >> j) + (t.tv_sec >> j)) % 2;
X gettimeofday(&t,(struct timezone *) NULL);
X for (j = 0;j < 20;j++)
X   y[j + 20] = (t.tv_usec >> j) % 2;
X y[54] = 1;
X j = 24;
X k = 0;
X}
X
Xint randombit()
X{
X j = (j + 54) % 55;
X k = (k + 54) % 55;
X return(y[k] = y[k] ^ y[j]);
X}
X
X/* input routines */
X
Xunsigned char buf[BUFSIZE];
Xint bufstart = 0;
Xint bufend = 0;
X
X/* getchar() with readable buffer */
X#define inchar() ( bufstart != bufend ? ((result = buf[bufstart]), \
X  (bufstart = (bufstart + 1) % BUFSIZE), result) : ((result = getchar()), \
X  result == EOF ? EOF : ((buf[bufstart] = result = (unsigned char) result), \
X  (bufend = (bufstart = (bufstart + 1) % BUFSIZE)), result )))
X/* uses register int result --- down in main */
X
X/* reread last n buffered characters */
X#define inrepeat(n) { bufstart = (bufstart + BUFSIZE - (n)) % BUFSIZE; }
X/* stupid C mod... note: need not check n > BUFSIZE since n < DICTSIZE */
X
X/* un-reread n buffered characters */
X#define uninrepeat(n) { bufstart = (bufstart + (n)) % BUFSIZE; }
X/* stupid C mod... note: need not check n > BUFSIZE since n < DICTSIZE */
X
X/* output routines */
X
Xint outn[OUTBUFSIZE];
Xint outb[OUTBUFSIZE];
Xint outbitpos = 0;
Xint outword = 0;
Xint outbuf = 0;
X
Xoutnum(ch,max)
Xregister int ch;
Xregister int max;
X{
X register int m = (max + flageof + flagblocking) >> 8;
X   /* skipping eight steps because max >= 128 */
X
X outb[outbuf] = 8;
X while (m)
X   outb[outbuf]++, m >>= 1;
X
X if (flagrandom)
X   if (ch < (1 << outb[outbuf]) - max - flageof - flagblocking - 1)
X     if (randombit())
X       ch += (max + flageof + flagblocking + 1);
X outn[outbuf] = ch;
X outbuf++;
X if (outbuf == OUTBUFSIZE)
X  {
X   for (outbuf = 0;outbuf < OUTBUFSIZE;outbuf++)
X    {
X     outword += (outn[outbuf] << outbitpos);
X     outbitpos += outb[outbuf];
X     while (outbitpos > 7)
X      {
X       putchar((outword & 255));
X       numberout++;
X       outword >>= 8;
X       outbitpos -= 8;
X      }
X    }
X   outbuf = 0;
X  }
X}
X
Xoutfinish()
X{
X register int i;
X
X for (i = 0;i < outbuf;i++)
X  {
X   outword += (outn[i] << outbitpos);
X   outbitpos += outb[i];
X   while (outbitpos > 7)
X    {
X     putchar((outword & 255));
X     numberout++;
X     outword >>= 8;
X     outbitpos -= 8;
X    }
X  }
X if (flagrandom)
X  {
X   while (outbitpos < 7)
X    {
X     outword += (randombit() << outbitpos);
X     outbitpos++; /* fill the final byte with random bits */
X    }
X  }
X putchar(outword); /* the final byte */
X numberout++;
X}
X
X/* the real stuff */
X
Xmain(argc,argv,envp)
Xint argc;
Xchar *argv[];
Xchar *envp[];
X{
X register int ch;
X register int maxnum;
X register int maxnode;
X register int i;
X register int match;
X register int matchlen;
X register int curhash;
X register int dictmatch;
X register int dictmatchlen;
X register int dictmatchhash;
X register int oldmatch;
X register int oldmatchhash;
X register int result; /* for inchar() */
X
X while (*(++argv))
X   if (**argv == '-')
X     while (*(++(*argv)))
X       switch(**argv)
X        {
X         case 'e': flageof = 1; break;
X         case 'E': flageof = 0; break;
X         case 'r': flagrandom = 1; break;
X         case 'R': flagrandom = 0; break;
X	 case 'b': flagblocking = 1; break;
X	 case 'B': flagblocking = 0; break;
X	 case 'v': flagverbose = 1; break;
X	 case 'A': printf(squeezeauthor); exit(0);
X         case 'C': printf(squeezecopyright); exit(0);
X         case 'V': printf(squeezeversion); exit(0);
X         case 'W': printf(squeezewarranty); exit(0);
X         case 'H': printf(squeezehelp); exit(0);
X         case 'U': printf(squeezeusage); exit(0);
X         default: ;
X        }
X   else
X    {
X     fprintf(stderr,"squeeze: I am a filter, try sqz for squeezing files\n");
X     exit(1);
X    }
X
X if (flagrandom)
X   initrandom();
X
Xstart_over:
X initdictionary();
X maxnum = ALPHABET - 1;
X maxnode = ALPHABET;
X
X if ((ch = inchar()) == EOF)
X  {
X   if (flageof) /* can't leave without saying goodbye! */
X     outnum(maxnum + 1,maxnum);
X   outfinish();
X   if (flagverbose)
X     goaheadandbeverbose();
X   exit(0);
X  }
X outnum(ch,maxnum);
X numberin++;
X oldmatch = table[oldmatchhash = morehash(0,ch)];
X
X for (;;)
X  {
X   match = matchlen = curhash = 0;
X   dictmatch = dictmatchlen = dictmatchhash = 0;
X
X   for (;;)
X    {
Xtop_of_loop:
X     if ((ch = inchar()) == EOF)
X       if (matchlen == 0)
X	{
X	 if (flageof) /* can't leave without saying goodbye! */
X	   outnum(maxnum + 1,maxnum);
X	 outfinish();
X	 if (flagverbose)
X	   goaheadandbeverbose();
X	 exit(0);
X	}
X       else
X	 break;
X     curhash = morehash(curhash,ch);
X     for (i = table[curhash];i;i = next[i])
X       if (parent[i] == match)
X	{
X	 match = i; matchlen++;
X	 if (num[i] != -1)
X	  {
X	   dictmatch = match;
X	   dictmatchlen = matchlen;
X	   dictmatchhash = curhash;
X	  }
X	 goto top_of_loop; /* I wish C had real control structures */
X	}
X     /* i is zero; we didn't match on this character. */
X     break; /* could stick the reread(1) here */
X    }
X   
X   numberin += dictmatchlen;
X   outnum(num[dictmatch],maxnum);
X   inrepeat((ch != EOF) + matchlen);
X   /* Reread first dictmatchlen and extend onto laststring. */
X   match = oldmatch;
X   curhash = oldmatchhash;
X   while (dictmatchlen-- > 0)
X    {
X     ch = inchar(); /* can't be EOF---repetition of previous */
X     curhash = morehash(curhash,ch);
X     for (i = table[curhash];i;i = next[i])
X       if (parent[i] == match)
X	{
X	 match = i;
X	 break;
X	}
X     if (!i) /* we're out of the tree---zoom on down! */
X      {
X       if (maxnode + dictmatchlen + 1 < DICTSIZE)
X	{
X	 maxnode++;
X         parent[maxnode] = match;
X         next[maxnode] = table[curhash];
X         num[maxnode] = -1;
X         match = maxnode;
X         table[curhash] = maxnode;
X         while (dictmatchlen-- > 0)
X	  {
X	   ch = inchar(); /* can't be EOF */
X	   curhash = morehash(curhash,ch);
X	   maxnode++;
X	   parent[maxnode] = match;
X	   next[maxnode] = table[curhash];
X           num[maxnode] = -1;
X	   match = maxnode;
X           table[curhash] = maxnode;
X	  }
X         break;
X	}
X       else
X	{
X	 /* oh, dear, we've run out of memory. */
X	 maxnode = DICTSIZE;
X	 uninrepeat(dictmatchlen);
X	 dictmatchlen = 0; /* is this necessary? */
X	 if (flagblocking) /* let's start over! */
X	  {
X	   outnum(maxnum + flageof + 2,maxnum + 1);
X	   cleartable();
X	   goto start_over; /* I wish C had real control structures */
X	  }
X	 break;
X	}
X      }
X    }
X   maxnum++;
X   if (maxnode < DICTSIZE)
X     if (num[match] == -1)
X       num[match] = maxnum;
X     else /* oops, a conflict */
X       if (flagrandom)
X         if (randombit())
X	   num[match] = maxnum;
X   /* The other repeated inchars are saved for the next match. */
X   oldmatch = dictmatch;
X   oldmatchhash = dictmatchhash;
X  }
X}
END_OF_FILE
if test 11779 -ne `wc -c <'squeeze.c'`; then
    echo shar: \"'squeeze.c'\" unpacked with wrong size!
fi
# end of 'squeeze.c'
fi
if test -f 'unsqueeze.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unsqueeze.c'\"
else
echo shar: Extracting \"'unsqueeze.c'\" \(7995 characters\)
sed "s/^X//" >'unsqueeze.c' <<'END_OF_FILE'
X/*
Xunsqeeze.c: Adaptive data decompression with Miller-Wegman method.
X*/
X
X/* perhaps a memoryfreeze state bit to delay the out-of-memory? */
X/* go from file to file and delete old file... .M? .W? .S? */
X/* alloc() instead of huge array? less obnoxious? */
X/* stick to shorts? */
X/* signals? */
X/* option to compress instead? I think not */
X/* concatenate strings at low levels? not worth it---or is it? */
X
Xstatic char unsqueezeauthor[] =
X"unsqueeze was written by Daniel J. Bernstein.\n\
XInternet address: brns...@acf10.nyu.edu.\n";
X
Xstatic char unsqueezeversion[] = 
X"unsqueeze version 1.711, October 28, 1989.\n\
XCopyright (c) 1989, Daniel J. Bernstein.\n\
XAll rights reserved.\n";
X
Xstatic char unsqueezecopyright[] =
X"unsqueeze version 1.711, October 28, 1989.\n\
XCopyright (c) 1989, Daniel J. Bernstein.\n\
XAll rights reserved.\n\
X\n\
XYou are granted the following rights: A. To make copies of this work in\n\
Xoriginal form, so long as (1) the copies are exact and complete; (2) the\n\
Xcopies include the copyright notice, this paragraph, and the disclaimer\n\
Xof warranty in their entirety. B. To distribute this work, or copies made\n\
Xunder the provisions above, so long as (1) this is the original work and\n\
Xnot a derivative form; (2) you do not charge a fee for copying or for\n\
Xdistribution; (3) you ensure that the distributed form includes the\n\
Xcopyright notice, this paragraph, and the disclaimer of warranty in their\n\
Xentirety. These rights are temporary and revocable upon written, oral, or\n\
Xother notice by Daniel J. Bernstein. This copyright notice shall be\n\
Xgoverned by the laws of the state of New York.\n\
X\n\
XIf you have questions about unsqueeze or about this copyright notice,\n\
Xor if you would like additional rights beyond those granted above,\n\
Xplease feel free to contact the author at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
Xstatic char unsqueezewarranty[] =
X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
Xall warranties, explicit or implied, including but not limited to the\n\
Ximplied warranties of merchantability and fitness for a particular purpose.\n\
XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
Xincidental or consequential, arising from the use of this program, even\n\
Xif you inform him of the possibility of such damages. This disclaimer\n\
Xshall be governed by the laws of the state of New York.\n\
X\n\
XIn other words, use this program at your own risk.\n\
X\n\
XIf you have questions about unsqueeze or about this disclaimer of warranty,\n\
Xplease feel free to contact the author at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
Xstatic char unsqueezeusage[] =
X"Usage: unsqueeze [ -eErRbBACHUVW ] [ -dstring ]\n\
XHelp:  unsqueeze -H\n";
X
Xstatic char unsqueezehelp[] =
X"unsqueeze decompresses its input and prints the result. The input is a\n\
Xfile compressed with squeeze, which uses adaptive Miller-Wegman encoding.\n\
X\n\
Xunsqueeze -A: print authorship notice\n\
Xunsqueeze -C: print copyright notice\n\
Xunsqueeze -H: print this notice\n\
Xunsqueeze -U: print short usage summary\n\
Xunsqueeze -V: print version number\n\
Xunsqueeze -W: print disclaimer of warranty\n\
X\n\
Xunsqueeze [ -eErRbBdv ]: decompress\n\
X  -e: look for explicit indication of EOF\n\
X  -E: don't look for explicit EOF (default)\n\
X  -r: accept ``randomized'' input (default)\n\
X  -R: do not accept randomized input\n\
X  -b: assume input is ``blocked'' (default)\n\
X  -B: assume input is not blocked\n\
X  -dstring: display string between output bunches, for debugging\n\
X  -v: announce decompression results (``verbose'')\n\
X\n\
XIf you have questions about or suggestions for unsqueeze, please feel free\n\
Xto contact the author, Daniel J. Bernstein, at brns...@acf10.nyu.edu\n\
Xon the Internet.\n";
X
X#include <stdio.h>
X
X#define ALPHABET 256
X#define DICTSIZE 2000000
X#define STACKSIZE 50000
X
Xint flageof = 0;
Xint flagrandom = 1;
Xint flagdisplay = 0;
Xint flagblocking = 1;
Xint flagverbose = 0;
X
Xint numberin = 0;
Xint numberout = 0;
X
Xint startch;
Xint d[DICTSIZE]; /* dictionary in normal form */
X
Xint stack[STACKSIZE];
X
Xgoaheadandbeverbose()
X{
X fprintf(stderr,"In: %d chars  Out: %d chars  Unsqueezed from: %d%%\n",
X numberin,numberout,(100 * numberin + numberout / 2) / numberout);
X}
X
Xoutput(ch)
Xregister int ch;
X{
X register int stackpos = 1;
X
X stack[0] = ch;
X while (stackpos)
X  {
X   ch = stack[--stackpos];
X   while (ch >= ALPHABET)
X    {
X     stack[stackpos++] = d[ch];
X     ch = (ch == ALPHABET ? startch : d[ch - 1]); /* tail recursion */
X    }
X   putchar((char) ch);
X   numberout++;
X  }
X}
X
X/* input routines */
X
X#define INBUFSIZE 2000
X
Xint inbuf[INBUFSIZE];
Xint inbufnum = INBUFSIZE;
Xint inbufstart = INBUFSIZE;
Xint inword = 0;
Xint inwordbits = 0;
X
Xint inchar(max)
Xregister int max;
X{
X register int result;
X register int inb = 8;
X
X max = (max + flageof + flagblocking) >> 8;
X   /* skipping eight steps because max >= 128 */
X
X while (max)
X   inb++, max >>= 1;
X
X while (inb > inwordbits)
X  {
X   if (inbufstart == inbufnum)
X    {
X     if (inbufnum == INBUFSIZE)
X      {
X       for (inbufnum = 0;inbufnum < INBUFSIZE;inbufnum++)
X	{
X         if ((inbuf[inbufnum] = getchar()) == EOF)
X	   break;
X	 else
X           numberin++;
X	}
X       inbufstart = 0;
X      }
X     if (inbufstart == inbufnum) /* end of file! */
X       return(EOF);
X    }
X   inword += inbuf[inbufstart++] << inwordbits;
X   inwordbits += 8;
X  }
X result = inword % (1 << inb);
X inword >>= inb;
X inwordbits -= inb;
X return(result);
X}
X
Xmain(argc,argv,envp)
Xint argc;
Xchar *argv[];
Xchar *envp[];
X{
X register int ch;
X register int max;
X register char *display;
X
X while (*(++argv))
X   if (**argv == '-')
X     while (*(++(*argv)))
X       switch(**argv)
X        {
X         case 'e': flageof = 1; break;
X         case 'E': flageof = 0; break;
X         case 'r': flagrandom = 1; break;
X         case 'R': flagrandom = 0; break;
X	 case 'b': flagblocking = 1; break;
X	 case 'B': flagblocking = 0; break;
X	 case 'd': flagdisplay = 1; display = *argv + 1;
X		   while (*(++(*argv))) /* null */ ;
X		   --(*argv); break; /* we want breakbreak here */
X	 case 'v': flagverbose = 1; break;
X         case 'A': printf(unsqueezeauthor); exit(0);
X         case 'C': printf(unsqueezecopyright); exit(0);
X         case 'V': printf(unsqueezeversion); exit(0);
X         case 'W': printf(unsqueezewarranty); exit(0);
X         case 'H': printf(unsqueezehelp); exit(0);
X         case 'U': printf(unsqueezeusage); exit(0);
X         default: ;
X        }
X   else
X    {
X     fprintf(stderr,
X       "unsqueeze: I am a filter, try unsqz for unsqueezing files\n");
X     exit(1);
X    }
X
Xstart_over:
X max = ALPHABET - 1; /* last spot in dictionary */
X
X if ((ch = inchar(max)) != EOF)
X  {
X   if (ch > max + flageof + flagblocking)
X     if (flagrandom)
X       ch = ch % (max + flageof + flagblocking + 1);
X     else
X       {
X        fprintf(stderr,"unsqueeze: bad (randomized?) input\n");
X        exit(1);
X       }
X   if (flageof && (ch == max + 1)) /* EOF signalled! */
X     goto eof_signalled;
X   if (flagblocking && (ch == max + flageof + 1))
X     goto start_over;
X   startch = ch;
X   output(ch);
X   if (flagdisplay)
X     printf(display);
X   while ((ch = inchar(max)) != EOF)
X    {
X     if (max >= DICTSIZE)
X      {
X       fprintf(stderr,"unsqueeze: not enough memory\n");
X       exit(1);
X      }
X     if (ch > max + flageof + flagblocking)
X       if (flagrandom)
X	 ch = ch % (max + flageof + flagblocking + 1);
X       else
X	{
X	 fprintf(stderr,"unsqueeze: bad (randomized?) input\n");
X	 exit(1);
X	}
X     if (flageof && (ch == max + 1)) /* EOF signalled! */
X       goto eof_signalled;
X     if (flagblocking && (ch == max + flageof + 1))
X       goto start_over;
X     d[++max] = ch;
X     output(ch);
X     if (flagdisplay)
X       printf(display);
X    }
X  }
X if (flageof) /* EOF not signalled? */
X  {
X   fprintf(stderr,"unsqueeze: EOF not signalled?\n");
X   if (flagverbose)
X     goaheadandbeverbose();
X   exit(1);
X  }
Xeof_signalled:
X if (flagverbose)
X   goaheadandbeverbose();
X exit(0);
X}
END_OF_FILE
if test 7995 -ne `wc -c <'unsqueeze.c'`; then
    echo shar: \"'unsqueeze.c'\" unpacked with wrong size!
fi
# end of 'unsqueeze.c'
fi
if test -f 'sqz' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sqz'\"
else
echo shar: Extracting \"'sqz'\" \(405 characters\)
sed "s/^X//" >'sqz' <<'END_OF_FILE'
X#!/bin/sh
XOPTIONS=
XFILES=
XFILTERFILEEXT=MW; export FILTERFILEEXT
Xfor ARG
Xdo
X  case "$ARG" in
X    -*) OPTIONS="$OPTIONS $ARG";;
X    *) ARG="`expr $ARG : '\(.*\)\.MW' '|' $ARG`"
X       FILES="$FILES $ARG";;
X  esac
Xdone
Xif test -z "$FILES"
Xthen
X  echo 'sqz: fatal: must specify filenames; use squeeze for a filter' 1>&2
X  exit 1
Xfi
Xset $FILES
Xfor ARG
Xdo
X  filterfile -dpt "$ARG" squeeze $OPTIONS
Xdone
Xexit 0
END_OF_FILE
if test 405 -ne `wc -c <'sqz'`; then
    echo shar: \"'sqz'\" unpacked with wrong size!
fi
chmod +x 'sqz'
# end of 'sqz'
fi
if test -f 'sqzdir' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sqzdir'\"
else
echo shar: Extracting \"'sqzdir'\" \(381 characters\)
sed "s/^X//" >'sqzdir' <<'END_OF_FILE'
X#!/bin/sh
XOPTIONS=
XFILES=
XFILTERFILEEXT=MW; export FILTERFILEEXT
Xfor ARG
Xdo
X  case "$ARG" in
X    -*) OPTIONS="$OPTIONS $ARG";;
X    *) FILES="$FILES $ARG";;
X  esac
Xdone
Xif test -z "$FILES"
Xthen
X  FILES=.
Xfi
Xset $FILES
Xfind $@ -type f -links 1 \! \( -name '*.MW' -o -name '.*.MW' \) -exec filterfile -dpt {} squeeze $OPTIONS \;
X# stupid find, thinks * doesn't match dot files
Xexit 0
END_OF_FILE
if test 381 -ne `wc -c <'sqzdir'`; then
    echo shar: \"'sqzdir'\" unpacked with wrong size!
fi
chmod +x 'sqzdir'
# end of 'sqzdir'
fi
if test -f 'unsqz' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unsqz'\"
else
echo shar: Extracting \"'unsqz'\" \(415 characters\)
sed "s/^X//" >'unsqz' <<'END_OF_FILE'
X#!/bin/sh
XOPTIONS=
XFILES=
XFILTERFILEEXT=.MW; export FILTERFILEEXT
Xfor ARG
Xdo
X  case "$ARG" in
X    -*) OPTIONS="$OPTIONS $ARG";;
X    *) ARG="`expr $ARG : '\(.*\.MW\)' '|' $ARG.MW`"
X       FILES="$FILES $ARG";;
X  esac
Xdone
Xif test -z "$FILES"
Xthen
X  echo 'unsqz: fatal: must specify filenames; use unsqueeze for a filter' 1>&2
X  exit 1
Xfi
Xset $FILES
Xfor ARG
Xdo
X  filterfile -dpt "$ARG" unsqueeze $OPTIONS
Xdone
Xexit 0
END_OF_FILE
if test 415 -ne `wc -c <'unsqz'`; then
    echo shar: \"'unsqz'\" unpacked with wrong size!
fi
chmod +x 'unsqz'
# end of 'unsqz'
fi
if test -f 'unsqzdir' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unsqzdir'\"
else
echo shar: Extracting \"'unsqzdir'\" \(381 characters\)
sed "s/^X//" >'unsqzdir' <<'END_OF_FILE'
X#!/bin/sh
XOPTIONS=
XFILES=
XFILTERFILEEXT=.MW; export FILTERFILEEXT
Xfor ARG
Xdo
X  case "$ARG" in
X    -*) OPTIONS="$OPTIONS $ARG";;
X    *) FILES="$FILES $ARG";;
X  esac
Xdone
Xif test -z "$FILES"
Xthen
X  FILES=.
Xfi
Xset $FILES
Xfind $@ -type f -links 1 \( -name '*.MW' -o -name '.*.MW' \) -exec filterfile -dpt {} unsqueeze $OPTIONS \;
X# stupid find, thinks * doesn't match dot files
Xexit 0
END_OF_FILE
if test 381 -ne `wc -c <'unsqzdir'`; then
    echo shar: \"'unsqzdir'\" unpacked with wrong size!
fi
chmod +x 'unsqzdir'
# end of 'unsqzdir'
fi
if test -f 'mwcat' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mwcat'\"
else
echo shar: Extracting \"'mwcat'\" \(361 characters\)
sed "s/^X//" >'mwcat' <<'END_OF_FILE'
X#!/bin/sh
XOPTIONS=
XFILES=
Xfor ARG
Xdo
X  case "$ARG" in
X    -*) OPTIONS="$OPTIONS $ARG";;
X    *) ARG="`expr $ARG : '\(.*\.MW\)' '|' $ARG.MW`"
X       FILES="$FILES $ARG";;
X  esac
Xdone
Xif test -z "$FILES"
Xthen
X  echo 'mwcat: fatal: must specify filenames; use unsqueeze for a filter' 1>&2
X  exit 1
Xfi
Xset $FILES
Xfor ARG
Xdo
X  unsqueeze $OPTIONS < "$ARG"
Xdone
Xexit 0
END_OF_FILE
if test 361 -ne `wc -c <'mwcat'`; then
    echo shar: \"'mwcat'\" unpacked with wrong size!
fi
chmod +x 'mwcat'
# end of 'mwcat'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(619 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCCOPTS=-O
XNROFFOPTS=-man
X
Xdefault: all
X
Xall: squeeze unsqueeze squeeze.1 unsqueeze.1 sqz.1 sqzdir.1 mwcat.1
X
Xsqueeze: squeeze.c Makefile
X	cc $(CCOPTS) -o squeeze squeeze.c
X
Xunsqueeze: unsqueeze.c Makefile
X	cc $(CCOPTS) -o unsqueeze unsqueeze.c
X
Xsqueeze.1: squeeze.man Makefile
X	nroff $(NROFFOPTS) < squeeze.man > squeeze.1
X
Xunsqueeze.1: unsqueeze.man Makefile
X	nroff $(NROFFOPTS) < unsqueeze.man > unsqueeze.1
X
Xsqz.1: sqz.man Makefile
X	nroff $(NROFFOPTS) < sqz.man > sqz.1
X
Xsqzdir.1: sqzdir.man Makefile
X	nroff $(NROFFOPTS) < sqzdir.man > sqzdir.1
X
Xmwcat.1: mwcat.man Makefile
X	nroff $(NROFFOPTS) < mwcat.man > mwcat.1
END_OF_FILE
if test 619 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
echo shar: End of shell archive.
exit 0