xref: /dflybsd-src/contrib/cvs-1.12/lib/allocsa.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /* Safe automatic memory allocation.
2*86d7f5d3SJohn Marino    Copyright (C) 2003-2004 Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino    Written by Bruno Haible <bruno@clisp.org>, 2003.
4*86d7f5d3SJohn Marino 
5*86d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
6*86d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
7*86d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
8*86d7f5d3SJohn Marino    any later version.
9*86d7f5d3SJohn Marino 
10*86d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
11*86d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
12*86d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*86d7f5d3SJohn Marino    GNU General Public License for more details.
14*86d7f5d3SJohn Marino 
15*86d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
16*86d7f5d3SJohn Marino    along with this program; if not, write to the Free Software Foundation,
17*86d7f5d3SJohn Marino    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18*86d7f5d3SJohn Marino 
19*86d7f5d3SJohn Marino #ifndef _ALLOCSA_H
20*86d7f5d3SJohn Marino #define _ALLOCSA_H
21*86d7f5d3SJohn Marino 
22*86d7f5d3SJohn Marino #include <alloca.h>
23*86d7f5d3SJohn Marino #include <stddef.h>
24*86d7f5d3SJohn Marino #include <stdlib.h>
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino /* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
27*86d7f5d3SJohn Marino    alloca(N); otherwise it returns NULL.  It either returns N bytes of
28*86d7f5d3SJohn Marino    memory allocated on the stack, that lasts until the function returns,
29*86d7f5d3SJohn Marino    or NULL.
30*86d7f5d3SJohn Marino    Use of safe_alloca should be avoided:
31*86d7f5d3SJohn Marino      - inside arguments of function calls - undefined behaviour,
32*86d7f5d3SJohn Marino      - in inline functions - the allocation may actually last until the
33*86d7f5d3SJohn Marino        calling function returns.
34*86d7f5d3SJohn Marino */
35*86d7f5d3SJohn Marino #if HAVE_ALLOCA
36*86d7f5d3SJohn Marino /* The OS usually guarantees only one guard page at the bottom of the stack,
37*86d7f5d3SJohn Marino    and a page size can be as small as 4096 bytes.  So we cannot safely
38*86d7f5d3SJohn Marino    allocate anything larger than 4096 bytes.  Also care for the possibility
39*86d7f5d3SJohn Marino    of a few compiler-allocated temporary stack slots.
40*86d7f5d3SJohn Marino    This must be a macro, not an inline function.  */
41*86d7f5d3SJohn Marino # define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
42*86d7f5d3SJohn Marino #else
43*86d7f5d3SJohn Marino # define safe_alloca(N) ((N), NULL)
44*86d7f5d3SJohn Marino #endif
45*86d7f5d3SJohn Marino 
46*86d7f5d3SJohn Marino /* allocsa(N) is a safe variant of alloca(N).  It allocates N bytes of
47*86d7f5d3SJohn Marino    memory allocated on the stack, that must be freed using freesa() before
48*86d7f5d3SJohn Marino    the function returns.  Upon failure, it returns NULL.  */
49*86d7f5d3SJohn Marino #if HAVE_ALLOCA
50*86d7f5d3SJohn Marino # define allocsa(N) \
51*86d7f5d3SJohn Marino   ((N) < 4032 - sa_increment					    \
52*86d7f5d3SJohn Marino    ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
53*86d7f5d3SJohn Marino    : mallocsa (N))
54*86d7f5d3SJohn Marino #else
55*86d7f5d3SJohn Marino # define allocsa(N) \
56*86d7f5d3SJohn Marino   mallocsa (N)
57*86d7f5d3SJohn Marino #endif
58*86d7f5d3SJohn Marino extern void * mallocsa (size_t n);
59*86d7f5d3SJohn Marino 
60*86d7f5d3SJohn Marino /* Free a block of memory allocated through allocsa().  */
61*86d7f5d3SJohn Marino #if HAVE_ALLOCA
62*86d7f5d3SJohn Marino extern void freesa (void *p);
63*86d7f5d3SJohn Marino #else
64*86d7f5d3SJohn Marino # define freesa free
65*86d7f5d3SJohn Marino #endif
66*86d7f5d3SJohn Marino 
67*86d7f5d3SJohn Marino /* Maybe we should also define a variant
68*86d7f5d3SJohn Marino     nallocsa (size_t n, size_t s) - behaves like allocsa (n * s)
69*86d7f5d3SJohn Marino    If this would be useful in your application. please speak up.  */
70*86d7f5d3SJohn Marino 
71*86d7f5d3SJohn Marino 
72*86d7f5d3SJohn Marino /* ------------------- Auxiliary, non-public definitions ------------------- */
73*86d7f5d3SJohn Marino 
74*86d7f5d3SJohn Marino /* Determine the alignment of a type at compile time.  */
75*86d7f5d3SJohn Marino #if defined __GNUC__
76*86d7f5d3SJohn Marino # define sa_alignof __alignof__
77*86d7f5d3SJohn Marino #elif defined __cplusplus
78*86d7f5d3SJohn Marino   template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
79*86d7f5d3SJohn Marino # define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
80*86d7f5d3SJohn Marino #elif defined __hpux
81*86d7f5d3SJohn Marino   /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
82*86d7f5d3SJohn Marino      values.  */
83*86d7f5d3SJohn Marino # define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
84*86d7f5d3SJohn Marino #else
85*86d7f5d3SJohn Marino # define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
86*86d7f5d3SJohn Marino #endif
87*86d7f5d3SJohn Marino 
88*86d7f5d3SJohn Marino enum
89*86d7f5d3SJohn Marino {
90*86d7f5d3SJohn Marino /* The desired alignment of memory allocations is the maximum alignment
91*86d7f5d3SJohn Marino    among all elementary types.  */
92*86d7f5d3SJohn Marino   sa_alignment_long = sa_alignof (long),
93*86d7f5d3SJohn Marino   sa_alignment_double = sa_alignof (double),
94*86d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
95*86d7f5d3SJohn Marino   sa_alignment_longlong = sa_alignof (long long),
96*86d7f5d3SJohn Marino #endif
97*86d7f5d3SJohn Marino #ifdef HAVE_LONG_DOUBLE
98*86d7f5d3SJohn Marino   sa_alignment_longdouble = sa_alignof (long double),
99*86d7f5d3SJohn Marino #endif
100*86d7f5d3SJohn Marino   sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
101*86d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
102*86d7f5d3SJohn Marino 		      | (sa_alignment_longlong - 1)
103*86d7f5d3SJohn Marino #endif
104*86d7f5d3SJohn Marino #ifdef HAVE_LONG_DOUBLE
105*86d7f5d3SJohn Marino 		      | (sa_alignment_longdouble - 1)
106*86d7f5d3SJohn Marino #endif
107*86d7f5d3SJohn Marino 		     ) + 1,
108*86d7f5d3SJohn Marino /* The increment that guarantees room for a magic word must be >= sizeof (int)
109*86d7f5d3SJohn Marino    and a multiple of sa_alignment_max.  */
110*86d7f5d3SJohn Marino   sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
111*86d7f5d3SJohn Marino };
112*86d7f5d3SJohn Marino 
113*86d7f5d3SJohn Marino #endif /* _ALLOCSA_H */
114