view src/ploki/xmalloc.c @ 12292:d51f2100210c draft

<kspalaiologos> `` cat <<<"asmbf && bfi output.b" > /hackenv/ibin/asmbf
author HackEso <hackeso@esolangs.org>
date Thu, 02 Jan 2020 15:38:21 +0000
parents ac0403686959
children
line wrap: on
line source

#include "config.h"
#include "main.h"
#include "xmalloc.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef DEBUG_MALLOC
	#define IF_DB(x) x
#else
	#define IF_DB(x)
#endif

static struct node {
	void *ptr;
	struct node *prev, *next;
	size_t size;
	#if DEBUG_P
		const char *file;
		unsigned line;
	#endif
} *Root;

#if 0
int xdump(void) {
	struct node *p;

	fprintf(stderr, ":%p\n", Root);
	for (p = Root; p; p = p->next) {
		fprintf(stderr, "\\<%p [%p]%p %p>\n", p->prev, p, p->ptr, p->next);
		assert(p != p->next);
	}
	fprintf(stderr, "\n");
	return 0;
}
#endif

void xend(void) {
	struct node *p;

	while ((p = Root)) {
#if DEBUG_P
		unsigned char *ptr;
		for (ptr = p->ptr; memcmp(ptr, &p, sizeof p); ++ptr)
			;
		ptr += sizeof p;
		fprintf(stderr, "%s: autofreeing pointer %p (%p) from %s:%u\n", Prog, p->ptr, (void *)ptr, p->file, p->line);
#else
		fprintf(stderr, "%s: autofreeing pointer %p\n", Prog, p->ptr);
#endif
		free(p->ptr);
		assert(Root != p->next);
		Root = p->next;
		free(p);
	}
}

#define XFACTOR(size) ((sizeof (struct node *) - 1) / (size) + 1u)

#if DEBUG_P
void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) {
#else
void *xrealloc(void *optr, size_t nmemb) {
#endif
	struct node *p;
	size_t k;
	size_t size;
	unsigned char *r;
	void *ptr;

	assert(optr != NULL);

	memcpy(&p, (unsigned char *)optr - sizeof Root, sizeof p);
	size = p->size;
	k = XFACTOR(size) * size;
	if (!(ptr = realloc(p->ptr, size * nmemb + k))) {
		fprintf(stderr, "%s: realloc(%p, %lu): %s\n", Prog, ptr, (unsigned long)(nmemb * size), strerror(errno));
		abort();
	}
	r = (unsigned char *)ptr + k;
	#if DEBUG_P
		IF_DB(fprintf(stderr, "%s: xrealloc(%zu): %p (%p) from %s:%u -> %p (%p) from %s:%u\n", Prog, nmemb, p->ptr, optr, p->file, p->line, ptr, r, file, line));
		p->file = file;
		p->line = line;
	#endif
	p->ptr = ptr;
	return r;
}

#if DEBUG_P
void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
#else
void *xmalloc(size_t nmemb, size_t size) {
#endif
	struct node *p;
	size_t k;
	unsigned char *r;

	if ((p = malloc(sizeof *p))) {
		k = XFACTOR(size) * size;
		if (!(p->ptr = malloc(size * nmemb + k))) {
			free(p);
			goto failure;
		}
	} else failure: {
		fprintf(stderr, "%s: malloc(%lu): %s\n", Prog, (unsigned long)(nmemb * size), strerror(errno));
		abort();
	}
	#if DEBUG_P
		memset(p->ptr, 'U', k);
	#endif
	r = (unsigned char *)p->ptr + k;
	memcpy(r - sizeof Root, &p, sizeof p);
	p->size = size;
	p->prev = NULL;
	p->next = Root;
	#if DEBUG_P
		p->file = file;
		p->line = line;
		IF_DB(fprintf(stderr, "%s: xmalloc(%zu, %zu): %p (%p) from %s:%u\n", Prog, nmemb, size, p->ptr, r, file, line));
	#endif
	if (Root) {
		Root->prev = p;
	}
	Root = p;
	return r;
}

#if 0
#if DEBUG_P
void *(xcalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
	void *const p = xmalloc(nmemb, size, file, line);
#else
void *xcalloc(size_t nmemb, size_t size) {
	void *const p = xmalloc(nmemb, size);
#endif
	memset(p, '\0', nmemb * size);
	return p;
}
#endif

void xfree(void *ptr) {
	struct node *p;

	if (!ptr)
		return;
	memcpy(&p, (unsigned char *)ptr - sizeof Root, sizeof p);
	assert(p != NULL);
	DEBUG(memset((unsigned char *)ptr - sizeof Root, 'F', sizeof Root));

	if (p->next) {
		p->next->prev = p->prev;
	}
	if (p->prev) {
		p->prev->next = p->next;
	} else {
		assert(p == Root);
		Root = Root->next;
	}
	#if DEBUG_P
		IF_DB(fprintf(stderr, "%s: xfree(): %p (%p) from %s:%u\n", Prog, p->ptr, ptr, p->file, p->line));
	#endif
	free(p->ptr);
	free(p);
}