xref: /dflybsd-src/contrib/cvs-1.12/lib/allocsa.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* Safe automatic memory allocation.
286d7f5d3SJohn Marino    Copyright (C) 2003-2004 Free Software Foundation, Inc.
386d7f5d3SJohn Marino    Written by Bruno Haible <bruno@clisp.org>, 2003.
486d7f5d3SJohn Marino 
586d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
686d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
786d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
886d7f5d3SJohn Marino    any later version.
986d7f5d3SJohn Marino 
1086d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
1186d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
1286d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1386d7f5d3SJohn Marino    GNU General Public License for more details.
1486d7f5d3SJohn Marino 
1586d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
1686d7f5d3SJohn Marino    along with this program; if not, write to the Free Software Foundation,
1786d7f5d3SJohn Marino    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
1886d7f5d3SJohn Marino 
1986d7f5d3SJohn Marino #ifndef _ALLOCSA_H
2086d7f5d3SJohn Marino #define _ALLOCSA_H
2186d7f5d3SJohn Marino 
2286d7f5d3SJohn Marino #include <alloca.h>
2386d7f5d3SJohn Marino #include <stddef.h>
2486d7f5d3SJohn Marino #include <stdlib.h>
2586d7f5d3SJohn Marino 
2686d7f5d3SJohn Marino /* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
2786d7f5d3SJohn Marino    alloca(N); otherwise it returns NULL.  It either returns N bytes of
2886d7f5d3SJohn Marino    memory allocated on the stack, that lasts until the function returns,
2986d7f5d3SJohn Marino    or NULL.
3086d7f5d3SJohn Marino    Use of safe_alloca should be avoided:
3186d7f5d3SJohn Marino      - inside arguments of function calls - undefined behaviour,
3286d7f5d3SJohn Marino      - in inline functions - the allocation may actually last until the
3386d7f5d3SJohn Marino        calling function returns.
3486d7f5d3SJohn Marino */
3586d7f5d3SJohn Marino #if HAVE_ALLOCA
3686d7f5d3SJohn Marino /* The OS usually guarantees only one guard page at the bottom of the stack,
3786d7f5d3SJohn Marino    and a page size can be as small as 4096 bytes.  So we cannot safely
3886d7f5d3SJohn Marino    allocate anything larger than 4096 bytes.  Also care for the possibility
3986d7f5d3SJohn Marino    of a few compiler-allocated temporary stack slots.
4086d7f5d3SJohn Marino    This must be a macro, not an inline function.  */
4186d7f5d3SJohn Marino # define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
4286d7f5d3SJohn Marino #else
4386d7f5d3SJohn Marino # define safe_alloca(N) ((N), NULL)
4486d7f5d3SJohn Marino #endif
4586d7f5d3SJohn Marino 
4686d7f5d3SJohn Marino /* allocsa(N) is a safe variant of alloca(N).  It allocates N bytes of
4786d7f5d3SJohn Marino    memory allocated on the stack, that must be freed using freesa() before
4886d7f5d3SJohn Marino    the function returns.  Upon failure, it returns NULL.  */
4986d7f5d3SJohn Marino #if HAVE_ALLOCA
5086d7f5d3SJohn Marino # define allocsa(N) \
5186d7f5d3SJohn Marino   ((N) < 4032 - sa_increment					    \
5286d7f5d3SJohn Marino    ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
5386d7f5d3SJohn Marino    : mallocsa (N))
5486d7f5d3SJohn Marino #else
5586d7f5d3SJohn Marino # define allocsa(N) \
5686d7f5d3SJohn Marino   mallocsa (N)
5786d7f5d3SJohn Marino #endif
5886d7f5d3SJohn Marino extern void * mallocsa (size_t n);
5986d7f5d3SJohn Marino 
6086d7f5d3SJohn Marino /* Free a block of memory allocated through allocsa().  */
6186d7f5d3SJohn Marino #if HAVE_ALLOCA
6286d7f5d3SJohn Marino extern void freesa (void *p);
6386d7f5d3SJohn Marino #else
6486d7f5d3SJohn Marino # define freesa free
6586d7f5d3SJohn Marino #endif
6686d7f5d3SJohn Marino 
6786d7f5d3SJohn Marino /* Maybe we should also define a variant
6886d7f5d3SJohn Marino     nallocsa (size_t n, size_t s) - behaves like allocsa (n * s)
6986d7f5d3SJohn Marino    If this would be useful in your application. please speak up.  */
7086d7f5d3SJohn Marino 
7186d7f5d3SJohn Marino 
7286d7f5d3SJohn Marino /* ------------------- Auxiliary, non-public definitions ------------------- */
7386d7f5d3SJohn Marino 
7486d7f5d3SJohn Marino /* Determine the alignment of a type at compile time.  */
7586d7f5d3SJohn Marino #if defined __GNUC__
7686d7f5d3SJohn Marino # define sa_alignof __alignof__
7786d7f5d3SJohn Marino #elif defined __cplusplus
7886d7f5d3SJohn Marino   template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
7986d7f5d3SJohn Marino # define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
8086d7f5d3SJohn Marino #elif defined __hpux
8186d7f5d3SJohn Marino   /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
8286d7f5d3SJohn Marino      values.  */
8386d7f5d3SJohn Marino # define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
8486d7f5d3SJohn Marino #else
8586d7f5d3SJohn Marino # define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
8686d7f5d3SJohn Marino #endif
8786d7f5d3SJohn Marino 
8886d7f5d3SJohn Marino enum
8986d7f5d3SJohn Marino {
9086d7f5d3SJohn Marino /* The desired alignment of memory allocations is the maximum alignment
9186d7f5d3SJohn Marino    among all elementary types.  */
9286d7f5d3SJohn Marino   sa_alignment_long = sa_alignof (long),
9386d7f5d3SJohn Marino   sa_alignment_double = sa_alignof (double),
9486d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
9586d7f5d3SJohn Marino   sa_alignment_longlong = sa_alignof (long long),
9686d7f5d3SJohn Marino #endif
9786d7f5d3SJohn Marino #ifdef HAVE_LONG_DOUBLE
9886d7f5d3SJohn Marino   sa_alignment_longdouble = sa_alignof (long double),
9986d7f5d3SJohn Marino #endif
10086d7f5d3SJohn Marino   sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
10186d7f5d3SJohn Marino #ifdef HAVE_LONG_LONG
10286d7f5d3SJohn Marino 		      | (sa_alignment_longlong - 1)
10386d7f5d3SJohn Marino #endif
10486d7f5d3SJohn Marino #ifdef HAVE_LONG_DOUBLE
10586d7f5d3SJohn Marino 		      | (sa_alignment_longdouble - 1)
10686d7f5d3SJohn Marino #endif
10786d7f5d3SJohn Marino 		     ) + 1,
10886d7f5d3SJohn Marino /* The increment that guarantees room for a magic word must be >= sizeof (int)
10986d7f5d3SJohn Marino    and a multiple of sa_alignment_max.  */
11086d7f5d3SJohn Marino   sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
11186d7f5d3SJohn Marino };
11286d7f5d3SJohn Marino 
11386d7f5d3SJohn Marino #endif /* _ALLOCSA_H */
114