/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	"xlerror.h"
#include	"xl.h"
#include	"memory_debug.h"

XL_SEXP * xl_MemoryStatistics();


void
init_MemoryStatistics(XLISP_ENV * env)
{
	set_env(env,l_string(std_cm,"MemoryStatistics"),
		get_func_prim(xl_MemoryStatistics,FO_APPLICATIVE,0,1,1));
}

XL_SEXP *
xl_MemoryStatistics(XLISP_ENV * env,XL_SEXP * s,
	XLISP_ENV * a,XL_SYM_FIELD * sf)
{
char ** buf;
int * cnt;
int *size;
int i,j;
XL_SEXP * ret;
extern int malloc_count,free_count;
int t;
char * ptr;
int max;
int total;
	max = MT_MAX;
	for ( ; sf ; sf = sf->next ) {
		if ( l_strcmp(sf->name,l_string(std_cm,"max")) == 0 )
			max = atoi(n_string(std_cm,sf->data));
	}
	buf = d_alloc(sizeof(char*)*MT_MAX,13);
	cnt = d_alloc(sizeof(int)*MT_MAX,14);
	size = d_alloc(sizeof(int)*MT_MAX,15);
	indicate_md_in_buf(buf,cnt,size);
	total = malloc_count;
	for ( i = 0 ; i < MT_MAX ; i ++ ) {
		total += size[i];
		for ( j = i+1 ; j < MT_MAX ; j ++ ) {
			if ( cnt[i] < cnt[j] ) {
				t = cnt[i];
				cnt[i] = cnt[j];
				cnt[j] = t;

				ptr = buf[i];
				buf[i] = buf[j];
				buf[j] = ptr;
			}
		}
	}
	d_f_ree(size);
	ret = cons(List(n_get_string("TOTAL"),
			get_integer(total,0),
			-1),0);
	for ( i = max-1 ; i >= 0 ; i -- ) {
		if ( buf[i] == 0 )
			continue;
		ret = cons(
			List(n_get_string(buf[i]),
				get_integer(cnt[i],0),
				-1),
			ret);
	}
	ret = cons(n_get_symbol("dm"),ret);
	ret = cons(List(	n_get_symbol("gcmalloc"),
				get_integer(malloc_count,0),
				-1),
		cons(List(	n_get_symbol("gcfree"),
				get_integer(free_count,0),
				-1),
			cons(ret,0)));
	free_indicate_md_buf(buf);
	d_f_ree(buf);
	d_f_ree(cnt);
	return ret;
}


