swr2.0/
swr2.0/area/
swr2.0/boards/
swr2.0/clans/
swr2.0/doc/
swr2.0/planets/
swr2.0/spacecraft/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>

#include "swr_support.h"

/*
 * Uni-directional dependencies. Fix that.
 */
#ifdef __cplusplus
extern "C" {
#endif
  void bug( const char *str, ... );
  void shutdown_mud( const char *reason );
#ifdef __cplusplus
}
#endif
/*
 * Added lots of EOF checks, as most of the file crashes are based on them.
 * If an area file encounters EOF, the fread_* functions will shutdown the
 * MUD, as all area files should be read in in full or bad things will
 * happen during the game.  Any files loaded in without fBootDb which
 * encounter EOF will return what they have read so far.   These files
 * should include player files, and in-progress areas that are not loaded
 * upon bootup.
 * -- Altrag
 */

extern bool fBootDb;

/*
 * Read a letter from a file.
 */
char fread_letter( FILE *fp )
{
  char c = '\0';

  do
  {
    if ( feof(fp) )
    {
      bug("fread_letter: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );

      return '\0';
    }

    c = fgetc( fp );
  }
  while ( isspace((int) c) );

  return c;
}

/*
 * Read a float number from a file. Turn the result into a float value.
 */
float fread_float( FILE *fp )
{
  float number = 0.0;
  bool sign = FALSE, decimal = FALSE;
  char c = '\0';
  double place = 0.0;

  do
  {
    if( feof( fp ) )
    {
      bug( "%s: EOF encountered on read.", __FUNCTION__ );
      if( fBootDb )
      {
	shutdown_mud( "Corrupt file somewhere." );
	exit( EXIT_FAILURE );
      }
      return 0;
    }
    c = fgetc( fp );
  }
  while( isspace( (int) c ) );

  if( c == '+' )
    c = fgetc( fp );
  else if( c == '-' )
  {
    sign = TRUE;
    c = fgetc( fp );
  }

  if( !isdigit( (int) c ) )
  {
    bug( "%s: bad format. (%c)", __FUNCTION__, c );

    if( fBootDb )
      exit( EXIT_FAILURE );
    return 0;
  }

  while( 1 )
  {
    if( c == '.' || isdigit( (int) c ) )
    {
      if( c == '.' )
      {
	decimal = TRUE;
	c = fgetc( fp );
      }

      if( feof( fp ) )
      {
	bug( "%s: EOF encountered on read.", __FUNCTION__ );
	if( fBootDb )
	  exit( EXIT_FAILURE );
	return number;
      }
      if( !decimal )
	number = number * 10 + c - '0';
      else
      {
	place++;
	number += pow( (double) 10, ( -1 * place ) ) * ( c - '0' );
      }
      c = fgetc( fp );
    }
    else
      break;
  }

  if( sign )
    number = 0 - number;

  if( c == '|' )
    {
      number += fread_float( fp );
    }
  else if( c != ' ' )
    {
      if( ungetc( c, fp ) == EOF )
	{
	  bug("fread_float: EOF encountered on ungetc.\r\n");

	  if ( fBootDb )
	    exit( EXIT_FAILURE );
	}
    }

  return number;
}

/*
 * Read a number from a file.
 */
int fread_number( FILE *fp )
{
  int number = 0;
  bool sign = FALSE;
  char c = 0;

  do
  {
    if ( feof(fp) )
    {
      bug("fread_number: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      return 0;
    }
    c = fgetc( fp );
  }
  while ( isspace( (int) c ) );

  if ( c == '+' )
  {
    c = fgetc( fp );
  }
  else if ( c == '-' )
  {
    sign = TRUE;
    c = fgetc( fp );
  }

  if ( !isdigit((int) c) )
  {
    bug( "Fread_number: bad format. (%c)", c );
    if ( fBootDb )
      exit( EXIT_FAILURE );
    return 0;
  }

  while ( isdigit( (int) c ) )
  {
    if ( feof(fp) )
    {
      bug("fread_number: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      return number;
    }
    number = number * 10 + c - '0';
    c      = fgetc( fp );
  }

  if ( sign )
    number = 0 - number;

  if ( c == '|' )
    number += fread_number( fp );
  else if ( c != ' ' )
    {
      if( ungetc( c, fp ) == EOF )
        {
          bug("fread_number: EOF encountered on ungetc.\r\n");

          if ( fBootDb )
            exit( EXIT_FAILURE );
        }
    }

  return number;
}

/*
 * custom str_dup using create                                  -Thoric
 */
char *str_dup( const char *str )
{
  static char *ret = NULL;

  if( !str )
    return NULL;

  CREATE( ret, char, strlen( str ) + 1 );
  strcpy( ret, str );
  return ret;
}

/*
 * Read a string from file fp
 */
char *fread_string( FILE *fp )
{
  char buf[MAX_STRING_LENGTH];
  char *plast = buf;
  char c = 0;
  int ln = 0;

  buf[0] = '\0';

  /*
   * Skip blanks.
   * Read first char.
   */
  do
  {
    if ( feof(fp) )
    {
      bug("fread_string: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      return STRALLOC("");
    }
    c = fgetc( fp );
  }
  while ( isspace((int)c) );

  if ( ( *plast++ = c ) == '~' )
    return STRALLOC( "" );

  for ( ;; )
  {
    if ( ln >= (MAX_STRING_LENGTH - 1) )
    {
      bug( "fread_string: string too long" );
      *plast = '\0';
      return STRALLOC( buf );
    }
    switch ( (int)( *plast = fgetc( fp ) ) )
    {
      default:
	plast++; ln++;
	break;

      case EOF:
	bug( "Fread_string: EOF" );
	if ( fBootDb )
	  exit( EXIT_FAILURE );
	*plast = '\0';
	return STRALLOC(buf);
	break;

      case '\n':
	plast++;  ln++;
	*plast++ = '\r';  ln++;
	break;

      case '\r':
	break;

      case '~':
	*plast = '\0';
	return STRALLOC( buf );
    }
  }
}

/*
 * Read a string from file fp using str_dup (ie: no string hashing)
 */
char *fread_string_nohash( FILE *fp )
{
  char buf[MAX_STRING_LENGTH];
  char *plast = buf;
  char c = 0;
  int ln = 0;

  buf[0] = '\0';

  /*
   * Skip blanks.
   * Read first char.
   */
  do
  {
    if ( feof(fp) )
    {
      bug("fread_string_no_hash: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      return str_dup("");
    }
    c = fgetc( fp );
  }
  while ( isspace((int)c) );

  if ( ( *plast++ = c ) == '~' )
    return str_dup( "" );

  for ( ;; )
  {
    if ( ln >= (MAX_STRING_LENGTH - 1) )
    {
      bug( "fread_string_no_hash: string too long" );
      *plast = '\0';
      return str_dup( buf );
    }
    switch ( (int)( *plast = fgetc( fp ) ) )
    {
      default:
	plast++; ln++;
	break;

      case EOF:
	bug( "Fread_string_no_hash: EOF" );
	if ( fBootDb )
	  exit( EXIT_FAILURE );
	*plast = '\0';
	return str_dup(buf);
	break;

      case '\n':
	plast++;  ln++;
	*plast++ = '\r';  ln++;
	break;

      case '\r':
	break;

      case '~':
	*plast = '\0';
	return str_dup( buf );
    }
  }
}

/*
 * Read to end of line (for comments).
 */
void fread_to_eol( FILE *fp )
{
  char c = 0;

  do
  {
    if ( feof(fp) )
    {
      bug("fread_to_eol: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      return;
    }
    c = fgetc( fp );
  }
  while ( c != '\n' && c != '\r' );

  do
  {
    c = fgetc( fp );
  }
  while ( c == '\n' || c == '\r' );

  if( ungetc( c, fp ) == EOF )
    {
      bug("fread_to_eol: EOF encountered on ungetc.\r\n");

      if ( fBootDb )
	exit( EXIT_FAILURE );
    }
}

/*
 * Read to end of line into static buffer                       -Thoric
 */
char *fread_line( FILE *fp )
{
  static char line[MAX_STRING_LENGTH];
  char *pline = line;
  char c = 0;
  int ln = 0;

  line[0] = '\0';

  /*
   * Skip blanks.
   * Read first char.
   */
  do
  {
    if ( feof(fp) )
    {
      bug("fread_line: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      strcpy(line, "");
      return line;
    }
    c = fgetc( fp );
  }
  while ( isspace((int)c) );

  if( ungetc( c, fp ) == EOF )
    {
      bug("fread_line: EOF encountered on ungetc.\r\n");

      if ( fBootDb )
	exit( EXIT_FAILURE );
    }

  do
  {
    if ( feof(fp) )
    {
      bug("fread_line: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      *pline = '\0';
      return line;
    }
    c = fgetc( fp );
    *pline++ = c; ln++;
    if ( ln >= (MAX_STRING_LENGTH - 1) )
    {
      bug( "fread_line: line too long" );
      break;
    }
  }
  while ( c != '\n' && c != '\r' );

  do
  {
    c = fgetc( fp );
  }
  while ( c == '\n' || c == '\r' );

  if( ungetc( c, fp ) == EOF )
    {
      bug("%s: EOF encountered on ungetc.\r\n", __FUNCTION__);

      if ( fBootDb )
	exit( EXIT_FAILURE );
    }

  *pline = '\0';
  return line;
}

/*
 * Read one word (into static buffer).
 */
char *fread_word( FILE *fp )
{
  static char word[MAX_INPUT_LENGTH];
  char *pword = NULL;
  char cEnd ='\0';

  do
  {
    if ( feof(fp) )
    {
      bug("fread_word: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      word[0] = '\0';
      return word;
    }
    cEnd = fgetc( fp );
  }
  while ( isspace( (int) cEnd ) );

  if ( cEnd == '\'' || cEnd == '"' )
  {
    pword   = word;
  }
  else
  {
    word[0] = cEnd;
    pword   = word+1;
    cEnd    = ' ';
  }

  for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )
  {
    if ( feof(fp) )
    {
      bug("fread_word: EOF encountered on read.\r\n");
      if ( fBootDb )
	exit( EXIT_FAILURE );
      *pword = '\0';
      return word;
    }
    *pword = fgetc( fp );
    if ( cEnd == ' ' ? isspace((int) *pword) : *pword == cEnd )
    {
      if ( cEnd == ' ' )
	{
	  if( ungetc( *pword, fp ) == EOF )
	    {
	      bug("%s: EOF encountered on ungetc.\r\n", __FUNCTION__);

	      if ( fBootDb )
		exit( EXIT_FAILURE );
	    }
	}

      *pword = '\0';
      return word;
    }
  }

  bug( "Fread_word: word too long" );
  exit( EXIT_FAILURE );
  return NULL;
}

/*
 * Append a string to a file.
 */
void append_to_file( const char *file, const char *str )
{
  FILE *fp = NULL;

  if ( ( fp = fopen( file, "a" ) ) )
  {
    fprintf( fp, "%s\n", str );
    fclose( fp );
  }
}