/*----- Functions and macros ----------------------------------------------*/
-/* --- @x_alloc@ --- *
+/* --- @x_alloc@, @x_allocv@ --- *
*
* Arguments: @arena *a@ = pointer to underlying arena
- * @size_t sz@ = size of block to allocate
+ * @size_t n@ = number of elements to allocate (for @x_allocv@)
+ * @size_t sz@ = size of elements to allocate
*
* Returns: Pointer to allocated block.
*
- * Use: Allocates memory. If there's not enough memory, the
- * exception @EXC_NOMEM@ is thrown.
+ * Use: The @x_allocv@ function allocates memory for @n@ elements of
+ * @sz@ bytes each (or, perhaps, %%\emph{vice versa}). The
+ * @x_alloc@ function is the same, but with @n@ fixed equal
+ * to 1. If there's not enough memory, the exception
+ * @EXC_NOMEM@ is thrown.
*/
extern void *x_alloc(arena */*a*/, size_t /*sz*/);
+extern void *x_allocv(arena */*a*/, size_t /*n*/, size_t /*sz*/);
+
+/* --- @X_NEW@, @X_NEWV@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ * @arena *a@ = pointer to underlying arena
+ * @size_t n@ = number of elements
+ *
+ * Returns: ---
+ *
+ * Use: Set @p@ to point to a freshly allocate block large enough for
+ * @n@ elements each of the type pointed to by @p@.
+ */
+
+#define X_NEW(p, a) do { (p) = x_alloc((a), sizeof(*(p))); } while (0)
+#define X_NEWV(p, a, n) \
+ do { (p) = x_allocv((a), (n), sizeof(*(p))); } while (0)
/* --- @x_strdup@ --- *
*
extern char *x_strdup(arena */*a*/, const char */*s*/);
-/* --- @x_realloc@ --- *
+/* --- @x_realloc@, @x_reallocv@ --- *
*
* Arguments: @arena *a@ = pointer to underlying arena
* @void *p@ = pointer to a block of memory
- * @size_t sz@ = new size desired for the block
- * @size_t osz@ = size of the old block
+ * @size_t n@ = new number of elements (for @x_reallocv@)
+ * @size_t on@ = old number of elements (for @x_reallocv@)
+ * @size_t sz@ = size of elements (for @x_reallocv@) or new
+ * block size (for @x_realloc@)
+ * @size_t osz@ = size of the old block (for @x_realloc@)
*
* Returns: Pointer to the resized memory block (which is almost
* certainly not in the same place any more).
*
* Use: Resizes a memory block. If there's not enough memory, the
* exception @EXC_NOMEM@ is thrown.
+ *
+ * The @x_reallocv@ function adjusts a block which currently has
+ * space for @on@ elements each of size @sz@, so that it now has
+ * enough space for @n@ elements, preserving the initial @min(n,
+ * on)@ elements. The @x_realloc@ function is the same, but
+ * with @sz@ fixed equal to 1, and @n@ and @on@ renamed to @sz@
+ * and @osz@ for historical reasons.
*/
extern void *x_realloc(arena */*a*/, void */*p*/,
size_t /*sz*/, size_t /*osz*/);
+extern void *x_reallocv(arena */*a*/, void */*p*/,
+ size_t /*n*/, size_t /*on*/, size_t /*sz*/);
+
+/* --- @X_RENEWV@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ * @arena *a@ = pointer to underlying arena
+ * @size_t n, on@ = new and existing numbers of elements
+ *
+ * Returns: ---
+ *
+ * Use: Adjust @p@ to point to a new block of memory with space for
+ * @n@ elements of the type pointed to by @p@, on the assumption
+ * that @p@ is either null or currently points to a block with
+ * space for @on@ elements.
+ */
+
+#define X_RENEWV(p, a, n, on) \
+ do { (p) = x_reallocv((a), (p), (n), (on), sizeof(*(p))); } while (0)
/* --- @x_free@ --- *
*
/*----- Old functions for the standard arena ------------------------------*/
-/* --- @xmalloc@ --- *
+/* --- @xmalloc@, @xmallocv@ --- *
*
- * Arguments: @size_t sz@ = size of block to allocate
+ * Arguments: @size_t n@ = number of elements to allocate (for @xmallocv@)
+ * @size_t sz@ = size of block to allocate
*
* Returns: Pointer to allocated block.
*
- * Use: Allocates memory. If there's not enough memory, the
- * exception @EXC_NOMEM@ is thrown.
+ * Use: Allocates memory for @n@ elements each of size @sz@. For
+ * @xmalloc@, @n@ is fixed equal to 1. If there's not enough
+ * memory, the exception @EXC_NOMEM@ is thrown.
*/
extern void *xmalloc(size_t /*sz*/);
+extern void *xmallocv(size_t /*n*/, size_t /*sz*/);
#define xmalloc(sz) x_alloc(arena_global, (sz))
+#define xmallocv(n, sz) x_allocv(arena_global, (n), (sz))
+
+/* --- @XNEW@, @XNEWV@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ * @size_t n@ = number of elements
+ *
+ * Returns: ---
+ *
+ * Use: Set @p@ to point to a freshly allocate block large enough for
+ * @n@ elements each of the type pointed to by @p@.
+ */
+
+#define XNEW(p) X_NEW(p, arena_global);
+#define XNEWV(p, n) X_NEWV(p, arena_global, n);
/* --- @xstrdup@ --- *
*
extern char *xstrdup(const char */*s*/);
#define xstrdup(p) x_strdup(arena_global, (p))
-/* --- @xrealloc@ --- *
+/* --- @xrealloc@, @xreallocv@ --- *
*
* Arguments: @void *p@ = pointer to a block of memory
- * @size_t sz@ = new size desired for the block
- * @size_t osz@ = size of the old block
+ * @size_t n@ = new number of elements (for @xreallocv@)
+ * @size_t on@ = old number of elements (for @xreallocv@)
+ * @size_t sz@ = size of elements (for @xreallocv@) or new
+ * block size (for @xrealloc@)
+ * @size_t osz@ = size of the old block (for @xrealloc@)
*
* Returns: Pointer to the resized memory block (which is almost
* certainly not in the same place any more).
*
* Use: Resizes a memory block. If there's not enough memory, the
* exception @EXC_NOMEM@ is thrown.
+ *
+ * The @xreallocv@ function adjusts a block which currently has
+ * space for @on@ elements each of size @sz@, so that it now has
+ * enough space for @n@ elements, preserving the initial @min(n,
+ * on)@ elements. The @xrealloc@ function is the same, but
+ * with @sz@ fixed equal to 1, and @n@ and @on@ renamed to @sz@
+ * and @osz@ for historical reasons.
*/
extern void *xrealloc(void */*p*/, size_t /*sz*/, size_t /*osz*/);
+extern void *xreallocv(void */*p*/,
+ size_t /*n*/, size_t /*on*/, size_t /*sz*/);
#define xrealloc(p, sz, osz) x_realloc(arena_global, (p), (sz), (osz))
+#define xreallocv(p, sz, osz, n) x_reallocv(arena_global, \
+ (p), (sz), (osz), (n))
+
+/* --- @XRENEWV@ --- *
+ *
+ * Arguments: @type *p@ = a pointer to allocate
+ * @size_t n, on@ = new and existing numbers of elements
+ *
+ * Returns: ---
+ *
+ * Use: Adjust @p@ to point to a new block of memory with space for
+ * @n@ elements of the type pointed to by @p@, on the assumption
+ * that @p@ is either null or currently points to a block with
+ * space for @on@ elements.
+ */
+
+#define XRENEWV(p, n, on) X_RENEWV((p), arena_global, (n), (on))
/* --- @xfree@ --- *
*