Add efficient realloc()
diff --git a/src/kernel/alloc.c b/src/kernel/alloc.c
index 4edc791..bcd58ae 100644
--- a/src/kernel/alloc.c
+++ b/src/kernel/alloc.c
@@ -157,7 +157,8 @@
 
 	// Header of block before this one
 	struct heap_alloc_header *prev_h =
-		(struct heap_alloc_header *)((size_t)prev_f - prev_f->size + FOOTER_SIZE);
+		(struct heap_alloc_header *)((size_t)prev_f - prev_f->size +
+									 FOOTER_SIZE);
 
 	// Header of block after this one
 	struct heap_alloc_header *next_h =
@@ -190,3 +191,79 @@
 
 	heap_insert(&heap, entry);
 }
+
+void *realloc(void *mem, size_t size)
+{
+	if (!mem)
+		return NULL; // freeing NULL ptr
+
+	struct heap_alloc_header *base =
+		(struct heap_alloc_header *)((size_t)mem - HEADER_SIZE);
+	struct heap_alloc_header *next =
+		(struct heap_alloc_header *)((size_t)base + base->size);
+
+	if (!next->allocated &&
+		next->size + base->size - HEADER_SIZE - FOOTER_SIZE >= size)
+	{
+		// Okay, we can just expand this block
+		// Actually, need to check if there is enough space remaining for an
+		// additional block, otherwise, just add that memory to this block (
+		// same as is done in malloc )
+
+		struct heap_alloc_footer *f;
+
+		size_t remaining =
+			base->size + next->size - size - HEADER_SIZE - FOOTER_SIZE;
+
+		struct heap_entry old_entry = {
+			.key = next->size,
+			.address = (size_t)next,
+		};
+
+		if (remaining <= HEADER_SIZE + FOOTER_SIZE + 8)
+		{
+			// Just join this into the same memory chunk
+			f = (struct heap_alloc_footer *)(next + next->size - FOOTER_SIZE);
+
+			heap_delete_entry(&heap, old_entry);
+		}
+		else
+		{
+			f = mem + size;
+			struct heap_alloc_header *new_h =
+				(struct heap_alloc_header *)(f + FOOTER_SIZE);
+
+			struct heap_alloc_footer *new_f =
+				(struct heap_alloc_footer *)(new_h + remaining - FOOTER_SIZE);
+
+			new_h->allocated = false;
+			new_h->size = new_f->size = remaining;
+			new_h->magic = HEAP_MAGIC;
+
+			struct heap_entry entry = {
+				.key = remaining,
+				.address = (size_t)new_h,
+			};
+
+			heap_decrease_entry(&heap, old_entry, entry);
+		}
+
+		size_t full_size = (size_t)f - (size_t)base + FOOTER_SIZE;
+
+		f->size = full_size;
+		base->size = full_size;
+		base->magic = HEAP_MAGIC;
+		base->allocated = true;
+	}
+	else
+	{
+		void *new = malloc(size);
+		if (!new)
+			return new;
+
+		memcpy(new, mem, base->size - HEADER_SIZE - FOOTER_SIZE);
+		free(mem);
+
+		return new;
+	}
+}