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

#ifdef DEBUG_ALLOCS
#undef safemalloc
#undef realloc
#undef free
typedef struct mem {
    struct mem *next;
    char *fname;
    int line;
    int length;
    void *ptr;
    char freed;
} mem;

mem *first_mem = NULL;

void *
 countmalloc(char *fname, int line, int length)
{
    mem *m = (mem *) malloc(sizeof(mem));
    memset(m, 0, sizeof(mem));
    m->next = first_mem;
    first_mem = m;
    m->fname = fname;
    m->line = line;
    m->length = length;
    m->ptr = safemalloc(length);
    m->freed = 0;
    return m->ptr;
}

void *
 countrealloc(char *fname, int line, void *ptr, int length)
{
    mem *m;
    if (ptr != NULL) {
       for (m = first_mem; m != NULL; m = m->next)
           if (m->ptr == ptr)
		break;
	if (m == NULL) {
	    printf("%s:mem to realloc not in list!\n", __FUNCTION__);
	    printf("%s:called from %s:%d\n", __FUNCTION__, fname, line);
	    exit(1);
	}
    } else {
        m = (mem *) malloc(sizeof(mem));
       memset(m, 0, sizeof(mem));
      }
    m->next = first_mem;

    first_mem = m;
    m->fname = fname;
    m->line = line;
    m->length = length;
    m->ptr = realloc(ptr, length);
    m->freed = 0;
    return m->ptr;
}

void countfree(char *fname, int line, void *ptr)
{
    mem *m1;
    mem *m2;

    for (m1 = m2 = first_mem; m1 != NULL; m2 = m1, m1 = m1->next)
       if (m1->ptr == ptr)
	    break;

    if (m1 == NULL) {
	printf("%s:mem to free not in list!\n", __FUNCTION__);
	printf("%s:called from %s:%d\n", __FUNCTION__, fname, line);
	exit(1);
    }
    free(m1->ptr);

#if 1
    if (m1->freed == 1) {
	printf("%s:mem already freed!\n", __FUNCTION__);
	printf("%s:freed from %s:%d\n", __FUNCTION__, (*m1).fname, (*m1).line);
	printf("%s:called from %s:%d\n", __FUNCTION__, fname, line);
	exit(1);
    }
    m1->freed = 1;
    m1->fname = fname;
    m1->line = line;
#else
    if (m1 == first_mem)
       first_mem = m1->next;
    else
       m2->next = m1->next;
    free(m1);
#endif
}

void print_unfreed_mem(void)
{
    mem *m;

    printf("%s\n", __FUNCTION__);
    for (m = first_mem; m != NULL; m = m->next)
       if (m->freed == 0)
           printf(" %20s:%4d:%d\n", m->fname, m->line, m->length);
}
#endif				/*DEBUG_ALLOCS */
/***********************************************************************
 *
 *  Procedure:
 *	safemalloc - mallocs specified space or exits if there's a 
 *		     problem
 *
 ***********************************************************************/
char *
 safemalloc(int length)
{
    char *ptr;

    if (length <= 0)
	length = 1;

    ptr = malloc(length);
    if (ptr == (char *) 0) {
	fprintf(stderr, "malloc of %d bytes failed. Exiting\n", length);
	exit(1);
    }
    return ptr;
}
