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