raw
vtools_genesis          1 #include <stdlib.h>
vtools_genesis 2 #include <string.h>
vtools_genesis 3 #include "xalloc.h"
vtools_genesis 4 #include "error.h"
vtools_genesis 5
vtools_genesis 6 /* 1 if |calloc| is known to be compatible with GNU |calloc|. This
vtools_genesis 7 matters if we are not also using the |calloc| module, which defines
vtools_genesis 8 |HAVE_CALLOC_GNU| and supports the GNU API even on non-GNU
vtools_genesis 9 platforms. */
vtools_genesis 10 #if defined HAVE_CALLOC_GNU || (defined __GLIBC__ && !defined __UCLIBC__)
vtools_genesis 11 enum { HAVE_GNU_CALLOC = 1 };
vtools_genesis 12 #else
vtools_genesis 13 enum { HAVE_GNU_CALLOC = 0 };
vtools_genesis 14 #endif
vtools_genesis 15
vtools_genesis 16 void
vtools_genesis 17 xalloc_die(void) {
vtools_genesis 18 error(2, 0, "%s", "memory exhausted");
vtools_genesis 19
vtools_genesis 20 /* |_Noreturn| cannot be given to error, since it may return if
vtools_genesis 21 its first argument is 0. To help compilers understand the
vtools_genesis 22 |xalloc_die| does not return, call abort. Also, the abort is a
vtools_genesis 23 safety feature if |exit_failure| is 0 (which shouldn't
vtools_genesis 24 happen). */
vtools_genesis 25 abort();
vtools_genesis 26 }
vtools_genesis 27
vtools_genesis 28 /* Allocate |n| bytes of memory dynamically, with error checking. */
vtools_genesis 29
vtools_genesis 30 void *
vtools_genesis 31 xmalloc(size_t n) {
vtools_genesis 32 void *p = malloc(n);
vtools_genesis 33 if (!p && n != 0)
vtools_genesis 34 xalloc_die();
vtools_genesis 35 return p;
vtools_genesis 36 }
vtools_genesis 37
vtools_genesis 38 /* Change the size of an allocated block of memory |p| to |n| bytes,
vtools_genesis 39 with error checking. */
vtools_genesis 40
vtools_genesis 41 void *
vtools_genesis 42 xrealloc(void *p, size_t n) {
vtools_genesis 43 if (!n && p) {
vtools_genesis 44 /* The GNU and C99 realloc behaviors disagree here. Act like
vtools_genesis 45 GNU, even if the underlying realloc is C99. */
vtools_genesis 46 free(p);
vtools_genesis 47 return NULL;
vtools_genesis 48 }
vtools_genesis 49
vtools_genesis 50 p = realloc(p, n);
vtools_genesis 51 if (!p && n)
vtools_genesis 52 xalloc_die();
vtools_genesis 53 return p;
vtools_genesis 54 }
vtools_genesis 55
vtools_genesis 56 /* If |p| is null, allocate a block of at least |*pn| bytes;
vtools_genesis 57 otherwise, reallocate |p| so that it contains more than |*pn|
vtools_genesis 58 bytes. |*PN| must be nonzero unless |p| is |NULL|. Set |*pn| to
vtools_genesis 59 the new block's size, and return the pointer to the new block.
vtools_genesis 60 |*pn| is never set to zero, and the returned pointer is never
vtools_genesis 61 |NULL|. */
vtools_genesis 62
vtools_genesis 63 void *
vtools_genesis 64 x2realloc(void *p, size_t *pn) {
vtools_genesis 65 return x2nrealloc(p, pn, 1);
vtools_genesis 66 }
vtools_genesis 67
vtools_genesis 68 /* Allocate |s| bytes of zeroed memory dynamically, with error
vtools_genesis 69 checking. There's no need for |xnzalloc (n, s)|, since it would be
vtools_genesis 70 equivalent to |xcalloc (n, s)|. */
vtools_genesis 71
vtools_genesis 72 void *
vtools_genesis 73 xzalloc(size_t s) {
vtools_genesis 74 return memset (xmalloc(s), 0, s);
vtools_genesis 75 }
vtools_genesis 76
vtools_genesis 77 /* Allocate zeroed memory for |n| elements of |s| bytes, with error
vtools_genesis 78 checking. |s| must be nonzero. */
vtools_genesis 79
vtools_genesis 80 void *
vtools_genesis 81 xcalloc(size_t n, size_t s) {
vtools_genesis 82 void *p;
vtools_genesis 83 /* Test for overflow, since objects with size greater than
vtools_genesis 84 |PTRDIFF_MAX| cause pointer subtraction to go awry. Omit
vtools_genesis 85 size-zero tests if |HAVE_GNU_CALLOC|, since GNU calloc never
vtools_genesis 86 returns |NULL| if successful. */
vtools_genesis 87 if (xalloc_oversized (n, s)
vtools_genesis 88 || (!(p = calloc(n, s)) && (HAVE_GNU_CALLOC || n != 0)))
vtools_genesis 89 xalloc_die();
vtools_genesis 90 return p;
vtools_genesis 91 }
vtools_genesis 92
vtools_genesis 93 /* Clone an object |p| of size |s|, with error checking. There's no
vtools_genesis 94 need for |xnmemdup (p, n, s)|, since |xmemdup (p, n * s)| works
vtools_genesis 95 without any need for an arithmetic overflow check. */
vtools_genesis 96
vtools_genesis 97 void *
vtools_genesis 98 xmemdup(void const *p, size_t s) {
vtools_genesis 99 return memcpy (xmalloc(s), p, s);
vtools_genesis 100 }
vtools_genesis 101
vtools_genesis 102 /* Clone |string|. */
vtools_genesis 103
vtools_genesis 104 char *
vtools_genesis 105 xstrdup(char const *string) {
vtools_genesis 106 return xmemdup(string, strlen(string) + 1);
vtools_genesis 107 }