Thanks! I'll stick to this convention when I propose changes in the code.
Indeed I would find it convenient to do this in one function call so that it is easy to catch unforeseen cases (in one line instead of four), like in
else ERROR("this cannot happen: foo=%d", foo)
but I would find it counterintuitive to call log_msg(0, 5, ...) in such a case. I would propose something like this C99 code:
#define ERROR(...) err_exit(__LINE__, __FILE__, __VA_ARGS__)
void err_exit(const int line, const char *file, const char *fmt, ...)
{
va_list argp;
fprintf(stderr, "\nERROR: ");
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, "\n Line %d of %s,", line, file);
fprintf(stderr, "\n errno = %d (%s)\n\n ==> ", errno, strerror(errno));
fflush(stdout);
fflush(stderr);
abort(); // get a core dump to facilitate debugging
}
The line and file are helpful to find out where in the code a particular error message is coming from, and makes it less problematic if you have lots of identical error messages.