Xref: news-dnh.mv.net comp.os.msdos.djgpp:446 Path: news-dnh.mv.net!mv!news.sprintlink.net!cs.utexas.edu!convex!not-for-mail From: rosenkra AT convex DOT com (William Rosenkranz) Newsgroups: comp.os.msdos.djgpp Subject: zlib(3x) library (part01/01) Date: 19 Jun 1995 00:16:52 -0500 Organization: Engineering, Convex Computer Corporation, Richardson, Tx USA Lines: 1627 Nntp-Posting-Host: convex1.convex.com Summary: stdio on compressed files Keywords: unix compress stdio uncompress To: djgpp AT sun DOT soe DOT clarkson DOT edu Dj-Gateway: from newsgroup comp.os.msdos.djgpp zlib part01/01 zlib for atari ST (and MSDOS) ----------------------------- [ excerpt from readme file ] note: if you do not have or use compress, this is probably not for you... zlib would be helpful with pagers like less. it would allow them to read compressed files if they can't already do this. it is read only (will not compress, just uncompress). this was posted to alt.sources circa nov 1990. i thought it would be useful so i ported it to TOS. it provides a stdio-like stream interface for reading compressed files. the args are similar to "normal" stdio. i ported it to TOS (Alcyon). it should work fine with sozobon, gcc, minix(?) and whatever, though i have not tested it with these. what it does: it provides a READ ONLY stream interface for compressed files, i.e. those compressed which unix compress (of which there is, of course, a TOS version). up to 16-bit compress is supported. no support for "zfputc" or "zfputs" or "zprintf" is provided here. still, this is very useful indeed. currently it might be limited to compressed text files, at least with alcyon, though that will probably not be the case with gcc. i also runs fine under unix. included are: zfopen open a compressed (or normal) file zfclose closes compressed stream zfgetc get a single char from stream (does cr-lf translation) zfgets get a single line from stream zfeof test for EOF on stream zfilter for working with stdin this library will handle 16-bit compressed files. it has been tested with 16-bit compress 4.3 for the atari ST: compress 4.3 88/12/26 08:00:00 don Options: Unix MAXBITS = 16 i have included an executable for zcat (the test program). see makefile for how to run it. all included in this post are alcyon-compatible libraries and aln index file (zlib.ndx). zlib.out is log of atari doindex command for aln random libraries. enjoy... -bill rosenkranz rosenkra AT convex DOT com ------------------------------ cut here ------------------------------ # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by William Rosenkranz on Mon Jun 19 00:59:17 1995 # # This archive contains: # zlib # # Error checking via sum(1) will be performed. LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH if sum -r /dev/null 2>&1 then sumopt='-r' else sumopt='' fi echo mkdir - zlib mkdir zlib echo x - zlib/ascii cat >zlib/ascii <<'@EOF' #ifndef _ZLIB_H #define _ZLIB_H 1 #include /* for _PROTO macro... */ #ifdef ALCYON # ifndef void # define void int # endif #endif #ifdef MSDOS # define PC_HUGE huge /* Microsoft C and contemptibles */ #else # define PC_HUGE #endif #define ZEXT ".Z" /* "normal" compressed file ext */ #ifdef __arm # undef ZEXT # define ZEXT "-z" #endif #define Z_BITS 16 #define Z_MAXBUF 256 /* * the major data structure, ZFILE */ typedef struct zfiletype { FILE *file; int flags; int n_bits; /* number of bits/code */ int maxbits; /* user settable max # bits/code */ long maxcode; /* maximum code, given n_bits */ long free_ent; /* first unused entry */ int block_compress; int clear_flg; long stackp; long finchar; long code, oldcode, incode; int offset, size; unsigned char buf[Z_BITS]; /* Passed to getcode */ unsigned char PC_HUGE *tab_suffixof; /* There is a flag bit to say whether */ long PC_HUGE *tab_prefixof; /* these have been allocated. */ int init; int bufput, bufget, bufend; unsigned char buff[Z_MAXBUF]; int c1, c2; int zeof; } ZFILE; /* * fcn prototypes... */ ZFILE *zfopen _PROTO((char *fileptr, char *how)); void zfclose _PROTO((ZFILE *z)); ZFILE *zfilter _PROTO((FILE *f)); int zfgetc _PROTO((ZFILE *z)); int zfeof _PROTO((ZFILE *z)); char *zfgets _PROTO((char *line, int len, ZFILE *zfp)); #endif /*_ZLIB_H*/ @EOF set `sum $sumopt zlib/readme.1st <<'@EOF' this is a replacement for stdio functions fopen, fclose, fgetc, fgets that will read (and decompress) files compressed with the unix compress program (.Z suffix). it is known to run under both unix and with gcc on the atari ST. it could be incorporated into a pager (like less). this would be especially helpful with manpages that tend to eat up a fair amount of space. compress usually will compress files to 40-50% of their original size. note that if file system fragment sizes are 8kb, and your files are all smaller than this, this would not be a win since the file would still eat up 8kb of space, even if it was 1 byte in size. anyway, i ported this to unix and the atari ST. it was originally written for DOS, so it should report back. -bill rosenkranz rosenkra AT convex DOT com @EOF set `sum $sumopt zlib/makefile <<'@EOF' # makefile for zlib as a library # # date: Sat Nov 17 14:27:48 1990 # version: 1.0 # SECT = 3 SUBSECT = x LIBTARG = zlib A =.a MANPAGE = zlib.$(SECT)$(SUBSECT) MANSRC = zlib.man H_FILE = zlib.h HEADERS = zdef.h OBJS = zfopen.o zfclose.o zfgets.o zfeof.o zfilter.o zfgetc.o SRCS = zfopen.c zfclose.c zfgets.c zfeof.c zfilter.c zfgetc.c OTHERS = readme $(MANSRC) makefile $(H_FILE) $(HEADERS) CC = cc -Aa OPT = -O CFLAGS = $(OPT) LDFLAGS = LIBS = #SLASH =\\ #LIBDIR = c:\usr\lib #MANTOP = c:\usr\man #MANDIR = $(MANTOP)$(SLASH)man$(SECT) #CATDIR = $(MANTOP)$(SLASH)cat$(SECT) #INCDIR = c:\usr\include SLASH =/ LIBDIR = /mnt/rosenkra/lib MANTOP = /mnt/rosenkra/man MANDIR = $(MANTOP)$(SLASH)man$(SECT) CATDIR = $(MANTOP)$(SLASH)cat$(SECT) INCDIR = /mnt/rosenkra/include TEST = testzcat EXE =#.ttp ZEXT =.Z INST_LIB = cp -p INST_H = cp -p INST_MAN = cp -p RM = rm -f RANLIB = ranlib # directions... # directions: @echo type "make initial" to built $(LIBTARG) the first time @echo type "make all" to built $(LIBTARG) @echo type "make install" to built/install $(LIBTARG) @echo type "make test" to make test for $(LIBTARG) @echo type "make runtest" to test $(LIBTARG) @echo type "make clean" to remove objects @echo type "make clobber" to remove objects and $(LIBTARG) # main library target (during development)... # all: $(LIBTARG)$(A) $(LIBTARG)$(A): $(OBJS) $(AR) rv $@ $? $(RANLIB) $(LIBTARG)$(A) # main target the first time... # initial: $(OBJS) $(AR) rv $(LIBTARG)$(A) $(OBJS) $(RANLIB) $(LIBTARG)$(A) # manpage # manpage: $(MANPAGE) $(MANPAGE): $(MANSRC) nroff -man $(MANSRC)|ul -t dumb|cat -s >$(MANPAGE) # install lib, header, and manpage... # install: install_lib install_h install_man install_lib: # $(LIBTARG)$(A) $(INST_LIB) $(LIBTARG)$(A) $(LIBDIR)$(SLASH)$(LIBTARG)$(A) $(RANLIB) $(LIBDIR)$(SLASH)$(LIBTARG)$(A) touch install_lib install_man: $(INST_MAN) $(MANSRC) $(MANDIR)$(SLASH)$(MANPAGE) $(INST_MAN) $(MANPAGE) $(CATDIR)$(SLASH)$(MANPAGE) touch install_man install_h: $(INST_H) $(H_FILE) $(INCDIR)$(SLASH)$(H_FILE) touch install_h # make a test program for the lib... # test: $(LIBTARG)$(A) $(TEST).o $(CC) $(LDFLAGS) -o $(TEST) $(TEST).o $(LIBTARG)$(A) $(LIBS) @echo done making $(LIBTARG) test program. @echo execute with "make runtest". runtest: @echo test ascii text file: ascii $(TEST)$(EXE) ascii >ascii.out cmp ascii ascii.out # rm ascii.out @echo test compressed file: asciic.z cp ascii asciic compress asciic $(TEST)$(EXE) asciic >asciic.out cmp ascii asciic.out # rm asciic$(ZEXT) asciic.out @echo test completed. # others... # clean: $(RM) *.o errs core clobber: clean $(RM) $(LIBTARG)$(A) # dependencies... # $(HEADERS): $(H_FILE) touch $(HEADERS) $(OBJS): $(HEADERS) $(TEST).o: $(H_FILE) $(TEST).c @EOF set `sum $sumopt zlib/manifest <<'@EOF' total 59 -rw------- 0 0 1615 Nov 17 04:18 ascii test file -rw------- 0 0 3110 Nov 17 15:22 makefile look here before leaping... -rw------- 0 0 1116 Nov 17 15:38 manifest this file -rw------- 0 0 1335 Nov 17 15:16 readme look here, too... -rw------- 0 0 937 Nov 17 15:27 zcat.c test program -rwx------ 0 0 15800 Nov 17 15:28 zcat.ttp its executable -rw------- 0 0 3992 Nov 17 15:27 zdef.h local header -rw------- 0 0 497 Nov 17 15:27 zfclose.c src... -rw------- 0 0 384 Nov 17 15:27 zfeof.c " -rw------- 0 0 6404 Nov 17 15:27 zfgetc.c " -rw------- 0 0 736 Nov 17 15:27 zfgets.c " -rw------- 0 0 1520 Nov 17 15:27 zfilter.c " -rw------- 0 0 2358 Nov 17 15:27 zfopen.c " -rw------- 0 0 7628 Nov 17 15:30 zlib ar68 library (alcyon,aln) -rw------- 0 0 2552 Nov 17 15:33 zlib.3x formatted manpage -rw------- 0 0 1615 Nov 17 15:26 zlib.h for include your dir -rw------- 0 0 2527 Nov 17 15:26 zlib.man nroff manpage -rw------- 0 0 204 Nov 17 15:31 zlib.ndx aln index -rw------- 0 0 606 Nov 17 15:31 zlib.out doindex output @EOF set `sum $sumopt zlib/readme <<'@EOF' zlib for atari ST ----------------- note: if you do not have or use compress, this is probably not for you... this was posted to alt.sources circa nov 1990. i thought it would be useful so i ported it to TOS. it provides a stdio-like stream interface for reading compressed files. the args are similar to "normal" stdio. i ported it to TOS (Alcyon). it should work fine with sozobon, gcc, minix(?) and whatever, though i have not tested it with these. what it does: it provides a READ ONLY stream interface for compressed files, i.e. those compressed which unix compress (of which there is, of course, a TOS version). up to 16-bit compress is supported. to write compressed files, you can do something like: write_to_tmp_file (buf, tmpfilename); sprintf (cmd, "compress %s", tmpfilename); system (cmd); no support for "zfputc" or "zfputs" or "zprintf" is provided here. still, this is very useful indeed. currently it might be limited to compressed text files, at least with alcyon, though that will probably not be the case with gcc. i also runs fine under unix. included are: zfopen open a compressed (or normal) file zfclose closes compressed stream zfgetc get a single char from stream (does cr-lf translation) zfgets get a single line from stream zfeof test for EOF on stream zfilter for working with stdin note that you MUST zfclose a file to free memory. exit/_exit will not do this for you (obviously). i have not tried working with zfilter for reading stdin. this is really compiler/library/shell dependent since stdin must be read binary (the cr-lf issue). my environment does not permit this (gulam), at least not to my knowledge. zfopen will currently only open compressed ascii files (DOS, TOS). zfgetc will check for a cr-lf and return only the linefeed. if the file is compressed, it normally has a .z extension. if not, zfopen will check to see if the file is in fact compressed. if not, zfgetc/zfgets will still read it using fgetc, though the read will be slower than using fgetc directly. i have not tested zfgets but it looks ok, more or less. see original author's comments in the src. this library will handle 16-bit compressed files. it has been tested with 16-bit compress 4.3 for the atari ST: compress 4.3 88/12/26 08:00:00 don Options: Unix MAXBITS = 16 makefile will build a library ("make initial" first time, then "make all" during development) and a version of zcat for testing ("make test"). to run the tests, do "make runtest" which uses file "ascii" for the tests. you will need compress(1) and cmp(1) to test. i have included an executable for zcat (the test program). see makefile for how to run it. all included in this post are alcyon-compatible libraries and aln index file (zlib.ndx). zlib.out is log of atari doindex command for aln random libraries. enjoy... -bill rosenkranz rosenkra%c1yankee AT convex DOT com @EOF set `sum $sumopt zlib/testzcat.c <<'@EOF' /* * test zlib package. this is more or less zcat */ #include "zlib.h" /* Written so it can be either included or linked in */ /*#include "zlib.c"*/ #ifndef __STDC__ int main (argc, argv) int argc; char *argv[]; #else int main (int argc, char **argv) #endif { char *myname; ZFILE *in; int i, c; #ifdef ALCYON myname = "testzcat"; #else myname = argv[0]; #endif if (argc == 1) { in = zfilter (stdin); for (c = zfgetc (in); c != EOF; putchar (c), c = zfgetc (in)) ; zfclose (in); } else if (argc > 1) { for (i = 1; i < argc; i++) { in = zfopen (argv[i], "r"); if (in != (ZFILE *) NULL) { for (c = zfgetc (in); c != EOF; putchar (c), c = zfgetc (in)) ; zfclose (in); } else { fprintf (stderr, "%s: cannot open %s\n", myname, argv[i]); } } } exit (0); } @EOF set `sum $sumopt zlib/zdef.h <<'@EOF' #undef DEBUG /*1*/ #undef MONITOR_CRLF /* * zdef.h */ /* * These wondrous debugging macros helped me find the nasty bug which * only manifested itself on msdos -- stackp has to be a long on msdos * because the array it is indexing is 'huge' ... */ #ifdef DEBUG int debug = 1; # define TRACT(lev, stmnt) if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt); # define TRACE(lev, stmnt) if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt); stmnt # define TRACA(lev, stmnt) stmnt; if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt); # define TRACL(lev, var) if (lev <= debug) fprintf(stderr, "%d: %s <- %ld\n", __LINE__, #var, var); #else # define TRACT(lev, stmnt) # define TRACE(lev, stmnt) stmnt # define TRACA(lev, stmnt) stmnt # define TRACL(lev, var) #endif /* * * Originally: * * compress.c - File compression ala IEEE Computer, June 1984. * * Authors: 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) * * $Header: zlib.c,v 4.1 90/11/12 14:52:24 gtoal Release $ * * Graham Toal, 3rd September 1988. My changes released to public domain. * Updated Nov 90. * * The original decompress has been restructured so that data can be * fetched on demand a byte at a time. This lets it be used as a filter * for programs which read large data files - you do not need the disk * space to decompress the input files first. * * (Incidentally, programs reading data off floppies will be speeded up * because decompression is always faster than the equivalent amount * of disk I/O). * * This implementation supplies 'z' versions of fopen, fputc, feof and fclose * to be used as direct substitutes for the originals; it would be cleaner * and more transparent if the decompress filter were hidden under the * real stdio procedures. An extra call zfilter() is supplied to convert * an already-opened stream into a z-stream: see the example at the end * of this file. * * If a file opened by zfopen() was not compressed, the files contents are * still recovered correctly at the low expense of an extra procedure call * per byte. This makes the routines more generally usable - they can be * left in production programs which can be speeded up in the field by * compressing selected input files(*); also, files can be compressed or * not selectively depending on whether the compression makes them * smaller or not - code accessing the files does not need to know. * * [(*) reading from a compressed file off floppy disk is faster than * reading from an uncompressed file. This probably isn't true of * hard disks though.] * * BUGS: Opening a file "r" will not do CR/LF processing on computers with * this file structure. */ #if defined(__unix) && !defined(unix) #define unix 1 #endif #include #include #ifdef __STDC__ # include #else # define size_t int #endif #include #if defined(MSDOS) # include #elif ! defined(unix) && ! defined(__unix) extern char *malloc (); #endif #ifndef min # define min(a,b) ((a>b) ? b : a) # endif #define HSIZE 69001L /* 95% occupancy */ /* * the next two codes should not be changed lightly, as they must not * lie within the contiguous general code space. */ #define FIRST 257L /* first free entry */ #define CLEAR 256L /* table clear output code */ #define BIT_MASK 0x1f #define BLOCK_MASK 0x80 #define INIT_BITS 9 /* initial number of bits/code */ #define CHECK_GAP 10000L /* ratio check interval */ #include "zlib.h" #define NOT_COMPRESSED 1 #define ALLOCATED 2 /* end of zdef.h */ @EOF set `sum $sumopt zlib/zfclose.c <<'@EOF' #include "zdef.h" /*------------------------------*/ /* zfclose */ /*------------------------------*/ #ifndef __STDC__ void zfclose (z) ZFILE *z; #else void zfclose (ZFILE *z) #endif { if (z == 0) return; if (z->zeof) { if ((z->flags & ALLOCATED) != 0) { #ifdef MSDOS hfree (z->tab_suffixof); hfree (z->tab_prefixof); #else free (z->tab_suffixof); free (z->tab_prefixof); #endif z->flags &= (~ALLOCATED); } } free (z); } @EOF set `sum $sumopt zlib/zfeof.c <<'@EOF' #include "zdef.h" /*------------------------------*/ /* zfeof */ /*------------------------------*/ #ifndef __STDC__ int zfeof (z) ZFILE *z; #else int zfeof (ZFILE *z) #endif { if ((z->flags & NOT_COMPRESSED) != 0) { if (z->c1 != EOF) { return ((int) (0 != 0)); } return ((int) feof (z->file)); } return ((int) (z->zeof)); } @EOF set `sum $sumopt zlib/zfgetc.c <<'@EOF' #include "zdef.h" #ifdef __STDC__ static void decompress_more(register ZFILE *z); static long getcode(register ZFILE *z); #else static void decompress_more(); static long getcode(); #endif #define CR 0x0D #define LF 0x0A /*------------------------------*/ /* zfgetc */ /*------------------------------*/ #ifndef __STDC__ int zfgetc (z) ZFILE *z; #else int zfgetc (ZFILE *z) #endif { int c; /* * If buffer empty, and not end-of-file, call decompress_more(); * return next in buffer. */ again: if ((z->flags & NOT_COMPRESSED) != 0) { if ((c = z->c1) >= 0) { z->c1 = z->c2; z->c2 = EOF; return ((int) c); } again2: c = fgetc (z->file); #if defined(ALCYON) /* * see note below... */ if (c == CR) goto again2; #endif return ((int) c); } if ((z->bufget == z->bufput) && (!z->zeof)) { decompress_more (z); } z->zeof = (z->bufput == z->bufget); if (z->zeof) { if ((z->flags & ALLOCATED) != 0) { #ifdef MSDOS hfree (z->tab_suffixof); hfree (z->tab_prefixof); #else free (z->tab_suffixof); free (z->tab_prefixof); #endif z->flags &= (~ALLOCATED); } return ((int) EOF); } c = z->buff[z->bufget]; z->bufget++; #ifdef MONITOR_CRLF if (c == CR) fprintf (stderr, "\n*** CR IN INPUT ***\n"); if (c == LF) fprintf (stderr, "\n*** LF IN INPUT ***\n"); #endif #if defined(ALCYON) /* * at least with alcyon, fputc will write a cr-nl if c is nl so * skip past the cr we read. other libraries may or may not have * this problem... */ if (c == CR) goto again; #endif return ((int) c); } /*------------------------------*/ /* decompress_more */ /*------------------------------*/ #ifndef __STDC__ static void decompress_more (z) register ZFILE *z; #else static void decompress_more (register ZFILE *z) #endif { z->bufput = 0; z->bufget = 0; if (z->init != 0) goto resume; z->init = 1; z->offset = 0; z->size = 0; #ifdef MSDOS z->tab_suffixof = (unsigned char PC_HUGE *) halloc (HSIZE, sizeof (unsigned char)); z->tab_prefixof = (long PC_HUGE *) halloc (HSIZE, sizeof (long)); #else z->tab_suffixof = (unsigned char *) malloc ((size_t) HSIZE * sizeof (unsigned char)); z->tab_prefixof = (long *) malloc ((size_t) HSIZE * sizeof (long)); #endif z->flags |= ALLOCATED; z->n_bits = INIT_BITS; z->maxcode = ((1L << (z->n_bits)) - 1L); for (z->code = 255L; z->code >= 0L; z->code--) { z->tab_prefixof[z->code] = 0L; z->tab_suffixof[z->code] = (unsigned char) z->code; } z->free_ent = ((z->block_compress) ? FIRST : 256L); z->finchar = z->oldcode = getcode (z); if (z->oldcode == -1L) return; /* EOF already? */ if (z->finchar < 0L || z->finchar >= 256L) fprintf (stderr, "****\n"); z->buff[z->bufput] = (char) (z->finchar & 0xff); z->bufput++; z->stackp = 1L << Z_BITS; /* The 1L is for DOS huge arrays */ while ((z->code = getcode (z)) != EOF) { if ((z->code == CLEAR) && z->block_compress) { for (z->code = 255; z->code >= 0; z->code--) z->tab_prefixof[z->code] = 0; z->clear_flg = 1; z->free_ent = FIRST - 1; if ((z->code = getcode (z)) == EOF) break; /* O, untimely death! */ } /* if */ z->incode = z->code; if (z->code >= z->free_ent) { z->tab_suffixof[z->stackp] = (unsigned char)z->finchar; z->stackp += 1L; z->code = z->oldcode; } while (z->code >= 256L) { z->tab_suffixof[z->stackp] = z->tab_suffixof[z->code]; z->stackp += 1L; z->code = z->tab_prefixof[z->code]; } z->finchar = z->tab_suffixof[z->code]; z->tab_suffixof[z->stackp] = (unsigned char) z->finchar; z->stackp += 1L; do { long tmp; z->stackp -= 1L; tmp = z->tab_suffixof[z->stackp]; z->buff[z->bufput++] = (unsigned char) (tmp & 255L); if (z->bufput == z->bufend) { /* * Logically a setjmp/longjump, but this * is more portable */ return; /* * jumped to here -- is jumping into a * loop safe? * - or should I use jumps for the loop too? */ resume: ; } /* if */ } while (z->stackp > (1L << Z_BITS)); /* ^ This is why I changed stackp from a pointer. */ /* Pointer comparisons can be dubious... */ if ((z->code = z->free_ent) < (1L << z->maxbits)) { z->tab_prefixof[z->code] = z->oldcode; z->tab_suffixof[z->code] = (unsigned char) z->finchar; z->free_ent = z->code + 1; } z->oldcode = z->incode; } /* while */ } static unsigned char rmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; /*------------------------------*/ /* getcode */ /*------------------------------*/ #ifndef __STDC__ static long getcode (z) register ZFILE *z; #else static long getcode (register ZFILE *z) #endif { /* Should be int!!! */ register long code; register long r_off, bits; register int bp; bp = 0; if (z->clear_flg != 0 || z->offset >= z->size || z->free_ent > z->maxcode) { if (z->free_ent > z->maxcode) { z->n_bits++; if (z->n_bits == z->maxbits) { z->maxcode = (1L << z->maxbits); /* won't get any bigger now */ } else { z->maxcode = ((1L << (z->n_bits)) - 1L); } } if (z->clear_flg != 0) { z->n_bits = INIT_BITS; z->maxcode = ((1L << (z->n_bits)) - 1L); z->clear_flg = 0; } z->size = fread (z->buf, 1, (size_t) z->n_bits, z->file); if (z->size <= 0) { fclose (z->file); return ((long) EOF); /* end of file */ } z->offset = 0; z->size = (z->size << 3) - (z->n_bits - 1); } r_off = z->offset; bits = z->n_bits; bp = bp + ((int) r_off >> 3); r_off = r_off & 7; code = ((long) z->buf[bp++] >> r_off); bits = bits - 8 + r_off; r_off = 8 - r_off; /* now, offset into code word */ if (bits >= 8) { code = code | ((long) z->buf[bp++] << r_off); r_off = r_off + 8; bits = bits - 8; } code = code | ((long)((long)(z->buf[bp]) & (long)rmask[bits]) << (long)r_off); z->offset = z->offset + z->n_bits; return ((long) code); } @EOF set `sum $sumopt zlib/zfgets.c <<'@EOF' #include "zdef.h" /*------------------------------*/ /* zfgets */ /*------------------------------*/ #ifndef __STDC__ char *zfgets (line, len, zfp) char *line; int len; ZFILE *zfp; #else char *zfgets (char *line, int len, ZFILE *zfp) #endif { /* * I *hope* this is what fgets does - I only added it * here when I came across a program that needed it; I'm * including the '\n' in the string. */ int c, pos = 0; for (;;) { c = zfgetc (zfp); if (c == EOF) return ((char *) NULL); c &= 255; line[pos] = (char) c; if (pos + 1 == len) /* Too long! */ break; pos++; if (c == '\n') break; } line[pos] = '\0'; return ((char *) line); } @EOF set `sum $sumopt zlib/zfilter.c <<'@EOF' #include "zdef.h" /*------------------------------*/ /* zfilter */ /*------------------------------*/ #ifndef __STDC__ ZFILE *zfilter (f) FILE *f; #else ZFILE *zfilter (FILE *f) #endif { register ZFILE *z; z = (ZFILE *) malloc (sizeof (ZFILE)); z->flags = 0; z->maxbits = Z_BITS; /* user settable max # bits/code */ z->free_ent = 0; /* first unused entry */ z->block_compress = BLOCK_MASK; z->clear_flg = 0; z->init = 0; z->zeof = (0 != 0); z->c1 = EOF; z->c2 = EOF; z->bufput = 0; z->bufget = 0; z->bufend = Z_MAXBUF - 1; z->maxbits = Z_BITS; /* user settable max # bits/code */ /* * Open input file */ z->file = f; if (z->file == (FILE *) NULL) { free (z); z = (ZFILE *) NULL; } /* * Check the magic number */ if (z != (ZFILE *) NULL) { z->c1 = fgetc (z->file); z->c2 = fgetc (z->file); if ((z->c1 != 0x1F) || (z->c2 != 0x9D)) { z->flags |= NOT_COMPRESSED; } } if ((z == (ZFILE *) NULL) || ((z->flags & NOT_COMPRESSED) != 0)) return ((ZFILE *) z); z->maxbits = fgetc (z->file); /* set -b from file */ z->block_compress = z->maxbits & BLOCK_MASK; z->maxbits &= BIT_MASK; if (z->maxbits > Z_BITS) { fprintf (stderr, "stdin compressed with %d bits; decompress can only handle %d bits\n", z->maxbits, Z_BITS); exit (0); } return ((ZFILE *) z); } @EOF set `sum $sumopt zlib/zfopen.c <<'@EOF' #include "zdef.h" /*------------------------------*/ /* zfopen */ /*------------------------------*/ #ifndef __STDC__ ZFILE *zfopen (fileptr, how) char *fileptr; char *how; #else ZFILE *zfopen (char *fileptr, char *how) #endif { ZFILE *z; /* * allocate space for the z structure */ z = (ZFILE *) malloc (sizeof (ZFILE)); if (z == (ZFILE *) NULL) { return ((ZFILE *) z); } /* * set up the structure... */ z->flags = 0; z->maxbits = Z_BITS; /* user settable max # bits/code */ z->free_ent = 0; /* first unused entry */ z->block_compress = BLOCK_MASK; z->clear_flg = 0; z->init = 0; z->zeof = (0 != 0); z->c1 = EOF; z->c2 = EOF; z->bufput = 0; z->bufget = 0; z->bufend = Z_MAXBUF - 1; z->maxbits = Z_BITS; /* user settable max # bits/code */ /* * Open input file */ if (*how == 'r') { #if defined(ALCYON) z->file = fopenb (fileptr, "r"); #elif defined(MSDOS) || defined(atarist) z->file = fopen (fileptr, "rb"); #else z->file = fopen (fileptr, "r"); #endif if (z->file == (FILE *) NULL) { char tempfname[256]; strcpy (tempfname, fileptr); strcat (tempfname, ZEXT); #if defined(ALCYON) z->file = fopenb (tempfname, "r"); #elif defined(MSDOS) || defined(atarist) z->file = fopen (tempfname, "rb"); #else z->file = fopen (tempfname, "r"); #endif } } else { /* * No compressed output yet, if ever... * Compress the file explicitly once it has been written */ #if defined(ALCYON) z->file = fopenb (fileptr, how); #else z->file = fopen (fileptr, how); #endif z->flags |= NOT_COMPRESSED; } if (z->file == (FILE *) NULL) { free (z); z = (ZFILE *) NULL; } /* * Check the magic number */ if ((z != (ZFILE *) NULL) && ((fgetc (z->file) != 0x1F) || (fgetc (z->file) != 0x9D))) { z->flags |= NOT_COMPRESSED; fclose (z->file); #ifdef ALCYON z->file = fopenb (fileptr, how); #else z->file = fopen (fileptr, how); #endif if (z->file == (FILE *) NULL) { free (z); z = (ZFILE *) NULL; } } if ((z == (ZFILE *) NULL) || ((z->flags & NOT_COMPRESSED) != 0)) return ((ZFILE *) z); z->maxbits = fgetc (z->file); /* set -b from file */ z->block_compress = z->maxbits & BLOCK_MASK; z->maxbits &= BIT_MASK; if (z->maxbits > Z_BITS) { fprintf (stderr, "%s: compressed with %d bits; decompress can only handle %d bits\n", fileptr, z->maxbits, Z_BITS); exit (0); } return ((ZFILE *) z); } @EOF set `sum $sumopt zlib/zlib.3x <<'@EOF' ZLIB(3X) ZLIB(3X) NAME zlib - stream interface to compress, read only SYNOPSIS #include ZFILE *zfopen (fileptr, how) char *fileptr; char *how; ZFILE *zfilter (f) FILE *f; int zfgetc (z) ZFILE *z; int zfeof (z) ZFILE *z; void zfclose (z) ZFILE *z; char *zfgets (line, len, zfp) char *line; int len; ZFILE *zfp; DESCRIPTION This implementation supplies 'z' versions of fopen(3s), fputc(3s), feof(3s), and fclose(3s) to be used as direct substitutes for the originals; it would be cleaner and more transparent if the decompress filter were hidden under the real stdio procedures. An extra call zfilter(3x) is supplied to convert an already-opened stream into a z- stream: see the example at the end of this file. Note that on the Atari or MSDOS, depending on the shell, stdin may have been opened as an ASCII stream and hence these routines are useless. A pre-existion stream MUST have been opened as a binary file. If a file opened by zfopen() was not compressed, the files contents are still recovered correctly at the low expense of an extra procedure call per byte. This makes the routines more generally usable - they can be left in production programs which can be speeded up in the field by compressing selected input files (see NOTES); also, files can be compressed or not selectively depending on whether the compression makes them smaller or not - code accessing the files does not need to know. NOTES Reading from a compressed file off floppy disk is faster than reading from an uncompressed file. This probably isn't true of hard disks - 1 - Formatted: June 18, 1995 ZLIB(3X) ZLIB(3X) though. The original decompress has been restructured so that data can be fetched on demand a byte at a time. This lets it be used as a filter for programs which read large data files - you do not need the disk space to decompress the input files first. Incidentally, programs reading data off floppies will be speeded up because decompression is always faster than the equivalent amount of disk I/O. BUGS Opening a file "r" will not do CR/LF processing on computers with this file structure. SEE ALSO intro(3S), fopen(3S) AUTHOR Graham Toal, 3rd September 1988. My changes released to public domain. Updated Nov 90. Modified for Atari ST (Alcyon C and GNU C) by Bill Rosenkranz - 2 - Formatted: June 18, 1995 @EOF set `sum $sumopt zlib/zlib.h <<'@EOF' #ifndef _ZLIB_H #define _ZLIB_H 1 /* * header for for zlib (compress file i/o utilities) */ #include #if defined(MSDOS) && !defined(__GNUC__) # define PC_HUGE huge /* Microsoft C and contemptibles */ #else # define PC_HUGE #endif #if defined(unix) || defined(__unix) #define ZEXT ".Z" /* "normal" compressed file ext */ #else #define ZEXT "Z" /* "normal" compressed file ext */ #endif #ifdef __arm # undef ZEXT # define ZEXT "-z" #endif #define Z_BITS 16 #define Z_MAXBUF 256 /* * the major data structure, ZFILE */ typedef struct zfiletype { FILE *file; int flags; int n_bits; /* number of bits/code */ int maxbits; /* user settable max # bits/code */ long maxcode; /* maximum code, given n_bits */ long free_ent; /* first unused entry */ int block_compress; int clear_flg; long stackp; long finchar; long code, oldcode, incode; int offset, size; unsigned char buf[Z_BITS]; /* Passed to getcode */ unsigned char PC_HUGE *tab_suffixof; /* There is a flag bit to say whether*/ long PC_HUGE *tab_prefixof; /* these have been allocated. */ int init; int bufput, bufget, bufend; unsigned char buff[Z_MAXBUF]; int c1, c2; int zeof; } ZFILE; /* * function prototypes... */ #if defined(__STDC__) ZFILE *zfopen(char *fileptr, char *how); void zfclose(ZFILE *z); ZFILE *zfilter(FILE *f); int zfgetc(ZFILE *z); int zfeof(ZFILE *z); char *zfgets(char *line, int len, ZFILE *zfp); #else ZFILE *zfopen(); void zfclose(); ZFILE *zfilter(); int zfgetc(); int zfeof(); char *zfgets(); #endif #endif /*_ZLIB_H*/ @EOF set `sum $sumopt zlib/zlib.man <<'@EOF' @.TH ZLIB 3X @.SH NAME zlib \- stream interface to compress, read only @.SH SYNOPSIS @.B "#include " @.sp @.B "ZFILE *zfopen" @.BI ( fileptr , @.IB how ) @.br @.B char @.BI * fileptr ; @.br @.B char @.BI * how ; @.sp @.B "ZFILE *zfilter" @.BI ( f ) @.br @.B FILE @.BI * f ; @.sp @.B "int zfgetc" @.BI ( z ) @.br @.B ZFILE @.BI * z ; @.sp @.B "int zfeof" @.BI ( z ) @.br @.B ZFILE @.BI * z ; @.sp @.B "void zfclose" @.BI ( z ) @.br @.B ZFILE @.BI * z ; @.sp @.B "char *zfgets" @.BI ( line , @.IB len , @.IB zfp ) @.br @.B char @.BI * line ; @.br @.B int @.IB len ; @.br @.B ZFILE @.BI * zfp ; @.sp @.SH DESCRIPTION This implementation supplies 'z' versions of @.BR fopen (3s), @.BR fputc (3s), @.BR feof (3s), and @.BR fclose (3s) to be used as direct substitutes for the originals; it would be cleaner and more transparent if the decompress filter were hidden under the real stdio procedures. An extra call @.BR zfilter (3x) is supplied to convert an already-opened stream into a z-stream: see the example at the end of this file. Note that on the Atari or MSDOS, depending on the shell, stdin may have been opened as an ASCII stream and hence these routines are useless. A pre-existion stream MUST have been opened as a binary file. @.PP If a file opened by @.B zfopen() was not compressed, the files contents are still recovered correctly at the low expense of an extra procedure call per byte. This makes the routines more generally usable \- they can be left in production programs which can be speeded up in the field by compressing selected input files (see NOTES); also, files can be compressed or not selectively depending on whether the compression makes them smaller or not \- code accessing the files does not need to know. @.SH NOTES Reading from a compressed file off floppy disk is faster than reading from an uncompressed file. This probably isn't true of hard disks though. @.PP The original decompress has been restructured so that data can be fetched on demand a byte at a time. This lets it be used as a filter for programs which read large data files \- you do not need the disk space to decompress the input files first. @.PP Incidentally, programs reading data off floppies will be speeded up because decompression is always faster than the equivalent amount of disk I/O. @.SH BUGS Opening a file "r" will not do CR/LF processing on computers with this file structure. @.SH "SEE ALSO" intro(3S), fopen(3S) @.SH AUTHOR Graham Toal, 3rd September 1988. @.br My changes released to public domain. @.br Updated Nov 90. @.sp Modified for Atari ST (Alcyon C and GNU C) by Bill Rosenkranz @EOF set `sum $sumopt