* Make CHECK_OBJECT, CHECK_PROJECTILE and CHECK_STRUCTURE macros that redirect to a function

* Add two new files: src/baseobject.[ch]
 * Have CHECK_OBJECT call any of CHECK_DROID, CHECK_PROJECTILE or CHECK_STRUCTURE depending on the object's type
 * Change CHECK_DROID and checkDroid to use the AT_MACRO to get the current filename and line number
 * Change checkDroid to use ASSERT_HELPER to provide the source of the assertion

NOTE: The autotools, Code::Blocks, win32 Makefiles and MSVC buildsystems are updated, Xcode will still require an update

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5866 4a71c877-e1ca-e34f-864e-861f7616d084
master
Giel van Schijndel 2008-08-24 15:56:00 +00:00
parent 173ee31214
commit 360dc86ef4
13 changed files with 185 additions and 70 deletions

View File

@ -23,7 +23,7 @@ CLEANFILES = level_lexer.lex.c message_lexer.lex.c message_parser.tab.c \
bin_PROGRAMS = warzone2100
noinst_HEADERS = action.h advvis.h ai.h aiexperience.h anim_id.h \
astar.h atmos.h basedef.h bridge.h bucket3d.h \
astar.h atmos.h basedef.h baseobject.h bridge.h bucket3d.h \
projectiledef.h cheat.h clparse.h cluster.h cmddroid.h \
cmddroiddef.h combat.h component.h configuration.h console.h data.h \
design.h difficulty.h display.h display3d.h display3ddef.h \
@ -44,7 +44,7 @@ noinst_HEADERS = action.h advvis.h ai.h aiexperience.h anim_id.h \
warcam.h warzoneconfig.h weapondef.h main.h wrappers.h
warzone2100_SOURCES = scriptvals_parser.tab.c scriptvals_lexer.lex.c \
level_lexer.lex.c ai.c aiexperience.c astar.c action.c advvis.c atmos.c bridge.c \
level_lexer.lex.c ai.c aiexperience.c astar.c action.c advvis.c atmos.c baseobject.c bridge.c \
cheat.c cluster.c cmddroid.c combat.c component.c console.c \
data.c design.c difficulty.c display.c droid.c e3demo.c \
edit3d.c effects.c environ.c fpath.c feature.c formation.c frontend.c \

View File

@ -25,6 +25,7 @@
#define __INCLUDED_BASEDEF_H__
#include "lib/ivis_common/pievector.h"
#include "baseobject.h"
#include "displaydef.h"
#include "statsdef.h"
@ -104,27 +105,4 @@ static inline bool isDead(const BASE_OBJECT* psObj)
return (psObj->died > NOT_CURRENT_LIST);
}
/* assert if object is bad */
#define CHECK_OBJECT(object) \
do \
{ \
assert(object != NULL); \
\
ASSERT(object->type == OBJ_DROID \
|| object->type == OBJ_STRUCTURE \
|| object->type == OBJ_FEATURE \
|| object->type == OBJ_PROJECTILE \
|| object->type == OBJ_TARGET, \
"CHECK_OBJECT: Invalid object type (type num %u)", (unsigned int)(object)->type); \
\
ASSERT(object->type == OBJ_FEATURE \
|| object->type == OBJ_TARGET \
|| object->player < MAX_PLAYERS, \
"CHECK_OBJECT: Out of bound owning player number (%u)", (unsigned int)(object)->player); \
\
ASSERT(object->direction <= 360.0f \
&& object->direction >= 0.0f, \
"CHECK_OBJECT: out of range direction (%f)", (float)(object)->direction); \
} while (0)
#endif // __INCLUDED_BASEDEF_H__

64
src/baseobject.c Normal file
View File

@ -0,0 +1,64 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "lib/framework/frame.h"
#include "lib/framework/debug.h"
#include "baseobject.h"
#include "basedef.h"
#include "droid.h"
#include "projectile.h"
#include "structure.h"
void checkObject(const struct BASE_OBJECT* psObject, const char * const location_description, const char * function)
{
ASSERT(psObject != NULL, "NULL pointer");
switch (psObject->type)
{
case OBJ_DROID:
checkDroid((const DROID *)psObject, location_description, function);
break;
case OBJ_STRUCTURE:
checkStructure((const STRUCTURE *)psObject, location_description, function);
break;
case OBJ_PROJECTILE:
checkProjectile((const PROJECTILE *)psObject, location_description, function);
break;
case OBJ_FEATURE:
case OBJ_TARGET:
break;
default:
ASSERT_HELPER(!"invalid object type", location_description, function, "CHECK_OBJECT: Invalid object type (type num %u)", (unsigned int)psObject->type);
break;
}
ASSERT(psObject->type == OBJ_FEATURE
|| psObject->type == OBJ_TARGET
|| psObject->player < MAX_PLAYERS,
location_description, function, "CHECK_OBJECT: Out of bound owning player number (%u)", (unsigned int)psObject->player);
ASSERT(psObject->direction <= 360.0f
&& psObject->direction >= 0.0f,
location_description, function, "CHECK_OBJECT: Out of range direction (%f)", (float)psObject->direction);
}

35
src/baseobject.h Normal file
View File

@ -0,0 +1,35 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \file
* Functions for the base object type.
*/
#ifndef __INCLUDED_BASEOBJECT_H__
#define __INCLUDED_BASEOBJECT_H__
// Forward declaration to allow pointers to this type
struct BASE_OBJECT;
void checkObject(const struct BASE_OBJECT* psObject, const char * const location_description, const char * function);
/* assert if object is bad */
#define CHECK_OBJECT(object) checkObject((object), AT_MACRO, __FUNCTION__)
#endif // __INCLUDED_BASEOBJECT_H__

View File

@ -5171,24 +5171,25 @@ void droidSetPosition(DROID *psDroid, int x, int y)
}
/** Check validity of a droid. Crash hard if it fails. */
void checkDroid(const DROID *droid, const int line, const char *file)
void checkDroid(const DROID *droid, const char * const location_description, const char * function)
{
int i;
ASSERT(droid != NULL, "NULL droid pointer coming from %s line %d", file, line);
ASSERT(droid != NULL && droid->type == OBJ_DROID, "Not droid (type %d) coming from %s line %d", (int)droid->type, file, line);
ASSERT(droid->direction <= 360.0f && droid->direction >= 0.0f, "Bad droid direction %f coming from %s line %d", droid->direction, file, line);
ASSERT(droid->numWeaps <= DROID_MAXWEAPS, "Bad number of droid weapons %d coming from %s line %d", (int)droid->numWeaps, file, line);
ASSERT(droid->listSize <= ORDER_LIST_MAX, "Bad number of droid orders %d coming from %s line %d", (int)droid->listSize, file, line);
ASSERT(droid->player < MAX_PLAYERS, "Bad droid owner %d coming from %s line %d", (int)droid->player, file, line);
ASSERT(droidOnMap(droid), "Droid off map coming from %s line %d", file, line);
ASSERT_HELPER(droid != NULL, location_description, function, "CHECK_DROID: NULL pointer");
ASSERT_HELPER(droid->type == OBJ_DROID, location_description, function, "CHECK_DROID: Not droid (type %d)", (int)droid->type);
ASSERT_HELPER(droid->direction <= 360.0f && droid->direction >= 0.0f, location_description, function, "CHECK_DROID: Bad droid direction %f", droid->direction);
ASSERT_HELPER(droid->numWeaps <= DROID_MAXWEAPS, location_description, function, "CHECK_DROID: Bad number of droid weapons %d", (int)droid->numWeaps);
ASSERT_HELPER(droid->listSize <= ORDER_LIST_MAX, location_description, function, "CHECK_DROID: Bad number of droid orders %d", (int)droid->listSize);
ASSERT_HELPER(droid->player < MAX_PLAYERS, location_description, function, "CHECK_DROID: Bad droid owner %d", (int)droid->player);
ASSERT_HELPER(droidOnMap(droid), location_description, function, "CHECK_DROID: Droid off map");
for (i = 0; i < DROID_MAXWEAPS; ++i)
{
ASSERT(droid->turretRotation[i] <= 360, "Bad turret rotation of turret %u coming from %s line %d", i, file, line);
ASSERT(droid->asWeaps[i].lastFired <= gameTime, "Bad last fired time for turret %u coming from %s line %d", i, file, line);
ASSERT_HELPER(droid->turretRotation[i] <= 360, location_description, function, "CHECK_DROID: Bad turret rotation of turret %u", i);
ASSERT_HELPER(droid->asWeaps[i].lastFired <= gameTime, location_description, function, "CHECK_DROID: Bad last fired time for turret %u", i);
if (droid->psActionTarget[i])
{
ASSERT(droid->psActionTarget[i]->direction >= 0.0f, "Bad direction of turret %u's target coming from %s line %d", i, file, line);
ASSERT_HELPER(droid->psActionTarget[i]->direction >= 0.0f, location_description, function, "CHECK_DROID: Bad direction of turret %u's target", i);
}
}
}

View File

@ -535,10 +535,10 @@ static inline void setSaveDroidBase(DROID *psSaveDroid, STRUCTURE *psNewBase)
#endif
}
void checkDroid(const DROID *droid, const int line, const char *file);
void checkDroid(const DROID *droid, const char * const location_description, const char * function);
/* assert if droid is bad */
#define CHECK_DROID(droid) checkDroid(droid, __LINE__, __FILE__)
#define CHECK_DROID(droid) checkDroid(droid, AT_MACRO, __FUNCTION__)
// Minimum damage a weapon will deal to its target
#define MIN_WEAPON_DAMAGE 1

View File

@ -9,6 +9,7 @@ SRC=ai.c \
action.c \
advvis.c \
atmos.c \
baseobject.c \
bridge.c \
cheat.c \
cluster.c \

View File

@ -2248,3 +2248,24 @@ static UDWORD establishTargetHeight(BASE_OBJECT *psTarget)
return 0;
}
}
void checkProjectile(const PROJECTILE* psProjectile, const char * const location_description, const char * function)
{
ASSERT_HELPER(psProjectile != NULL, location_description, function, "CHECK_PROJECTILE: NULL pointer");
ASSERT_HELPER(psProjectile->psWStats != NULL, location_description, function, "CHECK_PROJECTILE");
ASSERT_HELPER(psProjectile->type == OBJ_PROJECTILE, location_description, function, "CHECK_PROJECTILE");
ASSERT_HELPER(psProjectile->player < MAX_PLAYERS, location_description, function, "CHECK_PROJECTILE: Out of bound owning player number (%u)", (unsigned int)psProjectile->player);
ASSERT_HELPER(psProjectile->state == PROJ_INFLIGHT
|| psProjectile->state == PROJ_IMPACT
|| psProjectile->state == PROJ_POSTIMPACT, location_description, function, "CHECK_PROJECTILE: invalid projectile state: %u", (unsigned int)psProjectile->state);
ASSERT_HELPER(psProjectile->direction <= 360.0f && psProjectile->direction >= 0.0f, location_description, function, "CHECK_PROJECTILE: out of range direction (%f)", psProjectile->direction);
if (psProjectile->psDest)
checkObject(psProjectile->psDest, location_description, function);
if (psProjectile->psSource)
checkObject(psProjectile->psSource, location_description, function);
if (psProjectile->psDamaged)
checkObject(psProjectile->psDamaged, location_description, function);
}

View File

@ -97,20 +97,9 @@ static inline void setProjectileDamaged(PROJECTILE *psProj, BASE_OBJECT *psObj)
/* @} */
void checkProjectile(const PROJECTILE* psProjectile, const char * const location_description, const char * function);
/* assert if projectile is bad */
#define CHECK_PROJECTILE(object) \
do { \
assert(object != NULL); \
assert(object->psWStats != NULL); \
assert(object->type == OBJ_PROJECTILE); \
assert(object->player < MAX_PLAYERS); \
assert(object->state == PROJ_INFLIGHT \
|| object->state == PROJ_IMPACT \
|| object->state == PROJ_POSTIMPACT); \
assert(object->direction <= 360.0f && object->direction >= 0.0f); \
if (object->psDest) CHECK_OBJECT(object->psDest); \
if (object->psSource) CHECK_OBJECT(object->psSource); \
if (object->psDamaged) CHECK_OBJECT(object->psDamaged); \
} while (0)
#define CHECK_PROJECTILE(object) checkProjectile((object), AT_MACRO, __FUNCTION__)
#endif // __INCLUDED_SRC_PROJECTILE_H__

View File

@ -7952,3 +7952,23 @@ BOOL structureCheckReferences(STRUCTURE *psVictimStruct)
}
return true;
}
void checkStructure(const STRUCTURE* psStructure, const char * const location_description, const char * function)
{
unsigned int i;
ASSERT(psStructure != NULL, location_description, function, "CHECK_STRUCTURE: NULL pointer");
ASSERT(psStructure->type == OBJ_STRUCTURE, location_description, function, "CHECK_STRUCTURE: No structure (type num %u)", function, (unsigned int)psStructure->type);
ASSERT(psStructure->player < MAX_PLAYERS, location_description, function, "CHECK_STRUCTURE: Out of bound player num (%u)", (unsigned int)psStructure->player);
ASSERT(psStructure->pStructureType->type < NUM_DIFF_BUILDINGS, location_description, function, "CHECK_STRUCTURE: Out of bound structure type (%u)", (unsigned int)psStructure->pStructureType->type);
ASSERT(psStructure->numWeaps <= STRUCT_MAXWEAPS, location_description, function, "CHECK_STRUCTURE: Out of bound weapon count (%u)", (unsigned int)psStructure->numWeaps);
for (i = 0; i < ARRAY_SIZE(psStructure->turretRotation); ++i)
{
ASSERT(psStructure->turretRotation[i] <= 360, location_description, function, "CHECK_STRUCTURE: Out of range turret rotation (turret %u; rotation: %u)", i, (unsigned int)psStructure->turretRotation[i]);
if (psStructure->psTarget[i])
{
checkObject(psStructure->psTarget[i], location_description, function);
}
}
}

View File

@ -441,24 +441,9 @@ static inline void _setStructureTarget(STRUCTURE *psBuilding, BASE_OBJECT *psNew
#endif
}
#define CHECK_STRUCTURE(object) \
do { \
unsigned int i; \
\
ASSERT((object) != NULL, "CHECK_STRUCTURE: NULL pointer"); \
ASSERT((object)->type == OBJ_STRUCTURE, "CHECK_STRUCTURE: No structure (type num %u)", (unsigned int)(object)->type); \
ASSERT((object)->player < MAX_PLAYERS, "CHECK_STRUCTURE: Out of bound player num (%u)", (unsigned int)(object)->player); \
ASSERT((object)->pStructureType->type < NUM_DIFF_BUILDINGS, "CHECK_STRUCTURE: Out of bound structure type (%u)", (unsigned int)(object)->pStructureType->type); \
ASSERT((object)->numWeaps <= STRUCT_MAXWEAPS, "CHECK_STRUCTURE: Out of bound weapon count (%u)", (unsigned int)(object)->numWeaps); \
for (i = 0; i < STRUCT_MAXWEAPS; ++i) \
{ \
ASSERT((object)->turretRotation[i] <= 360, "Out of range turret rotation (turret %u; rotation: %u)", i, (unsigned int)(object)->turretRotation[i]); \
if ((object)->psTarget[i]) \
{ \
CHECK_OBJECT((object)->psTarget[i]); \
} \
} \
} while (0)
void checkStructure(const STRUCTURE* psStructure, const char * const location_description, const char * function);
#define CHECK_STRUCTURE(object) checkStructure((object), AT_MACRO, __FUNCTION__)
extern void structureInitVars(void);

View File

@ -1444,6 +1444,19 @@
<Option target="DBGWindows" />
<Option target="NDBGWindows" />
</Unit>
<Unit filename="src/baseobject.c">
<Option compilerVar="CC" />
<Option target="DBGUnix" />
<Option target="NDBGUnix" />
<Option target="DBGWindows" />
<Option target="NDBGWindows" />
</Unit>
<Unit filename="src/baseobject.h">
<Option target="DBGUnix" />
<Option target="NDBGUnix" />
<Option target="DBGWindows" />
<Option target="NDBGWindows" />
</Unit>
<Unit filename="src/bridge.c">
<Option compilerVar="CC" />
<Option target="DBGUnix" />

View File

@ -256,6 +256,10 @@
RelativePath="..\src\aud.c"
>
</File>
<File
RelativePath="..\src\baseobject.c"
>
</File>
<File
RelativePath="..\src\bridge.c"
>
@ -707,6 +711,10 @@
RelativePath="..\src\basedef.h"
>
</File>
<File
RelativePath="..\src\baseobject.h"
>
</File>
<File
RelativePath="..\src\bridge.h"
>