~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to support/xalloc.h

  • Committer: Arnold D. Robbins
  • Date: 2016-12-22 15:23:16 UTC
  • mfrom: (731.1.11)
  • mto: (731.14.2) (1056.1.1)
  • mto: This revision was merged to the branch mainline in revision 742.
  • Revision ID: git-v1:293b5a86a9053668773e75b35682c41ca64e0db6
Merge branch 'master' into feature/andy

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* xalloc.h -- malloc with out-of-memory checking
 
2
 
 
3
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 
4
   2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
 
5
   Inc.
 
6
 
 
7
   This program is free software: you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
 
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
19
 
 
20
#ifndef XALLOC_H_
 
21
# define XALLOC_H_
 
22
 
 
23
# include <stddef.h>
 
24
 
 
25
 
 
26
# ifdef __cplusplus
 
27
extern "C" {
 
28
# endif
 
29
 
 
30
 
 
31
# ifndef __attribute__
 
32
#  if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
 
33
#   define __attribute__(x)
 
34
#  endif
 
35
# endif
 
36
 
 
37
# ifndef ATTRIBUTE_NORETURN
 
38
#  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
 
39
# endif
 
40
 
 
41
# ifndef ATTRIBUTE_MALLOC
 
42
#  if __GNUC__ >= 3
 
43
#   define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
 
44
#  else
 
45
#   define ATTRIBUTE_MALLOC
 
46
#  endif
 
47
# endif
 
48
 
 
49
/* This function is always triggered when memory is exhausted.
 
50
   It must be defined by the application, either explicitly
 
51
   or by using gnulib's xalloc-die module.  This is the
 
52
   function to call when one wants the program to die because of a
 
53
   memory allocation failure.  */
 
54
extern void xalloc_die (void) ATTRIBUTE_NORETURN;
 
55
 
 
56
void *xmalloc (size_t s) ATTRIBUTE_MALLOC;
 
57
void *xzalloc (size_t s) ATTRIBUTE_MALLOC;
 
58
void *xcalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
 
59
void *xrealloc (void *p, size_t s);
 
60
void *x2realloc (void *p, size_t *pn);
 
61
void *xmemdup (void const *p, size_t s) ATTRIBUTE_MALLOC;
 
62
char *xstrdup (char const *str) ATTRIBUTE_MALLOC;
 
63
 
 
64
/* Return 1 if an array of N objects, each of size S, cannot exist due
 
65
   to size arithmetic overflow.  S must be positive and N must be
 
66
   nonnegative.  This is a macro, not an inline function, so that it
 
67
   works correctly even when SIZE_MAX < N.
 
68
 
 
69
   By gnulib convention, SIZE_MAX represents overflow in size
 
70
   calculations, so the conservative dividend to use here is
 
71
   SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
 
72
   However, malloc (SIZE_MAX) fails on all known hosts where
 
73
   sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
 
74
   exactly-SIZE_MAX allocations on such hosts; this avoids a test and
 
75
   branch when S is known to be 1.  */
 
76
# define xalloc_oversized(n, s) \
 
77
    ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
 
78
 
 
79
 
 
80
/* In the following macros, T must be an elementary or structure/union or
 
81
   typedef'ed type, or a pointer to such a type.  To apply one of the
 
82
   following macros to a function pointer or array type, you need to typedef
 
83
   it first and use the typedef name.  */
 
84
 
 
85
/* Allocate an object of type T dynamically, with error checking.  */
 
86
/* extern t *XMALLOC (typename t); */
 
87
# define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
 
88
 
 
89
/* Allocate memory for N elements of type T, with error checking.  */
 
90
/* extern t *XNMALLOC (size_t n, typename t); */
 
91
# define XNMALLOC(n, t) \
 
92
    ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
 
93
 
 
94
/* Allocate an object of type T dynamically, with error checking,
 
95
   and zero it.  */
 
96
/* extern t *XZALLOC (typename t); */
 
97
# define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
 
98
 
 
99
/* Allocate memory for N elements of type T, with error checking,
 
100
   and zero it.  */
 
101
/* extern t *XCALLOC (size_t n, typename t); */
 
102
# define XCALLOC(n, t) \
 
103
    ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
 
104
 
 
105
/*
 
106
 * Gawk uses this file only to keep dfa.c happy.
 
107
 * We're therefore safe in manually defining HAVE_INLINE to
 
108
 * make the !@#$%^&*() thing just work.
 
109
 */
 
110
#ifdef GAWK
 
111
#define HAVE_INLINE     1       /* so there. nyah, nyah, nyah. */
 
112
#endif
 
113
 
 
114
# if HAVE_INLINE
 
115
#  define static_inline static inline
 
116
# else
 
117
void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
 
118
void *xnrealloc (void *p, size_t n, size_t s);
 
119
void *x2nrealloc (void *p, size_t *pn, size_t s);
 
120
char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
 
121
# endif
 
122
 
 
123
# ifdef static_inline
 
124
 
 
125
/* Allocate an array of N objects, each with S bytes of memory,
 
126
   dynamically, with error checking.  S must be nonzero.  */
 
127
 
 
128
static_inline void *xnmalloc (size_t n, size_t s) ATTRIBUTE_MALLOC;
 
129
static_inline void *
 
130
xnmalloc (size_t n, size_t s)
 
131
{
 
132
  if (xalloc_oversized (n, s))
 
133
    xalloc_die ();
 
134
  return xmalloc (n * s);
 
135
}
 
136
 
 
137
#ifdef GAWK
 
138
#include <errno.h>
 
139
extern void r_fatal(const char *msg, ...) ATTRIBUTE_NORETURN ;
 
140
 
 
141
/* Allocate an array of N objects, each with S bytes of memory,
 
142
   dynamically, with error checking.  S must be nonzero.
 
143
   Clear the contents afterwards.  */
 
144
 
 
145
void *
 
146
xcalloc(size_t nmemb, size_t size)
 
147
{
 
148
  void *p = xmalloc (nmemb * size);
 
149
  memset(p, '\0', nmemb * size);
 
150
  return p;
 
151
}
 
152
 
 
153
/* Reallocate a pointer to a new size, with error checking. */
 
154
 
 
155
void *
 
156
xrealloc(void *p, size_t size)
 
157
{
 
158
   void *new_p = realloc(p, size);
 
159
   if (new_p ==  0)
 
160
     xalloc_die ();
 
161
 
 
162
   return new_p;
 
163
}
 
164
 
 
165
/* xalloc_die --- fatal error message when malloc fails, needed by dfa.c */
 
166
 
 
167
void
 
168
xalloc_die (void)
 
169
{
 
170
        r_fatal(_("xalloc: malloc failed: %s"), strerror(errno));
 
171
}
 
172
 
 
173
/* Clone an object P of size S, with error checking.  There's no need
 
174
   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
 
175
   need for an arithmetic overflow check.  */
 
176
 
 
177
void *
 
178
xmemdup (void const *p, size_t s)
 
179
{
 
180
  return memcpy (xmalloc (s), p, s);
 
181
}
 
182
 
 
183
/* xstrdup --- strdup and die if fails */
 
184
char *xstrdup(const char *s)
 
185
{
 
186
        char *p;
 
187
        int l;
 
188
 
 
189
        if (s == NULL)
 
190
                r_fatal(_("xstrdup: null parameter"));
 
191
 
 
192
        l = strlen(s);
 
193
        p = xmemdup(s, l + 1);
 
194
        p[l] = '\0';
 
195
 
 
196
        return p;
 
197
}
 
198
#endif
 
199
 
 
200
/* Change the size of an allocated block of memory P to an array of N
 
201
   objects each of S bytes, with error checking.  S must be nonzero.  */
 
202
 
 
203
static_inline void *
 
204
xnrealloc (void *p, size_t n, size_t s)
 
205
{
 
206
  if (xalloc_oversized (n, s))
 
207
    xalloc_die ();
 
208
  return xrealloc (p, n * s);
 
209
}
 
210
 
 
211
/* If P is null, allocate a block of at least *PN such objects;
 
212
   otherwise, reallocate P so that it contains more than *PN objects
 
213
   each of S bytes.  *PN must be nonzero unless P is null, and S must
 
214
   be nonzero.  Set *PN to the new number of objects, and return the
 
215
   pointer to the new block.  *PN is never set to zero, and the
 
216
   returned pointer is never null.
 
217
 
 
218
   Repeated reallocations are guaranteed to make progress, either by
 
219
   allocating an initial block with a nonzero size, or by allocating a
 
220
   larger block.
 
221
 
 
222
   In the following implementation, nonzero sizes are increased by a
 
223
   factor of approximately 1.5 so that repeated reallocations have
 
224
   O(N) overall cost rather than O(N**2) cost, but the
 
225
   specification for this function does not guarantee that rate.
 
226
 
 
227
   Here is an example of use:
 
228
 
 
229
     int *p = NULL;
 
230
     size_t used = 0;
 
231
     size_t allocated = 0;
 
232
 
 
233
     void
 
234
     append_int (int value)
 
235
       {
 
236
         if (used == allocated)
 
237
           p = x2nrealloc (p, &allocated, sizeof *p);
 
238
         p[used++] = value;
 
239
       }
 
240
 
 
241
   This causes x2nrealloc to allocate a block of some nonzero size the
 
242
   first time it is called.
 
243
 
 
244
   To have finer-grained control over the initial size, set *PN to a
 
245
   nonzero value before calling this function with P == NULL.  For
 
246
   example:
 
247
 
 
248
     int *p = NULL;
 
249
     size_t used = 0;
 
250
     size_t allocated = 0;
 
251
     size_t allocated1 = 1000;
 
252
 
 
253
     void
 
254
     append_int (int value)
 
255
       {
 
256
         if (used == allocated)
 
257
           {
 
258
             p = x2nrealloc (p, &allocated1, sizeof *p);
 
259
             allocated = allocated1;
 
260
           }
 
261
         p[used++] = value;
 
262
       }
 
263
 
 
264
   */
 
265
 
 
266
static_inline void *
 
267
x2nrealloc (void *p, size_t *pn, size_t s)
 
268
{
 
269
  size_t n = *pn;
 
270
 
 
271
  if (! p)
 
272
    {
 
273
      if (! n)
 
274
        {
 
275
          /* The approximate size to use for initial small allocation
 
276
             requests, when the invoking code specifies an old size of
 
277
             zero.  64 bytes is the largest "small" request for the
 
278
             GNU C library malloc.  */
 
279
          enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
 
280
 
 
281
          n = DEFAULT_MXFAST / s;
 
282
          n += !n;
 
283
        }
 
284
    }
 
285
  else
 
286
    {
 
287
      /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
 
288
         Check for overflow, so that N * S stays in size_t range.
 
289
         The check is slightly conservative, but an exact check isn't
 
290
         worth the trouble.  */
 
291
      if ((size_t) -1 / 3 * 2 / s <= n)
 
292
        xalloc_die ();
 
293
      n += n / 2 + 1;
 
294
    }
 
295
 
 
296
  *pn = n;
 
297
  return xrealloc (p, n * s);
 
298
}
 
299
 
 
300
/* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
 
301
   except it returns char *.  */
 
302
 
 
303
static_inline char *xcharalloc (size_t n) ATTRIBUTE_MALLOC;
 
304
static_inline char *
 
305
xcharalloc (size_t n)
 
306
{
 
307
  return XNMALLOC (n, char);
 
308
}
 
309
 
 
310
/* Allocate S bytes of zeroed memory dynamically, with error checking.
 
311
   There's no need for xnzalloc (N, S), since it would be equivalent
 
312
   to xcalloc (N, S).  */
 
313
 
 
314
inline void *
 
315
xzalloc (size_t s)
 
316
{
 
317
  return memset (xmalloc (s), 0, s);
 
318
}
 
319
 
 
320
# endif
 
321
 
 
322
# ifdef __cplusplus
 
323
}
 
324
 
 
325
/* C++ does not allow conversions from void * to other pointer types
 
326
   without a cast.  Use templates to work around the problem when
 
327
   possible.  */
 
328
 
 
329
template <typename T> inline T *
 
330
xrealloc (T *p, size_t s)
 
331
{
 
332
  return (T *) xrealloc ((void *) p, s);
 
333
}
 
334
 
 
335
template <typename T> inline T *
 
336
xnrealloc (T *p, size_t n, size_t s)
 
337
{
 
338
  return (T *) xnrealloc ((void *) p, n, s);
 
339
}
 
340
 
 
341
template <typename T> inline T *
 
342
x2realloc (T *p, size_t *pn)
 
343
{
 
344
  return (T *) x2realloc ((void *) p, pn);
 
345
}
 
346
 
 
347
template <typename T> inline T *
 
348
x2nrealloc (T *p, size_t *pn, size_t s)
 
349
{
 
350
  return (T *) x2nrealloc ((void *) p, pn, s);
 
351
}
 
352
 
 
353
template <typename T> inline T *
 
354
xmemdup (T const *p, size_t s)
 
355
{
 
356
  return (T *) xmemdup ((void const *) p, s);
 
357
}
 
358
 
 
359
# endif
 
360
 
 
361
 
 
362
#endif /* !XALLOC_H_ */