diff options
50 files changed, 3929 insertions, 1479 deletions
@@ -3,20 +3,59 @@ CONFIGFILE = config.mk include $(CONFIGFILE) +SUBHDR =\ + libsimple/definitions.h\ + libsimple/memalloc.h\ + libsimple/strdup.h\ + libsimple/strndup.h\ + libsimple/memdup.h\ + libsimple/aligned_memdup.h\ + libsimple/mallocz.h\ + libsimple/malloc.h\ + libsimple/calloc.h\ + libsimple/realloc.h\ + libsimple/memalignz.h\ + libsimple/memalign.h\ + libsimple/vallocz.h\ + libsimple/valloc.h\ + libsimple/pvallocz.h\ + libsimple/pvalloc.h\ + libsimple/aligned_allocz.h\ + libsimple/aligned_alloc.h\ + libsimple/posix_memalignz.h\ + libsimple/posix_memalign.h\ + libsimple/env.h\ + libsimple/time.h\ + libsimple/printf.h\ + libsimple/str.h\ + libsimple/strn.h\ + libsimple/mem.h + +HDR =\ + $(SUBHDR)\ + libsimple.h + OBJ =\ + aligned_memdup.o\ allocn.o\ asprintf.o\ difftimespec.o\ difftimeval.o\ doubletotimespec.o\ doubletotimeval.o\ + enaligned_memdup.o\ + enaligned_allocz.o\ + enposix_memalignz.o\ encalloc.o\ enmalloc.o\ enmemdup.o\ enrealloc.o\ enstrdup.o\ enstrndup.o\ + envaligned_alloczn.o\ envmalloczn.o\ + envmemalloc.o\ + envposix_memalignzn.o\ envputenvf.o\ envreallocn.o\ isutf8.o\ @@ -52,6 +91,7 @@ OBJ =\ timespectostr.o\ timevaltostr.o\ vasprintf.o\ + vmemalloc.o\ vputenvf.o\ vweprintf.o\ libsimple.o @@ -59,10 +99,10 @@ OBJ =\ TESTS = $(OBJ:.o=.test) all: libsimple.a $(TESTS) -$(OBJ): $(@:.o=.c) libsimple.h +$(OBJ): $(@:.o=.c) $(HDR) $(TESTS): $(@:=.o) test.o libsimple.a -$(TESTS:=.o): $(@:.test.o=.c) libsimple.h test.h -test.o: test.c libsimple.h test.h +$(TESTS:=.o): $(@:.test.o=.c) $(HDR) test.h +test.o: test.c $(HDR) test.h libsimple.a: $(OBJ) $(AR) rc $@ $? @@ -72,22 +112,24 @@ libsimple.a: $(OBJ) $(CC) -o $@ $< test.o libsimple.a $(LDFLAGS) .c.test.o: - $(CC) -c -o $@ $< $(CFLAGS) -DTEST + $(CC) -c -o $@ $< $(CFLAGS) -DTEST -O0 check: $(TESTS) @set -e; for t in $(TESTS); do printf '%s\n' "./$$t"; $(CHECK_PREFIX) "./$$t"; done install: libsimple.a mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" - mkdir -p -- "$(DESTDIR)$(PREFIX)/include" + mkdir -p -- "$(DESTDIR)$(PREFIX)/include/libsimple" cp -- libsimple.a "$(DESTDIR)$(PREFIX)/lib" cp -- libsimple.h "$(DESTDIR)$(PREFIX)/include" cp -- libsimple-arg.h "$(DESTDIR)$(PREFIX)/include" + cp -- $(SUBHDR) "$(DESTDIR)$(PREFIX)/include/libsimple" uninstall: -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libsimple.a" -rm -f -- "$(DESTDIR)$(PREFIX)/include/libsimple.h" -rm -f -- "$(DESTDIR)$(PREFIX)/include/libsimple-arg.h" + -rm -rf -- "$(DESTDIR)$(PREFIX)/include/libsimple" clean: -rm -rf -- *.o *.su *.a *.so *.so.* *.gch *.gcda *.gcno *.gcov *.lo *.test @@ -5,7 +5,8 @@ values for integer data types. All functions are namespaced with `libsimple_` and aliased with macro definitions to unnamespaced names unless there already is a macro with that -name. +name. However, the `libsimple_{,e,en}{,v}{mem,array}alloc` functions do +not have unnamespaced aliases as they are libsimple specific. Programs using this library should define `char *argv0` and set it to the 0:th command line argument. diff --git a/aligned_enmemdup.c b/aligned_enmemdup.c new file mode 100644 index 0000000..fced863 --- /dev/null +++ b/aligned_enmemdup.c @@ -0,0 +1,64 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_enaligned_memdup(int status, const void *s, size_t alignment, size_t n) +{ + void *ret = aligned_memdup(s, aligned, n); + if (!ret) + enprintf(status, "aligned_memdup:"); + return ret; +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *s; + + assert((s = libsimple_enaligned_memdup(1, "hello", 3, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 3); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 5)); + free(s); + + assert((s = libsimple_ealigned_memdup("test", 7, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 14); + assert(info->alignment == 7); + assert(!info->zeroed); + } + assert(!memcmp(s, "test", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_memdup(44, "hello", 3, 2)); + assert(exit_status == 44); + assert_stderr("%s: memdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_memdup("test", 7, 2)); + assert(exit_status == 55); + assert_stderr("%s: memdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + + return 0; +} + +#endif diff --git a/aligned_memdup.c b/aligned_memdup.c new file mode 100644 index 0000000..2dbba7b --- /dev/null +++ b/aligned_memdup.c @@ -0,0 +1,40 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_aligned_memdup(const void *s, size_t alignment, size_t n) +{ + void *ret = aligned_alloc(alignment, n + (alignment - n % alignment) % alignment); + if (!ret) + return NULL; + return memcpy(ret, s, n); +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + const char *s = "test"; + void *p = libsimple_aligned_memdup(s, 4, 5); + assert(p); + assert(p != s); + assert(!((uintptr_t)s % 4)); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->size == 8); + assert(info->alignment == 4); + } + assert(!strcmpnul(p, s)); + memset(p, 0, 5); + assert(!strcmpnul(s, "test")); + free(p); + return 0; +} + +#endif @@ -4,11 +4,11 @@ static inline size_t -alloc_size_product(size_t n, va_list ap) +alloc_size_product(int *errp, size_t n, va_list ap) { size_t prod = n; if (!n) { - errno = EINVAL; + *errp = EINVAL; return 0; } for (;;) { @@ -16,7 +16,7 @@ alloc_size_product(size_t n, va_list ap) if (!n) break; if (n >= SIZE_MAX / prod) { - errno = ENOMEM; + *errp = ENOMEM; return 0; } prod *= n; @@ -27,17 +27,41 @@ alloc_size_product(size_t n, va_list ap) void * libsimple_vmalloczn(int clear, size_t n, va_list ap) { - n = alloc_size_product(n, ap); + n = alloc_size_product(&errno, 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); + n = alloc_size_product(&errno, n, ap); return !n ? NULL : realloc(ptr, n); } +void * +libsimple_valigned_alloczn(int clear, size_t alignment, size_t n, va_list ap) +{ + void *ret; + n = alloc_size_product(&errno, n, ap); + ret = !n ? NULL : aligned_alloc(alignment, n); + if (ret && clear) + memset(ret, 0, n); + return ret; +} + +int +libsimple_vposix_memalignzn(void **memptr, int clear, size_t alignment, size_t n, va_list ap) +{ + int ret = 0; + n = alloc_size_product(&ret, n, ap); + if (ret) + return ret; + ret = posix_memalign(memptr, alignment, n); + if (!ret && clear) + memset(*memptr, 0, n); + return ret; +} + #else #include "test.h" @@ -58,6 +82,15 @@ main(void) errno = 0; assert(!libsimple_reallocn(NULL, 0) && errno == EINVAL); errno = 0; + assert(!libsimple_aligned_alloczn(0, 128, 0) && errno == EINVAL); + errno = 0; + assert(!libsimple_aligned_alloczn(1, 128, 0) && errno == EINVAL); + errno = 0; + assert(!libsimple_aligned_allocn(128, 0) && errno == EINVAL); + errno = 0; + assert(libsimple_posix_memalignzn(&ptr, 0, 128, 0) == EINVAL && !errno); + assert(libsimple_posix_memalignzn(&ptr, 1, 128, 0) == EINVAL && !errno); + assert(libsimple_posix_memalignn(&ptr, 128, 0) == EINVAL && !errno); assert(!libsimple_malloczn(0, SIZE_MAX, 2, 0) && errno == ENOMEM); errno = 0; @@ -69,12 +102,22 @@ main(void) errno = 0; assert(!libsimple_reallocn(NULL, SIZE_MAX, 2, 0) && errno == ENOMEM); errno = 0; + assert(!libsimple_aligned_alloczn(0, 1024, SIZE_MAX, 2, 0) && errno == ENOMEM); + errno = 0; + assert(!libsimple_aligned_alloczn(1, 1024, SIZE_MAX, 2, 0) && errno == ENOMEM); + errno = 0; + assert(!libsimple_aligned_allocn(1024, SIZE_MAX, 2, 0) && errno == ENOMEM); + errno = 0; + assert(libsimple_posix_memalignzn(&ptr, 0, 1024, SIZE_MAX, 2, 0) == ENOMEM && !errno); + assert(libsimple_posix_memalignzn(&ptr, 1, 1024, SIZE_MAX, 2, 0) == ENOMEM && !errno); + assert(libsimple_posix_memalignn(&ptr, 1024, SIZE_MAX, 2, 0) == ENOMEM && !errno); assert((ptr = libsimple_malloczn(0, 10, 10, 0))); if (have_custom_malloc()) { assert((info = get_allocinfo(ptr))); assert(info->size == 100); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -83,6 +126,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 400); assert(info->zeroed == 400); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -91,6 +135,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 121); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -99,6 +144,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 484); assert(info->zeroed == 484); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -108,6 +154,7 @@ main(void) assert(info->size == 5); assert(!info->zeroed); info->refcount += 1; + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } stpcpy(ptr, "test"); assert((ptr = libsimple_reallocn(old = ptr, 10, 0))); @@ -116,11 +163,72 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 10); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); assert(ptr != old); free(old); } free(ptr); + assert((ptr = libsimple_aligned_alloczn(0, 8, 12, 12, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 144); + assert(info->alignment == 8); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_aligned_alloczn(1, 16, 12, 12, 2, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 288); + assert(info->alignment == 16); + assert(info->zeroed == 288); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_aligned_allocn(32, 12, 12, 4, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 576); + assert(info->alignment == 32); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert(!libsimple_posix_memalignzn(&ptr, 0, sizeof(void *), 12, 12, 0)); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 144); + assert(info->alignment == sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert(!libsimple_posix_memalignzn(&ptr, 1, 2 * sizeof(void *), 12, 12, 2, 0)); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 288); + assert(info->alignment == 2 * sizeof(void *)); + assert(info->zeroed == 288); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert(!libsimple_posix_memalignn(&ptr, 2 * sizeof(void *), 12, 12, 3, 0)); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 432); + assert(info->alignment == 2 *sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + assert(!errno); return 0; @@ -2,5 +2,5 @@ PREFIX = /usr MANPREFIX = $(PREFIX)/share/man CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -CFLAGS = -std=c99 -Wall -Wextra -O2 $(CPPFLAGS) +CFLAGS = -std=c11 -Wall -Wextra -O2 $(CPPFLAGS) LDFLAGS = -s diff --git a/enaligned_allocz.c b/enaligned_allocz.c new file mode 100644 index 0000000..f92df4f --- /dev/null +++ b/enaligned_allocz.c @@ -0,0 +1,132 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_enaligned_allocz(int status, int clear, size_t alignment, size_t n) +{ + void *ret = libsimple_aligned_allocz(clear, alignment, n); + if (!ret) + enprintf(status, "aligned_alloc:"); + return ret; +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *ptr; + + assert((ptr = libsimple_enaligned_allocz(1, 1, 8, 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 8); + assert(info->zeroed == 8); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_ealigned_allocz(1, 4, 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 4); + assert(info->zeroed == 8); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_enaligned_allocz(1, 0, 4, 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 4); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_ealigned_allocz(0, 2, 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 4); + assert(info->alignment == 2); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_enaligned_alloc(1, 4, 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 4); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_ealigned_alloc(2, 4))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 4); + assert(info->alignment == 2); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_allocz(3, 1, 2, 4)); + assert(exit_status == 3); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 102; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_allocz(1, 1, 4)); + assert(exit_status == 102); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_allocz(5, 0, 2, 4)); + assert(exit_status == 5); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 103; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_allocz(0, 1, 4)); + assert(exit_status == 103); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_alloc(7, 2, 4)); + assert(exit_status == 7); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_alloc(1, 4)); + assert(exit_status == 104); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + + return 0; +} + +#endif diff --git a/enaligned_memdup.c b/enaligned_memdup.c new file mode 100644 index 0000000..ac94746 --- /dev/null +++ b/enaligned_memdup.c @@ -0,0 +1,64 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_enaligned_memdup(int status, const void *s, size_t alignment, size_t n) +{ + void *ret = aligned_memdup(s, alignment, n); + if (!ret) + enprintf(status, "aligned_memdup:"); + return ret; +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *s; + + assert((s = libsimple_enaligned_memdup(1, "hello", 2, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 6); + assert(info->alignment == 2); + assert(!info->zeroed); + } + assert(!memcmp(s, "hello", 5)); + free(s); + + assert((s = libsimple_ealigned_memdup("test", 8, 5))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(s))); + assert(info->size == 8); + assert(info->alignment == 8); + assert(!info->zeroed); + } + assert(!memcmp(s, "test", 5)); + free(s); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_memdup(44, "hello", 2, 2)); + assert(exit_status == 44); + assert_stderr("%s: aligned_memdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 55; + alloc_fail_in = 1; + assert_exit_ptr(libsimple_ealigned_memdup("test", 8, 2)); + assert(exit_status == 55); + assert_stderr("%s: aligned_memdup: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + + return 0; +} + +#endif @@ -27,6 +27,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 10); assert(info->zeroed == 10); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -35,6 +36,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 12); assert(info->zeroed == 12); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -27,6 +27,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 5); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -35,6 +36,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 4); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); diff --git a/enposix_memalignz.c b/enposix_memalignz.c new file mode 100644 index 0000000..64ae4f0 --- /dev/null +++ b/enposix_memalignz.c @@ -0,0 +1,145 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void +libsimple_enposix_memalignz(int status, void **memptr, int clear, size_t alignment, size_t n) +{ + int err = libsimple_posix_memalignz(memptr, clear, alignment, n); + if (err) { + errno = err; + enprintf(status, "posix_memalign:"); + } +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *ptr = NULL; + + libsimple_enposix_memalignz(1, &ptr, 1, sizeof(void *), 8); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == sizeof(void *)); + assert(info->zeroed == 8); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_eposix_memalignz(&ptr, 1, 2 * sizeof(void *), 8); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 2 * sizeof(void *)); + assert(info->zeroed == 8); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_enposix_memalignz(1, &ptr, 0, 2 * sizeof(void *), 8); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 2 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_eposix_memalignz(&ptr, 0, 4 * sizeof(void *), 4); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 4); + assert(info->alignment == 4 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_enposix_memalign(1, &ptr, sizeof(void *), 8); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_eposix_memalign(&ptr, 8 * sizeof(void *), 4); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 4); + assert(info->alignment == 8 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalignz(3, &ptr, 1, sizeof(void *), 4)); + assert(exit_status == 3); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 102; + alloc_fail_in = 1; + assert_exit(libsimple_eposix_memalignz(&ptr, 1, sizeof(void *), 4)); + assert(exit_status == 102); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalignz(5, &ptr, 0, sizeof(void *), 4)); + assert(exit_status == 5); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 103; + alloc_fail_in = 1; + assert_exit(libsimple_eposix_memalignz(&ptr, 0, sizeof(void *), 4)); + assert(exit_status == 103); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalign(7, &ptr, sizeof(void *), 4)); + assert(exit_status == 7); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + libsimple_default_failure_exit = 104; + alloc_fail_in = 1; + assert_exit(libsimple_eposix_memalign(&ptr, sizeof(void *), 4)); + assert(exit_status == 104); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + libsimple_default_failure_exit = 1; + } + + return 0; +} + +#endif diff --git a/enrealloc.c b/enrealloc.c index 59033e7..878674c 100644 --- a/enrealloc.c +++ b/enrealloc.c @@ -27,6 +27,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 5); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); info->refcount += 1; } stpcpy(ptr, "test"); @@ -36,6 +37,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 10); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); assert(ptr != old); free(old); } @@ -46,6 +48,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 5); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); info->refcount += 1; } stpcpy(ptr, "test"); @@ -55,6 +58,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 10); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); assert(ptr != old); free(old); } @@ -6,9 +6,11 @@ char * libsimple_enstrdup(int status, const char *s) { - char *ret = strdup(s); + size_t n = strlen(s) + 1; + char *ret = aligned_alloc(1, n); if (!ret) enprintf(status, "strdup:"); + memcpy(ret, s, n); return ret; } @@ -26,6 +28,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 6); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "hello")); @@ -35,6 +38,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 5); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "test")); diff --git a/enstrndup.c b/enstrndup.c index a6bc7b3..c02c0fd 100644 --- a/enstrndup.c +++ b/enstrndup.c @@ -26,6 +26,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 6); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "hello")); @@ -35,6 +36,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 5); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "test")); @@ -44,6 +46,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 3); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "he")); @@ -53,6 +56,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 4); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "tes")); @@ -62,6 +66,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 1); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "")); @@ -71,6 +76,7 @@ main(void) if (have_custom_malloc()) { assert((info = get_allocinfo(s))); assert(info->size == 1); + assert(info->alignment == 1); assert(!info->zeroed); } assert(!strcmp(s, "")); diff --git a/envaligned_alloczn.c b/envaligned_alloczn.c new file mode 100644 index 0000000..d79c6e7 --- /dev/null +++ b/envaligned_alloczn.c @@ -0,0 +1,159 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_envaligned_alloczn(int status, int clear, size_t alignment, size_t n, va_list ap) +{ + void *ret = libsimple_valigned_alloczn(clear, alignment, n, ap); + if (!ret) + enprintf(status, "aligned_alloc:"); + return ret; +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *ptr; + + assert((ptr = libsimple_enaligned_alloczn(1, 0, 8, 4, 4, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 16); + assert(info->alignment == 8); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_enaligned_alloczn(1, 1, 16, 32, 2, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 64); + assert(info->alignment == 16); + assert(info->zeroed == 64); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_enaligned_allocn(1, 32, 8, 16, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 128); + assert(info->alignment == 32); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_alloczn(3, 0, 32, 256, 0)); + assert(exit_status == 3); + stderr_buf[stderr_n] = 0; + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_alloczn(5, 1, 32, 128, 0)); + assert(exit_status == 5); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert_exit_ptr(libsimple_enaligned_allocn(9, 32, 64, 0)); + assert(exit_status == 9); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + } + + assert_exit_ptr(libsimple_enaligned_alloczn(13, 0, 8, SIZE_MAX, 2, 0)); + assert(exit_status == 13); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + assert_exit_ptr(libsimple_enaligned_alloczn(15, 1, 8, SIZE_MAX, 2, 0)); + assert(exit_status == 15); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + assert_exit_ptr(libsimple_enaligned_allocn(19, 8, SIZE_MAX, 2, 0)); + assert(exit_status == 19); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + assert((ptr = libsimple_ealigned_alloczn(0, 32, 2, 8, 8, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 128); + assert(info->alignment == 32); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_ealigned_alloczn(1, 8, 2, 4, 4, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 32); + assert(info->alignment == 8); + assert(info->zeroed == 32); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + assert((ptr = libsimple_ealigned_allocn(16, 2, 4, 8, 0))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 64); + assert(info->alignment == 16); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + + if (have_custom_malloc()) { + alloc_fail_in = 1; + libsimple_default_failure_exit = 23; + assert_exit_ptr(libsimple_ealigned_alloczn(0, 8, 16, 0)); + assert(exit_status == 23); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + libsimple_default_failure_exit = 25; + assert_exit_ptr(libsimple_ealigned_alloczn(1, 8, 32, 0)); + assert(exit_status == 25); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + libsimple_default_failure_exit = 29; + assert_exit_ptr(libsimple_ealigned_allocn(8, 64, 0)); + assert(exit_status == 29); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + } + + libsimple_default_failure_exit = 33; + assert_exit_ptr(libsimple_ealigned_alloczn(0, 8, SIZE_MAX, 2, 0)); + assert(exit_status == 33); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 35; + assert_exit_ptr(libsimple_ealigned_alloczn(1, 8, SIZE_MAX, 2, 0)); + assert(exit_status == 35); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 39; + assert_exit_ptr(libsimple_ealigned_allocn(8, SIZE_MAX, 2, 0)); + assert(exit_status == 39); + assert_stderr("%s: aligned_alloc: %s\n", argv0, strerror(ENOMEM)); + + return 0; +} + +#endif diff --git a/envmalloczn.c b/envmalloczn.c index 7531ecf..3e81b56 100644 --- a/envmalloczn.c +++ b/envmalloczn.c @@ -27,6 +27,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 15); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -35,6 +36,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 20); assert(info->zeroed == 20); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -43,6 +45,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 12); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -51,6 +54,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 16); assert(info->zeroed == 16); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -102,6 +106,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 30); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -110,6 +115,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 40); assert(info->zeroed == 40); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -118,6 +124,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 24); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); @@ -126,6 +133,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 32); assert(info->zeroed == 32); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); } free(ptr); diff --git a/envmemalloc.c b/envmemalloc.c new file mode 100644 index 0000000..c500063 --- /dev/null +++ b/envmemalloc.c @@ -0,0 +1,29 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void * +libsimple_envmemalloc(int status, size_t n, va_list ap) /* TODO test (e[n][v]{mem,array}alloc) */ +{ + void *ret; + int saved_errno = errno; + errno = 0; + ret = libsimple_vmemalloc(n, ap); + if (errno) + enprintf(status, "libsimple_vmemalloc:"); + errno = saved_errno; + return ret; +} + + +#else +#include "test.h" + +int +main(void) +{ + return 0; +} + +#endif diff --git a/envposix_memalignzn.c b/envposix_memalignzn.c new file mode 100644 index 0000000..62cc440 --- /dev/null +++ b/envposix_memalignzn.c @@ -0,0 +1,174 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +void +libsimple_envposix_memalignzn(int status, void **memptr, int clear, size_t alignment, size_t n, va_list ap) +{ + int err = libsimple_vposix_memalignzn(memptr, clear, alignment, n, ap); + if (err) { + errno = err; + enprintf(status, "posix_memalign:"); + } +} + + +#else +#include "test.h" + +int +main(void) +{ + struct allocinfo *info; + void *ptr = NULL; + + libsimple_enposix_memalignzn(1, &ptr, 0, sizeof(void *), 5, 3, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 15); + assert(info->alignment == sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_enposix_memalignzn(1, &ptr, 1, 2 * sizeof(void *), 5, 4, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 20); + assert(info->alignment == 2 * sizeof(void *)); + assert(info->zeroed == 20); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_enposix_memalignn(1, &ptr, 4 * sizeof(void *), 4, 3, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 12); + assert(info->alignment == 4 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + if (have_custom_malloc()) { + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalignzn(3, &ptr, 0, 4 * sizeof(void *), 4, 0)); + assert(exit_status == 3); + stderr_buf[stderr_n] = 0; + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalignzn(5, &ptr, 1, 4 * sizeof(void *), 2, 0)); + assert(exit_status == 5); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert_exit(libsimple_enposix_memalignn(9, &ptr, 4 * sizeof(void *), 1, 0)); + assert(exit_status == 9); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + } + + assert_exit(libsimple_enposix_memalignzn(13, &ptr, 0, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 13); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + assert_exit(libsimple_enposix_memalignzn(15, &ptr, 1, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 15); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + assert_exit(libsimple_enposix_memalignn(19, &ptr, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 19); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + ptr = NULL; + + libsimple_eposix_memalignzn(&ptr, 0, 4 * sizeof(void *), 2, 5, 3, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 30); + assert(info->alignment == 4 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_eposix_memalignzn(&ptr, 1, sizeof(void *), 2, 5, 4, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 40); + assert(info->alignment == sizeof(void *)); + assert(info->zeroed == 40); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + libsimple_eposix_memalignn(&ptr, 2 * sizeof(void *), 2, 4, 3, 0); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 24); + assert(info->alignment == 2 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); + } + free(ptr); + ptr = NULL; + + if (have_custom_malloc()) { + alloc_fail_in = 1; + libsimple_default_failure_exit = 23; + assert_exit(libsimple_eposix_memalignzn(&ptr, 0, sizeof(void *), 4, 0)); + assert(exit_status == 23); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + libsimple_default_failure_exit = 25; + assert_exit(libsimple_eposix_memalignzn(&ptr, 1, sizeof(void *), 2, 0)); + assert(exit_status == 25); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + libsimple_default_failure_exit = 29; + assert_exit(libsimple_eposix_memalignn(&ptr, sizeof(void *), 1, 0)); + assert(exit_status == 29); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + assert(!alloc_fail_in); + } + + libsimple_default_failure_exit = 33; + assert_exit(libsimple_eposix_memalignzn(&ptr, 0, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 33); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 35; + assert_exit(libsimple_eposix_memalignzn(&ptr, 1, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 35); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + libsimple_default_failure_exit = 39; + assert_exit(libsimple_eposix_memalignn(&ptr, sizeof(void *), SIZE_MAX, 2, 0)); + assert(exit_status == 39); + assert_stderr("%s: posix_memalign: %s\n", argv0, strerror(ENOMEM)); + + return 0; +} + +#endif diff --git a/envreallocn.c b/envreallocn.c index 571d077..03394a1 100644 --- a/envreallocn.c +++ b/envreallocn.c @@ -27,6 +27,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 15); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); info->refcount += 1; } stpcpy(ptr, "test"); @@ -36,6 +37,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 20); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); assert(ptr != old); free(old); } @@ -46,6 +48,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 20); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); info->refcount += 1; } stpcpy(ptr, "test"); @@ -55,6 +58,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 110); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)(info->alignment))); assert(ptr != old); free(old); } diff --git a/libsimple.c b/libsimple.c index 641748a..a874258 100644 --- a/libsimple.c +++ b/libsimple.c @@ -87,9 +87,6 @@ test_vasprintfa(const char *expected, const char *format, ...) } #endif -#ifdef __clang__ -__attribute__((optnone)) -#endif int main(void) { @@ -716,6 +713,19 @@ main(void) fprintf(stderr, "warning: libsimple_memdupa missing\n"); #endif +#ifdef libsimple_aligned_memdupa + cs = "xyz"; + for (n = 1; n < 4; n++) { + s = libsimple_aligned_memdupa(cs, 4 + i, n); + assert(s); + assert(s != cs); + assert(!((uintptr_t)s % (4 + i))); + assert(!memcmp(s, cs, n)); + } +#else + fprintf(stderr, "warning: libsimple_aligned_memdupa missing\n"); +#endif + unsetenv("X"); assert(!getenv("X")); assert(!libsimple_getenv_ne("X")); @@ -1017,6 +1027,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 11); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); @@ -1025,6 +1036,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 12); assert(info->zeroed == 12); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); @@ -1033,6 +1045,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 13); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); @@ -1041,6 +1054,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 14); assert(info->zeroed == 14); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); @@ -1049,6 +1063,7 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 15); assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); @@ -1057,8 +1072,55 @@ main(void) assert((info = get_allocinfo(ptr))); assert(info->size == 16); assert(info->zeroed == 16); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); + } + free(ptr); + + assert((ptr = libsimple_aligned_allocz(0, 8, 8))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 8); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); + } + free(ptr); + + assert((ptr = libsimple_aligned_allocz(1, 8, 16))); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 16); + assert(info->alignment == 8); + assert(info->zeroed == 16); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); + } + free(ptr); + + ptr = NULL; + + assert(!libsimple_posix_memalignz(&ptr, 0, 8 * sizeof(void *), 8)); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 8); + assert(info->alignment == 8 * sizeof(void *)); + assert(!info->zeroed); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); + } + free(ptr); + ptr = NULL; + + assert(!libsimple_posix_memalignz(&ptr, 1, 4 * sizeof(void *), 16)); + assert(ptr); + if (have_custom_malloc()) { + assert((info = get_allocinfo(ptr))); + assert(info->size == 16); + assert(info->alignment == 4 * sizeof(void *)); + assert(info->zeroed == 16); + assert(!((uintptr_t)ptr % (uintptr_t)info->alignment)); } free(ptr); + ptr = NULL; if (have_custom_malloc()) { alloc_fail_in = 1; @@ -1094,6 +1156,24 @@ main(void) alloc_fail_in = 1; assert(!(ptr = libsimple_mallocz(1, 20)) && errno == ENOMEM); assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert(!(ptr = libsimple_aligned_allocz(0, 8, 8)) && errno == ENOMEM); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert(!(ptr = libsimple_aligned_allocz(1, 8, 16)) && errno == ENOMEM); + assert(!alloc_fail_in); + + errno = 0; + + alloc_fail_in = 1; + assert(libsimple_posix_memalignz(&ptr, 0, 4 * sizeof(void *), 8) == ENOMEM && !errno); + assert(!alloc_fail_in); + + alloc_fail_in = 1; + assert(libsimple_posix_memalignz(&ptr, 1, 16 * sizeof(void *), 16) == ENOMEM && !errno); + assert(!alloc_fail_in); } assert((ptr = malloc(1))); @@ -1122,6 +1202,16 @@ main(void) assert(!read(fds[0], buf, sizeof(buf))); close(fds[0]); + assert(libsimple_memeq("abcxyz", "abc123", 3)); + assert(!libsimple_memeq("abcxyz", "abc123", 4)); + assert(libsimple_memeq("abcxyz", "abcx23", 4)); + assert(libsimple_memeq("1", "2", 0)); + assert(!libsimple_memeq("1", "2", 1)); + + stpcpy(buf, "abc123"); + assert(!strcmpnul(libsimple_mempset(buf, '.', 3), "123")); + assert(!strcmp(buf, "...123")); + #ifdef libsimple_asprintfa s = libsimple_asprintfa("%sxyz%s", "abc", "123"); assert(s); diff --git a/libsimple.h b/libsimple.h index c9fbffc..96cd73c 100644 --- a/libsimple.h +++ b/libsimple.h @@ -50,431 +50,32 @@ extern int libsimple_default_failure_exit; -#ifndef DONT_DEFINE_CLOCK_MONOTONIC_RAW -# ifndef CLOCK_MONOTONIC_RAW -# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC -# endif -#endif - - -#ifdef AF_LOCAL -# ifndef AF_UNIX -# define AF_UNIX AF_LOCAL -# endif -# ifndef AF_FILE -# define AF_FILE AF_LOCAL -# endif -#endif - -#ifdef AF_UNIX -# ifndef AF_LOCAL -# define AF_LOCAL AF_UNIX -# endif -# ifndef AF_FILE -# define AF_FILE AF_UNIX -# endif -#endif - -#ifdef AF_FILE -# ifndef AF_LOCAL -# define AF_LOCAL AF_FILE -# endif -# ifndef AF_UNIX -# define AF_UNIX AF_FILE -# endif -#endif - -#ifdef AF_NETLINK -# ifndef AF_ROUTE -# define AF_ROUTE AF_NETLINK -# endif -#endif - -#ifdef AF_ROUTE -# ifndef AF_NETLINK -# define AF_NETLINK AF_ROUTE -# endif -#endif - -#ifdef PF_LOCAL -# ifndef PF_UNIX -# define PF_UNIX PF_LOCAL -# endif -# ifndef PF_FILE -# define PF_FILE PF_LOCAL -# endif -#endif - -#ifdef PF_UNIX -# ifndef PF_LOCAL -# define PF_LOCAL PF_UNIX -# endif -# ifndef PF_FILE -# define PF_FILE PF_UNIX -# endif -#endif - -#ifdef PF_FILE -# ifndef PF_LOCAL -# define PF_LOCAL PF_FILE -# endif -# ifndef PF_UNIX -# define PF_UNIX PF_FILE -# endif -#endif - -#ifdef PF_NETLINK -# ifndef PF_ROUTE -# define PF_ROUTE PF_NETLINK -# endif -#endif - -#ifdef PF_ROUTE -# ifndef PF_NETLINK -# define PF_NETLINK PF_ROUTE -# endif -#endif - -#if !defined(PF_UNIX) && defined(AF_UNIX) -# define PF_UNIX AF_UNIX -#endif -#if !defined(PF_LOCAL) && defined(AF_LOCAL) -# define PF_LOCAL AF_LOCAL -#endif -#if !defined(PF_FILE) && defined(AF_FILE) -# define PF_FILE AF_FILE -#endif -#if !defined(PF_INET) && defined(AF_INET) -# define PF_INET AF_INET -#endif -#if !defined(PF_INET6) && defined(AF_INET6) -# define PF_INET6 AF_INET6 -#endif -#if !defined(PF_NETLINK) && defined(AF_NETLINK) -# define PF_NETLINK AF_NETLINK -#endif -#if !defined(PF_ROUTE) && defined(AF_ROUTE) -# define PF_ROUTE AF_ROUTE -#endif - - -#ifndef MIN -# define MIN(A, B) ((A) < (B) ? (A) : (B)) -#endif - - -#ifndef MAX -# define MAX(A, B) ((A) > (B) ? (A) : (B)) -#endif - - -#ifndef MIN3 -# define MIN3(A, B, C) MIN(MIN((A), (B)), (C)) -#endif - - -#ifndef MAX3 -# define MAX3(A, B, C) MAX(MAX((A), (B)), (C)) -#endif - - -#ifndef ELEMSOF -# define ELEMSOF(ARR) (sizeof(ARR) / (sizeof(*(ARR)))) -#endif - - -#ifndef STRLEN -# define STRLEN(STR) (sizeof(STR) - 1) -#endif - - -#ifndef INTSTRLEN -# define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : 5 * (sizeof(TYPE) / 2)) + ((TYPE)-1 < 0)) -#endif - - -#ifndef TYPE_MAX -# define TYPE_MAX(TYPE) ((TYPE)(((1ULL << (8 * sizeof(TYPE) - 1)) - 1) << ((TYPE)-1 > 0) | 1)) -#endif - - -#ifndef TYPE_MIN -# define TYPE_MIN(TYPE) ((TYPE)((TYPE)-1 > 0 ? 0 : (TYPE)~0 < (TYPE)-1 ? (TYPE)~0 : (TYPE)(1ULL << (8 * sizeof(TYPE) - 1)))) -#endif - - -#ifndef BLKCNT64_MAX -# define BLKCNT64_MAX TYPE_MAX(blkcnt64_t) -#endif - -#ifndef BLKCNT_MAX -# define BLKCNT_MAX TYPE_MAX(blkcnt_t) -#endif - -#ifndef BLKSIZE_MAX -# define BLKSIZE_MAX TYPE_MAX(blksize_t) -#endif - -#ifndef CC_MAX -# define CC_MAX TYPE_MAX(cc_t) -#endif - -#ifndef CLOCKID_MAX -# define CLOCKID_MAX TYPE_MAX(clockid_t) -#endif - -#ifndef CLOCK_MAX -# define CLOCK_MAX TYPE_MAX(clock_t) -#endif - -#ifndef DEV_MAX -# define DEV_MAX TYPE_MAX(dev_t) -#endif - -#ifndef FSBLKCNT64_MAX -# define FSBLKCNT64_MAX TYPE_MAX(fsblkcnt64_t) -#endif - -#ifndef FSBLKCNT_MAX -# define FSBLKCNT_MAX TYPE_MAX(fsblkcnt_t) -#endif - -#ifndef FSFILCNT64_MAX -# define FSFILCNT64_MAX TYPE_MAX(fsfilcnt64_t) -#endif - -#ifndef FSFILCNT_MAX -# define FSFILCNT_MAX TYPE_MAX(fsfilcnt_t) -#endif - -#ifndef GID_MAX -# define GID_MAX TYPE_MAX(gid_t) -#endif - -#ifndef ID_MAX -# define ID_MAX TYPE_MAX(id_t) -#endif - -#ifndef INO64_MAX -# define INO64_MAX TYPE_MAX(ino64_t) -#endif - -#ifndef INO_MAX -# define INO_MAX TYPE_MAX(ino_t) -#endif - -#ifndef KEY_MAX -# define KEY_MAX TYPE_MAX(key_t) -#endif - -#ifndef LOFF_MAX -# define LOFF_MAX TYPE_MAX(loff_t) -#endif - -#ifndef MODE_MAX -# define MODE_MAX TYPE_MAX(mode_t) -#endif - -#ifndef NLINK_MAX -# define NLINK_MAX TYPE_MAX(nlink_t) -#endif - -#ifndef OFF64_MAX -# define OFF64_MAX TYPE_MAX(off64_t) -#endif - -#ifndef OFF_MAX -# define OFF_MAX TYPE_MAX(off_t) -#endif - -#ifndef PID_MAX -# define PID_MAX TYPE_MAX(pid_t) -#endif - -#ifndef QUAD_MAX -# define QUAD_MAX TYPE_MAX(quad_t) -#endif - -#ifndef REGISTER_MAX -# define REGISTER_MAX TYPE_MAX(register_t) -#endif - -#ifndef RLIM64_MAX -# define RLIM64_MAX TYPE_MAX(rlim64_t) -#endif - -#ifndef RLIM_MAX -# define RLIM_MAX TYPE_MAX(rlim_t) -#endif - -#ifndef SOCKLEN_MAX -# define SOCKLEN_MAX TYPE_MAX(socklen_t) -#endif - -#ifndef SPEED_MAX -# define SPEED_MAX TYPE_MAX(speed_t) -#endif - -#ifndef SUSECONDS_MAX -# define SUSECONDS_MAX TYPE_MAX(suseconds_t) -#endif - -#ifndef TCFLAG_MAX -# define TCFLAG_MAX TYPE_MAX(tcflag_t) -#endif - -#ifndef TIME_MAX -# define TIME_MAX TYPE_MAX(time_t) -#endif - -#ifndef UID_MAX -# define UID_MAX TYPE_MAX(uid_t) -#endif - -#ifndef USECONDS_MAX -# define USECONDS_MAX TYPE_MAX(useconds_t) -#endif - -#ifndef U_QUAD_MAX -# define U_QUAD_MAX TYPE_MAX(u_quad_t) -#endif - - -#ifndef BLKCNT64_MIN -# define BLKCNT64_MIN TYPE_MIN(blkcnt64_t) -#endif - -#ifndef BLKCNT_MIN -# define BLKCNT_MIN TYPE_MIN(blkcnt_t) -#endif - -#ifndef BLKSIZE_MIN -# define BLKSIZE_MIN TYPE_MIN(blksize_t) -#endif - -#ifndef CC_MIN -# define CC_MIN TYPE_MIN(cc_t) -#endif - -#ifndef CLOCKID_MIN -# define CLOCKID_MIN TYPE_MIN(clockid_t) -#endif - -#ifndef CLOCK_MIN -# define CLOCK_MIN TYPE_MIN(clock_t) -#endif - -#ifndef DEV_MIN -# define DEV_MIN TYPE_MIN(dev_t) -#endif - -#ifndef FSBLKCNT64_MIN -# define FSBLKCNT64_MIN TYPE_MIN(fsblkcnt64_t) -#endif - -#ifndef FSBLKCNT_MIN -# define FSBLKCNT_MIN TYPE_MIN(fsblkcnt_t) -#endif - -#ifndef FSFILCNT64_MIN -# define FSFILCNT64_MIN TYPE_MIN(fsfilcnt64_t) -#endif - -#ifndef FSFILCNT_MIN -# define FSFILCNT_MIN TYPE_MIN(fsfilcnt_t) -#endif - -#ifndef GID_MIN -# define GID_MIN TYPE_MIN(gid_t) -#endif - -#ifndef ID_MIN -# define ID_MIN TYPE_MIN(id_t) -#endif - -#ifndef INO64_MIN -# define INO64_MIN TYPE_MIN(ino64_t) -#endif - -#ifndef INO_MIN -# define INO_MIN TYPE_MIN(ino_t) -#endif - -#ifndef KEY_MIN -# define KEY_MIN TYPE_MIN(key_t) -#endif - -#ifndef LOFF_MIN -# define LOFF_MIN TYPE_MIN(loff_t) -#endif - -#ifndef MODE_MIN -# define MODE_MIN TYPE_MIN(mode_t) -#endif - -#ifndef NLINK_MIN -# define NLINK_MIN TYPE_MIN(nlink_t) -#endif - -#ifndef OFF64_MIN -# define OFF64_MIN TYPE_MIN(off64_t) -#endif - -#ifndef OFF_MIN -# define OFF_MIN TYPE_MIN(off_t) -#endif - -#ifndef PID_MIN -# define PID_MIN TYPE_MIN(pid_t) -#endif - -#ifndef QUAD_MIN -# define QUAD_MIN TYPE_MIN(quad_t) -#endif - -#ifndef REGISTER_MIN -# define REGISTER_MIN TYPE_MIN(register_t) -#endif - -#ifndef RLIM64_MIN -# define RLIM64_MIN TYPE_MIN(rlim64_t) -#endif - -#ifndef RLIM_MIN -# define RLIM_MIN TYPE_MIN(rlim_t) -#endif - -#ifndef SOCKLEN_MIN -# define SOCKLEN_MIN TYPE_MIN(socklen_t) -#endif - -#ifndef SPEED_MIN -# define SPEED_MIN TYPE_MAX(speed_t) -#endif - -#ifndef SUSECONDS_MIN -# define SUSECONDS_MIN TYPE_MIN(suseconds_t) -#endif - -#ifndef TCFLAG_MIN -# define TCFLAG_MIN TYPE_MAX(tcflag_t) -#endif - -#ifndef TIME_MIN -# define TIME_MIN TYPE_MIN(time_t) -#endif - -#ifndef UID_MIN -# define UID_MIN TYPE_MIN(uid_t) -#endif - -#ifndef USECONDS_MIN -# define USECONDS_MIN TYPE_MIN(useconds_t) -#endif - -#ifndef U_QUAD_MIN -# define U_QUAD_MIN TYPE_MIN(u_quad_t) -#endif +#include "libsimple/definitions.h" +#include "libsimple/memalloc.h" +#include "libsimple/strdup.h" +#include "libsimple/strndup.h" +#include "libsimple/memdup.h" +#include "libsimple/aligned_memdup.h" +#include "libsimple/mallocz.h" +#include "libsimple/malloc.h" +#include "libsimple/calloc.h" +#include "libsimple/realloc.h" +#include "libsimple/memalignz.h" +#include "libsimple/memalign.h" +#include "libsimple/vallocz.h" +#include "libsimple/valloc.h" +#include "libsimple/pvallocz.h" +#include "libsimple/pvalloc.h" +#include "libsimple/aligned_allocz.h" +#include "libsimple/aligned_alloc.h" +#include "libsimple/posix_memalignz.h" +#include "libsimple/posix_memalign.h" +#include "libsimple/env.h" +#include "libsimple/time.h" +#include "libsimple/printf.h" +#include "libsimple/mem.h" +#include "libsimple/str.h" +#include "libsimple/strn.h" #define FREE(PTR) ((void)(free(PTR), (PTR) = NULL)) @@ -493,39 +94,6 @@ libsimple_close(int *__fdp) return __ret; } - -_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); } @@ -533,73 +101,6 @@ static inline int libsimple_inchrset(int __c, const char *__s) # define inchrset libsimple_inchrset #endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __nonnull__, __warn_unused_result__))) -void *libsimple_memdup(const void *, size_t); -#ifndef memdup -# define memdup libsimple_memdup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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 - - -#if defined(__GNUC__) || defined(__clang__) -# define libsimple_strdupa(s)\ - ({\ - const char *__s = (s);\ - size_t __n = strlen(__s) + 1;\ - char *__r = alloca(__n);\ - memcpy(__r, __s, __n);\ - }) -# ifndef strdupa -# define strdupa(s) libsimple_strdupa(s) -# endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -# define libsimple_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;\ - }) -# ifndef strndupa -# define strndupa(s, n) libsimple_strndupa(s, n) -# endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -# define libsimple_memdupa(s, n)\ - ({\ - const char *__s = (s);\ - size_t __n = (n);\ - char *__r = alloca(__n);\ - memcpy(__r, __s, __n);\ - }) -# ifndef memdupa -# define memdupa(s, n) libsimple_memdupa(s, n) -# endif -#endif - - /** * Check whether a NUL-terminated string is encoded in UTF-8 * @@ -613,888 +114,6 @@ int libsimple_isutf8(const char *, int); # 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 - -#if defined(__GNUC__) || defined(__clang__) -# define libsimple_asprintfa(__fmt, ...)\ - ({\ - const char *__f = (__fmt);\ - char *__ret = NULL;\ - int __r = snprintf(NULL, 0, __f, __VA_ARGS__);\ - if (__r >= 0) {\ - __ret = alloca((size_t)__r + 1);\ - sprintf(__ret, __f, __VA_ARGS__);\ - }\ - __ret;\ - }) -# ifndef asprintfa -# define asprintfa(...) libsimple_asprintfa(__VA_ARGS__) -# endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -# define libsimple_vasprintfa(__fmt, __ap)\ - ({\ - const char *__f = (__fmt);\ - va_list __a1;\ - va_list __a2;\ - char *__ret = NULL;\ - int __r;\ - va_copy(__a1, __ap);\ - va_copy(__a2, __a1);\ - __r = vsnprintf(NULL, 0, __f, __a1);\ - if (__r >= 0) {\ - __ret = alloca((size_t)__r + 1);\ - vsprintf(__ret, __f, __a2);\ - }\ - va_end(__a2);\ - va_end(__a1);\ - __ret;\ - }) -# ifndef vasprintfa -# define vasprintfa(fmt, ap) libsimple_vasprintfa(fmt, ap) -# 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__))) -void *libsimple_memrmem(const void *, size_t, const void *, size_t); -#ifndef memrmem -# define memrmem libsimple_memrmem -#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__))) -char *libsimple_strrstr(const char *, const char *); -#ifndef strrstr -# define strrstr libsimple_strrstr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strnstr(const char *, const char *, size_t); -#ifndef strnstr -# define strnstr libsimple_strnstr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strrnstr(const char *, const char *, size_t); -#ifndef strrnstr -# define strrnstr libsimple_strrnstr -#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__))) -static inline int libsimple_strcasestarts(const char *__s, const char *__t) -{ return !strncasecmp(__s, __t, strlen(__t)); } -#ifndef strcasestarts -# define strcasestarts libsimple_strcasestarts -#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__))) -int libsimple_strcaseends(const char *, const char *); -#ifndef strcaseends -# define strcaseends libsimple_strcaseends -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strcasestr(const char *, const char *); -#ifndef strcasestr -# define strcasestr libsimple_strcasestr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strrcasestr(const char *, const char *); -#ifndef strrcasestr -# define strrcasestr libsimple_strrcasestr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strncasestr(const char *, const char *, size_t); -#ifndef strncasestr -# define strncasestr libsimple_strncasestr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -char *libsimple_strrncasestr(const char *, const char *, size_t); -#ifndef strrncasestr -# define strrncasestr libsimple_strrncasestr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strcmpnul(const char *__a, const char *__b) -{ return (!__a || !__b) ? !__b - !__a : strcmp(__a, __b); } -#ifndef strcmpnul -# define strcmpnul libsimple_strcmpnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strncmpnul(const char *__a, const char *__b, size_t __n) -{ return (!__a || !__b) ? !__b - !__a : strncmp(__a, __b, __n); } -#ifndef strncmpnul -# define strncmpnul libsimple_strncmpnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strcasecmpnul(const char *__a, const char *__b) -{ return (!__a || !__b) ? !__b - !__a : strcasecmp(__a, __b); } -#ifndef strcasecmpnul -# define strcasecmpnul libsimple_strcasecmpnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strncasecmpnul(const char *__a, const char *__b, size_t __n) -{ return (!__a || !__b) ? !__b - !__a : strncasecmp(__a, __b, __n); } -#ifndef strncasecmpnul -# define strncasecmpnul libsimple_strncasecmpnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -static inline int libsimple_streq(const char *__a, const char *__b) -{ return !strcmp(__a, __b); } -#ifndef streq -# define streq libsimple_streq -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -static inline int libsimple_strneq(const char *__a, const char *__b, size_t __n) -{ return !strncmp(__a, __b, __n); } -#ifndef strneq -# define strneq libsimple_strneq -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_streqnul(const char *__a, const char *__b) -{ return !strcmpnul(__a, __b); } -#ifndef streqnul -# define streqnul libsimple_streqnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strneqnul(const char *__a, const char *__b, size_t __n) -{ return !strncmpnul(__a, __b, __n); } -#ifndef strneqnul -# define strneqnul libsimple_strneqnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -static inline int libsimple_strcaseeq(const char *__a, const char *__b) -{ return !strcasecmp(__a, __b); } -#ifndef strcaseeq -# define strcaseeq libsimple_strcaseeq -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) -static inline int libsimple_strncaseeq(const char *__a, const char *__b, size_t __n) -{ return !strncasecmp(__a, __b, __n); } -#ifndef strncaseeq -# define strncaseeq libsimple_strncaseeq -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strcaseeqnul(const char *__a, const char *__b) -{ return !strcasecmpnul(__a, __b); } -#ifndef strcaseeqnul -# define strcaseeqnul libsimple_strcaseeqnul -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) -static inline int libsimple_strncaseeqnul(const char *__a, const char *__b, size_t __n) -{ return !strncasecmpnul(__a, __b, __n); } -#ifndef strncaseeqnul -# define strncaseeqnul libsimple_strncaseeqnul -#endif - - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -void *libsimple_vmalloczn(int, size_t, va_list); -#ifndef vmalloczn -# define vmalloczn libsimple_vmalloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void *libsimple_vmallocn(size_t __n, va_list __ap) -{ return libsimple_vmalloczn(0, __n, __ap); } -#ifndef vmallocn -# define vmallocn libsimple_vmallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void *libsimple_vcallocn(size_t __n, va_list __ap) -{ return libsimple_vmalloczn(1, __n, __ap); } -#ifndef vcallocn -# define vcallocn libsimple_vcallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -void *libsimple_vreallocn(void *, size_t, va_list); -#ifndef vreallocn -# define vreallocn libsimple_vreallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void * -libsimple_mallocz(int __clear, size_t __n) -{ return __clear ? calloc(1, __n) : malloc(__n); } -#ifndef mallocn -# define mallocn libsimple_mallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void * -libsimple_malloczn(int __clear, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_vmalloczn(__clear, __n, __ap); - va_end(__ap); -} -#ifndef malloczn -# define malloczn libsimple_malloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void * -libsimple_mallocn(size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_vmalloczn(0, __n, __ap); - va_end(__ap); -} -#ifndef mallocn -# define mallocn libsimple_mallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void * -libsimple_callocn(size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_vmalloczn(1, __n, __ap); - va_end(__ap); -} -#ifndef callocn -# define callocn libsimple_callocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) -static inline void * -libsimple_reallocn(void *__ptr, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_vreallocn(__ptr, __n, __ap); - va_end(__ap); -} -#ifndef reallocn -# define reallocn libsimple_reallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_enmalloc(int, size_t); -#ifndef enmalloc -# define enmalloc libsimple_enmalloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_encalloc(int, size_t, size_t); -#ifndef encalloc -# define encalloc libsimple_encalloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_enrealloc(int, void *, size_t); -#ifndef enrealloc -# define enrealloc libsimple_enrealloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_enmallocz(int __status, int __clear, size_t __n) -{ return __clear ? libsimple_encalloc(__status, 1, __n) : libsimple_enmalloc(__status, __n); } -#ifndef enmallocz -# define enmallocz libsimple_enmallocz -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __nonnull__, __warn_unused_result__, __returns_nonnull__))) -char *libsimple_enstrdup(int, const char *); -#ifndef enstrdup -# define enstrdup libsimple_enstrdup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __nonnull__, __warn_unused_result__, __returns_nonnull__))) -char *libsimple_enstrndup(int, const char *, size_t); -#ifndef enstrndup -# define enstrndup libsimple_enstrndup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_enmemdup(int, const void *, size_t); -#ifndef enmemdup -# define enmemdup libsimple_enmemdup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_envmalloczn(int, int, size_t, va_list); -#ifndef envmalloczn -# define envmalloczn libsimple_envmalloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } -#ifndef envmallocn -# define envmallocn libsimple_envmallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } -#ifndef envcallocn -# define envcallocn libsimple_envcallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -void *libsimple_envreallocn(int, void *, size_t, va_list); -#ifndef envreallocn -# define envreallocn libsimple_envreallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_enmalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_envmalloczn(__status, __clear, __n, __ap); - va_end(__ap); -} -#ifndef enmalloczn -# define enmalloczn libsimple_enmalloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_enmallocn(int __status, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_envmallocn(__status, __n, __ap); - va_end(__ap); -} -#ifndef enmallocn -# define enmallocn libsimple_enmallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_encallocn(int __status, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_envcallocn(__status, __n, __ap); - va_end(__ap); -} -#ifndef encallocn -# define encallocn libsimple_encallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_enreallocn(int __status, void *__ptr, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_envreallocn(__status, __ptr, __n, __ap); - va_end(__ap); -} -#ifndef enreallocn -# define enreallocn libsimple_enreallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_emallocz(int __clear, size_t __n) -{ return libsimple_enmallocz(libsimple_default_failure_exit, __clear, __n); } -#ifndef emallocz -# define emallocz libsimple_emallocz -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_emalloc(size_t __n) -{ return libsimple_enmalloc(libsimple_default_failure_exit, __n); } -#ifndef emalloc -# define emalloc libsimple_emalloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_ecalloc(size_t __n, size_t __m) -{ return encalloc(libsimple_default_failure_exit, __n, __m); } -#ifndef ecalloc -# define ecalloc libsimple_ecalloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_erealloc(void *__ptr, size_t __n) -{ return enrealloc(libsimple_default_failure_exit, __ptr, __n); } -#ifndef erealloc -# define erealloc libsimple_erealloc -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline char *libsimple_estrdup(const char *__s) -{ return enstrdup(libsimple_default_failure_exit, __s); } -#ifndef estrdup -# define estrdup libsimple_estrdup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline char *libsimple_estrndup(const char *__s, size_t __n) -{ return enstrndup(libsimple_default_failure_exit, __s, __n); } -#ifndef estrndup -# define estrndup libsimple_estrndup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_ememdup(const void *__s, size_t __n) -{ return enmemdup(libsimple_default_failure_exit, __s, __n); } -#ifndef ememdup -# define ememdup libsimple_ememdup -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } -#ifndef evmalloczn -# define evmalloczn libsimple_evmalloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_evmallocn(size_t __n, va_list __ap) -{ return libsimple_envmallocn(libsimple_default_failure_exit, __n, __ap); } -#ifndef evmallocn -# define evmallocn libsimple_evmallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void *libsimple_evcallocn(size_t __n, va_list __ap) -{ return libsimple_envcallocn(libsimple_default_failure_exit, __n, __ap); } -#ifndef evcallocn -# define evcallocn libsimple_evcallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } -#ifndef evreallocn -# define evreallocn libsimple_evreallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_emalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_evmalloczn(__clear, __n, __ap); - va_end(__ap); -} -#ifndef emalloczn -# define emalloczn libsimple_emalloczn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_emallocn(size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_evmallocn(__n, __ap); - va_end(__ap); -} -#ifndef emallocn -# define emallocn libsimple_emallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_ecallocn(size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_evcallocn(__n, __ap); - va_end(__ap); -} -#ifndef ecallocn -# define ecallocn libsimple_ecallocn -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) -static inline void * -libsimple_ereallocn(void *__ptr, size_t __n, ... /*, (size_t)0 */) -{ - va_list __ap; - va_start(__ap, __n); - return libsimple_evreallocn(__ptr, __n, __ap); - va_end(__ap); -} -#ifndef ereallocn -# define ereallocn libsimple_ereallocn -#endif - - -/** - * Read an environment variable, but handle it as undefined if empty - * - * @param var The environment variable's name - * @return The environment variable's value, `NULL` if empty or not defined - */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) -static inline char * -libsimple_getenv_ne(const char *__name) -{ - char *__env = getenv(__name); - return (__env && *__env) ? __env : NULL; -} -#ifndef getenv_ne -# define getenv_ne libsimple_getenv_ne -#endif - -/** - * Read an environment variable, but handle it as empty if undefined - * - * @param var The environment variable's name - * @return The environment variable's value, "" if empty or not defined - */ -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __returns_nonnull__))) -static inline const char * -libsimple_getenv_e(const char *__name) -{ - const char *__env = getenv(__name); - return (__env && *__env) ? __env : ""; -} -#ifndef getenv_e -# define getenv_e libsimple_getenv_e -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_vputenvf(const char *, va_list); -#ifndef vputenvf -# define vputenvf libsimple_vputenvf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) -static inline int -libsimple_putenvf(const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - return libsimple_vputenvf(__fmt, __ap); - va_end(__ap); -} -#ifndef putenvf -# define putenvf libsimple_putenvf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -void libsimple_envputenvf(int, const char *, va_list); -#ifndef envputenvf -# define envputenvf libsimple_envputenvf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 2, 3)))) -static inline void -libsimple_enputenvf(int __status, const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - libsimple_envputenvf(__status, __fmt, __ap); - va_end(__ap); -} -#ifndef enputenvf -# define enputenvf libsimple_enputenvf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -static inline void -libsimple_evputenvf(const char *__fmt, va_list __ap) -{ - libsimple_envputenvf(libsimple_default_failure_exit, __fmt, __ap); -} -#ifndef evputenvf -# define evputenvf libsimple_evputenvf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) -static inline void -libsimple_eputenvf(const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - libsimple_evputenvf(__fmt, __ap); - va_end(__ap); -} -#ifndef eputenvf -# define eputenvf libsimple_eputenvf -#endif - - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) -void libsimple_vweprintf(const char *, va_list); -#ifndef vweprintf -# define vweprintf libsimple_vweprintf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2)))) -static inline void -libsimple_weprintf(const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - libsimple_vweprintf(__fmt, __ap); - va_end(__ap); -} -#ifndef weprintf -# define weprintf libsimple_weprintf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __noreturn__))) -static inline void -libsimple_venprintf(int __status, const char *__fmt, va_list __ap) -{ - libsimple_vweprintf(__fmt, __ap); - exit(__status); -} -#ifndef venprintf -# define venprintf libsimple_venprintf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __format__(__printf__, 2, 3), __noreturn__))) -static inline void -libsimple_enprintf(int __status, const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - libsimple_venprintf(__status, __fmt, __ap); - va_end(__ap); -} -#ifndef enprintf -# define enprintf libsimple_enprintf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __noreturn__))) -static inline void -libsimple_veprintf(const char *__fmt, va_list __ap) -{ - libsimple_vweprintf(__fmt, __ap); - exit(libsimple_default_failure_exit); -} -#ifndef veprintf -# define veprintf libsimple_veprintf -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2), __noreturn__))) -static inline void -libsimple_eprintf(const char *__fmt, ...) -{ - va_list __ap; - va_start(__ap, __fmt); - libsimple_veprintf(__fmt, __ap); - va_end(__ap); -} -#ifndef eprintf -# define eprintf libsimple_eprintf -#endif - - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_sumtimespec(struct timespec *, const struct timespec *, const struct timespec *); -#ifndef sumtimespec -# define sumtimespec libsimple_sumtimespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_difftimespec(struct timespec *, const struct timespec *, const struct timespec *); -#ifndef difftimespec -# define difftimespec libsimple_difftimespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_multimespec(struct timespec *, const struct timespec *, int); -#ifndef multimespec -# define multimespec libsimple_multimespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) -static inline int -libsimple_cmptimespec(const struct timespec *__a, const struct timespec *__b) -{ - if (__a->tv_sec != __b->tv_sec) - return __a->tv_sec < __b->tv_sec ? -1 : +1; - return __a->tv_nsec < __b->tv_nsec ? -1 : __a->tv_nsec > __b->tv_nsec; -} -#ifndef cmptimespec -# define cmptimespec libsimple_cmptimespec -#endif - - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_sumtimeval(struct timeval *, const struct timeval *, const struct timeval *); -#ifndef sumtimeval -# define sumtimeval libsimple_sumtimeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_difftimeval(struct timeval *, const struct timeval *, const struct timeval *); -#ifndef difftimeval -# define difftimeval libsimple_difftimeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_multimeval(struct timeval *, const struct timeval *, int); -#ifndef multimeval -# define multimeval libsimple_multimeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) -static inline int -libsimple_cmptimeval(const struct timeval *__a, const struct timeval *__b) -{ - if (__a->tv_sec != __b->tv_sec) - return __a->tv_sec < __b->tv_sec ? -1 : +1; - return __a->tv_usec < __b->tv_usec ? -1 : __a->tv_usec > __b->tv_usec; -} -#ifndef cmptimeval -# define cmptimeval libsimple_cmptimeval -#endif - - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -static inline void -libsimple_timeval2timespec(struct timespec *restrict __ts, const struct timeval *restrict __tv) -{ - __ts->tv_sec = __tv->tv_sec; - __ts->tv_nsec = __tv->tv_usec; - __ts->tv_nsec *= 1000L; -} -#ifndef timeval2timespec -# define timeval2timespec libsimple_timeval2timespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -int libsimple_timespec2timeval(struct timeval *restrict, const struct timespec *restrict); -#ifndef timespec2timeval -# define timespec2timeval libsimple_timespec2timeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) -int libsimple_strtotimespec(struct timespec *restrict, const char *restrict, char **restrict); -#ifndef strtotimespec -# define strtotimespec libsimple_strtotimespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) -int libsimple_strtotimeval(struct timeval *restrict, const char *restrict, char **restrict); -#ifndef strtotimeval -# define strtotimeval libsimple_strtotimeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) -char *libsimple_timespectostr(char *restrict, const struct timespec *restrict); -#ifndef timespectostr -# define timespectostr libsimple_timespectostr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) -char *libsimple_timevaltostr(char *restrict, const struct timeval *restrict); -#ifndef timevaltostr -# define timevaltostr libsimple_timevaltostr -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -static inline double -libsimple_timespectodouble(const struct timespec *__ts) -{ - double __ret = (double)(__ts->tv_nsec); - __ret /= (double)1000000000L; - __ret += (double)(__ts->tv_sec); - return __ret; -} -#ifndef timespectodouble -# define timespectodouble libsimple_timespectodouble -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -static inline double -libsimple_timevaltodouble(const struct timeval *__tv) -{ - double __ret = (double)(__tv->tv_usec); - __ret /= (double)1000000L; - __ret += (double)(__tv->tv_sec); - return __ret; -} -#ifndef timevaltodouble -# define timevaltodouble libsimple_timevaltodouble -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -void libsimple_doubletotimespec(struct timespec *, double); -#ifndef doubletotimespec -# define doubletotimespec libsimple_doubletotimespec -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) -void libsimple_doubletotimeval(struct timeval *, double); -#ifndef doubletotimeval -# define doubletotimeval libsimple_doubletotimeval -#endif - -_LIBSIMPLE_GCC_ONLY(__attribute__((__returns_nonnull__, __nonnull__))) -char *libsimple_minimise_number_string(char *); -#ifndef minimise_number_string -# define minimise_number_string libsimple_minimise_number_string -#endif - - #define LIBSIMPLE_UNLIST(LIST, I, NP) libsimple_unlist((LIST), (I), (NP), sizeof(*(LIST))) #ifndef UNLIST # define UNLIST(LIST, I, NP) LIBSIMPLE_UNLIST((LIST), (I), (NP)) diff --git a/libsimple/aligned_alloc.h b/libsimple/aligned_alloc.h new file mode 100644 index 0000000..8e7d66f --- /dev/null +++ b/libsimple/aligned_alloc.h @@ -0,0 +1,75 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) +static inline void *libsimple_valigned_allocn(size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_valigned_alloczn(0, __alignment, __n, __ap); } +#ifndef valigned_allocn +# define valigned_allocn libsimple_valigned_allocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) +static inline void * +libsimple_aligned_allocn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_valigned_allocn(__alignment, __n, __ap); + va_end(__ap); +} +#ifndef aligned_allocn +# define aligned_allocn libsimple_aligned_allocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_enaligned_alloc(int __status, size_t __alignment, size_t __n) +{ return libsimple_enaligned_allocz(__status, 0, __alignment, __n); } +#ifndef enaligned_alloc +# define enaligned_alloc libsimple_enaligned_alloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_envaligned_allocn(int __status, size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envaligned_alloczn(__status, 0, __alignment, __n, __ap); } +#ifndef envaligned_allocn +# define envaligned_allocn libsimple_envaligned_allocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enaligned_allocn(int __status, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envaligned_alloczn(__status, 0, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enaligned_allocn +# define enaligned_allocn libsimple_enaligned_allocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ealigned_alloc(size_t __alignment, size_t __n) +{ return libsimple_enaligned_alloc(libsimple_default_failure_exit, __alignment, __n); } +#ifndef ealigned_alloc +# define ealigned_alloc libsimple_ealigned_alloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evaligned_allocn(size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envaligned_allocn(libsimple_default_failure_exit, __alignment, __n, __ap); } +#ifndef evaligned_allocn +# define evaligned_allocn libsimple_evaligned_allocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ealigned_allocn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evaligned_allocn(__alignment, __n, __ap); + va_end(__ap); +} +#ifndef ealigned_allocn +# define ealigned_allocn libsimple_ealigned_allocn +#endif diff --git a/libsimple/aligned_allocz.h b/libsimple/aligned_allocz.h new file mode 100644 index 0000000..f34a015 --- /dev/null +++ b/libsimple/aligned_allocz.h @@ -0,0 +1,85 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) +void *libsimple_valigned_alloczn(int, size_t, size_t, va_list); +#ifndef valigned_alloczn +# define valigned_alloczn libsimple_valigned_alloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__))) +static inline void * +libsimple_aligned_allocz(int __clear, size_t __alignment, size_t __n) +{ + void *__ret = aligned_alloc(__alignment, __n); + if (__ret && __clear) + memset(__ret, 0, __n); + return __ret; +} +#ifndef aligned_allocz +# define aligned_allocz libsimple_aligned_allocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) +static inline void * +libsimple_aligned_alloczn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_valigned_alloczn(__clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef aligned_alloczn +# define aligned_alloczn libsimple_aligned_alloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __alloc_size__(4), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enaligned_allocz(int, int, size_t, size_t); +#ifndef enaligned_allocz +# define enaligned_allocz libsimple_enaligned_allocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_envaligned_alloczn(int, int, size_t, size_t, va_list); +#ifndef envaligned_alloczn +# define envaligned_alloczn libsimple_envaligned_alloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enaligned_alloczn(int __status, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envaligned_alloczn(__status, __clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enaligned_alloczn +# define enaligned_alloczn libsimple_enaligned_alloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ealigned_allocz(int __clear, size_t __alignment, size_t __n) +{ return libsimple_enaligned_allocz(libsimple_default_failure_exit, __clear, __alignment, __n); } +#ifndef ealigned_allocz +# define ealigned_allocz libsimple_ealigned_allocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evaligned_alloczn(int __clear, size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envaligned_alloczn(libsimple_default_failure_exit, __clear, __alignment, __n, __ap); } +#ifndef evaligned_alloczn +# define evaligned_alloczn libsimple_evaligned_alloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ealigned_alloczn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evaligned_alloczn(__clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef ealigned_alloczn +# define ealigned_alloczn libsimple_ealigned_alloczn +#endif diff --git a/libsimple/aligned_memdup.h b/libsimple/aligned_memdup.h new file mode 100644 index 0000000..8138eb2 --- /dev/null +++ b/libsimple/aligned_memdup.h @@ -0,0 +1,40 @@ +/* See LICENSE file for copyright and license details. */ + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_aligned_memdupa(s, alignment, n)\ + ({\ + const char *__s = (s);\ + size_t __n = (n);\ + size_t __a = (alignment);\ + uintptr_t __misalignment;\ + char *__r;\ + __a += !__a;\ + __r = alloca(__n + (__a - 1));\ + __misalignment = (uintptr_t)__r % (uintptr_t)__a;\ + if (__misalignment)\ + __r += (uintptr_t)__a - __misalignment;\ + memcpy(__r, __s, __n);\ + }) +# ifndef aligned_memdupa +# define aligned_memdupa(s, alignment, n) libsimple_aligned_memdupa(s, alignment, n) +# endif +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_align__(2), __alloc_size__(3), __nonnull__, __warn_unused_result__))) +void *libsimple_aligned_memdup(const void *, size_t, size_t); +#ifndef aligned_memdup +# define aligned_memdup libsimple_aligned_memdup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_align__(3), __alloc_size__(4), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enaligned_memdup(int, const void *, size_t, size_t); +#ifndef enaligned_memdup +# define enaligned_memdup libsimple_enaligned_memdup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ealigned_memdup(const void *__s, size_t __alignment, size_t __n) +{ return enaligned_memdup(libsimple_default_failure_exit, __s, __alignment, __n); } +#ifndef ealigned_memdup +# define ealigned_memdup libsimple_ealigned_memdup +#endif diff --git a/libsimple/calloc.h b/libsimple/calloc.h new file mode 100644 index 0000000..ab73ff3 --- /dev/null +++ b/libsimple/calloc.h @@ -0,0 +1,74 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_vcallocn(size_t __n, va_list __ap) +{ return libsimple_vmalloczn(1, __n, __ap); } +#ifndef vcallocn +# define vcallocn libsimple_vcallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_callocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmalloczn(1, __n, __ap); + va_end(__ap); +} +#ifndef callocn +# define callocn libsimple_callocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2, 3), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_encalloc(int, size_t, size_t); +#ifndef encalloc +# define encalloc libsimple_encalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } +#ifndef envcallocn +# define envcallocn libsimple_envcallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_encallocn(int __status, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envcallocn(__status, __n, __ap); + va_end(__ap); +} +#ifndef encallocn +# define encallocn libsimple_encallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1, 2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ecalloc(size_t __n, size_t __m) +{ return encalloc(libsimple_default_failure_exit, __n, __m); } +#ifndef ecalloc +# define ecalloc libsimple_ecalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evcallocn(size_t __n, va_list __ap) +{ return libsimple_envcallocn(libsimple_default_failure_exit, __n, __ap); } +#ifndef evcallocn +# define evcallocn libsimple_evcallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ecallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evcallocn(__n, __ap); + va_end(__ap); +} +#ifndef ecallocn +# define ecallocn libsimple_ecallocn +#endif diff --git a/libsimple/definitions.h b/libsimple/definitions.h new file mode 100644 index 0000000..9bbc649 --- /dev/null +++ b/libsimple/definitions.h @@ -0,0 +1,421 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef DONT_DEFINE_CLOCK_MONOTONIC_RAW +# ifndef CLOCK_MONOTONIC_RAW +# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC +# endif +#endif + + +#ifdef AF_LOCAL +# ifndef AF_UNIX +# define AF_UNIX AF_LOCAL +# endif +# ifndef AF_FILE +# define AF_FILE AF_LOCAL +# endif +#endif + +#ifdef AF_UNIX +# ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +# endif +# ifndef AF_FILE +# define AF_FILE AF_UNIX +# endif +#endif + +#ifdef AF_FILE +# ifndef AF_LOCAL +# define AF_LOCAL AF_FILE +# endif +# ifndef AF_UNIX +# define AF_UNIX AF_FILE +# endif +#endif + +#ifdef AF_NETLINK +# ifndef AF_ROUTE +# define AF_ROUTE AF_NETLINK +# endif +#endif + +#ifdef AF_ROUTE +# ifndef AF_NETLINK +# define AF_NETLINK AF_ROUTE +# endif +#endif + +#ifdef PF_LOCAL +# ifndef PF_UNIX +# define PF_UNIX PF_LOCAL +# endif +# ifndef PF_FILE +# define PF_FILE PF_LOCAL +# endif +#endif + +#ifdef PF_UNIX +# ifndef PF_LOCAL +# define PF_LOCAL PF_UNIX +# endif +# ifndef PF_FILE +# define PF_FILE PF_UNIX +# endif +#endif + +#ifdef PF_FILE +# ifndef PF_LOCAL +# define PF_LOCAL PF_FILE +# endif +# ifndef PF_UNIX +# define PF_UNIX PF_FILE +# endif +#endif + +#ifdef PF_NETLINK +# ifndef PF_ROUTE +# define PF_ROUTE PF_NETLINK +# endif +#endif + +#ifdef PF_ROUTE +# ifndef PF_NETLINK +# define PF_NETLINK PF_ROUTE +# endif +#endif + +#if !defined(PF_UNIX) && defined(AF_UNIX) +# define PF_UNIX AF_UNIX +#endif +#if !defined(PF_LOCAL) && defined(AF_LOCAL) +# define PF_LOCAL AF_LOCAL +#endif +#if !defined(PF_FILE) && defined(AF_FILE) +# define PF_FILE AF_FILE +#endif +#if !defined(PF_INET) && defined(AF_INET) +# define PF_INET AF_INET +#endif +#if !defined(PF_INET6) && defined(AF_INET6) +# define PF_INET6 AF_INET6 +#endif +#if !defined(PF_NETLINK) && defined(AF_NETLINK) +# define PF_NETLINK AF_NETLINK +#endif +#if !defined(PF_ROUTE) && defined(AF_ROUTE) +# define PF_ROUTE AF_ROUTE +#endif + + +#ifndef MIN +# define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#ifndef MAX +# define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + +#ifndef MIN3 +# define MIN3(A, B, C) MIN(MIN((A), (B)), (C)) +#endif + +#ifndef MAX3 +# define MAX3(A, B, C) MAX(MAX((A), (B)), (C)) +#endif + + +#ifndef ELEMSOF +# define ELEMSOF(ARR) (sizeof(ARR) / (sizeof(*(ARR)))) +#endif + +#ifndef STRLEN +# define STRLEN(STR) (sizeof(STR) - 1) +#endif + +#ifndef INTSTRLEN +# define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : 5 * (sizeof(TYPE) / 2)) + ((TYPE)-1 < 0)) +#endif + + +#ifndef TYPE_MAX +# define TYPE_MAX(TYPE) ((TYPE)(((1ULL << (8 * sizeof(TYPE) - 1)) - 1) << ((TYPE)-1 > 0) | 1)) +#endif + +#ifndef TYPE_MIN +# define TYPE_MIN(TYPE) ((TYPE)((TYPE)-1 > 0 ? 0 : (TYPE)~0 < (TYPE)-1 ? (TYPE)~0 : (TYPE)(1ULL << (8 * sizeof(TYPE) - 1)))) +#endif + + +#ifndef BLKCNT64_MAX +# define BLKCNT64_MAX TYPE_MAX(blkcnt64_t) +#endif + +#ifndef BLKCNT_MAX +# define BLKCNT_MAX TYPE_MAX(blkcnt_t) +#endif + +#ifndef BLKSIZE_MAX +# define BLKSIZE_MAX TYPE_MAX(blksize_t) +#endif + +#ifndef CC_MAX +# define CC_MAX TYPE_MAX(cc_t) +#endif + +#ifndef CLOCKID_MAX +# define CLOCKID_MAX TYPE_MAX(clockid_t) +#endif + +#ifndef CLOCK_MAX +# define CLOCK_MAX TYPE_MAX(clock_t) +#endif + +#ifndef DEV_MAX +# define DEV_MAX TYPE_MAX(dev_t) +#endif + +#ifndef FSBLKCNT64_MAX +# define FSBLKCNT64_MAX TYPE_MAX(fsblkcnt64_t) +#endif + +#ifndef FSBLKCNT_MAX +# define FSBLKCNT_MAX TYPE_MAX(fsblkcnt_t) +#endif + +#ifndef FSFILCNT64_MAX +# define FSFILCNT64_MAX TYPE_MAX(fsfilcnt64_t) +#endif + +#ifndef FSFILCNT_MAX +# define FSFILCNT_MAX TYPE_MAX(fsfilcnt_t) +#endif + +#ifndef GID_MAX +# define GID_MAX TYPE_MAX(gid_t) +#endif + +#ifndef ID_MAX +# define ID_MAX TYPE_MAX(id_t) +#endif + +#ifndef INO64_MAX +# define INO64_MAX TYPE_MAX(ino64_t) +#endif + +#ifndef INO_MAX +# define INO_MAX TYPE_MAX(ino_t) +#endif + +#ifndef KEY_MAX +# define KEY_MAX TYPE_MAX(key_t) +#endif + +#ifndef LOFF_MAX +# define LOFF_MAX TYPE_MAX(loff_t) +#endif + +#ifndef MODE_MAX +# define MODE_MAX TYPE_MAX(mode_t) +#endif + +#ifndef NLINK_MAX +# define NLINK_MAX TYPE_MAX(nlink_t) +#endif + +#ifndef OFF64_MAX +# define OFF64_MAX TYPE_MAX(off64_t) +#endif + +#ifndef OFF_MAX +# define OFF_MAX TYPE_MAX(off_t) +#endif + +#ifndef PID_MAX +# define PID_MAX TYPE_MAX(pid_t) +#endif + +#ifndef QUAD_MAX +# define QUAD_MAX TYPE_MAX(quad_t) +#endif + +#ifndef REGISTER_MAX +# define REGISTER_MAX TYPE_MAX(register_t) +#endif + +#ifndef RLIM64_MAX +# define RLIM64_MAX TYPE_MAX(rlim64_t) +#endif + +#ifndef RLIM_MAX +# define RLIM_MAX TYPE_MAX(rlim_t) +#endif + +#ifndef SOCKLEN_MAX +# define SOCKLEN_MAX TYPE_MAX(socklen_t) +#endif + +#ifndef SPEED_MAX +# define SPEED_MAX TYPE_MAX(speed_t) +#endif + +#ifndef SUSECONDS_MAX +# define SUSECONDS_MAX TYPE_MAX(suseconds_t) +#endif + +#ifndef TCFLAG_MAX +# define TCFLAG_MAX TYPE_MAX(tcflag_t) +#endif + +#ifndef TIME_MAX +# define TIME_MAX TYPE_MAX(time_t) +#endif + +#ifndef UID_MAX +# define UID_MAX TYPE_MAX(uid_t) +#endif + +#ifndef USECONDS_MAX +# define USECONDS_MAX TYPE_MAX(useconds_t) +#endif + +#ifndef U_QUAD_MAX +# define U_QUAD_MAX TYPE_MAX(u_quad_t) +#endif + + +#ifndef BLKCNT64_MIN +# define BLKCNT64_MIN TYPE_MIN(blkcnt64_t) +#endif + +#ifndef BLKCNT_MIN +# define BLKCNT_MIN TYPE_MIN(blkcnt_t) +#endif + +#ifndef BLKSIZE_MIN +# define BLKSIZE_MIN TYPE_MIN(blksize_t) +#endif + +#ifndef CC_MIN +# define CC_MIN TYPE_MIN(cc_t) +#endif + +#ifndef CLOCKID_MIN +# define CLOCKID_MIN TYPE_MIN(clockid_t) +#endif + +#ifndef CLOCK_MIN +# define CLOCK_MIN TYPE_MIN(clock_t) +#endif + +#ifndef DEV_MIN +# define DEV_MIN TYPE_MIN(dev_t) +#endif + +#ifndef FSBLKCNT64_MIN +# define FSBLKCNT64_MIN TYPE_MIN(fsblkcnt64_t) +#endif + +#ifndef FSBLKCNT_MIN +# define FSBLKCNT_MIN TYPE_MIN(fsblkcnt_t) +#endif + +#ifndef FSFILCNT64_MIN +# define FSFILCNT64_MIN TYPE_MIN(fsfilcnt64_t) +#endif + +#ifndef FSFILCNT_MIN +# define FSFILCNT_MIN TYPE_MIN(fsfilcnt_t) +#endif + +#ifndef GID_MIN +# define GID_MIN TYPE_MIN(gid_t) +#endif + +#ifndef ID_MIN +# define ID_MIN TYPE_MIN(id_t) +#endif + +#ifndef INO64_MIN +# define INO64_MIN TYPE_MIN(ino64_t) +#endif + +#ifndef INO_MIN +# define INO_MIN TYPE_MIN(ino_t) +#endif + +#ifndef KEY_MIN +# define KEY_MIN TYPE_MIN(key_t) +#endif + +#ifndef LOFF_MIN +# define LOFF_MIN TYPE_MIN(loff_t) +#endif + +#ifndef MODE_MIN +# define MODE_MIN TYPE_MIN(mode_t) +#endif + +#ifndef NLINK_MIN +# define NLINK_MIN TYPE_MIN(nlink_t) +#endif + +#ifndef OFF64_MIN +# define OFF64_MIN TYPE_MIN(off64_t) +#endif + +#ifndef OFF_MIN +# define OFF_MIN TYPE_MIN(off_t) +#endif + +#ifndef PID_MIN +# define PID_MIN TYPE_MIN(pid_t) +#endif + +#ifndef QUAD_MIN +# define QUAD_MIN TYPE_MIN(quad_t) +#endif + +#ifndef REGISTER_MIN +# define REGISTER_MIN TYPE_MIN(register_t) +#endif + +#ifndef RLIM64_MIN +# define RLIM64_MIN TYPE_MIN(rlim64_t) +#endif + +#ifndef RLIM_MIN +# define RLIM_MIN TYPE_MIN(rlim_t) +#endif + +#ifndef SOCKLEN_MIN +# define SOCKLEN_MIN TYPE_MIN(socklen_t) +#endif + +#ifndef SPEED_MIN +# define SPEED_MIN TYPE_MAX(speed_t) +#endif + +#ifndef SUSECONDS_MIN +# define SUSECONDS_MIN TYPE_MIN(suseconds_t) +#endif + +#ifndef TCFLAG_MIN +# define TCFLAG_MIN TYPE_MAX(tcflag_t) +#endif + +#ifndef TIME_MIN +# define TIME_MIN TYPE_MIN(time_t) +#endif + +#ifndef UID_MIN +# define UID_MIN TYPE_MIN(uid_t) +#endif + +#ifndef USECONDS_MIN +# define USECONDS_MIN TYPE_MIN(useconds_t) +#endif + +#ifndef U_QUAD_MIN +# define U_QUAD_MIN TYPE_MIN(u_quad_t) +#endif diff --git a/libsimple/env.h b/libsimple/env.h new file mode 100644 index 0000000..1c10a75 --- /dev/null +++ b/libsimple/env.h @@ -0,0 +1,93 @@ +/* See LICENSE file for copyright and license details. */ + +/** + * Read an environment variable, but handle it as undefined if empty + * + * @param var The environment variable's name + * @return The environment variable's value, `NULL` if empty or not defined + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) +static inline char * +libsimple_getenv_ne(const char *__name) +{ + char *__env = getenv(__name); + return (__env && *__env) ? __env : NULL; +} +#ifndef getenv_ne +# define getenv_ne libsimple_getenv_ne +#endif + +/** + * Read an environment variable, but handle it as empty if undefined + * + * @param var The environment variable's name + * @return The environment variable's value, "" if empty or not defined + */ +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __returns_nonnull__))) +static inline const char * +libsimple_getenv_e(const char *__name) +{ + const char *__env = getenv(__name); + return (__env && *__env) ? __env : ""; +} +#ifndef getenv_e +# define getenv_e libsimple_getenv_e +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_vputenvf(const char *, va_list); +#ifndef vputenvf +# define vputenvf libsimple_vputenvf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) +static inline int +libsimple_putenvf(const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + return libsimple_vputenvf(__fmt, __ap); + va_end(__ap); +} +#ifndef putenvf +# define putenvf libsimple_putenvf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +void libsimple_envputenvf(int, const char *, va_list); +#ifndef envputenvf +# define envputenvf libsimple_envputenvf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 2, 3)))) +static inline void +libsimple_enputenvf(int __status, const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + libsimple_envputenvf(__status, __fmt, __ap); + va_end(__ap); +} +#ifndef enputenvf +# define enputenvf libsimple_enputenvf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline void libsimple_evputenvf(const char *__fmt, va_list __ap) +{ libsimple_envputenvf(libsimple_default_failure_exit, __fmt, __ap); } +#ifndef evputenvf +# define evputenvf libsimple_evputenvf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __format__(__printf__, 1, 2)))) +static inline void +libsimple_eputenvf(const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + libsimple_evputenvf(__fmt, __ap); + va_end(__ap); +} +#ifndef eputenvf +# define eputenvf libsimple_eputenvf +#endif diff --git a/libsimple/malloc.h b/libsimple/malloc.h new file mode 100644 index 0000000..feb1944 --- /dev/null +++ b/libsimple/malloc.h @@ -0,0 +1,74 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_vmallocn(size_t __n, va_list __ap) +{ return libsimple_vmalloczn(0, __n, __ap); } +#ifndef vmallocn +# define vmallocn libsimple_vmallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_mallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmalloczn(0, __n, __ap); + va_end(__ap); +} +#ifndef mallocn +# define mallocn libsimple_mallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enmalloc(int, size_t); +#ifndef enmalloc +# define enmalloc libsimple_enmalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } +#ifndef envmallocn +# define envmallocn libsimple_envmallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enmallocn(int __status, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envmallocn(__status, __n, __ap); + va_end(__ap); +} +#ifndef enmallocn +# define enmallocn libsimple_enmallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_emalloc(size_t __n) +{ return libsimple_enmalloc(libsimple_default_failure_exit, __n); } +#ifndef emalloc +# define emalloc libsimple_emalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evmallocn(size_t __n, va_list __ap) +{ return libsimple_envmallocn(libsimple_default_failure_exit, __n, __ap); } +#ifndef evmallocn +# define evmallocn libsimple_evmallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_emallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evmallocn(__n, __ap); + va_end(__ap); +} +#ifndef emallocn +# define emallocn libsimple_emallocn +#endif diff --git a/libsimple/mallocz.h b/libsimple/mallocz.h new file mode 100644 index 0000000..80b2ef1 --- /dev/null +++ b/libsimple/mallocz.h @@ -0,0 +1,87 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2, 3), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_encalloc(int, size_t, size_t); + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enmalloc(int, size_t); + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +void *libsimple_vmalloczn(int, size_t, va_list); +#ifndef vmalloczn +# define vmalloczn libsimple_vmalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__))) +static inline void *libsimple_mallocz(int __clear, size_t __n) +{ return __clear ? calloc(1, __n) : malloc(__n); } +#ifndef mallocz +# define mallocz libsimple_mallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_malloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef malloczn +# define malloczn libsimple_malloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_enmallocz(int __status, int __clear, size_t __n) +{ return __clear ? libsimple_encalloc(__status, 1, __n) : libsimple_enmalloc(__status, __n); } +#ifndef enmallocz +# define enmallocz libsimple_enmallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +void *libsimple_envmalloczn(int, int, size_t, va_list); +#ifndef envmalloczn +# define envmalloczn libsimple_envmalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enmalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envmalloczn(__status, __clear, __n, __ap); + va_end(__ap); +} +#ifndef enmalloczn +# define enmalloczn libsimple_enmalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_emallocz(int __clear, size_t __n) +{ return libsimple_enmallocz(libsimple_default_failure_exit, __clear, __n); } +#ifndef emallocz +# define emallocz libsimple_emallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __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); } +#ifndef evmalloczn +# define evmalloczn libsimple_evmalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_emalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evmalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef emalloczn +# define emalloczn libsimple_emalloczn +#endif diff --git a/libsimple/mem.h b/libsimple/mem.h new file mode 100644 index 0000000..37913d0 --- /dev/null +++ b/libsimple/mem.h @@ -0,0 +1,64 @@ +/* See LICENSE file for copyright and license details. */ + +_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__, __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__))) +void *libsimple_memrmem(const void *, size_t, const void *, size_t); +#ifndef memrmem +# define memrmem libsimple_memrmem +#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__, __warn_unused_result__))) +static inline int libsimple_memeq(const void *__s1, const void *__s2, size_t __n) +{ return !memcmp(__s1, __s2, __n); } +#ifndef memeq +# define memeq libsimple_memeq +#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 + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +static inline void *libsimple_mempset(void *__s, int __c, size_t __n) +{ return &((char *)memset(__s, __c, __n))[__n]; } +#ifndef mempset +# define mempset libsimple_mempset +#endif diff --git a/libsimple/memalign.h b/libsimple/memalign.h new file mode 100644 index 0000000..046edd4 --- /dev/null +++ b/libsimple/memalign.h @@ -0,0 +1,82 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) +static inline void *libsimple_vmemalignn(size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_vmemalignzn(0, __alignment, __n, __ap); } +#ifndef vmemalignn +# define vmemalignn libsimple_vmemalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__))) +static inline void *libsimple_memalign(size_t __alignment, size_t __n) +{ return libsimple_memalignz(0, __alignment, __n); } +#ifndef memalign +# define memalign libsimple_memalign +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__))) +static inline void * +libsimple_memalignn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmemalignn(__alignment, __n, __ap); + va_end(__ap); +} +#ifndef memalignn +# define memalignn libsimple_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_enmemalign(int __status, size_t __alignment, size_t __n) +{ return libsimple_enmemalignz(__status, 0, __alignment, __n); } +#ifndef enmemalign +# define enmemalign libsimple_enmemalign +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_envmemalignn(int __status, size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envmemalignzn(__status, 0, __alignment, __n, __ap); } +#ifndef envmemalignn +# define envmemalignn libsimple_envmemalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enmemalignn(int __status, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envmemalignzn(__status, 0, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enmemalignn +# define enmemalignn libsimple_enmemalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ememalign(size_t __alignment, size_t __n) +{ return libsimple_enmemalign(libsimple_default_failure_exit, __alignment, __n); } +#ifndef ememalign +# define ememalign libsimple_ememalign +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evmemalignn(size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envmemalignn(libsimple_default_failure_exit, __alignment, __n, __ap); } +#ifndef evmemalignn +# define evmemalignn libsimple_evmemalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ememalignn(size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evmemalignn(__alignment, __n, __ap); + va_end(__ap); +} +#ifndef ememalignn +# define ememalignn libsimple_ememalignn +#endif diff --git a/libsimple/memalignz.h b/libsimple/memalignz.h new file mode 100644 index 0000000..8a20295 --- /dev/null +++ b/libsimple/memalignz.h @@ -0,0 +1,123 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) +static inline void * +libsimple_vmemalignzn(int __clear, size_t __alignment, size_t __n, va_list __ap) /* TODO test ([v]memalign[z]n) */ +{ + if (!__alignment || (__alignment & (__alignment - 1UL))) { + errno = EINVAL; + return NULL; + } + return libsimple_memalloc(0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_ALIGNMENT, __alignment, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef vmemalignzn +# define vmemalignzn libsimple_vmemalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__))) +static inline void * +libsimple_memalignz(int __clear, size_t __alignment, size_t __n) /* TODO test (memalign[z]) */ +{ + if (!__alignment || (__alignment & (__alignment - 1UL))) { + errno = EINVAL; + return NULL; + } + return libsimple_memalloc(__n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_ALIGNMENT, __alignment, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef memalignz +# define memalignz libsimple_memalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__))) +static inline void * +libsimple_memalignzn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmemalignzn(__clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef memalignzn +# define memalignzn libsimple_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __alloc_size__(4), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enmemalignz(int __status, int __clear, size_t __alignment, size_t __n) /* TODO test (e[n]memalign[z]) */ +{ + if (!__alignment || (__alignment & (__alignment - 1UL))) { + errno = EINVAL; + return NULL; + } + return libsimple_enmemalloc(__status, __n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_ALIGNMENT, __alignment, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef enmemalignz +# define enmemalignz libsimple_enmemalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envmemalignzn(int __status, int __clear, size_t __alignment, size_t __n, va_list __ap) /* TODO test (e[n][v]memalign[z]n) */ +{ + if (!__alignment || (__alignment & (__alignment - 1UL))) { + errno = EINVAL; + return NULL; + } + return libsimple_enmemalloc(__status, + 0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_ALIGNMENT, __alignment, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef envmemalignzn +# define envmemalignzn libsimple_envmemalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enmemalignzn(int __status, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envmemalignzn(__status, __clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enmemalignzn +# define enmemalignzn libsimple_enmemalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ememalignz(int __clear, size_t __alignment, size_t __n) +{ return libsimple_enmemalignz(libsimple_default_failure_exit, __alignment, __clear, __n); } +#ifndef ememalignz +# define ememalignz libsimple_ememalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evmemalignzn(int __clear, size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_envmemalignzn(libsimple_default_failure_exit, __alignment, __clear, __n, __ap); } +#ifndef evmemalignzn +# define evmemalignzn libsimple_evmemalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_align__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ememalignzn(int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evmemalignzn(__clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef ememalignzn +# define ememalignzn libsimple_ememalignzn +#endif diff --git a/libsimple/memalloc.h b/libsimple/memalloc.h new file mode 100644 index 0000000..181bc72 --- /dev/null +++ b/libsimple/memalloc.h @@ -0,0 +1,113 @@ +/* See LICENSE file for copyright and license details. */ + +enum libsimple_memalloc_option { + LIBSIMPLE_MEMALLOC_END, + LIBSIMPLE_MEMALLOC_ZERO_INIT, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, + LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO, + LIBSIMPLE_MEMALLOC_NULL_IF_ZERO, + LIBSIMPLE_MEMALLOC_ALIGNMENT, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, + LIBSIMPLE_MEMALLOC_PRODUCT_SIZE, + LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE, + LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, + LIBSIMPLE_MEMALLOC_VA_LIST, +}; +#define libsimple_arrayalloc_option libsimple_memalloc_option + +#define LIBSIMPLE_MEMALLOC_END LIBSIMPLE_MEMALLOC_END +#define LIBSIMPLE_MEMALLOC_ZERO_INIT LIBSIMPLE_MEMALLOC_ZERO_INIT +#define LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT +#define LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO +#define LIBSIMPLE_MEMALLOC_NULL_IF_ZERO LIBSIMPLE_MEMALLOC_NULL_IF_ZERO +#define LIBSIMPLE_MEMALLOC_ALIGNMENT LIBSIMPLE_MEMALLOC_ALIGNMENT +#define LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT +#define LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT +#define LIBSIMPLE_MEMALLOC_ELEMENT_SIZE LIBSIMPLE_MEMALLOC_ELEMENT_SIZE +#define LIBSIMPLE_MEMALLOC_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_PRODUCT_SIZE +#define LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE +#define LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE +#define LIBSIMPLE_MEMALLOC_VA_LIST LIBSIMPLE_MEMALLOC_VA_LIST + +#define LIBSIMPLE_ARRAYALLOC_END LIBSIMPLE_MEMALLOC_END +#define LIBSIMPLE_ARRAYALLOC_ZERO_INIT LIBSIMPLE_MEMALLOC_ZERO_INIT +#define LIBSIMPLE_ARRAYALLOC_CONDITIONAL_ZERO_INIT LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT +#define LIBSIMPLE_ARRAYALLOC_UNIQUE_IF_ZERO LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO +#define LIBSIMPLE_ARRAYALLOC_NULL_IF_ZERO LIBSIMPLE_MEMALLOC_NULL_IF_ZERO +#define LIBSIMPLE_ARRAYALLOC_ROUND_UP_SIZE_TO_ALIGNMENT LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT +#define LIBSIMPLE_ARRAYALLOC_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_PRODUCT_SIZE +#define LIBSIMPLE_ARRAYALLOC_VA_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE +#define LIBSIMPLE_ARRAYALLOC_1_VA_PRODUCT_SIZE LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE +#define LIBSIMPLE_ARRAYALLOC_VA_LIST LIBSIMPLE_MEMALLOC_VA_LIST + +#define libsimple_varrayalloc(TYPE, N, AP)\ + libsimple_memalloc(N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + LIBSIMPLE_MEMALLOC_VA_LIST, AP, LIBSIMPLE_MEMALLOC_END) + +#define libsimple_evarrayalloc(TYPE, N, AP)\ + libsimple_ememalloc(N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + LIBSIMPLE_MEMALLOC_VA_LIST, AP, LIBSIMPLE_MEMALLOC_END) + +#define libsimple_envarrayalloc(STATUS, TYPE, N, AP)\ + libsimple_enmemalloc(STATUS, N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + LIBSIMPLE_MEMALLOC_VA_LIST, AP, LIBSIMPLE_MEMALLOC_END) + +#define libsimple_arrayalloc(TYPE, N, ... /*, LIBSIMPLE_ARRAYALLOC_END */)\ + libsimple_memalloc(N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + __VA_ARGS__) + +#define libsimple_earrayalloc(TYPE, N, ... /*, LIBSIMPLE_ARRAYALLOC_END */)\ + libsimple_ememalloc(N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + __VA_ARGS__) + +#define libsimple_enarrayalloc(STATUS, TYPE, N, ... /*, LIBSIMPLE_ARRAYALLOC_END */)\ + libsimple_enmemalloc(STATUS, N, LIBSIMPLE_MEMALLOC_ELEMENT_SIZE, sizeof(TYPE),\ + LIBSIMPLE_MEMALLOC_ALIGNMENT, _Alignof(TYPE),\ + __VA_ARGS__) + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +void *libsimple_vmemalloc(size_t, va_list); + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +void *libsimple_envmemalloc(int, size_t, va_list); + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_evmemalloc(size_t __n, va_list __ap) +{ return libsimple_envmemalloc(libsimple_default_failure_exit, __n, __ap); } + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_memalloc(size_t __n, ... /*, LIBSIMPLE_MEMALLOC_END */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vmemalloc(__n, __ap); + va_end(__ap); +} + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_enmemalloc(int __status, size_t __n, ... /*, LIBSIMPLE_MEMALLOC_END */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envmemalloc(__status, __n, __ap); + va_end(__ap); +} + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_ememalloc(size_t __n, ... /*, LIBSIMPLE_MEMALLOC_END */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evmemalloc(__n, __ap); + va_end(__ap); +} diff --git a/libsimple/memdup.h b/libsimple/memdup.h new file mode 100644 index 0000000..44d3a2a --- /dev/null +++ b/libsimple/memdup.h @@ -0,0 +1,33 @@ +/* See LICENSE file for copyright and license details. */ + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_memdupa(s, n)\ + ({\ + const char *__s = (s);\ + size_t __n = (n);\ + char *__r = alloca(__n);\ + memcpy(__r, __s, __n);\ + }) +# ifndef memdupa +# define memdupa(s, n) libsimple_memdupa(s, n) +# endif +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2), __nonnull__, __warn_unused_result__))) +void *libsimple_memdup(const void *, size_t); +#ifndef memdup +# define memdup libsimple_memdup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enmemdup(int, const void *, size_t); +#ifndef enmemdup +# define enmemdup libsimple_enmemdup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_ememdup(const void *__s, size_t __n) +{ return enmemdup(libsimple_default_failure_exit, __s, __n); } +#ifndef ememdup +# define ememdup libsimple_ememdup +#endif diff --git a/libsimple/posix_memalign.h b/libsimple/posix_memalign.h new file mode 100644 index 0000000..dfe7a53 --- /dev/null +++ b/libsimple/posix_memalign.h @@ -0,0 +1,75 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline int libsimple_vposix_memalignn(void **__memptr, size_t __alignment, size_t __n, va_list __ap) +{ return libsimple_vposix_memalignzn(__memptr, 0, __alignment, __n, __ap); } +#ifndef vposix_memalignn +# define vposix_memalignn libsimple_vposix_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline int +libsimple_posix_memalignn(void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vposix_memalignn(__memptr, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef posix_memalignn +# define posix_memalignn libsimple_posix_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +static inline void libsimple_enposix_memalign(int __status, void **__memptr, size_t __alignment, size_t __n) +{ libsimple_enposix_memalignz(__status, __memptr, 0, __alignment, __n); } +#ifndef enposix_memalign +# define enposix_memalign libsimple_enposix_memalign +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +static inline void libsimple_envposix_memalignn(int __status, void **__memptr, size_t __alignment, size_t __n, va_list __ap) +{ libsimple_envposix_memalignzn(__status, __memptr, 0, __alignment, __n, __ap); } +#ifndef envposix_memalignn +# define envposix_memalignn libsimple_envposix_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +static inline void +libsimple_enposix_memalignn(int __status, void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + libsimple_envposix_memalignzn(__status, __memptr, 0, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enposix_memalignn +# define enposix_memalignn libsimple_enposix_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void libsimple_eposix_memalign(void **__memptr, size_t __alignment, size_t __n) +{ libsimple_enposix_memalign(libsimple_default_failure_exit, __memptr, __alignment, __n); } +#ifndef eposix_memalign +# define eposix_memalign libsimple_eposix_memalign +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void libsimple_evposix_memalignn(void **__memptr, size_t __alignment, size_t __n, va_list __ap) +{ libsimple_envposix_memalignn(libsimple_default_failure_exit, __memptr, __alignment, __n, __ap); } +#ifndef evposix_memalignn +# define evposix_memalignn libsimple_evposix_memalignn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void +libsimple_eposix_memalignn(void **__memptr, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + libsimple_evposix_memalignn(__memptr, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef eposix_memalignn +# define eposix_memalignn libsimple_eposix_memalignn +#endif diff --git a/libsimple/posix_memalignz.h b/libsimple/posix_memalignz.h new file mode 100644 index 0000000..94fc82c --- /dev/null +++ b/libsimple/posix_memalignz.h @@ -0,0 +1,85 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +int libsimple_vposix_memalignzn(void **, int, size_t, size_t, va_list); +#ifndef vposix_memalignzn +# define vposix_memalignzn libsimple_vposix_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline int +libsimple_posix_memalignz(void **__memptr, int __clear, size_t __alignment, size_t __n) +{ + int __ret = posix_memalign(__memptr, __alignment, __n); + if (!__ret && __clear) + memset(*__memptr, 0, __n); + return __ret; +} +#ifndef posix_memalignz +# define posix_memalignz libsimple_posix_memalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline int +libsimple_posix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vposix_memalignzn(__memptr, __clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef posix_memalignzn +# define posix_memalignzn libsimple_posix_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +void libsimple_enposix_memalignz(int, void **, int, size_t, size_t); +#ifndef enposix_memalignz +# define enposix_memalignz libsimple_enposix_memalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +void libsimple_envposix_memalignzn(int, void **, int, size_t, size_t, va_list); +#ifndef envposix_memalignzn +# define envposix_memalignzn libsimple_envposix_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +static inline void +libsimple_enposix_memalignzn(int __status, void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + libsimple_envposix_memalignzn(__status, __memptr, __clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef enposix_memalignzn +# define enposix_memalignzn libsimple_enposix_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void libsimple_eposix_memalignz(void **__memptr, int __clear, size_t __alignment, size_t __n) +{ libsimple_enposix_memalignz(libsimple_default_failure_exit, __memptr, __clear, __alignment, __n); } +#ifndef eposix_memalignz +# define eposix_memalignz libsimple_eposix_memalignz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void libsimple_evposix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, va_list __ap) +{ libsimple_envposix_memalignzn(libsimple_default_failure_exit, __memptr, __clear, __alignment, __n, __ap); } +#ifndef evposix_memalignzn +# define evposix_memalignzn libsimple_evposix_memalignzn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +static inline void +libsimple_eposix_memalignzn(void **__memptr, int __clear, size_t __alignment, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + libsimple_evposix_memalignzn(__memptr, __clear, __alignment, __n, __ap); + va_end(__ap); +} +#ifndef eposix_memalignzn +# define eposix_memalignzn libsimple_eposix_memalignzn +#endif diff --git a/libsimple/printf.h b/libsimple/printf.h new file mode 100644 index 0000000..f1e0b0d --- /dev/null +++ b/libsimple/printf.h @@ -0,0 +1,122 @@ +/* See LICENSE file for copyright and license details. */ + +_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 + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_asprintfa(__fmt, ...)\ + ({\ + const char *__f = (__fmt);\ + char *__ret = NULL;\ + int __r = snprintf(NULL, 0, __f, __VA_ARGS__);\ + if (__r >= 0) {\ + __ret = alloca((size_t)__r + 1);\ + sprintf(__ret, __f, __VA_ARGS__);\ + }\ + __ret;\ + }) +# ifndef asprintfa +# define asprintfa(...) libsimple_asprintfa(__VA_ARGS__) +# endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_vasprintfa(__fmt, __ap)\ + ({\ + const char *__f = (__fmt);\ + va_list __a1;\ + va_list __a2;\ + char *__ret = NULL;\ + int __r;\ + va_copy(__a1, __ap);\ + va_copy(__a2, __a1);\ + __r = vsnprintf(NULL, 0, __f, __a1);\ + if (__r >= 0) {\ + __ret = alloca((size_t)__r + 1);\ + vsprintf(__ret, __f, __a2);\ + }\ + va_end(__a2);\ + va_end(__a1);\ + __ret;\ + }) +# ifndef vasprintfa +# define vasprintfa(fmt, ap) libsimple_vasprintfa(fmt, ap) +# endif +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1)))) +void libsimple_vweprintf(const char *, va_list); +#ifndef vweprintf +# define vweprintf libsimple_vweprintf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2)))) +static inline void +libsimple_weprintf(const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + libsimple_vweprintf(__fmt, __ap); + va_end(__ap); +} +#ifndef weprintf +# define weprintf libsimple_weprintf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __noreturn__))) +static inline void +libsimple_venprintf(int __status, const char *__fmt, va_list __ap) +{ + libsimple_vweprintf(__fmt, __ap); + exit(__status); +} +#ifndef venprintf +# define venprintf libsimple_venprintf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2), __format__(__printf__, 2, 3), __noreturn__))) +static inline void +libsimple_enprintf(int __status, const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + libsimple_venprintf(__status, __fmt, __ap); + va_end(__ap); +} +#ifndef enprintf +# define enprintf libsimple_enprintf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __noreturn__))) +static inline void +libsimple_veprintf(const char *__fmt, va_list __ap) +{ + libsimple_vweprintf(__fmt, __ap); + exit(libsimple_default_failure_exit); +} +#ifndef veprintf +# define veprintf libsimple_veprintf +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1), __format__(__printf__, 1, 2), __noreturn__))) +static inline void +libsimple_eprintf(const char *__fmt, ...) +{ + va_list __ap; + va_start(__ap, __fmt); + libsimple_veprintf(__fmt, __ap); + va_end(__ap); +} +#ifndef eprintf +# define eprintf libsimple_eprintf +#endif diff --git a/libsimple/pvalloc.h b/libsimple/pvalloc.h new file mode 100644 index 0000000..876366b --- /dev/null +++ b/libsimple/pvalloc.h @@ -0,0 +1,82 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_vpvallocn(size_t __n, va_list __ap) +{ return libsimple_vpvalloczn(0, __n, __ap); } +#ifndef vpvallocn +# define vpvallocn libsimple_vpvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_pvalloc(size_t __n) +{ return libsimple_pvallocz(0, __n); } +#ifndef pvalloc +# define pvalloc libsimple_pvalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_pvallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vpvallocn(__n, __ap); + va_end(__ap); +} +#ifndef pvallocn +# define pvallocn libsimple_pvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_enpvalloc(int __status, size_t __n) +{ return libsimple_enpvallocz(__status, 0, __n); } +#ifndef enpvalloc +# define enpvalloc libsimple_enpvalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_envpvallocn(int __status, size_t __n, va_list __ap) +{ return libsimple_envpvalloczn(__status, 0, __n, __ap); } +#ifndef envpvallocn +# define envpvallocn libsimple_envpvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enpvallocn(int __status, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envpvalloczn(__status, 0, __n, __ap); + va_end(__ap); +} +#ifndef enpvallocn +# define enpvallocn libsimple_enpvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_epvalloc(size_t __n) +{ return libsimple_enpvalloc(libsimple_default_failure_exit, __n); } +#ifndef epvalloc +# define epvalloc libsimple_epvalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evpvallocn(size_t __n, va_list __ap) +{ return libsimple_envpvallocn(libsimple_default_failure_exit, __n, __ap); } +#ifndef evpvallocn +# define evpvallocn libsimple_evpvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_epvallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evpvallocn(__n, __ap); + va_end(__ap); +} +#ifndef epvallocn +# define epvallocn libsimple_epvallocn +#endif diff --git a/libsimple/pvallocz.h b/libsimple/pvallocz.h new file mode 100644 index 0000000..f1e58ed --- /dev/null +++ b/libsimple/pvallocz.h @@ -0,0 +1,111 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_vpvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]pvalloc[z]n) */ +{ + return libsimple_memalloc(0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef vpvalloczn +# define vpvalloczn libsimple_vpvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__))) +static inline void * +libsimple_pvallocz(int __clear, size_t __n) /* TODO test (pvalloc[z]) */ +{ + return libsimple_memalloc(__n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef pvallocz +# define pvallocz libsimple_pvallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_pvalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vpvalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef pvalloczn +# define pvalloczn libsimple_pvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enpvallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]pvalloc[z]) */ +{ + return libsimple_enmemalloc(__status, __n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef enpvallocz +# define enpvallocz libsimple_enpvallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envpvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* TODO test (e[n][v]pvalloc[z]n) */ +{ + return libsimple_enmemalloc(__status, + 0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef envpvalloczn +# define envpvalloczn libsimple_envpvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enpvalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envpvalloczn(__status, __clear, __n, __ap); + va_end(__ap); +} +#ifndef enpvalloczn +# define enpvalloczn libsimple_enpvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_epvallocz(int __clear, size_t __n) +{ return libsimple_enpvallocz(libsimple_default_failure_exit, __clear, __n); } +#ifndef epvallocz +# define epvallocz libsimple_epvallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evpvalloczn(int __clear, size_t __n, va_list __ap) +{ return libsimple_envpvalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } +#ifndef evpvalloczn +# define evpvalloczn libsimple_evpvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_epvalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evpvalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef epvalloczn +# define epvalloczn libsimple_epvalloczn +#endif diff --git a/libsimple/realloc.h b/libsimple/realloc.h new file mode 100644 index 0000000..3e2fece --- /dev/null +++ b/libsimple/realloc.h @@ -0,0 +1,72 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +void *libsimple_vreallocn(void *, size_t, va_list); +#ifndef vreallocn +# define vreallocn libsimple_vreallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__))) +static inline void * +libsimple_reallocn(void *__ptr, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vreallocn(__ptr, __n, __ap); + va_end(__ap); +} +#ifndef reallocn +# define reallocn libsimple_reallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +void *libsimple_enrealloc(int, void *, size_t); +#ifndef enrealloc +# define enrealloc libsimple_enrealloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) +void *libsimple_envreallocn(int, void *, size_t, va_list); +#ifndef envreallocn +# define envreallocn libsimple_envreallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_enreallocn(int __status, void *__ptr, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envreallocn(__status, __ptr, __n, __ap); + va_end(__ap); +} +#ifndef enreallocn +# define enreallocn libsimple_enreallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_erealloc(void *__ptr, size_t __n) +{ return enrealloc(libsimple_default_failure_exit, __ptr, __n); } +#ifndef erealloc +# define erealloc libsimple_erealloc +#endif + +_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); } +#ifndef evreallocn +# define evreallocn libsimple_evreallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_ereallocn(void *__ptr, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evreallocn(__ptr, __n, __ap); + va_end(__ap); +} +#ifndef ereallocn +# define ereallocn libsimple_ereallocn +#endif diff --git a/libsimple/str.h b/libsimple/str.h new file mode 100644 index 0000000..cacec57 --- /dev/null +++ b/libsimple/str.h @@ -0,0 +1,99 @@ +/* See LICENSE file for copyright and license details. */ + +_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__))) +int libsimple_strstarts(const char *, const char *); +#ifndef strstarts +# define strstarts libsimple_strstarts +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int libsimple_strcasestarts(const char *__s, const char *__t) +{ return !strncasecmp(__s, __t, strlen(__t)); } +#ifndef strcasestarts +# define strcasestarts libsimple_strcasestarts +#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__))) +int libsimple_strcaseends(const char *, const char *); +#ifndef strcaseends +# define strcaseends libsimple_strcaseends +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strrstr(const char *, const char *); +#ifndef strrstr +# define strrstr libsimple_strrstr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strcasestr(const char *, const char *); +#ifndef strcasestr +# define strcasestr libsimple_strcasestr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strrcasestr(const char *, const char *); +#ifndef strrcasestr +# define strrcasestr libsimple_strrcasestr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strcmpnul(const char *__a, const char *__b) +{ return (!__a || !__b) ? !__b - !__a : strcmp(__a, __b); } +#ifndef strcmpnul +# define strcmpnul libsimple_strcmpnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strcasecmpnul(const char *__a, const char *__b) +{ return (!__a || !__b) ? !__b - !__a : strcasecmp(__a, __b); } +#ifndef strcasecmpnul +# define strcasecmpnul libsimple_strcasecmpnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int libsimple_streq(const char *__a, const char *__b) +{ return !strcmp(__a, __b); } +#ifndef streq +# define streq libsimple_streq +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_streqnul(const char *__a, const char *__b) +{ return !strcmpnul(__a, __b); } +#ifndef streqnul +# define streqnul libsimple_streqnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int libsimple_strcaseeq(const char *__a, const char *__b) +{ return !strcasecmp(__a, __b); } +#ifndef strcaseeq +# define strcaseeq libsimple_strcaseeq +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strcaseeqnul(const char *__a, const char *__b) +{ return !strcasecmpnul(__a, __b); } +#ifndef strcaseeqnul +# define strcaseeqnul libsimple_strcaseeqnul +#endif diff --git a/libsimple/strdup.h b/libsimple/strdup.h new file mode 100644 index 0000000..1397893 --- /dev/null +++ b/libsimple/strdup.h @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_strdupa(s)\ + ({\ + const char *__s = (s);\ + size_t __n = strlen(__s) + 1;\ + char *__r = alloca(__n);\ + memcpy(__r, __s, __n);\ + }) +# ifndef strdupa +# define strdupa(s) libsimple_strdupa(s) +# endif +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __assume_aligned__(1), __nonnull__, __warn_unused_result__, __returns_nonnull__))) +char *libsimple_enstrdup(int, const char *); +#ifndef enstrdup +# define enstrdup libsimple_enstrdup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __assume_aligned__(1), __nonnull__, __warn_unused_result__, __returns_nonnull__))) +static inline char *libsimple_estrdup(const char *__s) +{ return enstrdup(libsimple_default_failure_exit, __s); } +#ifndef estrdup +# define estrdup libsimple_estrdup +#endif diff --git a/libsimple/strn.h b/libsimple/strn.h new file mode 100644 index 0000000..e2dffdb --- /dev/null +++ b/libsimple/strn.h @@ -0,0 +1,74 @@ +/* See LICENSE file for copyright and license details. */ + +/* TODO strnchrnul */ +/* TODO strnend */ +/* TODO strnstarts */ +/* TODO strncasestarts */ +/* TODO strnends */ +/* TODO strncaseends */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strnstr(const char *, const char *, size_t); +#ifndef strnstr +# define strnstr libsimple_strnstr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strrnstr(const char *, const char *, size_t); +#ifndef strrnstr +# define strrnstr libsimple_strrnstr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strncasestr(const char *, const char *, size_t); +#ifndef strncasestr +# define strncasestr libsimple_strncasestr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +char *libsimple_strrncasestr(const char *, const char *, size_t); +#ifndef strrncasestr +# define strrncasestr libsimple_strrncasestr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strncmpnul(const char *__a, const char *__b, size_t __n) +{ return (!__a || !__b) ? !__b - !__a : strncmp(__a, __b, __n); } +#ifndef strncmpnul +# define strncmpnul libsimple_strncmpnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strncasecmpnul(const char *__a, const char *__b, size_t __n) +{ return (!__a || !__b) ? !__b - !__a : strncasecmp(__a, __b, __n); } +#ifndef strncasecmpnul +# define strncasecmpnul libsimple_strncasecmpnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int libsimple_strneq(const char *__a, const char *__b, size_t __n) +{ return !strncmp(__a, __b, __n); } +#ifndef strneq +# define strneq libsimple_strneq +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strneqnul(const char *__a, const char *__b, size_t __n) +{ return !strncmpnul(__a, __b, __n); } +#ifndef strneqnul +# define strneqnul libsimple_strneqnul +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __nonnull__, __warn_unused_result__))) +static inline int libsimple_strncaseeq(const char *__a, const char *__b, size_t __n) +{ return !strncasecmp(__a, __b, __n); } +#ifndef strncaseeq +# define strncaseeq libsimple_strncaseeq +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__pure__, __warn_unused_result__))) +static inline int libsimple_strncaseeqnul(const char *__a, const char *__b, size_t __n) +{ return !strncasecmpnul(__a, __b, __n); } +#ifndef strncaseeqnul +# define strncaseeqnul libsimple_strncaseeqnul +#endif diff --git a/libsimple/strndup.h b/libsimple/strndup.h new file mode 100644 index 0000000..28ec293 --- /dev/null +++ b/libsimple/strndup.h @@ -0,0 +1,38 @@ +/* See LICENSE file for copyright and license details. */ + +#if defined(__GNUC__) || defined(__clang__) +# define libsimple_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;\ + }) +# ifndef strndupa +# define strndupa(s, n) libsimple_strndupa(s, n) +# endif +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __assume_aligned__(1), __nonnull__, __warn_unused_result__))) +char *libsimple_strndup(const char *, size_t); +#ifndef strndup +# define strndup libsimple_strndup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __assume_aligned__(1), __nonnull__, __warn_unused_result__, __returns_nonnull__))) +char *libsimple_enstrndup(int, const char *, size_t); +#ifndef enstrndup +# define enstrndup libsimple_enstrndup +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __assume_aligned__(1), __nonnull__, __warn_unused_result__, __returns_nonnull__))) +static inline char *libsimple_estrndup(const char *__s, size_t __n) +{ return enstrndup(libsimple_default_failure_exit, __s, __n); } +#ifndef estrndup +# define estrndup libsimple_estrndup +#endif diff --git a/libsimple/time.h b/libsimple/time.h new file mode 100644 index 0000000..7304030 --- /dev/null +++ b/libsimple/time.h @@ -0,0 +1,149 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_sumtimespec(struct timespec *, const struct timespec *, const struct timespec *); +#ifndef sumtimespec +# define sumtimespec libsimple_sumtimespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_difftimespec(struct timespec *, const struct timespec *, const struct timespec *); +#ifndef difftimespec +# define difftimespec libsimple_difftimespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_multimespec(struct timespec *, const struct timespec *, int); +#ifndef multimespec +# define multimespec libsimple_multimespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) +static inline int +libsimple_cmptimespec(const struct timespec *__a, const struct timespec *__b) +{ + if (__a->tv_sec != __b->tv_sec) + return __a->tv_sec < __b->tv_sec ? -1 : +1; + return __a->tv_nsec < __b->tv_nsec ? -1 : __a->tv_nsec > __b->tv_nsec; +} +#ifndef cmptimespec +# define cmptimespec libsimple_cmptimespec +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_sumtimeval(struct timeval *, const struct timeval *, const struct timeval *); +#ifndef sumtimeval +# define sumtimeval libsimple_sumtimeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_difftimeval(struct timeval *, const struct timeval *, const struct timeval *); +#ifndef difftimeval +# define difftimeval libsimple_difftimeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_multimeval(struct timeval *, const struct timeval *, int); +#ifndef multimeval +# define multimeval libsimple_multimeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__))) +static inline int +libsimple_cmptimeval(const struct timeval *__a, const struct timeval *__b) +{ + if (__a->tv_sec != __b->tv_sec) + return __a->tv_sec < __b->tv_sec ? -1 : +1; + return __a->tv_usec < __b->tv_usec ? -1 : __a->tv_usec > __b->tv_usec; +} +#ifndef cmptimeval +# define cmptimeval libsimple_cmptimeval +#endif + + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline void +libsimple_timeval2timespec(struct timespec *restrict __ts, const struct timeval *restrict __tv) +{ + __ts->tv_sec = __tv->tv_sec; + __ts->tv_nsec = __tv->tv_usec; + __ts->tv_nsec *= 1000L; +} +#ifndef timeval2timespec +# define timeval2timespec libsimple_timeval2timespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +int libsimple_timespec2timeval(struct timeval *restrict, const struct timespec *restrict); +#ifndef timespec2timeval +# define timespec2timeval libsimple_timespec2timeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) +int libsimple_strtotimespec(struct timespec *restrict, const char *restrict, char **restrict); +#ifndef strtotimespec +# define strtotimespec libsimple_strtotimespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(1, 2)))) +int libsimple_strtotimeval(struct timeval *restrict, const char *restrict, char **restrict); +#ifndef strtotimeval +# define strtotimeval libsimple_strtotimeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +char *libsimple_timespectostr(char *restrict, const struct timespec *restrict); +#ifndef timespectostr +# define timespectostr libsimple_timespectostr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__(2)))) +char *libsimple_timevaltostr(char *restrict, const struct timeval *restrict); +#ifndef timevaltostr +# define timevaltostr libsimple_timevaltostr +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline double +libsimple_timespectodouble(const struct timespec *__ts) +{ + double __ret = (double)(__ts->tv_nsec); + __ret /= (double)1000000000L; + __ret += (double)(__ts->tv_sec); + return __ret; +} +#ifndef timespectodouble +# define timespectodouble libsimple_timespectodouble +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +static inline double +libsimple_timevaltodouble(const struct timeval *__tv) +{ + double __ret = (double)(__tv->tv_usec); + __ret /= (double)1000000L; + __ret += (double)(__tv->tv_sec); + return __ret; +} +#ifndef timevaltodouble +# define timevaltodouble libsimple_timevaltodouble +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +void libsimple_doubletotimespec(struct timespec *, double); +#ifndef doubletotimespec +# define doubletotimespec libsimple_doubletotimespec +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__nonnull__))) +void libsimple_doubletotimeval(struct timeval *, double); +#ifndef doubletotimeval +# define doubletotimeval libsimple_doubletotimeval +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__returns_nonnull__, __nonnull__))) +char *libsimple_minimise_number_string(char *); +#ifndef minimise_number_string +# define minimise_number_string libsimple_minimise_number_string +#endif diff --git a/libsimple/valloc.h b/libsimple/valloc.h new file mode 100644 index 0000000..02d301a --- /dev/null +++ b/libsimple/valloc.h @@ -0,0 +1,82 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void *libsimple_vvallocn(size_t __n, va_list __ap) +{ return libsimple_vvalloczn(0, __n, __ap); } +#ifndef vvallocn +# define vvallocn libsimple_vvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1), __warn_unused_result__))) +static inline void *libsimple_valloc(size_t __n) +{ return libsimple_vallocz(0, __n); } +#ifndef valloc +# define valloc libsimple_valloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_vallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vvallocn(__n, __ap); + va_end(__ap); +} +#ifndef vallocn +# define vallocn libsimple_vallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_envalloc(int __status, size_t __n) +{ return libsimple_envallocz(__status, 0, __n); } +#ifndef envalloc +# define envalloc libsimple_envalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_envvallocn(int __status, size_t __n, va_list __ap) +{ return libsimple_envvalloczn(__status, 0, __n, __ap); } +#ifndef envvallocn +# define envvallocn libsimple_envvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envallocn(int __status, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envvalloczn(__status, 0, __n, __ap); + va_end(__ap); +} +#ifndef envallocn +# define envallocn libsimple_envallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(1), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evalloc(size_t __n) +{ return libsimple_envalloc(libsimple_default_failure_exit, __n); } +#ifndef evalloc +# define evalloc libsimple_evalloc +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evvallocn(size_t __n, va_list __ap) +{ return libsimple_envvallocn(libsimple_default_failure_exit, __n, __ap); } +#ifndef evvallocn +# define evvallocn libsimple_evvallocn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_evallocn(size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evvallocn(__n, __ap); + va_end(__ap); +} +#ifndef evallocn +# define evallocn libsimple_evallocn +#endif diff --git a/libsimple/vallocz.h b/libsimple/vallocz.h new file mode 100644 index 0000000..d32598e --- /dev/null +++ b/libsimple/vallocz.h @@ -0,0 +1,107 @@ +/* See LICENSE file for copyright and license details. */ + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_vvalloczn(int __clear, size_t __n, va_list __ap) /* TODO test ([v]valloc[z]n) */ +{ + return libsimple_memalloc(0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef vvalloczn +# define vvalloczn libsimple_vvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__))) +static inline void * +libsimple_vallocz(int __clear, size_t __n) /* TODO test (valloc[z]) */ +{ + return libsimple_memalloc(__n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef vallocz +# define vallocz libsimple_vallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__))) +static inline void * +libsimple_valloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_vvalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef valloczn +# define valloczn libsimple_valloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(3), __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envallocz(int __status, int __clear, size_t __n) /* TODO test (e[n]valloc[z]) */ +{ + return libsimple_enmemalloc(__status, __n, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef envallocz +# define envallocz libsimple_envallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envvalloczn(int __status, int __clear, size_t __n, va_list __ap) /* TODO test (e[n][v]valloc[z]n, e[n]vallocn) */ +{ + return libsimple_enmemalloc(__status, + 0, LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE, __n, __ap, + LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT, __clear, + LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT, + LIBSIMPLE_MEMALLOC_END); +} +#ifndef envvalloczn +# define envvalloczn libsimple_envvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_envalloczn(int __status, int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_envvalloczn(__status, __clear, __n, __ap); + va_end(__ap); +} +#ifndef envalloczn +# define envalloczn libsimple_envalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __alloc_size__(2), __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evallocz(int __clear, size_t __n) +{ return libsimple_envallocz(libsimple_default_failure_exit, __clear, __n); } +#ifndef evallocz +# define evallocz libsimple_evallocz +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void *libsimple_evvalloczn(int __clear, size_t __n, va_list __ap) +{ return libsimple_envvalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } +#ifndef evvalloczn +# define evvalloczn libsimple_evvalloczn +#endif + +_LIBSIMPLE_GCC_ONLY(__attribute__((__malloc__, __warn_unused_result__, __returns_nonnull__))) +static inline void * +libsimple_evalloczn(int __clear, size_t __n, ... /*, (size_t)0 */) +{ + va_list __ap; + va_start(__ap, __n); + return libsimple_evvalloczn(__clear, __n, __ap); + va_end(__ap); +} +#ifndef evalloczn +# define evalloczn libsimple_evalloczn +#endif @@ -13,7 +13,7 @@ libsimple_strndup(const char *s, size_t n) errno = ENOMEM; return NULL; } - if (!(ret = malloc(n + 1))) + if (!(ret = aligned_alloc(1, n + 1))) return NULL; memcpy(ret, s, n); ret[n] = '\0'; @@ -27,6 +27,7 @@ libsimple_strndup(const char *s, size_t n) int main(void) { + struct allocinfo *info; const char *s = "test"; void *p; @@ -35,6 +36,10 @@ main(void) assert(!strcmpnul(p, "test")); memset(p, 0, 5); assert(!strcmpnul(s, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->alignment == 1); + } free(p); p = libsimple_strndup(s, 3); @@ -42,6 +47,10 @@ main(void) assert(!strcmpnul(p, "tes")); memset(p, 0, 4); assert(!strcmpnul(s, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->alignment == 1); + } free(p); p = libsimple_strndup(s, 0); @@ -49,6 +58,10 @@ main(void) assert(!strcmpnul(p, "")); memset(p, 0, 1); assert(!strcmpnul(s, "test")); + if (have_custom_malloc()) { + assert((info = get_allocinfo(p))); + assert(info->alignment == 1); + } free(p); return 0; @@ -2,10 +2,12 @@ #include "libsimple.h" #include "test.h" #include <sys/syscall.h> -#include <malloc.h> #undef strndup #undef memdup +#undef memalign +#undef valloc +#undef pvalloc char *argv0 = (char []){"<test>"}; @@ -21,6 +23,7 @@ volatile int stderr_real = 0; volatile int stderr_ok = 0; static volatile int custom_malloc = 0; +static volatile void *just_alloced = NULL; size_t @@ -59,59 +62,6 @@ get_allocinfo(void *ptr) void * -malloc(size_t size) -{ - size_t alignment = get_pagesize(); - while (alignment < sizeof(long long int)) - alignment *= 2; - while (alignment < sizeof(long double)) - alignment *= 2; - return memalign(alignment, size); -} - - -void * -calloc(size_t nelem, size_t elsize) -{ - struct allocinfo *info; - void *volatile ret; - assert(nelem && elsize); /* unspecified behaviour otherwise */ - if (nelem > SIZE_MAX / elsize) { - errno = ENOMEM; - return NULL; - } - ret = malloc(nelem * elsize); - if (!ret) - return NULL; - memset(ret, 0, nelem * elsize); - info = get_allocinfo(ret); - info->zeroed = nelem * elsize; - return ret; -} - - -void * -realloc(void *ptr, size_t size) -{ - struct allocinfo *info; - void *volatile ret; - size_t n; - assert(size); /* unspecified behaviour otherwise */ - if (!ptr) - return malloc(size); - ret = malloc(size); - if (!ret) - return malloc; - info = get_allocinfo(ret); - n = MIN(size, info->size); - info->zeroed = MIN(n, info->zeroed); - memcpy(ret, ptr, n); - free(ptr); - return ret; -} - - -void * memalign(size_t alignment, size_t size) { struct allocinfo *info; @@ -156,14 +106,69 @@ memalign(size_t alignment, size_t size) info->zeroed = 0; info->refcount = 1; + just_alloced = ptr; return ptr; enomem: + just_alloced = NULL; errno = ENOMEM; return NULL; } +void * +malloc(size_t size) +{ + size_t alignment = get_pagesize(); + while (alignment < sizeof(long long int)) + alignment *= 2; + while (alignment < sizeof(long double)) + alignment *= 2; + return memalign(alignment, size); +} + + +void * +calloc(size_t nelem, size_t elsize) +{ + struct allocinfo *info; + void *volatile ret; + assert(nelem && elsize); /* unspecified behaviour otherwise */ + if (nelem > SIZE_MAX / elsize) { + errno = ENOMEM; + return NULL; + } + ret = malloc(nelem * elsize); + if (!ret) + return NULL; + memset(ret, 0, nelem * elsize); + info = get_allocinfo(ret); + info->zeroed = nelem * elsize; + return ret; +} + + +void * +realloc(void *ptr, size_t size) +{ + struct allocinfo *info; + void *volatile ret; + size_t n; + assert(size); /* unspecified behaviour otherwise */ + if (!ptr) + return malloc(size); + ret = malloc(size); + if (!ret) + return malloc; + info = get_allocinfo(ret); + n = MIN(size, info->size); + info->zeroed = MIN(n, info->zeroed); + memcpy(ret, ptr, n); + free(ptr); + return ret; +} + + int posix_memalign(void **memptr, size_t alignment, size_t size) { @@ -171,8 +176,9 @@ posix_memalign(void **memptr, size_t alignment, size_t size) void *volatile *volatile ptrp = memptr; assert(!(alignment % sizeof(void *))); assert(ptrp); + errno = 0; *memptr = memalign(alignment, size); - ret = *memptr ? ENOMEM : 0; + ret = errno; errno = saved_errno; return ret; } @@ -237,6 +243,21 @@ free(void *ptr) } +void * +memset(void *s, int c, size_t n) +{ + char *str = s; + struct allocinfo *info; + if (just_alloced && s == just_alloced) { + info = get_allocinfo(s); + info->zeroed = MAX(info->zeroed, n); + } + while (n--) + str[n] = (char)c; + return s; +} + + void exit(int status) { diff --git a/vmemalloc.c b/vmemalloc.c new file mode 100644 index 0000000..855d078 --- /dev/null +++ b/vmemalloc.c @@ -0,0 +1,232 @@ +/* See LICENSE file for copyright and license details. */ +#include "libsimple.h" +#ifndef TEST + + +struct memalloc_state { + int zero_init; + int if_zero; + int round_up_size; + int have_size; + size_t alignment; + size_t elem_size; + size_t size_prod; +}; + +static int +vmemalloc_parse_size_prod(struct memalloc_state *state, size_t n, size_t arg, va_list ap) +{ + if (state->have_size++) + goto inval; + state->elem_size = arg; + if (n) { + for (n--; n--;) { + arg = va_arg(ap, size_t); + if (!state->elem_size) + continue; + if (arg > SIZE_MAX / state->elem_size) { + errno = ENOMEM; + return -1; + } + state->elem_size *= arg; + } + } else { + if (!arg) + goto inval; + for (;;) { + arg = va_arg(ap, size_t); + if (!arg) + break; + if (arg > SIZE_MAX / state->elem_size) { + errno = ENOMEM; + return -1; + } + state->elem_size *= arg; + } + } + + return 0; +inval: + errno = EINVAL; + return -1; +} + +static int +vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list ap) +{ + enum libsimple_memalloc_option opt; + long int page_size; + va_list *subapp; + size_t arg; + + for (;;) { + opt = va_arg(ap, enum libsimple_memalloc_option); + switch (opt) { + case LIBSIMPLE_MEMALLOC_END: + return 0; + + case LIBSIMPLE_MEMALLOC_ZERO_INIT: + if (state->zero_init >= 0) + goto inval; + state->zero_init = 1; + break; + + case LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT: + if (state->zero_init >= 0) + goto inval; + state->zero_init = va_arg(ap, int); + state->zero_init = !!state->zero_init; + break; + + case LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO: + case LIBSIMPLE_MEMALLOC_NULL_IF_ZERO: + if (state->if_zero >= 0) + goto inval; + state->if_zero = (opt == LIBSIMPLE_MEMALLOC_UNIQUE_IF_ZERO); + break; + + case LIBSIMPLE_MEMALLOC_ALIGNMENT: + if (state->alignment) + goto inval; + state->alignment = va_arg(ap, size_t); + if (!state->alignment) + goto inval; + break; + + case LIBSIMPLE_MEMALLOC_PAGE_ALIGNMENT: + if (state->alignment) + goto inval; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) + return -1; + state->alignment = (size_t)page_size; + break; + + case LIBSIMPLE_MEMALLOC_ROUND_UP_SIZE_TO_ALIGNMENT: + if (state->round_up_size++) + goto inval; + break; + + case LIBSIMPLE_MEMALLOC_ELEMENT_SIZE: + if (state->elem_size) + goto inval; + state->elem_size = va_arg(ap, size_t); + if (!state->elem_size) + goto inval; + break; + + case LIBSIMPLE_MEMALLOC_PRODUCT_SIZE: + arg = va_arg(ap, size_t); + if (vmemalloc_parse_size_prod(state, n, arg, ap)) + return -1; + break; + + case LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE: + subapp = va_arg(ap, va_list *); + arg = va_arg(*subapp, size_t); + if (vmemalloc_parse_size_prod(state, n, arg, *subapp)) + return -1; + break; + + case LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE: + arg = va_arg(ap, size_t); + subapp = va_arg(ap, va_list *); + if (vmemalloc_parse_size_prod(state, n, arg, *subapp)) + return -1; + break; + + case LIBSIMPLE_MEMALLOC_VA_LIST: + subapp = va_arg(ap, va_list *); + if (vmemalloc_parse_args(state, n, *subapp)) + return -1; + break; + + default: + goto inval; + } + } + + return 0; +inval: + errno = EINVAL; + return -1; +} + +void * +libsimple_vmemalloc(size_t n, va_list ap) /* TODO test ([v]{mem,array}alloc) */ +{ + struct memalloc_state state; + size_t misalignment, size; + void *ptr = NULL; + int saved_errno; + + state.zero_init = -1; + state.if_zero = -1; + state.round_up_size = 0; + state.have_size = 0; + state.alignment = 0; + state.elem_size = 0; + state.size_prod = 1; + + if (vmemalloc_parse_args(&state, n, ap)) + return NULL; + + state.elem_size = state.elem_size ? state.elem_size : 1; + state.zero_init = state.zero_init >= 0 ? state.zero_init : 0; + n = state.have_size ? state.size_prod : n; + if (state.elem_size > 1) { + if (n > SIZE_MAX / state.elem_size) { + errno = ENOMEM; + return NULL; + } + n *= state.elem_size; + } + if (state.round_up_size) { + if (!state.alignment) { + errno = EINVAL; + return NULL; + } + if ((misalignment = n % state.alignment)) + n += state.alignment - misalignment; + } + if (!n && state.if_zero == 0) + return NULL; + n = n ? n : (state.if_zero > 0); + + saved_errno = errno; + errno = 0; + if (state.alignment) { + if (state.alignment % sizeof(void *)) { + size = n; + if ((misalignment = size % state.alignment)) + size += state.alignment - misalignment; + ptr = aligned_alloc(state.alignment, size); + } else { + errno = posix_memalign(&ptr, state.alignment, n); + } + if (ptr && state.zero_init) + memset(ptr, 0, n); + } else { + ptr = state.zero_init ? calloc(n, 1) : malloc(n); + } + if (!ptr && n) { + if (!errno) + errno = ENOMEM; + return NULL; + } + errno = errno ? errno : saved_errno; + + return ptr; +} + + +#else +#include "test.h" + +int +main(void) +{ + return 0; +} + +#endif |