2006-11-06 Paul Eggert <eggert@cs.ucla.edu>
+ * lib/xalloc.h (xnmalloc, xnrealloc, x2nrealloc): Now static
+ inline functions that are identical with the old xnmalloc_inline,
+ xnrealloc_inline, x2nrealloc_inline of lib/xmalloc.c. This is so
+ that we can avoid some unnecessary integer multiplications and
+ divisions in the common case where the element size is known at
+ compile time.
+ (XNMALLOC) [HAVE_INLINE]: Remove special case, which is no longer
+ needed.
+ (xnboundedmalloc): Remove.
+ (XMALLOC, XNMALLOC, XZALLOC, XCALLOC): Use lower-case letters for
+ arguments, for consistency with rest of this header.
+ (xcharalloc): Rewrite using XNMALLOC.
+ * lib/xmalloc.c (xnmalloc_inline, xnmalloc, xnrealloc_inline):
+ (xnrealloc, x2nrealloc_inline, x2nrealloc): Remove. The *_inline
+ versions have been moved to lib/xalloc.h and renamed to be the
+ non-*_inline versions.
+ (xmalloc, xrealloc): Implement without reference to the xnmalloc
+ and xnrealloc functions, since those functions are now inline and
+ now call us.
+ (x2realloc): Invoke x2realloc, not x2realloc_inline, to accommodate
+ renaming described above.
+
New module canonicalize-lgpl, proposed by Charles Wilson in
<http://lists.gnu.org/archive/html/bug-gnulib/2006-11/msg00020.html>
with a few small changes afterwards.
/* xalloc.h -- malloc with out-of-memory checking
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
void *xmalloc (size_t s);
-void *xnmalloc (size_t n, size_t s);
void *xzalloc (size_t s);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t s);
-void *xnrealloc (void *p, size_t n, size_t s);
void *x2realloc (void *p, size_t *pn);
-void *x2nrealloc (void *p, size_t *pn, size_t s);
void *xmemdup (void const *p, size_t s);
char *xstrdup (char const *str);
# define xalloc_oversized(n, s) \
((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
-/* In the following macros, T must be an elementary or structure/union or
- typedef'ed type, or a pointer to such a type. To apply one of the
- following macros to a function pointer or array type, you need to typedef
- it first and use the typedef name. */
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
-/* Allocate an object of type T dynamically, with error checking. */
-/* extern T *XMALLOC (typename T); */
-#define XMALLOC(T) \
- ((T *) xmalloc (sizeof (T)))
-
-/* Allocate memory for NMEMB elements of type T, with error checking. */
-/* extern T *XNMALLOC (size_t nmemb, typename T); */
-#if HAVE_INLINE
-/* xnmalloc performs a division and multiplication by sizeof (T). Arrange to
- perform the division at compile-time and the multiplication with a factor
- known at compile-time. */
-# define XNMALLOC(N,T) \
- ((T *) (sizeof (T) == 1 \
- ? xmalloc (N) \
- : xnboundedmalloc(N, (size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / sizeof (T), sizeof (T))))
static inline void *
-xnboundedmalloc (size_t n, size_t bound, size_t s)
+xnmalloc (size_t n, size_t s)
{
- if (n > bound)
+ if (xalloc_oversized (n, s))
xalloc_die ();
return xmalloc (n * s);
}
-#else
-# define XNMALLOC(N,T) \
- ((T *) (sizeof (T) == 1 ? xmalloc (N) : xnmalloc (N, sizeof (T))))
-#endif
+
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+static inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ return xrealloc (p, n * s);
+}
+
+/* If P is null, allocate a block of at least *PN such objects;
+ otherwise, reallocate P so that it contains more than *PN objects
+ each of S bytes. *PN must be nonzero unless P is null, and S must
+ be nonzero. Set *PN to the new number of objects, and return the
+ pointer to the new block. *PN is never set to zero, and the
+ returned pointer is never null.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are doubled so that
+ repeated reallocations have O(N log N) overall cost rather than
+ O(N**2) cost, but the specification for this function does not
+ guarantee that sizes are doubled.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static inline void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. 64 bytes is the largest "small" request for the
+ GNU C library malloc. */
+ enum { DEFAULT_MXFAST = 64 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ }
+ else
+ {
+ if (((size_t) -1) / 2 / s < n)
+ xalloc_die ();
+ n *= 2;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+/* In the following macros, T must be an elementary or structure/union or
+ typedef'ed type, or a pointer to such a type. To apply one of the
+ following macros to a function pointer or array type, you need to typedef
+ it first and use the typedef name. */
+
+/* Allocate an object of type T dynamically, with error checking. */
+/* extern t *XMALLOC (typename t); */
+#define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
+
+/* Allocate memory for N elements of type T, with error checking. */
+/* extern t *XNMALLOC (size_t n, typename t); */
+#define XNMALLOC(n, t) ((t *) xnmalloc (n, sizeof (t)))
/* Allocate an object of type T dynamically, with error checking,
and zero it. */
-/* extern T *XZALLOC (typename T); */
-#define XZALLOC(T) \
- ((T *) xzalloc (sizeof (T)))
+/* extern t *XZALLOC (typename t); */
+#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
-/* Allocate memory for NMEMB elements of type T, with error checking,
+/* Allocate memory for N elements of type T, with error checking,
and zero it. */
-/* extern T *XCALLOC (size_t nmemb, typename T); */
-#define XCALLOC(N,T) \
- ((T *) xcalloc (N, sizeof (T)))
+/* extern t *XCALLOC (size_t n, typename t); */
+#define XCALLOC(n, t) ((t *) xcalloc (n, sizeof (t)))
/* Return a pointer to a new buffer of N bytes. This is like xmalloc,
- except it returns char *.
- xcharalloc (N) is equivalent to XNMALLOC (N, char). */
+ except it returns char *. */
static inline char *
xcharalloc (size_t n)
{
- return (char *) xmalloc (n);
+ return XNMALLOC (n, char);
}
# ifdef __cplusplus
enum { HAVE_GNU_CALLOC = 0 };
#endif
-/* Allocate an array of N objects, each with S bytes of memory,
- dynamically, with error checking. S must be nonzero. */
-
-static inline void *
-xnmalloc_inline (size_t n, size_t s)
-{
- void *p;
- if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
- xalloc_die ();
- return p;
-}
-
-void *
-xnmalloc (size_t n, size_t s)
-{
- return xnmalloc_inline (n, s);
-}
-
/* Allocate N bytes of memory dynamically, with error checking. */
void *
xmalloc (size_t n)
{
- return xnmalloc_inline (n, 1);
-}
-
-/* Change the size of an allocated block of memory P to an array of N
- objects each of S bytes, with error checking. S must be nonzero. */
-
-static inline void *
-xnrealloc_inline (void *p, size_t n, size_t s)
-{
- if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
+ void *p = malloc (n);
+ if (!p && n != 0)
xalloc_die ();
return p;
}
-void *
-xnrealloc (void *p, size_t n, size_t s)
-{
- return xnrealloc_inline (p, n, s);
-}
-
/* Change the size of an allocated block of memory P to N bytes,
with error checking. */
void *
xrealloc (void *p, size_t n)
{
- return xnrealloc_inline (p, n, 1);
-}
-
-
-/* If P is null, allocate a block of at least *PN such objects;
- otherwise, reallocate P so that it contains more than *PN objects
- each of S bytes. *PN must be nonzero unless P is null, and S must
- be nonzero. Set *PN to the new number of objects, and return the
- pointer to the new block. *PN is never set to zero, and the
- returned pointer is never null.
-
- Repeated reallocations are guaranteed to make progress, either by
- allocating an initial block with a nonzero size, or by allocating a
- larger block.
-
- In the following implementation, nonzero sizes are doubled so that
- repeated reallocations have O(N log N) overall cost rather than
- O(N**2) cost, but the specification for this function does not
- guarantee that sizes are doubled.
-
- Here is an example of use:
-
- int *p = NULL;
- size_t used = 0;
- size_t allocated = 0;
-
- void
- append_int (int value)
- {
- if (used == allocated)
- p = x2nrealloc (p, &allocated, sizeof *p);
- p[used++] = value;
- }
-
- This causes x2nrealloc to allocate a block of some nonzero size the
- first time it is called.
-
- To have finer-grained control over the initial size, set *PN to a
- nonzero value before calling this function with P == NULL. For
- example:
-
- int *p = NULL;
- size_t used = 0;
- size_t allocated = 0;
- size_t allocated1 = 1000;
-
- void
- append_int (int value)
- {
- if (used == allocated)
- {
- p = x2nrealloc (p, &allocated1, sizeof *p);
- allocated = allocated1;
- }
- p[used++] = value;
- }
-
- */
-
-static inline void *
-x2nrealloc_inline (void *p, size_t *pn, size_t s)
-{
- size_t n = *pn;
-
- if (! p)
- {
- if (! n)
- {
- /* The approximate size to use for initial small allocation
- requests, when the invoking code specifies an old size of
- zero. 64 bytes is the largest "small" request for the
- GNU C library malloc. */
- enum { DEFAULT_MXFAST = 64 };
-
- n = DEFAULT_MXFAST / s;
- n += !n;
- }
- }
- else
- {
- if (SIZE_MAX / 2 / s < n)
- xalloc_die ();
- n *= 2;
- }
-
- *pn = n;
- return xrealloc (p, n * s);
-}
-
-void *
-x2nrealloc (void *p, size_t *pn, size_t s)
-{
- return x2nrealloc_inline (p, pn, s);
+ p = realloc (p, n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
}
/* If P is null, allocate a block of at least *PN bytes; otherwise,
void *
x2realloc (void *p, size_t *pn)
{
- return x2nrealloc_inline (p, pn, 1);
+ return x2nrealloc (p, pn, 1);
}
/* Allocate S bytes of zeroed memory dynamically, with error checking.