#include <stdio.h>
#ifndef NO_STDLIB_H
#include <stdlib.h>
#endif

#ifdef MALLOC_DEBUG
#undef MALLOC_DEBUG
#endif

#include "slang.h"

static void fixup (unsigned char *p, unsigned long n)
{
   *p = (unsigned char) ((n >> 24) & 0xFF);
   *(p + 1) = (unsigned char) ((n >> 16) & 0xFF);
   *(p + 2) = (unsigned char) ((n >> 8) & 0xFF);
   *(p + 3) = (unsigned char) (n & 0xFF);
   *(p + (int) (n + 4)) = 27;
   *(p + (int) (n + 5)) = 182;
   *(p + (int) (n + 6)) = 81;
   *(p + (int) (n + 7)) = 86;
}

static int check_memory (unsigned char *p, char *what)
{
   char buf[100];
   unsigned long n;
   
   n = ((unsigned long) *(p - 4)) << 24;
   n |= ((unsigned long) *(p - 3)) << 16;
   n |= ((unsigned long) *(p - 2)) << 8;
   n |= (unsigned long) *(p - 1);
   
   *(p - 4) = *(p - 3) = *(p - 2) = *(p - 1) = 0xFF;
   if (n == 0xFFFFFFFFL)
     {
	sprintf (buf, "%s: %p: Already FREE! Abort NOW.", what, p - 4);
	SLang_doerror (buf);
	return 0;
     }
   
   if ((*(p + (int) n) != 27)
       || (*(p + (int) (n + 1)) != 182)
       || (*(p + (int) (n + 2)) != 81)
       || (*(p + (int) (n + 3)) != 86))
     {
	sprintf (buf, "%s: %p: Memory corrupt! Abort NOW.", what, p - 4);
	SLang_doerror (buf);
	return 0;
     }
   return 1;
}

  

void SLdebug_free (unsigned char *p)
{   
   if (!check_memory ((unsigned char *) p, "FREE")) return;
   FREE (p - 4);
}

unsigned char *SLdebug_malloc (unsigned long n)
{
   unsigned char *p;
   
   if ((p = (unsigned char *) MALLOC (n + 8)) == NULL) return NULL;
   
   fixup ((unsigned char *) p, n);
   return p + 4;
}

unsigned char *SLdebug_realloc (unsigned char *p, unsigned long n)
{
   if (!check_memory ((unsigned char *) p, "REALLOC")) return NULL;
   if ((p = (unsigned char *) REALLOC (p - 4, n + 8)) == NULL) return NULL;
   fixup ((unsigned char *) p, n);
   return p + 4;
}

unsigned char *SLdebug_calloc (unsigned long n, unsigned long size)
{
   unsigned char *p;
   int m;
   
   /* This is tough -- hope this is a good assumption!! */
   if (size >= 4) m = 1; else m = 4;
   
   if ((p = (unsigned char *) CALLOC (n + m + m, size)) == NULL) return NULL;
   fixup ((unsigned char *) p, size * n);
   return p + 4;
}


#undef MALLOC
#undef REALLOC
#undef CALLOC
#undef FREE

void FREE (void)
{
   fprintf(stderr, "You compiled wrong!");
   exit (-1);
}
void REALLOC (void)
{
   fprintf(stderr, "You compiled wrong!");
   exit (-1);
}
void MALLOC (void)
{
   fprintf(stderr, "You compiled wrong!");
   exit (-1);
}
void CALLOC (void)
{
   fprintf(stderr, "You compiled wrong!");
   exit (-1);
}
