Remove dependency of hash and xalloc modules on the malloc and realloc
[pspp] / lib / xmalloc.c
1 /* xmalloc.c -- malloc with out of memory checking
2
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
4    1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #if HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "xalloc.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31 #define N_(msgid) msgid
32
33 #include "error.h"
34 #include "exitfail.h"
35
36 #ifndef SIZE_MAX
37 # define SIZE_MAX ((size_t) -1)
38 #endif
39
40 /* If non NULL, call this function when memory is exhausted. */
41 void (*xalloc_fail_func) (void) = 0;
42
43 /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
44    before exiting when memory is exhausted.  Goes through gettext. */
45 char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
46
47 void
48 xalloc_die (void)
49 {
50   if (xalloc_fail_func)
51     (*xalloc_fail_func) ();
52   error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
53   /* The `noreturn' cannot be given to error, since it may return if
54      its first argument is 0.  To help compilers understand the
55      xalloc_die does terminate, call abort.  */
56   abort ();
57 }
58
59 /* Allocate an array of N objects, each with S bytes of memory,
60    dynamically, with error checking.  S must be nonzero.  */
61
62 static inline void *
63 xnmalloc_inline (size_t n, size_t s)
64 {
65   void *p;
66   if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0))
67     xalloc_die ();
68   return p;
69 }
70
71 void *
72 xnmalloc (size_t n, size_t s)
73 {
74   return xnmalloc_inline (n, s);
75 }
76
77 /* Allocate N bytes of memory dynamically, with error checking.  */
78
79 void *
80 xmalloc (size_t n)
81 {
82   return xnmalloc_inline (n, 1);
83 }
84
85 /* Change the size of an allocated block of memory P to an array of N
86    objects each of S bytes, with error checking.  S must be nonzero.  */
87
88 static inline void *
89 xnrealloc_inline (void *p, size_t n, size_t s)
90 {
91   if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0))
92     xalloc_die ();
93   return p;
94 }
95
96 void *
97 xnrealloc (void *p, size_t n, size_t s)
98 {
99   return xnrealloc_inline (p, n, s);
100 }
101
102 /* Change the size of an allocated block of memory P to N bytes,
103    with error checking.  */
104
105 void *
106 xrealloc (void *p, size_t n)
107 {
108   return xnrealloc_inline (p, n, 1);
109 }
110
111
112 /* If P is null, allocate a block of at least *PN such objects;
113    otherwise, reallocate P so that it contains more than *PN objects
114    each of S bytes.  *PN must be nonzero unless P is null, and S must
115    be nonzero.  Set *PN to the new number of objects, and return the
116    pointer to the new block.  *PN is never set to zero, and the
117    returned pointer is never null.
118
119    Repeated reallocations are guaranteed to make progress, either by
120    allocating an initial block with a nonzero size, or by allocating a
121    larger block.
122
123    In the following implementation, nonzero sizes are doubled so that
124    repeated reallocations have O(N log N) overall cost rather than
125    O(N**2) cost, but the specification for this function does not
126    guarantee that sizes are doubled.
127
128    Here is an example of use:
129
130      int *p = NULL;
131      size_t used = 0;
132      size_t allocated = 0;
133
134      void
135      append_int (int value)
136        {
137          if (used == allocated)
138            p = x2nrealloc (p, &allocated, sizeof *p);
139          p[used++] = value;
140        }
141
142    This causes x2nrealloc to allocate a block of some nonzero size the
143    first time it is called.
144
145    To have finer-grained control over the initial size, set *PN to a
146    nonzero value before calling this function with P == NULL.  For
147    example:
148
149      int *p = NULL;
150      size_t used = 0;
151      size_t allocated = 0;
152      size_t allocated1 = 1000;
153
154      void
155      append_int (int value)
156        {
157          if (used == allocated)
158            {
159              p = x2nrealloc (p, &allocated1, sizeof *p);
160              allocated = allocated1;
161            }
162          p[used++] = value;
163        }
164
165    */
166
167 static inline void *
168 x2nrealloc_inline (void *p, size_t *pn, size_t s)
169 {
170   size_t n = *pn;
171
172   if (! p)
173     {
174       if (! n)
175         {
176           /* The approximate size to use for initial small allocation
177              requests, when the invoking code specifies an old size of
178              zero.  64 bytes is the largest "small" request for the
179              GNU C library malloc.  */
180           enum { DEFAULT_MXFAST = 64 };
181
182           n = DEFAULT_MXFAST / s;
183           n += !n;
184         }
185     }
186   else
187     {
188       if (SIZE_MAX / 2 / s < n)
189         xalloc_die ();
190       n *= 2;
191     }
192
193   *pn = n;
194   return xrealloc (p, n * s);
195 }
196
197 void *
198 x2nrealloc (void *p, size_t *pn, size_t s)
199 {
200   return x2nrealloc_inline (p, pn, s);
201 }
202
203 /* If P is null, allocate a block of at least *PN bytes; otherwise,
204    reallocate P so that it contains more than *PN bytes.  *PN must be
205    nonzero unless P is null.  Set *PN to the new block's size, and
206    return the pointer to the new block.  *PN is never set to zero, and
207    the returned pointer is never null.  */
208
209 void *
210 x2realloc (void *p, size_t *pn)
211 {
212   return x2nrealloc_inline (p, pn, 1);
213 }
214
215 /* Allocate S bytes of zeroed memory dynamically, with error checking.
216    There's no need for xnzalloc (N, S), since it would be equivalent
217    to xcalloc (N, S).  */
218
219 void *
220 xzalloc (size_t s)
221 {
222   return memset (xmalloc (s), 0, s);
223 }
224
225 /* Allocate zeroed memory for N elements of S bytes, with error
226    checking.  S must be nonzero.  */
227
228 void *
229 xcalloc (size_t n, size_t s)
230 {
231   void *p;
232   /* Test for overflow, since some calloc implementations don't have
233      proper overflow checks.  */
234   if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0))
235     xalloc_die ();
236   return p;
237 }
238
239 /* Clone an object P of size S, with error checking.  There's no need
240    for xnclone (P, N, S), since xclone (P, N * S) works without any
241    need for an arithmetic overflow check.  */
242
243 void *
244 xclone (void const *p, size_t s)
245 {
246   return memcpy (xmalloc (s), p, s);
247 }