tfe-1.0/area/
tfe-1.0/files/
tfe-1.0/logs/
tfe-1.0/logs/immortal/
tfe-1.0/logs/mob/
tfe-1.0/logs/object/
tfe-1.0/logs/player/
tfe-1.0/logs/room/
tfe-1.0/notes/clans/
tfe-1.0/player/
tfe-1.0/prev/
tfe-1.0/prev/area/
tfe-1.0/prev/player/
tfe-1.0/prev/rooms/
tfe-1.0/rooms/
tfe-1.0/src-gc/
tfe-1.0/src-msvc/
tfe-1.0/src-unix/
tfe-1.0/www/
tfe-1.0/www/html/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "define.h"
#include "struct.h"
#include "unistd.h"


char* empty_string = (char*) "\0";


/*
 *   STRING COMPARISON
 */


inline bool null_strings( const char* astr, const char* bstr )
{
  if( astr != NULL && bstr != NULL )
    return FALSE;

  if( astr == NULL && bstr == NULL )
    bug( "Str*cmp: Null string (x2)." );
  else
    bug( "Str*cmp: Comparing '%s' to null.",
      astr == NULL ? bstr : astr );

  return TRUE;
}


int strcasecmp( const char* astr, const char* bstr )
{
  if( astr == bstr )
    return 0;

  if( null_strings( astr, bstr ) )
    return 1;

  for( ; *astr != '\0' || *bstr != '\0'; astr++, bstr++ )
    if( tolower( *astr ) != tolower( *bstr ) )
      return( tolower( *astr ) > tolower( *bstr ) ? 1 : -1 );

  return 0;
}


int strncasecmp( const char* astr, const char* bstr, int n )
{
  const char* end;

  if( null_strings( astr, bstr ) )
    return 1;

  end = astr+n;

  for( ; astr < end && ( *astr != '\0' || *bstr != '\0' ); astr++, bstr++ )
    if( tolower( *astr ) != tolower( *bstr ) )
      return( tolower( *astr ) > tolower( *bstr ) ? 1 : -1 );

  return 0;
}


int strncmp( const char* astr, const char* bstr, int n )
{
  const char* end;

  if( null_strings( astr, bstr ) )
    return 1;

  end = astr+n;

  for( ; astr < end && ( *astr != '\0' || *bstr != '\0' ); astr++, bstr++ )
    if( *astr != *bstr )
      return( *astr > *bstr ? 1 : -1 );

  return 0;
}


char* strcat( char* dst, const char* src )
{
  char* s;

  for( s = dst; *s != '\0'; s++ );
  for( ; *src != '\0'; )
    *s++ = *src++;

  *s = '\0';

  return dst;
}


int rstrcasecmp( const char* astr, const char* bstr )
{
  int  a, b, c;
  int        i;

  if( null_strings( astr, bstr ) )
    return 1;

  a = strlen( astr );
  b = strlen( bstr );
  c = min( a, b ); 

  for( i = 1; i <= c; i++ )
    if( tolower( astr[a-i] ) != tolower( bstr[b-i] ) ) 
      return( tolower( astr[a-i] ) > tolower( bstr[b-i] ) ? 1 : -1 );

  return( a < b ? -1 : a > b );
}


int rstrncasecmp( const char* astr, const char* bstr, int n )
{
  int   a, b, c;
  int         i;

  if( null_strings( astr, bstr ) )
    return 1;

  a = strlen( astr );
  b = strlen( bstr );
  c = min( min( a, b ), n ); 

  for( i = 1; i <= c; i++ ) 
    if( tolower( astr[a-i] ) != tolower( bstr[b-i] ) ) 
      return( tolower( astr[a-i] ) > tolower( bstr[b-i] ) ? 1 : -1 );

  return( c == n ? 0 : a < b );
}


/*
 *   GENERIC UTILITY ROUTINES
 */


bool fmatches( const char* argument, const char* word, int length )
{
  int i;

  for( i = 0; argument[i] != '\0'; i++ ) 
    if( tolower( word[i] ) != tolower( argument[i] ) )
      return FALSE;

  return( i > length );
}


bool matches( const char*& argument, const char* word )
{
  const char* str = argument;

  if( *str == '\0' )
    return FALSE;

  for( ; *str != '\0' && *str != ' '; word++, str++ ) 
    if( tolower( *word ) != tolower( *str ) )
      return FALSE;

  skip_spaces( str );
  argument = str;

  return TRUE;
}


bool exact_match( const char*& argument, const char* word )
{
  const char* str = argument;

  for( ; *word != '\0'; word++, str++ )
    if( tolower( *word ) != tolower( *str ) )
      return FALSE;

  if( *str != ' ' && *str != '\0' && *str != ',' && *str != ';' )
    return FALSE;

  skip_spaces( str );
  argument = str;

  return TRUE;
}


bool number_arg( const char*& argument, int& i )
{
  const char* str  = argument;
  int           j  = 0;
  bool      minus  = FALSE;

  if( *str == '-' ) {
    minus = TRUE;
    str++;
    }
  else if( *str == '+' )
    str++;

  for( ; ; ) {
    if( !isdigit( *str ) )
      return FALSE;
    j = 10*j+(*str++)-'0';
    if( *str == '\0' || *str == ' ' )
      break;
    }

  argument = str;
  i        = minus ? -j : j;

  skip_spaces( argument );

  return TRUE;
}


/*
 *
 */


char* seperate( char* string, bool identified )
{
  int i;

  if( *string != '{' )
    return string;

  for( i = 1; string[i] != '}' && string[i] != '\0'; i++ );

  if( !identified ) {
    if( i == 1 )
      return empty_string;
    char* tmp = static_string( );
    memcpy( tmp, &string[1], i-1 );
    tmp[i-1] = '\0';
    return tmp;
    }

  if( string[i] == '\0' )
    return empty_string;

  for( i++; string[i] == ' '; i++ );

  return &string[i];
}


char* one_condition( char *argument, char *cond )
{
  if( *argument == '\0' )
    *cond = '\0';
  else {
    for( ; *argument != '\n' && *argument != '\0'
      && *argument != '&'; argument++, cond++ )
      *cond = *argument;

    *cond = '\0';

    if( *argument == '&' )
      argument += 2;

    if( *argument == '\n' ) {
      argument++;
      if( *argument == '\r' )
        argument++;
      }
    }

  return argument;
}


/*
 *  IS_NAME ROUTINE
 */


bool is_name( char* str, const char* namelist, bool command )
{
  char           name  [ MAX_INPUT_LENGTH ];
  char           word  [ MAX_INPUT_LENGTH ];
  const char*    list;
  int          length;
  int             pos;

  for( ; ; ) {
    str = one_argument( str, word );

    if( *word == '\0' )
      return TRUE;

    list = namelist;
    length = 3;

    for( ; ; ) {
      list = one_argument( list, name );

      if( *name == '\0' )
        return FALSE;

      if( isdigit( *name ) ) {
        length = atoi( name );
        continue;
        }

      if( strncasecmp( word, name, strlen( word ) ) ) {
        length = 3;
        continue;
        }

      if( command ) {
        pos = search( command_table, MAX_ENTRY_COMMAND, name );
        if( pos >= 0 && command_table[pos].reqlen <= strlen( word ) )
          break;
        }

      if( strlen( word ) >= min( length, strlen( name ) ) )
        break;
      }
    }
}


int subset( const char* s1, const char* s2, bool cmd )
{
  int i = 100;

  for( ; *s1 != '\0'; ) {
    switch( member( s1, s2, cmd ) ) {
      case 0 : return 0;
      case 1 : i = 50;
      }
    for( ; *s1 != '\0' && *s1 != ' '; s1++ );
    for( ; *s1 == ' '; s1++ );
    }

  return( i-count( s2 ) );
}


int member( const char* s1, const char* s2, bool cmd )
{
  int  len  = 3;
  int    i  = 0;
  
  skip_spaces( s2 );

  if( *s1 == '\0' )
    return( *s2 == '\0' );

  for( ; *s2 != '\0'; ) {
    if( isdigit( *s2 ) ) {
      len = atoi( s2 );
      } 
    else {
      switch( compare( s1, s2, cmd, len ) ) {
        case 2 : return 2;
        case 1 : i = 1;
        }
      len = 3;
      }
    for( ; *s2 != '\0' && *s2 != ' '; s2++ );
    for( ; *s2 == ' '; s2++ );
    }

  return i;
}
 

int compare( const char* s1, const char* s2, bool cmd, int len )
{
  const char*  s3  = s2;
  int         pos;

  for( ; *s1 != ' ' && *s1 != '\0'; s1++, s2++ )
    if( toupper( *s1 ) != toupper( *s2 ) )
      return 0;

  if( cmd && ( pos = search( command_table, MAX_ENTRY_COMMAND, s3 ) ) > 0 ) {
    if( command_table[pos].reqlen > s2-s3 )
      return 0;
    }
  else if( s2-s3 < len && *s2 != '\0' && *s2 != ' ' )
    return 0;

  return( *s2 == ' ' || *s2 == '\0' ? 2 : 1 );
}


/*
 *   STRING TYPES
 */


bool is_number( char* arg )
{
  if( *arg == '\0' )
    return FALSE;

  if( ( *arg == '+' ) || ( *arg == '-' ) )
    arg++;

  for( ; *arg != '\0' && *arg != ' '; arg++ )
    if( !isdigit( *arg ) )
      return FALSE;

  return TRUE;
}


bool isperiod( char letter )
{
  switch( letter ) {
    case '.' :
    case '?' :
    case '!' :
    return TRUE;
    }

  return FALSE;
}


bool isvowel( char letter )
{
  switch( toupper( letter ) ) {
    case 'A' :
    case 'E' :
    case 'I' :
    case 'O' :
    case 'U' :
      return TRUE;
    }

  return FALSE;
}


/*
 *   PARSE INPUT
 */


bool contains_word( const char*& argument, const char* word, char* arg )
{
  const char*  s1  = argument;
  const char*  s2;

  for( ; *s1 != '\0'; ) {
    if( exact_match( s2 = s1, word ) ) {
      for( ; s1 != argument && *(s1-1) == ' '; s1-- );
      memcpy( arg, argument, s1-argument );
      arg[s1-argument] = '\0';
      argument = s2;
      return TRUE;
      } 
    for( ; *s1 != '\0' && *s1 != ' '; s1++ );
    for( ; *s1 == ' '; s1++ );
    }

  return FALSE;
}


bool two_argument( const char*& argument, const char* word, char* arg )
{
  int i;

  if( ( i = count( argument ) ) < 2 )
    return FALSE;

  if( i == 2 ) {
    argument = one_argument( argument, arg );
    return TRUE;
    }

  return( contains_word( argument, word, arg )
    && *argument != '\0' && *arg != '\0' );
}
 

char* one_argument( const char* argument, char* arg_first )
{
  char cEnd;

  while( isspace( *argument ) )
    argument++;

  cEnd = ' ';
  if( *argument == '\'' || *argument == '"' ) {
    cEnd = *argument++;
    if( *argument == ' ' || *argument == '\0' ) {
      argument--;
      cEnd = ' ';
      }
    }

  while( *argument != '\0' ) {
    if( *argument == cEnd ) {
      argument++;
      break;
      }
    *arg_first = *argument;
    arg_first++;
    argument++;
    }

  *arg_first = '\0';

  while( isspace( *argument ) )
    argument++;

  return (char*) argument;
}


int smash_argument( char* tmp, char* argument )
{
  int   number  = 0;

  skip_spaces( argument );

  if( !strncasecmp( argument, "all", 3 ) ) {
    if( argument[3] == '\0' ) {
      *tmp = '\0';
      return -1;
      }
    if( argument[3] == '*' || argument[3] == '.' ) {
      argument += 4;
      number = -1;
      }
    }

  if( number == 0 ) {
    if( !isdigit( *argument ) ) 
      number = 1;
    else { 
      for( ; *argument != '\0' && isdigit( *argument ); argument++ ) 
        number = 10*number+*argument-'0';
      if( *argument == '*' ) {
        number *= -1;
        argument++;  
        }
      else if( *argument == '.' )
        argument++;  
      }
    }

  for( ; *argument != '\0'; argument++ ) 
    *tmp++ = ( *argument == '.' ? ' ' : *argument );

  *tmp = '\0';

  return number;
}


/*
 *   FORMATTING STRINGS
 */


char* capitalize( char* arg )
{
  char* letter;

  if( *arg != '' ) {
    *arg = toupper( *arg );
    return arg;
    }

  for( letter = arg; *letter != '\0'; ) 
    if( *letter++ == 'm' ) {
      *letter = toupper( *letter );
      return arg;
      }

  bug( "Capitalize: Missing end of escape code?" );
  bug( "-- arg = %s", arg );

  return arg;
}


char* capitalize_words( const char* argument )
{
  char*  tmp  = static_string( );
  int      i; 

  *tmp = toupper( *argument );

  for( i = 1; argument[i] != '\0'; i++ ) 
    tmp[i] = ( argument[i-1] == ' ' ? toupper( argument[i] )
      : argument[i] );

  tmp[i] = '\0';

  return tmp;
}


void smash_spaces( char* tmp )
{
  int i;

  for( i = 0; i < strlen( tmp ); i++ )
    if( tmp[i] == ' ' )
      tmp[i] = '_';

  return;
}


void add_spaces( char* tmp, int i )
{
  if( i < 0 ) {
    roach( "Add_Spaces: Number to add negative." );
    return;
    }

  tmp += strlen( tmp );

  for( ; i > 0; i-- ) 
    *tmp++ = ' ';

  *tmp = '\0';

  return;
}