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

#define MAX_CATCH_ALLOC		(32)

extern void *mallocwrapper_realMalloc(size_t);
extern void *mallocwrapper_realRealloc(void *, size_t);
extern void mallocwrapper_realFree(void *);

int mallocwrapper_enableTrace = 1;
void *mallocwrapper_catchAlloc[MAX_CATCH_ALLOC] = { NULL };
int mallocwrapper_catchAllocMax = MAX_CATCH_ALLOC;

void mallocwrapper_catch(const char *id, void *ptr, int index)
{
  printf("mallocwrapper_catch(id = \"%s\", ptr = 0x%lx, index = %i)\n",
      id, (unsigned long)ptr, index);
}

static void mallocwrapper_checkAddr(void *ptr, const char *id)
{
  int i;

  if (ptr == NULL)
    return;
  for (i = 0; i < MAX_CATCH_ALLOC; ++i)
  {
    if (!mallocwrapper_catchAlloc[i])
      continue;
    if (mallocwrapper_catchAlloc[i] == ptr)
    {
      mallocwrapper_catch(id, ptr, i);
      break;
    }
  }
}

void *malloc(size_t size)
{
  void *ptr = mallocwrapper_realMalloc(size);

  if (mallocwrapper_enableTrace)
    mallocwrapper_checkAddr(ptr, "malloc");
  return ptr;
}

void *calloc(size_t nmemb, size_t size)
{
  void *ptr;

  size *= nmemb;
  ptr = malloc(size);
  memset(ptr, 0, size);
  return ptr;
}

void *realloc(void *ptr, size_t size)
{
  if (mallocwrapper_enableTrace)
    mallocwrapper_checkAddr(ptr, "realloc-in");
  ptr = mallocwrapper_realRealloc(ptr, size);
  if (mallocwrapper_enableTrace)
    mallocwrapper_checkAddr(ptr, "realloc");
  return ptr;
}

void free(void *ptr)
{
  if (mallocwrapper_enableTrace)
    mallocwrapper_checkAddr(ptr, "free");
  mallocwrapper_realFree(ptr);
}

