1 /*
2  *	Copyright 2018, University Corporation for Atmospheric Research
3  *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  */
5 /* $Id: onstack.h,v 2.7 2006/09/15 20:40:39 ed Exp $ */
6 
7 #ifndef _ONSTACK_H_
8 #define _ONSTACK_H_
9 /**
10  * This file provides definitions which allow us to
11  * "allocate" arrays on the stack where possible.
12  * (Where not possible, malloc and free are used.)
13  *
14  * The macro ALLOC_ONSTACK(name, type, nelems) is used to declare
15  * an array of 'type' named 'name' which is 'nelems' long.
16  * FREE_ONSTACK(name) is placed at the end of the scope of 'name'
17  * to call 'free' if necessary.
18  *
19  * The macro ALLOC_ONSTACK wraps a call to alloca() on most systems.
20  */
21 
22 #ifdef _WIN32
23 #ifdef HAVE_MALLOC_H
24 #undef HAVE_ALLOCA
25 #define HAVE_ALLOCA 1
26 #include <malloc.h>
27 #endif
28 #endif
29 
30 #ifdef HAVE_ALLOCA
31 /*
32  * Implementation based on alloca()
33  */
34 
35 #if defined(__GNUC__)
36 # if !defined(alloca)
37 # define alloca __builtin_alloca
38 # endif
39 #else
40 # ifdef HAVE_ALLOCA_H
41 #  include <alloca.h>
42 # elif defined(_AIX)
43 #  pragma alloca
44 # endif /* HAVE_ALLOCA_H */
45 #endif /* __GNUC__ */
46 
47 # if !defined(ALLOCA_ARG_T)
48 # define ALLOCA_ARG_T int /* the usual type of the alloca argument */
49 # endif
50 
51 # define ALLOC_ONSTACK(name, type, nelems) \
52 	type *const name = (type *) alloca((ALLOCA_ARG_T)((nelems) * sizeof(type)))
53 
54 # define FREE_ONSTACK(name)
55 
56 #elif defined(_CRAYC) && !defined(__crayx1) && !__cplusplus && __STDC__ > 1
57 /*
58  * Cray C allows sizing of arrays with non-constant values.
59  */
60 
61 # define ALLOC_ONSTACK(name, type, nelems) \
62 	type name[nelems]
63 
64 # define FREE_ONSTACK(name)
65 
66 #elif defined(_WIN32) || defined(_WIN64)
67 #include <malloc.h>
68 #undef ALLOCA_ARG_T
69 # define ALLOCA_ARG_T size_t
70 
71 #else
72 /*
73  * Default implementation. When all else fails, use malloc/free.
74  */
75 
76 # define ALLOC_ONSTACK(name, type, nelems) \
77 	type *const name = (type *) malloc((nelems) * sizeof(type))
78 
79 # define FREE_ONSTACK(name) \
80 	free(name)
81 
82 #endif
83 
84 #endif /* _ONSTACK_H_ */
85