Over the past couple of weeks I have been working on a general purpose logging library for C in my free time. At the moment I have stabilized the API and most of the features I wanted to implement have been implemented. I am looking for general suggestions (note I haven't done much API documentation yet) on code quality and correctness (especially the synchronization techniques, IO methods, and message building functions).You can find the full repository here.And below I have included the sample usage that appears in the repo:#include <stdio.h>#include <stdlib.h>#include scribe.hint main(void){    if (SCRB_Success != scrb_init()) {        return EXIT_FAILURE;    }    // We open a new file called `example.log` in write mode without synchronization that only    // listens to info level log messages.    struct scrb_stream * const logstream = scrb_open_stream(example.log, w, false, LVL_INFO);    // We define a log format to tell scribe how to format our messages.    // This format prints out the file, method, and line locations followed by the message itself.    struct scrb_format const * const fmt = scrb_create_format([%F:%L:%M] %m, NULL);    // Now we're ready to go.    scrb_logln(logstream, fmt, LVL_INFO, Hello from the example program!);    // We can do formatted output as well.    scrb_flogln(logstream, fmt, LVL_INFO, Hello for the %dnd time!, 2);    // If we want to write directly to the file without formatting or location/time info    // (or paying attention to log levels) we can use the `scrb_putstrln` method to write directly to the file.    scrb_putstrln(logstream, Now we're done.);    scrb_format_release(&fmt);    scrb_close_stream(&logstream);    return EXIT_SUCCESS;}I have written a synchronized version similar to the above wherein 4 separate threads all log to the same file, which you may find the the examples folder.Here is the scribe.h header file (as per request):#ifndef SCRIBE_H#define SCRIBE_H#ifdef __cplusplusextern C {#endif#include <stdarg.h>#include <stdbool.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include scribe_conf.h#include scribe_debug.h#include scribe_format.h#include scribe_io.h#include scribe_loglevel.h#include scribe_metainfo.h#include scribe_return_types.h#include scribe_stream.h#include scribe_utils.h#include spinlock.h#if defined(SCRIBE_WINDOWS)#include Windows.h#endif#define LVL_TO_DEBUG  (LVL_DEBUG)#define LVL_TO_TRACE  (LVL_DEBUG | LVL_TRACE)#define LVL_TO_INFO   (LVL_DEBUG | LVL_TRACE | LVL_INFO)#define LVL_TO_NOTICE (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE)#define LVL_TO_WARN   (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE | LVL_WARN)#define LVL_TO_ALERT  (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE | LVL_WARN | LVL_ALERT)#define LVL_TO_ERROR  (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE | LVL_WARN | LVL_ALERT | LVL_ERROR)#define LVL_TO_EMERG  (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE | LVL_WARN | LVL_ALERT | LVL_ERROR | LVL_EMERG)#define LVL_ALL       (LVL_DEBUG | LVL_TRACE | LVL_INFO | LVL_NOTICE | LVL_WARN | LVL_ALERT | LVL_ERROR | LVL_EMERG)staticstruct scrb_stream * const scrb_stdout = &stream_out_default;staticstruct scrb_stream * const scrb_stdin  = &stream_in_default;staticstruct scrb_stream * const scrb_stderr = &stream_err_default;#if SCRIBE_DEBUGstaticstruct scrb_stream const * const scrb_debug  = &scrb_dbg_default;#endif// `scrb_init`// doc...static inlineint scrb_init(void){#if defined(SCRIBE_WINDOWS)    static volatile LONG initialized = 0;    if (0 == InterlockedCompareExchange(&initialized, 1, 0)) {#else        static volatile int initialized = 0;    if (__sync_bool_compare_and_swap(&initialized, 0, 1)) {#endif        struct scrb_stream outstream = (struct scrb_stream) {            .name        = stdout,            .synchronize = true,            .severity    = LVL_ALL,             .stream = {                .mode       = NULL,                .filestream = stdout,            },            .rwlock = spinlock_init(SCRIBE_RWLOCK_DELAY)        };        struct scrb_stream instream = (struct scrb_stream) {            .name        = stdin,            .synchronize = true,            .severity    = LVL_ALL,            .stream = {                .mode       = NULL,                .filestream = stdin,            },            .rwlock = spinlock_init(SCRIBE_RWLOCK_DELAY)        };        struct scrb_stream errstream = (struct scrb_stream) {            .name        = stderr,            .synchronize = true,            .severity    = LVL_ALL,            .stream = {                .mode       = NULL,                .filestream = stderr,            },            .rwlock = spinlock_init(SCRIBE_RWLOCK_DELAY)         };#if SCRIBE_DEBUG        FILE * const dbg_filestream = fopen(scribedebug.log, a);        struct scrb_stream dbgstream = (struct scrb_stream) {            .name        = debug,            .synchronize = true,            .severity    = LVL_ALL,            .stream = {                .mode       = NULL,                .filestream = dbg_filestream,            },            .rwlock = spinlock_init(SCRIBE_RWLOCK_DELAY)        };        if (NULL == dbgstream.stream.filestream) {            return (SCRB_Failure);        }        scrb_init_defaults(&outstream, &instream, &errstream, &dbgstream);        fprintf(dbgstream.stream.filestream, ----- scribe init :: version (%s) :: compile date (%s %s) :: compiled as SCRB_LANGUAGE by SCRB_CC ver.  SCRB_CC_VER  :: pid (%d) -----\n,                SCRIBE_VERSION, __DATE__, __TIME__, (int) scrb_getpid());#else        scrb_init_defaults(&outstream, &instream, &errstream);#endif    }    return (SCRB_Success);}// `scrb_create_format`// doc...static inlinestruct scrb_format * scrb_create_format(char const * const fmtstr,                                         void (*timehook)(char ** buff,                                                          size_t * len,                                                          SCRIBE_TIME_T ts)){    return scrb_create_format__internal(fmtstr, timehook);}////static inlinevoid (scrb_format_release)(struct scrb_format ** fmtptr){    scrb_format_release__internal(fmtptr);}#define scrb_format_release(fmtptr) (scrb_format_release)((struct scrb_format **) (fmtptr))// `scrb_stream_name`// doc...static inlinechar const * scrb_stream_name(struct scrb_stream const * const st){    return scrb_stream_name__internal(st);}// `scrb_stream_severity`// doc...static inlineuint16_t scrb_stream_severity(struct scrb_stream const * const st){    return scrb_stream_severity__internal(st);}// `scribe_open_file`// doc...static inlinestruct scrb_stream * scrb_open_stream(char const * const path,                                       char const * const mode,                                       bool const synchronize,                                      uint16_t const severity){    return scrb_open_stream__internal(path, mode, synchronize, severity);}// `scribe_close`// doc...static inlinevoid (scrb_close_stream)(struct scrb_stream ** streamptr){    scrb_close_stream__internal(streamptr);}#define scrb_close_stream(streamptr) (scrb_close_stream)((struct scrb_stream **)(streamptr))// `scribe_flush_stream`// doc...static inlinevoid scrb_flush_stream(struct scrb_stream * const st){    scrb_flush_stream__internal(st);}// `scribe_write`// doc...static inlineint (scrb_log)(struct scrb_meta_info const mi,                struct scrb_stream * const st,                struct scrb_format const * const fmt,                uint16_t const severity,               char const * const msg){    if (severity & st->severity) {        return scrb_log__internal(mi, st, fmt, severity, msg, false);     } else {        return SCRB_Success;    }}#define scrb_log(st, fmt, sv, msg) (scrb_log)(get_meta_info((st)->name), (st), (fmt), (sv), (msg))// `scribe_writeln`// doc...static inlineint (scrb_logln)(struct scrb_meta_info const mi,                  struct scrb_stream * const st,                  struct scrb_format const * const fmt,                  uint16_t const severity,                 char const * const msg){    if (severity & st->severity) {        return scrb_log__internal(mi, st, fmt, severity, msg, true);     } else {        return SCRB_Success;    }}#define scrb_logln(st, fmt, sv, msg) (scrb_logln)(get_meta_info((st)->name), (st), (fmt), (sv), (msg))// `scribe_writestr`// doc...static inlineint scrb_putstr(struct scrb_stream * const st, char const * const msg){    return scrb_putstr__internal(st, msg, false);}// `scribe_writestrln`// doc...static inlineint scrb_putstrln(struct scrb_stream * const st, char const * const msg){    return scrb_putstr__internal(st, msg, true);}// `fscribe_write`// doc...static inlineint (scrb_flog)(struct scrb_meta_info const mi,                 struct scrb_stream * const st,                struct scrb_format const * const fmt,                 uint16_t const severity,                char const * const msgfmt, ...){    if (severity & st->severity) {        va_list ap;        va_start (ap, msgfmt);        int const rval = scrb_flog__internal(mi, st, fmt, severity, msgfmt, false, ap);        va_end (ap);        return rval;    } else {        return SCRB_Success;    }}#define scrb_flog(st, fmt, sv, msg, ...) (scrb_flog)(get_meta_info((st)->name), (st), (fmt), (sv), (msg), ##__VA_ARGS__)// `fscribe_writeln`// doc...static inlineint (scrb_flogln)(struct scrb_meta_info const mi,                   struct scrb_stream * const st,                  struct scrb_format const * const fmt,                   uint16_t const severity,                  char const * const msgfmt, ...){    if (severity & st->severity) {        va_list ap;        va_start (ap, msgfmt);        int const rval = scrb_flog__internal(mi, st, fmt, severity, msgfmt, true, ap);        va_end (ap);        return rval;    } else {        return SCRB_Success;    }}#define scrb_flogln(st, fmt, sv, msg, ...) (scrb_flogln)(get_meta_info((st)->name), (st), (fmt), (sv), (msg), ##__VA_ARGS__)#ifdef __cplusplus}#endif#endif
Logging library for C
c;library;logging