Blame gl/malloca.h

Packit a4aae4
/* Safe automatic memory allocation.
Packit a4aae4
   Copyright (C) 2003-2007, 2009-2017 Free Software Foundation, Inc.
Packit a4aae4
   Written by Bruno Haible <bruno@clisp.org>, 2003.
Packit a4aae4
Packit a4aae4
   This program is free software; you can redistribute it and/or modify
Packit a4aae4
   it under the terms of the GNU Lesser General Public License as published by
Packit a4aae4
   the Free Software Foundation; either version 2, or (at your option)
Packit a4aae4
   any later version.
Packit a4aae4
Packit a4aae4
   This program is distributed in the hope that it will be useful,
Packit a4aae4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit a4aae4
   GNU Lesser General Public License for more details.
Packit a4aae4
Packit a4aae4
   You should have received a copy of the GNU Lesser General Public License
Packit a4aae4
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit a4aae4
Packit a4aae4
#ifndef _MALLOCA_H
Packit a4aae4
#define _MALLOCA_H
Packit a4aae4
Packit a4aae4
#include <alloca.h>
Packit a4aae4
#include <stddef.h>
Packit a4aae4
#include <stdlib.h>
Packit a4aae4
#include <stdint.h>
Packit a4aae4
Packit a4aae4
#include "xalloc-oversized.h"
Packit a4aae4
Packit a4aae4
Packit a4aae4
#ifdef __cplusplus
Packit a4aae4
extern "C" {
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
Packit a4aae4
/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
Packit a4aae4
   alloca(N); otherwise it returns NULL.  It either returns N bytes of
Packit a4aae4
   memory allocated on the stack, that lasts until the function returns,
Packit a4aae4
   or NULL.
Packit a4aae4
   Use of safe_alloca should be avoided:
Packit a4aae4
     - inside arguments of function calls - undefined behaviour,
Packit a4aae4
     - in inline functions - the allocation may actually last until the
Packit a4aae4
       calling function returns.
Packit a4aae4
*/
Packit a4aae4
#if HAVE_ALLOCA
Packit a4aae4
/* The OS usually guarantees only one guard page at the bottom of the stack,
Packit a4aae4
   and a page size can be as small as 4096 bytes.  So we cannot safely
Packit a4aae4
   allocate anything larger than 4096 bytes.  Also care for the possibility
Packit a4aae4
   of a few compiler-allocated temporary stack slots.
Packit a4aae4
   This must be a macro, not a function.  */
Packit a4aae4
# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
Packit a4aae4
#else
Packit a4aae4
# define safe_alloca(N) ((void) (N), NULL)
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
/* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
Packit a4aae4
   memory allocated on the stack, that must be freed using freea() before
Packit a4aae4
   the function returns.  Upon failure, it returns NULL.  */
Packit a4aae4
#if HAVE_ALLOCA
Packit a4aae4
# define malloca(N) \
Packit a4aae4
  ((N) < 4032 - sa_increment                                        \
Packit a4aae4
   ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
Packit a4aae4
   : mmalloca (N))
Packit a4aae4
#else
Packit a4aae4
# define malloca(N) \
Packit a4aae4
  mmalloca (N)
Packit a4aae4
#endif
Packit a4aae4
extern void * mmalloca (size_t n);
Packit a4aae4
Packit a4aae4
/* Free a block of memory allocated through malloca().  */
Packit a4aae4
#if HAVE_ALLOCA
Packit a4aae4
extern void freea (void *p);
Packit a4aae4
#else
Packit a4aae4
# define freea free
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
Packit a4aae4
   It allocates an array of N objects, each with S bytes of memory,
Packit a4aae4
   on the stack.  S must be positive and N must be nonnegative.
Packit a4aae4
   The array must be freed using freea() before the function returns.  */
Packit a4aae4
#define nmalloca(n, s) (xalloc_oversized (n, s) ? NULL : malloca ((n) * (s)))
Packit a4aae4
Packit a4aae4
Packit a4aae4
#ifdef __cplusplus
Packit a4aae4
}
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
Packit a4aae4
/* ------------------- Auxiliary, non-public definitions ------------------- */
Packit a4aae4
Packit a4aae4
/* Determine the alignment of a type at compile time.  */
Packit a4aae4
#if defined __GNUC__ || defined __IBM__ALIGNOF__
Packit a4aae4
# define sa_alignof __alignof__
Packit a4aae4
#elif defined __cplusplus
Packit a4aae4
  template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
Packit a4aae4
# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
Packit a4aae4
#elif defined __hpux
Packit a4aae4
  /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
Packit a4aae4
     values.  */
Packit a4aae4
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
Packit a4aae4
#elif defined _AIX
Packit a4aae4
  /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof
Packit a4aae4
     values.  */
Packit a4aae4
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
Packit a4aae4
#else
Packit a4aae4
# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
enum
Packit a4aae4
{
Packit a4aae4
/* The desired alignment of memory allocations is the maximum alignment
Packit a4aae4
   among all elementary types.  */
Packit a4aae4
  sa_alignment_long = sa_alignof (long),
Packit a4aae4
  sa_alignment_double = sa_alignof (double),
Packit a4aae4
#if HAVE_LONG_LONG_INT
Packit a4aae4
  sa_alignment_longlong = sa_alignof (long long),
Packit a4aae4
#endif
Packit a4aae4
  sa_alignment_longdouble = sa_alignof (long double),
Packit a4aae4
  sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
Packit a4aae4
#if HAVE_LONG_LONG_INT
Packit a4aae4
                      | (sa_alignment_longlong - 1)
Packit a4aae4
#endif
Packit a4aae4
                      | (sa_alignment_longdouble - 1)
Packit a4aae4
                     ) + 1,
Packit a4aae4
/* The increment that guarantees room for a magic word must be >= sizeof (int)
Packit a4aae4
   and a multiple of sa_alignment_max.  */
Packit a4aae4
  sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
#endif /* _MALLOCA_H */