/* sketch for the routines controlling memory leaks. Doesn't work yet */
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gtk/gtk.h>

#define ARKA_MAX_STACK 10000

typedef struct {
	void *ptr ;
	char *filename ;
	int line ;
	size_t bytes ;
	int times ;
} allocated_t ;


allocated_t alloc_stack[ARKA_MAX_STACK] ;

int alloc_start = 0 ;
int alloc_total = 0 ;
size_t alloc_total_mem = 0 ;


void *arka_malloc(char *fct, int line, size_t size) {
	void *allocated ;
	int i ;

	for(i = 0 ; i < alloc_start && alloc_stack[i].ptr != NULL ; i++) ;
	if(i == alloc_start) alloc_start++ ;

	allocated = g_malloc(size) ;
	alloc_total++ ;
	alloc_total_mem += size ;

	if(i >= ARKA_MAX_STACK) {
		fprintf(stderr, "Bad news: no further stacking of malloc call possible\n") ;
		fprintf(stderr, "Caller: File: %s Line: %i\n", fct, line) ;
		return allocated ;
	} else {
		alloc_stack[i].ptr = allocated ;
		alloc_stack[i].filename = fct ;
		alloc_stack[i].line = line ;
		alloc_stack[i].bytes = size ;
		return allocated ;
	}
		
}


void *arka_realloc(char *fct, int line, void *ptr, size_t size) {
	int i ;
	void *res ;

	for(i = 0 ; i < alloc_start && alloc_stack[i].ptr != ptr ; i++) ;

	if(i >= alloc_start) {
		fprintf(stderr, "Reallocating a non-existing pointer.\n") ;
		fprintf(stderr, "Caller: File: %s Line: %i\n", fct, line) ;
	}
		
	alloc_total_mem += size - alloc_stack[i].bytes ;
	alloc_stack[i].bytes = size ;
	res = g_realloc(ptr, size) ;

	return res ;
}


void arka_free(char *fct, int line, void *ptr) {
	int i ;

	if(ptr == NULL) {
		fprintf(stderr, "Trying to free NULL ptr, file %s, line %i\n",
			fct, line) ;
		return ;
	}

	for(i = 0 ; i < alloc_start && alloc_stack[i].ptr != ptr ; i++) ;

	/* some memory will be reserved by gtk* functions */
	if(i < alloc_start) {
		alloc_stack[i].ptr = NULL ;
		if(i + 1 == alloc_start && i > 0) alloc_start-- ;
	}

	g_free(ptr) ;

}


void memory_start() {
	int i ;

	return ;
	for(i = 0 ; i < ARKA_MAX_STACK ; i++) {
		alloc_stack[i].ptr = NULL ;
	}

}


void memory_summary() {
	int i, j, alloc_left = 0, last = 0 ;
	size_t alloc_left_mem = 0 ;
	allocated_t summary[ARKA_MAX_STACK] ;

	fprintf(stderr, "Pointers which were not freed:\n") ;

	for(i = 0 ; i < ARKA_MAX_STACK ; i++) {
		summary[i].line = 0 ;
		summary[i].filename = NULL ;
		summary[i].bytes = 0 ;
		summary[i].times = 0 ;
	}

	for(i = 0 ; i < ARKA_MAX_STACK ; i++) {

		if(alloc_stack[i].ptr != NULL) {
			alloc_left++ ;
			
			/* looking for the right slot in the summary */
			for(j = 0 ; 
				j < last 
				&& summary[j].filename != NULL 
				&& (summary[j].line != alloc_stack[i].line 
				|| strcmp(summary[j].filename, alloc_stack[i].filename)) != 0 ;
				j++) ;
			
			if(j == last) {
				summary[j].filename = alloc_stack[i].filename ;
				summary[j].line = alloc_stack[i].line ;
				last++ ;
			}

			summary[j].bytes += alloc_stack[i].bytes ;
			alloc_left_mem += alloc_stack[i].bytes ;
			summary[j].times++ ;

		}
	}

	for(i = 0 ; i < last ; i++) {
		fprintf(stderr, "%s: line %i bytes %i. %i time(s)\n", 
			summary[i].filename, summary[i].line, summary[i].bytes, summary[i].times) ;
	}

	fprintf(stderr, "Number of allocated pointers: %i not freed: %i\n", 
		alloc_total, alloc_left) ;

	fprintf(stderr, "Total bytes not freed: %i\n", alloc_left_mem) ;
	fprintf(stderr, "Allocated at least %i bytes in toto\n", alloc_total_mem) ;

}
