Script: Initial proplists are readonly at runtime

That way, recreating them from game data during savegame load won't
suddenly revert changes, because there aren't any changes.
floating-point
Günther Brammer 2010-09-08 14:54:39 +02:00
parent 1a3f8fe80b
commit bf9137149c
7 changed files with 21 additions and 3 deletions

View File

@ -1432,6 +1432,7 @@ void C4DefList::CallEveryDefinition()
{
C4AulParSet Pars(C4VPropList(it->second));
it->second->Script.Call(PSF_Definition, 0, &Pars, true);
it->second->Freeze();
}
}

View File

@ -1021,6 +1021,8 @@ static C4Value FnSetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value
if (!pObj) return C4VFalse;
C4String * key = key_C4V->_getStr();
if (!key) return C4VFalse;
if (pObj->IsFrozen())
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
pObj->SetProperty(key, *to);
return C4VTrue;
}

View File

@ -141,10 +141,12 @@ typedef ptrdiff_t ssize_t;
#define GNUC_FORMAT_ATTRIBUTE __attribute__ ((format (printf, 1, 2)))
#define GNUC_FORMAT_ATTRIBUTE_O __attribute__ ((format (printf, 2, 3)))
#define ALWAYS_INLINE inline __attribute__ ((always_inline))
#define NORETURN __attribute__ ((noreturn))
#else
#define GNUC_FORMAT_ATTRIBUTE
#define GNUC_FORMAT_ATTRIBUTE_O
#define ALWAYS_INLINE __forceinline
#define NORETURN
#endif

View File

@ -247,6 +247,8 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
C4Value *pPropList = pCurVal - 1;
if (!(pPropList->ConvertTo(C4V_PropList) && pPropList->_getPropList()))
throw new C4AulExecError(pCurCtx->Obj, FormatString("proplist write: proplist expected, got %s", pPropList->GetTypeName()).getData());
if (pPropList->_getPropList()->IsFrozen())
throw new C4AulExecError(pCurCtx->Obj, "proplist write: proplist is readonly");
pPropList->_getPropList()->SetProperty(pCPos->Par.s, pCurVal[0]);
pPropList->Set(pCurVal[0]);
PopValue();
@ -492,6 +494,8 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
{
assert(pStruct->GetType() == C4V_PropList || pStruct->GetType() == C4V_C4Object);
C4PropList *pPropList = pStruct->_getPropList();
if (pPropList->IsFrozen())
throw new C4AulExecError(pCurCtx->Obj, "proplist write: proplist is readonly");
pPropList->SetProperty(pIndex->_getStr(), *pValue);
}
// Set result, remove array and index from stack

View File

@ -175,7 +175,7 @@ public:
void Shift(HoldStringsPolicy HoldStrings = Hold, bool bOperator = true);
void Match(C4AulTokenType TokenType, const char * Message = NULL);
void UnexpectedToken(const char * Expected);
void UnexpectedToken(const char * Expected) NORETURN;
const char * GetTokenName(C4AulTokenType TokenType);
void Warn(const char *pMsg, const char *pIdtf=0);
@ -3003,6 +3003,7 @@ C4Value C4AulParseState::Parse_ConstExpression()
else if (TokenType != ATT_BLCLOSE)
UnexpectedToken("'}' or ','");
}
r._getPropList()->Freeze();
break;
}
default:

View File

@ -97,7 +97,7 @@ C4PropListNumbered::~C4PropListNumbered()
C4PropList::C4PropList(C4PropList * prototype):
Status(1),
FirstRef(NULL), prototype(prototype)
FirstRef(NULL), prototype(prototype), constant(false)
{
if (prototype)
SetProperty(Strings.P[P_Prototype], C4VPropList(prototype));
@ -318,6 +318,7 @@ int32_t C4PropList::GetPropertyInt(C4PropertyName n)
void C4PropList::SetProperty(C4String * k, const C4Value & to)
{
assert(!constant);
assert(Strings.Set.Has(k));
if (k == Strings.P[P_Prototype] && to.GetType() == C4V_PropList)
{

View File

@ -63,10 +63,17 @@ public:
bool GetPropertyVal(C4PropertyName k, C4Value *pResult) { return GetPropertyVal(Strings.P[k], pResult); }
C4String * GetPropertyStr(C4PropertyName k);
int32_t GetPropertyInt(C4PropertyName k);
// not allowed on frozen proplists
void SetProperty(C4String * k, const C4Value & to);
void ResetProperty(C4String * k);
static C4PropList * New(C4PropList * prototype = 0);
static C4PropList * NewAnon(C4PropList * prototype = 0);
// only freeze proplists which are not going to be modified
void Freeze() { constant = true; }
bool IsFrozen() { return constant; }
virtual void DenumeratePointers();
virtual ~C4PropList();
@ -79,7 +86,7 @@ protected:
private:
C4Value *FirstRef; // No-Save
bool constant; // if true, this proplist is neither saved nor changeable FIXME: implement
bool constant; // if true, this proplist is not changeable
C4PropList * prototype;
friend void CompileNewFunc<C4PropList>(C4PropList *&pStruct, StdCompiler *pComp);