home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2064 < prev    next >
Internet Message Format  |  1990-12-28  |  19KB

  1. From: gtoal@tharr.UUCP (Graham Toal)
  2. Newsgroups: alt.sources
  3. Subject: code for reading from .Z files (with free zcat :-) )
  4. Message-ID: <1422@tharr.UUCP>
  5. Date: 15 Nov 90 00:59:40 GMT
  6.  
  7. Archive-name: zlib.shr
  8.  
  9. This posting consists of a set of routines which roughly simulate fopen,
  10. fgetc, fgets, and fclose.  The difference between these and the originals is
  11. that these will read data from a .Z compressed file, decompressing it on the
  12. fly.  It does *not* uses pipes, processes, or intermediate files.  This makes
  13. it useful to add to any programs which read large text files sequentially.
  14.  
  15. An example of this might be a version of LaTeX which read its .sty files in
  16. compressed form -- it satisfies the following criteria: 1) the files are read
  17. sequentially; 2) the files are read from *much* more often than they are
  18. written to.
  19.  
  20. I passed this code around a couple of years back, and forgot about it since. 
  21. I recently had to resurrect it, and have taken the chance to fix a couple of
  22. bugs which had surfaced in the mean time, and to port it to MSDOS. (Of course
  23. it still works on Unix or any standard ANSI C system)
  24.  
  25. I include as a test program a simple version of zcat; someone was asking
  26. recently for a small uncompress program; well this is it.
  27.  
  28. The source is heavily based on the original compress.  I've removed as much
  29. unneccesary code as I could get away with, and simplified many expressions to
  30. get them through the dismal MSDOS compilers.
  31.  
  32. Any comments/bug reports to me; Graham Toal <gtoal@ed.ac.uk>
  33.  
  34. #!/bin/sh-----cut here-----cut here-----cut here-----cut here-----
  35. # shar:    Shell Archiver
  36. #    Run the following text with /bin/sh to create:
  37. #    zcat.c 
  38. #    zlib.h 
  39. #    zlib.c 
  40. cat - << \SHAR_EOF > zcat.c
  41. #include <stdio.h>
  42. #include "zlib.h"
  43. /*#include "zlib.c"*/   /* Written so it can be either included or linked in */
  44.  
  45. /* This part is optional... you probably wouldn't do this in real life */
  46. #define FILE ZFILE
  47. #define fgetc(in) zfgetc(in)
  48. #define fopen(f, m) zfopen(f, m)
  49. #define fclose(f) zfclose(f)
  50.  
  51. #ifndef __STDC__
  52. int main(argc, argv)
  53. int argc;
  54. char **argv;
  55. #else
  56. int main(int argc, char **argv)
  57. #endif
  58. {
  59.   FILE *in;
  60.   int i, c;
  61.  
  62.   if (argc == 1) {
  63.     in = zfilter(stdin);
  64.     for (c = fgetc(in); c != EOF; putchar(c), c = fgetc(in)) ;
  65.     fclose(in);
  66.   } else if (argc > 1) {
  67.     for (i = 1; i < argc; i++) {
  68.       in = fopen(argv[i], "r");
  69.       if (in != NULL) {
  70.         for (c = fgetc(in); c != EOF; putchar(c), c = fgetc(in)) ;
  71.         fclose(in);
  72.       } else {
  73.        fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[i]);
  74.       }
  75.     }
  76.   }
  77.   return(0);
  78. }
  79. SHAR_EOF
  80. cat - << \SHAR_EOF > zlib.h
  81. #ifndef _ZLIB_H
  82. #define _ZLIB_H 1
  83.  
  84. #ifdef MSDOS
  85. #define PC_HUGE huge  /* Microsoft C and contemptibles */ 
  86. #else
  87. #define PC_HUGE
  88. #endif
  89.  
  90.  
  91. #define ZEXT ".Z"
  92.  
  93. #ifdef __arm
  94. #undef ZEXT
  95. #define ZEXT "-z"
  96. #endif
  97.  
  98. typedef struct zfiletype {
  99. #define Z_BITS 16
  100. #define Z_MAXBUF 256
  101.   FILE *file;
  102.   int flags;
  103.   int n_bits;                            /* number of bits/code */
  104.   int maxbits;                           /* user settable max # bits/code */
  105.   long maxcode;                           /* maximum code, given n_bits */
  106.   long free_ent;                          /* first unused entry */
  107.   int block_compress;
  108.   int clear_flg;
  109.  
  110.   long stackp;
  111.   long finchar;
  112.   long code, oldcode, incode;
  113.   int offset, size;
  114.   unsigned char buf[Z_BITS]; /* Passed to getcode */
  115.   unsigned char PC_HUGE *tab_suffixof;   /* There is a flag bit to say whether */
  116.   long PC_HUGE *tab_prefixof;    /* these have been allocated.         */
  117.   int init;
  118.  
  119.   int bufput, bufget, bufend;
  120.   unsigned char buff[Z_MAXBUF];
  121.   int c1, c2;
  122.   int zeof;
  123. } ZFILE;
  124.  
  125. #ifndef __STDC__
  126. ZFILE *zfopen(/* char *fileptr, char *how */);
  127. void zfclose(/* ZFILE *z */);
  128. ZFILE *zfilter(/* FILE *f */);
  129. int zfgetc(/* ZFILE *z */);
  130. int zfeof(/* ZFILE *z */);
  131. char *zfgets(/* char *line, int len, ZFILE *zfp */);
  132. #else
  133. ZFILE *zfopen(char *fileptr, char *how);
  134. void zfclose(ZFILE *z);
  135. ZFILE *zfilter(FILE *f);
  136. int zfgetc(ZFILE *z);
  137. int zfeof(ZFILE *z);
  138. char *zfgets(char *line, int len, ZFILE *zfp);
  139. #endif /* Not __STDC__ */
  140. #endif
  141. SHAR_EOF
  142. cat - << \SHAR_EOF > zlib.c
  143. /*#define MAIN*/
  144. /*int debug = 1;*/
  145. /*#define DEBUG 1*/
  146.  
  147. /* These wondrous debugging macros helped me find the nasty bug which
  148.    only manifested itself on msdos -- stackp has to be a long on msdos
  149.    because the array it is indexing is 'huge' ... */
  150. #ifdef DEBUG
  151. #define TRACT(lev, stmnt) \
  152.   if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt);
  153. #define TRACE(lev, stmnt) \
  154.   if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt); stmnt
  155. #define TRACA(lev, stmnt) \
  156.   stmnt; if (lev <= debug) fprintf(stderr, "%d: %s\n", __LINE__, #stmnt);
  157. #define TRACL(lev, var) \
  158.   if (lev <= debug) fprintf(stderr, "%d: %s <- %ld\n", __LINE__, #var, var);
  159. #else
  160. #define TRACT(lev, stmnt)
  161. #define TRACE(lev, stmnt) stmnt
  162. #define TRACA(lev, stmnt) stmnt
  163. #define TRACL(lev, var)
  164. #endif
  165. /* 
  166.  *
  167.  * Originally:
  168.  *
  169.  * compress.c - File compression ala IEEE Computer, June 1984.
  170.  *
  171.  * Authors:    Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  172.  *             Jim McKie               (decvax!mcvax!jim)
  173.  *             Steve Davies            (decvax!vax135!petsd!peora!srd)
  174.  *             Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  175.  *             James A. Woods          (decvax!ihnp4!ames!jaw)
  176.  *             Joe Orost               (decvax!vax135!petsd!joe)
  177.  *
  178.  * $Header: zlib.c,v 4.1 90/11/12 14:52:24 gtoal Release $
  179.  *
  180.  * Graham Toal, 3rd September 1988.  My changes released to public domain.
  181.  *                                   Updated Nov 90.
  182.  *
  183.  * The original decompress has been restructured so that data can be
  184.  * fetched on demand a byte at a time.  This lets it be used as a filter
  185.  * for programs which read large data files - you do not need the disk
  186.  * space to decompress the input files first.
  187.  *
  188.  * (Incidentally, programs reading data off floppies will be speeded up
  189.  *  because decompression is always faster than the equivalent amount
  190.  *  of disk I/O).
  191.  *
  192.  * This implementation supplies 'z' versions of fopen, fputc, feof and fclose
  193.  * to be used as direct substitutes for the originals; it would be cleaner
  194.  * and more transparent if the decompress filter were hidden under the
  195.  * real stdio procedures.  An extra call zfilter() is supplied to convert
  196.  * an already-opened stream into a z-stream: see the example at the end
  197.  * of this file.
  198.  *
  199.  * If a file opened by zfopen() was not compressed, the files contents are
  200.  * still recovered correctly at the low expense of an extra procedure call
  201.  * per byte.  This makes the routines more generally usable - they can be
  202.  * left in production programs which can be speeded up in the field by
  203.  * compressing selected input files(*); also, files can be compressed or
  204.  * not selectively depending on whether the compression makes them
  205.  * smaller or not - code accessing the files does not need to know.
  206.  *
  207.  * [(*) reading from a compressed file off floppy disk is faster than
  208.  * reading from an uncompressed file. This probably isn't true of
  209.  * hard disks though.]
  210.  *
  211.  * BUGS: Opening a file "r" will not do CR/LF processing on computers with
  212.  *       this file structure.
  213.  */
  214.  
  215. #include <stdio.h>
  216. #include <string.h>
  217. #ifdef __STDC__
  218. #include <stdlib.h>
  219. #else
  220. #define size_t int
  221. #endif
  222. #include <ctype.h>
  223.  
  224. #ifdef MSDOS
  225. #include <malloc.h>
  226. #endif
  227.  
  228. #ifndef min
  229. #define min(a,b)        ((a>b) ? b : a)
  230. #endif
  231. #define HSIZE           69001L  /* 95% occupancy */
  232.  
  233. /*
  234.  * the next two codes should not be changed lightly, as they must not
  235.  * lie within the contiguous general code space.
  236.  */
  237.  
  238. #define FIRST  257L     /* first free entry */
  239. #define CLEAR  256L     /* table clear output code */
  240.  
  241. #define BIT_MASK        0x1f
  242. #define BLOCK_MASK      0x80
  243. #define INIT_BITS       9       /* initial number of bits/code */
  244.  
  245. #define CHECK_GAP 10000L/* ratio check interval */
  246.  
  247. #include "zlib.h"
  248. #define NOT_COMPRESSED 1
  249. #define ALLOCATED 2
  250.  
  251. #ifndef __STDC__
  252. static void decompress_more( /* register ZFILE *z */ );
  253. static long getcode( /* register ZFILE *z */ );
  254. #else
  255. static void decompress_more(register ZFILE *z);
  256. static long getcode(register ZFILE *z);
  257. #endif
  258.  
  259. #ifndef __STDC__
  260. ZFILE *zfopen(fileptr, how)
  261.    char *fileptr;
  262.    char *how;
  263. #else
  264. ZFILE *zfopen(char *fileptr, char *how)
  265. #endif
  266. {
  267. register ZFILE *z;
  268.  
  269.    z = (ZFILE *) malloc(sizeof(ZFILE));
  270.    z->flags = 0;
  271.    z->maxbits = Z_BITS;         /* user settable max # bits/code */
  272.    z->free_ent = 0;             /* first unused entry */
  273.    z->block_compress = BLOCK_MASK;
  274.    z->clear_flg = 0;
  275.    z->init = 0;
  276.  
  277.    z->zeof = (0 != 0);
  278.    z->c1 = EOF;
  279.    z->c2 = EOF;
  280.    z->bufput = 0;
  281.    z->bufget = 0;
  282.    z->bufend = Z_MAXBUF - 1;
  283.  
  284.    z->maxbits = Z_BITS;         /* user settable max # bits/code */
  285.  
  286.    /* Open input file */
  287.    if (*how == 'r') {
  288.       z->file = fopen(fileptr, "rb");
  289.       if (z->file == NULL) {
  290. char tempfname[256];
  291.  
  292.          strcpy(tempfname, fileptr);
  293.          strcat(tempfname, ZEXT);
  294.          z->file = fopen(tempfname, "rb");
  295.       }
  296.    } else {
  297.       /* No compressed output yet, if ever...                  */
  298.       /* Compress the file explicitly once it has been written */
  299.       z->file = fopen(fileptr, how);
  300.       z->flags |= NOT_COMPRESSED;
  301.    }
  302.    if (z->file == NULL) {
  303.       free(z);
  304.       z = NULL;
  305.    }
  306.    /* Check the magic number */
  307.    if ((z != NULL) 
  308.        && ((fgetc(z->file) != 0x1F) || (fgetc(z->file) != 0x9D))) {
  309.       z->flags |= NOT_COMPRESSED;
  310.       fclose(z->file);
  311.       z->file = fopen(fileptr, how);
  312.       if (z->file == NULL) {
  313.          free(z);
  314.          z = NULL;
  315.       }
  316.    }
  317.    if ((z == NULL) || ((z->flags & NOT_COMPRESSED) != 0))
  318.       return (z);
  319.    z->maxbits = fgetc(z->file); /* set -b from file */
  320.    z->block_compress = z->maxbits & BLOCK_MASK;
  321.    z->maxbits &= BIT_MASK;
  322.    if (z->maxbits > Z_BITS) {
  323.       fprintf(stderr,
  324.         "%s: compressed with %d bits; decompress can only handle %d bits\n",
  325.               fileptr, z->maxbits, Z_BITS);
  326.       exit(0);
  327.    }
  328.    return (z);
  329. }
  330.  
  331. #ifndef __STDC__
  332. ZFILE *zfilter(f)
  333.    FILE *f;
  334. #else
  335. ZFILE *zfilter(FILE *f)
  336. #endif
  337. {
  338. register ZFILE *z;
  339.  
  340.    z = (ZFILE *) malloc(sizeof(ZFILE));
  341.    z->flags = 0;
  342.    z->maxbits = Z_BITS;         /* user settable max # bits/code */
  343.    z->free_ent = 0;             /* first unused entry */
  344.    z->block_compress = BLOCK_MASK;
  345.    z->clear_flg = 0;
  346.    z->init = 0;
  347.  
  348.    z->zeof = (0 != 0);
  349.    z->c1 = EOF;
  350.    z->c2 = EOF;
  351.    z->bufput = 0;
  352.    z->bufget = 0;
  353.    z->bufend = Z_MAXBUF - 1;
  354.  
  355.    z->maxbits = Z_BITS;         /* user settable max # bits/code */
  356.  
  357.    /* Open input file */
  358.    z->file = f;
  359.    if (z->file == NULL) {
  360.       free(z);
  361.       z = NULL;
  362.    }
  363.    /* Check the magic number */
  364.    if (z != NULL) {
  365.       z->c1 = fgetc(z->file);
  366.       z->c2 = fgetc(z->file);
  367.       if ((z->c1 != 0x1F) || (z->c2 != 0x9D)) {
  368.          z->flags |= NOT_COMPRESSED;
  369.       }
  370.    }
  371.    if ((z == NULL) || ((z->flags & NOT_COMPRESSED) != 0))
  372.       return (z);
  373.    z->maxbits = fgetc(z->file); /* set -b from file */
  374.    z->block_compress = z->maxbits & BLOCK_MASK;
  375.    z->maxbits &= BIT_MASK;
  376.    if (z->maxbits > Z_BITS) {
  377.       fprintf(stderr,
  378.       "stdin compressed with %d bits; decompress can only handle %d bits\n",
  379.               z->maxbits, Z_BITS);
  380.       exit(0);
  381.    }
  382.    return (z);
  383. }
  384.  
  385. #ifndef __STDC__
  386. int zfgetc(z)
  387.    ZFILE *z;
  388. #else
  389. int zfgetc(ZFILE *z)
  390. #endif
  391. {
  392. int c;
  393.  
  394.    /*
  395.       If buffer empty, and not end-of-file, call decompress_more(); return
  396.       next in buffer.  
  397.    */
  398.    if ((z->flags & NOT_COMPRESSED) != 0) {
  399.       if ((c = z->c1) >= 0) {
  400.          z->c1 = z->c2;
  401.          z->c2 = EOF;
  402.          return (c);
  403.       }
  404.       return (fgetc(z->file));
  405.    }
  406.    if ((z->bufget == z->bufput) && (!z->zeof)) {
  407.       decompress_more(z);
  408.    }
  409.    z->zeof = (z->bufput == z->bufget);
  410.    if (z->zeof) {
  411.       if ((z->flags & ALLOCATED) != 0) {
  412. #ifdef MSDOS
  413.          hfree(z->tab_suffixof);
  414.          hfree(z->tab_prefixof);
  415. #else
  416.          free(z->tab_suffixof);
  417.          free(z->tab_prefixof);
  418. #endif
  419.          z->flags &= (~ALLOCATED);
  420.       }
  421.       return (EOF);
  422.    }
  423.    c = z->buff[z->bufget];
  424.    z->bufget++;
  425.    return (c);
  426. }
  427.  
  428. #ifndef __STDC__
  429. int zfeof(z)
  430.    ZFILE *z;
  431. #else
  432. int zfeof(ZFILE *z)
  433. #endif
  434. {
  435.    if ((z->flags & NOT_COMPRESSED) != 0) {
  436.       if (z->c1 != EOF) {
  437.          return (0 != 0);
  438.       }
  439.       return (feof(z->file));
  440.    }
  441.    return (z->zeof);
  442. }
  443.  
  444. #ifndef __STDC__
  445. void zfclose(z)
  446.    ZFILE *z;
  447. #else
  448. void zfclose(ZFILE *z)
  449. #endif
  450. {
  451.    if (z == 0)
  452.       return;
  453.    if (z->zeof) {
  454.       if ((z->flags & ALLOCATED) != 0) {
  455. #ifdef MSDOS
  456.          hfree(z->tab_suffixof);
  457.          hfree(z->tab_prefixof);
  458. #else
  459.          free(z->tab_suffixof);
  460.          free(z->tab_prefixof);
  461. #endif
  462.          z->flags &= (~ALLOCATED);
  463.       }
  464.    }
  465.    free(z);
  466. }
  467.  
  468. #ifndef __STDC__
  469. char *zfgets(line, len, zfp)
  470.    char *line;
  471.    int len;
  472.    ZFILE *zfp;
  473. #else
  474. char *zfgets(char *line, int len, ZFILE *zfp)
  475. #endif
  476. {
  477. /* I *hope* this is what fgets does - I only added it
  478.    here when I came across a program that needed it; I'm
  479.    including the '\n' in the string. */
  480. int c, pos = 0;
  481.  
  482.    for (;;) {
  483.       c = zfgetc(zfp);
  484.       if (c == EOF)
  485.          return (NULL);
  486.       c &= 255;
  487.       line[pos] = (char) c;
  488.       if (pos + 1 == len)       /* Too long! */
  489.          break;
  490.       pos++;
  491.       if (c == '\n')
  492.          break;
  493.    }
  494.    line[pos] = '\0';
  495.    return (line);
  496. }
  497.  
  498. #ifndef __STDC__
  499. static void decompress_more(z)
  500.    register ZFILE *z;
  501. #else
  502. static void decompress_more(register ZFILE *z)
  503. #endif
  504. {
  505.    z->bufput = 0;
  506.    z->bufget = 0;
  507.  
  508.    if (z->init != 0)
  509.       goto resume;
  510.    z->init = 1;
  511.  
  512.    z->offset = 0;
  513.    z->size = 0;
  514. #ifdef MSDOS
  515.    z->tab_suffixof =
  516.      (unsigned char PC_HUGE *) halloc(HSIZE, sizeof(unsigned char));
  517.    z->tab_prefixof =
  518.      (long PC_HUGE *) halloc(HSIZE, sizeof(long));
  519. #else
  520.    z->tab_suffixof =
  521.     (unsigned char *) malloc((size_t) HSIZE * sizeof(unsigned char));
  522.    z->tab_prefixof = (long *) malloc((size_t) HSIZE * sizeof(long));
  523. #endif
  524.    z->flags |= ALLOCATED;
  525.  
  526.    z->n_bits = INIT_BITS;
  527.    z->maxcode = ((1L << (z->n_bits)) - 1L);
  528.    for (z->code = 255L; z->code >= 0L; z->code--) {
  529.       z->tab_prefixof[z->code] = 0L;
  530.       z->tab_suffixof[z->code] = (unsigned char) z->code;
  531.    }
  532.    z->free_ent = ((z->block_compress) ? FIRST : 256L);
  533.  
  534.    z->finchar = z->oldcode = getcode(z);
  535.    if (z->oldcode == -1L)
  536.       return;                   /* EOF already? */
  537.    if (z->finchar < 0L || z->finchar >= 256L)
  538.       fprintf(stderr, "****\n");
  539.    z->buff[z->bufput] = (char) (z->finchar & 0xff);
  540.    z->bufput++;
  541.  
  542.    z->stackp = 1L << Z_BITS;    /* The 1L is for DOS huge arrays */
  543.  
  544.    while ((z->code = getcode(z)) != EOF) {
  545.       if ((z->code == CLEAR) && z->block_compress) {
  546.          for (z->code = 255; z->code >= 0; z->code--)
  547.             z->tab_prefixof[z->code] = 0;
  548.          z->clear_flg = 1;
  549.          z->free_ent = FIRST - 1;
  550.          if ((z->code = getcode(z)) == EOF)
  551.             break;              /* O, untimely death! */
  552.       }                         /* if */
  553.       z->incode = z->code;
  554.       if (z->code >= z->free_ent) {
  555.          z->tab_suffixof[z->stackp] = (unsigned char) z->finchar;
  556.          z->stackp += 1L;
  557.          z->code = z->oldcode;
  558.       }
  559.       while (z->code >= 256L) {
  560.          z->tab_suffixof[z->stackp] = z->tab_suffixof[z->code];
  561.          z->stackp += 1L;
  562.          z->code = z->tab_prefixof[z->code];
  563.       }
  564.       z->finchar = z->tab_suffixof[z->code];
  565.       z->tab_suffixof[z->stackp] = (unsigned char) z->finchar;
  566.       z->stackp += 1L;
  567.       do {
  568. long tmp;
  569.  
  570.          z->stackp -= 1L;
  571.          tmp = z->tab_suffixof[z->stackp];
  572.          z->buff[z->bufput++] = (unsigned char) (tmp & 255L);
  573.          if (z->bufput == z->bufend) {
  574.             return;             /* Logically a setjmp/longjump, but this is
  575.                                    more portable */
  576.       resume:;                  /* jumped to here -- is jumping into a loop
  577.                                    safe? */
  578.             /* - or should I use jumps for the loop too?      */
  579.          }                      /* if */
  580.       } while (z->stackp > (1L << Z_BITS));
  581.       /* ^ This is why I changed stackp from a pointer. */
  582.       /* Pointer comparisons can be dubious...          */
  583.       if ((z->code = z->free_ent) < (1L << z->maxbits)) {
  584.          z->tab_prefixof[z->code] = z->oldcode;
  585.          z->tab_suffixof[z->code] = (unsigned char) z->finchar;
  586.          z->free_ent = z->code + 1;
  587.       }
  588.       z->oldcode = z->incode;
  589.    }                            /* while */
  590. }                       /* decompress more */
  591.  
  592. static unsigned char rmask[9] =
  593. {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  594.  
  595. #ifndef __STDC__
  596. static long getcode(z)
  597.    register ZFILE *z;
  598. #else
  599. static long getcode(register ZFILE *z)
  600. #endif
  601. {                       /* Should be int!!! */
  602. register long code;
  603. register long r_off, bits;
  604. register int bp;
  605.  
  606.    bp = 0;
  607.    if (z->clear_flg != 0 ||
  608.        z->offset >= z->size ||
  609.        z->free_ent > z->maxcode) {
  610.       if (z->free_ent > z->maxcode) {
  611.          z->n_bits++;
  612.          if (z->n_bits == z->maxbits) {
  613.             z->maxcode = (1L << z->maxbits);    /* won't get any bigger now */
  614.          } else {
  615.             z->maxcode = ((1L << (z->n_bits)) - 1L);
  616.          }
  617.       }
  618.       if (z->clear_flg != 0) {
  619.          z->n_bits = INIT_BITS;
  620.          z->maxcode = ((1L << (z->n_bits)) - 1L);
  621.          z->clear_flg = 0;
  622.       }
  623.       z->size = fread(z->buf, 1, (size_t) z->n_bits, z->file);
  624.       if (z->size <= 0) {
  625.          fclose(z->file);
  626.          return (EOF);          /* end of file */
  627.       }
  628.       z->offset = 0;
  629.       z->size = (z->size << 3) - (z->n_bits - 1);
  630.    }
  631.    r_off = z->offset;
  632.    bits = z->n_bits;
  633.    bp = bp + ((int) r_off >> 3);
  634.    r_off = r_off & 7;
  635.    code = ((long) z->buf[bp++] >> r_off);
  636.    bits = bits - 8 + r_off;
  637.    r_off = 8 - r_off;           /* now, offset into code word */
  638.    if (bits >= 8) {
  639.       code = code | ((long) z->buf[bp++] << r_off);
  640.       r_off = r_off + 8;
  641.       bits = bits - 8;
  642.    }
  643.    code = code 
  644.       | ((long) ((long) (z->buf[bp]) & (long) rmask[bits]) << (long) r_off);
  645.    z->offset = z->offset + z->n_bits;
  646.    return (code);
  647. }
  648.  
  649. #ifdef MAIN
  650.  
  651. /* This part is optional... */
  652. #define FILE ZFILE
  653. #define fgetc(in) zfgetc(in)
  654. #define fopen(f, m) zfopen(f, m)
  655. #define fclose(f) zfclose(f)
  656.  
  657. #ifndef __STDC__
  658. int main(argc, argv)
  659.    int argc;
  660.    char **argv;
  661. #else
  662. int main(int argc, char **argv)
  663. #endif
  664. {
  665. FILE *in;
  666. int i, c;
  667.  
  668.    if (argc == 1) {
  669.       in = zfilter(stdin);
  670.       for (c = fgetc(in); c != EOF; fputc(c, stderr), c = fgetc(in));
  671.       zfclose(in);
  672.    } else if (argc > 1) {
  673.       for (i = 1; i < argc; i++) {
  674.          in = fopen(argv[i], "r");
  675.          if (in != NULL) {
  676.             for (c = fgetc(in); c != EOF; fputc(c, stderr), c = fgetc(in));
  677.             fclose(in);
  678.          } else {
  679.             fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[i]);
  680.          }
  681.       }
  682.    }
  683.    return (0);
  684. }
  685.  
  686. #endif
  687. SHAR_EOF
  688.  
  689. -- 
  690. (* Posted from tharr.uucp - Public Access Unix - +44 (234) 261804 *)
  691.