aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/cerr.c73
-rw-r--r--src/common/cerr.h19
2 files changed, 92 insertions, 0 deletions
diff --git a/src/common/cerr.c b/src/common/cerr.c
new file mode 100644
index 0000000..0032795
--- /dev/null
+++ b/src/common/cerr.c
@@ -0,0 +1,73 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "cerr.h"
+
+#define SGR_BOLD "\33[1m"
+#define SGR_DONE "\33[0m"
+
+static bool color;
+static const char *progname;
+
+void
+cerrinit(const char *s)
+{
+ const char *p = strrchr(s, '/');
+ progname = p ? p + 1 : s;
+
+ if (isatty(STDOUT_FILENO)) {
+ const char *ev = getenv("NO_COLOR");
+ if (!ev || !*ev)
+ color = true;
+ }
+}
+
+void
+die(const char *fmt, ...)
+{
+ va_list ap;
+ int e = errno;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s%s:%s ", color ? SGR_BOLD : "", progname,
+ color ? SGR_DONE : "");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ": %s\n", strerror(e));
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
+
+void
+diex(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s%s:%s ", color ? SGR_BOLD : "", progname,
+ color ? SGR_DONE : "");
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
+
+void
+die_with_off(const char *file, size_t off, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s%s:%s:%zu:%s ", color ? SGR_BOLD : "", progname, file,
+ off, color ? SGR_DONE : "");
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
diff --git a/src/common/cerr.h b/src/common/cerr.h
new file mode 100644
index 0000000..de58b1d
--- /dev/null
+++ b/src/common/cerr.h
@@ -0,0 +1,19 @@
+#ifndef AHOY_COMMON_CERR_H
+#define AHOY_COMMON_CERR_H
+
+#include <stddef.h>
+
+/* clang-format off */
+
+[[gnu::nonnull]] void cerrinit(const char *);
+
+[[noreturn, gnu::nonnull, gnu::format(printf, 1, 2)]]
+void die(const char *, ...);
+
+[[noreturn, gnu::nonnull, gnu::format(printf, 1, 2)]]
+void diex(const char *, ...);
+
+[[noreturn, gnu::nonnull, gnu::format(printf, 3, 4)]]
+void die_with_off(const char *, size_t, const char *, ...);
+
+#endif /* !AHOY_COMMON_CERR_H */