/roar

A basic eRrOr hAndling libRary (ROAR)

Primary LanguageCGNU Lesser General Public License v3.0LGPL-3.0

ROAR

( eRrOr hAndling libRary )

Description

ROAR is a C99 single header library implementing a basic error handler. It provides:

  1. formated error logging to a stream, e.g. stderr or to a char array.
  2. Pre and post error processing with user defined callbacks.

The format of error messages is brief, though it provides the key information required for debugging, e.g. with gdb. An example of most lengthy error message is as follow:

error { main, examples/example.c:20 } : Invalid argument { "nofile.nop" }

The first part is the header. The brackets contain information on where the error was raised. Following the colon is the body of the error. It contains a brief summary of the reason that triggered the error. In this case it is an errno error report that was generated by the ROAR library using strerror. Finally, the faulty parameter is displayed in the second brackets.

Integration

The ROAR library can be directly integrated into a project by copying the roar.h file. In order to build the implementation one of the project's file can define the ROAR_IMPLEMENTATION macro before including roar.h, e.g. as:

#define ROAR_IMPLEMENTATION
#include "roar.h"

Note that the implementation must be defined once and only once. Alternatively you can also compile roar.h directly defining the ROAR_IMPLEMENTATION macro at the compiler.

Build parameters

The following macros allow to control some of the build parameters. In order to be activated they must be defined before including roar.h.

  • ROAR_API : controls the scope of the API functions. It defaults to extern. Note that if you overwrite this setting it must be consistent every time that you include the roar.h file.

  • ROAR_STRING_SIZE : controls the maximum length that will be written to the output char array, including a 0x0 terminating character. This macro needs to be defined only once at implementation.

  • ROAR_FORMAT_HEADER, ROAR_FORMAT_BRA and ROAR_FORMAT_CKET : those are printf like formats used for formating the error summary. They need to be defined only once at implementation.

API documentation

A rather complete example of usage can be found here. In the following is a more systematic description.

The roar_handler structure

This is the base object used for configuring the error handling. It has the following fields :

struct roar_handler {
        /* An output stream where to log errors, or NULL. */
        FILE * stream;
        /* A buffer string where to write errors, or NULL. */
        char * string;
        /* A callback for pre processing of errors, or NULL. */
        roar_callback_t * pre;
        /* A callback for post processing of errors, or NULL. */
        roar_callback_t * post;
};

This structure is passed to the error pre and post processing callbacks. It can be extended if needed, as long as it can be casted back to a struct roar_handler.

Raising an error

Signaling an error is done with the ROAR_ERROR, ROAR_ERRWP and ROAR_ERRNO macros. These three macro types differ only by the content of the error's body text that will be logged.

  1. The ROAR_ERROR macros log are the less verbose. They log a single body message. Their signatures are as following :

    /* Raise an error with a formated body message from variable arguments. */
    ROAR_API void ROAR_ERROR_FORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * format, ...);
    
    /* Raise an error with a formated body message from a variadic list. */
    ROAR_API void ROAR_ERROR_VFORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * format, args);
    
    /* Raise an error with a static body message. */
    ROAR_API void ROAR_ERROR_MESSAGE(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * message);
  2. The ROAR_ERRWP macros log a static body message With a Parameter (WP). They come in three flavours as previously depending on the formating of the parameter. Their signatures are as following :

    /* Raise an error message with a formated body parameter from
     * variable arguments.
     */
    ROAR_API ROAR_ERRWP_FORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * message,
        const char * format, ...);
    
    /* Raise an error message with a formated body parameter from a
     * variadic list.
     */
    ROAR_API ROAR_ERRWP_FORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * message,
        const char * format, args);
    
    /* Raise an error message with a static body parameter. */
    ROAR_API ROAR_ERRWP_FORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * message,
        const char * parameter);
  3. Finally the ROAR_ERRNO macros dump a body message corresponding to the given errno value, or to the current one if code is set to 0. the body message is generated with strerror. The signatures of these macros is as following :

    /* Raise an error with an errno body message, i.e. as returned by strerror. */
    ROAR_API void ROAR_ERRNO(struct roar_handler * handler,
        roar_function_t * referent, int code);
    
    /* Raise an error with an errno body message and a formated body parameter
     * from variable arguments.
     */
    ROAR_API void ROAR_ERRNO_FORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * format, ...);
    
    /* Raise an error with an errno body message and a formated body parameter
     * from a variadic list.
     */
    ROAR_API void ROAR_ERRNO_VFORMAT(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * format, ...);
    
    /* Raise an error with an errno body message and a static body parameter. */
    ROAR_API void ROAR_ERRNO_MESSAGE(struct roar_handler * handler,
        roar_function_t * referent, int code, const char * parameter);

Note that in any case the format strings must conform to the printf semantic.

Handling errors

Errors are handled by two user defined callbacks. A pre-processing callback that is triggered before the error is logged and a post-processing one. The signature of these callbacks is :

/* Callback function called when an error is triggered. */
typedef int roar_callback_t(
    struct roar_handler * handler, roar_function_t * referent, int code);

where referent is an indication about the caller function, as passed over at raise. Note that at pre-processing if EXIT_SUCCESS is returned the error will be ignored.

License

The ROAR library is under the GNU LGPLv3 license. See the provided LICENSE and COPYING.LESSER files.