summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-03-01 11:44:02 +0000
committerTomasz Kramkowski <tk@the-tk.com>2018-03-01 11:44:02 +0000
commit7a802c4ff4c715f50825d833fa44f2ad1a5993f4 (patch)
treefe4d734653f6367b516e19f2bf7c8f29870b94b9
downloadeprintf-7a802c4ff4c715f50825d833fa44f2ad1a5993f4.tar.gz
eprintf-7a802c4ff4c715f50825d833fa44f2ad1a5993f4.tar.xz
eprintf-7a802c4ff4c715f50825d833fa44f2ad1a5993f4.zip
init commit
-rw-r--r--eprintf.c117
-rw-r--r--eprintf.h16
-rw-r--r--module.mk3
3 files changed, 136 insertions, 0 deletions
diff --git a/eprintf.c b/eprintf.c
new file mode 100644
index 0000000..9f4aa11
--- /dev/null
+++ b/eprintf.c
@@ -0,0 +1,117 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eprintf.h"
+
+static char *pname;
+
+// doprintf: print error message
+__attribute__((format(printf, 1, 0)))
+static void doprintf(const char *fmt, va_list va, int errnum)
+{
+ assert(fmt != NULL);
+
+ if (pname != NULL)
+ fprintf(stderr, "%s: ", pname);
+
+ vfprintf(stderr, fmt, va);
+
+ if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':')
+ fprintf(stderr, " %s", strerror(errnum));
+ fputc('\n', stderr);
+}
+
+// eprintf: print error and exit, a trailing : in fmt prints strerror(errno)
+void eprintf(const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ doprintf(fmt, va, errno); // TODO: can va_start set errno
+ va_end(va);
+
+ exit(EXIT_FAILURE);
+}
+
+// weprintf: print warning, a trailing : in fmt prints strerror(errno)
+void weprintf(const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ doprintf(fmt, va, errno); // TODO: Ditto
+ va_end(va);
+}
+
+// estrdup: attempt to strdup a string or exit on error
+char *estrdup(const char *s)
+{
+ size_t len;
+ char *dup;
+
+ assert(s != NULL);
+
+ len = strlen(s);
+ if (len == SIZE_MAX)
+ eprintf("estrdup(\"%.20s\") failed: Too long", s);
+ dup = malloc(len + 1);
+ if (dup == NULL)
+ eprintf("estrdup(\"%.20s\") failed:", s);
+ strcpy(dup, s);
+
+ return dup;
+}
+
+// emalloc: attempt to allocate memory or exit on error
+void *emalloc(size_t n)
+{
+ void *p;
+
+ p = malloc(n);
+ if (p == NULL)
+ eprintf("emalloc(%zu) failed:", n);
+
+ return p;
+}
+
+// ecalloc: attempt to allocate memory or exit on error
+void *ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ p = calloc(nmemb, size);
+ if (p == NULL)
+ eprintf("ecalloc(%zu, %zu) failed:", nmemb, size);
+
+ return p;
+}
+
+// erealloc: attempt to reallocate memory or exit on error
+void *erealloc(void *p, size_t n)
+{
+ void *r;
+
+ r = realloc(p, n);
+ if (r == NULL)
+ eprintf("erealloc(%p, %zu) failed:", p, n);
+
+ return r;
+}
+
+// setprogname: set stored name of program
+void setprogname(const char *s)
+{
+ assert(s != NULL);
+
+ if (pname != NULL) {
+ weprintf("setprogname(\"%.20s\") called more than once", s);
+ return;
+ }
+
+ pname = estrdup(s);
+}
diff --git a/eprintf.h b/eprintf.h
new file mode 100644
index 0000000..0bd662b
--- /dev/null
+++ b/eprintf.h
@@ -0,0 +1,16 @@
+#ifndef EPRINTF_EPRINTF_H
+#define EPRINTF_EPRINTF_H
+#include <stdnoreturn.h>
+#include <stddef.h>
+
+noreturn void eprintf(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+void weprintf(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
+char *estrdup(const char *str);
+void *emalloc(size_t size);
+void *ecalloc(size_t nmemb, size_t size);
+void *erealloc(void *p, size_t size);
+void setprogname(const char *name);
+
+#endif // !EPRINTF_EPRINTF_H
diff --git a/module.mk b/module.mk
new file mode 100644
index 0000000..c27afee
--- /dev/null
+++ b/module.mk
@@ -0,0 +1,3 @@
+EPRINTF_FILES = eprintf.c eprintf.h
+$(EPRINTF_FILES): %: $(EPRINTF_PATH)/%
+ $(LN) $< $@