#include <stdio.h>
#include <ssdef.h>
#include <stdlib.h>
#include <starler.h>
#include <lib$routines.h>

#define MAX_CHECKS
#ifdef MAX_CHECKS

int mem_list_size=0;
char *mem_list[100000];

#endif

#define SENTINAL -16

static void dummy_access(sent, flag, last)
  char sent, flag, last;
{
   printf("%s: error trying to free!!! %s sentinal has been replaced by %d!\n",
          (flag==0)?"CHECK":"REAL", last?"END":"START", sent);
   lib$signal(88);
}

static void dummy_verbose_access(sent, flag, last, len, start)
  char sent, flag, last, *start;
  short len;
{
   printf("%s: error trying to free!!! %s sentinal has been replaced by %d!\n",
          (flag==0)?"CHECK":"REAL", last?"END":"START", sent);
   printf("%d len\n", len);
/*   printf("%*.*s\n", len-1, len-1, start); */
   lib$signal(88);
}

void mem_check_access(add)
  char *add;
{
  short *slen;
  if (!add) return;
  slen = (short *)((int)add - 3);
  if (add[*slen] != SENTINAL) dummy_access(add[*slen], 0, 0);
  if (add[-1] != SENTINAL) dummy_access(add[-1], 0, 1);
}

#ifdef MAX_CHECKS
int check_all_malloc(char *str)
{
  char *add;
  short *len;
  int loop, ok = 1;
  for (loop=0;loop<mem_list_size;loop++)
  {
    add = mem_list[loop];
    if (add) {
      len = (short *)((int)add - 3);
      if (add[*len] != SENTINAL) {
        printf("%s\n", str);
        dummy_verbose_access(add[*len], 1, 0, *len, add);
        ok = 0;
      }
      if (add[-1] != SENTINAL) {
        printf("%s\n", str);
        dummy_verbose_access(add[-1], 1, 1, *len, add);
        ok = 0;
      }
    }
  }
  return ok;
}
#endif

void myfree(add)
  char *add;
{
  char *sent;
  short *len;
  int old;
  if (!add) return;
  old = sys$setast(0);
  len = (short *)((int)add - 3);
  if (add[*len] != SENTINAL) dummy_access(add[*len], 1, 0);
  if (add[-1] != SENTINAL) dummy_access(add[-1], 1, 1);
  add[*len] = 0;
  add[-1] = 0;
#ifdef MAX_CHECKS
  {
    int loop;
    for (loop=0;loop<mem_list_size;loop++)
      if (mem_list[loop]==add) {
        mem_list[loop] = NULL;
        if (loop==(mem_list_size-1)) mem_list_size--;
        break;
      }
  }
#endif
  free(&add[-3]);
  if (old == SS$_WASSET) sys$setast(1);
}

/*

size data sentinal  real data    sentinal
[0][1]    [2]       [3][4][5]    [6]

*/

char *mymalloc(len)
  int len;
{
  char *ret;
  short *rlen;
  int old;

  if (!len) return NULL;
  old = sys$setast(0);
  ret = (char *)malloc(len+4);
  rlen = (short *)ret;
  ret += 3;
  *rlen = len;
  ret[-1] = SENTINAL;
  ret[len] = SENTINAL;
#ifdef MAX_CHECKS
  {
    int loop, found=0, found_at;
    for (loop=0;!found && (loop<mem_list_size);loop++)
      if (mem_list[loop]==0) found = 1;
    if (found) mem_list[loop-1] = ret;
    else {
      mem_list[mem_list_size++] = ret;
      if (mem_list_size>5000) printf("5000 elements!!!!\n\n");
    }
    if (!check_all_malloc("in malloc"))
    {
      printf("Failure when trying to malloc %d bytes element, ele %d\n", len,
             mem_list_size-1);
    }
  }
#endif
  if (old == SS$_WASSET) sys$setast(1);
  return ret;
}
