#include "dg.h" #include "mem.h" #include #include #include void tobi_diag_init(tobi_diag_list *dl) { dl->items = NULL; dl->len = 0; dl->cap = 0; } void tobi_diag_free(tobi_diag_list *dl) { for (size_t i = 0; i < dl->len; i++) { free(dl->items[i].msg); } free(dl->items); dl->items = NULL; dl->len = 0; dl->cap = 0; } void tobi_diag_add(tobi_diag_list *dl, tobi_diag_level level, size_t off, const char *fmt, ...) { if (dl->len == dl->cap) { dl->cap = dl->cap ? dl->cap * 2 : 8; dl->items = tobi_xrealloc(dl->items, dl->cap * sizeof(dl->items[0])); } va_list ap; va_start(ap, fmt); va_list cp; va_copy(cp, ap); int n = vsnprintf(NULL, 0, fmt, cp); va_end(cp); if (n < 0) { va_end(ap); n = 0; } char *msg = tobi_xmalloc((size_t)n + 1); (void)vsnprintf(msg, (size_t)n + 1, fmt, ap); va_end(ap); dl->items[dl->len].level = level; dl->items[dl->len].off = off; dl->items[dl->len].msg = msg; dl->len++; } int tobi_diag_has_error(const tobi_diag_list *dl) { for (size_t i = 0; i < dl->len; i++) { if (dl->items[i].level == TOBI_DIAG_ERROR) { return 1; } } return 0; } const char *tobi_diag_level_name(tobi_diag_level level) { return level == TOBI_DIAG_ERROR ? "error" : "warning"; }