Blame gnulib/lib/malloca.h

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