// ******************************************************************************** //
// **Creator:    Dazzle                Licence:      Diku Merc Smaug Terms       ** //
// **Difficulty:    4                  Snippet:      StrAlloc/Quicklink Change   ** // 
// ******************************************************************************** //
// **                           Contact Information                              ** //
// **Yahoo:      ldevil.geo                 Msn:          ldevil@hotmail.com     ** //
// **Aim:        pocketweasle               Email:      sandstorm@arthmoor.com   ** //
// **Webpage:    http://sandstorm.arthmoor.com                                   ** //
// ******************************************************************************** //
// **Terms of Usage:                                                             ** //
// **Follow the Diku, Merc, Smaug Licences, also, if you have a snippet helpfile ** //
// **Put my name in there, if not, leave my name in the source.                  ** //
// **Also, this code is given AS-IS, straight from my mud, so there will be some ** //
// **Effort required to make this work in your mud.                              ** //
// **Install at your own risk, if you have any comments or questions on this     ** //
// **Visit the website mentioned above, and enter the forum, post and bugs or    ** //
// **suggestions there.                                                          ** //
// ******************************************************************************** //

Okay, first off, this code was ripped from my mud, which is a rom/smaug hybrid mud,
I have enhanced the str_alloc and quick_link functions, now, the STRALLOC and DISPOSE
variables have been enhanced by samson, i am posting those changes here aswell just
incase someone out there doesn't visit the smaugfuss site to get these.

In anycase, is what this does is enhance your str_alloc and quick_link to destroy potential
crash's in them.   now, STRALLOC will alloc memory multipul times, so if you STRALLOC the same
variable, it will give it, its own mark in the table, so instead, we check the hash table
before we STRALLOC, if it is already in the hash-table, it will result in a quicklink.

Now, quicklink will check if the string is in the table, and here is the main crasher, if you
quicklink to a variable that doesn't exist, this will generaly cause a crash, so now, the code
will check for the string in the hash-table first, and then if it isn't there, it will STRALLOC it
and if it is in the table, it will continue with the quicklink.

Now, the DISPOSE and STRFREE enhancements, here is what they do.  DISPOSE will now check
the pointer, to see if it is a char * or const char *, if it is one of those, it will check
the hash-table, to see if it is in the hash, if it is, it will str_free it, if it isn't
in the table, it will simply free it like it should.

STRFREE will check for the string in the hash-table, if it doesn't exist, it will try running
DISPOSE on the data, this should eliminate all the potentials for mixing up the DISPOSE/STRFREE
functions.

They will log any improper calls to dispose or strfree, right down to the file, function, and 
line of code.     Making the job of the coder, allot simpler

Warning: This *MAY* only work under G++, backup your code before you do this if you are
not G++ compatable!

#define DISPOSE(point)                         \
do                                             \
{                                              \
  if( (point) )                               \
  {                                           \
     if( typeid((point)) == typeid(char*) || typeid((point)) == typeid(const char*)  )   \
     {                                        \
        if( in_hash_table((char*)(point) ) ) \
        {                                     \
           nlogf( "`!Dispose called on StrAlloc pointer: %s, %s, line %d\n",  __FILE__, __FUNCTION__, _LINE__ ); \
           log_string( "Attempting to correct." ); \
           if( str_free( (char*)(point) ) == -1 ) \
              nlogf( "`!Strfreeing bad pointer: %s, %s, line %d\n",__FILE__, __FUNCTION__ , __LINE__ ); \
        }                                     \
	else \
        {   \
            free( (point) );                      \
        }	\
     }                                        \
     else                                     \
     {   \
        free( (point) );                      \
     }	\
     (point) = NULL;                          \
  }                                           \
} while(0)


#define Strfree(point)                                            \
do                                                                \
{                                                                 \
  if((point))                                                    \
  {                                                              \
     if( !in_hash_table( (point) ) )                             \
     {                                                           \
        nlogf( "`!Strfree called on str_dup pointer: %s, %s line %d\n",__FILE__, __FUNCTION__ , __LINE__  ); \
        nlogf( "Attempting to correct." );                  \
        free( (point) );                                         \
     }                                                           \
     else if( str_free((point)) == -1 )                          \
        nlogf( "`!Strfreeing bad pointer: %s, %s, line %d\n", __FILE__ , __FUNCTION__, __LINE__  ); \
     (point) = NULL;                                             \
  }                                                              \
} while(0)


Okay, now the fun stuff begins.

In str_alloc (in hashstr.c)

before len =... it should be the first part of the handling.. put this.

   if( in_hash_table( str ) )
      return quick_link( ( char * )str );

in quick_link, add this before ptr =      it should be the first part of the actaul handling


   if( !in_hash_table( str ) )
      return str_alloc( ( const char * )str );


at the end of hashstr.c  put this..

/*
* str must be the actual pointer you want to know about, it cannot be a copy
* of a pointer, or a variable.
*/
bool in_hash_table( const char *str )
{
   register int len, hash, psize;
   register struct hashstr_data *ptr;

   len = strlen( str );
   psize = sizeof( struct hashstr_data );
   hash = len % STR_HASH_SIZE;
   for( ptr = string_hash[hash]; ptr; ptr = ptr->next )
      if( len == ptr->length && str == ( ( char * )ptr + psize ) )
         return TRUE;
   return FALSE;
}


in your mud.h with the rest of the prototypes, put this.
bool in_hash_table( const char *str );



Compile clean, and have fun..  I haven't had any problems with this code, infact, it found allot
of bugs for me, effectively saving my mud allot of downtime.   Samson gets the credit for the 
strfree/dispose release, you can read more about it at www.smaugfuss.org i believe.