From 2d75df22efe25d4e50a6f1cc117f3258829316db Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Sun, 9 Feb 2020 18:06:28 +0100
Subject: [PATCH] add a dumb but working implementation of h_arena_realloc()

---
 src/allocator.c    | 29 +++++++++++++++++++++++++++++
 src/allocator.h    |  1 +
 src/parsers/bind.c |  3 +--
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/src/allocator.c b/src/allocator.c
index 2ff5caca..93c94e1d 100644
--- a/src/allocator.c
+++ b/src/allocator.c
@@ -267,3 +267,32 @@ void h_allocator_stats(HArena *arena, HArenaStats *stats) {
   stats->arena_li_malloc_bytes = arena->arena_li_malloc_bytes;
 #endif
 }
+
+void* h_arena_realloc(HArena *arena, void* ptr, size_t n) {
+  struct arena_link *link;
+  void* ret;
+  size_t ncopy;
+
+  // XXX this is really wasteful, but maybe better than nothing?
+  //
+  // first, we walk the blocks to find our ptr. since we don't know how large
+  // the original allocation was, we must always make a new one and copy as
+  // much data from the old block as there could have been.
+
+  for (link = arena->head; link; link = link->next) {
+    if (ptr >= (void *)link->rest && ptr <= (void *)link->rest + link->used)
+      break;	/* found it */
+  }
+  assert(link != NULL);
+
+  ncopy = (void *)link->rest + link->used - ptr;
+  if (n < ncopy)
+    ncopy = n;
+
+  ret = h_arena_malloc_noinit(arena, n);
+  assert(ret != NULL);
+  memcpy(ret, ptr, ncopy);
+  h_arena_free(arena, ptr);
+
+  return ret;
+}
diff --git a/src/allocator.h b/src/allocator.h
index 06d1e6f5..8ebde723 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -55,6 +55,7 @@ HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for def
 
 void* h_arena_malloc_noinit(HArena *arena, size_t count) ATTR_MALLOC(2);
 void* h_arena_malloc(HArena *arena, size_t count) ATTR_MALLOC(2);
+void* h_arena_realloc(HArena *arena, void* ptr, size_t count);
 void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers.
 void h_delete_arena(HArena *arena);
 void h_arena_set_except(HArena *arena, jmp_buf *except);
diff --git a/src/parsers/bind.c b/src/parsers/bind.c
index 87f42330..eac49744 100644
--- a/src/parsers/bind.c
+++ b/src/parsers/bind.c
@@ -21,8 +21,7 @@ static void *aa_alloc(HAllocator *allocator, size_t size)
 static void *aa_realloc(HAllocator *allocator, void *ptr, size_t size)
 {
     HArena *arena = ((ArenaAllocator *)allocator)->arena;
-    assert(((void)"XXX need realloc for arena allocator", 0));
-    return NULL;
+    return h_arena_realloc(arena, ptr, size);
 }
 
 static void aa_free(HAllocator *allocator, void *ptr)
-- 
GitLab