Changeset - r14662:8798e984ee81
[Not reviewed]
master
0 3 0
yexo - 14 years ago 2010-02-25 15:54:40
yexo@openttd.org
(svn r19251) -Codechange: add a contructor to GRFError and use it to allocating errors more uniform.
-Fix: some grf error messages didn't free the previous error messages, creating a memory leak
3 files changed with 36 insertions and 45 deletions:
0 comments (0 inline, 0 general)
src/newgrf.cpp
Show inline comments
 
@@ -2753,14 +2753,14 @@ static bool HandleChangeInfoResult(const
 
			/* Fall through */
 

	
 
		case CIR_INVALID_ID:
 
			/* No debug message for an invalid ID, as it has already been output */
 
			_skip_sprites = -1;
 
			_cur_grfconfig->status = GCS_DISABLED;
 
			_cur_grfconfig->error  = CallocT<GRFError>(1);
 
			_cur_grfconfig->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
			delete _cur_grfconfig->error;
 
			_cur_grfconfig->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL);
 
			_cur_grfconfig->error->message  = (cir == CIR_INVALID_ID) ? STR_NEWGRF_ERROR_INVALID_ID : STR_NEWGRF_ERROR_UNKNOWN_PROPERTY;
 
			return true;
 
	}
 
}
 

	
 
/* Action 0x00 */
 
@@ -4328,22 +4328,16 @@ static void CfgApply(ByteReader *buf)
 
 * but that might give unwanted results. Disabling the NewGRF gives the
 
 * best result as no NewGRF author can complain about that.
 
 * @param c the NewGRF to disable.
 
 */
 
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
 
{
 
	if (c->error != NULL) {
 
		free(c->error->custom_message);
 
		free(c->error->data);
 
		free(c->error);
 
	}
 
	delete c->error;
 
	c->status = GCS_DISABLED;
 
	c->error  = CallocT<GRFError>(1);
 
	c->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC);
 
	c->error->data = strdup(_cur_grfconfig->name);
 
	c->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
	c->error->message  = STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC;
 

	
 
	ClearTemporaryNewGRFData(GetFileByGRFID(c->grfid));
 
}
 

	
 
/* Action 0x07
 
 * Action 0x09 */
 
@@ -4546,15 +4540,14 @@ static void GRFInfo(ByteReader *buf)
 
	uint8 version    = buf->ReadByte();
 
	uint32 grfid     = buf->ReadDWord();
 
	const char *name = buf->ReadString();
 

	
 
	if (_cur_stage < GLS_RESERVE && _cur_grfconfig->status != GCS_UNKNOWN) {
 
		_cur_grfconfig->status = GCS_DISABLED;
 
		_cur_grfconfig->error  = CallocT<GRFError>(1);
 
		_cur_grfconfig->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
		_cur_grfconfig->error->message  = STR_NEWGRF_ERROR_MULTIPLE_ACTION_8;
 
		delete _cur_grfconfig->error;
 
		_cur_grfconfig->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
 

	
 
		_skip_sprites = -1;
 
		return;
 
	}
 

	
 
	_cur_grffile->grfid = grfid;
 
@@ -4686,15 +4679,13 @@ static void GRFLoadError(ByteReader *buf
 

	
 
	if (buf->Remaining() <= 1) {
 
		grfmsg(7, "GRFLoadError: No message data supplied.");
 
		return;
 
	}
 

	
 
	GRFError *error = CallocT<GRFError>(1);
 

	
 
	error->severity = sevstr[severity];
 
	GRFError *error = new GRFError(sevstr[severity]);
 

	
 
	if (message_id == 0xFF) {
 
		/* This is a custom error message. */
 
		if (buf->HasData()) {
 
			const char *message = buf->ReadString();
 

	
 
@@ -5556,23 +5547,18 @@ static void TranslateGRFStrings(ByteRead
 
		return;
 
	}
 

	
 
	if (c->status == GCS_INITIALISED) {
 
		/* If the file is not active but will be activated later, give an error
 
		 * and disable this file. */
 
		GRFError *error = CallocT<GRFError>(1);
 
		delete _cur_grfconfig->error;
 
		_cur_grfconfig->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_LOAD_AFTER);
 

	
 
		char tmp[256];
 
		GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
 
		error->data = strdup(tmp);
 

	
 
		error->message  = STR_NEWGRF_ERROR_LOAD_AFTER;
 
		error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 

	
 
		if (_cur_grfconfig->error != NULL) free(_cur_grfconfig->error);
 
		_cur_grfconfig->error = error;
 
		_cur_grfconfig->error->data = strdup(tmp);
 

	
 
		_cur_grfconfig->status = GCS_DISABLED;
 
		ClearTemporaryNewGRFData(_cur_grffile);
 
		_skip_sprites = -1;
 
		return;
 
	}
 
@@ -5859,15 +5845,13 @@ static void ResetNewGRF()
 
}
 

	
 
static void ResetNewGRFErrors()
 
{
 
	for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 
		if (!HasBit(c->flags, GCF_COPY) && c->error != NULL) {
 
			free(c->error->custom_message);
 
			free(c->error->data);
 
			free(c->error);
 
			delete c->error;
 
			c->error = NULL;
 
		}
 
	}
 
}
 

	
 
/**
 
@@ -6358,15 +6342,14 @@ static void DecodeSpecialSprite(byte *bu
 
		}
 
	} catch (...) {
 
		grfmsg(1, "DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
 

	
 
		_skip_sprites = -1;
 
		_cur_grfconfig->status = GCS_DISABLED;
 
		_cur_grfconfig->error  = CallocT<GRFError>(1);
 
		_cur_grfconfig->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
		_cur_grfconfig->error->message  = STR_NEWGRF_ERROR_READ_BOUNDS;
 
		delete _cur_grfconfig->error;
 
		_cur_grfconfig->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_READ_BOUNDS);
 
	}
 
}
 

	
 

	
 
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
 
{
 
@@ -6390,15 +6373,13 @@ void LoadNewGRFFile(GRFConfig *config, u
 
		_cur_grffile->is_ottdfile = config->IsOpenTTDBaseGRF();
 
	}
 

	
 
	if (file_index > LAST_GRF_SLOT) {
 
		DEBUG(grf, 0, "'%s' is not loaded as the maximum number of GRFs has been reached", filename);
 
		config->status = GCS_DISABLED;
 
		config->error  = CallocT<GRFError>(1);
 
		config->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
		config->error->message  = STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED;
 
		config->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
 
		return;
 
	}
 

	
 
	FioOpenFile(file_index, filename);
 
	_file_index = file_index; // XXX
 
	_palette_remap_grf[_file_index] = (config->windows_paletted != (_use_palette == PAL_WINDOWS));
 
@@ -6438,15 +6419,14 @@ void LoadNewGRFFile(GRFConfig *config, u
 
				FioSkipBytes(num);
 
			}
 
		} else {
 
			if (_skip_sprites == 0) {
 
				grfmsg(0, "LoadNewGRFFile: Unexpected sprite, disabling");
 
				config->status = GCS_DISABLED;
 
				config->error  = CallocT<GRFError>(1);
 
				config->error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
				config->error->message  = STR_NEWGRF_ERROR_UNEXPECTED_SPRITE;
 
				delete config->error;
 
				config->error  = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
 
				break;
 
			}
 

	
 
			FioSkipBytes(7);
 
			SkipSpriteData(type, num - 8);
 
		}
src/newgrf_config.cpp
Show inline comments
 
@@ -23,12 +23,23 @@
 

	
 
GRFConfig *_all_grfs;
 
GRFConfig *_grfconfig;
 
GRFConfig *_grfconfig_newgame;
 
GRFConfig *_grfconfig_static;
 

	
 
GRFError::GRFError(StringID severity, StringID message) :
 
	message(message),
 
	severity(severity)
 
{
 
}
 

	
 
GRFError::~GRFError()
 
{
 
	free(this->custom_message);
 
	free(this->data);
 
 }
 

	
 
/**
 
 * Update the palettes of the graphics from the config file.
 
 * This is needed because the config file gets read and parsed
 
 * before the palette is chosen (one can configure the base
 
 * graphics set governing the palette in the config after all).
 
@@ -98,18 +109,13 @@ void ClearGRFConfig(GRFConfig **config)
 
{
 
	/* GCF_COPY as in NOT strdupped/alloced the filename, name and info */
 
	if (!HasBit((*config)->flags, GCF_COPY)) {
 
		free((*config)->filename);
 
		free((*config)->name);
 
		free((*config)->info);
 

	
 
		if ((*config)->error != NULL) {
 
			free((*config)->error->custom_message);
 
			free((*config)->error->data);
 
			free((*config)->error);
 
		}
 
		delete (*config)->error;
 
	}
 
	free(*config);
 
	*config = NULL;
 
}
 

	
 

	
 
@@ -136,14 +142,15 @@ GRFConfig *DuplicateGRFConfig(const GRFC
 
	*config = *c;
 

	
 
	if (c->filename != NULL) config->filename = strdup(c->filename);
 
	if (c->name     != NULL) config->name = strdup(c->name);
 
	if (c->info     != NULL) config->info = strdup(c->info);
 
	if (c->error    != NULL) {
 
		config->error = MallocT<GRFError>(1);
 
		memcpy(config->error, c->error, sizeof(GRFError));
 
		config->error = new GRFError(c->error->severity, c->error->message);
 
		config->error->num_params = c->error->num_params;
 
		memcpy(config->error->param_value, c->error->param_value, sizeof(config->error->param_value));
 
		if (c->error->data           != NULL) config->error->data = strdup(c->error->data);
 
		if (c->error->custom_message != NULL) config->error->custom_message = strdup(c->error->custom_message);
 
	}
 

	
 
	ClrBit(config->flags, GCF_COPY);
 

	
src/newgrf_config.h
Show inline comments
 
@@ -10,12 +10,13 @@
 
/** @file newgrf_config.h Functions to find and configure NewGRFs. */
 

	
 
#ifndef NEWGRF_CONFIG_H
 
#define NEWGRF_CONFIG_H
 

	
 
#include "strings_type.h"
 
#include "core/alloc_type.hpp"
 

	
 
/** GRF config bit flags */
 
enum GCF_Flags {
 
	GCF_SYSTEM,     ///< GRF file is an openttd-internal system grf
 
	GCF_UNSAFE,     ///< GRF file is unsafe for static usage
 
	GCF_STATIC,     ///< GRF file is used statically (can be used in any MP game)
 
@@ -52,13 +53,16 @@ enum GRFListCompatibility {
 
struct GRFIdentifier {
 
	uint32 grfid;     ///< GRF ID (defined by Action 0x08)
 
	uint8 md5sum[16]; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
 
};
 

	
 
/** Information about why GRF had problems during initialisation */
 
struct GRFError {
 
struct GRFError : ZeroedMemoryAllocator {
 
	GRFError(StringID severity, StringID message = 0);
 
	~GRFError();
 

	
 
	char *custom_message;  ///< Custom message (if present)
 
	char *data;            ///< Additional data for message and custom_message
 
	StringID message;      ///< Default message
 
	StringID severity;     ///< Info / Warning / Error / Fatal
 
	uint8 num_params;      ///< Number of additinal parameters for message and custom_message (0, 1 or 2)
 
	uint32 param_value[2]; ///< Values of GRF parameters to show for message and custom_message
0 comments (0 inline, 0 general)