#include #include #include #include #include #include #include #include "eprintf.h" static char *pname; static int debug = 0; // doprintf: print error message __attribute__((format(printf, 1, 0))) static void doprintf(const char *fmt, va_list va, int errnum) { assert(fmt != NULL); if (pname != NULL) fprintf(stderr, "%s: ", pname); vfprintf(stderr, fmt, va); if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') fprintf(stderr, " %s", strerror(errnum)); fputc('\n', stderr); } // eprintf: print error and exit, a trailing : in fmt prints strerror(errno) void eprintf(const char *fmt, ...) { va_list va; va_start(va, fmt); doprintf(fmt, va, errno); // TODO: can va_start set errno va_end(va); exit(EXIT_FAILURE); } // weprintf: print warning, a trailing : in fmt prints strerror(errno) void weprintf(const char *fmt, ...) { va_list va; va_start(va, fmt); doprintf(fmt, va, errno); // TODO: Ditto va_end(va); } // deprintf: print debug message if debugging is enabled void deprintf(const char *fmt, ...) { va_list va; assert(fmt != NULL); if (!debug) return; if (pname != NULL) fprintf(stderr, "%s: ", pname); fputs("debug: ", stderr); va_start(va, fmt); vfprintf(stderr, fmt, va); va_end(va); } // estrdup: attempt to strdup a string or exit on error char *estrdup(const char *s) { size_t len; char *dup; assert(s != NULL); len = strlen(s); if (len == SIZE_MAX) eprintf("estrdup(\"%.20s\") failed: Too long", s); dup = malloc(len + 1); if (dup == NULL) eprintf("estrdup(\"%.20s\") failed:", s); strcpy(dup, s); return dup; } // emalloc: attempt to allocate memory or exit on error void *emalloc(size_t n) { void *p; p = malloc(n); if (p == NULL) eprintf("emalloc(%zu) failed:", n); return p; } // ecalloc: attempt to allocate memory or exit on error void *ecalloc(size_t nmemb, size_t size) { void *p; p = calloc(nmemb, size); if (p == NULL) eprintf("ecalloc(%zu, %zu) failed:", nmemb, size); return p; } // erealloc: attempt to reallocate memory or exit on error void *erealloc(void *p, size_t n) { void *r; r = realloc(p, n); if (r == NULL) eprintf("erealloc(%p, %zu) failed:", p, n); return r; } // setprogname: set stored name of program void setprogname(const char *s) { assert(s != NULL); if (pname != NULL) { weprintf("setprogname(\"%.20s\") called more than once", s); return; } pname = estrdup(s); } // setdebug: set debug void setdebug(int d) { debug = d; }