/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Memory Cleanup -Druid * **************************************************************************** * * PirateMUD is a derivative work of SMAUG and therefore the SMAUG License, * Merc License, and Diku License must all be followed, no exceptions. The * PirateMUD license simply states, "AS IS". * * This by no means cleans all the memory, there is stuff that my mud doesn't * use, therefore the memory is not allocated, and hence it may not be cleaned * up in here. * * First, Add this file to the Makefile * * At the top of comm.c * Add: * void cleanup_memory( void ); * Search for: * log_string( "Normal termination of game." ); * * After that add: * log_string( "Cleaning up memory." ); * cleanup_memory( ); * * $Header: /home/ddruid/smaug/src/RCS/cleanup.c,v 0.4 2002/09/29 15:06:01 ddruid Exp ddruid $ * Robert Haas - $Date: 2002/09/29 15:06:01 $ * * $Id: cleanup.c,v 0.4 2002/09/29 15:06:01 ddruid Exp ddruid $ * * $State: Exp $ * * REVISION HISTORY: * $Log: cleanup.c,v $ * Revision 0.4 2002/09/29 15:06:01 ddruid * Had to modify the order a bit to fix a crash with Dmalloc. * * Revision 0.3 2002/09/03 19:43:22 ddruid * Random global variables * * Revision 0.2 2002/08/28 17:45:59 ddruid * Most things cleaned, seem to be catching global variables now. * * Revision 0.1 2002/08/27 23:04:26 ddruid * Check in * * Revision 0.0 2002/08/26 18:09:12 ddruid * Initial revision * * NOTES: * STRALLOC free with MY_STRFREE * fread_string free with MY_STRFREE * fread_string_nohash free with MY_DISPOSE * str_dup free with MY_DISPOSE */ #include <stdio.h> #include "mud.h" /* RCS Version */ static char clversion_rcsid[] __attribute__ ((unused)) = "$Id: cleanup.c,v 0.4 2002/09/29 15:06:01 ddruid Exp ddruid $"; extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH]; extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH]; extern OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH]; extern MAP_INDEX_DATA *first_map; extern struct act_prog_data *room_act_list; extern struct act_prog_data *obj_act_list; extern char *ranged_target_name; void unlink_social( SOCIALTYPE *social ); void free_desc( DESCRIPTOR_DATA *d ); #define MY_DISPOSE( ptr ) if( (ptr) ) DISPOSE( (ptr) ); #define MY_STRFREE( ptr ) if( (ptr) ) STRFREE( (ptr) ); /* * Print current version */ void do_clversion( CHAR_DATA *ch, char *argument ) { ch_printf_color( ch, "&RCurrent Cleanup_Mem version: &Y%s\n\r", clversion_rcsid ); return; } /* do_clversion */ /* * Clean all memory on exit to help find leaks */ void cleanup_memory( void ) { int hash; CMDTYPE *command, *cmd_next; CLAN_DATA *clan, *clan_next; SOCIALTYPE *social, *social_next; struct class_type *class; struct race_type *race; SKILLTYPE *skill; SMAUG_AFF *aff, *aff_next; WATCH_DATA *pw, *pw_next; HELP_DATA *pHelp, *pHelp_next; LANG_DATA *lang, *lang_next; LCNV_DATA *lcnv, *lcnv_next; CHAR_DATA *character, *char_next; OBJ_DATA *object, *object_next; MOB_INDEX_DATA *mob, *mob_indx_next; ROOM_INDEX_DATA *room, *room_indx_next; OBJ_INDEX_DATA *obj, *obj_indx_next; AREA_DATA *area, *area_next; RESET_DATA *res, *res_next; MAP_INDEX_DATA *map, *map_next; DESCRIPTOR_DATA *desc, *desc_next; BOARD_DATA *board, *board_next; NOTE_DATA *note, *note_next; AFFECT_DATA *paf, *paf_next; EXTRA_DESCR_DATA *ed, *ed_next; MPROG_DATA *mp, *mp_next; struct act_prog_data *apd, *apd_next; /* Close open files */ fprintf( stdout, "Closing reserve files.\n" ); if( fpReserve ) fclose( fpReserve ); if( fpLOG ) fclose( fpLOG ); /* Whack supermob */ fprintf( stdout, "Whacking supermob.\n" ); if( supermob ) { char_from_room( supermob ); UNLINK( supermob, first_char, last_char, next, prev ); free_char( supermob ); } /* Descriptors */ fprintf( stdout, "Descriptors.\n" ); for( desc = first_descriptor; desc; desc = desc_next ) { desc_next = desc->next; UNLINK( desc, first_descriptor, last_descriptor, next, prev ); free_desc( desc ); } /* Free Characters */ fprintf( stdout, "Characters.\n" ); for( character = first_char; character; character = char_next ) { if( !character ) break; char_next = character->next; UNLINK( character, first_char, last_char, next, prev ); char_from_room( character ); character->desc = NULL; character->first_carrying = NULL; character->last_carrying = NULL; free_char( character ); } clean_char_queue( ); first_char = NULL; /* Mob Hash */ fprintf( stdout, "Mob hash table.\n" ); for( hash = 0; hash < MAX_KEY_HASH; hash++ ) { for( mob = mob_index_hash[hash]; mob; mob = mob_indx_next ) { mob_indx_next = mob->next; delete_mob( mob ); } } /* Free Objects */ fprintf( stdout, "Objects.\n" ); clean_obj_queue( ); for( object = first_object; object; object = object_next ) { object_next = object->next; UNLINK( object, first_object, last_object, next, prev ); if( object->item_type == ITEM_PORTAL ) remove_portal( object ); /*if( object->carried_by ) object->carried_by = NULL; if( object->in_room ) obj_from_room( object ); else if( object->in_obj ) obj_from_obj( object );*/ for( paf = object->first_affect; paf; paf = paf_next ) { paf_next = paf->next; MY_DISPOSE( paf ); } for( ed = object->first_extradesc; ed; ed = ed_next ) { ed_next = ed->next; MY_STRFREE( ed->description ); MY_STRFREE( ed->keyword ); MY_DISPOSE( ed ); } if( object->mpact ) { MY_DISPOSE( object->mpact->buf ); MY_DISPOSE( object->mpact ); } MY_STRFREE( object->name ); MY_STRFREE( object->description ); MY_STRFREE( object->short_descr ); MY_STRFREE( object->action_desc ); MY_DISPOSE( object ); } /* Commands */ fprintf( stdout, "Commands.\n" ); for( hash = 0; hash < 126; hash++ ) for( command = command_hash[hash]; command; command = cmd_next ) { cmd_next = command->next; command->next = NULL; command->do_fun = NULL; free_command( command ); } /* Clans */ fprintf( stdout, "Clans.\n" ); for( clan = first_clan; clan; clan = clan_next ) { clan_next = clan->next; MY_DISPOSE( clan->filename ); MY_STRFREE( clan->name ); MY_STRFREE( clan->motto ); MY_STRFREE( clan->description ); MY_STRFREE( clan->deity ); MY_STRFREE( clan->leader ); MY_STRFREE( clan->number1 ); MY_STRFREE( clan->number2 ); MY_STRFREE( clan->badge ); MY_DISPOSE( clan ); } /* Classes */ fprintf( stdout, "Classes.\n" ); for( hash = 0; hash < 0; hash++ ) { class = class_table[hash]; STRFREE( class->who_name ); DISPOSE( class ); } /* socials */ fprintf( stdout, "Socials.\n" ); for( hash = 0; hash < 27; hash++ ) for( social = social_index[hash]; social; social = social_next ) { social_next = social->next; free_social( social ); } /* Skills */ fprintf( stdout, "Skills.\n" ); for( hash = 0; hash < top_sn; hash++ ) { skill = skill_table[hash]; if( skill->affects ) { for( aff = skill->affects; aff; aff = aff_next ) { aff_next = aff->next; MY_DISPOSE( aff->duration ); MY_DISPOSE( aff->modifier ); MY_DISPOSE( aff ); } } MY_DISPOSE( skill->name ); MY_DISPOSE( skill->noun_damage ); MY_DISPOSE( skill->msg_off ); MY_DISPOSE( skill->hit_char ); MY_DISPOSE( skill->hit_vict ); MY_DISPOSE( skill->hit_room ); MY_DISPOSE( skill->hit_dest ); MY_DISPOSE( skill->miss_char ); MY_DISPOSE( skill->miss_vict ); MY_DISPOSE( skill->miss_room ); MY_DISPOSE( skill->die_char ); MY_DISPOSE( skill->die_vict ); MY_DISPOSE( skill->die_room ); MY_DISPOSE( skill->imm_char ); MY_DISPOSE( skill->imm_vict ); MY_DISPOSE( skill->imm_room ); MY_DISPOSE( skill->dice ); MY_DISPOSE( skill->components ); MY_DISPOSE( skill->teachers ); skill->spell_fun = NULL; skill->skill_fun = NULL; MY_DISPOSE( skill ); } /* Watches */ fprintf( stdout, "Watches.\n" ); for( pw = first_watch; pw; pw = pw_next ) { pw_next = pw->next; MY_DISPOSE( pw->imm_name ); MY_DISPOSE( pw->player_site ); MY_DISPOSE( pw->target_name ); UNLINK( pw, first_watch, last_watch, next, prev ); MY_DISPOSE( pw ); } /* Helps */ fprintf( stdout, "Helps.\n" ); for( pHelp = first_help; pHelp; pHelp = pHelp_next ) { pHelp_next = pHelp->next; UNLINK( pHelp, first_help, last_help, next, prev ); MY_STRFREE( pHelp->text ); MY_STRFREE( pHelp->keyword ); MY_DISPOSE( pHelp ); } /* Races */ fprintf( stdout, "Races.\n" ); for( hash = 0; hash < MAX_RACE; hash++ ) { race = race_table[hash]; MY_DISPOSE( race ); } /* Languages */ fprintf( stdout, "Languages.\n" ); for( lang = first_lang; lang; lang = lang_next ) { lang_next = lang->next; for( lcnv = lang->first_precnv; lcnv; lcnv = lcnv_next ) { lcnv_next = lcnv->next; UNLINK( lcnv, lang->first_precnv, lang->last_precnv, next, prev ); MY_DISPOSE( lcnv->old ); MY_DISPOSE( lcnv->new ); MY_DISPOSE( lcnv ); } for( lcnv = lang->first_cnv; lcnv; lcnv = lcnv_next ) { lcnv_next = lcnv->next; UNLINK( lcnv, lang->first_cnv, lang->last_cnv, next, prev ); MY_DISPOSE( lcnv->old ); MY_DISPOSE( lcnv->new ); MY_DISPOSE( lcnv ); } MY_STRFREE( lang->name ); MY_STRFREE( lang->alphabet ); MY_DISPOSE( lang ); } /* Boards */ fprintf( stdout, "Boards.\n" ); for( board = first_board; board; board = board_next ) { board_next = board->next; for( note = board->first_note; note; note = note_next ) { note_next = note->next; UNLINK( note, board->first_note, board->last_note, next, prev ); free_note( note ); } UNLINK( board, first_board, last_board, next, prev ); MY_DISPOSE( board->extra_readers ); MY_DISPOSE( board->extra_removers ); MY_DISPOSE( board->note_file ); MY_DISPOSE( board->read_group ); MY_DISPOSE( board ); } /* Rooms */ fprintf( stdout, "Room hash table.\n" ); for( hash = 0; hash < MAX_KEY_HASH; hash++ ) for( room = room_index_hash[hash]; room; room = room_indx_next ) { room_indx_next = room->next; room->first_content = NULL; room->last_content = NULL; delete_room( room ); } /* Obj Hash */ fprintf( stdout, "Object hash table.\n" ); for( hash = 0; hash < MAX_KEY_HASH; hash++ ) for( obj = obj_index_hash[hash]; obj; obj = obj_indx_next ) { obj_indx_next = obj->next; for( ed = obj->first_extradesc; ed; ed = ed_next ) { ed_next = ed->next; MY_STRFREE( ed->keyword ); MY_STRFREE( ed->description ); MY_DISPOSE( ed ); } for( paf = obj->first_affect; paf; paf = paf_next ) { paf_next = paf->next; MY_DISPOSE( paf ); } for( mp = obj->mudprogs; mp; mp = mp_next ) { mp_next = mp->next; MY_STRFREE( mp->arglist ); MY_STRFREE( mp->comlist ); MY_DISPOSE( mp ); } MY_STRFREE( obj->name ); MY_STRFREE( obj->short_descr ); MY_STRFREE( obj->description ); MY_STRFREE( obj->action_desc ); MY_DISPOSE( obj ); } /* Area data */ fprintf( stdout, "Area data.\n" ); for( area = first_area; area; area = area_next ) { area_next = area->next; for( res = area->first_reset; res; res = res_next ) { res_next = res->next; UNLINK( res, area->first_reset, area->last_reset, next, prev ); MY_DISPOSE( res ); } MY_DISPOSE( area->name ); MY_DISPOSE( area->filename ); MY_STRFREE( area->author ); MY_DISPOSE( area->resetmsg ); MY_DISPOSE( area ); } /* Map Indexes */ fprintf( stdout, "Map indexes.\n" ); for( map = first_map; map; map = map_next ) { map_next = map->next; DISPOSE( map ); } /* Get rid of auction pointer MUST BE AFTER OBJECTS DESTROYED */ fprintf( stdout, "Auction.\n" ); MY_DISPOSE( auction ); /* System Data */ fprintf( stdout, "System data.\n" ); MY_DISPOSE( sysdata.time_of_max ); MY_DISPOSE( sysdata.mud_name ); MY_STRFREE( sysdata.guild_overseer ); MY_STRFREE( sysdata.guild_advisor ); /* Herbs */ fprintf( stdout, "Herbs.\n" ); for( hash = 0; hash < top_herb; hash++ ) { skill = herb_table[hash]; if( skill->affects ) { for( aff = skill->affects; aff; aff = aff_next ) { aff_next = aff->next; MY_DISPOSE( aff->duration ); MY_DISPOSE( aff->modifier ); MY_DISPOSE( aff ); } } MY_DISPOSE( skill->name ); MY_DISPOSE( skill->noun_damage ); MY_DISPOSE( skill->msg_off ); MY_DISPOSE( skill->hit_char ); MY_DISPOSE( skill->hit_vict ); MY_DISPOSE( skill->hit_room ); MY_DISPOSE( skill->hit_dest ); MY_DISPOSE( skill->miss_char ); MY_DISPOSE( skill->miss_vict ); MY_DISPOSE( skill->miss_room ); MY_DISPOSE( skill->die_char ); MY_DISPOSE( skill->die_vict ); MY_DISPOSE( skill->die_room ); MY_DISPOSE( skill->imm_char ); MY_DISPOSE( skill->imm_vict ); MY_DISPOSE( skill->imm_room ); MY_DISPOSE( skill->dice ); MY_DISPOSE( skill->components ); MY_DISPOSE( skill->teachers ); skill->spell_fun = NULL; skill->skill_fun = NULL; MY_DISPOSE( skill ); } /* Prog Act lists */ fprintf( stdout, "Mprog act list.\n" ); for( apd = mob_act_list; apd; apd = apd_next ) { apd_next = apd->next; MY_DISPOSE( apd ); } fprintf( stdout, "Rprog act list.\n" ); for( apd = room_act_list; apd; apd = apd_next ) { apd_next = apd->next; MY_DISPOSE( apd ); } fprintf( stdout, "Oprog act list.\n" ); for( apd = obj_act_list; apd; apd = apd_next ) { apd_next = apd->next; MY_DISPOSE( apd ); } /* Some freaking globals */ fprintf( stdout, "Globals.\n" ); MY_DISPOSE( ranged_target_name ); } /* cleanup memory */ /* End $RCSfile: cleanup.c,v $ */