/* Placeholders for what's in lisp.h already. */ #include #include #include typedef long Lisp_Object; enum { word_size = sizeof (Lisp_Object) }; enum { MAX_ALLOCA = 16 * 1024 }; #define USE_SAFE_ALLOCA bool sa_must_free = false #define SAFE_FREE() (sa_must_free ? magic_freer () : (void) 0) #define min(a, b) ((a) < (b) ? (a) : (b)) extern void *xnmalloc (size_t, size_t); extern Lisp_Object make_save_memory (Lisp_Object *, ptrdiff_t); extern void magic_freer (void); extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object); extern void free_save_value (Lisp_Object); extern _Noreturn void memory_full (size_t); /* The new macro. */ #ifdef __STDC_NO_VLA__ # define SAFE_LISP_ARRAY(name, elems) \ Lisp_Object *name; \ SAFE_ALLOCA_LISP (name, elems) #else # define SAFE_LISP_ARRAY(name, elems) \ ptrdiff_t name##n = elems; \ bool name##issmall = name##n <= MAX_ALLOCA / word_size; \ Lisp_Object name##vec[name##issmall && name##n ? name##n : 1]; \ Lisp_Object *name; \ if (name##issmall) \ name = name##vec; \ else \ { \ name = xnmalloc (name##n, word_size); \ record_unwind_protect (free_save_value, \ make_save_memory (name, name##n)); \ sa_must_free = true; \ } #endif /* Example use. */ Lisp_Object foo (ptrdiff_t n) { USE_SAFE_ALLOCA; SAFE_LISP_ARRAY (foo, n); for (ptrdiff_t i = 0; i < n; i++) foo[i] = i; Lisp_Object x = 0; for (ptrdiff_t i = 0; i < n; i++) x ^= foo[0]; SAFE_FREE (); return x; }