pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/*****************************************************************************
 ** MEMSTAT: A set of routines to determine where all that bloody memory
 **          is going to!
 ****************************************************************************/
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/types.h>
#include "gen.h"
#include "events.h"
#include "config.h"

/* Definition for a linked list with all used types in it, where we can store
 * how many entries of each block have been allocated.
 */
typedef struct _memoryBlock 
{  size_t   count;
   int      typenr;
   struct   _memoryBlock *next;
} memoryBlock;

typedef struct _dataType
{   char   *name;
    int	   typenr;
    size_t datasize;
} dataType;

dataType LocalTypes[] = {
  { "token_record",	REC_TOKEN,	sizeof(token_record) },
  { "string_record",    REC_STRING,	sizeof(string_record) },
  { "loc_str_record",	REC_LOCSTR,	sizeof(loc_str_record) },
  { "location_record",	REC_LOCATION,	sizeof(location_record) },
  { "mobile_record",	REC_MOBILE,	sizeof(mobile_record) },
  { "object_record",    REC_OBJECT,	sizeof(object_record) },
  { "zone_record",	REC_ZONE,	sizeof(zone_record) },
  { "thecode_record",	REC_THECODE,	sizeof(thecode_record) },
  { "param_record",     REC_PARAM,	sizeof(param_record) },
  { "mudcode_record",	REC_MUDCODE,	sizeof(mudcode_record) },
  { "stmt_list_record", REC_STMTLIST,	sizeof(stmt_list_record) },
  { "trap_desc",	REC_TRAPDESC,	sizeof(trap_desc) },
  { "trap_record",	REC_TRAP,	sizeof(trap_record) },
  { "memoryBlock",	REC_MEMSTAT,	sizeof(memoryBlock) },
  { "arith_number",	REC_ARITHNR,	sizeof(arith_number) },
  { "arith_string",	REC_ARITHSTR,	sizeof(arith_string) },
  { "mudfunct_param",	REC_MFPARAM,	sizeof(mudfunct_param) },
  { "mudfunct_decl",	REC_MFDECL,	sizeof(mudfunct_decl) },
  { "ident_decl",	REC_IDENTDECL,	sizeof(ident_decl) },
  { "raw_decl",		REC_RAWDECL,	sizeof(raw_decl) },
  { "block_decl",	REC_BLOCKDECL,	sizeof(block_decl) },
  { "if_decl",		REC_IFDECL,	sizeof(if_decl) },
  { "while_decl",	REC_WHILEDECL,	sizeof(while_decl) },
  { "for_decl",		REC_FORDECL,	sizeof(for_decl) },
  { "const_decl",	REC_CONSTDECL,	sizeof(const_decl) },
  { "var_decl",		REC_VARDECL,	sizeof(var_decl) },
  { "the_stmt",		REC_THESTMT,	sizeof(the_stmt) },
  { "stmt_record",	REC_STMT,	sizeof(stmt_record) },
  { "hashRecord",	REC_HRECORD,	sizeof(hashRecord) },
  { "hashTable",	REC_HTABLE,	sizeof(hashTable) },
  { "string",		REC_CHAR,	sizeof(char) },
  { "ConfigOpt",	REC_CONFIG,	sizeof(ConfigOpt) },
  { "event_record",	REC_EVENT,	sizeof(event_record) },
  { "bool_stmt",        REC_BOOLSTMT,   sizeof(bool_stmt) },
  { TABLE_END,		-1 ,		-1}
};

memoryBlock *dynamicList = NULL;

void updateMemStat(int typenr, int count)
{   memoryBlock *p = dynamicList;

    while (p != NULL && p->typenr != typenr)
         p = p->next;

    if (p != NULL)
       p->count += count;
}

void initializeMemStat()
{   memoryBlock *p;
    int i;
    
    for (i = 0; LocalTypes[i].name != TABLE_END; i++)
    {  p = (memoryBlock *)malloc(sizeof(memoryBlock));
       p->typenr = LocalTypes[i].typenr;
       p->count	= 0;
       p->next = dynamicList;
       dynamicList = p;
    }
    updateMemStat(REC_MEMSTAT,i); 
}

void xfree(void *p, int typenr)
{   
#ifdef MEMORY_STATISTIC
    if (typenr == REC_CHAR)
       updateMemStat(typenr,(strlen(p) + 1) * (-1));
    else
       updateMemStat(typenr,-1);
#endif
    free(p); 
}

#ifdef MEMORY_STATISTIC
static memoryBlock *findMemoryBlock(int typenr)
{   memoryBlock *p = dynamicList;

    while (p != NULL && p->typenr != typenr)
        p = p->next;
    return p;
}
#endif

void printMemStat(void)
{
#ifdef MEMORY_STATISTIC
   memoryBlock *p;
   struct rusage r;
   int i;

   getrusage(RUSAGE_SELF,&r);

   printf("Data Type      Size    Number      Total Allocated\n");
   for (i = 0; LocalTypes[i].name != TABLE_END; i++)
   {   p = findMemoryBlock(LocalTypes[i].typenr);
       if (p != NULL)
          printf("%-15.15s %-4d    %-6d   %d\n",LocalTypes[i].name,
		LocalTypes[i].datasize, p->count, p->count * LocalTypes[i].datasize);
   }

   printf("RUSAGE Stats:\n"
          "            Max Resident Size = %ld\n"
          "  Integral Shared Memory Size = %ld\n"
          "Integral Unshared Memory Size = %ld\n"
          " Integral Unshared Stack Size = %ld\n\n"
          "                Page recliams = %ld\n"
          "                  Page Faults = %ld\n\n",
          r.ru_maxrss,r.ru_ixrss,r.ru_idrss,r.ru_isrss,r.ru_minflt,r.ru_majflt);
#else
   printf("Memory statistics have been disabled.\n");
#endif
}