#ifndef LOGGER_H #define LOGGER_H /* LOGGER RETURN CODE */ #define LOGGER_RC_TYPE unsigned char extern __thread LOGGER_RC_TYPE logger_errno; #define LOGGER_RC_OK ((LOGGER_RC_TYPE) 0L) /* No Error */ #define LOGGER_RC_EFM ((LOGGER_RC_TYPE) 1L) /* Failed to malloc */ #define LOGGER_RC_EVN ((LOGGER_RC_TYPE) 2L) /* Value is Null */ #if defined(LOGGER_TYPEDEF) || defined(TYPEDEFS) typedef struct str str_st; #endif /* LOGGER_TYPEDEF || TYPEDEFS */ enum logger_level { LL_TRACE, LL_DEBUG, LL_INFO, LL_WARN, LL_ERROR, LL_FATAL }; typedef void (*_print_like)(const char *, ...); struct logger { _print_like trace; _print_like debug; _print_like info; _print_like warn; _print_like error; _print_like fatal; }; struct logger* logger_create(enum logger_level lvl); LOGGER_RC_TYPE logger_destroy(struct logger *logger); #if defined(LOGGER_IMP) || defined(IMPLEMENTATIONS) #include #include #include #if defined(LOGGER_LOG) || defined(LOGS) #define __LOG(OUT, PFX, TXT) fprintf(OUT, PFX" %s: %s", __func__, TXT) #define LOG_ERROR(TXT) __LOG(stderr, "[ERROR]", TXT) #else #define LOG_ERROR(TXT) ; #endif /* LOGGER_LOG */ #define TEST_FOR_NULL(POINTER) \ if ( POINTER == NULL ) { \ LOG_ERROR("Null Pointer Not Expected"); \ logger_errno = LOGGER_RC_EVN; \ return logger_errno; \ } #define CHECK_MALLOC(POINTER, STR_RC) \ if ( POINTER == NULL ) { \ LOG_ERROR("Failed to malloc"); \ logger_errno = LOGGER_RC_EFM; \ return STR_RC; \ } static void nop(const char *format, ...) {(void) format;} __attribute__((format(printf, 1, 2))) static void trace(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stdout, "[TRACE] "); vfprintf(stdout, format, vargs); } __attribute__((format(printf, 1, 2))) static void debug(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stdout, "[DEBUG] "); vfprintf(stdout, format, vargs); } __attribute__((format(printf, 1, 2))) static void info(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stdout, "[INFO] "); vfprintf(stdout, format, vargs); } __attribute__((format(printf, 1, 2))) static void warn(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stdout, "[WARN] "); vfprintf(stdout, format, vargs); } __attribute__((format(printf, 1, 2))) static void error(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stderr, "[ERROR] "); vfprintf(stderr, format, vargs); } __attribute__((format(printf, 1, 2))) static void fatal(const char *format, ...) { va_list vargs; va_start(vargs, format); fprintf(stderr, "[FATAL] "); vfprintf(stderr, format, vargs); } struct logger* logger_create(enum logger_level lvl) { logger_errno = LOGGER_RC_OK; struct logger *ret = malloc(sizeof(struct logger)); CHECK_MALLOC(ret, NULL) ret->trace = *nop; ret->debug = *nop; ret->info = *nop; ret->warn = *nop; ret->error = *nop; ret->fatal = *nop; switch (lvl) { case LL_TRACE: ret->trace = *trace; /* fall through */ case LL_DEBUG: ret->debug = *debug; /* fall through */ case LL_INFO: ret->info = *info; /* fall through */ case LL_WARN: ret->warn = *warn; /* fall through */ case LL_ERROR: ret->error = *error; /* fall through */ case LL_FATAL: ret->fatal = *fatal; } return ret; } LOGGER_RC_TYPE logger_destroy(struct logger *logger) { logger_errno = LOGGER_RC_OK; TEST_FOR_NULL(logger); free(logger); return LOGGER_RC_OK; } #undef LOG_ERROR #undef TEST_FOR_NULL #undef CHECK_MALLOC #endif /* LOGGER_IMP || IMPLEMENTATIONS */ #endif /* LOGGER_H */