report.h
c8078bd5
 // TODO: Document that `perror(3)` is standard but does not take a printf-style
 // format argument. The ones that do are nonstandard, `err(3)` (BSD), `error`
 // (GNU).
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <errno.h>
 
 
 #define REPORT_INFO  0
 #define REPORT_ERROR 1
 #define REPORT_FATAL 2
 
 #define report_info( ...) report(REPORT_INFO,  __VA_ARGS__)
 #define report_error(...) report(REPORT_ERROR, __VA_ARGS__)
 #define report_fatal(...) report(REPORT_FATAL, __VA_ARGS__)
 
 #ifndef REPORT_STREAM_INFO
 #define REPORT_STREAM_INFO  stderr
 #endif
 #ifndef REPORT_STREAM_ERROR
 #define REPORT_STREAM_ERROR stderr
 #endif
 
 #ifndef REPORT_FORMAT_PREFIX_INFO
 #define REPORT_FORMAT_PREFIX_INFO  "Info: "
 #endif
 #ifndef REPORT_FORMAT_PREFIX_ERROR
 #define REPORT_FORMAT_PREFIX_ERROR "Error: "
 #endif
 #ifndef REPORT_FORMAT_PREFIX_FATAL
 #define REPORT_FORMAT_PREFIX_FATAL "Fatal: "
 #endif
 
 
 static int report(int report, int report_errno, char const * format, ...) {
     FILE * stream = REPORT_STREAM_INFO;
     if (report >= REPORT_ERROR)
         stream = REPORT_STREAM_ERROR;
     fprintf(stream, "%s",
         report == REPORT_INFO  ? REPORT_FORMAT_PREFIX_INFO  :
         report == REPORT_ERROR ? REPORT_FORMAT_PREFIX_ERROR :
         report == REPORT_FATAL ? REPORT_FORMAT_PREFIX_FATAL :
         ""
     );
     {
         va_list ap;
         va_start(ap, format);
         vfprintf(stream, format, ap);
         va_end(ap);
     }
     if (report_errno)
         fprintf(stream, ": %s", strerror(report_errno));
     fprintf(stream, "\n");
     if (report >= REPORT_FATAL)
         exit(EXIT_FAILURE);
     return report;
 }