map creator: don't crash when using a template within itself (#534)

scancodes-fix
Armin Burgmeier 2013-01-13 18:18:26 +01:00
parent 28e2bdbb92
commit 2d3a4981bf
2 changed files with 22 additions and 17 deletions

View File

@ -196,13 +196,17 @@ C4MCNode::C4MCNode(C4MCNode *pOwner)
*Name=0;
}
C4MCNode::C4MCNode(C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone)
C4MCNode::C4MCNode(C4MCParser* pParser, C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone)
{
// Make sure the template is not used recursively within itself
for(C4MCNode* pParent = pOwner; pParent != NULL; pParent = pParent->Owner)
if(pParent == &rTemplate)
throw C4MCParserErr(pParser, C4MCErr_NoRecTemplate, rTemplate.Name);
// set owner and stuff
Reg2Owner(pOwner);
// copy children from template
for (C4MCNode *pChild=rTemplate.Child0; pChild; pChild=pChild->Next)
pChild->clone(this);
pChild->clone(pParser, this);
// no name
*Name=0;
}
@ -324,7 +328,7 @@ C4MCOverlay::C4MCOverlay(C4MCNode *pOwner) : C4MCNode(pOwner)
pEvaluateFunc=pDrawFunc=NULL;
}
C4MCOverlay::C4MCOverlay(C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone) : C4MCNode(pOwner, rTemplate, fClone)
C4MCOverlay::C4MCOverlay(C4MCParser* pParser, C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone) : C4MCNode(pParser, pOwner, rTemplate, fClone)
{
// copy fields
X=rTemplate.X; Y=rTemplate.Y; Wdt=rTemplate.Wdt; Hgt=rTemplate.Hgt;
@ -642,7 +646,7 @@ C4MCPoint::C4MCPoint(C4MCNode *pOwner) : C4MCNode(pOwner)
X=Y=0;
}
C4MCPoint::C4MCPoint(C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone) : C4MCNode(pOwner, rTemplate, fClone)
C4MCPoint::C4MCPoint(C4MCParser* pParser, C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone) : C4MCNode(pParser, pOwner, rTemplate, fClone)
{
// copy fields
X=rTemplate.X; Y=rTemplate.Y;
@ -695,7 +699,7 @@ C4MCMap::C4MCMap(C4MCNode *pOwner) : C4MCOverlay(pOwner)
}
C4MCMap::C4MCMap(C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone) : C4MCOverlay(pOwner, rTemplate, fClone)
C4MCMap::C4MCMap(C4MCParser* pParser, C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone) : C4MCOverlay(pParser, pOwner, rTemplate, fClone)
{
}
@ -1129,7 +1133,7 @@ void C4MCParser::ParseTo(C4MCNode *pToNode)
if (SEqual(CurrTokenIdtf, C4MC_Overlay))
{
// overlay: create overlay node, using default template
pNewNode = new C4MCOverlay(pToNode, MapCreator->DefaultOverlay, false);
pNewNode = new C4MCOverlay(this, pToNode, MapCreator->DefaultOverlay, false);
State=PS_KEYWD1;
}
else if (SEqual(CurrTokenIdtf, C4MC_Point) && !pToNode->GetNodeByName(CurrTokenIdtf))
@ -1138,7 +1142,7 @@ void C4MCParser::ParseTo(C4MCNode *pToNode)
if (!pToNode->Type() == MCN_Overlay)
throw C4MCParserErr(this, C4MCErr_PointOnlyOvl);
// create point node, using default template
pNewNode = new C4MCPoint(pToNode, MapCreator->DefaultPoint, false);
pNewNode = new C4MCPoint(this, pToNode, MapCreator->DefaultPoint, false);
State=PS_KEYWD1;
}
else if (SEqual(CurrTokenIdtf, C4MC_Map))
@ -1147,7 +1151,7 @@ void C4MCParser::ParseTo(C4MCNode *pToNode)
if (!pToNode->GlobalScope())
throw C4MCParserErr(this, C4MCErr_MapNoGlobal);
// create map node, using default template
pNewNode = new C4MCMap(pToNode, MapCreator->DefaultMap, false);
pNewNode = new C4MCMap(this, pToNode, MapCreator->DefaultMap, false);
State=PS_KEYWD1;
}
else
@ -1229,7 +1233,7 @@ void C4MCParser::ParseTo(C4MCNode *pToNode)
{
case MCN_Overlay:
// create overlay
pNewNode=new C4MCOverlay(pToNode, *((C4MCOverlay *) pCpyNode), false);
pNewNode=new C4MCOverlay(this, pToNode, *((C4MCOverlay *) pCpyNode), false);
break;
case MCN_Map:
// maps not allowed

View File

@ -63,6 +63,7 @@
#define C4MCErr_AlgoNotFound "algorithm '%s' not found"
#define C4MCErr_SFuncNotFound "script func '%s' not found in scenario script"
#define C4MCErr_PointOnlyOvl "point only allowed in overlays"
#define C4MCErr_NoRecTemplate "cannot use template '%s' within itself"
// predef
class C4MCCallbackArray;
@ -156,10 +157,10 @@ public:
public:
C4MCNode(C4MCNode *pOwner=NULL); // constructor
C4MCNode(C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone); // constructor using template
C4MCNode(C4MCParser* pParser, C4MCNode *pOwner, C4MCNode &rTemplate, bool fClone); // constructor using template
virtual ~C4MCNode(); // destructor
virtual C4MCNode *clone(C4MCNode *pToNode) { return new C4MCNode(pToNode, *this, true); }
virtual C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCNode(pParser, pToNode, *this, true); }
void Clear(); // clear all child nodes
void Reg2Owner(C4MCNode *pOwner); // register into list
@ -201,9 +202,9 @@ class C4MCOverlay : public C4MCNode
{
public:
C4MCOverlay(C4MCNode *pOwner=NULL); // constructor
C4MCOverlay(C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone); // construct of template
C4MCOverlay(C4MCParser* pParser, C4MCNode *pOwner, C4MCOverlay &rTemplate, bool fClone); // construct of template
C4MCNode *clone(C4MCNode *pToNode) { return new C4MCOverlay(pToNode, *this, true); }
C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCOverlay(pParser, pToNode, *this, true); }
protected:
void Default(); // set default values for default presets
@ -254,9 +255,9 @@ class C4MCPoint : public C4MCNode
{
public:
C4MCPoint(C4MCNode *pOwner=NULL); // constructor
C4MCPoint(C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone); // construct of template
C4MCPoint(C4MCParser* pParser, C4MCNode *pOwner, C4MCPoint &rTemplate, bool fClone); // construct of template
C4MCNode *clone(C4MCNode *pToNode) { return new C4MCPoint(pToNode, *this, true); }
C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCPoint(pParser, pToNode, *this, true); }
protected:
void Default(); // set default values for default presets
@ -280,9 +281,9 @@ class C4MCMap : public C4MCOverlay
{
public:
C4MCMap(C4MCNode *pOwner=NULL); // constructor
C4MCMap(C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone); // construct of template
C4MCMap(C4MCParser* pParser, C4MCNode *pOwner, C4MCMap &rTemplate, bool fClone); // construct of template
C4MCNode *clone(C4MCNode *pToNode) { return new C4MCMap(pToNode, *this, true); }
C4MCNode *clone(C4MCParser* pParser, C4MCNode *pToNode) { return new C4MCMap(pParser, pToNode, *this, true); }
protected:
void Default(); // set default values for default presets