#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 ); } }