To compile:

1.  cd to the zlib directory.  do:

    % ./configure
    % make libz.a

2.  when that completes, cd to the zfunc directory.  do:

    % vi Makefile
    Make sure that everything is correct.  For most people, it already
    should be.


To use:

There are only a couple of simple changes you will need to make to your
code to use the zfunc functions.  These are:

1.  Change relevant "FILE *" variables to type "gzFile".

2.  Change the following functions to their equivalents.  Argument lists
    remain identical:

    fopen    -> zfopen (*)
    fgets    -> zfgets
    fungets  -> zfungets
    fprintf  -> zfprintf (**)
    ftell    -> zftell
    fclose   -> zfclose

    (*) You may want to change fopen( .. , "w") to  zfopen( .. , "w9") since
    the '9' indicates the level of compression to use.  Without it, the
    default gzip compression level is used.

    (**) zfprintf is only implemented if you have an ANSI compliant compiler
    (as specified in the Makefile).  Non-ANSI compilers don't do varargs the
    same..  If your compiler isn't ANSI, just use zlib's zwrite() function.
    -- Note:  I have found that some other compilers don't do varargs quite
    the same either;  if you aren't using gcc, you should probably turn off
    ANSI_COMPLIANT...

    Note that these functions will automagically Do The Right Thing(tm).
    Whether the file is compressed or uncompressed, the zfunc functions work.
    If you open a file for writing with zfopen, it will always be compressed,
    however.  (And have a .gz ending appended!)

3.  There are also a couple of new functions that you can use:

    gz_compress(FILE *in, gzFile out);

        Compresses a file which has been opened.  Both 'in' and 'out' must
        be previously opened.  This is usually accomplished by:

            FILE *f_in;
            gzFile f_out;
            int ok;  /* returns status */

            f_in = fopen("inputfile", "r");
            f_out = gzopen("outputfile.gz", "w9");
            ok = gz_compress(f_in, f_out);

        Does not delete input file.  DOES close both input and output files.

    z_fopen(char *path, char *mode, int compress);

        Differs from zfopen in that it accepts a "compress" argument, for
        which "compress" equals:

	    0:  Only open the file; don't do any modification

            1:  If the file isn't already compressed, compress it, creating
                an output file with a filename equivalent to the input
                filename, but with a ".gz" appended.  Does not delete the
                input file, however.

            2:  Same as (1) but also deletes the input file, if compression
                does not fail.

    z_fgets(char *s, int size, gzFile fd, char brk);

        Differs from zfgets in that it accepts a "brk" character, on which
        it assumes lines are broken.  zfgets(buffer, 10, f) is equivalent
        to z_fgets(buffer, 10, f, '\n').

        One note on this:  If you use the zfungets() function, you can't
        change the 'brk' character without getting unexpected results.  Also,
        brk should not be '\0'.

4.  You can test to make sure everything built ok, by going into the 'test'
    directory and typing 'make'.  (You might need to edit the Makefile)
    Use the source, Luke :)  The test program shows in quite a straight-
    forward way how to use zfunc.


NOTES ABOUT ZLIB:
=================

   The entire zlib library is included here.  This is zlib 1.0.4.  There may
be newer versions; I haven't checked lately.  (This one works good for me,
why upgrade?)

   I didn't write zlib, I don't maintain zlib, I barely know what zlib does :)
Please, ask the authors any questions pertaining to zlib.  Contact information
for the zlib guys is in zlib/README.

   If you find a bug in zlib, I suggest upgrading it (if an upgrade is
available).  Though it is relied upon heavily for zfunc, the version isn't
really that important.  In fact, you may not even need to recompile zfunc
to use it with a newer zlib.


NOTES ABOUT ZFUNC:
==================

   The zfunc library was written to be as portable as possible; it even works
on Windows.  The test program, however, only works on Unix since I was lazy
and used system() calls :)

   The library was also written with the intent of having multiple input
streams open at all times, without contention between them.  Therefore, you
can be reasonably assured that you are getting the correct data, even with
many files open at once.

   As usual, there is no guarantee that this will work, I do not support it,
I am making it available as a public service, I am not responsible for its
proper operation, "if it breaks you get to keep both pieces".

   I ran this program through Purify(tm), and I'd just like to get a little
plug in here for that program.. it is _excellent_ for finding memory leaks.
AFAIK, there are no memory leaks in this library.

   Finally, these instructions build zfunc & zlib as static libraries,
rather than shared libraries.  This is because a) you never know what the
users of your software have installed, and b) you can't even be sure they
have the right version of your libraries..  For these reasons I prefer
to build things with zfunc & zlib both statically linked.  RAM is cheap
nowadays, anyways :)


KNOWN BUGS:
===========

   You can't use '\0' as a break-character when using z_fgets.  If you use
zfungets, you must use the same break-character for every z_fgets, or you
will get unpredictable results.

   The pushback buffer for zfungets is, by default, only 256 bytes.  You
might want it bigger; change it in zfunc.h.

   It is definately possible, as a programmer, to create buffer-overflow
problems when using these functions.  I am almost certain that there are
buffer-overflow problems now.  Don't ever use this library for a suid root
program.  I don't worry about it otherwise though; the buffer is large, and
I have never had a problem with it :)

   If you use this with MS Windows, you MUST open all files in binary mode
(by opening with mode "rb", "wb" or "w9b").  Otherwise, the CR/LF hex that
plagues the DOS/Win world will bite you..

   I don't suggest defining ANSI_COMPLIANT in the Makefiles unless you are
using GCC.  Other compilers sometimes act like there are no problems, until
you try to use zprintf; then they core dump.  A better way to get around
this is to use the zlib function gzwrite() in combination with sprintf().
I.E.  you would change:
      fprintf(f, "The number %d and the string %s.", d, s);
to:
      char buffer[1024];  /* or some other large number */
      sprintf(buffer, "The number %d and the string %s.", d, s);
      gzwrite(f, buffer, strlen(buffer));

(If you look at the code, you'll see that this is what I do anyways..)
Of course, this makes code modification quite a bit more difficult.. could
someone do the work of porting the varargs stuff to other compilers?


CONTACT INFORMATION:
====================
If you use zfunc for something useful, tell me about it!  It's always a good
ego-booster to know that my code does more than waste space :)

If you find a problem in ZLIB:
****** DON'T ASK ME - I don't know the answer.  I really don't know anything
****** at all about how zlib works internally.  Contact that program's
****** authors; contact information for them is in zlib/README.

If you find a problem in ZFUNC:
ASK ME!  :)  I am usually willing to help if you are having a problem, or if
you find a bug.  You will find me even more cooperative when you find a
problem, if you fix the problem yourself, and send me the patch :)

The author of zfunc (that's me) is:

    Tom Kludy  (tkludy@engin.umich.edu)

Hope this makes programming those compression-aware apps much easier!
-Tom
