My C utilitiy library is just one of my computer related personal projects. This project is finished.

.

C Utility Library

I have a bunch of data abstractions that I tend to use when I write C code that I have collected together into my own personal C utility library.

All of the code in this library has the following copyright:

    Copyright (c) 199x by Wayne C. Gramlich.
    All rights reserved.

    Permission to use, copy, modify, distribute, and
    sell this software for any purpose is hereby
    granted without fee provided that the above
    copyright notice and this permission are retained.
    The author makes no representations about the
    suitability of this software for any purpose.
    It is provided "as is" without express or implied
    warranty.
 								

This is basically the same copyright notice used for the code in the X11 release. Basically all it says is that you are free to use the code and you do not owe me a dime; likewise if you do not like the code for any reason, I do not owe you a dime. That is all there is to it.

For each data abstraction there tends to be 4 or 5 files that I use for declaration, implementation and testing:

Definition Header
A definition header contains the actual structure definitions that implement data type. In general, a definition header should only be included by the code that implements the data type, but there are occasional instances where it is necessary to violate abstraction boundaries. Definition header files have a suffix of `_defs.h'.
Exports Header
An exports header contains the prototypes for the exported global routines for the datatype. It is legitimate for any source file to include an exports header file. Exports header files have a suffix of `_exports.h'.
Types Header
A types header contains C typedefs for the data type. A types header file can be legitimately included by either other header files or by any C source file. Types header files have a suffix of `_types.h'.

The reason why types header files are not rolled into exports header files is because it is really to get a cycle of routine prototypes that need type definitions that have not been defined yet. The only way to ensure that these cycles do not occur is to have all C typedef occur before any prototype declarations.

Implementation Source File
The implementation source file contains the routine definitions that implement the data abstraction. Source files end with a plain `.c' suffix.
Test File
A test file is a C program that exercises a data abstraction to ensure that it works reasonably. Test files end with a suffix of `_test.c'.
In addition to the data abstraction files, I have:
Wrappers
It is a common practice to make header files be standalone so that they do not need any other header files to be pre-included for use. Unfortunately, the practice of stand-alone header files predates the Unix system header files. So for each Unix header file that I use, I have created a simple wrapper header file that ensures that it is a standalone header file. Wrapper header files have a prefix of `unix_'.
Miscellaneous
There a few miscellaneous files that do not fit any of the criteria above.

As with any effort, if I were going to do it again, I would do some things differently. However, my overall plan is to stop writing code in C entirely, and write all new code for my personal projects in my own personal programming language (STIPPLE). Thus, I have no intentions of fixing any of the architectual problems associated with this C utility library.

The data types provided by the C utility library are (in alphabetical order):

Attribute-value list
While it seemed like a good idea at the time I wrote it, I tend not to write code that uses attribute value lists. Hence, I've never really used this package.
Error Routines
I wrote up some generic error routines. I used these some of the time.
File I/O
When I was writing the first STIPPLE compiler in C I incorrectly decided that the standard Unix file I/O library would not correctly keep track of position, so I wrote my own file I/O package. This was a complete mistake.
Hash Table
I have found hash tables to be incredibly useful in all of the code that I write. There are two kinds -- ones that implement a set abstraction and ones that implement a key-value pair abstraction. This one implements the set abstraction.
Heap Allocator
Back in 1990 when I first started writing this library I had grandious plans that I would be very careful to arrange that memory to preserve locality of reference. This heap package was the mechanism by which I was going to achieve this locality. Well, it was a very bad idea. There are no real tools to help figure out memory locality issues. Furthermore, by making memory allocation an explicit argument, it cluttered up all of the interfaces that used it. What's worse is that this bad idea managed to make it into STIPPLE where I'm going to have to tediously rip it out. Sigh.
Integer Routines
There are a few routines for working with integers that I use all the time, so they are in the utility library.
Lint
I am a strong believer of strongly typed languages. The type rules implemented by lint are significantly stickier than standard ANSI-C. So I tend to run my code through lint to see what problems it uncovers. In order to get lint to not complain about some standard routines in libc, I declare them in a separate "C" file and compile it into a .ln file with line. My goal is to have lint emit no warnings and no errors.
Strings
I find the number of string routines in libc to be quite inadequate. So I've had to define a number of my own.
Strings (Dynamic)
For a while I thought I was going to use dynamic strings for everything, but eventually decided it was a real hassle not being able to easily print out the contents of a string in the debugger. This abstraction is used here and there in some of the older code, but is not used in the newer code.
Table (Key-Value)
I find key-value hash tables to be extremely useful.
Vector (Dynamic Array)
The vector data type is probably the most commonly used type from this package.
Write Buffer
Write buffers are used to implement the dynamic strings and file I/O. Since I don't think either of those types were very successful, I do not think this data types is very successful either.

The source and header files are available.


Copyright (c) 1995-1998 Wayne C. Gramlich All rights reserved.