Blame lib/malloca.h

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