From:	CSBVAX::MRGATE!ijah400%ivax.decnet@gold.bacs.indiana.edu@SMTP 16-AUG-1988 22:20
To:	ARISIA::EVERHART
Subj:	lzcomp/lzdcmp part 1 of 6.


Date: 16 Aug 88 15:18:00 EST
From: "IVAX::IJAH400" <ijah400%ivax.decnet@gold.bacs.indiana.edu>
Subject: lzcomp/lzdcmp part 1 of 6.
To: "everhart%arisia.decnet" <everhart%arisia.decnet@ge-crd.arpa>

........................ Cut between dotted lines and save ......................
$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by IJAH400
$! on Tuesday 16-AUG-1988 12:58:22.22
$!
$! ATTENTION: To keep each article below 30720 bytes, this program
$! has been transmitted in 6 parts.
$! You should concatenate ALL parts to ONE file and execute (@) that file.
$!
$! It contains the following 21 files:
$! LZ.H LZ.HLP AAAREADME.TXT LZCMP1.C VAXCRTL.OPT LZDCM1.C LZDCM2.C LZDCM3.C
$! LZVIOISAM.C LZCMP2.C LZVIO.C LZIO.C MAKEFILE.TXT README.TXT RULES.MMS
$! DESCRIP.MMS LZCMP3.C LZDEF.COM LZBLD.COM LZBLDSHR.COM LZCMP.COM
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o);
Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;
Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1);
ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop
x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1);
If Current_Character='`' then Move_Horizontal(1);else
Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="LZ.H"
$ Check_Sum_is=1433645041
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X * Header file for all lz compression/decompression routines.
X *
X * Machine/Operating system/compiler selection: (#ifdef'ed)
X * vax`009`009`009`009Vax/Unix or Vax/VMS
X * pdp11`009`009`009makes a small compressor
X * M_XENIX`009`009`009"large-model" Z8000
X * interdata`009`009`009Signed long compare is slow
X * unix`009`009`009`009Defined on true Unix systems
X * decus`009`009`009Decus C (no signal)
X * vms`009`009`009`009Vax/VMS (VMS_V4 may be set automatically)
X * #define readonly`009`009If the compiler doesn't support it correctly.
X *
X * Compiler configuration (#if'ed):
X * #define vax_asm   TRUE/FALSE`009TRUE on Vax (4bsd) if the compiler supports
X *`009`009`009`009the asm() operator.  Check the generated code!
X * #define UCHAR     TRUE/FALSE`009TRUE if compiler supports unsigned char
X * #define DEBUG     TRUE/FALSE`009TRUE to compile in debug printouts
X *
X * Algorithm Tuning parameters:
X * #define USERMEM   <n>`009Memory available to compress.
X *`009`009`009`009If large enough, a faster algorithm is used.
X * #define SACREDMEM <n>`009Don't use this part of USERMEM.
X * #define BITS      <n>`009Maximum number of code bits.
X * #define MAXIO     <n>`009Output buffer size (squeeze memory if needed)
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <setjmp.h>
X#ifndef decus
X# include <signal.h>
X/*
X * Arguments to signal():
X */
Xextern int`009abort();`009`009/* Debugging interrupt trap`009*/
Xextern int`009interrupt();`009`009/* Non-debugging interrupt trap`009*/
Xextern int`009address_error();`009/* "Segment" violation`009`009*/
X#endif
X
X#ifndef`009TRUE
X# define FALSE`009`0090
X# define TRUE`009`0091
X#endif
X#ifndef`009EOS
X# define EOS`009`009'\0'
X#endif
X#define`009streq(a, b)`009(strcmp((a), (b)) == 0)
X#define min(a,b)`009((a) > (b)) ? (b) : (a))
X
X/*
X * Set USERMEM to the maximum amount of physical user memory available
X * in bytes.  USERMEM is used to determine the maximum BITS that can be used
X * for compression.
X *
X * SACREDMEM is the amount of physical memory saved for others; compress
X * will hog the rest.
X */
X
X#ifndef SACREDMEM
X# define SACREDMEM`0090
X#endif
X
X/*
X * Set machine-specific parameters
X */
X
X#ifdef vax
X# ifdef unix
X#  define vax_asm`009TRUE`009`009/* If asm() supported on vax`009*/
X# endif
X#endif
X#ifndef`009vax_asm
X# define vax_asm`009FALSE
X#endif
X
X#ifdef pdp11
X# define BITS`00912`009/* max bits/code for 16-bit machine`009`009*/
X# define USERMEM 0`009/* Force no user memory`009`009`009`009*/
X# define UCHAR`009FALSE`009/* TRUE if compiler supports unsigned char`009*/
X# define MAXIO 512`009/* Buffer size for PDP-11 I/O buffers`009`009*/
X#endif
X
X/*
X * Set default values for some parameters.
X */
X
X#ifndef DEBUG
X# define DEBUG`009FALSE
X#endif
X
X#ifdef interdata
X# define SIGNED_COMPARE_SLOW TRUE
X#endif
X#ifndef SIGNED_COMPARE_SLOW
X# define SIGNED_COMPARE_SLOW FALSE
X#endif
X
X#ifndef USERMEM
X# define USERMEM 750000`009/* default user memory`009`009`009`009*/
X#endif
X
X#ifndef`009UCHAR
X# define UCHAR`009TRUE`009/* Compiler supports unsigned char`009`009*/
X#endif
X
X#ifndef MAXIO
X# define MAXIO`0092048`009/* I/O buffer size`009`009`009`009*/
X#endif
X
X/*
X * Set derived tuning parameters.
X */
X
X#ifndef USERMEM
X# define USERMEM`009 0
X#endif
X#if USERMEM >=`009`009`009(433484 + SACREDMEM)
X# define PBITS`009`00916
X#else
X# if USERMEM >=`009`009`009(229600 + SACREDMEM)
X#  define PBITS`009`00915
X# else
X#  if USERMEM >=`009`009(127536 + SACREDMEM)
X#   define PBITS`00914
X#   else
X#    if USERMEM >=`009`009( 73464 + SACREDMEM)
X#     define PBITS`00913
X#    else`009`009`009/* Smaller systems`009`009`009*/
X#     define PBITS`00912
X#    endif
X#   endif
X# endif
X#endif
X
X#ifndef BITS
X# define BITS PBITS
X#endif
X
X#ifdef M_XENIX
X# if BITS >= 16
X#  define XENIX_16`009`009/* Enable special vector access macros`009*/
X# else
X#  if BITS > 13
X#   undef BITS
X#   define BITS 13`009`009/* Code only handles BITS = 12, 13, 16`009*/
X#  endif
X# endif
X#endif
X
X/*
X * HSIZE is the size of the hash lookup table.  It is set to
X * 1 << BITS + fudge factor, rounded up to a prime number.
X * If it is too big, the "clear the hash" routine will take
X * too long.  The same numbers are replicated in the getsize()
X * routine's data table.
X */
X
X#if BITS == 16
X# define HSIZE`00969001`009`009/* 95% occupancy`009`009`009*/
X#endif
X#if BITS == 15
X# define HSIZE`00935023`009`009/* 94% occupancy`009`009`009*/
X#endif
X#if BITS == 14
X# define HSIZE`00918013`009`009/* 91% occupancy`009`009`009*/
X#endif
X#if BITS == 13
X# define HSIZE`009 9001`009`009/* 91% occupancy`009`009`009*/
X#endif
X#if BITS <= 12
X# define HSIZE`009 5003`009`009/* 80% occupancy`009`009`009*/
X#endif
X`012
X/*
X * typedef's -- somewhat machine specific.
X */
X
X/*
X * a code_int must be able to hold 2**BITS values of type int, and also -1
X */
X#if BITS > 15
Xtypedef long int`009code_int;
X#else
Xtypedef int`009`009code_int;
X#endif
X
X/*
X * A count_int must hold ((2**BITS)-1) + (255<<BITS)) and -1.
X *
X * count_int's also hold counters.
X *
X * count_short's hold small counters (for the interdata)
X *
X * Some implementations don't support unsigned char (Decus C, for example)
X * Decus C is also brain damaged with regards to unsigned shorts.
X */
X#if SIGNED_COMPARE_SLOW
Xtypedef unsigned long int count_int;
Xtypedef unsigned short int count_short;
X#else
Xtypedef long int`009count_int;
X#endif
X
X#if UCHAR
Xtypedef`009unsigned char`009char_type;
X#else
Xtypedef char`009`009char_type;
X#endif
X
X#ifdef decus
Xtypedef unsigned`009U_short;
X#define`009readonly`009`009`009/* Dummy out readonly modifier`009*/
X#else
Xtypedef unsigned short`009U_short;
X#endif
X
X#ifdef unix
X#define`009readonly
X#endif
X
Xtypedef short`009`009flag;`009`009/* Boolean flag or parameter`009*/
X`012
X/*
X * The following define the "magic cookie" header
X */
X#define`009HEAD1_MAGIC`0090x1F
X#define HEAD2_MAGIC`0090x9D
X#define`009VMS_HEAD2_MAGIC`0090x9E`009`009/* vms-private output format`009*/
X
X/*
X * Defines for third byte of header
X */
X#define BIT_MASK`0090x1F`009`009/* Gets NBITS in the code`009*/
X#define BLOCK_MASK`0090x80`009`009/* Gets block_compress flag`009*/
X/*
X * Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
X * a fourth header byte (for expansion).
X */
X
X/*
X * This is for backwards compatibilty with an old version of Unix compress.
X */
X#ifdef COMPATIBLE`009`009`009/* Compatible, but wrong!`009*/
X# define MAXCODE(n_bits)`009(1 << (n_bits) - 1)
X#else
X# define MAXCODE(n_bits)`009((1 << (n_bits)) - 1)
X#endif
X
X#define INIT_BITS 9`009`009`009/* initial number of bits/code */
X
X/*
X * One code could conceivably represent (1<<BITS) characters, but
X * to get a code of length N requires an input string of at least
X * N*(N-1)/2 characters.  With 5000 chars in the stack, an input
X * file would have to contain a 25Mb string of a single character.
X * This seems unlikely.
X */
X#define MAXSTACK    8000`009`009/* size of lzdcmp output stack`009*/
X
X#ifndef CHECK_GAP
X# define CHECK_GAP `00910000`009`009/* ratio check interval`009`009*/
X#endif
X
X#ifndef __LINE__
X# define NO__LINE__
X#endif
X#ifndef __FILE__
X# define NO__LINE__
X#endif
X#if DEBUG
X# define VERBOSE_DEFAULT    1
X# ifndef NO__LINE__
X#  define FAIL(why)`009`009`009`009`009\
X`009fprintf(stderr, "\nfatal: %s (%s at %d)\n",`009\
X`009    why, __FILE__, __LINE__); `009`009`009\
X`009longjmp(failure, 1);
X# else
X#  define FAIL(why)`009`009`009`009`009\
X`009fprintf(stderr, "\nfatal: %s\n", why); `009`009\
X`009longjmp(failure, 1);
X# endif
X#else
X# define VERBOSE_DEFAULT    0
X# define FAIL(why)`009longjmp(failure, 1);
X#endif
X
X/*
X * Note -- for compatibility with Unix compress,
X * NBR_CHAR and LZ_CLEAR must equal 256.
X * Also, (1 << (MIN_BITS - 1) should equal or exceed NBR_CHR
X */
X#define`009NBR_CHAR      256`009`009/* Number of input codes`009*/
X#define MIN_BITS`0099`009`009/* Smallest code is 9 bits`009*/
X#if ((1 << BITS) < NBR_CHAR) || (BITS < MIN_BITS)
X    << Can't compile: not enough bits for the input character set size >>
X#endif
X#define`009LZ_CLEAR`009(NBR_CHAR)`009/* Clear code`009`009`009*/
X#define`009LZ_SOH`009`009(LZ_CLEAR + 1)`009/* Start of header block`009*/
X#define`009LZ_STX`009`009(LZ_SOH   + 1)`009/* Start of text block`009`009*/
X#define`009LZ_EOR`009`009(LZ_STX   + 1)`009/* End of text record`009`009*/
X#define`009LZ_ETX`009`009(LZ_EOR   + 1)`009/* End of header/text block`009*/
X#define`009LZ_FIRST`009(LZ_ETX   + 1)`009/* First user (data) code`009*/
X
X#ifdef`009vms
X#include`009`009errno
X#include`009`009ssdef
X#include`009`009stsdef
X#define`009IO_SUCCESS`009(SS$_NORMAL | STS$M_INHIB_MSG)
X#define`009IO_ERROR`009(SS$_ABORT)
X#define VMS_V4`009`009L_cuserid >= 16`009`009/* Enable new stuff`009*/
X#else
X#define VMS_V4`009`0090`009`009`009/* Disable new stuff`009*/
Xextern int`009`009errno;
X#ifdef decus
X#define`009errno`009`009$$ferr
X#endif
X#endif
X
X/*
X * Define exit() codes.
X */
X
X#ifndef`009IO_SUCCESS
X#define`009IO_SUCCESS`0090`009`009`009/* Normal exit`009`009*/
X#define`009IO_ERROR`0091`009`009`009/* Error exit`009`009*/
X#endif
X`012
X/*
X * All I/O is done by way of "streams".  To establish a stream,
X * set the parameters appropriately and off you go.  The following
X * functions are provided:
X *`009lz_fill(stream)`009`009fills the buffer from stdin
X *`009lz_flush(stream)`009writes the buffer to stdout
X *`009lz_eof(stream)`009`009returns EOF (for fill from memory)
X *`009lz_fail(stream)`009`009abort (for writing to memory).
X *`009lz_dummy(stream)`009throw an output stream away.
X * Note: if VMS_V4 is enabled and the private (non-export) format
X * chosen, lz_fill and lz_flush access the files appropriately.
X * Stream elements are initialized as follows:
X *`009Input:`009bp = NULL;`009bend = NULL;
X *`009Output:`009bp = bstart;`009bend = bstart + bsize;
X */
X
Xtypedef struct STREAM {
X    char_type`009*bp;`009`009/* Next character to get/put`009`009*/
X    char_type`009*bend;`009`009/* -> end of stream buffer`009`009*/
X    char_type`009*bstart;`009/* Start of stream buffer`009`009*/
X    short`009bsize;`009`009/* Stream buffer size`009`009`009*/
X    int`009`009(*func)();`009/* Read/write a buffer function`009`009*/
X} STREAM;
X
X/*
X * Note also that the compress routine uses putbuf(buf, count, outstream)
X * and the decompress routine uses getbuf(buf, count, instream) to (quickly)
X * transfer multiple bytes.
X */
X#if UCHAR
X#define`009GET(s)`009`009\
X`009(((s)->bp < (s)->bend) ? *(s)->bp++        : (*(s)->func)(s))
X#else
X#define`009GET(s)`009`009\
X`009(((s)->bp < (s)->bend) ? *(s)->bp++ & 0xFF : (*(s)->func)(s))
X#endif
X#define`009PUT(c, s)`009\
X`009((((s)->bp >= (s)->bend) ? (*(s)->func)(s) : 0), *(s)->bp++ = (c))
X
Xextern int lz_fill();
Xextern int lz_flush();
Xextern int lz_eof();
Xextern int lz_fail();
Xextern int lz_dummy();
X
X#if DEBUG
Xextern readonly char *lz_names[];`009`009/* "LZ_CLEAR" etc.`009*/
X#endif
X
X/*
X * Options and globals.
X */
X#if VMS_V4
X#define`009ATT_NAME`009"vms$attributes "
X#define`009ATT_SIZE`00915`009`009`009/* strlen(ATT_NAME)`009*/
Xextern int`009fdl_status;`009/* Error code from fdl library`009`009*/
X#endif
X
Xextern flag`009binary;`009`009/* -b Readable text file if FALSE`009*/
Xextern flag`009noheader;`009/* -x3 No magic header if TRUE`009`009*/
Xextern flag`009export;`009`009/* -x  (non-zero) Supress vms private`009*/
Xextern flag`009block_compress;`009/* -x2`009`009`009`009`009*/
Xextern flag`009verbose;`009/* -v  (non-zero) Verbose logging`009*/
Xextern readonly flag is_compress; /* TRUE if compress, FALSE if decomp.`009*/
Xextern char`009*infilename;`009/* For error printouts`009`009`009*/
Xextern char`009*outfilename;`009/* For more error printouts`009`009*/
Xextern short`009n_bits;`009`009/* Current # of bits in compressed file`009*/
Xextern int`009firstcode;`009/* First value past signals`009`009*/
Xextern jmp_buf`009failure;`009/* For longjmp() return`009`009`009*/
$ GoSub Convert_File
$ File_is="LZ.HLP"
$ Check_Sum_is=1292288670
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X1 LZCOMP
X File Compression Utility
X Usage:
X
X`009$ LZCOMP  [-options]  infile  outfile
X
X LZCOMP implements the Lempel-Ziv file compression algorithm.
X (Files compressed by LZCOMP are uncompressed by LZDCMP.)
X It operates by finding common substrings and replaces them
X with a variable-size code.  This is deterministic, and
X can be done with a single pass over the file.  Thus,
X the decompression procedure needs no input table, but
X can track the way the table was built.
X
X2 Options
X Options may be given in either case.
X2 -BInput
X Input file is "binary", not "human readable text".
X This is necessary on Dec operating systems, such as VMS and
X RSX-11M, that treat these files differently.  (Note that binary
X support is rudamentary and probably insufficient as yet.)
X (On VMS version 4, this is ignored unless the -x option is
X specified or the input file is record-oriented.)
X2 -M bits
X Write using the specified number of bits in the code -- necessary
X for big machines making files for little machines.  For example,
X if compressing a file on VMS which is to be read on a PDP-11,
X you should select -M 12.
X2 -V [n]
X Verbose if specified.  If a value is specified,
X it will enable debugging code (if compiled in).
X2 -X [n]
X "Export" -- write a file format that can be read by
X other operating systems.  Only the bytes in the file are copied;
X file attributes are not preserved.  If specified, the value
X determines the level of compatiblity.  If not specified,
X or specified with an explicit value of zero, and LZCOMP is
X running on Vax/VMS version 4 under VaxC and the input file
X is a disk or magtape file (block-oriented), a VMS-private output
X format is used which is incompatible with the Unix compress
X utility, but which preserves VMS file attributes.  -X may
X take on the following values:
X
X    0  Choose VMS private format.  See restrictions below.
X    1  Compatible with Unix compress version 3.0:
X       this is the default if -x is given without a value.
X    2  As above, but supress "block compression"
X    3  Supress block compression and do not output
X       a compress header block.  This is for compatiblity
X       with a quite early version of Unix compress (and requires
X       conditional-compilation to use).
X
X Note that the -B (binary) option is ignored unless
X the input file is "record-oriented", such as a terminal
X or mailbox.
X2 Arguments
X The other two arguments are the input and output
X filenames respectively.  Redirection is supported,
X however, the output must be a disk/tape file.
X
X The file format is almost identical to the current
X Unix implementation of compress (V4.0).  Files written
X by Unix compress should be readable by LZDCMP.  Files
X written by LZCOMP in export (-x) format will be
X readable by Unix compress (except that LZCOMP outputs
X two "clear" codes to mark EOF.  A patch to Unix
X compress is available.)
X
X2 VMS_Restrictions
X
X VMS Private mode stores the true name and attributes
X of the input file into the compressed file and LZDCMP
X restores the attributes (and filename if requested).
X The following restrictions apply -- they may be lifted
X in the future as they are primarily due to the author's
X lack of understanding of the intricacies of of VMS I/O:
X
X    All files must be stored on disk.
X    The LZCOMP output file must be specified directly.
X
X Also, for all usage on VMS, the compressed file must
X be written to, and read from disk.
X
X2 Compression_Algorithm
X
X This section is abstracted from Terry Welch's article
X referenced below.  The algorithm builds a string
X translation table that maps substrings in the input
X into fixed-length codes.  The compress algorithm may
X be described as follows:
X
X  1. Initialize table to contain single-character
X     strings.
X  2. Read the first character.  Set <w> (the prefix
X     string) to that character.
X  3. (step): Read next input character, K.
X  4. If at end of file, output code(<w>); exit.
X  5. If <w>K is in the string table:
X     Set <w> to <w>K; goto step 3.
X  6. Else <w>K is not in the string table.
X     Output code(<w>);
X     Put <w>K into the string table;
X     Set <w> to K; Goto step 3.
X
X "At each execution of the basic step an acceptable input
X string <w> has been parsed off.  The next character K is
X read and the extended string <w>K is tested to see if it
X exists in the string table.  If it is there, then the
X extended string becomes the parsed string <w> and the
X step is repeated.  If <w>K is not in the string table,
X then it is entered, the code for the successfully
X parsed string <w> is put out as comprssed data, the
X character K becomes the beginning of the next string,
X and the step is repeated."
X
X The decompression algorithm translates each received
X code into a prefix string and extension [suffix] character.
X The extension character is stored (in a push-down stack),
X and the prefix translated again, until the prefix is a
X single character, which completes decompression of this
X code.  The entire code is then output by popping the
X stack.
X
X "An update to the string table is made for each code received
X (except the first one).  When a code has been translated,
X its final character is used as the extension character,
X combined with the prior string, to add a new string to
X the string table.  This new string is assigned a unique
X code value, which is the same code that the compressor
X assigned to that string.  In this way, the decompressor
X incrementally reconstructs the same string table that
X the decompressor used.... Unfortunately ... [the algorithm]
X does not work for an abnormal case.
X
X The abnormal case occurs whenever an input character string
X contains the sequence K<w>K<w>K, where K<w> already
X appears in the compressor string table."
X
X The decompression algorithm, augmented to handle
X the abnormal case, is as follows:
X
X  1. Read first input code;
X     Store in CODE and OLDcode;
X     With CODE = code(K), output(K);  FINchar = K;
X  2. Read next code to CODE; INcode = CODE;
X     If at end of file, exit;
X  3. If CODE not in string table (special case) then
X     Output(FINchar);
X     CODE = OLDcode;
X     INcode = code(OLDcode, FINchar);
X
X  4. If CODE == code(<w>K) then
X     Push K onto the stack;
X     CODE == code(<w>);
X     Goto 4.
X
X  5. If CODE == code(K) then
X     Output K;
X     FINchar = K;
X
X  6. While stack not empty
X     Output top of stack;
X     Pop stack;
X
X  7. Put OLDcode,K into the string table.
X     OLDcode = INcode;
X     Goto 2.
X
X The algorithm as implemented here introduces two additional
X complications.
X
X The actual codes are transmitted using a variable-length
X encoding.  The lowest-level routines increase the number
X of bits in the code when the largest possible code is
X transmitted.
X
X Periodically, the algorithm checks that compression is
X still increasing.  If the ratio of input bytes to output
X bytes decreases, the entire process is reset.  This can
X happen if the characteristics of the input file change.
X
X2 VMS_Private_File_Structure
X
X In VMS Private mode, the compressed data file contains
X a variable-length (but compressed) file header with the
X file "attributes" needed by the operating system to
X  construct the file.  This allows the decompression
X program to recreate the file in its original format,
X which is essential if ISAM databases are compressed.
X
X The overall file format is as follows:
X
X    LZ_SOH  "start of header" signal (this value cannot appear
X            in user data).
X
X            A variable-length data record (maximum 256 bytes)
X            containing the header name, followed by whitespace, followed
X            by header-specific information.  In this case, the name
X            record will contain the string "vms$attributes" followed
X            by the number of bytes in the attribute data block.
X            (I assume that the name record will consist of a facility
X            name, such as "vms", followed by a dollar sign, followed
X            by a facility-unique word.)
X
X    LZ_EOR  Signals "end of record".
X
X            This is followed by a VMS file attributes record (generated
X            by a VMS system libraryroutine).
X
X    LZ_ETX  Signals "end of segment".
X
X    ST_STX  Signals "start of text" (i.e., start of data file).
X
X            This is followed by the user data file.
X
X    LZ_ETX  Signals "end of segment"
X
X    LZ_ETX  Two in a row signals "end of file".
X
X Note that this format can easily be extended to include
X trailer records (with file counts and checksums) and/or
X multiple data files in one compressed file.
X
X Note also that the LZ_CLEAR code may appear in headers
X or data files to cause the decompression program to
X "readapt" to the characteristics of the input data.
X LZ_STX and LZ_SOH reset the compression algorithm.
X LZ_EOR does not.
X
X2 Authors
X The algorithm is from "A Technique for High Performance
X Data Compression."  Terry A. Welch. IEEE Computer Vol 17,
X No. 6 (June 1984), pp 8-19.
X
X This revision is by Martin Minow.
X
X Unix Compress authors are as follows:
X
X Spencer W. Thomas  (decvax!harpo!utah-cs!utah-gr!thomas)
X Jim McKie          (decvax!mcvax!jim)
X Steve Davies       (decvax!vax135!petsd!peora!srd)
X Ken Turkowski      (decvax!decwrl!turtlevax!ken)
X James A. Woods     (decvax!ihnp4!ames!jaw)
X Joe Orost          (decvax!vax135!petsd!joe)
X
X Compatible with compress.c, v3.0 84/11/27
X
X1 LZDCMP
X File Decompression Utility
X Usage:
X
X`009$ LZDCMP  [-options]  infile  outfile
X
X LZDCMP decompresses files compressed by LZCOMP.  The
X help information for LZCOMP describes the process in
X greater detail.
X
X2 Options
X Options may be given in either case.
X2 -BOutput
X Output file is "binary", not text.  (Ignored
X in VMS private mode.)
X2 -X 3
X To read files compressed by an old Unix version
X that doesn't generate header records.
X2 -V val
X Verbose (print status messages and debugging
X information).  The value selects the amount of verbosity.
$ GoSub Convert_File
$ File_is="AAAREADME.TXT"
$ Check_Sum_is=554838299
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X
XLZCOMP and LZDCMP file compression/decompression programs.
X
XThe original versions had some memory management bugs where argv
Xstrings and dynamic string space was being realloc'ed.  That doesn't
Xwork anymore in with the VAXC 2.3 RTL so the offending code was fixed.
XTested under VAXC v2.3-024 and VMS v4.6 and 4.7.
X
X`009- Jim Harvey, IUPUI Academic Computing Services
X
X
XSource files:
X
XLZCMP1.C, LZCMP2.C, LZCMP3.C - C sources for LZCOMP.  Description of
Xusage, compression algorithm, and edit history is in LZCMP1.C.
X
XLZDCM1.C, LZDCM2.C, LZDCM3.C - C sources for LZDCMP.  Description of
Xusage and edit history is in LZDCM1.C.
X
XLZIO.C - Operating-system independent I/O routines.
X
XLZVIO.C - Apparently an old version of LZVIO.  Not used (uses LZVIOISAM
Xinstead).
X
XLZVIOISAM.C - Current LZVIO module.
X
XLZ.H - include file for LZCOMP/LZDCMP.
X
X
XCommand procedures/link option files:
X
XLZBLD.COM - Builds version using non-shareable VAXC RTL.
X
XLZBLDSHR.COM - Builds version using shareable VAXC RTL.
X
XVAXCRTL.OPT - LINK option file used by LZBLDSHR.COM.
X
XLZDEF.COM - Defines foreign command symbols used to run LZCOMP/LZDCMP.
X
X
XInstallation procedure:
X
X1.`009Build the EXE files using LZBLDSHR.COM, or use the EXEs from
X`009the saveset.
X
X2.`009Copy the EXEs to SYS$SYSTEM.  Set protection to W=RE or W=E.
X
X3.`009Use the foreign command symbols defined by LZDEF.COM to
X`009execute the programs.
X
XOriginal AAAREADME.TXT from VAX SIG tape follows:
X
X
XThis area contains source and executable for the LZCMP and LZDCM
Xutilities used in several places on the tape to compress large
Xfiles to gain room. The sources contain documentation in comments
Xat the start of the code for those curious about the programs'
Xoperation.
X`009To use LZCMP and LZDCM, define them as DCL foreign
Xsymbols. For instance, you might use commands like
X
X$LZCMP:==$DECUS$DISK:[VAX86D.LZW]LZCMP
X$LZDCM:==$DECUS$DISK:[VAX86D.LZW]LZDCM
X
XThen to compress a file use a command like
X
X$ LZCMP -v inputfile.typ squeezedfile.typ
X
Xor to decompress the file use a command like
X
X$ LZDCM squeezedfile.typ unsqueezedfile.typ
X
XIf you use those commands, "inputfile.typ" and "unsqueezedfile.typ"
Xwill be copies of each other.
X
X`009Note that you'd have to define "DECUS$DISK" before giving the
X$ lzcmp:==...
Xetc. definitions above... the idea is to run the programs as foreign
Xcommands. The -v switch for LZCMP is the "verbose" switch so that
Xwhen LZCMP is done it'll report to you what it did. The default
Xoperation on VMS preserves file attributes in the squeezed file.
XSeveral "compatibility" options (not used on the tapes) treat the
Xfiles in one of two stream modes (text and binary) and can be used
Xfor transporting files to/from non-VMS systems.
X`009It is presumed that if you're able to read the tape in VMS
XBACKUP, you must have a VMS system handy to do the decompress on, and
Xthat in that case, preserving all the file attributes is desirable.
X
X`009USAGE NOTE FOR THE VAX SIG TAPES
X
X`009Wherever any file has a type of form  .*_LZW,  where * is any
Xextension, it is compressed by LZCMP here and should be decompressed
Xwith LZDCM before use. In all cases, where this has been done, there
Xwill be a directory (often named THIS_DIR.LIS) of the file directory
Xtree prior to backing up and compressing. Areas have been compressed
Xby creating a VMS Backup saveset and compressing the saveset, so
Xthat only one squeezed file per directory tree need be dealt with.
$ GoSub Convert_File
$ Goto Part2

