#ifndef dbg_h #define dbg_h #include #include #include #ifdef NDEBUG #define debug(M, ...) #define DEBUG_LOC_FMT #define DEBUG_LOC_VALS #define DEBUG_LEVEL(X) #else #define debug(M, ...) fprintf(stderr, "[DEBUG] %s:%d %s: " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) #define DEBUG_LOC_FMT "%s:%d %s: " #define DEBUG_LOC_VALS , __FILE__, __LINE__, __func__ #define DEBUG_LEVEL(X) X #endif #define clean_errno() (errno == 0 ? "" : ": "), (errno == 0 ? "" : strerror(errno)) #define log_err(M, ...) fprintf(stderr, DEBUG_LEVEL("[ERROR] ") DEBUG_LOC_FMT M "%s%s\n" DEBUG_LOC_VALS, ##__VA_ARGS__, clean_errno()) #define log_warn(M, ...) fprintf(stderr, DEBUG_LEVEL("[WARN] ") DEBUG_LOC_FMT M "%s%s\n" DEBUG_LOC_VALS, ##__VA_ARGS__, clean_errno()) #define log_info(M, ...) fprintf(stderr, DEBUG_LEVEL("[INFO] ") DEBUG_LOC_FMT M "\n" DEBUG_LOC_VALS, ##__VA_ARGS__) #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define check_mem(A) check((A), "out of memory") #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } #define zero(func, ...) ({ typeof(func(__VA_ARGS__)) rv = func(__VA_ARGS__); check(rv == 0, #func " failed"); rv; }) #define chk(func, ...) ({ typeof(func(__VA_ARGS__)) rv = func(__VA_ARGS__); check(rv != 0, #func " failed"); rv; }) #define nneg(func, ...) ({ typeof(func(__VA_ARGS__)) rv = func(__VA_ARGS__); check(rv >= 0, #func " failed"); rv; }) #define Malloc(size) chk(malloc, size) #define Realloc(ptr, size) chk(realloc, ptr, size) #define Free(ptr) free(ptr), ptr = NULL // #define Fopen(path, mode) chk(fopen, path, mode) #define Fopen(path, mode) ({ char *p = path; FILE *rv = fopen(p, mode); check(rv, "fopen failed: %s", p); rv; }) #define Fclose(fp) zero(fclose, fp), fp = NULL #endif