html_special(): move va_end() call outside the switch and make variables
[elinks.git] / src / util / memory.h
blobd03f0b674c2e86c2319fdccfbac0755a23558ad5
2 #ifndef EL__UTIL_MEMORY_H
3 #define EL__UTIL_MEMORY_H
5 /* If defined, we'll crash if ALLOC_MAXTRIES is attained,
6 * if not defined, we'll try to continue. */
7 /* #define CRASH_IF_ALLOC_MAXTRIES */
9 /* Max. number of retry in case of memory allocation failure. */
10 #define ALLOC_MAXTRIES 3
12 /* Delay in seconds between each alloc try. */
13 #define ALLOC_DELAY 3
15 #define fmem_alloc(x) mem_alloc(x)
16 #define fmem_free(x) mem_free(x)
19 /* Cygwin wants some size_t definition here... let's try to make it happy
20 * then. Hrmpf. */
21 #include <sys/types.h>
22 #include <stddef.h>
24 #ifdef HAVE_MMAP
25 void *mem_mmap_alloc(size_t size);
26 void mem_mmap_free(void *p, size_t size);
27 void *mem_mmap_realloc(void *p, size_t old_size, size_t new_size);
28 #else
29 #define mem_mmap_alloc(x) mem_alloc(x)
30 #define mem_mmap_free(x, y) mem_free(x)
31 #define mem_mmap_realloc(x, y, z) mem_realloc(x, z)
32 #endif
35 #ifdef DEBUG_MEMLEAK
37 #include "util/memdebug.h"
39 #define mem_alloc(x) debug_mem_alloc(__FILE__, __LINE__, x)
40 #define mem_calloc(x, y) debug_mem_calloc(__FILE__, __LINE__, x, y)
41 #define mem_free(x) debug_mem_free(__FILE__, __LINE__, x)
42 #define mem_realloc(x, y) debug_mem_realloc(__FILE__, __LINE__, x, y)
44 #else
46 #ifndef CONFIG_FASTMEM
48 void *mem_alloc(size_t);
49 void *mem_calloc(size_t, size_t);
50 void mem_free(void *);
51 void *mem_realloc(void *, size_t);
53 #else
55 # include <stdlib.h>
57 /* TODO: For enhanced portability, checks at configure time:
58 * malloc(0) -> NULL
59 * realloc(NULL, 0) -> NULL
60 * realloc(p, 0) <-> free(p)
61 * realloc(NULL, n) <-> malloc(n)
62 * Some old implementations may not respect these rules.
63 * For these we need some replacement functions.
64 * This should not be an issue on most modern systems.
67 # define mem_alloc(size) malloc(size)
68 # define mem_calloc(count, size) calloc(count, size)
69 # define mem_free(p) free(p)
70 # define mem_realloc(p, size) realloc(p, size)
73 /* fmem_* functions should be use for allocation and freeing of memory
74 * inside a function.
75 * See alloca(3) manpage. */
77 #undef fmem_alloc
78 #undef fmem_free
80 #ifdef HAVE_ALLOCA
82 #ifdef HAVE_ALLOCA_H
83 #include <alloca.h>
84 #endif
85 #define fmem_alloc(x) alloca(x)
86 #define fmem_free(x)
88 #else /* HAVE_ALLOCA */
90 #define fmem_alloc(x) mem_alloc(x)
91 #define fmem_free(x) mem_free(x)
93 #endif /* HAVE_ALLOCA */
95 #endif /* CONFIG_FASTMEM */
97 #endif /* DEBUG_MEMLEAK */
100 /* Granular memory allocation. */
102 /* The ``old'' style granularity. XXX: Must be power of 2 */
103 #define ALLOC_GR 0x100
105 #include <string.h> /* for memset() */
107 /* The granularity used by the aligned memory functions below must be a mask
108 * with all bits set from but not including the most significant bit and down.
109 * So if an alignment of 256 is wanted use 0xFF. */
111 #define ALIGN_MEMORY_SIZE(x, gr) (((x) + (gr)) & ~(gr))
113 static inline void *
114 mem_align_alloc__(
115 #ifdef DEBUG_MEMLEAK
116 unsigned char *file, int line,
117 #endif
118 void **ptr, size_t old, size_t new, size_t objsize, size_t mask)
120 size_t newsize = ALIGN_MEMORY_SIZE(new, mask);
121 size_t oldsize = ALIGN_MEMORY_SIZE(old, mask);
123 if (newsize > oldsize) {
124 unsigned char *data;
126 newsize *= objsize;
127 oldsize *= objsize;
129 #ifdef DEBUG_MEMLEAK
130 data = debug_mem_realloc(file, line, *ptr, newsize);
131 #else
132 data = mem_realloc(*ptr, newsize);
133 #endif
134 if (!data) return NULL;
136 *ptr = (void *) data;
137 memset(&data[oldsize], 0, newsize - oldsize);
140 return *ptr;
143 #ifdef DEBUG_MEMLEAK
144 #define mem_align_alloc(ptr, old, new, obj, mask) \
145 mem_align_alloc__(__FILE__, __LINE__, (void **) ptr, old, new, sizeof(obj), mask)
146 #else
147 #define mem_align_alloc(ptr, old, new, obj, mask) \
148 mem_align_alloc__((void **) ptr, old, new, sizeof(obj), mask)
149 #endif
152 /* Maybe-free macros */
153 /* TODO: Think about making what they do more obvious in their identifier, they
154 * could be obfuscating their users a little for the newcomers otherwise. */
156 #define mem_free_set(x, v) do { if (*(x)) mem_free(*(x)); *(x) = (v); } while (0)
157 #define mem_free_if(x) do { register void *p = (x); if (p) mem_free(p); } while (0)
159 #if 0
160 /* This may help to find bugs. */
161 #undef mem_free_if
162 #define mem_free_if(x) mem_free_set(&x, NULL)
163 #endif
165 #endif