I~LZ.SAVl)LZ.SAV$BACK/LOG [.LZ]*.*;* LZ.SAV/SAV/INTER PERROT E +%V5.2 _IPNMGR::  _$1$DUA2: V5.2 ~ !*[SYSDEV.PERROT.LZ]AAAREADME.TXT;2+,Kg./E 4K-F0123KPWO56 `U7`J%8`i)"9GEHJ@This area contains source and executable for the LZCMP and LZDCM>utilities used in several places on the tape to compress largeAfiles to gain room. The sources contain documentation in comments>at the start of the code for those curious about the programs' operation.3 To use LZCMP and LZDCM, define them as DCL foreign2symbols. For instance, you might use commands like&$LZCMP:==$DECUS$DISK:[VAX86D.LZW]LZCMP&$LZDCM:==$DECUS$DISK:[VAX86D.LZW]LZDCM*Then to compress a file use a command like)$ LZCMP -v inputfile.typ squeezedfile.typ,or to decompress the file use a command like+$ LZDCM squeezedfile.typ unsqueezedfile.typCIf you use those commands, "inputfile.typ" and "unsqueezedfile.typ"will be copies of each other.> Note that you'd have to define "DECUS$DISK" before giving the $ lzcmp:==...Detc. definitions above... the idea is to run the programs as foreignAcommands. The -v switch for LZCMP is the "verbose" switch so that?when LZCMP is done it'll report to you what it did. The default@operation on VMS preserves file attributes in the squeezed file.ASeveral "compatibility" options (not used on the tapes) treat theBfiles in one of two stream modes (text and binary) and can be used/for transporting files to/from non-VMS systems.; It is presumed that if you're able to read the tape in VMSEBACKUP, you must have a VMS system handy to do the decompress on, andCthat in that case, preserving all the file attributes is desirable.! USAGE NOTE FOR THE VAX SIG TAPES< Wherever any file has a type of form .?Z?, where ? is anyDcharacter, it is compressed by LZCMP here and should be decompressedEwith LZDCM before use. In all cases, where this has been done, eitherBthere is a command file which will decompress all compressed filesBin its directory (after editing to define LZDCM as a symbol to run?LZDCM.EXE on your system), OR the file squeezed is a VMS BackupGsaveset, so LZDCM needs to be run on only one file, and Backup can then0break it up to individual files and directories.E The above is by Glenn Everhart. I (Joe Bingham) have used differentHconventions. When compressing a single file I have appended _LZC to theJfile extension. Thus COMMON_WORDS.DAT becomes COMMON_WORDS.DAT_LZC. WhenHcompressing a directory or a directory tree I have first used VMS BACKUPJto package all of the files in a single file. I have then compressed thatKfile and used the name THIS_DIR.LZS or THIS_TREE.LZS. In such cases I haveIalso included a THIS_DIR or THIS_TREE.FILES so you do not have to reverseKthe procedure just to see what files are there. I hope this does not causetoo much confusion.*[SYSDEV.PERROT.LZ]LZ.H;1+,./E 4L-F0123KPWO56`+*7@%8d"9GEHJ/*= * Header file for all lz compression/decompression routines. *; * Machine/Operating system/compiler selection: (#ifdef'ed) * vax Vax/Unix or Vax/VMS# * pdp11 makes a small compressor * M_XENIX "large-model" Z8000* * interdata Signed long compare is slow' * unix Defined on true Unix systems * decus Decus C (no signal)3 * vms Vax/VMS (VMS_V4 may be set automatically)B * #define readonly If the compiler doesn't support it correctly. * # * Compiler configuration (#if'ed):K * #define vax_asm TRUE/FALSE TRUE on Vax (4bsd) if the compiler supports4 * the asm() operator. Check the generated code!G * #define UCHAR TRUE/FALSE TRUE if compiler supports unsigned charB * #define DEBUG TRUE/FALSE TRUE to compile in debug printouts * * Algorithm Tuning parameters:6 * #define USERMEM Memory available to compress.2 * If large enough, a faster algorithm is used.8 * #define SACREDMEM Don't use this part of USERMEM.5 * #define BITS Maximum number of code bits.F * #define MAXIO Output buffer size (squeeze memory if needed) */#include #include #include #ifndef decus# include /* * Arguments to signal(): */3extern int abort(); /* Debugging interrupt trap */;extern int interrupt(); /* Non-debugging interrupt trap */6extern int address_error(); /* "Segment" violation */#endif #ifndef TRUE# define FALSE 0# define TRUE 1#endif #ifndef EOS# de&fine EOS '\0'#endif+#define streq(a, b) (strcmp((a), (b)) == 0)m)#define min(a,b) ((a) > (b)) ? (b) : (a)) /*F * Set USERMEM to the maximum amount of physical user memory availableL * in bytes. USERMEM is used to determine the maximum BITS that can be used * for compression. *H * SACREDMEM is the amount of physical memory saved for others; compress * will hog the rest. */#ifndef SACREDMEM# define SACREDMEM 0#endif/*" * Set machine-specific parameters */ #ifdef vax # ifdef unix7# define vax_asm TRUE /* If asm() supported on vax */# endif#endif#ifndef vax_asm# define vax_asm FALSE#endif #ifdef pdp118# define BITS 12 /* max bits/code for 16-bit machine */0# define USERMEM 0 /* Force no user memory */B# define UCHAR FALSE /* TRUE if compiler supports unsigned char */<# define MAXIO 512 /* Buffer size for PDP-11 I/O buffers */#endif/** * Set default values for some parameters. */ #ifndef DEBUG # define DEBUG FALSE#endif#ifdef interdata!# define SIGNED_COMPARE_SLOW TRUEs#endif#ifndef SIGNED_COMPARE_SLOWe"# define SIGNED_COMPARE_SLOW FALSE#endif#ifndef USERMEM 4# define USERMEM 750000 /* default user memory */#endif #ifndef UCHARk:# define UCHAR TRUE /* Compiler supports unsigned char */#endif #ifndef MAXIOi,# define MAXIO 2048 /* I/O buffer size */#endif/*! * Set derived tuning parameters.  */"#ifndef USERMEM_# define USERMEM 0I#endif%#if USERMEM >= (433484 + SACREDMEM)C# define PBITS 16#else&# if USERMEM >= (229600 + SACREDMEM)# define PBITS 15r# else&# if USERMEM >= (127536 + SACREDMEM)# define PBITS 14e# else(# if USERMEM >= ( 73464 + SACREDMEM)# define PBITS 132## else /* Smaller systems */w# define PBITS 122 # endif # endifl# endifa#endif #ifndef BITS# define BITS PBITSe#endif#ifdef M_XENIX# if BITS >= 16w=# define XENIX_16 /* Enable special vector access macros */T# else# if BITS > 13t# undef BITS=# define BITS 13 /* Code only handles BITS = 12, 13, 16 */y# endif# endifo#endif/*< * HSIZE is the size of the hash lookup table. It is set to: * 1 << BITS + fudge factor, rounded up to a prime number.; * If it is too big, the "clear the hash" routine will takel> * too long. The same numbers are replicated in the getsize() * routine's data table. */i#if BITS == 16+# define HSIZE 69001 /* 95% occupancy */y#endif#if BITS == 15+# define HSIZE 35023 /* 94% occupancy */+#endif#if BITS == 14+# define HSIZE 18013 /* 91% occupancy */m#endif#if BITS == 13+# define HSIZE 9001 /* 91% occupancy */ #endif#if BITS <= 12+# define HSIZE 5003 /* 80% occupancy */y#endif a/** * typedef's -- somewhat machine specific. */ /*J * a code_int must be able to hold 2**BITS values of type int, and also -1 */n #if BITS > 15Rtypedef long int code_int;#elsektypedef int code_int;#endif/*= * A count_int must hold ((2**BITS)-1) + (255<>#endif.#define LZ_CLEAR (NBR_CHAR) /* Clear code */:#define LZ_SOH (LZ_CLEAR + 1) /* Start of header block */9#define LZ_STX (LZ_SOH + 1) /* Start of text block */8#define LZ_EOR (LZ_STX + 1) /* End of text record */=#define LZ_ETX (LZ_EOR + 1) /* End of header/text block */<#define LZ_FIRST (LZ_ETX + 1) /* First user (data) code */ #ifdef vms#include errno#include ssdef#include stsdef1#define IO_SUCCESS (SS$_NORMAL | STS$M_INHIB_MSG)#define IO_ERROR (SS$_ABORT)7#define VMS_V4 L_cuserid >= 16 /* Enable new stuff */#else+#define VMS_V4 0 /* Disable new stuff */extern int errno; #ifdef decus#define errno $$ferr#endif#endif/* * Define exit() codes. */#ifndef IO_SUCCESS)#define IO_SUCCESS 0 /* Normal exit */&#define IO_ERROR 1 /* Error exit */#endif /*? * All I/O is done by way of "streams". To establish a stream,B * set the parameters appropriately and off you go. The following * functions are provided:/ * lz_fill(stream) fills the buffer from stdin/ * lz_flush(stream) writes the buffer to stdout5 * lz_eof(stream) returns EOF (for fill from memory)2 * lz_fail(stream) abort (for writing to memory).0 * lz_dummy(stream) throw an output stream away.A * Note: if VMS_V4 is enabled and the private (non-export) format? * chosen, lz_fill and lz_flush access the files appropriately.. * Stream elements are initialized as follows:! * Input: bp = NULL; bend = NULL;. * Output: bp = bstart; bend = bstart + bsize; */typedef struct STREAM {4 char_type *bp; /* Next character to get/put */4 char_type *bend; /* -> end of stream buffer */4 char_type *bstart; /* Start of stream buffer */, short bsize; /* Stream buffer size */7 int (*func)(); /* Read/write a buffer function */ } STREAM;/*I * Note also that the compress routine uses putbuf(buf, count, outstream)L * and the decompress routine uses getbuf(buf, count, instream) to (quickly) * transfer multiple bytes. */ #if UCHAR#define GET(s) \> (((s)->bp < (s)->bend) ? *(s)->bp++ : (*(s)->func)(s))#else#define GET(s) \> (((s)->bp < (s)->bend) ? *(s)->bp++ & 0xFF : (*(s)->func)(s))#endif#define PUT(c, s) \oC ((((s)->bp >= (s)->bend) ? (*(s)->func)(s) : 0), *(s)->bp++ = (c))'extern int lz_fill();oextern int lz_flush();extern int lz_eof();extern int lz_fail();-extern int lz_dummy(); #if DEBUGo8extern readonly char *lz_names[]; /* "LZ_CLEAR" etc. */#endif/* * Options and globals.v */ #if VMS_V4"#define ATT_NAME "vms$attributes ",#define ATT_SIZE 15 /* strlen(ATT_NAME) */9extern int fdl_status; /* Error code from fdl library */#endif9extern flag binary; /* -b Readable text file if FALSE */s8extern flag noheader; /* -x3 No magic header if TRUE */=extern flag export; /* -x (non-zero) Supress vms private */ )extern flag block_compress; /* -x2 */A9extern flag verbose; /* -v (non-zero) Verbose logging */nJextern readonly flag is_compress; /* TRUE if compress, FALSE if decomp. */4extern char *infilename; /* For error printouts */9extern char *outfilename; /* For more error printouts */e@extern short n_bits; /* Current # of bits in compressed file */5extern int firstcode; /* First value past signals */4extern jmp_buf failure; /* For longjmp() return */*[SYSDEV.PERROT.LZ]LZCMP.EXE;1+,R.o/E 4on-F0123 KPWOp56Ŕ7@%8"9GEHJ@0DX0205(> h\_LZCMP1V1.0?04-00  ) 7E@] ^ ?(! FDLSHR_001?!d FORRTL_001v!  LIBRTL_001Y       N .*;*.*;*/sys$disk...*;*.*;*DIR.DIR@Kg| P`D ,,LX $ ((((( DDDDDDDDDDAAAAAABBBBBB %ld chars in, %ld bytes out, compression ratio: (%) %ld.%02ld seconds (process time) for compression. input bytes per second. Error when compressing "%s" to "%s" lzcomp fatal error%s%ld.%02ld%s%s%d;vms$attributes The following options are valid:-B Binary file (important on VMS/RSX, ignored on Unix)-M val Explicitly set the maximum number of code bits-V val Print status information (or debugging) to stderr-X val Set export (compatiblity) mode: -X 0 Explicitly choose VMS Private mode -X 1 (default if -X specified, output format is compatible with Unix compress V3.0 -X 2 Compatible with Unix compress 3.0, block compression supressed.Illegal -M value Illegal -X value: %d Unknown option '%c' in "%s" %s --Too many file arguments Cannot open "%s" in vms private format, trying export format. FDL information for "%s" rRestriction: The output file must be specified. Can't create "%s" (VMS private) w%s: is a terminal. We object. Read errorWrite errorMemory buffer [%d bytes] filled -- fatal. Decompress: corrupt input file rarat=crrfm=varLZ_CLEARLZ_SOHLZ_STXLZ_EORLZ_ETX???%2d: %02x " \n\t\b\f\ropening fileRecord only deviceconnecting after opengetting fdl infocreating (sys$create)creating (fdl$create)opening created fileRecord only deviceconnecting after createparsingclose %s %s%s%s: %s RMS error %x when %s %s "%s" %s: non-translatable vms error code: 0x%X, vms message: %s %s: %s DCLMCRSHELLerror 0not ownerno such file or directoryno such processinterrupted system calli/o errorno such device or addressarg list too longexec format errorbad file numberno childrenno more processesnot enough corepermission deniedbad addressblock device requiredmount device busyfile existscross-device linkno such devicenot a directoryis a directoryinvalid argumentfile table overflowtoo many open filesnot a typewritertext file busyfile too largeno space left on deviceillegal seekread-only file systemtoo many linksbroken pipemath argumentresult too largeI/O stream emptySYS$LOGINSYS$COMMANDSYS$DISKPATH=HOME=TERM=USER=PATHHOMETERMUSERft1-132ft1-80ft1ft2-132ft2-80ft2ft3-132ft3-80ft3ft4-132ft4-80ft4ft5-132ft5-80ft5ft6-132ft6-80ft6ft7-132ft7-80ft7ft8-132ft8-80ft8la12-132la12-80la12la120-132la120-80la120la24-132la24-80la24la34-132la34-80la34la36-132la36-80la36la38-132la38-80la38unknown-132unknown-80unknownvk100-132vk100-80vk100vt05-132vt05-80vt05vt100-132vt100-80vt100vt101-132vt101-80vt101vt102-132vt102-80vt102vt105-132vt105-80vt105vt125-132vt125-80vt125vt131-132vt131-80vt131vt132-132vt132-80vt132vt173-132vt173-80vt173vt52-132vt52-80vt52vt55-132vt55-80vt55vt200-132vt200-80vt200undefined' HSHELL$FILE_  $ 5 J̄*55Q$5d,5 |Ą45<5DD5L5 T5  \5 D  Ԅ  d5 $  l5 t5|5l@AHr555  5(5555Ā5̀5Ԁ5܀5PD55\555 !!!!!̂!! 5!""Ă"5"5#JDundefined error $(   %!08B\l (>P\n})?NZhy# )#@]Fψe 2 i ) f  ^DTUX YV ZX[ɒW]PRRRfлP ~'RPRRff3jF]5] &]\ZP1ݬݬϷkc'j Pg7 7 襁'<~ <~ ʶ <~ <~~ ~s PR  j1ngPgihhiek"h,ߥ2hiߥߥ6ihiRŏdR~ߥ3zgP{PQP P~Ǐg~ߥ:k"gߥp2gRǏdR~ i~ߥmfݏLS#RTRTTRůSRSSŊk4"< X,NLP^TݬЬ SzP{SPQPŏdPRSR~S~ݬ!^oPQ`  ```2`\x\\\M﫴<a%<a<a^fT+S️Rmm ec cУ\lc\lPl`l cЬ\lc\lPl`l cЬ\lc\lQlPPPa1c cУ\lc\lPl`l cЬ\lc\lPl`l cЬ\lcP`Q`6\3\a` cР\lc\lPlÏij\\`<~~ <~^)_P=<~C <~ݢ#<~ <~ ^.RЬ Т  ^-QЏ aPτ\lPlЬa\l8^βRbu!:\l\ ~QPЭb/Pb^VY(X凜[ZWЬnnݬ PЬѭ1ЭUESSTSRd-bЮT֮ЬSEcDc1MS1EˏSTDj S`PSSPPB7=e|1;852/,)&3?Q4Q̵%ԤdG?^YZ:VЦR2QfPլ1dxRTTPʏRЬX`TTBTTWxRXTBUTTTUTTW`PRTTQTTxTXTTSQSxSRRSQQS`2SS2RѦRSijSfԦOզj2~f2RRiԦ2RRRRR  2RRxRRRЬRR1R 1RPPVVK?զj2~fh2RRiԦ H<RѬRRt ЦRRxRSSRjRfRiԦj ^ЬRNsF2 ~ݢPSP`P WYKҧLK92 ~ݢ PS z{ӧ SPТbCbPb`P^V{X3UЬRТVVbWL_reWVVTWTSTSed~ATTSеS WJrJ9)WVmPߨ ヲ7JТb|^Ь RլPЬS׬\bTT TUTbeV RPVVTT2TbQQPPЬP@aTQTQTPQb׬STìSTTP|^ЬD~LZ.SAVRF[SYSDEV.PERROT.LZ]LZCMP.EXE;1o|!SЬ R׬CbRbUbebQQPPЬP@aTQTQTPQb׬^P^yRЬP2 ~ߢsI^ЬPР`^gy\Rb߬BbQP b,m<^-y\p߬K^ySVUTWЬXTX1ЬYDiRbPP>4P<1eߣkRRP1R~H,;1Rb>5RRY P$fߣmRPjR?H,;ߣvߣoR! PQQжP ~Q P!RG,K; WQW޼PRA`TTX1"޼RGbWP<^wTЬSЬRݣݬ ɣRħЬ UURPˏP~ĬURIJݬ ^xwTЬRЬ SS"׬S~P׬ݬ Ĵ^+wS~TˏRRˏRP@qPhPRdHRPP 2&,$?÷PúPýPPPRddP^:\n\PdzEPfCPjPP^լ ݬAP<^"wTUݬwPSP"ZDPee dSÄߤ SSP<cPee ߤ S_ЬR1b%<~L?PDc߭߭R|~߭߭1}uPee RzDߤ6SЭP@~ݢ5?PbSP^uUW|VլGݬ4PRP!Zȏ`HacDPgˏgP1ߥGRMЬScT"TSPMPS|~ߦTݬ tPgˏgP ߥ]P@yPRP!ZDPgg ߥsRϢ„ňRϐRP<bPggśR\RP^tW<~O=PVP(PZkD(`kƔ(Dkf(,{lƔlhЬRRpRLPxD< ƠƞƖD0PRdzVϪƟRB֠ƠpƟxȏHVP^ЬRբ ݢ=Ԣ ^sSЬRDPûR0RB=^Ь RЬ$ Ԣ8bP˞ŞP<"P^Ь RЬ("Ԣ8bPP<"P^ЬPݠpݬJЬP^ЬPx Q<PQP<^rSЬU.YP ;PЬQTСpTTeRRRU]x  ^zkS yR߭ ?߬q2P@PPQޢPQP aPPP@cPa  QޢPQPޢP ^qSЬ QRQRRݬA *TP  ^ЬPРS<`PSPRSR:c"ݬ~ c"ݬc~ ; ݬ  SRP ALQ  BLS < DEQ  DNA 0FOP CTG CBT TEF CIF SUP SCF SPL TMD TMP NEF RCK WCK DLT MXV RWO POS RWC FSZ ?  MRS 6@*RAT CR BLK FTN PRN ?RFM FIX VAR VFC UDF STM STMLFSTMCR?SHR GET PUT DEL UPD NIL UPI MSE  MBC 7 MBF 6ROP ASY TMO  TMO  *CTX @STM BIN NOCVTREC fop=cif  SYS$ERRORRUN SYS$INPUTSYS$OUTPUT_NLA0:SYS$DISK0VM^^Z0|~߮~~^Y|~i<UTD|TTPUT'TiTTUT TTPP: VPPVVZ VnVZVZZn0tnZɔkЬPЏL5P0`[甼PЬWP0 g0 Pg֧PЬWP0j 0kPP֧g,P߬ l~n ߬l~n0 ЬUЬRSVSrVSw Sa1b+VP0 HvpЭZYЭ\01HRpSwhP#Sa<&pPPPY0h,-)*Z a ~Zt[PЏ5P0PЬWP0O )^^[߬ ݬ[$P PZ0ЎPPЬWP0 7gV0-gV,֧g   ,02ЬPѧ $!Ч $(çPP( P֧$P(ЬPPЬWP0 4Ь[ЏZ:Zk Џ5P04[QZ0 ЏL5P0PЬWP0U $Ь[Ь ~լЬZ0 nÎ PPЬ WP0 P ~6Լ lЬWP0 Pѧ $(VV ЏzP0P߬ ݬݬ3ЬWP0 }~ ~ϰPPЬWP0  ~ ~ώЬWP0y -Ь[Ь ~ЬZ00enЬ PЏL5P0PЬWP0; iPP0W1F0j&RDžSlլ 3 86P'ImRYO0mR-mS(SbcmPP/ mЬP'WP0 LЬ[ЏZZ~gV0 4: VPPVVZ VnVZVZZn0 nZɔ{ЬP[PЬWP01 Z~n[0ЎPP0 P@P0 P@P0 Z [1 ѧ 0;,6ˏ@Vя@V(ݩnՎϬ +Џ5P0IPP[[Zլ 1$[(Z,g Z[[P[PZP iY[$6Z(0ipPPz0 Ч$[<(Z[Z,1dV[ZipVяzPяP0 1,0Ϭ +Џ5P0r [Ч PPP[çUUZ$[(Z<V Z[[PЏ5P02 [$jx $T(TVT~ݬcPrx [UZUTUVTTUUTTggT}T~,nT,nTTTg01}TTUƨ,Y[ g0[ [8i0  , [$'Z(!<(PPZTT(PS,nTc, ZVgZ0~[x [[Z[P0 iPP07 0ЬUVP0`ՎYЬPPPiP0 Ш,045ǂVЦ  h0PJӏ4 ӏ4 Џ5P1E:Tæ HUUTЦ U}T~^R~l>n~l>nYY~l> nR`P0ЎP0s P0}UʏVP0l;Ь P iPY0 Yl@hlZZެ\0J @hP4ˏQя Q Џ5P1ӏGhPnяPӏ Џ5P1L{hh,,(*Z  ZZP0l 5WP0)^^[߬ݬ[xP PZ0ЎPPW1NWP0Z5Ь[ЏZ:Zk Џ5P0 [QZ0g[Z0PZЬWP0Ь~^[0~ЬP0  ,P0 0 Z P82-<PP P0z]P$PPP1@B,@9 *h0L,h01<6R@<֧ Ч 8iP#я P , ,ЧЏgPק 0Џ5P0,1/Ч<gP,0Ч<g,0Pg/,0(Ч<g,  0J֧ ,gP1rZ, : ZkQ[QZgV0gKZVZV,(VkVgSQ[VnVZ0=! , 0"nZPՎPgV0 %ZVZV,(VkSVgQ[VZPЧVVU0} PЧ<gP0ЏPѧ $,çQQ(<(Q,QP,<ЧR,gPAb<"Ч(Ч 8iя P i0 }U~>?TV,TVTU ЏP1TP.1 EU12~T^, EUn1U1~f f ;,%, ~}U~ޮVU0}UT}U~1f  ,19Pf P1Q+Q, Q,E  ,U:E U/,'Q1P Q $QQ EU1_Q~P (UfVSUfJ@E@xUTT^^S, R R RU S,^V^SUT^1mU"V(ˏ@Sя@S,i@@i?VUVVVVV( (֧$T^}Uя P i0), P` çPP6P ,nPSЧ QçP PQQ$Q$(P(P( ^|RPP $RRRRRYYYYYYYYYYYYYYYYYYRYYYYYYYYYYVYT?R֬֬ЬP`0(`9# SQЬP֬`PPQ0QSЬP`0`9RSQSQQP^ݬA!OL!XL!SL!UL  @@doxucsefgDOXUEG%doxscef[DOXEFΫ^ͫ<ԭЬZЬXЬ Y:hPW:%Wh}P~PWP XQ01P1"}WXW1 ԭԭh-XWh* ЉXW#+WhZPWRh00XS}PW0Pѭ1h.?XWh* ЉXW)+WhPWRXS}PW0P1{PhlXWh:h ͫQhaP 0P1DXWͫSVѭP+譾PV}P~,aVc}PVR,PaRcЭPͫQP1ЭPP~(PajSZPRА+ͫ(Rcͬ ͫ6PPl~Tl0 ~TiͫՉPͫQP:PPխ ѭPЭPЉQܚ݉?P;0ͫPQϰܚ݉?P;0ͫPQ譽}PRA Ruܚ݉?PόP[~Zj7P[j@ݬ ݬݬϵЏ5P1ѭ  ЏL5P1~>nYЫX^YP0^SYR0Di }P~^S ~^Tcd~^ZDIЬTЭU~~T/PITIUP TU^TUVV^(Ud(όnnV~^Tώ ~^R|~߮~~^V|~fb<~PxяBnS1 H~^SXϥ~~~~ZS~T Y@PU! ~^TdUPPЫ PЏ\5P10d^^U nJHR^S0P1Z,H[k[1WnSZGV5*4RHUeUTVDRTU[TW R* %HZUP%ƅPP(P&c^SR^S0hP1W1tIP76РРK[nkZZR^S0#PCZn[kkךZЬ [0@PZЬ[03P nR^S0FPFPШPRR^nSЬT|~|~Rc|~<1~< ~ KGʏ< ~T%G |~ݏݏݏ?`PPPը ߨ]P[P0DDD`PDР P] ^]PbDP`XDݠݠPЎPРPlЏL5P1*D[k9kZ Z[l լЪݪjkZDЎPЏT5P1P4PPct~^Qa?aHԤLV2 P|~|~@|~PP2P@dЬRdPbSbԢ PݭPRˏRPP ݭx߭`/RRMOc'/я|PcT.PPT.PPRP?T.PP ^ ;R.\P\\P ^|~|~2:QQЬS RRR|~<#~Q S:P^ЬP1P1PE:=լ"P@:P`x: tլ`: \QA`:P`RЬ`AU:P`AO:P`AI:P`RPݏ5QP^ݬݬ5PPQQQP|^"SЬVVݏ5P߭ѽ ЏUЬUT TP@cP`1 TQAP`VhAP`U UUAcP`RЬQQP@F9P`QPxRPPRQ Q  UR, R,PT TP@cP`1t(Δ^8V8ЬRR*PRfRkP d(P`#ʹ(`#fͤ͠ʹ0PWWRR<ʹHPWWRR&:ݬݬPPPRBͤͤPͬͮͯͤͰedg(h*j,l|~~͜~ͤ ͔>͘͞ԭ|~?ͬ͠PPXXP||~|~2<͠~ PXX ͢|ԭ|~|~<͠~PXX XP<͢RSRrS<͠~ЬThjl pw͞<͞RQRPR RP Q{RPQPQRQRPRRRPRQPQ{RPPQQXxP[<͞RQRPЏR RP Q{RPQPQRQRPRRRPRQPQ{RPPQQxPZ<͞RQRPЏR RP Q{RPQPQRQRPRRRPRQPQ{RPPQQPY[ZRYRR ͘@  < RR Ԥ ͔Q͔PЏR RP Q{RPQPQԤQPP%-%77777777777777777777 t?P@1P@T?P`1P`9S1?ޢZS1ޢmS1€S1~“S1v¦S1n¹S1fS1^S1VS1N S1F#S1>9S16OS1.eS1&S1œS1³S1ЬP¸S1S1ЬPS1S1ЬPS1S1ЬPS1 S1ЬPS1&S1ЬP5So?ShЬPNSUXSNЬPgS;qS4‘S-§S&ЬP¬S¶S SSSݬ^|~|~ݬ|~<#~ݬ ' 'Џ' .c/csPcPPnnc~P/cRn:.nQQR/bRcPPnRccR:]nbQQc :>nbQQcP!ZjWWVЬ YYXY /gjX1YY Y1ЬXY( G g jr/jY ЬX /gj.GY@1ЬX /gj.j.jX 0j(XXjY!j*VQQjXX:%XfQQ?aQVPPXQVYPP R/b.b.bP R/b.b.b.bP[O Z,^lլYЬYPѬPPXЬ$QVPPPPPQPVQ1Ь$j,| 0004ЏЏЏ$,n$V  K bP1', ,w[j0T0PTP-  ,.j0T0PTP9jU- -e-.ejN.jdT<V1,,,,YjPPW, ..`[`j,.j(VVj]jXz,nPPƐϞP؞ܞ$PPj,n`P`PR$TZP\0PRERk1ZWj,*, ,Y1jP.j]j,.j,jP%.j,5,jQ.jPQP a**j.j$, ,kz,nPPƐϞP؞ܞPPj,n`P`PR$TZP\0Pk1,,kPWHP[SP(PTnSP@$.RYWR,PPWRPݬP SP(PnTk[WPPY[XW$^g,| 0004ЏЏЏ$,n$nn:QìQЬ j Ph1m,s[g0V0PVP- i ,.g0V0PVP9gT- i-d-.dg( <PPg.gfVѬE<V/gP, ..`[`g,.g(VVg]gg1,gP.g]g(<PPg,.g( <PPg,gP%.g,;,gQ.gPQP a**g.g($(<$PPghPPWV(VVg:g:gP|V(f:fPXW^VЬUUP/U-Uhw-Uh8VgЮTPTP$- hקdZ 6K P&ЮPU Ь `V֧֧PP1Ь-P<5UѬ8ЬTSeRPPa Pz PQPQReЬPЬP~[ЬZWQ2QPWV(XfX8S[VVX:?XfQQV%fPPVTУSµfV;P@LݢLgPS8SSQ[5Q%ܑQ?׊QQSVVVTXRdPdTVRXQQWWQQ]ȑQ-QӑQ]S-SWґSQ QQSšQQ]1\}PP}Q{PPQhq is.; Z.;@? ::"":[<]l>d.M-'.]>b.--.]>.]>*pm- *pE%p9R/ :/&".` ;p *z.p ;p @ !""., ./*p-y$py^*?} @[]-eVAXCMSG@@8@HH@( x 0HP  @FDLSHRFORRTLLIBRTL* ~LZ.SAVRF[SYSDEV.PERROT.LZ]LZCMP.EXE;1okQ_ LZCMP1 \main divoutD: initializeSput_magic_header' mem_compress5\ gethashsize7 getfilesizeH ۅsetupR-getvaluei openinput openoutput&y \ ,y$  y   LZCMP2Acompress όclearf5 init_compressy A  - LZCMP39 outputcodep C9)   LZIOlz_filllz_flusho lz_getbuf lz_putbufV Olz_eof Xlz_fail4lz_dummy interrupt:Ԓ address_error,getredirectiondumphexpdumptextM֔dumpcharfcputime2^ ' y     -3 LZVIO failfdl_open"і fdl_createpA fdl_setupfdl_free- fdl_closeFsfdl_read< fdl_write< fdl_getname fdl_fsize fdl_messageu vms_etextimessageWSfdl_dumpT]  z F C$ATOL katol atoi)=k C$$TRANSLATE1 c$$translatef 1C$CTYPEC$FSTAT fstatb  C$GETENV ,getenv E ,C$PERROR perror( PSHELL$FROM_VMSSHELL$FROM_VMS  :4SHELL$$RMS_PARSE  3(nTERMINATE_PARSE n m  SHELL$TRANSLATE_VMS  9)5 DEFAULT_DIR 5 A2 [  COPY_TOKEN  r}B     . INSERT_MINUS  /!-3 DOTDOTDOT 3 \!3CLI$DATA2 _LIB$KEY0$2 _LIB$STATE$_tCLI$READ_ONLY_DATACLI$CODESHELL$CLI_NAMEshell$cli_nameshell$is_shell@N o  SHELL$TO_VMSf SHELL$TO_VMS f Z J    "   d a  9BSHELL$$VMS_FILE  ͹;   #    SAVE_NODE  Y)'SAVE_DEV   &SAVE_DIRECTORY  :B SAVE_NAME  @ & SAVE_TYPE  m-(  Y  SAVE_VERS    &"COPY_STR " H1!FREE_DIRECTORY_DESCRIPTORS  w  4F MATCH_REGEX F C, # MATCH_SUBSTRING  *' R Q+PRUNE_FILESPEC + g^&     FIND_LAST_DOT  " .TERMINATE_PARSE     CLI$READ_ONLY_DATACLI$DATA82 _LIB$KEY0$ _LIB$STATE$4fCLI$CODE  . ABS .C$SIGNAL declare_control_c_handlerD +signalssignal& gsignalm # ! $  C$STAT stat1 swap_bits6g_copy_file_name5y a NX#  C$DATAC$$MAINc$$mainG expand_buffer lowercase/5 get_paramsqget_terminal_typez  c$$ctrlc_hando c$$cond_hand.y t0y " y  &! y"SHELL$FIX_TIMESHELL$FIX_TIMEDATACODE SHELL$CLINTSHELL$GET_ARGVCLI$CODEDSHELL$MATCH_WILD`SHELL$MATCH_WILD`CLI$CODEC$SIGVEC sigvecsigblock5C sigsetmasksigpause4 sigstack>y  *[SYSDEV.PERROT.LZ]LZCMP1.C;1+,..6/E 4H65:-F0123KPWO75 6 7JP%8 w"9GEHJ/*$ * lzcomp [-options] infile outfile */#ifdef DOCUMENTATIONtitle lzcomp File Compressionindex File compressionsynopsis .s.nf% lzcomp [-options] [infile [outfile]] .s.f description= lzcomp implements the Lempel-Ziv file compression algorithm.9 (Files compressed by lzcomp are uncompressed by lzdcmp.); It operates by finding common substrings and replaces them7 with a variable-size code. This is deterministic, and5 can be done with a single pass over the file. Thus,6 the decompression procedure needs no input table, but' can track the way the table was built.% Options may be given in either case. .lm +8 .p -86 -B Input file is "binary", not "human readable text".< This is necessary on Dec operating systems, such as VMS and@ RSX-11M, that treat these files differently. (Note that binary: support is rudamentary and probably insufficient as yet.); (On VMS version 4, this is ignored unless the -x option is1 specified or the input file is record-oriented.) .p -88 -M bits Write using the specified number of bits in the; code -- necessary for big machines making files for little5 machines. For example, if compressing a file on VMS: which is to be read on a PDP-11, you should select -M 12. .p -87 -V [n] Verbose if specified. If a value is specified,0 it will enable debugging code (if compiled in). .p -8; -X [n] "Export" -- write a file format that can be read byA other operating systems. Only the bytes in the file are copied;< file Tattributes are not preserved. If specified, the value9 determines the level of compatiblity. If not specified,n; or specified with an explicit value of zero, and lzcomp is; running on Vax/VMS version 4 under VaxC and the input fileoA is a disk or magtape file (block-oriented), a VMS-private output< format is used which is incompatible with the Unix compress: utility, but which preserves VMS file attributes. -X may take on the following values: .lm +4.s> .i -4;#0##Choose VMS private format. See restrictions below.5 .i -4;#1##Compatible with Unix compress version 3.0:4 this is the default if -x is given without a value.4 .i -4;#2##As above, but supress "block compression"6 .i -4;#3##Supress block compression and do not output3 a compress header block. This is for compatiblityL: with a quite early version of Unix compress (and requires! conditional-compilation to use).n .lm -4.se3 Note that the -B (binary) option is ignored unless 8 the input file is "record-oriented", such as a terminal or mailbox. .lm -8.se1 The other two arguments are the input and outputt3 filenames respectively. Redirection is supported,e. however, the output must be a disk/tape file.3 The file format is almost identical to the currento7 Unix implementation of compress (V4.0). Files written76 by Unix compress should be readable by lzdcmp. Files0 written by lzcomp in export (-x) format will be6 readable by Unix compress (except that lzcomp outputs0 two "clear" codes to mark EOF. A patch to Unix compress is available.)VMS Restrictions5 VMS Private mode stores the true name and attributesn6 of the input file into the compressed file and lzdcmp5 restores the attributes (and filename if requested).17 The following restrictions apply -- they may be liftedd8 in the future as they are primarily due to the author's8 lack of understanding of the intricacies of of VMS I/O:& All files must be stored on disk.7 The lzcomp output file must be specified directly.H5 Also, for all usage on VMS, the compressed file must# be written to, and read from disk.eLZW compression algorithm 6 This section is abstracted from Terry Welch's article1 referenced below. The algorithm builds a stringo4 translation table that maps substrings in the input5 into fixed-length codes. The compress algorithm mayE be described as follows:B2 1. Initialize table to contain single-character strings.4 2. Read the first character. Set (the prefix string) to that character.+ 3. (step): Read next input character, K.i1 4. If at end of file, output code(); exit."% 5. If K is in the string table:c Set to K; goto step 3.y+ 6. Else K is not in the string table.e Output code(); ! Put K into the string table;k Set to K; Goto step 3.9 "At each execution of the basic step an acceptable inpute9 string has been parsed off. The next character K isi9 read and the extended string K is tested to see if itl6 exists in the string table. If it is there, then the6 extended string becomes the parsed string and the7 step is repeated. If K is not in the string table,2 then it is entered, the code for the successfully4 parsed string is put out as comprssed data, the6 character K becomes the beginning of the next string, and the step is repeated."5 The decompression algorithm translates each received < code into a prefix string and extension [suffix] character.: The extension character is stored (in a push-down stack),7 and the prefix translated again, until the prefix is at8 single character, which completes decompression of this5 code. The entire code is then output by popping the stack.y> "An update to the string table is made for each code received: (except the first one). When a code has been translated,8 its final character is used as the extension character,7 combined with the prior string, to add a new string tos8 the string table. This new string is assigned a unique7 code value, which is the same code that the compressor 8 assigned to that string. In this way, the decompressor6 incrementally reconstructs the same string table that< the decompressor used.... Unfortunately ... [the algorithm]$ does not work for an abnormal case.< The abnormal case occurs whenever an input character string4 contains the sequence KKK, where K already) appears in the compressor string table."y1 The decompression algorithm, augmented to handleg" the abnormal case, is as follows: 1. Read first input code; Store in CODE and OLDcode;3 With CODE = code(K), output(K); FINchar = K;a, 2. Read next code to CODE; INcode = CODE; If at end of file, exit;5 3. If CODE not in string table (special case) then Output(FINchar); CODE = OLDcode;" INcode = code(OLDcode, FINchar); 4. If CODE == code(K) then Push K onto the stack; CODE == code(); Goto 4. 5. If CODE == code(K) then Output K; FINchar = K; 6. While stack not empty Output top of stack; Pop stack;* 7. Put OLDcode,K into the string table. OLDcode = INcode;F Goto 2.O< The algorithm as implemented here introduces two additional complications.C9 The actual codes are transmitted using a variable-lengthD9 encoding. The lowest-level routines increase the numberC6 of bits in the code when the largest possible code is transmitted.D7 Periodically, the algorithm checks that compression isN9 still increasing. If the ratio of input bytes to output8 bytes decreases, the entire process is reset. This can8 happen if the characteristics of the input file change.VMS Private File Structure7 In VMS Private mode, the compressed data file contains8 a variable-length (but compressed) file header with the4 file "attributes" needed by the operating system to4 construct the file. This allows the decompression5 program to recreate the file in its original format,5 which is essential if ISAM databases are compressed.' The overall file format is as follows: .lm +8 .p -8: LZ_SOH "start of header" signal (this value cannot appear in user data).2 A variable-length data record (maximum 256 bytes)= containing the header name, followed by whitespace, followed8 by header-specific information. In this case, the name9 record will contain the string "vms$attributes" followed4 by the number of bytes in the attribute data block.: (I assume that the name record will consist of a facility9 name, such as "vms", followed by a dollar sign, followed by a facility-unique word.) .p -8 LZ_EOR Signals "end of record".< This is followed by a VMS file attributes record (generated" by a VMS system library routine). .p -8! LZ_ETX Signals "end of segment". .p -8; ST_STX Signals "start of text" (i.e., start of data file).( This is followed by the user data file. .p -8 LZ_ETX Signals "end of segment" .p -8+ LZ_ETX Two in a row signals "end of file". .s.lm -88 Note that this format can easily be extended to include8 trailer records (with file counts and checksums) and/or, multiple data files in one compressed file.7 Note also that the LZ_CLEAR code may appear in headers4 or data files to cause the decompression program to4 "readapt" to the characteristics of the input data.3 LZ_STX and LZ_SOH reset the compression algorithm. LZ_EOR does not.Authors8 The algorithm is from "A Technique for High Performance: Data Compression." Terry A. Welch. IEEE Computer Vol 17, No. 6 (June 1984), pp 8-19." This revision is by Martin Minow.& Unix Compress authors are as follows: .s.nf8 Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) Jim McKie (decvax!mcvax!jim). Steve Davies (decvax!vax135!petsd!peora!srd)- Ken Turkowski (decvax!decwrl!turtlevax!ken)( James A. Woods (decvax!ihnp4!ames!jaw)% Joe Orost (decvax!vax135!petsd!joe) .s.f#endif/*, * Compatible with compress.c, v3.0 84/11/27 *//*)BUILD $(PROGRAM) = lzcomp $(INCLUDE) = lz.h $(CPP) = 1: $(FILES) = { lzcmp1.c lzcmp2.c lzcmp3.c lzio.c lzvio.c }*/ D#include "lz.h"i #ifdef unixo#include #include s#endif/*> * These global parameters are written to the compressed file.D * The decompressor needs them. The initialized values are defaults. * and are modified by command line arguments. */ 6short maxbits = BITS; /* settable max # bits/code */<code_int maxmaxcode = 1 << BITS; /* Totally largest code */5code_int hsize = HSIZE; /* Actual hash table size */t/*9 * Flags (command line arguments) to control compression.t */y #if VMS_V42flag export = 0; /* Assume vms "private" mode */#else+4flag export = 1; /* Assume Unix compatible mode */#endif;flag block_compress = TRUE; /* Assume block compression */S7flag binary = FALSE; /* Reading text file if FALSE */e5flag noheader = FALSE; /* No magic header if TRUE */f@flag verbose = VERBOSE_DEFAULT; /* Non-zero for status/debug */7flag background = FALSE; /* TRUE (Unix) if detached */n=readonly flag is_compress = TRUE; /* for lzio.c (needed?) */t-long fsize; /* Input file size in bytes */a4char *infilename = NULL; /* For error printouts */:char *outfilename = NULL; /* For openoutput and errors */1int firstcode; /* First code after internals */f<count_int tot_incount = 0; /* Total number of input bytes */>count_int tot_outcount = 0; /* Total number of output codes */extern count_int in_count;extern count_int out_count;s8static long start_time; /* Time we started (in msec) */:extern long cputime(); /* Returns process time in msec */STREAM instream;STREAM outstream;char_type inbuffer[MAXIO];char_type outbuffer[MAXIO];static STREAM mem_stream;jmp_buf failure; #if VMS_V4#include types #include stat#include descrip#ifndef FDLSTUFF#define FDLSTUFF char#endifFDLSTUFF *fdl_input;FDLSTUFF *fdl_output;,static struct dsc$descriptor fdl_descriptor;#endif main(argc, argv) int argc;char *argv[];/* * Compress mainline */{ #ifndef decus /*E * background is TRUE if running detached from the command terminal. */B background = (signal(SIGINT, SIG_IGN) == SIG_IGN) ? TRUE : FALSE; if (!background)* background = !isatty(fileno(stderr)); if (!background) { if (verbose > 0) signal(SIGINT, abort); else { signal(SIGINT, interrupt);! signal(SIGSEGV, address_error); } }#endif if (setjmp(failure) == 0) {6 setup(argc, argv); /* Command line parameters */1 openinput(); /* Open input, set instream *// getfilesize(); /* Get input file size */5 gethashsize(); /* Get actual hash table size */2 initialize(); /* Set maxbits and the like */+ openoutput(); /* Open output file */ if (verbose > 0) start_time = cputime(); put_magic_header(); init_compress(TRUE); compress(&instream); #if VMS_V4 if (export == 0) { outputcode((code_int) LZ_ETX); outputcode((code_int) LZ_ETX); fdl_close(fdl_input); } else#endif if (block_compress) {" outputcode((code_int) LZ_CLEAR);" outputcode((code_int) LZ_CLEAR); }; outputcode((code_int) -1); /* Flush output buffers */ #if VMS_V4 if (export == 0) fdl_close(fdl_output); else { fclose(stdout); }#else fclose(stdout);#endif if (verbose > 0) {& start_time = cputime() - start_time; tot_incount += in_count; tot_outcount += out_count;2 fprintf(stderr, "%ld chars in, %ld bytes out, ",! tot_incount, tot_outcount); if (tot_outcount > 0) {# divout("compression ratio: ",0 (long) tot_incount, (long) tot_outcount, ""); divout(" (",4 ((long) tot_incount - (long) tot_outcount) * 100, (long) tot_incount, "%)\n"); } fprintf(stderr,< "%ld.%02ld seconds (process time) for compression.\n",6 start_time / 1000L, (start_time % 1000L) / 10L); if (start_time > 0) {, divout(" ", (long) tot_incount * 10L, (start_time + 50L) / 100L,! " input bytes per second.\n"); } } exit(IO_SUCCESS); } else {A fprintf(stderr, "Error when compressing \"%s\" to \"%s\"\n", (infilename == NULL) ? * "" : infilename, (outfilename == NULL) ?- "" : outfilename); if (errno != 0) perror("lzcomp fatal error"); exit(IO_ERROR); }} %divout(leader, numer, denom, trailer)char *leader; long numer; long denom;char *trailer;/*> * Print numer/denom without floating point on small machines. */{! fprintf(stderr, "%s%ld.%02ld%s",G leader, numer / denom, ((numer % denom) * 100L) / denom, trailer);}static initialize()/* * Mung some global values. */{9 if (maxbits < INIT_BITS) /* maxbits is set by the -M */7 maxbits = INIT_BITS; /* option. Make sure it's */5 if (maxbits > BITS) /* within a reasonable range */ maxbits = BITS;5 maxmaxcode = 1 << maxbits; /* Truly biggest code */ if (export == 0). firstcode = LZ_FIRST; /* VMS private */ else if (block_compress). firstcode = LZ_CLEAR + 1; /* Default */ else2 firstcode = 256; /* Backwards compatible */} put_magic_header()/* * Write the magic header bits. */{#ifndef COMPATIBLE if (export && !noheader) {" PUT(HEAD1_MAGIC, &outstream);" PUT(HEAD2_MAGIC, &outstream);7 PUT(maxbits | ((block_compress) ? BLOCK_MASK : 0), &outstream); } #if VMS_V4 else if (export == 0) { char text[256]; /*/ * VMS private mode (with attribute block) */" PUT(HEAD1_MAGIC, &outstream);& PUT(VMS_HEAD2_MAGIC, &outstream);4 PUT((char) (maxbits | BLOCK_MASK), &outstream);( PUT(firstcode - 0x100, &outstream); init_compress(); outputcode(LZ_SOH); #if DEBUG( if (strlen(ATT_NAME) != ATT_SIZE) {* fprintf("\"%s\", expected %d, got %d\n",, ATT_NAME, ATT_SIZE, strlen(ATT_NAME)); }#endifC sprintf(text, "%s%d;", ATT_NAME, fdl_descriptor.dsc$w_length);& mem_compress(text, strlen(text)); outputcode(LZ_EOR);/ mem_compress(fdl_descriptor.dsc$a_pointer,! fdl_descriptor.dsc$w_length); fdl_free(&fdl_descriptor); outputcode(LZ_ETX); outputcode(LZ_STX); }#endif#endif}mem_compress(datum, length)char_type *datum; int length;/* * Compress from memory */{+ mem_stream.bp = mem_stream.bstart = datum; mem_stream.bsize = length;" mem_stream.bend = datum + length; mem_stream.func = lz_eof; compress(&mem_stream);} /*@ * This routine is used to tune the hash table size according to> * the file size. If the filesize is unknown, fsize should be * set to zero. */typedef struct TUNETAB { long fsize; code_int hsize; } TUNETAB;%static readonly TUNETAB tunetab[] = {#if HSIZE > 5003 { 1 << 12, 5003 },#endif#if HSIZE > 9001 { 1 << 13, 9001 },#endif#if HSIZE > 18013 { 1 << 14, 18013 },#endif#if HSIZE > 35023 { 1 << 15, 35023 }, { 47000, 50021 },#endif { 0, 0 },};static gethashsize()/*2 * Tune the hash table parameters for small files.< * We don't have a good way to find the file size on vms V3., * fsize is set to zero if we can't find it. */{ register TUNETAB *tunep; hsize = HSIZE; if (fsize > 0) {8 for (tunep = tunetab; tunep->fsize != 0; tunep++) { if (fsize < tunep->fsize) { hsize = tunep->hsize; break; } } }} static getfilesize()/*: * Set fsize to the input filesize (in bytes) if possible.# * Magic for all operating systems. */{ #ifdef rsx: extern char f_efbk; /* F.EFBK -- highest block in file */A#define fdb(p,offset) (stdin->io_fdb[((int) &p + offset)] & 0xFF)(#define efbk(offset) fdb(f_efbk, offset)1 extern char f_rtyp; /* F.RTYP -- Record type */7 extern char f_ratt; /* F.RATT -- Record attributes */ /*7 * Note: Block number is stored high-order word first. */ fsize = efbk(2) + (efbk(3) << 8)e + (efbk(0) << 16) + (efbk(1) << 24);  fsize *= 512;#endif #ifdef rt11i/ fsize = stdin->io_size; /* Set by Decus C */o fsize *= 512;#endif #ifdef vms #if VMS_V4 struct stat statbuf;t fsize = 0;i if (export != 0) {l- if (fstat(fileno(stdin), &statbuf) == 0)s! fsize = (long) statbuf.st_size;e } else {s) fsize = (long) fdl_fsize(fdl_input);t }#elseX( fsize = 0; /* Can't find filesize */#endif#endif #ifdef unix  struct stat statbuf;l fsize = 0;c) if (fstat(fileno(stdin), &statbuf) == 0)e$ fsize = (long) statbuf.st_size;#endif}> i$static readonly char *helptext[] = {$ "The following options are valid:",; "-B\tBinary file (important on VMS/RSX, ignored on Unix)",i: "-M val\tExplicitly set the maximum number of code bits",= "-V val\tPrint status information (or debugging) to stderr",a+ "-X val\tSet export (compatiblity) mode:",B #if VMS_V4. " -X 0\tExplicitly choose VMS Private mode",#endifA " -X 1\t(default if -X specified, output format is compatible",n# "\twith Unix compress V3.0",@ " -X 2\tCompatible with Unix compress 3.0, block compression", "\tsupressed.",#ifdef COMPATIBLE 6 " -X 3No header (file is readable by old compress)",#endif NULL,};staticsetup(argc, argv)n int argc;char *argv[];/*: * Get parameters and open files. Exit fatally on errors. */ {B register char *ap;e register int c; char **hp; auto int i; int j; #ifdef vms# argc = getredirection(argc, argv); #endif! for (i = j = 1; i < argc; i++) {  ap = argv[i];5 if (*ap++ != '-' || *ap == EOS) /* Filename? */e+ argv[j++] = argv[i]; /* Just copy it */; else {u while ((c = *ap++) != EOS) { if (islower(c))r c = toupper(c); switch (c) { case 'B':r binary = TRUE; break;o case 'M':T$ maxbits = getvalue(ap, &i, argv); if (maxbits < MIN_BITS) {- fprintf(stderr, "Illegal -M value\n");/ goto usage; } break;n case 'V':*$ verbose = getvalue(ap, &i, argv); break;m case 'X':a# export = getvalue(ap, &i, argv);t" if (export < 0 || export > 3) {9 fprintf(stderr, "Illegal -X value: %d\n", export);p goto usage; }' block_compress = "\1\1\0\0"[export];S' noheader = "\0\0\0\1"[export];' export = "\0\1\1\1"[export];$ break;f default:5 fprintf(stderr, "Unknown option '%c' in \"%s\"\n", *ap, argv[i]);/usage: for (hp = helptext; *hp != NULL; hp++)u$ fprintf(stderr, "%s\n", *hp); FAIL("usage");" } /* Switch on options */ } /* Everything for -xxx */ } /* If -option */ } /* For all argc's */s5 /* infilename = NULL; */ /* Set "stdin" signal */5 /* outfilename = NULL; */ /* Set "stdout" signal */,* switch (j) { /* Any file arguments? */# case 3: /* both files given */(8 if (!streq(argv[2], "-")) /* But - means stdout */ outfilename = argv[2];# case 2: /* Input file given */* if (!streq(argv[1], "-")) { infilename = argv[1];g } break;  case 0: /* None! */ $ case 1: /* No file arguments */ break; default:(2 fprintf(stderr, "Too many file arguments\n"); FAIL("too many files"); }}t g static intgetvalue(ap, ip, argv)register char *ap;i int *ip;char *argv[];i/*H * Compile a "value". We are currently scanning *ap, part of argv[*ip]. * The following are possible:7 * -x123 return (123) and set *ap to EOS so the caller{$ * ap^ cycles to the next argument. *6 * -x 123 *ap == EOS and argv[*ip + 1][0] is a digit.3 * return (123) and increment *i to skip over the_ * next argument.= *1 * -xy or -x y return(1), don't touch *ap or *ip.s *D * Note that the default for "flag option without value" is 1. This@ * can only cause a problem for the -M option where the value is@ * mandatory. However, the result of 1 is illegal as it is less * than INIT_BITS. */{  register int result;o register int i; i = *ip + 1; if (isdigit(*ap)) { result = atoi(ap);  *ap = EOS;g } else if (*ap == EOS && argv[i] != NULLt && isdigit(argv[i][0])) { result = atoi(argv[i]); *ip = i; } else {t result = 1; } return (result); }e o openinput().{, #ifdef decus if (infilename == NULL) {" infilename = malloc(256 + 1);! fgetname(stdin, infilename);_> infilename = realloc(infilename, strlen(infilename) + 1); } else {nE if (freopen(infilename, (binary) ? "rn" : "r", stdin) == NULL) {s perror(infilename);r FAIL("can't reopen input");  } }#elseL #ifdef vms #if VMS_V4 if (export == 0) {m char *fname; char filename[256];f( if ((fname = infilename) == NULL) { fgetname(stdin, filename); fname = filename;i }B if ((fdl_input = fdl_open(fname, &fdl_descriptor)) == NULL) { if ((fdl_status & 01) == 0) { fdl_message(NULL, fname);m FA.IL("can't fdl_open");  }a fprintf(stderr,: "Cannot open \"%s\" in vms private format,", fname);. fprintf(stderr, " trying export format.\n"); export = TRUE; goto try_export; } fclose(stdin); stdin = NULL;" infilename = malloc(256 + 1);4 infilename = realloc(fname, strlen(fname) + 1); if (verbose > 1) {x< fprintf(stderr, "FDL information for \"%s\"\n", filename);$ fdl_dump(&fdl_descriptor, stderr); } goto opened;i } try_export:#endS.3~LZ.SAV.F[SYSDEV.PERROT.LZ]LZCMP1.C;1H66/if if (infilename == NULL) {" infilename = malloc(256 + 1);! fgetname(stdin, infilename);/> infilename = realloc(infilename, strlen(infilename) + 1); } else { #if VMS_V4= if ((stdin = freopen(infilename, "r", stdin)) == NULL) {i#elseO3 if (freopen(infilename, "r", stdin) == NULL) {1#endif perror(infilename);H exit(IO_ERROR);e } }#elsei if (infilename == NULL) infilename = "stdin"; else {3 if (freopen(infilename, "r", stdin) == NULL) {[ perror(infilename);  exit(IO_ERROR);( }  }#endif#endif+opened: instream.bp = instream.bend = NULL;V instream.bstart = inbuffer;" instream.bsize = sizeof inbuffer; instream.func = lz_fill;f}t e openoutput()/*? * Open the output file (after the input file has been opened).7 * if outfilename == NULL, it's already open on stdout.% */e{c if (outfilename == NULL) {_ #if VMS_V4*#if 0 /* The following doesn't work */# outfilename = malloc(256 + 1);_# fgetname(stdout, outfilename);cA outfilename = realloc(outfilename, strlen(outfilename) + 1);m if (export == 0) {a fclose(stdout);_4 stdout = NULL; /* Can't do terminal test below */= if ((fdl_output = fdl_create(NULL, outfilename)) == NULL) {! if ((fdl_status & 01) == 0)d" fdl_message(NULL, outfilename);< fprintf(stderr, "Can't create \"%s\"\n", outfilename); FAIL("can't fdl_create");m }m }#else  fprintf(stderr,7 "Restriction: The output file must be specified.\n");m& FAIL("can't redirect on VMS V4");#endif#elsee #ifdef vms# outfilename = malloc(256 + 1);e# fgetname(stdout, outfilename);wA outfilename = realloc(outfilename, strlen(outfilename) + 1);B#else #ifdef decus# outfilename = malloc(256 + 1);t# fgetname(stdout, outfilename);A outfilename = realloc(outfilename, strlen(outfilename) + 1);1#else  outfilename = "";#endif#endif#endif } else {} #if VMS_V4 if (export == 0) {  fclose(stdout);4 stdout = NULL; /* Can't do terminal test below */= if ((fdl_output = fdl_create(NULL, outfilename)) == NULL) {p! if ((fdl_status & 01) == 0)o" fdl_message(NULL, outfilename); fprintf(stderr,i7 "Can't create \"%s\" (VMS private)\n", outfilename);e FAIL("can't fdl_create");I } } else { 2 if (freopen(outfilename, "w", stdout) == NULL) { perror(outfilename); FAIL("can't create");h } }#else #ifdef decus6 if (freopen(outfilename, "wn", stdout) == NULL) { perror(outfilename); FAIL("can't create");g }#elsea5 if (freopen(outfilename, "w", stdout) == NULL) {b perror(outfilename); FAIL("can't create");  }#endif#endif }0 if (stdout != NULL && isatty(fileno(stdout))) {8 fprintf(stderr, "%s: is a terminal. We object.\n", outfilename); FAIL("can't create"); }- outstream.bp = outstream.bstart = outbuffer; / outstream.bend = outbuffer + sizeof outbuffer;f$ outstream.bsize = sizeof outbuffer; outstream.func = lz_flush; }(*[SYSDEV.PERROT.LZ]LZCMP2.C;1+,H./E 4O-F0123KPWO56@m7%8= #9GEHJ,/* * l z c m p 2 . c  *9 * Actually do compression. Terminology (and algorithm): *E * Assume the input string is "abcd", we have just processed "ab" andpF * read 'c'. At this point, a "prefix code" will be assigned to "ab".E * Search in the prefix:character memory (either the "fast memory" or*D * the hash-code table) for the code followed by this character. IfA * found, assign the code found to the "prefix code" and read therA * next character. If not found, output the current prefix code,s@ * generate a new prefix code and store "old_prefix:char" in the- * table with "new_prefix" as its definition. * * Naming conventions:- * code a variable containing a prefix coden0 * c or char a variable containing a character *F * There are three tables that are searched (dependent on compile-time& * and execution time considerations):C * fast Direct table-lookup -- requires a huge amount of physical*) * (non-paged) memory, but is very fast. " * hash Hash-coded table-lookup.A * cache A "look-ahead" cache for the hash table that optimizes"A * searching for the most frequent character. This considerably*; * speeds up processing for raster-images (for example) at  * a modest amount of memory.I * Structures are used to hold the actual tables to simplify organizationa * of the program. * * Subroutines: B * compress() performs data compression on an input datastream.C * init_compress() called by the output routine to clear tables.  */#include "lz.h"=/* * General variables6 * Cleared by init_compress on a "hard initialization"0 * outputcode() in lzcmp3.c refers to next_code. */*long int in_count; /* Length of input */7long int out_count; /* Bytes written to output file */;static flag first_clear = TRUE; /* Don't zero first time */,code_int next_code; /* Next output code */Gstatic count_int checkpoint = CHECK_GAP; /* When to test ratio again */4static long ratio = 0; /* Ratio for last segment *//*E * These global parameters are set by mainline code. Unchanged here. */5extern short maxbits; /* Settable max # bits/code */?extern short block_compress; /* For old-style compatibility */=extern code_int maxmaxcode; /* Actual maximum output code */2extern long tot_incount; /* Total input count */4extern long tot_outcount; /* Total output count */5extern code_int hsize; /* Actual hash table size */#ifdef XENIX_16static count_int htab0[8192];static count_int htab1[8192];static count_int htab2[8192];static count_int htab3[8192];static count_int htab4[8192];static count_int htab5[8192];static count_int htab6[8192];static count_int htab7[8192];&static count_int htab8[HSIZE - 65536]; static count_int *hashtab[9] = {A htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8};static U_short code0[16384];static U_short code1[16384];static U_short code2[16384];static U_short code3[16384];$static U_short code4[HSIZE - 65536];static U_short *codetab[5] = {% code0, code1, code3, code3, code4}@#define HASH(i) (hashtab[((unsigned) (i)) >> 13][(i) & 0x1FFF])@#define CODE(i) (codetab[((unsigned) (i)) >> 14][(i) & 0x3FFF])#elsecount_int hashtab[HSIZE];U_short codetab[HSIZE];#define HASH(i) hashtab[i]#define CODE(i) codetab[i]#endif /* * compress a datastream *M * Algorithm: on large machines, for maxbits <= FBITS, use fast direct tableL * lookup on the prefix code / next character combination. For smaller codeO * size, use open addressing modular division double hashing (no chaining), alaM * Knuth vol. 3, sec. 6.4 Algorithm D, along with G. Knott's relatively-primeM * secondary probe. Do block compression with an adaptive reset, whereby theL * code table is cleared when the compression ratio decreases, but after theM * table fills. The variable-length output codes are re-sized at this point,rJ * and a special LZ_CLEAR code is generated for the decompressor. For theG * megamemory version, the sparse array is cleared indirectly through aiG * "shadow" output code history. Late additions: for the hashing code,tN * construct the table according to file size for noticeable speed improvementH * on small files. Also detect and cache codes associated with the mostO * common character to bypass hash calculation on these codes (a characteristiceM * of highly-compressable raster images). Please direct questions about thisd * implementation to ames!jaw. */[ compress(in)+STREAM *in; /* Input stream structure */p/*F * Compress driver. Global fsize is the size of the entire datastream? * (from LZ_STX or LZ_SOH to the terminating LZ_ETX). You must K * force a reinitialization -- by calling outputcode() with a new header --eD * if size is changed. If the "newer" output format is chosen (withA * data streams delimited by LZ_SOH/LZ_STX, init_compress will beF * called automatically. Otherwise, you must call init_compress(TRUE)0 * before calling compress() for the first time. */{1 register long hash_code; /* What we look for *// register code_int i; /* Index into vectors */+ register int c; /* Current input char */. register code_int code; /* Substring code */5 register int displacement; /* For secondary hash */6 register code_int hsize_reg; /* Size of hash table */, register int hshift; /* For xor hasher */ if ((code = GET(in)) == EOF)< return; in_count++; hsize_reg = hsize;l /* * Set hash code range bound  */ hshift = 0;D for (hash_code = (long) hsize; hash_code < 65536L; hash_code <<= 1) hshift++; hshift = 8 - hshift; * while ((c = GET(in)) != (unsigned) EOF) { in_count++;7 hash_code = (long) (((long) c << maxbits) + code);e2 i = (c << hshift) ^ code; /* XOR hashing */< if (HASH(i) == hash_code) { /* Found at first slot? */ code = CODE(i);r continue;  }3 else if ((long) HASH(i) < 0) /* empty slot */= goto nomatch;o7 displacement = hsize_reg - i; /* secondary hash */  if (i == 0) displacement = 1;mprobe:5 if ((i -= displacement) < 0) /* Wrap around? */, i += hsize_reg;a< if (HASH(i) == hash_code) { /* Found in hash table? */- code = CODE(i); /* Set new prefix code */l( continue; /* Read next input char */ }; else if ((long) HASH(i) > 0) /* If slot is occupied */r) goto probe; /* Look somewhere else */hnomatch: /*g= * Output the current prefix and designate a new prefix.r< * If the input character was the "hog", save it in the> * look-ahead cache table. Then, save in the hash table. */< outputcode((code_int) code); /* No match, put prefix */#if SIGNED_COMPARE_SLOW8 if ((unsigned) next_code < (unsigned) maxmaxcode) {#elseo" if (next_code < maxmaxcode) {#endif1 CODE(i) = next_code++; /* code -> hashtable */i HASH(i) = hash_code; } else if (block_compress, && (count_int) in_count >= checkpoint) { clear(); }+ code = c; /* Start new substring */v } /*v# * At EOF, put out the final code.o */ outputcode((code_int) code);}m Aclear()(/*< * Check the compression ratio to see whether it is going up: * or staying the same. If it is going down, the internal8 * statistics of the file have changed, so clear out our9 * tables and start over. Inform the decompressor of the ) * change by sending out a LZ_CLEAR code.e */{d register long int rat;y# checkpoint = in_count + CHECK_GAP; #if DEBUGe if (verbose > 2) {a9 divout("at clear() test", in_count, out_count, "");d= fprintf(stderr, ", ratio at entry: %ld.%02ld, gap %d\n",e7 rat / 256L, ((rat & 255L) * 100L) / 256L, CHECK_GAP);; }#endif8 if (in_count > 0x007FFFFL) { /* Shift will overflow */ rat = out_count >> 8; if (rat == 0) rat = 0x7FFFFFFFL; else { rat = in_count / rat;e } } else {l' rat = (in_count << 8) / out_count;x } if (rat > ratio)s ratio = rat; else {l #if DEBUG= if (verbose > 0) {t= fprintf(stderr, "Resetting compression, in %ld, out %ld\n",o in_count, out_count);a2 fprintf(stderr, "Old ratio: %ld == (%ld.%02ld)",; ratio, ratio / 256L, ((ratio & 255L) * 100L) / 256L);b> fprintf(stderr, ", test ratio: %ld = (%ld.%02ld), gap %d\n",@ rat, rat / 256L, ((rat & 255L) * 100L) / 256L, CHECK_GAP); }#endif? outputcode((code_int) LZ_CLEAR); /* Calls init_compress */  }}s einit_compress(full_init)4flag full_init; /* TRUE for full initialization *//*> * Clear the tables. Called by outputcode() on LZ_SOH, LZ_STX5 * (full_init TRUE) or on LZ_CLEAR (full_init FALSE). + * init_compress() is not called on LZ_EOR.u */0{*#ifdef XENIX_16o register count_int *hp; register int n;x register int j;c register code_int k;r k = hsize;e for (j = 0; k > 0; k -= 8192) { i = (k < 8192) ? k : 8192;s hp = hashtab[j++];  n = i >> 4; switch (i & 15) { case 15: *hp++ = -1;  case 14: *hp++ = -1;S case 13: *hp++ = -1;  case 12: *hp++ = -1; case 11: *hp++ = -1; case 10: *hp++ = -1; case 9: *hp++ = -1; case 8: *hp++ = -1; case 7: *hp++ = -1; case 6: *hp++ = -1; case 5: *hp++ = -1; case 4: *hp++ = -1; case 3: *hp++ = -1; case 2: *hp++ = -1; case 1: *hp++ = -1; } while (--n >= 0) {1 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;1 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;1 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;1 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;m }n }#elseo register count_int *hp; register code_int n;i hp = &hashtab[0];' n = hsize >> 4; /* divide by 16 */t switch (hsize & 15) { case 15: *hp++ = -1;o case 14: *hp++ = -1;e case 13: *hp++ = -1;y case 12: *hp++ = -1;r case 11: *hp++ = -1;e case 10: *hp++ = -1;l case 9: *hp++ = -1;. case 8: *hp++ = -1;t case 7: *hp++ = -1;r case 6: *hp++ = -1;r case 5: *hp++ = -1;f case 4: *hp++ = -1;c case 3: *hp++ = -1;* case 2: *hp++ = -1;c case 1: *hp++ = -1;i } while (--n >= 0) {w4 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;4 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;4 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1;4 *hp++ = -1; *hp++ = -1; *hp++ = -1; *hp++ = -1; }#endif if (full_init) {e tot_incount += in_count; tot_outcount += out_count;r in_count = 0; out_count = 0;n ratio = 0;  } first_clear = FALSE;s next_code = firstcode;.}**[SYSDEV.PERROT.LZ]LZCMP3.C;1+,./E 4H -F0123KPWO56`^m7 %89#9GEHJ/* * l z c m p 3 . c * Output a given code. */#include "lz.h"extern STREAM outstream;extern code_int next_code;=extern code_int maxmaxcode; /* Actual maximum output code */extern short maxbits;extern count_int out_count;static char_type buf[BITS];static int offset;Cstatic short n_bits = INIT_BITS; /* # of bits in compressed file */&static short n_bits8 = INIT_BITS << 3;-static code_int maxcode = MAXCODE(INIT_BITS); #if !vax_asm&static readonly char_type lmask[9] = {8 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};&static readonly char_type rmask[9] = {8 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};#endif #if DEBUGextern int col;static int todump;#endifoutputcode(code)code_int code;/* * Output the given code. * Inputs:B * code: A n_bits-bit integer. If == -1, then EOF. This assumes& * that n_bits <= (long)wordsize - 1.C * Note: if not in "export" mode, the following values are special:8 * LZ_CLEAR (also in export mode if block_compress TRUE)3 * (soft) clear out compress tables and reset the, * number of bits per code to the minimum.F * LZ_SOH, LZ_STX (hard) clear out compress tables and reset as above.A * LZ_ETX, LZ_EOR force out the current output segment, analogous * to fflush. * * Outputs:: * Outputs code to the file. If the codespace has filled0 * (next_code >= (1 << n_bits), increase n_bits.7 * If LZ_CLEAR, LZ_SOH, or LZ_STX is seen, reset n_bits7 * to the initial value and call init_compress to resetn * the lookup and cache tables. * * Assumptions: : * Output chars are 8 bits long. This is deeply hardwired: * into the algorithm. It is independent, however, of the * size of the input data. * * Algorithm:? * Maintain a BITS character long buffer (so that 8 codes willC * fit in it exactly). Use the VAX insv instruction to insert eachC * code in turn. When the buffer fills up empty it and start over. */{ /*H * On the VAX (Unix), it is important to have the register declarations6 * in exactly the order given, or the asm will break. */ register int r_off, bits; register char_type *bp; #if !vax_asm register code_int r_code;#endif r_off = offset; bits = n_bits; bp = buf; if (code >= 0) {d /* * Not at EOF, add the code */ #if DEBUGG if (verbose > 3) {u fprintf(stderr, "%c%5d %5d",2 ((col += 12) >= 72) ? (col = 0, '\n') : ' ', code, next_code); - if (code >= LZ_CLEAR && code < firstcode) {a: fprintf(stderr, " = %s", lz_names[code - LZ_CLEAR]); col = 74;g }o }#endif #if vax_asm /*e? * VAX DEPENDENT!! Implementation on other machines may bec * difficult. * C * Translation: Insert BITS bits from the argument starting at. * offset bits from the beginning of buf. */# 0; /* C compiler bug ?? */ $ asm("insv 4(ap),r11,r10,(r9)");#else" /*I; * WARNING: byte/bit numbering on the vax is simulated- * by the following codeo */5 bp += (r_off >> 3); /* -> first output slot */n r_off &= 7; /*oC * Since code is always >= 8 bits, only need to mask the firstC * hunk on the left.A */ r_code = code;cC *bp = (*bp & rmask[r_off]) | (r_code << r_off) & lmask[r_off];W bp++; bits -= (8 - r_off);n r_code >>= 8 - r_off; /*cD * Get any 8 bit parts in the middle ( <= 1 for up to 16 bits). */ if (bits >= 8) {e *bp++ = r_code;w r_code >>= 8; bits -= 8; }' if (bits != 0) /* Last bits. */x *bp = r_code;y#endif offset += n_bits; if (offset == n_bits8) {) out_count += n_bits;% lz_putbuf(buf, n_bits, &outstream); #if DEBUGO if (todump > 0) {c# dumphex(buf, n_bits, stderr);S todump -= n_bits;a }L#endif offset = 0;f } /*eC * If the next entry is going to be too big for the code size,(- * then increase it, if possible. Note:F+ * !export firstcode == LZ_FIRSTn= * export && block_compress firstcode == LZ_CLEAR + 1H: * export && !block_compress firstcode == LZ_CLEAR */ if (next_code > maxcode) {k if (offset > 0) {") lz_putbuf(buf, n_bits, &outstream);a out_count += n_bits; offset = 0;a #if DEBUG  if (todump > 0) {y dumphex(buf, n_bits, stderr); todump -= n_bits; }0#endif }=" n_bits++; /* Need more bits */ n_bits8 += (1 << 3); if (n_bits == maxbits) maxcode = maxmaxcode;  else maxcode = MAXCODE(n_bits); #if DEBUGt if (verbose > 2) { fprintf(stderr,l. "%snext_code %d, change to %d bits max %d",$ (col > 0) ? "\n" : "", next_code, n_bits, maxcode); col = 74;G }C#endif }0 if (code >= LZ_CLEAR && code < firstcode) { switch (code) {N case LZ_SOH: case LZ_STX: case LZ_CLEAR: if (offset > 0) {L& lz_putbuf(buf, n_bits, &outstream); out_count += n_bits;+ offset = 0; #if DEBUGl if (todump > 0) {$ dumphex(buf, n_bits, stderr); todump -= n_bits; }#endif }T- n_bits = INIT_BITS; /* Reset codes */  n_bits8 = INIT_BITS << 3;t# maxcode = MAXCODE(INIT_BITS);!& init_compress(code != LZ_CLEAR); #if DEBUGL if (verbose > 2) { fprintf(stderr,= "\n(%s) Change to %d bits, maxcode %d, next_code = %d", ! lz_names[code - LZ_CLEAR],S# n_bits, maxcode, next_code);s col = 74; todump = 32;c }s#endif break; case LZ_EOR:' case LZ_ETX: /* Just written out */ break; default:$ abort(); /* Can't happen */ }  } } else {: /*i- * At EOF, write the rest of the buffer.u */ if ((r_off = offset) > 0) { r_off += 7; r_off >>= 3;$ lz_putbuf(buf, r_off, &outstream); out_count += r_off;i #if DEBUG  if (todump > 0) { " dumphex(buf, r_off, stderr); todump -= r_off; }e#endif } offset = 0;5 lz_flush(&outstream); /* Flush output buffer */a #if DEBUG% if (verbose > 3 || todump > 0) {c fprintf(stderr, "\n*EOF*\n");d col = 0; }#endif }}I*[SYSDEV.PERROT.LZ]LZDCM.EXE;1+,/%.l/E 4lk-F0123 KPWOm56+7%8z#9GEHJ$0DX0205(6>h,N]LZDCM1V1.0604-00   A[ \ ?(! FDLSHR_001?!d FORRTL_001v!  LIBRTL_001Y       N .*;*.*;*/sys$disk...*;*.*;*DIR.DIRF O V ] d k P`D ,,LX $ ((((( DDDDDDDDDDAAAAAABBBBBB Decompress didn't finish correctly. %ld.%02ld seconds (process time) for decompression. Error when decompressing "%s" to "%s" lzdcmp fatal errorIncorrect first header byte 0x%X Incorrect second header byte 0x%X %s: compressed with %d bits, lzdcmp can only handle %d bits Expected header, read 0x%X vms$attributes Expected "%s", read "%.*s" vms$attributes Error reading fdl attributes block, expected %d bytes, read %d bytes FDL information read from "%s" Expecting start of text, got 0x%X Decompress to memory failed. The following options are valid:-B Binary file (important on VMS/RSX, ignored on Unix)-M val Set the maximum number of code bits (unless header present)-V val Print status information or debugging data.-X val Set export (compatibility) mode:-X 0 VMS private mode-X 1 Compatibility with Unix compress-X 2 Do not read a header, disable "block-compress" mode (If a header is present, lzdcmp will properly configure itself, overriding the -X, -B and -M flag values.Illegal -M value Illegal -X value: %d Unknown option '%c' in "%s" %s --Too many file arguments rCan't create output file wrat=crrfm=var Unexpected control 0x%X Read errorWrite errorMemory buffer [%d bytes] filled -- fatal. Decompress: corrupt input file rarat=crrfm=varLZ_CLEARLZ_SOHLZ_STXLZ_EORLZ_ETX???%2d: %02x " \n\t\b\f\ropening fileRecord only deviceconnecting after opengetting fdl infocreating (sys$create)creating (fdl$create)opening created fileRecord only deviceconnecting after createparsingclose %s %s%s%s: %s RMS error %x when %s %s "%s" %s: non-translatable vms error code: 0x%X, vms message: %s %s: %s DCLMCRSHELLerror 0not ownerno such file or directoryno such processinterrupted system calli/o errorno such device or addressarg list too longexec format errorbad file numberno childrenno more processesnot enough corepermission deniedbad addressblock device requiredmount device busyfile existscross-device linkno such devicenot a directoryis a directoryinvalid argumentfile table overflowtoo many open filesnot a typewritertext file busyfile too largeno space left on deviceillegal seekread-only file systemtoo many linksbroken pipemath argumentresult too largeI/O stream emptySYS$LOGINSYS$COMMANDSYS$DISKPATH=HOME=TERM=USER=PATHHOMETERMUSERft1-132ft1-80ft1ft2-132ft2-80ft2ft3-132ft3-80ft3ft4-132ft4-80ft4ft5-132ft5-80ft5ft6-132ft6-80ft6ft7-132ft7-80ft7ft8-132ft8-80ft8la12-132la12-80la12la120-132la120-80la120la24-132la24-80la24la34-132la34-80la34la36-132la36-80la36la38-132la38-80la38unknown-132unknown-80unknownvk100-132vk100-80vk100vt05-132vt05-80vt05vt100-132vt100-80vt100vt101-132vt101-80vt101vt102-132vt102-80vt102vt105-132vt105-80vt105vt125-132vt125-80vt125vt131-132vt131-80vt131vt132-132vt132-80vt132vt173-132vt173-80vt173vt52-132vt52-80vt52vt55-132vt55-80vt55vt200-132vt200-80vt200undefined 3SHELL$FILE_ 444$ 5 J̄*55Q$5d,5 |Ą45<5DD5L5 T5  \5 D  Ԅ  d5 $  l5 t5|5l@AHr555  5(5555Ā5̀5Ԁ5܀5PD55\555 !!!!!̂!! 5!""Ă"5"5#688undefined error D NZ?l~LZ.SAV/%F[SYSDEV.PERROT.LZ]LZDCM.EXE;1lS|555$<F`r&5ETey 1#@ a  6 L r ^`RùUVXYWXPRRRfйP ~%RPRRff3hhXWX HX~UP1ݬݬϓAHh NPga  {&P P ei!QA h1gPgzgP{PQP P~Ǐg~ߥ%ik!ݏKRxRŖTRTT7RŁSRSSߥZi&! ŧT,@KP^SXZ[YVk1hQa\\ \P\a`R hС\lPRR\\\úi 4ThQa\\ \P\a`W hС\lPWWThQa\\ \P\a`R hС\lPRRUTT k"kTi SˏU\\jU\\\!j42j~iiW5S2j\x\\\k2hQa\\ \P\a`R hС\lPRRV <C <8k1I PP=i R<~P\LYYP&\ÅiihFR\\~9P\\9OP\\ݦP\<P\P/Õin\<~úi[Q(3i0imPPiQ^TRЬSS SS P PSP"2QP^|VyX Z[lYWЬnnݬ4 PЬѭ1ЭUESSTSRd-bЮT֮ЬSEcDc1GS1?ˏSTDi S#WPSSPPB7=e|1?k1ݬ߭RPPhh 1gi1ݬ߭R(P41ݬ߭RPjPUU2U~)g%=TUTTUTUTTIЭP޼T@db~?gTdd\gTdiGOS1֭ѭ1ЮPPLL.C?`ЬRݢSPТbЬRݢeSP%ТEdgAN<^ЬRЬUeTbSSSC&R6PSb3b,޼ RDbP"`RRRBP5PSTeSSP^DZT\RSGjb3<~-KPbbcTbRPPb[KPbb P<1bZMdb5<~JPbbcb4RPPbJPb+c}bPbM`MԬl ^ﴰUWT?XSVR1fSfc$ Pg/G. cHhLc1<~IPccg c%QPPcIPc1c=<~zIPccfcPPPcIPc3{)fřcP`cWLh LJŢśc;Pж\ ~PPc LhKLФd@\\ ^YZ*['WBRPSSTЬUeUЬUeVeTfPU1U1Uj1ݬBXRX~RmXRUPP5 Y?1U kJJPU1 U1i1eUVUiTrSUUEBrV3UTWЬXTX1ЬYDiRbPP>4P<1eߣkRRP1RvE,;1Rb>5RRY P$fߣmRPjR7E,;ߣvߣoR! PQQжP ~Q P!RD,K; WQW޼PRA`TTX1"޼RGbWP<^︬TЬSЬRqݬ ]RħЬ UURPˏP~ĬURIJݬ ^HTЬRЬ SS"׬S~P׬ݬ Ĵ^STˏRRˏRP@PhPRdHRPP 2&,$?÷PúPýPPPRddP^:\n\PdzEPfCPjPP^լ ݬAP<^T7UݬwPSP"ZDPee dSÄߤ SSP<cPee ߤ S_ЬR1b%<~L?PDc߭߭R|~߭߭9oPee RzDߤ6SЭP@~ݢ5?PbSP^ΪUWVլGݬ4PRP!Zȏ`HacDPgˏgP1ߥGRMЬScT"TSEPS|~ߦTݬ nPgˏgP ߥ]P@yPRP!ZDPgg ߥsRϢ„ňRϐRP<bPggśR\RP^`W<~O=PVP(PbD(`履Ɣ(Df(,ƔlhЬRRpRDPxD< ƠƞƖD0P$RdzVϪƟRB֠ƠpƟxȏHVP^ЬRբ ݢ=Ԣ ^tSЬRDPûR0RB=^Ь RЬ$ Ԣ8bP_YP<"P^Ь RЬ("Ԣ8bP#P<"P^ЬPݠpݬCCЬP^ЬPx Q<PQP<^SЬUYP ;PЬQTСpTTeRRRUx  ^SR߭ ?߬l2P@PPQޢPQP aPPP@cPa  QޢPQPޢP ^復SЬ QRQRRݬ TP  ^ЬPРS<`PSPRSR:c"ݬ~ c"ݬc~ ; ݬ  SRP ALQ  BLS < DEQ  DNA 0FOP CTG CBT TEF CIF SUP SCF SPL TMD TMP NEF RCK WCK DLT MXV RWO POS RWC FSZ ?  MRS 6@*RAT CR BLK FTN PRN ?RFM FIX VAR VFC UDF STM STMLFSTMCR?SHR GET PUT DEL UPD NIL UPI MSE  MBC 7 MBF 6ROP ASY TMO  TMO  *CTX @STM BIN NOCVTREC fop=cif  SYS$ERRORRUN SYS$INPUTSYS$OUTPUT_NLA0:SYS$DISK0VM^^Z0|~߮~~^Y|~i<UTD|TTPUT'TiTTUT TTPP: VPPVVZ VnVZVZZn0tnZɔkЬPЏL5P0`[甼PЬWP0 g0 Pg֧PЬWP0j 0kPP֧g,P߬ l~n ߬l~n0 ЬUЬRSVSrVSw Sa1b+VP0 H~ЭZYЭ\01HZSwhP#Sa<.PPPY0h,-)*Z a ~Zt[PЏ5P0PЬWP0O )^^[߬ ݬ[$P PZ0ЎPPЬWP0 7gV0-gV,֧g   ,02ЬPѧ $!Ч $(çPP( P֧$P(ЬPPЬWP0 4Ь[ЏZ:Zk Џ5P04[QZ0 ЏL5P0PЬWP0U $Ь[Ь ~լЬZ0 nÎ PPЬ WP0 P ~6Լ lЬWP0 Pѧ $(VV ЏzP0P߬ ݬݬ3ЬWP0 }~ ~ϰPPЬWP0  ~ ~ώЬWP0y -Ь[Ь ~ЬZ00enЬ PЏL5P0PЬWP0; iPP0W1F0j&RDžSlլ 3 03P'QRiH8R5S(Sbc#PP/ЬPWP0 LЬ[ЏZZ~gV0 4: VPPVVZ VnVZVZZn0 nZɔ{ЬP[PЬWP01 Z~n[0ЎPP0 P@P0 P@P0 Z [1 ѧ 0;,6ˏ@Vя@V(ݩnՎϬ +Џ5P0IPP[[Zլ 1$[(Z,g Z[[P[PZP iY[$6Z(0ipPPz0 Ч$[<(Z[Z,1dV[ZipVяzPяP0 1,0Ϭ +Џ5P0r [Ч PPP[çUUZ$[(Z<V Z[[PЏ5P02 [$jx $T(TVT~ݬcPrx [UZUTUVTTUUTTggT}T~,nT,nTTTg01}TTUƨ,Y[ g0[ [8i0  , [$'Z(!<(PPZTT(PS,nTc, ZVgZ0~[x [[Z[P0 iPP07 0ЬUVP0`ՎYЬPPP߽P0 Ш,045ǂVЦ  h0PJӏ4 ӏ4 Џ5P1E:Tæ HUUTЦ U}T~^R~l>n~l>nYY~l> nR[P0ЎP0s P0}UʏVP0l;Ь P PY0 Yl@lZZެ\0J @hP4ˏQя Q Џ5P1ӏGhPnяPӏ Џ5P1Lh,,(*Z  ZZP0l WP0)^^[߬ݬ[xP PZ0ЎPPXW1NLWP0Z5Ь[ЏZ:Zk Џ5P0 [QZ0層[Z0PZЬWP0Ь~^[0~ЬP0  ,P0 0 Z P82-<PP P0z]P$PPP1@B,@9 *h0L,h01<6R@<֧ Ч 8iP#я P , ,ЧЏgPק 0Џ5P0,1/Ч<gP,0Ч<g,0Pg/,0(Ч<g,  0J֧ ,gP1rZ, : ZkQ[QZgV0gKZVZV,(VkVgSQ[VnVZ0=! , 0"nZPՎPgV0 %ZVZV,(VkSVgQ[VZPЧVVU0} PЧ<gP0ЏPѧ $,çQQ(<(Q,QP,<ЧR,gPAb<"Ч(Ч 8iя P i0 }U~>?TV,TVTU ЏP1TP.1 EU12~T^, EUn1U1~f f ;,%, ~}U~ޮVU0}UT}U~1f  ,19Pf P1Q+Q, Q,E  ,U:E U/,'Q1P Q $QQ EU1_Q~P (UfVSUfJ@E@xUTT^^S, R R RU S,^V^SUT^1mU"V(ˏ@Sя@S,i@@i?VUVVVVV( (֧$T^}Uя P i0), P` çPP6P ,nPSЧ QçP PQQ$Q$(P(P( ^|RPP $RRRRRYYYYYYYYYYYYYYYYYYRYYYYYYYYYYVYT?R֬֬ЬP`0(`9# SQЬP֬`PPQ0QSЬP`0`9RSQSQQP^ݬA!OL!XL!SL!UL  @@doxucsefgDOXUEG%doxscef[DOXEFΫ^ͫ<ԭЬZЬXЬ Y:hPW:%Wh}P~PWP XQ01P1"}WXW1 ԭԭh-XWh* ЉXW#+WhZPWRh00XS}PW0Pѭ1h.?XWh* ЉXW)+WhPWRXS}PW0P1{PhlXWh:h ͫQhaP 0P1DXWͫSVѭP+譾PV}P~,aVc}PVR,PaRcЭPͫQP1ЭPP~(PajSZPRА+ͫ(Rcͬ ͫ6PPl~Tl0 ~TiͫՉPͫQP:PPխ ѭPЭPЉQܚ݉?P;0ͫPQϰܚ݉?P;0ͫPQ譽}PRA Ruܚ݉?PόP[~Zj7P[j@ݬ ݬݬϵЏ5P1ѭ  ЏL5P1~>nYЫX^YP0^SYR0Di }P~^S ~^Tcd~^ZLЬTЭU~~T(P'T$UP TU^TUVV^(Ud(όnnV~^Tώ ~^R|~߮~~^V|~fb<~PxяBnS1 H~^SXϥ~~~~ZS~T m:PU! ~^TdUPPЫ PЏ\5P10d^^U nRR^S0P1Z4[k[1WnSZGV5*4RUeUTVDRTU[TW R* %HZUP%ƅPP(P&c^SR^S0hP1W1tIP76РРB[nkZZR^S0#PCZn[kkךZЬ [0@PZЬ[03P nR^S0PPШPRR^nSЬT|~|~Rc|~<1~< ~ Sʏ< ~T- |~ݏݏݏ?`PPPը ߨ]P[P0`PР P] ^]PjP``ݠݠPЎPРPlЏL5P12[k9kZ Z[l լЪݪjkZDЎPЏT5P1P4PPct~^Qa?aݭPRˏRPP ݭx߭|,RRMOcC,я|PcT,PPT,PPRP?T+PP ^‘R+\P\\P ^|~|~2QQЬS +RRR|~<#~Q SiP^ЬP1P1PE@=լ"P@SP`( tլ \QAP`RЬ`AP`AP`AP`RPݏ5YP^ݬݬ5PPQQQP|^ZSЬVVݏ5P߭+ѽ ЏUЬUT TP@cP`1 TQAP`VhAP`U UUAcP`RЬQQP@P`QPxRPPRQ Q  UR) R)PT TP@cP`1t0}QP PPPbPPPЬQ:aìQP|}SV:dVTQR (RdcQTVcЬP}SVЬ WD:dVTQRRWWRVRW(RdcQTVЏVVWWV ,nVcVWЬP|}QV:aQS:bVRQP (PbcQRVcЬP}QЬ W5V:aQS:bVRQPPWWPPW(PbcQRVڔcЬP<^,nnUЬQ6ЬR :a&P@nQT:dUTQ*QdnUìQP<^,nnUЬQ6ЬR :a&P@nQT:dUTQ+QdnUìQP|^,nnUЬQ.P@nЬQQT:dUTQ*QdnUQP Ь S}QP P SPbPPPPPaP zP PPPPPPнPl լP0^XeYAWީ ީ%nީ+ީ1h hxb|z|~x?bXb|P)ЧRb<RRRt|~?(PP"|~2 ~B 22~PRRԧRSRPc֧Հ 1{d<~PPTݧT.PtZTRR!RRpr|~p?pXPTPptϬQPP%-%77777777777777777777 t?P@1P@T?P`1P`9S1?ޢZS1ޢmS1€S1~“S1v¦S1n¹S1fS1^S1VS1N S1F#S1>9S16OS1.eS1&S1œS1³S1ЬP¸S1S1ЬPS1S1ЬPS1S1ЬPS1 S1ЬPS1&S1ЬP5So?ShЬPNSUXSNЬPgS;qS4‘S-§S&ЬP¬S¶S SSSݬ^|~|~ݬ|~<#~ݬ : ЏvP`B6P`S1ЬR1bSѬE~=S$RB~Rb~ S~ SЬPC~R`bC~RРbC~RРbP^f~R_~X~~ RP|^1~VЬSSRRRR~US~SM~ TUNU=TP@~QaS@}P`RaS RSxUPPUTUVP^ݬ\}}ݏ$5P^߭DнQQЬPQ}`N}Qм<}P<l^T]P^Q!}R0լ+}#ЬPՀ} p}pmpʏPQ|}]|}P]Ь STRcSݬݬPRc|}|]RPX{WP^ݬhPV˛6K~LZ.SAV/%F[SYSDEV.PERROT.LZ]LZDCM.EXE;1lz4Q1,nPPƐϞPЬܞIG:QQ,n`P`PRnTZ\0P~VgP g5RHPSP@n^hP RPPןgRPP|w}VP^,nPPƐϞPЬܞqF:QQ,n`P`PZf\0PRR[P@fn\ RfPPЬQС(Pՠ04Q0|}V$^fԦ,n$nn:QìQЬ ծhB<POPQfP. .f0ffQ.ffP/fQPP }S ^]> .c/csPcPPnnc~P/cRn:.nQQR/bRcPPnRccR:]nbQQc :>nbQQcPt|ZjWWVЬ YYXY /gjX1YY Y1ЬXY( KDg jr/jY ЬX /gj.GY@1ЬX /gj.j.jX 0j(XXjY!j*VQQjXX:%XfQQ?aQVPPXQVYPPF{R/b.b.bP{R/b.b.b.bP[zZ,^lլYЬYPѬPPXЬ$QVPPPPPQPVQ1Ь$j,| 0004ЏЏЏ$,n$V  + fP1', ,w[j0T0PTP- B ,.j0T0PTP9jU- A-e-.ejN.jdT<V1,,,,YjPPW, ..`[`j,.j(VVj]jXz,nPPƐϞP؞ܞ(APPj,n`P`PR$TZP\0PRERk1ZWj,*, ,Y1jP.j]j,.j,jP%.j,5,jQ.jPQP a**j.j$, ,kz,nPPƐϞP؞ܞ?PPj,n`P`PR$TZP\0Pk1,,kPWHP[SP(PTnSP@$.RYWR,PPWRPݬP SP(PnTk[WPP>Y[XvW$^g,| 0004ЏЏЏ$,n$nn:QìQЬ J Ph1m,s[g0V0PVP- i ,.g0V0PVP9gT- i-d-.dg( <PPg.gfVѬE<V/gP, ..`[`g,.g(VVg]gg1,gP.g]g(<PPg,.g( <PPg,gP%.g,;,gQ.gPQP a**g.g($(<$PPghPPtWV(VVg:g:gP|tV(f:fPTУSµfV;P@LݢLgPS8SSQ[5Q%ܑQ?׊QQSVVVTXRdPdTVRXQQWWQQ]ȑQ-QӑQ]S-SWґSQ QQSšQQ]1\hq i.; z.;@_ ::"":[<]>.m-6'.]>b.--.]>. An]>*p%n- *pm%pm1 o/@n/Fn.`n;pn *z.pn ;pn @ !""., ./*p>n-y$(nyn*?} m[]-eVAXCMSG@@8@HH@( x 0HP @FDLSHRFORRTLLIBRTL LZDCM1 ,NmainOget_magic_headerSmem_decompressx ySsetupLUgetvaluei.V openinputAW openoutputy ,N  y !y   LZDCM2X decompress~oZinit_decompress_o IX   LZDCM3Zgetcode R PZ  LZIO[lz_fill\lz_flush[] lz_getbuf] lz_putbufV ;^lz_eof D^lz_fail4x^lz_dummy^ interrupt:^ address_error,^getredirection`dumphexpu`dumptextM`dumpcharRacputime2^ '[ y     -3 LZVIO afailafdl_open"b fdl_createp-d fdl_setupdfdl_freee fdl_closeF_efdl_read<e fdl_write<e fdl_getnamee fdl_fsize f fdl_messageuf vms_etextifmessageW?gfdl_dumpT] a z F C$ATOL Watol atoi)=W C$$TRANSLATE c$$translatef C$CTYPEC$PERROR Ƥperror( PƤSHELL$FROM_VMSSHELL$FROM_VMS  :4ѼSHELL$$RMS_PARSE Ѽ 3(jTERMINATE_PARSE j m  SHELL$TRANSLATE_VMS  9)1 DEFAULT_DIR 1 A2 [ Ծ COPY_TOKEN Ծ r}B     . INSERT_MINUS  /!-/ DOTDOTDOT / \!3P:CLI$DATA _LIB$KEY0$ _LIB$STATE$_tCLI$READ_ONLY_DATACLI$CODESHELL$CLI_NAMEshell$cli_nameshell$is_shell@N o  SHELL$TO_VMSb SHELL$TO_VMS b Z J    "   d a  9BSHELL$$VMS_FILE  ͹;   #    SAVE_NODE  Y)'SAVE_DEV   &SAVE_DIRECTORY  :B SAVE_NAME  @ & SAVE_TYPE  m-(  Y SAVE_VERS   &COPY_STR  H1!FREE_DIRECTORY_DESCRIPTORS  w  4B MATCH_REGEX B C, # MATCH_SUBSTRING  *' R Q'PRUNE_FILESPEC ' g^&     FIND_LAST_DOT  " .TERMINATE_PARSE     CLI$READ_ONLY_DATAX;CLI$DATA8 _LIB$KEY0$n _LIB$STATE$4bCLI$CODE  . ABS .C$SIGNAL ˦declare_control_c_handlerD signalȧssignal&gsignalm ˦# ! $  C$DATAC$$MAINc$$main; expand_buffer lowercase/) get_paramsqget_terminal_typez c$$ctrlc_hando c$$cond_hand.y t0y " y  &! y"C$GETENV getenv E  SHELL$CLINTSHELL$GET_ARGVCLI$CODEDSHELL$MATCH_WILD\SHELL$MATCH_WILD\CLI$CODEC$SIGVEC sigvec sigblock5@ sigsetmaskպsigpause4 sigstack>y *[SYSDEV.PERROT.LZ]LZDCM1.C;1+,9./E 4H-F0123KPWO5 6F 7`%%8Ž#9GEHJ:/*( * lzdcmp [-options] [infile [outfile]] */#ifdef DOCUMENTATIONtitle lzdcmp File Decompressionindex File decompressionsynopsis .s.nf% lzdcmp [-options] [infile [outfile]] .s.f description5 lzdcmp decompresses files compressed by lzcomp. The2 documentation for lzcomp describes the process in greater detail.% Options may be given in either case. .lm +8 .p -80 -B Output file is "binary", not text. (Ignored in VMS private mode.) .p -85 -X 3 To read files compressed by an old Unix version& that doesn't generate header records. .p -84 -V val Verbose (print status messages and debugging: information). The value selects the amount of verbosity.Author3 This version by Martin Minow. See lzcomp for more details.#endif/*, * Compatible with compress.c, v3.0 84/11/27 *//*)BUILD $(PROGRAM) = lzdcmp $(INCLUDE) = lz.h $(CPP) = 1: $(FILES) = { lzdcm1.c lzdcm2.c lzdcm3.c lzio.c lzvio.c }*/#include "lz.h"/*= * These global parameters are read from the compressed file. * The decompressor needs them. */6short maxbits = BITS; /* settable max # bits/code */ code_int maxmaxcode = 1 << BITS;/*B * Note, if export is zero or 1, the "true" value will be set from8 * the file header. If it is 2, no header will be read. */ #if VMS_V4,flag export = 0; /* Assume VMS private */#else/flag export = 1; /* Assume Unix compatible */#endif0flag binary = FALSE; /* Read text if false */8flag block_compress = TRUE; /* TRUE if CLEAR enabled */5flag noheader = FALSE; /* No magic header if TRUE */C@flag verbose = VERBOSE_DEFAULT; /* Non-zero for status/debug */7flag background = FALSE; /* TRUE (Unix) if detached */N0flag is_compress = FALSE; /* For lzio.c (?) */4char *infilename = NULL; /* For error printouts */:char *outfilename = NULL; /* For openoutput and errors */1int firstcode; /* First code after internals */8static long start_time; /* Time we started (in msec) */:extern long cputime(); /* Returns process time in msec */jmp_buf failure;STREAM instream;STREAM outstream;char_type inbuffer[MAXIO];char_type outbuffer[MAXIO];static STREAM mem_stream; #if VMS_V4#include #ifndef FDLSTUFF#define FDLSTUFF charw#endifFDLSTUFF *fdl_input;FDLSTUFF *fdl_output;n,static struct dsc$descriptor fdl_descriptor;#endif main(argc, argv) int argc;char *argv[];/* * Decompress mainline */ { int result; #ifndef decus  /*dE * background is TRUE if running detached from the command terminal.s */B background = (signal(SIGINT, SIG_IGN) == SIG_IGN) ? TRUE : FALSE; if (!background)r* background = !isatty(fileno(stderr)); if (!background) { if (verbose > 0)  signal(SIGINT, abort); else { signal(SIGINT, interrupt);! signal(SIGSEGV, address_error);i } }#endif if (setjmp(failure) == 0) { setup(argc, argv);i openinput();g2 get_magic_header(); /* Sets export, etc. */ openoutput(); if (verbose > 0)e start_time = cputime();p init_decompress();r% result = decompress(&outstream);g if (!export && result != LZ_ETX"* && getcode() != (code_int) LZ_ETX) {; fprintf(stderr, "Decompress didn't finish correctly.\n");2 goto fail; } lz_flush(&outstream); #if DEBUGH if ((verbose & 04) != 0)c dump_tab(stdout);1#endif if (verbose > 0) {& start_time = cputime() - start_time; fprintf(stderr,H> "%ld.%02ld seconds (process time) for decompression.\n",6 start_time / 1000L, (start_time % 1000L) / 10L); } exit(IO_SUCCESS); } else { Hfail: fprintf(stderr, "Error when decompressing \"%s\" to \"%s\"\n", (infilename == NULL) ? * "" : infilename, (outfilename == NULL) ? ( "" : outfilename); if (errno != 0) perror("lzdcmp fatal error");D exit(IO_ERROR); }} istaticget_magic_header(){! int head1; int head2; int head3; head2 = 0;d if (export != 2) {y3 if ((head1 = GET(&instream)) != HEAD1_MAGIC) {e7 fprintf(stderr, "Incorrect first header byte 0x%X\n",e head1);l FAIL("can't get header");  } head2 = GET(&instream); head3 = GET(&instream); switch (head2) {B case HEAD2_MAGIC: export = 1;R break; case VMS_HEAD2_MAGIC: export = 0;? break; default:e8 fprintf(stderr, "Incorrect second header byte 0x%X\n", head2);2 FAIL("can't get header");  } maxbits = head3 & BIT_MASK;A block_compress = ((head3 & BLOCK_MASK) != 0) ? TRUE : FALSE; #if DEBUGt if (verbose > 1) {t1 fprintf(stderr, "%s: compressed with %d bits,",y infilename, maxbits);- fprintf(stderr, " block compression %s.\n",T6 (block_compress != 0) ? "enabled" : "disabled"); }#endif } if (maxbits > BITS) {4 fprintf(stderr, "%s: compressed with %d bits,", infilename, maxbits);s@ fprintf(stderr, " lzdcmp can only handle %d bits\n", BITS); FAIL("too many bits");l } maxmaxcode = 1 << maxbits;a if (export == 0)kC firstcode = GET(&instream) + 0x100; /* From compressed file */i else if (block_compress)E. firstcode = LZ_CLEAR + 1; /* Default */ else!2 firstcode = 256; /* Backwards compatible */ #if VMS_V4 if (!export) {k register code_int code; char text[256];H /*e! * Get the attribute record.t */( if ((code = getcode()) != LZ_SOH) {8 fprintf(stderr, "Expected header, read 0x%X\n", code);% FAIL("can't get header (private)");a } init_decompress();E. code = mem_decompress(text, sizeof text); text[code] = EOS;2 if (strncmp(text, ATT_NAME, ATT_SIZE) != 0) {5 fprintf(stderr, "Expected \"%s\", read \"%.*s\"\n",= ATT_NAME, code, text);+ FAIL("can't get attribute block header");' }" code = atoi(text + ATT_SIZE);1 fdl_descriptor.dsc$a_pointer = malloc(code);s( fdl_descriptor.dsc$w_length = code;D if ((code = mem_decompress(fdl_descriptor.dsc$a_pointer, code))' != fdl_descriptor.dsc$w_length) {e; fprintf(stderr, "\nError reading fdl attributes block,");S8 fprintf(stderr, " expected %d bytes, read %d bytes\n",) fdl_descriptor.dsc$w_length, code);) FAIL("can't get attribute block data"); } if (verbose > 1) {9 fprintf(stderr, "\nFDL information read from \"%s\"\n", infilename);$ fdl_dump(&fdl_descriptor, stderr); }( if ((code = getcode()) != LZ_STX) {A fprintf(stderr, "\nExpecting start of text, got 0x%X\n", code);T FAIL("no start of text");F } }#endif}O Iint mem_decompress(buffer, size)char_type *buffer; int size;/*> * Decompress up to size bytes to buffer. Return actual size. */{C int result;N, mem_stream.bp = mem_stream.bstart = buffer;! mem_stream.bend = buffer + size; mem_stream.bsize = size; mem_stream.func = lz_fail;*1 if ((result = decompress(&mem_stream)) == LZ_EOR* || result == LZ_ETX)% return (mem_stream.bp - buffer); else {7 fprintf(stderr, "Decompress to memory failed.\n");( FAIL("can't decompress to memory"); }$ return (-1); /* Can't happen */} $static readonly char *helptext[] = {$ "The following options are valid:",; "-B\tBinary file (important on VMS/RSX, ignored on Unix)",G "-M val\tSet the maximum number of code bits (unless header present)",7 "-V val\tPrint status information or debugging data.",, "-X val\tSet export (compatibility) mode:", "-X 0\tVMS private mode",* "-X 1\tCompatibility with Unix compress",? "-X 2\tDo not read a header, disable \"block-compress\" mode",E "\t(If a header is present, lzdcmp will properly configure itself,",/ "\toverriding the -X, -B and -M flag values.", NULL,};staticsetup(argc, argv) int argc;char *argv[];/*: * Get parameters and open files. Exit fatally on errors. */{ register char *ap; register int c; char **hp; auto int i; int j; #ifdef vms# argc = getredirection(argc, argv);#endif! for (i = j = 1; i < argc; i++) { ap = argv[i];5 if (*ap++ != '-' || *ap == EOS) /* Filename? */+ argv[j++] = argv[i]; /* Just copy it */ else { while ((c = *ap++) != EOS) { if (islower(c)) c = toupper(c); switch (c) { case 'B': binary = TRUE; break; case 'M':$ maxbits = getvalue(ap, &i, argv); if (maxbits < MIN_BITS) {- fprintf(stderr, "Illegal -M value\n"); goto usage; } break; case 'V':$ verbose = getvalue(ap, &i, argv); break; case 'X':# export = getvalue(ap, &i, argv);" if (export < 0 || export > 3) {9 fprintf(stderr, "Illegal -X value: %d\n", export); goto usage; }! block_compress = (export < 2); noheader = (export == 3); break; default:5 fprintf(stderr, "Unknown option '%c' in \"%s\"\n", *ap, argv[i]);/usage: for (hp = helptext; *hp != NULL; hp++)$ fprintf(stderr, "%s\n", *hp); FAIL("unknown option");" } /* Switch on options */ } /* Everything for -xxx */ } /* If -option */ } /* For all argc's */5 /* infilename = NULL; */ /* Set "stdin" signal */5 /* outfilename = NULL; */ /* Set "stdout" signal */* switch (j) { /* Any file arguments? */# case 3: /* both files given */8 if (!streq(argv[2], "-")) /* But - means stdout */ outfilename = argv[2];# case 2: /* Input file given */ if (!streq(argv[1], "-")) { infilename = argv[1];o } break;f case 0: /* None! */p$ case 1: /* No file arguments */ break; default:.2 fprintf(stderr, "Too many file arguments\n"); FAIL("too many files"); }}f s static intgetvalue(ap, ip, argv)register char *ap;e int *ip;char *argv[];t/*H * Compile a "value". We are currently scanning *ap, part of argv[*ip]. * The following are possible:7 * -x123 return (123) and set *ap to EOS so the caller $ * ap^ cycles to the next argument. *6 * -x 123 *ap == EOS and argv[*ip + 1][0] is a digit.3 * return (123) and increment *i to skip over thea * next argument.e *1 * -xy or -x y return(1), don't touch *ap or *ip.  *D * Note that the default for "flag option without value" is 1. This@ * can only cause a problem for the -M option where the value is@ * mandatory. However, the result of 1 is illegal as it is less * than INIT_BITS. */.{z register int result;i register int i; i = *ip + 1;a if (isdigit(*ap)) { result = atoi(ap); *ap = EOS;s } else if (*ap == EOS && argv[i] != NULLt && isdigit(argv[i][0])) { result = atoi(argv[i]); *ip = i;x } else {o result = 1; } return (result);*}e l openinput() {i #ifdef decus if (infilename == NULL) { infilename = malloc(257);! fgetname(stdin, infilename);x> infilename = realloc(infilename, strlen(infilename) + 1); }0 if (freopen(infilename, "rn", stdin) == NULL) { perror(infilename);) FAIL("can't open compressed input"); }#else #ifdef vms #if VMS_V4 if (!export) { if (infilename == NULL) { infilename = malloc(256 + 1); fgetname(stdin, infilename);; infilename = realloc(infilename, strlen(infilename) + 1); }< if ((fdl_input = fdl_open(infilename, NULL)) == NULL) { fdl_message(NULL, infilename);4 FAIL("can't open compressed input (vms private)"); } } else#endif { if (infilename == NULL) { infilename = malloc(256 + 1); fgetname(stdin, infilename);; infilename = realloc(infilename, strlen(infilename) + 1); } else {0 if (freopen(infilename, "r", stdin) == NULL) { perror(infilename);3 FAIL("can't open compressed input (export)"); } } }#else if (infilename == NULL) infilename = ""; else {3 if (freopen(infilename, "r", stdin) == NULL) { perror(infilename); FAIL("can't open input"); } }#endif#endif$ instream.bp = instream.bend = NULL; instream.bstart = inbuffer;" instream.bsize = sizeof inbuffer; instream.func = lz_fill;} openoutput(){ #ifdef vms #if VMS_V4 if (!export) { fclose(stdout); stdout = NULL; if ((fdl_output =: fdl_create(&fdl_descriptor, outfilename)) == NULL) {0 fprintf(stderr, "Can't create output file\n"); if ((fdl_status & 01) == 0)% fdl_message(NULL, outfilename);, FAIL("can't create output (vms private)"); } if (outfilename == NULL) { outfilename = malloc(256 + 1);' fdl_getname(fdl_output, outfilename);> outfilename = realloc(outfilename, strlen(outfilename) + 1); } } else#endif { /** * Not VMS Version 4, or export mode. */ if (outfilename == NULL) { outfilename = malloc(256 + 1); fgetname(stdout, outfilename);> outfilename = realloc(outfilename, strlen(outfilename) + 1); if (!binary) goto do_reopen; } else { if (binary) {6 if (freopen(outfilename, "w", stdout) == NULL) { perror(outfilename);( FAIL("can't create output (binary)"); } } else { int i; do_reopen:@ if ((i = creat(outfilename, 0, "rat=cr", "rfm=var")) == -1* || dup2(i, fileno(stdout)) == -1) { perror(outfilename);& FAIL("can't create output (text)"); } } } }#else #ifdef decus if (outfilename == NULL) {# outfilename = malloc(256 + 1);# fgetname(stdout, outfilename);A outfilename = realloc(outfilename, strlen(outfilename) + 1); if (binary) {3 if (freopen(outfilename, "wn", stdout) == NULL) { perror(outfilename);$ FAIL("can't create (binary)"); } } } else {G if (freopen(outfilename, (binary) ? "wn" : "w", stdout) == NULL) { perror(outfilename); FAIL("can't create"); } }#else if (outfilename == NULL) outfilename = ""; else {5 if (freopen(outfilename, "w", stdout) == NULL) { perror(outfilename); FAIL("can't create"); } }#endif#endif- outstream.bp = outstream.bstart = outbuffer;/ outstream.bend = outbuffer + sizeof outbuffer;$ outstream.bsize = sizeof outbuffer; outstream.func = lz_flush;}*[SYSDEV.PERROT.LZ]LZDCM2.C;1+,3. /E 4E l-F0123KPWO 56 [7@g%8@#9GEHJ /* * l z d c m 2 . c * * Actual decompression code */#include "lz.h"/*= * These global parameters are read from the compressed file. * The decompressor needs them. */5extern short maxbits; /* settable max # bits/code */1extern code_int maxmaxcode; /* 1 << maxbits */static flag first_clear = TRUE;/* * Big data storage stuff */!static char_type stack[MAXSTACK];$#define STACK_TOP (&stack[MAXSTACK])9static U_short tab_prefix[1 << BITS]; /* prefix code */Cstatic char_type tab_suffix[1 << BITS]; /* last char in string */code_int next_code; #if DEBUG#define CHECK(what) \ if (stp <= stack) { \7 fprintf(stderr, "Stack overflow -- %s\n", what); \ abort(); \ }#else#define CHECK(what)#endif intdecompress(out) STREAM *out;/*> * Decompress instream (global) to out. Returns "end" signal: * -1 end of file * LZ_EOR end of record * LZ_ETX end of segment */{. register char_type *stp; /* Stack pointer */) register code_int code, oldcode, incode;. register int final; /* End of a sequence? */ extern code_int getcode(); stp = STACK_TOP; final = oldcode = getcode(); PUT((char) final, out);" while ((code = getcode()) >= 0) {5test: if (code >= LZ_CLEAR && code < firstcode) {' lz_putbuf(stp, STACK_TOP - stp, out); stp = STACK_TOP; switch (code) { case LZ_ETX: case LZ_EOR: goto finish;" case LZ_SOH: /* Unexpected */" case LZ_STX: /* Unexpected */ default:; fprintf(stderr, "\nUnexpected control 0x%X\n", code); ! FAIL("Unexpected control");o case LZ_CLEAR:3 init_decompress(); /* Before getcode() !! */o if ((code = getcode()) < 0( || (export && code == LZ_CLEAR)) goto finish; else { /*5 * init_decompress has set next_code to firstcode,3 * however, for magical reasons, we want to toss0 * the next substring, so we set next_code so4 * that the tab_... entry is effectively ignored.2 * Note below that tab_prefix[next_code] is set. * to the character before the LZ_CLEAR and5 * tab_suffix to the character after the LZ_CLEAR.3 * But, these values have no relationship to one2 * another, so, by decrementing next_code, they" * will be ignored. (I think.) */ next_code--;x goto test;O }  }  } incode = code;  /*e& * Special case for KwKwK string. */ if (code >= next_code) { CHECK("KwKwK");m *--stp = final;t code = oldcode;e } /*e3 * Generate output characters in reverse ordero */#ifdef interdataC while (((unsigned long) code) >= ((unsigned long) NBR_CHAR)) {l#elsen while (code >= NBR_CHAR) { #endif CHECK("generate output"); *--stp = tab_suffix[code]; code = tab_prefix[code]; } CHECK("final char");' *--stp = final = tab_suffix[code];x /*e) * And put them out in forward orderr */* lz_putbuf(stp, STACa+~LZ.SAV3F[SYSDEV.PERROT.LZ]LZDCM2.C;1E QK_TOP - stp, out); stp = STACK_TOP;c /*t * Generate the new entry.t */+ if ((code = next_code) < maxmaxcode) { ' tab_prefix[code] = (U_short) oldcode;I tab_suffix[code] = final;C next_code++; } I /* * Remember previous code.i */ oldcode = incode; }finish:  return (code); }  tinit_decompress()n/*8 * Called on cold start, or on LZ_SOH, LZ_STX, LZ_CLEAR. */{e register char_type *cp; register U_short *up; register int code; if (first_clear) {9E for (cp = &tab_suffix[0], code = 0; cp < &tab_suffix[NBR_CHAR];)o *cp++ = code++;k first_clear = FALSE;  } else {#if ((NBR_CHAR % 8) != 0) * << error, the following won't work >>#endif= for (up = &tab_prefix[0]; up < &tab_prefix[NBR_CHAR];) { *up++ = 0; *up++ = 0; *up++ = 0; *up++ = 0; *up++ = 0; *up++ = 0; *up++ = 0; *up++ = 0; } } next_code = firstcode;r}E #if DEBUG!dump_tab(dumpfd)FILE *dumpfd;/* * dump string table */r{. register char_type *stp; /* Stack pointer */ register int i;y register int ent;  extern char *dumpchar(); stp = STACK_TOP;N+ fprintf(dumpfd, "%d %s in string table\n",c8 next_code, (next_code == 1) ? "entry" : "entries");" for (i = 0; i < next_code; i++) {& fprintf(dumpfd, "%5d: %5d/'%s' ",- i, tab_prefix[i], dumpchar(tab_suffix[i]));f for (ent = i;;) { *--stp = tab_suffix[ent];! if (ent < firstcode) break; ent = tab_prefix[ent]; }, dumptext(stp, STACK_TOP - stp, dumpfd); stp = STACK_TOP; }}k#endif*[SYSDEV.PERROT.LZ]LZDCM3.C;1+,"!. /E 4J *-F0123KPWO 56"7%8@.$9GEHJ/* * l z d c m 3 . c *$ * Read codes from the input stream. */#include "lz.h" #if !vax_asm&static readonly char_type rmask[9] = {5 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};#endif #if DEBUGextern int col;static int todump;#endif/* * getcode() *= * Read one code from the standard input. If EOF, return -1. * Inputs: * stdin (via GET) * Outputs: * code or -1 is returned. */extern code_int next_code;extern STREAM instream;extern code_int maxmaxcode;extern short maxbits;!static short n_bits = INIT_BITS;.static code_int maxcode = MAXCODE(INIT_BITS);/*C * buf[] contains 8-bit data read from the input stream. getcode()J * treats buf[] as a vector of bits, repacking it into variable-bit codes. */static char_type buf[BITS];9static int offset = 0; /* Offset into buf IN BITS */7static int size = 0; /* Actual size of buf IN BITS */code_int getcode(){ /*> * On the VAX (4.2 bsd), it is important to have the registerC * declarations in exactly the order given, or the asm will break. */ register code_int code; register int r_off, bits; register char_type *bp; bp = buf; if (next_code > maxcode) { n_bits++; if (n_bits == maxbits) maxcode = maxmaxcode; else { maxcode = MAXCODE(n_bits); } size = 0; #if DEBUG if (verbose > 2) {1 fprintf(stderr, "\nChange to %d bits", n_bits); col = 74; }#endif } if (offset >= size) {. size = lz_getbuf(buf, n_bits, &instream); #if DEBUGr% if (verbose > 4 || todump > 0) {  dumphex(buf, size, stderr);f if (todump > 0)C todump -= size;d }#endif if (size <= 0)T# return (-1); /* end of file */ offset = 0; /*B * Round size down to integral number of codes in the buffer.( * (Expressed as a number of bits). */' size = (size << 3) - (n_bits - 1); } r_off = offset; bits = n_bits; #if vax_asm asm("extzv r10,r9,(r8),r11");#else /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /*# * Get first part (low order bits) */ #if UCHAR code = (*bp++ >> r_off);#else /*5 * Don't touch the 0xFF; it prevents sign extension.w */5 code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xFF;#endif bits -= (8 - r_off);t5 r_off = 8 - r_off; /* now, offset into code word */c /*e> * Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if (bits >= 8) { #if UCHARi code |= *bp++ << r_off;#elser% code |= (*bp++ & 0xFF) << r_off;e#endif r_off += 8; bits -= 8; } /* high order bits. */Z #if UCHARe& code |= (*bp & rmask[bits]) << r_off;#elsee& code |= (*bp & rmask[bits]) << r_off;#endif /*i( * End of non-vax (Unix) specific code. */#endif offset += n_bits;, if (code >= LZ_CLEAR && code < firstcode) { switch (code) { case LZ_SOH:c case LZ_STX:e case LZ_CLEAR:C( size = 0; /* Force read next time */ n_bits = INIT_BITS;m maxcode = MAXCODE(INIT_BITS); #if DEBUGt if (verbose > 1) {' fprintf(stderr, "Read %s (%d)\n", $ lz_names[code - LZ_CLEAR], code); todump = 32; }C#endif break; } } #if DEBUG if (verbose > 3) {1! fprintf(stderr, "%c%5d %5d",k. ((col += 12) >= 72) ? (col = 0, '\n') : ' ', code, next_code);0 if (code >= LZ_CLEAR && code < firstcode) {6 fprintf(stderr, " = %s", lz_names[code - LZ_CLEAR]); col = 74; } }#endif return (code);}*[SYSDEV.PERROT.LZ]LZIO.C;1+,'./E 4J-F0123KPWO56`=P87 %8@_$9GEHJ*/* * l z i o . c *E * I/O buffer management. All input/output I/O is done through theseA * routines (and the macros in lz.h). The rules of the game are: * * input via GET() and getbuf().1 * GET returns an 8-bit byte, or -1 on eof/error.D * getbuf() returns the number of things gotten, or -1 on eof/error.2 * No return on error: longjmp's to the main-line. *$ * output via PUT() and lz_putbuf().2 * No return on error: longjmp's to the main-line.J * flush output by lz_flush() before closing files -- or you'll lose data. */#include "lz.h" #if VMS_V4#include #ifndef FDLSTUFF#define FDLSTUFF char#endifextern FDLSTUFF *fdl_input;extern FDLSTUFF *fdl_output;extern int fdl_status;#endif int lz_fill(s)register STREAM *s;{ register int i; extern char *infilename; #if VMS_V4 if (export && is_compress) {7 i = fread((char *) s->bstart, 1, s->bsize, stdin); if (ferror(stdin)) { perror(infilename);, FAIL("export && is_compress fread error"); } }- else { /* Decompress and export/private */2 i = fdl_read(s->bstart, s->bsize, fdl_input);) if (i < 0 && fdl_status != RMS$_EOF)' fdl_message(fdl_input, "Read error"); }#else #ifdef unix7 i = read(fileno(stdin), (char *) s->bstart, s->bsize); if (i < 0) { perror(infilename); FAIL("unix read error"); }#else3 i = fread((char *) s->bstart, 1, s->bsize, stdin); if (ferror(stdin)) { perror(infilename); exit(IO_ERROR); }#endif#endif if (i <= 0) return (EOF); else {m s->bp = s->bstart;  s->bend = &s->bstart[i];L #if UCHARf return (*s->bp++);x#elsef return (*s->bp++ & 0xFF);#endif }}T N lz_flush(s)oregister STREAM *s;{ register int count; extern char *outfilename; count = s->bp - s->bstart; #if DEBUG# if (!is_compress && verbose > 4) {. fprintf(stderr, "lz_flush %d: ", count);( dumptext(s->bstart, count, stderr); }#endif #if VMS_V4 if (export) { if (is_compress)/ fwrite((char *) s->bstart, count, 1, stdout); else { register char *bp, *bend;: for (bp = s->bstart, bend = bp + count; bp < bend; bp++) putchar(*bp); } if (ferror(stdout)) { perror(outfilename);& FAIL("VMS V4 fwrite/putchar error"); } } else {cB if (fdl_write((char *) s->bstart, count, fdl_output) == -1) {) fdl_message(fdl_output, "Write error"); ! FAIL("VMS V4 fdl_write error"); } }#elsel #ifdef unixA if (write(fileno(stdout), (char *) s->bstart, count) != count) { perror(outfilename);o= fprintf(stderr, "Can't write to \"%s\"\n", outfilename); FAIL("Unix write error"); }#elsee. fwrite((char *) s->bstart, 1, count, stdout); if (ferror(stdout)) { perror(outfilename);( FAIL("Other (decus) fwrite error"); }#endif#endif s->bp = s->bstart;e}y linttlz_getbuf(buffer, count, s)_char_type *buffer;I int count;register STREAM *s;/*B * Read a block of data -- be clever. Return number gotten, or -1 * on eof. */i{d* register char_type *bp; /* -> buffer */- register char_type *ip; /* -> I/O buffer */g. register char_type *ep; /* End of segment *// register int remaining; /* Size of segment */o int datum;d* if (count == 0) /* Shouldn't happen */ return (0); bp = buffer; while (--count >= 0) {p: if ((datum = GET(s)) == EOF) /* Maybe fill LZ buff */ break; *bp++ = datum;T( remaining = s->bend - (ip = s->bp); if (remaining > count) remaining = count; ep = &ip[remaining];  while (ip < ep) *bp++ = *ip++; count -= remaining;( s->bp = ip; /* Refresh buffer */ }, return ((bp == buffer) ? -1 : bp - buffer);}  Pint lz_putbuf(bp, count, s)nregister char_type *bp; int count;register STREAM *s;/*& * Write a block of data -- be clever. */k{c- register char_type *op; /* -> I/O buffer */y. register char_type *ep; /* End of segment *// register int remaining; /* Size of segment */e while (--count >= 0) {E+ PUT(*bp++, s); /* Forces a buffer */l( remaining = s->bend - (op = s->bp); if (remaining > count)T remaining = count; ep = &op[remaining];  while (op < ep) *op++ = *bp++; count -= remaining;( s->bp = op; /* Refresh buffer */ }}s cint lz_eof(s)c STREAM *s;C/*5 * Dummy routine for read from memory -- returns EOF.F */E{" return (s, EOF);k}ginta lz_fail(s) STREAM *s;r/*? * Dummy routine for write to memory -- called if buffer fills.: */ {l? fprintf(stderr, "Memory buffer [%d bytes] filled -- fatal.\n",k s->bsize); FAIL("lz_fail crash");P}Eint lz_dummy(s)g STREAM *s; /*A * Dummy routine for write to memory -- writes to the bit-bucket.A */'{l s->bp = s->bstart;}i k #ifndef decusa/* * Signal error handlers.s */v #ifdef vms#define unlink deleteo#endif interrupt()E{ < if (outfilename != NULL && !streq(outfilename, "")) unlink(outfilename); exit(IO_ERROR);}taddress_error()2{! if (!is_compress)9 fprintf(stderr, "Decompress: corrupt input file\n"); interrupt();e}y#endif Z/*< * getredirection() is intended to aid in porting C programs7 * to VMS (Vax-11 C) which does not support '>' and '<'/7 * I/O redirection. With suitable modification, it maya1 * useful for other portability problems as well.X */' #ifdef vmsint!getredirection(argc, argv) int argc; char **argv;C/*= * Process vms redirection arg's. Exit if any error is seen..: * If getredirection() processes an argument, it is erased? * from the vector. getredirection() returns a new argc value.o *> * Warning: do not try to simplify the code for vms. The codeA * presupposes that getredirection() is called before any data isy( * read from stdin or written to stdout. * * Normal usage is as follows: * * main(argc, argv) * int argc;i * char *argv[];X * {& * argc = getredirection(argc, argv); * } */ {T+ register char *ap; /* Argument pointer */m int i; /* argv[] index */r int j; /* Output index */a# int file; /* File_descriptor */L: for (j = i = 1; i < argc; i++) { /* Do all arguments */ switch (*(ap = argv[i])) { case '<': /* ': /* >file or >>file */# if (*++ap == '>') { /* >>file */, /*3 * If the file exists, and is writable by us,L6 * call freopen to append to the file (using the7 * file's current attributes). Otherwise, createF3 * a new file with "vanilla" attributes as ifC/ * the argument was given as ">filename".N3 * access(name, 2) is TRUE if we can write onN * the specified file. */E! if (access(++ap, 2) == 0) {( if (freopen(ap, "a", stdout) != NULL)' break; /* Exit case statement */( perror(ap); /* Error, can't append */* exit(IO_ERROR); /* After access test */" } /* If file accessable */ } /*8 * On vms, we want to create the file using "standard"5 * record attributes. create(...) creates the file3 * using the caller's default protection mask and/ * "variable length, implied carriage return"8 * attributes. dup2() associates the file with stdout. */6 if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1) || dup2(file, fileno(stdout)) == -1) {* perror(ap); /* Can't create file */, exit(IO_ERROR); /* is a fatal error */ } /* If '>' creation */ break; /* Exit case test */ default:) argv[j++] = ap; /* Not a redirector */ break; /* Exit case test */ } } /* For all arguments */) argv[j] = NULL; /* Terminate argv[] */$ return (j); /* Return new argc */}#endif #if 1 || DEBUG int col;readonly char *lz_names[] = {= "LZ_CLEAR", "LZ_SOH", "LZ_STX", "LZ_EOR", "LZ_ETX", "???"};dumphex(buffer, count, fd)register char_type *buffer;register int count; FILE *fd;{ if (col > 0) { putc('\n', fd); col = 0; } fprintf(fd, "%2d:", count); while (--count >= 0) {, fprintf(fd, " %02x", *buffer++ & 0xFF); } fprintf(fd, "\n");}dumptext(buffer, count, fd)register char_type *buffer; int count; FILE *fd;{ extern char *dumpchar(); putc('"', fd); while (--count >= 0)* fputs(dumpchar((int) *buffer++), fd); fputs("\"\n", fd);}char * dumpchar(c)register int c;/*9 * Make a character printable. Returns a static pointer. */{ static char dump_buffer[8]; c &= 0xFF; if (isascii(c) && isprint(c)) { dump_buffer[0] = c; dump_buffer[1] = EOS; } else { switch (c) { case '\n': return ("\\n"); case '\t': return ("\\t"); case '\b': return ("\\b"); case '\f': return ("\\f"); case '\r': return ("\\r"); }( sprintf(dump_buffer, "", c); } return (dump_buffer);}#endif /*F * Cputime returns the elapsed process time (where available) in msec.E * Note: Unix doesn't seem to have a good way to determine ticks/sec. */ #ifdef decus#include long cputime(){ struct timeb buf; static struct timeb origin; long result; int msec; if (origin.time == 0) ftime(&origin); ftime(&buf);* result = (buf.time - origin.time) * 1000;/ msec = ((int) buf.msec) - ((int) origin.msec);l! return (result + ((long) msec));e}t#elsei #ifdef vms#include struct tms { time_t tms_utime; time_t tms_stime;$ time_t tms_uchild; /* forgot the */' time_t tms_uchildsys; /* real names */-};*#define HERTZ 100.0 /* 10 msec units */#else #include #include #ifndef HERTZr-#define HERTZ 60.0 /* Change for Europe */ #endif#endiflong cputime()e{n struct tms tms; double temp; long result; times(&tms);(( result = tms.tms_utime + tms.tms_stime;5 temp = result * 1000.0 / HERTZ; /* Time in msec. */m result = temp;  return (result);D}U#endif*[SYSDEV.PERROT.LZ]LZVIO.C;1+,F.!/E 4I! b-F0123KPWO"56we<7E %8@$9GEHJ6/* * l z v i o . c * For VMS V4 only. *//* * Problems:; * If you open a second input file (getting rms attributes)D * it aborts with an internal "fatal" error (15820C LIB-F-FATERRLIB) */ /*3 * Make TESTING_FDLIO non-zero to enable test code. * * Edit History */#ifndef TESTING_FDLIO#define TESTING_FDLIO 0#endif/*E * RMS/FDL record level i/o routines for Vax-11 C V4 or greater only. * Rather crude. * * The following are provided: * * #define FDLSTUFF char * #include descrip * * FDLSTUFF *% * fdl_open(filename, fdl_descriptor) * char *filename;) * struct dsc$descriptor *fdl_descriptor;8 * Initializes internal buffers and opens this existing< * file for input. The filename may not contain wildcards.8 * On (successful) return, fdl_descriptor will point to6 * an initialized fdl specification. The description< * string will be in malloc'ed memory. The caller does not: * initialize the fdl_descriptor. Returns NULL on error.6 * (Note an error will be returned if the file is not * block-oriented.) *6 * When you don't need the fdl_descriptor information * any more, free it by calling! * fdl_free(fdl_descriptor);: * if fdl_descriptor is NULL on entry, the file is opened0 * normally (fdl information is not collected). * * FDLSTUFF *0 * fdl_create(fdl_descriptor, override_filename)) * struct dsc$descriptor *fdl_descriptor; * char *override_filename;/ * Creates a file using the fdl specification.9 * If override_filename is not NULL and not equal to "",N7 * it will override the filename specified in the fdl.d2 * fdl_write() is used to write data to the file. * Returns NULL on error. *8 * if fdl_descriptor is NULL, the file is created using: * the name in override_filename (which must be present).5 * The file is created in "undefined" record format. * * fdl_free(fdl_descriptor)) * struct dsc$descriptor *fdl_descriptor;& * Releases the fdl descriptor block. * * int% * fdl_read(buffer, buffer_length, r) * char *buffer; * int buffer_length; * FDLSTUFF *r;< * Read buffer_length bytes from the file (using SYS$READ).6 * No expansion or interpretation. buffer_length had9 * better be even or you're asking for trouble. Returnss7 * the actual number of bytes read. The file has beenx * opened by fdl_open.  * * int& * fdl_write(buffer, buffer_length, r) * char *buffer;L * int buffer_length; * FDLSTUFF *r; < * Write buffer_length bytes to the file (using SYS$WRITE).6 * No expansion or interpretation. buffer_length had9 * better be even or you're asking for trouble. Returns < * the actual number of bytes written. The file was opened * by fdl_create(); * * fdl_getname(r, buffer)x * FDLSTUFF *r; * char *buffer;u9 * Copies the currently open file's name to the caller'si * data buffer buffer. * * longi * fdl_fsize(r)o1 * Returns the size in bytes of the opened file.e * * fdl_dump(fdl_descriptor, fd)A) * struct dsc$descriptor *fdl_descriptor;e * FILE *fd;2 * Writes the fdl info to the indicated file with& * line breaks in appropriate places. * * fdl_message(r, why) * FDLSTUFF *r;  * char *why;= * All system-level routines set a global value, fdl_status.c= * fdl_message() prints the error message text corresponding < * to the current value of fdl_status. The message printed * has the format:c) * why current_filename: error_message.e6 * If why is NULL, only the error_message is printed. */  e#include "lz.h" #if VMS_V4 #include rms#include ssdef#include descrip#include devdefx#ifndef FDL$M_FDL_SIGNAL6#define FDL$M_FDL_SIGNAL 1 /* Signal errors if set */#endif#ifndef FDL$M_FDL_STRING8#define FDL$M_FDL_STRING 2 /* Use string for fdl text */#endif#if TESTING_FDLIO (#define SIGNAL_ON_ERROR FDL$M_FDL_SIGNAL#elseV#define SIGNAL_ON_ERROR 0 #endif#define TRUE 1#define FALSE 0l #define EOS 0itypedef struct FDLSTUFF { - struct RAB rab; /* Record access buffer */.+ struct FAB fab; /* File access buffer */a) struct NAM nam; /* File name buffer */k4 struct XABFHC xab; /* Extended attributes block */7 char starname[NAM$C_MAXRSS + 1]; /* Wild file name */i7 char filename[NAM$C_MAXRSS + 1]; /* Open file name */y } FDLSTUFF; 3int fdl_status; /* Set to last rms call status */ static FDLSTUFF *ifail(r, why, name)FDLSTUFF *r; /* Buffer */(char *why; /* A little commentary */(char *name; /* Argument to perror *//* * Problem exit routinen */e{e#if TESTING_FDLIO2 if (name == NULL && r != NULL)l name = r->fab.fab$l_fna;  message(r, why, name);#endif if (r != NULL) free(r);_ return (NULL);}e e FDLSTUFF *#fdl_open(filename, fdl_descriptor)&char *filename; /* What to open */>struct dsc$descriptor *fdl_descriptor; /* Result descriptor *//*H * Open the file. Returns NULL on failure, else a pointer to RMS stuff.H * Which is equivalently a pointer to the RAB. (Note that the RAB points * in turn to the FAB.)e *H * Return the file's fdl descriptor in the user-supplied (uninitialized) * descriptor. */T{  register FDLSTUFF *r; int retlen; int badblk; struct FAB *fab_add; struct RAB *rab_add;: static int flags = (FDL$M_FDL_STRING | SIGNAL_ON_ERROR); extern FDLSTUFF *fdl_setup();e' if ((r = fdl_setup(filename)) == NULL)C return (NULL);H /* * Now open the file. */? r->fab.fab$b_fac = FAB$M_GET | FAB$M_BIO; /* Block I/O only */"7 if ((fdl_status = sys$open(&r->fab)) != RMS$_NORMAL) {e, return (fail(r, "opening file", NULL)); }+ if ((r->fab.fab$l_dev & DEV$M_REC) != 0) {e# fail(r, "Record only device");o fdl_close(r); return (NULL);g }4 r->rab.rab$l_rop = RAB$M_BIO; /* Block I/O only */8 if ((fdl_status = sys$connect(&r->rab)) != RMS$_NORMAL)5 return (fail(r, "connecting after open", NULL)); if (fdl_descriptor != NULL) { /* $ * Now, get the file attributes */) fdl_descriptor->dsc$w_length = 4096;X2 fdl_descriptor->dsc$b_dtype = DSC$K_DTYPE_VT;1 fdl_descriptor->dsc$b_class = DSC$K_CLASS_D;2 fdl_descriptor->dsc$a_pointer = malloc(4096); fab_add = &r->fab;M rab_add = &r->rab;$ if ((fdl_status = fdl$generate( &flags, &fab_add, &rab_add, 0, 0, fdl_descriptor, &badblk, &retlen)) != SS$_NORMAL) { fdl_free(fdl_descriptor); sys$close(&r->fab);, return(fail(r, "getting fdl info", NULL)); } /*F? * Success, null-terminate fdl info and squeeze the block.U */1 fdl_descriptor->dsc$a_pointer[retlen] = EOS;O" fdl_descriptor->dsc$a_pointer7 = realloc(fdl_descriptor->dsc$a_pointer, retlen + 1);T+ fdl_descriptor->dsc$w_length = retlen; } return (r);}R FDLSTUFF *-fdl_create(fdl_descriptor, override_filename)H>struct dsc$descriptor *fdl_descriptor; /* Result descriptor */.char *override_filename; /* What to open *//*I * Create the file, Returns NULL on failure, else a pointer to RMS stuff.H * Which is equivalently a pointer to the RAB. (Note that the RAB pointsF * in turn to the FAB.) The file is open for writing using fdl_write. *F * Uses the filename in the descriptor block, or the override filename( * if supplied (non-NULL and not == ""); *G * If fdl_descriptor is NULL, the override_filename is opened normally. */{ register FDLSTUFF *r; int retlen; int badblk;: static int flags = (FDL$M_FDL_STRING | SIGNAL_ON_ERROR); struct dsc$descriptor newname;$ struct dsc$descriptor *newname_ptr; int fid_block[3];' char created_name[NAM$C_MAXRSS + 1];+ struct dsc$descriptor created_name_des = { NAM$C_MAXRSS, DSC$K_DTYPE_T,  DSC$K_CLASS_S, &created_name[0] }; extern FDLSTUFF *fdl_setup(); if (fdl_descriptor == NULL) {4 if ((r = fdl_setup(override_filename)) == NULL) return (NULL);C r->fab.fab$b_fac = FAB$M_PUT | FAB$M_BIO; /* Block I/O only */= r->fab.fab$l_fop |= (FAB$M_NAM | FAB$M_SQO | FAB$M_BIO);8 r->fab.fab$b_org = FAB$C_SEQ; /* Sequential only */9 r->fab.fab$b_rfm = FAB$C_UDF; /* Undefined format */6 if ((fdl_status = sys$create(&r->fab)) & 01 == 0), return (fail(r, "creating (sys$create)")); goto exit; }? if (override_filename == NULL || override_filename[0] == '\0') newname_ptr = NULL; else { newname_ptr = &newname;6 newname.dsc$w_length = strlen(override_filename);) newname.dsc$b_dtype = DSC$K_DTYPE_T;) newname.dsc$b_class = DSC$K_CLASS_S;/ newname.dsc$a_pointer = override_filename; }- if ((fdl_status = fdl$create(fdl_descriptor,+ newname_ptr, /* New file name if any */ 0, /* Default filename */. &created_name_des, /* Resultant filename */& &fid_block[0], /* File ID block */ &flags, /* FDL flag bits */ 0, /* Statement number */& &retlen, /* Created name length */# 0, 0) /* Create status, stv */ ) & 01 == 0) {7 return(fail(NULL, "creating (fdl$create)", NULL)); } created_name[retlen] = '\0';+ if ((r = fdl_setup(created_name)) == NULL) return (NULL); /*" * Now, open the file for output. */? r->fab.fab$b_fac = FAB$M_PUT | FAB$M_BIO; /* Block I/O only */7 if ((fdl_status = sys$open(&r->fab)) != RMS$_NORMAL) {4 return (fail(r, "opening created file", NULL)); }0exit: if ((r->fab.fab$l_dev & DEV$M_REC) != 0) {# fail(r, "Record only device"); fdl_close(r); return (NULL); }4 r->rab.rab$l_rop = RAB$M_BIO; /* Block I/O only */8 if ((fdl_status = sys$connect(&r->rab)) != RMS$_NORMAL)7 return (fail(r, "connecting after create", NULL));t return (r);}o 1static FDLSTUFF *Ifdl_setup(filename)Mchar *filename;/*< * Initializes rms blocks and parses file name. Returns the, * FDL data block on success, NULL on error. */{* register FDLSTUFF *r;5 if ((r = (char *)malloc(sizeof (FDLSTUFF))) == NULL)e return (NULL);f* r->fab = cc$rms_fab; /* Preset fab, */+ r->nam = cc$rms_nam; /* name block */F0 r->rab = cc$rms_rab; /* and record block */4 r->xab = cc$rms_xabfhc; /* file header block */5 r->fab.fab$l_nam = &r->nam; /* fab -> name block */ 6 r->fab.fab$l_xab = &r->xab; /* fab -> file header */6 r->fab.fab$l_fna = filename; /* Argument filename */5 r->fab.fab$b_fns = strlen(filename); /* ... size */ / r->rab.rab$l_fab = &r->fab; /* rab -> fab */ /* Stuff the name block */9 r->nam.nam$l_esa = r->starname; /* Expanded filename */ 5 r->nam.nam$b_ess = NAM$C_MAXRSS + 1; /* ... size */ 9 r->nam.nam$b_rss = NAM$C_MAXRSS + 1; /* ... max size */i8 if ((fdl_status = sys$parse(&r->fab)) != RMS$_NORMAL) {+ return (fail(r, "parsing", filename));r }4 ((char *)r->nam.nam$l_esa)[r->nam.nam$b_esl] = EOS;6 r->fab.fab$l_fna = r->nam.nam$l_esa; /* File name */3 r->fab.fab$b_fns = r->nam.nam$b_esl; /* Length */s5 r->fab.fab$l_fop |= FAB$M_NAM; /* Use name block */r return (r);}* rfdl_free(fdl_descriptor)&struct dsc$descriptor *fdl_descriptor;/* * Release the descriptor */{- if (fdl_descriptor->dsc$a_pointer != NULL) {) free(fdl_descriptor->dsc$a_pointer);* fdl_descriptor->dsc$a_pointer = NULL; }} fdl_close(r)register FDLSTUFF *r;{6 if ((fdl_status = sys$close(&r->fab)) != RMS$_NORMAL)$ return(fail(r, "close", NULL)); free(r);} int"fdl_read(buffer, buffer_length, r)char *buffer; /* Record */)int buffer_length; /* Record length */,register FDLSTUFF *r; /* Record info. *//*G * Read the next record from the file. Returns number of bytes read or. * -1 on any error. fdl_status has the status. */{ r->rab.rab$l_ubf = buffer;" r->rab.rab$w_usz = buffer_length; r->rab.rab$l_bkt = 0;7 if ((fdl_status = sys$read(&r->rab)) != RMS$_NORMAL) {#if TESTING_FDLIO" if (fdl_status != RMS$_EOF) {/ fdl_message(r, "error return from sys$read"); sleep(1); }#endif return (-1); } return (r->rab.rab$w_rsz);} int#fdl_write(buffer, buffer_length, r)char *buffer; /* Record */)int buffer_length; /* Record length */,register FDLSTUFF *r; /* Record info. *//*I * Write the next record to the file. Returns number of bytes written or. * -1 on any error. fdl_status has the status. */{ r->rab.rab$l_rbf = buffer;" r->rab.rab$w_rsz = buffer_length; r->rab.rab$l_bkt = 0;8 if ((fdl_status = sys$write(&r->rab)) != RMS$_NORMAL) {#if TESTING_FDLIO3 fdl_message(r, "error return from sys$write"); sleep(1);#endif return (-1); } return (r->rab.rab$w_rsz);} fdl_getname(r, buffer)#FDLSTUFF *r; /* File pointer */&char *buffer; /* Where to put it *//* * Return current file name */{" strcpy(buffer, r->fab.fab$l_fna); return (buffer);}long fdl_fsize(r)#FDLSTUFF *r; /* File pointer *//* * Return current file size */{= return (((long) r->xab.xab$l_ebk * 512) + r->xab.xab$w_ffb);}fdl_message(r, why) FDLSTUFF *r; char *why;/* * Print error message */{ extern char *vms_etext(); if (why == NULL) {8 fprintf(stderr, "\n%s\n\n", vms_etext(fdl_status)); } else {( fprintf(stderr, "\n%s%s%s: %s\n\n", why, (why[0] == EOS) ? "" : " ",& (r == NULL) ? "" : r->fab.fab$l_fna, vms_etext(fdl_status)); }}7static char errname[257]; /* Error text stored here */Astatic $DESCRIPTOR(err, errname); /* descriptor for error text */ static char *vms_etext(errorcode)int errorco]~LZ.SAVFFYSDEV.PERROT.LZ]LZVIO.C;1I!Ga de;{ char *bp;* short errlen; /* Actual text length */0 lib$sys_getmsg(&errorcode, &errlen, &err, &15); /* * Trim trailing junk. */0 for (bp = &errname[errlen]; --bp >= errname;) {$ if (isgraph(*bp) && *bp != ' ') break; } bp[1] = EOS; return(errname);}staticmessage(r, why, name)FDLSTUFF *r; /* Buffer */(char *why; /* A little commentary */ char *name; /* File name *//* * Print error message */{/ fprintf(stderr, "\nRMS error %x when %s %s\n",2 fdl_status, why, (name == NULL) ? "" : name);4 fprintf(stderr, "\"%s\"\n", vms_etext(fdl_status));} fdl_dump(fdl_descriptor, fd)&struct dsc$descriptor *fdl_descriptor; FILE *fd;/* * Dump the descriptor to fd. */{ register char *tp, *end;$ tp = fdl_descriptor->dsc$a_pointer;) end = tp + fdl_descriptor->dsc$w_length; while (tp < end) { if (*tp == '"') { do { putc(*tp++, fd); } while (*tp != '"'); } putc(*tp, fd); if (*tp++ == ';') putc('\n', fd); }} #if TESTING_FDLIO/* * Test program for rms io */#include char line[133];char filename[133];char buffer[2048];main(argc, argv) int argc;char *argv[];{ FDLSTUFF *old; FDLSTUFF *new; int size, total, nrecords;8 struct dsc$descriptor fdl_info; /* Result descriptor */ for (;;) {( fprintf(stderr, "Old file name: "); fflush(stdout); if (gets(line) == NULL) break; if (line[0] == EOS) continue;5 if ((old = fdl_open(line, &fdl_info)) == NULL) {# fprintf(stderr, "open failed\n"); continue; }( fprintf(stderr, "New file name: "); if (gets(line) == NULL) break;7 if ((new = fdl_create(&fdl_info, line)) == NULL) {% fprintf(stderr, "create failed\n"); fdl_free(&fdl_info); continue; } fdl_getname(old, buffer);2 fprintf(stderr, "Fdl for \"%s\", size %ld\n", buffer, fdl_fsize(old));! fdl_dump(&fdl_info, stderr); total = nrecords = 0;@ while ((size = fdl_read(buffer, sizeof buffer, old)) > 0) { fdl_write(buffer, size, new); nrecords++; total += size; } fdl_close(old); fdl_close(new);; fprintf(stderr, "copied %d records, %d bytes total\n", nrecords, total); fdl_free(&fdl_info); }}#endif#endif*[SYSDEV.PERROT.LZ]SQ.DOC;2+,J8./E 4A-F0123KPWO56D< 7R%8 )$9GEHJ(title lzcomp File Compressionindex File compressionsynopsis .s.nf% lzcomp [-options] [infile [outfile]] .s.f description= lzcomp implements the Lempel-Ziv file compression algorithm.9 (Files compressed by lzcomp are uncompressed by lzdcmp.); It operates by finding common substrings and replaces them7 with a variable-size code. This is deterministic, and5 can be done with a single pass over the file. Thus,6 the decompression procedure needs no input table, but' can track the way the table was built.% Options may be given in either case. .lm +8 .p -86 -B Input file is "binary", not "human readable text".< This is necessary on Dec operating systems, such as VMS and@ RSX-11M, that treat these files differently. (Note that binary: support is rudamentary and probably insufficient as yet.); (On VMS version 4, this is ignored unless the -x option is1 specified or the input file is record-oriented.) .p -88 -M bits Write using the specified number of bits in the; code -- necessary for big machines making files for little5 machines. For example, if compressing a file on VMS: which is to be read on a PDP-11, you should select -M 12. .p -87 -V [n] Verbose if specified. If a value is specified,0 it will enable debugging code (if compiled in). .p -8; -X [n] "Export" -- write a file format that can be read byA other operating systems. Only the bytes in the file are copied;< file attributes are not preserved. If specified, the value9 determines the level of compatiblity. If not specified,; or specified with an explicit value of zero, and lzcomp is; running on Vax/VMS version 4 under VaxC and the input fileA is a disk or magtape file (block-oriented), a VMS-private output< format is used which is incompatible with the Unix compress: utility, but which preserves VMS file attributes. -X may take on the following values: .lm +4.s> .i -4;#0##Choose VMS private format. See restrictions below.5 .i -4;#1##Compatible with Unix compress version 3.0:4 this is the default if -x is given without a value.4 .i -4;#2##As above, but supress "block compression"6 .i -4;#3##Supress block compression and do not output3 a compress header block. This is for compatiblity: with a quite early version of Unix compress (and requires! conditional-compilation to use). .lm -4.s3 Note that the -B (binary) option is ignored unless8 the input file is "record-oriented", such as a terminal or mailbox. .lm -8.s1 The other two arguments are the input and output3 filenames respectively. Redirection is supported,. however, the output must be a disk/tape file.3 The file format is almost identical to the current7 Unix implementation of compress (V4.0). Files written6 by Unix compress should be readable by lzdcmp. Files0 written by lzcomp in export (-x) format will be6 readable by Unix compress (except that lzcomp outputs0 two "clear" codes to mark EOF. A patch to Unix compress is available.)VMS Restrictions5 VMS Private mode stores the true name and attributes6 of the input file into the compressed file and lzdcmp5 restores the attributes (and filename if requested).7 The following restrictions apply -- they may be lifted8 in the future as they are primarily due to the author's8 lack of understanding of the intricacies of of VMS I/O:& All files must be stored on disk.7 The lzcomp output file must be specified directly.5 Also, for all usage on VMS, the compressed file must# be written to, and read from disk.LZW compression algorithm6 This section is abstracted from Terry Welch's article1 referenced below. The algorithm builds a string4 translation table that maps substrings in the input5 into fixed-length codes. The compress algorithm may be described as follows:2 1. Initialize table to contain single-character strings.4 2. Read the first character. Set (the prefix string) to that character.+ 3. (step): Read next input character, K.1 4. If at end of file, output code(); exit.% 5. If K is in the string table: Set to K; goto step 3.+ 6. Else K is not in the string table. Output code();! Put K into the string table; Set to K; Goto step 3.9 "At each execution of the basic step an acceptable input9 string has been parsed off. The next character K is9 read and the extended string K is tested to see if it6 exists in the string table. If it is there, then the6 extended string becomes the parsed string and the7 step is repeated. If K is not in the string table,2 then it is entered, the code for the successfully4 parsed string is put out as comprssed data, the6 character K becomes the beginning of the next string, and the step is repeated."5 The decompression algorithm translates each received< code into a prefix string and extension [suffix] character.: The extension character is stored (in a push-down stack),7 and the prefix translated again, until the prefix is a8 single character, which completes decompression of this5 code. The entire code is then output by popping the stack.> "An update to the string table is made for each code received: (except the first one). When a code has been translated,8 its final character is used as the extension character,7 combined with the prior string, to add a new string to8 the string table. This new string is assigned a unique7 code value, which is the same code that the compressor8 assigned to that string. In this way, the decompressor6 incrementally reconstructs the same string table that< the decompressor used.... Unfortunately ... [the algorithm]$ does not work for an abnormal case.< The abnormal case occurs whenever an input character string4 contains the sequence KKK, where K already) appears in the compressor string table."1 The decompression algorithm, augmented to handle" the abnormal case, is as follows: 1. Read first input code; Store in CODE and OLDcode;3 With CODE = code(K), output(K); FINchar = K;, 2. Read next code to CODE; INcode = CODE; If at end of file, exit;5 3. If CODE not in string table (special case) then Output(FINchar); CODE = OLDcode;" INcode = code(OLDcode, FINchar); 4. If CODE == code(K) then Push K onto the stack; CODE == code(); Goto 4. 5. If CODE == code(K) then Output K; FINchar = K; 6. While stack not empty Output top of stack; Pop stack;* 7. Put OLDcode,K into the string table. OLDcode = INcode; Goto 2.< The algorithm as implemented here introduces two additional complications.9 The actual codes are transmitted using a variable-length9 encoding. The lowest-level routines increase the number6 of bits in the code when the largest possible code is transmitted.7 Periodically, the algorithm checks that compression is9 still increasing. If the ratio of input bytes to output8 bytes decreases, the entire process is reset. This can8 happen if the characteristics of the input file change.VMS Private File Structure7 In VMS Private mode, the compressed data file contains8 a variable-length (but compressed) file header with the4 file "attributes" needed by the operating system to4 construct the file. This allows the decompression5 program to recreate the file in its original format,5 which is essential if ISAM databases are compressed.' The overall file format is as follows: .lm +8 .p -8: LZ_SOH "start of header" signal (this value cannot appear in user data).2 A variable-length data record (maximum 256 bytes)= containing the header name, followed by whitespace, followed8 by header-specific information. In this case, the name9 record will contain the string "vms$attributes" followed4 by the number of bytes in the attribute data block.: (I assume that the name record will consist of a facility9 name, such as "vms", followed by a dollar sign, followed by a facility-unique word.) .p -8 LZ_EOR Signals "end of record".< This is followed by a VMS file attributes record (generated" by a VMS system library routine). .p -8! LZ_ETX Signals "end of segment". .p -8; ST_STX Signals "start of text" (i.e., start of data file).( This is followed by the user data file. .p -8 LZ_ETX Signals "end of segment" .p -8+ LZ_ETX Two in a row signals "end of file". .s.lm -88 Note that this format can easily be extended to include8 trailer records (with file counts and checksums) and/or, multiple data files in one compressed file.7 Note also that the LZ_CLEAR code may appear in headers4 or data files to cause the decompression program to4 "readapt" to the characteristics of the input data.3 LZ_STX and LZ_SOH reset the compression algorithm. LZ_EOR does not.Authors8 The algorithm is from "A Technique for High Performance: Data Compression." Terry A. Welch. IEEE Computer Vol 17, No. 6 (June 1984), pp 8-19." This revision is by Martin Minow.& Unix Compress authors are as follows: .s.nf8 Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) Jim McKie (decvax!mcvax!jim). Steve Davies (decvax!vax135!petsd!peora!srd)- Ken Turkowski (decvax!decwrl!turtlevax!ken)( James A. Woods (decvax!ihnp4!ames!jaw)% Joe Orost (decvax!vax135!petsd!joe) .s.ftitle lzdcmp File Decompressionindex File decompressionsynopsis .s.nf% lzdcmp [-options] [infile [outfile]] .s.f description5 lzdcmp decompresses files compressed by lzcomp. The2 documentation for lzcomp describes the process in greater detail.% Options may be given in either case. .lm +8 .p -80 -B Output file is "binary", not text. (Ignored in VMS private mode.) .p -85 -X 3 To read files compressed by an old Unix version& that doesn't generate header records. .p -84 -V val Verbose (print status messages and debugging: information). The value selects the amount of verbosity.Author3 This version by Martin Minow. See lzcomp for more details.I bFYSDEV.PERROT.LZ]LZQGR-C;1D&yUuj S~l !0j|B Bƽ"VV\ǂة>C8p$)lďX=6%¶!v P##zLR;6X!ȔlSA2m SR}06unH8e!iU+1U*ghie4Z7Z|Z~ZIe9؎K wdO&y\*@t(fhtHޯhiQ)nh,; cdhC&$&/)\"KZ4}zeSY9 F7A7&7VS>Gϔ@:&'xE,%B,F3 OeOMۙ3_.p(﷑iP$6C N*æ= 䨗f9z1~{ bi:k:P>~cܗ+WFUBgݨWba]) lǟ {$xGZm,YCFufXڏ qA8?4fXo{')l_ϽZ 9LtVփN)Lt:'$e~$pԒ3pWiͷ /늞lrD.~#1+WףHDRZ\+- *L C~?X`b `oW4b_=NjtpO=veOyNFtWq&ӽ;bŠ.ZgTZ*?@Oy)yGL߳āiri>Ʉ̏m:+eDeϒ2뽨Mj7)@4Xdg3>1郶fdGY-Qk|<"p_b uvAՅ[M (1L$v{`u\2sfޅPK/HJ m5+)׃ҜÈ-IuSU-ޔ{Ty ~8S4! S5"1p0# dI }&.@0g 2#/YwYl3hc+PQxZ ̍Qظt( ]"Kqmce3"&L^[ʹ]Y0ԜV(臱f#yibaFps;cQu$c]dvEg XUFSDIx_&I|1tO>-d%Ntڜ}^ԚWKFǤXLD/pȋ6* IC o| FQVҮ~k5~ F84ՠa4OZy@o3ԜY )vc}u6/=O GSfhv^b~ol؉A(r B Zv>m08%|'0іvFsĴ ="ǔX#_9[n z! }#f?5X y']1X?Z1\54rE.\91&暥TtR%f݋et*̊T)q9xoA}7K֍")d]Q!l'x5YIlIFVN:6^ !,^uQ jILt"V؎ L rŽ8D)WF Mq47˂+gtmGd*`p&N_zxRׇ67Ǧ,ƟcE|^KW6mU-1Bd)'cR7h .~o_AerTЧ.::\P@Z䦜HosLe,0J} Žz*㰷Z7e`{V[)7OF|^{2 \pM2d klRp> j^~dh#$h8禔1@DL v).pNg}vejpcrۏ!vpDjiR3{nUј<\N/y1,N )ZH(Ɛ״4NoMRt詼FgAUղ"D_#]M[Ǵ Pv"!6S^{Gw3l??ba bW 31S{5?|8@GbN|P51 1PdzvDJʌqU0ox`U-+VbU 4brM;?}1\֤mQWdm:DAc~HĹBG$X%#]`cXhra.oSo 7D"lڂ@ QS4MŴU&ƗpsifQ}JYSQ8pfzxD;MVdk?EӀ5HOXaΉsNl f լ@%8 WOk],!MS 6l?FCquE~X!9W`o)+lF)/Xߕ ¾􍐊[rl {2.iC\,_μyKΡ=V_EX ayD  r ޣfhCIOOmsIw2zS!+@oo/N b §mz!?utt= |wH."SՈO'mMrͬ~rmBsWaŒJ}mTӟCzOVIzgUt'"!h0xȖ 2&m`nyB}=%hX4!k>_x.;4 ȗz1ы8uSqj9hf%AY`{̾HsǩX&_g M)ͯW1ęC Ws| u"m>c=Ɋ!B.jl'/V|KU#1" \lVdMU#Ar!w*Bs@ҙouߝC _VHЊEh;^%Ǯ*~Q=@P>e#gOV';rlSw%?r+yt,Ӽٛʬk?b"øvUϏrctSL&yu6!>j/M)[SnPh4'إg%,wfzQ Z|ZӉҤw!gf8ע$ 4h⿩w$VrKeyfPN">ӶG<%I{6q\$ b/J56~U]?PHK ) mtQRlXޘ5o8t47pop^= %fAv_~i:`K#.y=a;u]&\Qq|>BڷEfjyKƖl ahZ1tc e8 r7$6v}ķrYަQ\_uL ꃄT 4.1rjwF/h0A7yW {cAj-XE$~{nhQR)C*Ix jv U.sɫ 5? z꼢SUY_WM7Rҕ[HZ,T Q]$A/_Ҭpcv^*~Mp-q/^[ckn+7nêncI&ڷ:+9(^ʵB⠢Hk뀌}(cfsΫzxbg ? HX<)XL.$fg%*棽_6 #?q{R?Ǝ&'HRHe YKQ<V>]k`{+ciH?Q3E0knCV-dƍ؊ 7}ZM fMv*_oѕ5rqvII`~A.G a`yf+F{? EwOB \V.jۅ%iq. LY`ivx$ѹuiY@k!a$HDF0Ʉ,iSb{2R>O"TQˈᶗ3=+V }Ԓm/`]UYF DSθ6s&'43'skZY|[_As茪-=}p/ϔָA4qctM L-aUcU0>Z_4Py>|k)&/su~N'`>Of}^mgWZjO~^ov6هq %d \ nr'DW( FtNS)PA$ԭo6ZUO7hn Y-=R2Al 8[~("yq e6p=t8ž>v&34jBfE4:-i½(qrkf!F,a*UMO=Zd6ޝ(8" ͗K r܈Ew讃[;xyXW#c?= -Bv {z{NZUT!aaP .I cJ\{.///jWBF8&6=BH|maI_A5WbQ0U#zgϣ度q*Ǡ]|4;[DMh'36KU 8Sӵ4|pñB;%n!71Yc!TuzXZJm L'1lKU2lnP %9eT;B>^2h6+Vq -7"79NY2ľwSHaP^rv(i~L:(HW4V |v1^=gjyi%]}V>Y}Ht=~8wUobJhs_ZjU<&Ҕv^4}ҀOX@bIrbsܴpTyh/!Ol$8dBq:\ tpxdI e8nېt3;p_SoÂ/t.A nw8 L-d/(+~l(UUm_gуkq { ;c1<[ufkT^iRp0I'BC#2yYv6 ȍCT^2/Da~׽N*ЋĢaO6qnATd@ 1>;pViw;*TtUd*NXL0.# e-2e :G/l Ҿk* ?0U\PP஖SgXN7B?SY5:tzqzPfjŬ0s1{&כ9ȪIwA9(sw%/.+@10cnC(di2$^s6t,Σ^VH h⟛4``?O9Yf3؏>Hs{1k F9AZjޯZZUzuf}&; u,5Lu'',xS &d*3lR?ZC8~Wp^LD|xѵ^cf6bJʃW<ΰ#+J{U?BQ 6'"_s1H'RZNߘᬽEgZw4aJBH5,äxN.E}=pZhf{!B\bj-M?/="k&)]I};b-Wjq?cMFq2PKZpxqwK*[v'lAz18P:+? U[yNSw^Po/Qu i'Þ'Ce:9?x~8<jݐ]Em@*%Ug1>ɕtag?GOpN-ψoxaҌ֋xD5ջ7NQIȶSnˇmЖyAǶB+qI>t:-ڳ) m4y^g r !lb``YޔUmmgR[v KK4V`T8 ޶MMV*}ŀLqE&YUi*_[|],_(>e:d0G^)>z?GiH (`#id/U 8À&\P+4P‚Z#&icgC S<Z~hk^„~?/ oDh$=4Y/sr,#,@,kt %`0wQǨ>ʣݬc=9T% aRXu*FĐt}/ Rk$/?'{tr|n.]R rԵq{]1@`nZDjXev.Ii?Zb UQ+ocB [C< [hS߽ٹ7fjNI>|u4T k[6Q=gl vhfdةݻ0G[ޝE_-nW+*Қo{N qatRAI>ofSD%nᨯTA|3ؠlW G!J(s+Kp%2 )u.NJϨ#j0P J(ygmD"n4m|3v%CTVx,1k{+T.@dٴJwWj% O |wS7]}!Ic|vرKcAڽAIgoWm%R~!SWǽdL*S0R5;me Gt(mWo PTi#x)pNtjN|ŦS#=#8-&v5wm>bg5K<|'_Xipr8tEmd)\xڅ;)ρu:Z()p%?SpA]"M&䆕YO~J^O.2}4W'O"^(8~-g DŌx5j7*KL@ČsТzHu[WW|4"8ەu dU`qq:(%Ѣ$뙬ҿQH)(t_{/G*$Nۡw8TT^U^ jo;]Y܉|/OP!~U.yp(kmy%dɄN8}3RO @<[V&hec-N;ETuab/P,ҞT.wC#\ϩ?$,Uӆ9c>) Sb'!,ylVt8~bi{J jV`_W.HI=ц &q~6KgS%lw*e1p0uB[yN pz!Gu_/ožD+$CȘA5;sqmG1s.93E22O!ߧm-xLib3yjU?]WqD$v+ LV 3vANޔԴ z*ec("er)>12'q~{+|:gHk ~IT W5t6Oo W[ z!/5'u(\hZ{=4VQ\xh|A֧*fLD^JelG:6m\Cj̓j>m5ob:ѵߨ%K uw(P-S֓ QLsưP 9`-5U2̼-4OG.xhiΑa!]@#& v6D_+O p S(vGlvfWln5x@7Y !=~w|PZe P@Y̭9v9!ӂWM٦{Uq 9/ İ7,YBzQ*b<),FiEo=p[G /GB~}'"rģ`Ŵ2WGe#^N an`O6䍂:]4oAk0fq`nT4Nz[.'؄A;;+,4!A)A5(i8O/-gol07|.9Ke0=ZQ¢Ճnnf FTJ h.)+ N3!Ae ~"-*k]UCl4 ExDb_o|zhrauYpJQ!ۊ{vUB&w4F/\T rPV_.{s0QepE/U[FITAK {k& Lde+o =9E|O9'y]1&p% WN^rOlU4k8?{g'X /&BDBEg!p[-O|nyՂ>%S۪9:oH)6Tcsjܢ6!@`S4RjcrV2&r Ջ$sUyRh TCV gogțWMT.|Q:r^`x2WUPr̨TP5TctN+g'xk!(l)pR=R+Q:Bx 0VA zwqVmSNMXJ:]2 kG~f@CΚ)XjΙ\_u\FI03[{kmT_R#W}jhhA۳hؓZ5UJ_DKiMyhGt/OMP0f`@@2EJt̸svͰ)d…ao*S,d% 3,>_+beXZгUGx: n! dl|eMwﶵPETFdH} wLrǰQ\1BZ2R6A@%KOQ%Sy5qu? K%g>oUɤ/3?.+gSKnOW:jaT`Y{$}dZU(\H2Sˢs6yHL~#ߝIB萲dyqh_#.FvkHw'K$5})q)c%@%ͨl)ɓݤjj"S̓cw{Xu<ENіH3#|:f32RN;G;hƫ^f7)!4%Asq?߲>]ˋx+K;*ֆq/VBSaq?a'/Ò3 >0Ҝؾ'5v&?G)8_&Om`LD`dz^v;{imtQd i3 x\"3/-P55"-i w]w#,WD#yU&Zh 1J$U0ĸ9~׉1+;Ԁ[X~@bsmS%U.=1,V u )pNj4'ux=[C`"jȜcvu9/6 L|b^4ƈZ!:N*D2kd[\W:1x[x?tZ豜c LHމU]zAv 7079:l_تD\zCKTO~B9dP.7Y-X ڀ([͔5 BZ6pUGuj4Ue<-oU@R结vl׀.@4"`ymC orewA@c @\s9818dMO.oT}%jX3r3XhAaW%P0ex~#.0)t%G1꬛ϞRԤL6K#,K1&VO\s>1nOhI6!/ի%3|Nx:vaҌpqU"9/0Ӟb41jĩu%@}<Pdv{ô$%/3Zx1}.}R9XI]$ρr O8QGӛ dfU'_ ^CwrS* ہX#V KTjv5S4m(_(j(ƒ] `@rC>)5yp4s8yGQ>(Ѱ**Q?Ԛ[Ex9Q S0䨑o,Uk9c6ŢɀmH1/O^wtod qZO1,.:8,Vlj.]$*d .;b` dFҰy"u`рm@хM wNCekWwS&}`1+@hLxh)brp޺͞-G)zH*]؉W <'<ؒ|/Co-(dJPNBbekr`/|[bSY7T2|0m/B >a)X Rcttđ;{K@[-ke_Wfu ORGdH͘|wYA>`0pϮתf=a^ zD ]C*0ZVlSaOǙӽ/YZvy9% Gk t~7,$RI$9u֓sWҽ)joOKmpi|FTe۳=@fh2v_3<i;ڛ4bIahVȮng!P~|_hX@!H鷜K78vf^K!i 5)]$ˈ eR0I;Y|`ؾ="P˨rLv\NCn!M$_E1-nm^47I{}XkyHJas;C?#wKev(pq&#lC)؂#K)7^+YZW"eۂMx;c/EO=f硜b ^͆&|һlHIGznt.+`,YړB_d9;\PuD++X\E_JtzL OpAN7R52)z Gf˙ݾL Q+4qqS/B3hF\COҧD !qpos{-ޤ޸-_7a72y.44ԛJ&lQwɄی>|~zq{ۙDGrI:(^H .U ^&E=QA,c w}E(;`/0ؠ8^5>/T _w)ٱBΈ-9E .OF(c#wdou6b1eR6gX"O7@~eɣ\ˢ\T:LvX5(/8b{1\u& OxiX4$V.Y<gfc`D.'p}>ؓ_`®!` b(敧BH@~47krKB܋֍2_b aj< ZLoǺeht[j+6q7$;&GGuA}lw#bp p5Xl$$}uVEj9^.n4XxݢU{|{J)ې!fv(Ug%\o˪ȭd|{SfjHu#eLjekUTy(vz)wuE? ڞ۷LovN"]޴ppI&K0a3Ja#W~`NZ஝ ^p9$1`NUs:o\W#(NtuyjJw(jMpL[`w@h'ܔ|܂ LQ:xJWc(:2 0sBb̅dҗoz`qK/>G@QE$)e=¤MBF>L5sGrEqM%^i:DZk*o98,ؚ,'\q>LpA5#_kC6'U|jeFhڠ?G -}"*_6g~͋mKmD}'GAT]DЏ#$ی=RǼX&fۓg=՜Cvi@灊yS?h=)G|m*[T,8#+&˂zYK/3Ƌ9:;Q~z5]l)_U/YL ҷSLs 9zo*Pk@ 􉔦\MjkXgK/_'$a|d(lC:}'gD(]:yOI>2p[oN۱ou#6xd5~Qfl)oUE8xpp^S{CKc3GW$=-nfONv&:ݫHFYq *"0@:a˚e"Hq;yiw {hU)- %%zyܬ\S{c`=P/~yoZ4-]yMLq|O|'9  9$Wp= 1\Y3tD%K+jʉcɣ ^yS;Փlހ^tƳ} Gqr⴦I˭l6X>}B Oьx&Z!#,Yvჟְj.k:,BjfMv 7OGLi J6Cd=ԗ@_MlSj_qgr(Tʩw,!ΩxLcY/taTݨXE&iC~0ӭG!Ϛ;yW^FH؁F d_P7k7=f&A*y.52XpxJ4(Wzh4LX=)WrCݛC4F=kBِ~/1WzɾzIr> BĹ$A\AvL%KoG%j-U/qxchh7)Q}GAxVv>kW&_PLf??s4;zWQAtˆba^Ym/21l~G3ӠRҭHUYȳ~D٭, PKK/(LOwηRJ4 Z,Ȱs`BWF/Ƨ Bv_欶:&-/`hkKkRd\X`g)YRe9 b|-Ǣ݄{_"6MsJM'(8b/T#6 |aJ;&}aW MEvnEpW,aa=NHM' 򊔾;IφE耄2sxb^vԭ]At%wD 0-d><2rkAvV'x=CJx ]Gs,^5inw=~fٙ WnN-o|ɖa+&>[Ń ș _.KBeD Z; qr"$2{A!Zk]B)|t ԅ).ƞozCen!lIU 5n7ʞ*[13%0FWE`A[Ūl uDG핒\i춞]A"*)uu0DV3Pϼ7E3|ìϾ =wVY_%M-ܳ?5ܰ` 1wk|4 +edHU۵NTmD$03`Qɇ#o<~<5 CC3y}k[g ꬖYS{Ѯ-5="kz4 rS#T}~8aы=*Uk<6;@r`a]M^S;O\g伢hШU!Cj1<}@uX $:nηWz0u:v=߷qyz+rMdsm.pq`C38u&6HSPPŐE=C.hHag>,OO"* 5%zF~Xueh|ߵ > EL!}͋ذWQwJ Wa:Gped6 ~𭺵&%~P sw/o£ɍёyTt+7V^0fUŦTꂎ%[3HOA'pakWQ~I 6yhrb0Ѝ"ޱNRͅ xruzq$@~Fʐ6P *{Iv6Ͷ$a"DMƉN1DU*(Y\vL[~ o>#@$E1&C隤ӊRgue@\Q~ǩ{ߑY~ImPXMqð{iJ͚q, KaNK"Q;[nq$ \H:ӄ%E{?ͯ (Uz5wq3g.0xEɞ=OVsB;pa(n>X\R"cHǯA7@{+=#_R{Pnȋ[i@)Z^]dsVœ~|/F<G:+jAw egV#yB|P~/{1*cj@Y>v~aq7D(~@ (sz!UM~hp_U;?ԩ e# 8=jVѽ)̋دnг |&ʻ}N&dݵ&"F: 9M {*}YŹ<c% A 7_̔vu%e bb9{+8YX㶺fN:mz7Jɸ}&MģٴaR׌A.vPxn8mgNZƉXȠdȶM . $p72+gX{ڡg%-9o:`oI!4?S3389wu5ww|9!Ʈz5gt^{62P' 4}5:n)F4+{/R;sb׊0'<6D.F ^XA9z1YI3M3J^YR$WP~}vs;K4TAP(aVtڝ4y:U[ДI^Z|fD?+_ gG+(%X7 89e=4 c7i2|v:YBӍm o)g]oۧ<whGmh|{Z1˯;*JWPEG,0{! G1z5w|:+0m_0ϋ}jo=u[H~n('QBG.&043%-vI֔5:ͤѫ, ekdeU,sgf5TמҼC^;f#C;'=cɁt *Dpk]ίj@L."m[PV١ -Ź\DG:b>^0tZ2 0F񠝷#kƃѬ ETá$A%`1+TVfP-&v͡HsV/ӫ0z4^q{K}EҰY-p몐emJ־{$_-LHd"j-}Vg@s5̬Y "gȹ'lR F!T 9r)oW, R+l΃Ɲt.(Sol:֧,A3MPtԌ6xw:GIXf?k:P=!(B9m1CW_A.o!w{/uDkK c1^s_hpKR#i3K.s~YgBW8eE-wlOSi :'lH5gW% _e9)I+]fOX#j\ۊ1ZCwђ~2"=rUx>fzzY-OR_uY2lSЁ;}uU _6۸]k{\~LP zICDfTk#.93K@Tnכ ʮpҮ_OLH]B*\ԩ|WH+eFbJp]2!‡K30cRP(z17p+NkӴC'zuV¨HU> ?>{OF0sfi:V1:]0w,y߹Pdh?p\#iR@e> \#?t2_[~/sZyN/Uq ss9rnx\sSщ'cz;.#zy -#6 m S_Ď2[ j WP&-.ɳ zitԒH"!WͫH(`ZabSoՁC!{UCM 0\oHZ &Ԓ@42_wⷴ"s7՞) ).xMcL1'Lf{;fIŕs%"@yvr̓k4GMj~/ _F:^2;sLL;1s{ѣ<]V'I9귡tWxr3i4^ғ! g=gڇ$L9ݙ|¡$X&UFC٘z 4[h;q-IY,8yYӸl-Q3s/0qJ1M`P`46eޚR,I9Qb0YM ;_^:Dpa߿HmW+_H;q`ԏ?m=4VאJU x6B.=۵ :jhh2^GBtEݺ79A3g+E'efU:x} &l- YAK&'!BhNJ潷; `;Gw[vNؾ:reE&| $X&x8]4ɂ% \]㑃o/mD(L$tjC(nɄf?BJC.\X+ w17~`@guQ@#)EС]Ya6ck0dAŞlۤeOʷDI&͉&@ K߲g @d.5]#ST͔ h8a} -$nz , k`KoaQЁ5x^}lc蛦SlA!pd_m=܎p1\$ SVirO{RY7P;{"|mH`dS `K"Zo=;}%WI_o|3TgS{f`{k7M4&6.tPg6dzSN ejtIksD] UMP\k9O)?mwzQ tyQrmZm1ni>Yqµ_xv,:qV5`*9"WpO\!eZn1W@; J>O>0}ɢnRhA!y+vBSEl 0elbyvp( mGc(O_V8O{$%g~h`f(` 4 t 䊷Q&m4xl%O~' 9f@ (s݀`eR'2IJhL{$T`GR b0IgJ:RaTpOppsɎlGМz0Y!|=Z,&&"e>\)$<}"H݉?iU(X\7{8k?Y}З&$ lqAؽ)m/,& ?]_Ylȋ V>ꢝ!{]`Հ"YGIT՜9mjakmG(;J˺#"> :ffYcOB| ~p. D;ZXFG@0>幁((d r߶w[lhĊ>Yu0}SF<ܕ" Cb!bE,KH%ɶ^,004/]% jڶV{G!1ʭcj~R9R|RD_*XT_H?!H2[Ȑ [g!cYaS7im O*IP\qg5T) evp۵ 0EȨgcCDlj\^Q4VFv7"zbO;Iha6Ԑm e"`*_ߑۏL0Dgd3t%8$aH#X5<~fQ v{2uOhg'רwjr8<||T:oد.NV`EI{ƬK%(!VǺWHoU$?|HsRv*ϣh5)jpyӵ侧w{YpF:p>`؀o3p!CVXHnqBK?J_=Sʚn~W T|;_5z!4q[i_KdPFq3\9QcA*Mõ+8{NaZV5qizy%h,?9VdX4L (B E6U4;U$Yn{$%$3qm9L-sk%N."G}hŹ3G.&`)y4 ^giՃm%* q*(J]MC"bKa'Q瘴+c Ϣ'(ȼ],U_.* E-Z3*|5t=F̈9qKf I U]ڛ("%juL6 KF /0isVvSny(:x sǑ[gnUX/!#P+bѝĞĽ ʺPv`%W?cRw#fT{^;&~Z_{餴X)Amk?NUi2',zyH BW~u'˧2-&܂SES6~7OuZmN54}?_$@WS/&H- T(0=6X2zn{X̀)JFAIUC816<|Xu&G[.ݖZW88D-Te2-V}A!OZ# ^Bx ^S͟&u'ARa?ܷ41rccc& {[#M=ĈQIà+XN.:nMhJzAܴ)8/p&9mFaZkU _}S%Auhs[xg,B.^  $c!0)]`"d3-+5ru9AiS,:Ϸ^r(h6Sb#=w0X1JX72?ؚKg>oBf&[rea!!אaBR8Щ 3^3m̶Ä|lj5i:{# ȟ2BRy)g4)E\^9Ԁ3U]Gs4 &#ft`1|`8P"?Nb3 i?-~?Y#~S1d y`L"+ߎBIrUG_|]ǚzhʓ }?.㶑)og0%~ y%,B L^xx|s)b$dIp/UtPw9;t!kJz:Ŝ[oHTd$-ptQH3+?D劓j[AƮj8 𵵑  Ks\o>ž*:V%PޮvuhueF8o:^NA 5$HHQ8!yu׿^d+[yD$`.yQ>S6)M%ƯliW Zv#6`}|DAF)Gzh*0I p ?m "&o>N8_"z[^yZ(D-Q79} <'_H$UQX:6SjGqQD8ڷã׈sb.AFh 7=>:SO kd7.]@S@} wIV-1K}?C/DJ W7Ďe+_AWן¢(fRFžϲA̓(#O^/R)s-Tj2k+;-Wo$;tv!qxjhmFDj"?~Ky>?| i) C4mj7UbkVӈ'@Jy3g֧%$"R2@ 9m P5Naε5+*c=,tʞ:xu.PW60;sZ#2bC}DZF\G E9S z΃͗{vH#guh!ІE1x  -_v>p˴nj4G2)L`.v4䳐"wQ$레V<$S- :=1N8 _u;2ky ̆ɨL)4[Dgv>o ;NJScVGt&j!ŌƆ8ۂ e;Y?Qfj<6~d]ia}\gc /^Dtfhqَ{Mފro kv`9yw 'Gڢ8ろ2D~z T\-|ONz9{W'mU-WވMz@+ir-H:N1 mEIu}) U'i0=;uzc&a\`! &?zM8Gt7q+aSu5tv܏/&hyŁS|15J kd0’7U\SꇊDSѬ>S}|`=(ZU)&qRV{\"t/ i%bZ_ :=]o*k+6#<"/o !]ow q_cs)ntw=/5n-&`\ˏ */* lz_putbuf(stp, STAC