Anyone who's written any C knows that it lacks a serious form of error tracking and control. Nothing like C++'s exception handling system is available. This makes errors especially tedious to handle. Having look at quite a lot of source code in my time, I was quite pleased to stumble upon a very elegant solution to this problem. It's common practice to return numeric error codes from all functions in a specific API, for an example look at nearly every function in the APR public interface. State uses a system, first seen by me in the Subversion project, where a more complex error object is, potentially, returned from each public function. Such functions in State are easy to see, they all returned a pointer to an sul_error_t object. If no error occurs, then the function returns SUL_NO_ERROR, which is simply NULL. Things become more complicated when an error does occur. which is where the following macros and functions come in:
All errors are initially created with this function. Each error is given a descriptive message and its source line number and file are marked and recorded. In addition, if the error is the result of an APR error, the APR status code will be given and included in messages. All errors are created in their own Pools, this avoids strange problems with lifetimes and such, since errors will often be passed up a call stack, through pool and lifetime boundaries.
Any call to a function that returns errors should be wrapped by this macro. It will check the return of the function for an error, and if one is found, return it from the current function, passing the error up the call stack very much like an exception.
This macro is very similar to the SUL_ERR macro, except it creates and wraps the error returned with a new one that gives more information on the problem. This way, very general errors such as Premature end of file! can be futhured qualified with the operation that failed, so that the user can see that operation X failed because of Y happened and made Z fail. Otherwise, simple errors such as File Not Found are simply too broad to narrow the problem down, especially if multiple areas of the code base use that specific file.