Revert "strcpy -> strlcpy."
[elinks.git] / src / util / memory.h
blob9da756ccd52fd34c923c0b233385dc15d80ae30e
1 #ifndef EL__UTIL_MEMORY_H
2 #define EL__UTIL_MEMORY_H
4 /* If defined, we'll crash if ALLOC_MAXTRIES is attained,
5 * if not defined, we'll try to continue. */
6 /* #define CRASH_IF_ALLOC_MAXTRIES */
8 /** Max. number of retry in case of memory allocation failure. */
9 #define ALLOC_MAXTRIES 3
11 /** Delay in seconds between each alloc try. */
12 #define ALLOC_DELAY 3
14 #define fmem_alloc(x) mem_alloc(x)
15 #define fmem_free(x) mem_free(x)
18 /** Cygwin wants some size_t definition here... let's try to make it happy
19 * then. Hrmpf. */
20 #include <sys/types.h>
21 #include <stddef.h>
23 #ifdef CONFIG_GC
24 #include <gc.h>
25 #endif
27 #ifdef HAVE_MMAP
28 void *mem_mmap_alloc(size_t size);
29 void mem_mmap_free(void *p, size_t size);
30 void *mem_mmap_realloc(void *p, size_t old_size, size_t new_size);
31 #else
32 #define mem_mmap_alloc(x) mem_alloc(x)
33 #define mem_mmap_free(x, y) mem_free(x)
34 #define mem_mmap_realloc(x, y, z) mem_realloc(x, z)
35 #endif
38 #ifdef DEBUG_MEMLEAK
40 #include "util/memdebug.h"
42 #define mem_alloc(x) debug_mem_alloc(__FILE__, __LINE__, x)
43 #define mem_calloc(x, y) debug_mem_calloc(__FILE__, __LINE__, x, y)
44 #define mem_free(x) debug_mem_free(__FILE__, __LINE__, x)
45 #define mem_realloc(x, y) debug_mem_realloc(__FILE__, __LINE__, x, y)
47 #else
49 #ifndef CONFIG_FASTMEM
51 void *mem_alloc(size_t);
52 void *mem_calloc(size_t, size_t);
53 void mem_free(void *);
54 void *mem_realloc(void *, size_t);
56 #else
58 # include <stdlib.h>
60 /* TODO: For enhanced portability, checks at configure time:
61 * malloc(0) -> NULL
62 * realloc(NULL, 0) -> NULL
63 * realloc(p, 0) <-> free(p)
64 * realloc(NULL, n) <-> malloc(n)
65 * Some old implementations may not respect these rules.
66 * For these we need some replacement functions.
67 * This should not be an issue on most modern systems.
69 #ifdef CONFIG_GC
70 # define mem_alloc(size) GC_MALLOC(size)
71 # define mem_calloc(count, size) GC_MALLOC((count) * (size))
72 # define mem_free(p) (p) = NULL
73 # define mem_realloc(p, size) GC_REALLOC(p, size)
75 #else
77 # define mem_alloc(size) malloc(size)
78 # define mem_calloc(count, size) calloc(count, size)
79 # define mem_free(p) free(p)
80 # define mem_realloc(p, size) realloc(p, size)
82 #endif
84 /* fmem_* functions should be use for allocation and freeing of memory
85 * inside a function.
86 * See alloca(3) manpage. */
88 #undef fmem_alloc
89 #undef fmem_free
91 #ifdef HAVE_ALLOCA
93 #ifdef HAVE_ALLOCA_H
94 #include <alloca.h>
95 #endif
96 #define fmem_alloc(x) alloca(x)
97 #define fmem_free(x)
99 #else /* HAVE_ALLOCA */
101 #define fmem_alloc(x) mem_alloc(x)
102 #define fmem_free(x) mem_free(x)
104 #endif /* HAVE_ALLOCA */
106 #endif /* CONFIG_FASTMEM */
108 #endif /* DEBUG_MEMLEAK */
111 /** @name Granular memory allocation.
112 * The granularity used by the aligned memory functions below must be a mask
113 * with all bits set from but not including the most significant bit and down.
114 * So if an alignment of 256 is wanted use 0xFF.
115 * @{ */
117 /** The 'old' style granularity. XXX: Must be power of 2 */
118 #define ALLOC_GR 0x100
120 #include <string.h> /* for memset() */
122 #define ALIGN_MEMORY_SIZE(x, gr) (((x) + (gr)) & ~(gr))
124 static inline void *
125 mem_align_alloc__(
126 #ifdef DEBUG_MEMLEAK
127 const unsigned char *file, int line,
128 #endif
129 void **ptr, size_t old, size_t new, size_t objsize, size_t mask)
131 size_t newsize = ALIGN_MEMORY_SIZE(new, mask);
132 size_t oldsize = ALIGN_MEMORY_SIZE(old, mask);
134 if (newsize > oldsize) {
135 unsigned char *data;
137 newsize *= objsize;
138 oldsize *= objsize;
140 #ifdef DEBUG_MEMLEAK
141 data = debug_mem_realloc(file, line, *ptr, newsize);
142 #else
143 data = mem_realloc(*ptr, newsize);
144 #endif
145 if (!data) return NULL;
147 *ptr = (void *) data;
148 memset(&data[oldsize], 0, newsize - oldsize);
151 return *ptr;
154 #ifdef DEBUG_MEMLEAK
155 #define mem_align_alloc(ptr, old, new, mask) \
156 mem_align_alloc__(__FILE__, __LINE__, (void **) ptr, old, new, sizeof(**ptr), mask)
157 #else
158 #define mem_align_alloc(ptr, old, new, mask) \
159 mem_align_alloc__((void **) ptr, old, new, sizeof(**ptr), mask)
160 #endif
162 /** @} */
165 /** @name Maybe-free macros
166 * @todo TODO: Think about making what they do more obvious in their
167 * identifier, they could be obfuscating their users a little for the
168 * newcomers otherwise.
169 * @{ */
171 #define mem_free_set(x, v) do { if (*(x)) mem_free(*(x)); *(x) = (v); } while (0)
172 #define mem_free_if(x) do { register void *p = (x); if (p) mem_free(p); } while (0)
174 #if 0
175 /* This may help to find bugs. */
176 #undef mem_free_if
177 #define mem_free_if(x) mem_free_set(&x, NULL)
178 #endif
179 /** @} */
182 /* This is out of place, but there is no better place. */
184 #ifdef DEBUG_MEMLEAK
185 #define intdup(i) intdup__(__FILE__, __LINE__, i)
186 #else
187 #define intdup(i) intdup__(i)
188 #endif
190 static inline int *
191 intdup__(
192 #ifdef DEBUG_MEMLEAK
193 unsigned char *file, int line,
194 #endif
195 int i)
197 #ifdef DEBUG_MEMLEAK
198 int *p = debug_mem_alloc(file, line, sizeof(*p));
199 #else
200 int *p = mem_alloc(sizeof(*p));
201 #endif
203 if (p) *p = i;
205 return p;
208 #endif