aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2017-11-05 19:40:14 +0100
committerMattias Andrée <maandree@kth.se>2017-11-05 19:40:14 +0100
commit8d337f303d908e6b99f6b9403c5033ff4aacd12b (patch)
tree96c65b07812a294f8fae3b70d619d91ec0903281
parentFirst commit (diff)
downloadlibsimple-8d337f303d908e6b99f6b9403c5033ff4aacd12b.tar.gz
libsimple-8d337f303d908e6b99f6b9403c5033ff4aacd12b.tar.bz2
libsimple-8d337f303d908e6b99f6b9403c5033ff4aacd12b.tar.xz
Add libsimple.c and libsimple.h
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r--libsimple.c462
-rw-r--r--libsimple.h576
2 files changed, 1038 insertions, 0 deletions
diff --git a/libsimple.c b/libsimple.c
new file mode 100644
index 0000000..9a58ba1
--- /dev/null
+++ b/libsimple.c
@@ -0,0 +1,462 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsimple.h"
+
+
+extern char *argv0;
+
+
+int libsimple_default_failure_exit = 1;
+
+
+void *
+libsimple_rawmemchr(const void *s_, int c)
+{
+ char *s = *(char **)(void *)&s_;
+ while ((int)*s++ != c);
+ return &s[-1];
+}
+
+
+void *
+libsimple_memrchr(const void *s_, int c, size_t n_)
+{
+ char *s = *(char **)(void *)&s_;
+ ssize_t n = n_;
+ while (n-- && (int)s[n] != c);
+ return n < 0 ? NULL : &s[n];
+}
+
+
+void *
+libsimple_rawmemrchr(const void *s_, int c, size_t n)
+{
+ char *s = *(char **)(void *)&s_;
+ while ((int)s[--n] != c);
+ return &s[n];
+}
+
+
+char *
+libsimple_strchrnul(const char *s_, int c)
+{
+ char *s = *(char **)(void *)&s_;
+ for (; *s && (int)*s != c; s++)
+ return s;
+}
+
+
+void *
+libsimple_memdup(const void *s, size_t n)
+{
+ void *ret = malloc(n);
+ if (!ret)
+ return NULL;
+ return memcpy(ret, s, n);
+}
+
+
+char *
+libsimple_strndup(const char *s, size_t n)
+{
+ void *ret;
+ if (n == SIZE_MAX) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (!(ret = malloc(n + 1)))
+ return NULL;
+ memcpy(ret, s, n);
+ ((char *)ret)[n] = '\0';
+ return ret;
+}
+
+
+int
+libsimple_isutf8(const char *string, int allow_modified_nul)
+{
+ static long BYTES_TO_MIN_BITS[] = {0, 0, 8, 12, 17, 22, 37};
+ static long BYTES_TO_MAX_BITS[] = {0, 7, 11, 16, 21, 26, 31};
+ long int bytes = 0, read_bytes = 0, bits = 0, c, character;
+
+ /* min bits max bits
+ 0....... 0 7
+ 110..... 10...... 8 11
+ 1110.... 10...... 10...... 12 16
+ 11110... 10...... 10...... 10...... 17 21
+ 111110.. 10...... 10...... 10...... 10...... 22 26
+ 1111110. 10...... 10...... 10...... 10...... 10...... 27 31
+ */
+
+ while ((c = (long int)(*string++))) {
+ if (!read_bytes) {
+ /* First byte of the character. */
+
+ if (!(c & 0x80))
+ /* Single-byte character. */
+ continue;
+
+ if ((c & 0xC0) == 0x80)
+ /* Single-byte character marked as multibyte, or
+ a non-first byte in a multibyte character. */
+ return -1;
+
+ /* Multibyte character. */
+ while ((c & 0x80))
+ bytes++, c <<= 1;
+ read_bytes = 1;
+ character = c & 0x7F;
+ if (bytes > 6)
+ /* 31-bit characters can be encoded with 6-bytes,
+ and UTF-8 does not cover higher code points. */
+ return -1;
+ } else {
+ /* Not first byte of the character. */
+
+ if ((c & 0xC0) != 0x80)
+ /* Beginning of new character before a
+ multibyte character has ended. */
+ return -1;
+
+ character = (character << 6) | (c & 0x7F);
+
+ if (++read_bytes < bytes)
+ /* Not at last byte yet. */
+ continue;
+
+ /* Check that the character is not unnecessarily long. */
+ while (character)
+ character >>= 1, bits++;
+ bits = (!bits && bytes == 2 && allow_modified_nul) ? 8 : bits;
+ if (bits < BYTES_TO_MIN_BITS[bytes] || BYTES_TO_MAX_BITS[bytes] < bits)
+ return -1;
+
+ read_bytes = bytes = bits = 0;
+ }
+ }
+
+ /* Make sure we did not stop at the middle of a multibyte character. */
+ return !read_bytes;
+}
+
+
+int
+libsimple_asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+ va_start(ap, fmt);
+ r = libsimple_vasprintf(strp, fmt, ap);
+ va_end(ap);
+ return r;
+}
+
+
+int
+libsimple_vasprintf(char **strp, const char *fmt, va_list ap)
+{
+ FILE *fp;
+ size_t siz = 0;
+ int ret;
+ *strp = NULL;
+ fp = open_memstream(strp, &siz);
+ if (!fp)
+ goto fail;
+ ret = vfprintf(fp, fmt, ap);
+ if (ret < 0)
+ goto fail;
+ if (fputc(0, fp))
+ goto fail;
+ fclose(fp);
+ return ret;
+fail:
+ free(*strp);
+ *strp = NULL;
+ return -1;
+}
+
+
+void *
+libsimple_memmem(const void *hay_, size_t hayn, const void *sub_, size_t subn)
+{
+ char *hay = *(char **)(void *)&hay_, *end;
+ const char *sub = sub_;
+
+ if (!subn)
+ return hay;
+ if (hayn < subn)
+ return NULL;
+ if (subn == 1)
+ return memchr(hay, *sub, hayn);
+
+ for (end = &hay[hayn - subn + 1]; hay != end; hay++)
+ if (*hay == *sub && !memcmp(hay, sub, subn))
+ return hay;
+
+ return NULL;
+}
+
+
+char *
+libsimple_strcasestr(const char *h_, const char *n)
+{
+ char *h = *(char **)(void *)&h_;
+ size_t hn = strlen(h);
+ size_t nn = strlen(n);
+ if (hn < nn)
+ return NULL;
+ for (hn -= nn; hn--; h++)
+ if (!strcasecmp(h, n))
+ return h;
+ return NULL;
+}
+
+
+int
+libsimple_memstarts(const void *s_, size_t n, const void *t_, size_t m)
+{
+ const char *s = s_, *t = t_;
+ size_t i = 0;
+ if (n < m)
+ return 0;
+ while (i < m && s[i] == t[i]) i++;
+ return i == m;
+}
+
+
+int
+libsimple_memends(const void *s_, size_t n, const void *t_, size_t m)
+{
+ const char *s = s_, *t = t_;
+ if (n < m)
+ return 0;
+ while (n--, m--)
+ if (s[n] != t[m])
+ return 0;
+ return 1;
+}
+
+
+int
+libsimple_strstarts(const char *s, const char *t)
+{
+ for (; *t && *s == *t; s++, t++);
+ return !*t;
+}
+
+
+int
+libsimple_strends(const char *s, const char *t)
+{
+ return memends(s, strlen(s), t, strlen(t));
+}
+
+
+static inline size_t
+alloc_size_product(size_t n, va_list ap)
+{
+ size_t prod = n;
+ if (!n) {
+ errno = EINVAL;
+ return 0;
+ }
+ for (;;) {
+ n = va_arg(ap, size_t);
+ if (!n)
+ break;
+ if (n >= SIZE_MAX / prod) {
+ errno = ENOMEM;
+ return 0;
+ }
+ prod *= n;
+ }
+ return prod;
+}
+
+void *
+libsimple_vmalloczn(int clear, size_t n, va_list ap)
+{
+ n = alloc_size_product(n, ap);
+ return !n ? NULL : clear ? calloc(1, n) : malloc(n);
+}
+
+void *
+libsimple_vreallocn(void *ptr, size_t n, va_list ap)
+{
+ n = alloc_size_product(n, ap);
+ return !n ? NULL : realloc(ptr, n);
+}
+
+
+void *
+enmalloc(int status, size_t n)
+{
+ void *ret = malloc(n);
+ if (!ret) {
+ fprintf(stderr, "%s: malloc: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+void *
+encalloc(int status, size_t n, size_t m)
+{
+ void *ret = calloc(n, m);
+ if (!ret) {
+ fprintf(stderr, "%s: calloc: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+void *
+enrealloc(int status, void *ptr, size_t n)
+{
+ char *ret = realloc(ptr, n);
+ if (!ret) {
+ fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+char *
+enstrdup(int status, const char *s)
+{
+ char *ret = strdup(s);
+ if (!ret) {
+ fprintf(stderr, "%s: strdup: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+char *
+enstrndup(int status, const char *s, size_t n)
+{
+ void *ret = strndup(s, n);
+ if (!ret) {
+ fprintf(stderr, "%s: strndup: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+void *
+enmemdup(int status, const void *s, size_t n)
+{
+ void *ret = memdup(s, n);
+ if (!ret) {
+ fprintf(stderr, "%s: memdup: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+void *
+libsimple_envmalloczn(int status, int clear, size_t n, va_list ap)
+{
+ void *ret = libsimple_vmalloczn(clear, n, ap);
+ if (!ret) {
+ fprintf(stderr, "%s: %s: %s\n", argv0, clear ? "calloc" : "malloc", strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+void *
+libsimple_envreallocn(int status, void *ptr, size_t n, va_list ap)
+{
+ void *ret = libsimple_vreallocn(ptr, n, ap);
+ if (!ret) {
+ fprintf(stderr, "%s: realloc: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+ return ret;
+}
+
+
+int
+vputenvf(const char *fmt, va_list ap)
+{
+ va_list ap2;
+ int n;
+ char *s;
+ va_copy(ap2, ap);
+ n = vsnprintf(NULL, 0, fmt, ap2);
+ va_end(ap2);
+ if (n < 0)
+ return -1;
+ if ((size_t)n == SIZE_MAX) {
+ errno = ENOMEM;
+ return -1;
+ }
+ s = alloca((size_t)n + 1);
+ vsprintf(s, fmt, ap);
+ return putenv(s);
+}
+
+
+void
+envputenvf(int status, const char *fmt, va_list ap)
+{
+ if (vputenvf(fmt, ap)) {
+ fprintf(stderr, "%s: putenvf: %s\n", argv0, strerror(errno));
+ exit(status);
+ }
+}
+
+
+void
+vweprintf(const char *fmt, va_list ap)
+{
+ int saved_errno = errno, r;
+ const char *end = strchr(fmt, '\0');
+ const char *prefix1 = argv0;
+ const char *prefix2 = ": ";
+ const char *suffix1 = "";
+ const char *suffix2 = "";
+ const char *suffix3 = "";
+ char *message = NULL;
+ va_list ap1;
+ va_list ap2;
+
+ if (!argv0 || !strncmp(fmt, "usage: ", strlen("usage: ")))
+ prefix1 = prefix2 = "";
+
+ va_copy(ap1, ap);
+ va_copy(ap2, ap);
+ r = vsnprintf(NULL, 0, fmt, ap1);
+ if (0 <= r && (size_t)r < SIZE_MAX) {
+ message = alloca((size_t)r + 1);
+ vsprintf(message, fmt, ap2);
+ }
+ va_end(ap2);
+ va_end(ap1);
+
+ if (*end == ':') {
+ suffix1 = " ";
+ suffix2 = strerror(saved_errno);
+ suffix3 = "\n";
+ } else if (*end != '\n') {
+ suffix1 = "\n";
+ }
+
+ if (message) {
+ /* This is to avoid mangling when multiple processes are writting. */
+ fprintf(stderr, "%s%s%s%s%s%s", prefix1, prefix2, message, suffix1, suffix2, suffix3);
+ } else {
+ fprintf(stderr, "%s%s", prefix1, prefix2);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "%s%s%s", suffix1, suffix2, suffix3);
+ }
+
+ errno = saved_errno;
+}
diff --git a/libsimple.h b/libsimple.h
new file mode 100644
index 0000000..02fc912
--- /dev/null
+++ b/libsimple.h
@@ -0,0 +1,576 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSIMPLE_H
+#define LIBSIMPLE_H
+
+
+#include <alloca.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define _LIBSIMPLE_GCC_ONLY(x) x
+#else
+# define _LIBSIMPLE_GCC_ONLY(x)
+#endif
+
+
+extern int libsimple_default_failure_exit;
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+void *libsimple_rawmemchr(const void *, int);
+#ifndef rawmemchr
+# define rawmemchr libsimple_rawmemchr
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+void *libsimple_memrchr(const void *, int, size_t);
+#ifndef memrchr
+# define memrchr libsimple_memrchr
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+void *libsimple_rawmemrchr(const void *, int, size_t);
+#ifndef rawmemrchr
+# define rawmemrchr libsimple_rawmemrchr
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+char *libsimple_strchrnul(const char *, int);
+#ifndef strchrnul
+# define strchrnul libsimple_strchrnul
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+static inline char *libsimple_strend(const char *__s) { return strchr(__s, '\0'); }
+#ifndef strend
+# define strend libsimple_strend
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+static inline int libsimple_inchrset(int __c, const char *__s) { return __c && strchr(__s, __c); }
+#ifndef inchrset
+# define inchrset libsimple_inchrset
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result)))
+void *libsimple_memdup(const void *, size_t);
+#ifndef memdup
+# define memdup libsimple_memdup
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result)))
+char *libsimple_strndup(const char *, size_t);
+#ifndef strndup
+# define strndup libsimple_strndup
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *libsimple_mempcpy(void *__d, const void *__s, size_t __n)
+{ return &((char *)memcpy(__d, __s, __n))[__n]; }
+#ifndef mempcpy
+# define mempcpy libsimple_mempcpy
+#endif
+
+
+#ifndef strdupa
+# if defined(__GNUC__) || defined(__clang__)
+# define strdupa(s)\
+ ({\
+ const char *__s = (s);\
+ size_t __n = strlen(__s) + 1;\
+ char *__r = alloca(__n);\
+ memcpy(__r, __s, __n);\
+ })
+# endif
+#endif
+
+
+#ifndef strdupa
+# if defined(__GNUC__) || defined(__clang__)
+# define strndupa(s, n)\
+ ({\
+ const char *__s = (s);\
+ size_t __n = (n);\
+ size_t __m = strlen(__s);\
+ char *__r;\
+ __n = __n < __m ? __n : __m;\
+ __r = alloca(__n + 1);\
+ memcpy(__r, __s, __n);\
+ __r[n] = '\0';\
+ __r;\
+ })
+# endif
+#endif
+
+
+#ifndef strdupa
+# if defined(__GNUC__) || defined(__clang__)
+# define memdupa(s, n)\
+ ({\
+ const char *__s = (s);\
+ size_t __n = (n);\
+ char *__r = alloca(__n);\
+ memcpy(__r, __s, __n);\
+ })
+# endif
+#endif
+
+
+/**
+ * Check whether a NUL-terminated string is encoded in UTF-8
+ *
+ * @param string The string
+ * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL
+ * @return 1 if good, 0 on encoding error
+ */
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+int libsimple_isutf8(const char *, int);
+#ifndef isutf8
+# define isutf8 libsimple_isutf8
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2), format(printf, 2, 3))))
+int libsimple_asprintf(char **, const char *, ...);
+#ifndef asprintf
+# define asprintf libsimple_asprintf
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2))))
+int libsimple_vasprintf(char **, const char *, va_list);
+#ifndef vasprintf
+# define vasprintf libsimple_vasprintf
+#endif
+
+
+#ifndef asprintfa
+# if defined(__GNUC__) && !defined(__clang__)
+# define asprintfa(__fmt, ...)\
+ ({\
+ const char *__f = (__fmt);\
+ char *__ret = NULL;\
+ int __r = snprintf(NULL, 0, __f, __VA_ARGS__);\
+ if (__r < 0) {\
+ __ret;\
+ } else if ((size_t)__r == SIZE_MAX) {\
+ errno = ENOMEM;\
+ __ret;\
+ } else {\
+ __ret = alloca((size_t)__r + 1);\
+ sprintf(__ret, __f, __VA_ARGS__);\
+ __ret;\
+ }\
+ })
+# endif
+#endif
+
+
+#ifndef vasprintfa
+# if defined(__GNUC__) || defined(__clang__)
+# define vasprintfa(__fmt, __ap)\
+ ({\
+ const char *__f = (__fmt);\
+ va_list __a = (__ap);\
+ va_list __a2;\
+ char *__ret = NULL;\
+ int __r;\
+ va_copy(__a2, __a);\
+ __r = vsnprintf(NULL, 0, __f, __a);\
+ if (__r < 0);\
+ else if ((size_t)__r == SIZE_MAX) {\
+ errno = ENOMEM;\
+ } else {\
+ __ret = alloca((size_t)__r + 1);\
+ vsprintf(__ret, __f, __a2);\
+ }\
+ va_end(__a2);\
+ __ret;\
+ })
+# endif
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result)))
+void *libsimple_memmem(const void *, size_t, const void *, size_t);
+#ifndef memmem
+# define memmem libsimple_memmem
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result)))
+int libsimple_memstarts(const void *, size_t, const void *, size_t);
+#ifndef memstarts
+# define memstarts libsimple_memstarts
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result)))
+int libsimple_memends(const void *, size_t, const void *, size_t);
+#ifndef memends
+# define memends libsimple_memends
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+int libsimple_strstarts(const char *, const char *);
+#ifndef strstarts
+# define strstarts libsimple_strstarts
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+int libsimple_strends(const char *, const char *);
+#ifndef strends
+# define strends libsimple_strends
+#endif
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result)))
+char *libsimple_strcasestr(const char *, const char *);
+#ifndef strcasestr
+# define strcasestr libsimple_strcasestr
+#endif
+
+
+#define malloczn(CLEAR, ...) _libsimple_malloczn((CLEAR), __VA_ARGS__, (size_t)0)
+#define mallocn(...) malloczn(0, __VA_ARGS__)
+#define callocn(...) malloczn(1, __VA_ARGS__)
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+void *libsimple_vmalloczn(int, size_t, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *libsimple_vmallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(0, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *libsimple_vcallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(1, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *
+libsimple_malloczn(int __clear, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_vmalloczn(__clear, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *
+libsimple_mallocn(size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_vmalloczn(0, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *
+libsimple_callocn(size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_vmalloczn(1, __n, __ap);
+ va_end(__ap);
+}
+
+
+#define reallocn(PTR, ...) _libsimple_reallocn((PTR), __VA_ARGS__, (size_t)0)
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+void *libsimple_vreallocn(void *, size_t, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result)))
+static inline void *
+libsimple_reallocn(void *__ptr, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_vreallocn(__ptr, __n, __ap);
+ va_end(__ap);
+}
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *enmalloc(int, size_t);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *encalloc(int, size_t, size_t);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *enrealloc(int, void *, size_t);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull)))
+char *enstrdup(int, const char *);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull)))
+char *enstrndup(int, const char *, size_t);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *enmemdup(int, const void *, size_t);
+
+#define enmalloczn(STATUS, CLEAR, ...) _libsimple_enmalloczn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0)
+#define enmallocn(STATUS, ...) _libsimple_enmallocn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0)
+#define encallocn(STATUS, ...) _libsimple_encallocn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0)
+#define enreallocn(STATUS, PTR, ...) _libsimple_enreallocn((STATUS), (PTR), __VA_ARGS__, (size_t)0)
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *libsimple_envmalloczn(int, int, size_t, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+void *libsimple_envreallocn(int, void *, size_t, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_envmallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 0, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_envcallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 1, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_enmalloczn(int __status, int __clear, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(__status, __clear, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_enmallocn(int __status, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(__status, 0, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_encallocn(int __status, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(__status, 1, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_enreallocn(int __status, void *__ptr, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envreallocn(__status, __ptr, __n, __ap);
+ va_end(__ap);
+}
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *emalloc(size_t __n) { return enmalloc(libsimple_default_failure_exit, __n); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *ecalloc(size_t __n, size_t __m) { return encalloc(libsimple_default_failure_exit, __n, __m); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *erealloc(void *__ptr, size_t __n) { return enrealloc(libsimple_default_failure_exit, __ptr, __n); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull)))
+static inline char *estrdup(const char *__s) { return enstrdup(libsimple_default_failure_exit, __s); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull)))
+static inline char *estrndup(const char *__s, size_t __n) { return enstrndup(libsimple_default_failure_exit, __s, __n); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *ememdup(const void *__s, size_t __n) { return enmemdup(libsimple_default_failure_exit, __s, __n); }
+
+#define emalloczn(CLEAR, ...) enmalloczn(libsimple_default_failure_exit, (CLEAR), __VA_ARGS__)
+#define emallocn(...) enmallocn(libsimple_default_failure_exit, __VA_ARGS__)
+#define ecallocn(...) encallocn(libsimple_default_failure_exit, __VA_ARGS__)
+#define ereallocn(PTR, ...) enreallocn(libsimple_default_failure_exit, (PTR), __VA_ARGS__)
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_evmalloczn(int __clear, size_t __n, va_list __ap)
+{ return libsimple_envmalloczn(libsimple_default_failure_exit, __clear, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_evmallocn(size_t __n, va_list __ap)
+{ return libsimple_envcallocn(libsimple_default_failure_exit, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_evcallocn(size_t __n, va_list __ap)
+{ return libsimple_envmallocn(libsimple_default_failure_exit, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *libsimple_evreallocn(void *__ptr, size_t __n, va_list __ap)
+{ return libsimple_envreallocn(libsimple_default_failure_exit, __ptr, __n, __ap); }
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_emalloczn(int __c, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(libsimple_default_failure_exit, __c, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_emallocn(size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(libsimple_default_failure_exit, 0, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_ecallocn(size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envmalloczn(libsimple_default_failure_exit, 1, __n, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull)))
+static inline void *
+libsimple_ereallocn(void *__p, size_t __n, ...)
+{
+ va_list __ap;
+ va_start(__ap, __n);
+ return libsimple_envreallocn(libsimple_default_failure_exit, __p, __n, __ap);
+ va_end(__ap);
+}
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull)))
+static inline char *
+getenv_ne(const char *__name)
+{
+ char *__env = getenv(__name);
+ return (__env && *__env) ? __env : NULL;
+}
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull)))
+int vputenvf(const char *, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull)))
+void envputenvf(int, const char *, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2))))
+static inline int
+putenvf(const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ return vputenvf(__fmt, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2))))
+static inline void
+eputenvf(const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ envputenvf(1, __fmt, __ap);
+ va_end(__ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull)))
+static inline void
+evputenvf(const char *__fmt, va_list __ap)
+{
+ envputenvf(libsimple_default_failure_exit, __fmt, __ap);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 2, 3))))
+static inline void
+enputenvf(int __status, const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ envputenvf(__status, __fmt, __ap);
+ va_end(__ap);
+}
+
+
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1))))
+void vweprintf(const char *, va_list);
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2), noreturn)))
+static inline void
+eprintf(const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ vweprintf(__fmt, __ap);
+ va_end(__ap);
+ exit(libsimple_default_failure_exit);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), noreturn)))
+static inline void
+veprintf(const char *__fmt, va_list __ap)
+{
+ vweprintf(__fmt, __ap);
+ exit(libsimple_default_failure_exit);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), format(printf, 2, 3), noreturn)))
+static inline void
+enprintf(int __status, const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ vweprintf(__fmt, __ap);
+ va_end(__ap);
+ exit(__status);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), noreturn)))
+static inline void
+venprintf(int __status, const char *__fmt, va_list __ap)
+{
+ vweprintf(__fmt, __ap);
+ exit(__status);
+}
+
+_LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2))))
+static inline void
+weprintf(const char *__fmt, ...)
+{
+ va_list __ap;
+ va_start(__ap, __fmt);
+ vweprintf(__fmt, __ap);
+ va_end(__ap);
+}
+
+
+#endif