Blame lib/malloca.h

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