ackfuss-4.3.2/area/boards/
ackfuss-4.3.2/npcs/a/
ackfuss-4.3.2/npcs/b/
ackfuss-4.3.2/npcs/c/
ackfuss-4.3.2/npcs/d/
ackfuss-4.3.2/npcs/e/
ackfuss-4.3.2/npcs/f/
ackfuss-4.3.2/npcs/h/
ackfuss-4.3.2/npcs/i/
ackfuss-4.3.2/npcs/k/
ackfuss-4.3.2/npcs/l/
ackfuss-4.3.2/npcs/n/
ackfuss-4.3.2/npcs/o/
ackfuss-4.3.2/npcs/p/
ackfuss-4.3.2/npcs/r/
ackfuss-4.3.2/npcs/s/
ackfuss-4.3.2/npcs/w/
ackfuss-4.3.2/player/c/
ackfuss-4.3.2/reports/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Zepp 1998    *
 *    _/_/_/_/      _/          _/  _/             Version #: 4.3          *
 *   _/      _/      _/_/_/     _/    _/     _/                            *
 *                                                                         *
 *                        http://ackmud.nuc.net/                           *
 *                        zenithar@ackmud.nuc.net                          *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

#include <sys/types.h>
#include <sys/time.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "globals.h"
#include "tables.h"

#ifdef DEBUG_MONEY
#ifndef DEC_MONEY_H
#include "money.h"
#endif
#endif


#include "ssm.h"

/*  String checker, Spectrum 11/96
 *
 *  Basic idea is to walk through all the strings we know about, and mark them
 *  as referenced. Then we check for strings that have a reference count thats
 *  different from ptr->usage and log them
 */

/*
 * Things which are walked (anything else must be touched from these):
 *
 * o char_list
 * o descriptor_list
 * o object_list
 * o mob_index hash table
 * o obj_index hash table
 * o room_index hash table
 * o socials table
 * o helps
 * o areas
 * o notes/ideas/etc
 *
 */



/* From ban.c: */

extern BAN_DATA *first_ban;


extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
extern OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH];
extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];

/* Main code */

static void touch( char *str )
{
   BufEntry *p;

   if( !str )
      return;

   if( str < string_space || str > top_string )
      return;  /* not in string space */

   p = ( BufEntry * ) ( str - HEADER_SIZE );
   p->ref++;
}

static void clear( void )
{
   /*
    * Set all reference counts to 0 
    */

   BufEntry *p;

   for( p = ssm_buf_head; p; p = p->next )
      p->ref = 0;
}

static BufEntry *dump_ptr[2];

static long dump( void )
{
   /*
    * Dump strings that have ref!=usage 
    */

   FILE *dumpf;
   BufEntry *p;
   long count = 0;

   fclose( fpReserve );
   dumpf = fopen( "../reports/leaks.dmp", "w" );

   for( p = ssm_buf_head; p; p = p->next )
   {
      if( p->usage > 0 && p->usage != p->ref )
      {
         /*
          * things to ignore:
          * * the common <%hhp %mm %vmv> prompt string
          * * a '$' (from socials)
          */

         if( !str_cmp( p->buf, "<%hhp %mm %vmv> " ) || !str_cmp( p->buf, "$" ) )
            continue;

         fprintf( dumpf, "usage %2d/%2d, caller %s, string %s\n", p->ref, p->usage, p->caller, p->buf );
         count += abs( p->usage - p->ref );
      }
      dump_ptr[0] = dump_ptr[1];
      dump_ptr[1] = p;
   }

   fclose( dumpf );
   fpReserve = fopen( NULL_FILE, "r" );

   return count;
}

static void walk_mprog_data( MPROG_DATA * prog )
{
   if( !prog )
      return;

   touch( prog->arglist );
   touch( prog->comlist );
   touch( prog->filename );

}
static void walk_mprog_act_data( MPROG_ACT_LIST * act )
{
   if( !act )
      return;

   touch( act->buf );

}


static void walk_mob_index_data( MOB_INDEX_DATA * m )
{
   MPROG_DATA *mobprog;
   if( !m )
      return;

   touch( m->player_name );
   touch( m->short_descr );
   touch( m->long_descr );
   touch( m->description );
   touch( m->target );
   for( mobprog = m->first_mprog; mobprog; mobprog = mobprog->next )
      walk_mprog_data( mobprog );

}

static void walk_ngroup_data( NPC_GROUP_DATA * ngrp )
{
   if( !ngrp )
      return;

   touch( ngrp->enemies );
   touch( ngrp->last_fighting );
   touch( ngrp->wants );
   touch( ngrp->needs );
}

static void walk_ngroups( void )
{
   NPC_GROUP_DATA *ngroup;

   for( ngroup = first_npc_group; ngroup; ngroup = ngroup->next )
   {
      walk_ngroup_data( ngroup );
   }
}

static void walk_pcdata( PC_DATA * p )
{
   int i;

   if( !p )
      return;

   touch( p->pwd );
   touch( p->bamfin );
   touch( p->bamfout );
   touch( p->title );
   touch( p->room_enter );
   touch( p->room_exit );
   touch( p->immskll );
   touch( p->host );
   touch( p->who_name );
   touch( p->header );
   touch( p->message );
   touch( p->lastlogin );
   touch( p->load_msg );

   for( i = 0; i < MAX_IGNORES; i++ )
      touch( p->ignore_list[i] );

   for( i = 0; i < MAX_ALIASES; i++ )
   {
      touch( p->alias[i] );
      touch( p->alias_name[i] );
   }
   for( i = 0; i < 5; i++ )
   {
      touch( p->pedit_string[i] );
   }
   touch( p->pedit_state );
   touch( p->email_address );
   touch( p->assist_msg );
}
static void walk_shield_data( MAGIC_SHIELD * shield )
{
   if( !shield )
      return;

   touch( shield->name );
   touch( shield->absorb_message_room );
   touch( shield->absorb_message_victim );
   touch( shield->absorb_message_self );
   touch( shield->wearoff_room );
   touch( shield->wearoff_self );

}

static void walk_note_data( NOTE_DATA * note )
{
   if( !note )
      return;

   touch( note->sender );
   touch( note->date );
   touch( note->to_list );
   touch( note->subject );
   touch( note->text );
}
static void walk_brand_data( BRAND_DATA * brand )
{
   if( !brand )
      return;

   touch( brand->branded );
   touch( brand->branded_by );
   touch( brand->dt_stamp );
   touch( brand->message );
   touch( brand->priority );
}
static void walk_brands( void )
{
   BRAND_DATA *this_brand;
   DL_LIST *brands;
   for( brands = first_brand; brands; brands = brands->next )
   {
      this_brand = brands->this_one;
      walk_brand_data( this_brand );
   }
}

static void walk_shieldlist( MAGIC_SHIELD * shield )
{
   for( ; shield; shield = shield->next )
      walk_shield_data( shield );
}

static void walk_mprog_act( MPROG_ACT_LIST * act )
{
   for( ; act; act = act->next )
      walk_mprog_act_data( act );
}

void walk_notelist( NOTE_DATA * pnote )
{
   for( ; pnote; pnote = pnote->next )
      walk_note_data( pnote );
}

static void walk_char_data( CHAR_DATA * ch )
{
   if( !ch )
      return;

   walk_notelist( ch->pnote );
   walk_pcdata( ch->pcdata );
   walk_shieldlist( ch->first_shield );
   walk_mprog_act( ch->first_mpact );

   touch( ch->name );
   touch( ch->short_descr );
   touch( ch->long_descr );
   touch( ch->long_descr_orig );
   touch( ch->description );
   touch( ch->prompt );
   touch( ch->old_prompt );
   touch( ch->searching );
   touch( ch->target );
#ifdef DEBUG_MONEY
   if( ch->money )
      touch( ch->money->money_key );
   if( ch->bank_money )
      touch( ch->bank_money->money_key );
#endif


}

static void walk_extra_descr_data( EXTRA_DESCR_DATA * ed )
{
   if( !ed )
      return;

   touch( ed->keyword );
   touch( ed->description );
}

static void walk_obj_index_data( OBJ_INDEX_DATA * o )
{
   EXTRA_DESCR_DATA *ed;

   if( !o )
      return;

   for( ed = o->first_exdesc; ed; ed = ed->next )
      walk_extra_descr_data( ed );

   touch( o->name );
   touch( o->short_descr );
   touch( o->description );
   touch( o->owner );
}


static void walk_obj_data( OBJ_DATA * o )
{
   EXTRA_DESCR_DATA *ed;

   if( !o )
      return;

   for( ed = o->first_exdesc; ed; ed = ed->next )
      walk_extra_descr_data( ed );

   touch( o->owner );
   touch( o->name );
   touch( o->short_descr );
   touch( o->description );
#ifdef DEBUG_MONEY
   if( o->money )
      touch( o->money->money_key );
#endif


}

static void walk_exit_data( EXIT_DATA * e )
{
   if( !e )
      return;

   touch( e->keyword );
   touch( e->description );
}

static void walk_reset_data( RESET_DATA * r )
{
   if( !r )
      return;

   touch( r->notes );
   touch( r->auto_message );
}

static void walk_area_data( AREA_DATA * ad )
{

   RESET_DATA *reset;
   if( !ad )
      return;

   touch( ad->filename );
   touch( ad->name );
   touch( ad->owner );
   touch( ad->can_read );
   touch( ad->can_write );
   touch( ad->keyword );   /* spec- missed strings */
   touch( ad->level_label );  /* spec - missed strings */
   touch( ad->reset_msg );
   for( reset = ad->first_reset; reset; reset = reset->next )
      walk_reset_data( reset );

}

/* spec - for the new rulers stuff */
static void walk_ruler_data( RULER_DATA * ruler )
{
   if( !ruler )
      return;
   touch( ruler->name );
   touch( ruler->affiliation_name );
   touch( ruler->keywords );
}

static void walk_room_index_data( ROOM_INDEX_DATA * r )
{
   int i;
   EXTRA_DESCR_DATA *ed;
/*  BUILD_DATA_LIST *reset;  */
   if( !r )
      return;

   for( i = 0; i < 6; i++ )
      walk_exit_data( r->exit[i] );


   for( ed = r->first_exdesc; ed; ed = ed->next )
      walk_extra_descr_data( ed );
   touch( r->name );
   touch( r->description );
   touch( r->auto_message );
#ifdef DEBUG_MONEY
   touch( r->treasure->money_key );
#endif
}


static void walk_social_type( struct social_type *s )
{


   if( !s )
      return;
   touch( s->name );
   touch( s->char_no_arg );
   touch( s->others_no_arg );
   touch( s->char_found );
   touch( s->others_found );
   touch( s->vict_found );
   touch( s->char_auto );
   touch( s->others_auto );
}

static void walk_help_data( HELP_DATA * h )
{
   if( !h )
      return;

   touch( h->keyword );
   touch( h->text );
}

static void walk_descriptor_data( DESCRIPTOR_DATA * d )
{
   if( !d )
      return;

   touch( d->host );
}



static void walk_ban_data( BAN_DATA * b )
{
   touch( b->name );
   touch( b->banned_by );
}



static void walk_socials( void )
{
   extern int maxSocial;
   int i;

   for( i = 0; i < maxSocial; i++ )
      walk_social_type( &social_table[i] );
}

static void walk_helps( void )
{
   HELP_DATA *h;

   for( h = first_help; h; h = h->next )
      walk_help_data( h );
}

static void walk_chars( void )
{
   CHAR_DATA *ch;

   for( ch = first_char; ch; ch = ch->next )
      walk_char_data( ch );
}

static void walk_descriptors( void )
{
   DESCRIPTOR_DATA *d;

   for( d = first_desc; d; d = d->next )
      walk_descriptor_data( d );
}

static void walk_objects( void )
{
   OBJ_DATA *o;

   for( o = first_obj; o; o = o->next )
      walk_obj_data( o );
}

static void walk_areas( void )
{
   AREA_DATA *ad;

   for( ad = first_area; ad; ad = ad->next )
      walk_area_data( ad );
}

/* spec- more rulers stuff */
static void walk_rulers( void )
{
   RULER_LIST *r;

   for( r = first_ruler_list; r; r = r->next )
      walk_ruler_data( r->this_one );
}

static void walk_mob_indexes( void )
{
   MOB_INDEX_DATA *m;
   int i;

   for( i = 0; i < MAX_KEY_HASH; i++ )
      for( m = mob_index_hash[i]; m; m = m->next )
         walk_mob_index_data( m );
}

static void walk_obj_indexes( void )
{
   OBJ_INDEX_DATA *o;
   int i;

   for( i = 0; i < MAX_KEY_HASH; i++ )
      for( o = obj_index_hash[i]; o; o = o->next )
         walk_obj_index_data( o );
}

static void walk_room_indexes( void )
{
   ROOM_INDEX_DATA *r;
   int i;

   for( i = 0; i < MAX_KEY_HASH; i++ )
      for( r = room_index_hash[i]; r; r = r->next )
         walk_room_index_data( r );
}


static void walk_notes( void )
{
   walk_notelist( first_note );
}

static void walk_bans( void )
{
   BAN_DATA *b;

   for( b = first_ban; b; b = b->next )
      walk_ban_data( b );
}

static void walk_mark_data( MARK_DATA * m )
{
   if( !m )
      return;

   touch( m->message );
   touch( m->author );
}

void walk_marklist( void )
{
   MARK_LIST_MEMBER *tmark;
   for( tmark = first_mark_list; tmark; tmark = tmark->next )
      walk_mark_data( tmark->mark );
}

static void walk_message_data( MESSAGE_DATA * m )
{
   if( !m )
      return;

   touch( m->message );
   touch( m->author );
   touch( m->title );
}

void walk_messages( MESSAGE_DATA * m )
{
   for( ; m; m = m->next )
      walk_message_data( m );
}
void walk_boards( void )
{
   BOARD_DATA *board;
   extern BOARD_DATA *first_board;
   for( board = first_board; board; board = board->next )
      walk_messages( board->first_message );
}


void walk_councils( void )
{
   sh_int index;
   extern COUNCIL_DATA super_councils[MAX_SUPER];

   for( index = 0; index < MAX_SUPER; index++ )
      touch( super_councils[index].council_name );
}
void walk_sysdata( void )
{
   sh_int looper;
   touch( sysdata.playtesters );
   for( looper = 0; looper < MAX_NUM_IMMS; looper++ )
      touch( sysdata.imms[looper].this_string );
}


void do_scheck( CHAR_DATA * ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
   extern bool disable_timer_abort;
   disable_timer_abort = TRUE;
   clear(  );

   walk_socials(  );
   walk_helps(  );
   walk_chars(  );
   walk_descriptors(  );
   walk_objects(  );
   walk_areas(  );
   walk_bans(  );


   walk_mob_indexes(  );
   walk_obj_indexes(  );
   walk_room_indexes(  );
   walk_notes(  );
   walk_marklist(  );
   walk_councils(  );
   walk_boards(  );
   walk_rulers(  );
   walk_brands(  );
   walk_sysdata(  );
   walk_ngroups(  );

   sprintf( buf, "%ld leaks dumped to leaks.dmp\n\r", dump(  ) );
   send_to_char( buf, ch );
   disable_timer_abort = FALSE;
}