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
 
 #ifndef REPORT_STREAM_INFO
 #define REPORT_STREAM_INFO  stderr
 #endif
 #ifndef REPORT_STREAM_ERROR
 #define REPORT_STREAM_ERROR stderr
 #endif
00a2dd39
 #ifndef REPORT_STREAM_FATAL
 #define REPORT_STREAM_FATAL stderr
 #endif
c8078bd5
 
00a2dd39
 #ifndef REPORT_PREFIX_INFO
 #define REPORT_PREFIX_INFO  "Info: "
c8078bd5
 #endif
00a2dd39
 #ifndef REPORT_PREFIX_ERROR
 #define REPORT_PREFIX_ERROR "Error: "
c8078bd5
 #endif
00a2dd39
 #ifndef REPORT_PREFIX_FATAL
 #define REPORT_PREFIX_FATAL "Fatal: "
c8078bd5
 #endif
 
00a2dd39
 #define report_info( ...) report(REPORT_STREAM_INFO,  REPORT_PREFIX_INFO,  0, __VA_ARGS__)
 #define report_error(...) report(REPORT_STREAM_ERROR, REPORT_PREFIX_ERROR, 0, __VA_ARGS__)
 #define report_fatal(...) report(REPORT_STREAM_FATAL, REPORT_PREFIX_FATAL, 1, __VA_ARGS__)
 
c8078bd5
 
00a2dd39
 static int report(
     FILE * stream,
     char const * prefix,
     int fatal,
     int report_errno,
     char const * format,
     ...
 ) {
     fprintf(stream, "%s", prefix);
c8078bd5
     {
         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");
00a2dd39
     if (fatal)
c8078bd5
         exit(EXIT_FAILURE);
00a2dd39
     return EXIT_FAILURE;
c8078bd5
 }