stable-5.2
Tobias Zwick 2009-07-23 22:20:07 +02:00
commit f56e4e3dd5
7 changed files with 100 additions and 375 deletions

View File

@ -163,17 +163,13 @@ enum C4AulBCCType
AB_LessThanEqual, // <=
AB_GreaterThan, // >
AB_GreaterThanEqual, // >=
AB_EqualIdent, // old ==
AB_Equal, // new ==
AB_NotEqualIdent, // old !=
AB_NotEqual, // new !=
AB_Equal, // ==
AB_NotEqual, // !=
AB_SEqual, // S=, eq
AB_SNEqual, // ne
AB_BitAnd, // &
AB_BitXOr, // ^
AB_BitOr, // |
AB_And, // &&
AB_Or, // ||
AB_MulIt, // *=
AB_DivIt, // /=
AB_ModIt, // %=
@ -326,7 +322,6 @@ class C4AulScriptFunc : public C4AulFunc
C4ValueMapNames VarNamed; // list of named vars in this function
C4ValueMapNames ParNamed; // list of named pars in this function
C4V_Type ParType[C4AUL_MAX_Par]; // parameter types
bool bNewFormat; // new func format? [ func xyz(par abc) { ... } ]
bool bReturnRef; // return reference
C4AulScript *pOrgScript; // the orginal script (!= Owner if included or appended)

View File

@ -1,3 +1,21 @@
/*
* Copyright (c) 2009 Günther Brammer <gbrammer@gmx.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* "Clonk" is a registered trademark of Matthes Bender.
*/
/* Property lists */
#ifndef C4PROPLIST_H

View File

@ -173,7 +173,7 @@ void C4AulScript::Default()
IncludesResolved = false;
// defaults
Strict = NONSTRICT;
Strict = MAXSTRICT;
Preparsing=Resolving=false;
Temporary = false;
LocalNamed.Reset();
@ -390,7 +390,6 @@ void C4AulScriptFunc::CopyBody(C4AulScriptFunc &FromFunc)
Script = FromFunc.Script;
VarNamed = FromFunc.VarNamed;
ParNamed = FromFunc.ParNamed;
bNewFormat = FromFunc.bNewFormat;
bReturnRef = FromFunc.bReturnRef;
pOrgScript = FromFunc.pOrgScript;
for(int i = 0; i < C4AUL_MAX_Par; i++)

View File

@ -534,15 +534,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
PopValue();
break;
}
case AB_EqualIdent: // old ==
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
pPar1->SetBool(pPar1->_getRaw() == pPar2->_getRaw());
PopValue();
break;
}
case AB_Equal: // new ==
case AB_Equal: // ==
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
@ -550,15 +542,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
PopValue();
break;
}
case AB_NotEqualIdent: // old !=
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
pPar1->SetBool(pPar1->_getRaw() != pPar2->_getRaw());
PopValue();
break;
}
case AB_NotEqual: // new !=
case AB_NotEqual: // !=
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
@ -608,22 +592,6 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
PopValue();
break;
}
case AB_And: // &&
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
pPar1->SetBool(pPar1->_getRaw() && pPar2->_getRaw());
PopValue();
break;
}
case AB_Or: // ||
{
CheckOpPars(pCPos->Par.i);
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
pPar1->SetBool(pPar1->_getRaw() || pPar2->_getRaw());
PopValue();
break;
}
case AB_MulIt: // *=
{
CheckOpPars(pCPos->Par.i);

View File

@ -172,8 +172,7 @@ class C4AulParseState
const char * GetTokenName(C4AulTokenType TokenType);
void Warn(const char *pMsg, const char *pIdtf=0);
void StrictError(const char *pMsg, const char *pIdtf=0);
void Strict2Error(const char *pMsg, const char *pIdtf=0);
void Error(const char *pMsg, const char *pIdtf=0);
private:
@ -236,19 +235,9 @@ void C4AulParseState::Warn(const char *pMsg, const char *pIdtf)
++::ScriptEngine.warnCnt;
}
void C4AulParseState::StrictError(const char *pMsg, const char *pIdtf)
void C4AulParseState::Error(const char *pMsg, const char *pIdtf)
{
if (Fn ? (Fn->pOrgScript->Strict < C4AulScript::STRICT1) : (a->Strict < C4AulScript::STRICT1))
Warn(pMsg, pIdtf);
else
throw new C4AulParseError(this, pMsg, pIdtf);
}
void C4AulParseState::Strict2Error(const char *pMsg, const char *pIdtf)
{
if (Fn ? (Fn->pOrgScript->Strict < C4AulScript::STRICT2) : (a->Strict < C4AulScript::STRICT2))
Warn(pMsg, pIdtf);
else
throw new C4AulParseError(this, pMsg, pIdtf);
throw new C4AulParseError(this, pMsg, pIdtf);
}
C4AulParseError::C4AulParseError(C4AulParseState * state, const char *pMsg, const char *pIdtf, BOOL Warn)
@ -457,8 +446,8 @@ C4ScriptOpDef C4ScriptOpMap[] = {
{ 8, "&", AB_BitAnd, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "^", AB_BitXOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 6, "|", AB_BitOr, 1, 0, 0, C4V_Int, C4V_Int, C4V_Int},
{ 5, "&&", AB_And, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 4, "||", AB_Or, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 5, "&&", AB_JUMPAND, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 4, "||", AB_JUMPOR, 1, 0, 0, C4V_Bool, C4V_Bool, C4V_Bool},
{ 2, "*=", AB_MulIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
{ 2, "/=", AB_DivIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
{ 2, "%=", AB_ModIt, 1, 1, 0, C4V_Any, C4V_pC4Value, C4V_Int},
@ -481,20 +470,11 @@ int C4AulParseState::GetOperator(const char* pScript)
unsigned int i;
if(!*pScript) return 0;
// text with > 2 characters or text and #strict 2?
// then break (may be misinterpreted as operator
// operators are not alphabetical
if((*pScript >= 'a' && *pScript <= 'z') ||
(*pScript >= 'A' && *pScript <= 'Z'))
{
if(Fn ? (Fn->pOrgScript->Strict >= C4AulScript::STRICT2) : (a->Strict >= C4AulScript::STRICT2))
return -1;
if((*(pScript+1) >= 'a' && *(pScript+1) <= 'z') ||
(*(pScript+1) >= 'A' && *(pScript+1) <= 'Z'))
if((*(pScript+2) >= 'a' && *(pScript+2) <= 'z') ||
(*(pScript+2) >= 'A' && *(pScript+2) <= 'Z') ||
(*(pScript+2) >= '0' && *(pScript+2) <= '9') ||
*(pScript+2) == '_')
return -1;
return -1;
}
// it is a two-char-operator?
@ -646,14 +626,8 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
// identifier by all non-special chars
if (C >= '@')
{
// Old Scripts could have wacky identifier
if (a->Strict < C4AulScript::STRICT2)
{
State = TGS_Ident;
break;
}
// But now only the alphabet and '_' is allowed
else if ((C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || (C == '_'))
// only the alphabet and '_' is allowed
if ((C >= 'A' && C <= 'Z') || (C >= 'a' && C <= 'z') || (C == '_'))
{
State = TGS_Ident;
break;
@ -757,12 +731,6 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
// return integer
Len = Min(Len, C4AUL_MAX_Identifier);
SCopy(SPos0, pToken, Len);
// or is it a func label?
if ((C == '(') || (C == ':'))
{
Strict2Error("stupid func label: ", pToken);
return ATT_IDTF;
}
// do not parse 0x prefix for hex
if (State == TGS_IntHex) pToken += 2;
// it's not, so return the int
@ -779,12 +747,6 @@ C4AulTokenType C4AulParseState::GetNextToken(char *pToken, long int *pInt, HoldS
// return C4ID string
Len = Min(Len, C4AUL_MAX_Identifier);
SCopy(SPos0, pToken, Len);
// another stupid label identifier?
if ((C == '(') || (C == ':' && *(SPos+1) != ':'))
{
Strict2Error("stupid func label: ", pToken);
return ATT_IDTF;
}
// check if valid
if (!LooksLikeID(pToken)) throw new C4AulParseError(this, "erroneous Ident: ", pToken);
// get id of it
@ -886,17 +848,13 @@ static const char * GetTTName(C4AulBCCType e)
case AB_LessThanEqual: return "LessThanEqual"; // <=
case AB_GreaterThan: return "GreaterThan"; // >
case AB_GreaterThanEqual: return "GreaterThanEqual"; // >=
case AB_EqualIdent: return "EqualIdent"; // old ==
case AB_Equal: return "Equal"; // new ==
case AB_NotEqualIdent: return "NotEqualIdent"; // old !=
case AB_NotEqual: return "NotEqual"; // new !=
case AB_Equal: return "Equal"; // ==
case AB_NotEqual: return "NotEqual"; // !=
case AB_SEqual: return "SEqual"; // S=, eq
case AB_SNEqual: return "SNEqual"; // ne
case AB_BitAnd: return "BitAnd"; // &
case AB_BitXOr: return "BitXOr"; // ^
case AB_BitOr: return "BitOr"; // |
case AB_And: return "And"; // &&
case AB_Or: return "Or"; // ||
case AB_MulIt: return "MulIt"; // *=
case AB_DivIt: return "DivIt"; // /=
case AB_ModIt: return "ModIt"; // %=
@ -1005,7 +963,7 @@ BOOL C4AulScript::Preparse()
state.Parse_Script();
// no #strict? we don't like that :(
if (!Strict)
if (Strict < MAXSTRICT)
{
Engine->nonStrictCnt++;
}
@ -1057,16 +1015,12 @@ void C4AulParseState::AddBCC(C4AulBCCType eType, intptr_t X)
case AB_GreaterThan:
case AB_GreaterThanEqual:
case AB_Equal:
case AB_EqualIdent:
case AB_NotEqual:
case AB_NotEqualIdent:
case AB_SEqual:
case AB_SNEqual:
case AB_BitAnd:
case AB_BitXOr:
case AB_BitOr:
case AB_And:
case AB_Or:
case AB_MulIt:
case AB_DivIt:
case AB_ModIt:
@ -1526,7 +1480,7 @@ void C4AulParseState::Parse_FuncHead()
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
throw new C4AulParseError(this, "function definition: name already in use (global variable)");
if (a->Engine->GlobalConstNames.GetItemNr(Idtf) != -1)
Strict2Error("function definition: name already in use (global variable)", 0);
Error("function definition: name already in use (global constant)", 0);
}
// create script fn
if (Acc == AA_GLOBAL)
@ -1545,7 +1499,7 @@ void C4AulParseState::Parse_FuncHead()
// set up func (in the case we got an error)
Fn->Script = SPos; // temporary
Fn->Access = Acc; Fn->pOrgScript = a;
Fn->bNewFormat = true; Fn->bReturnRef = bReturnRef;
Fn->bReturnRef = bReturnRef;
Shift(Discard,false);
// expect an opening bracket now
if (TokenType != ATT_BOPEN)
@ -1572,11 +1526,6 @@ void C4AulParseState::Parse_FuncHead()
{
UnexpectedToken("parameter or closing bracket");
}
char TypeIdtf[C4AUL_MAX_Identifier] = ""; // current identifier
if (TokenType == ATT_IDTF)
{
SCopy(Idtf, TypeIdtf);
}
// type identifier?
if (SEqual(Idtf, C4AUL_TypeInt)) { Fn->ParType[cpar] = C4V_Int; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeBool)) { Fn->ParType[cpar] = C4V_Bool; Shift(Discard,false); }
@ -1589,12 +1538,7 @@ void C4AulParseState::Parse_FuncHead()
if (TokenType == ATT_AMP) { Fn->ParType[cpar] = C4V_pC4Value; Shift(Discard,false); }
if (TokenType != ATT_IDTF)
{
if (SEqual(TypeIdtf,""))
UnexpectedToken("parameter or closing bracket");
// A parameter with the same name as a type
Strict2Error("parameter has the same name as type ", TypeIdtf);
Fn->ParType[cpar] = C4V_Any;
Fn->ParNamed.AddName(TypeIdtf);
UnexpectedToken("parameter name");
}
else
{
@ -1614,132 +1558,14 @@ void C4AulParseState::Parse_FuncHead()
Shift(Discard,false);
cpar++;
}
// ok, expect opening block
if(TokenType != ATT_BLOPEN)
{
// warn
Strict2Error("'func': expecting opening block ('{') after func declaration", 0);
// not really new syntax (a sort of legacy mode)
Fn->bNewFormat = false;
}
else
{
Fn->Script = SPos;
Shift();
}
Fn->Script = SPos;
Match(ATT_BLOPEN);
Parse_Desc();
Parse_Function();
Match(ATT_BLCLOSE);
return;
}
// Must be old-style function declaration now
if (a->Strict >= C4AulScript::STRICT2)
throw new C4AulParseError(this, "Declaration expected, but found identifier ", Idtf);
// check: symbol already in use?
switch(Acc)
{
case AA_PRIVATE:
case AA_PROTECTED:
case AA_PUBLIC:
if(a->LocalNamed.GetItemNr(Idtf) != -1)
throw new C4AulParseError(this, "function definition: name already in use (local variable)");
if(a->Def)
break;
// func in global context: fallthru
case AA_GLOBAL:
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
throw new C4AulParseError(this, "function definition: name already in use (global variable)");
}
char FuncIdtf[C4AUL_MAX_Identifier] = ""; // current identifier
SCopy(Idtf, FuncIdtf);
Shift();
if (TokenType != ATT_COLON)
throw new C4AulParseError(this, FormatString("declaration expected, but found identifier '%s'", FuncIdtf).getData());
// create script fn
if (Acc == AA_GLOBAL)
{
// global func
Fn = new C4AulScriptFunc(a->Engine, FuncIdtf);
C4AulFunc *FnLink = new C4AulFunc(a, NULL);
FnLink->LinkedTo = Fn; Fn->LinkedTo = FnLink;
Acc = AA_PUBLIC;
}
else
{
// normal, local func
Fn = new C4AulScriptFunc(a, FuncIdtf);
}
Fn->Script = SPos;
Fn->Access = Acc;
Fn->pOrgScript = a;
Fn->bNewFormat = false;
Fn->bReturnRef = false;
Shift();
Parse_Desc();
const char * SPos0 = SPos;
while(1) switch(TokenType)
{
// end of function
case ATT_EOF: case ATT_DIR: return;
case ATT_IDTF:
{
// check for func declaration
if (SEqual(Idtf, C4AUL_Private)) return;
else if (SEqual(Idtf, C4AUL_Protected)) return;
else if (SEqual(Idtf, C4AUL_Public)) return;
else if (SEqual(Idtf, C4AUL_Global)) return;
else if (SEqual(Idtf, C4AUL_Func)) return;
// check for variable definition (var)
else if(SEqual(Idtf, C4AUL_VarNamed))
{
Shift();
Parse_Var();
}
// check for variable definition (local)
else if(SEqual(Idtf, C4AUL_LocalNamed))
{
if(a->Def)
{
Shift();
Parse_Local();
}
else
throw new C4AulParseError(this, "'local' variable declaration in global script");
}
// check for variable definition (static)
else if(SEqual(Idtf, C4AUL_GlobalNamed))
{
Shift();
Parse_Static();
}
// might be old style declaration
else
{
const char * SPos0_ = SPos;
Shift();
if (TokenType == ATT_COLON)
{
// Reset source position to the point before the label
SPos = SPos0;
Shift();
return;
}
else
{
// The current token might be a label
// In that case the next round of the loop will need to reset the position to what's in SPos0_ now
SPos0 = SPos0_;
}
}
break;
}
default:
{
SPos0 = SPos;
Shift();
break;
}
}
throw new C4AulParseError(this, "Declaration expected, but found identifier ", Idtf);
}
void C4AulParseState::Parse_Desc()
@ -1785,23 +1611,18 @@ void C4AulParseState::Parse_Function()
// a block end?
case ATT_BLCLOSE:
{
// new-form func?
if(Fn->bNewFormat)
// all ok, insert a return
C4AulBCC * CPos = a->GetCodeByPos(Max(a->GetCodePos() - 1,0));
if (!CPos || CPos->bccType != AB_RETURN || fJump)
{
// all ok, insert a return
C4AulBCC * CPos = a->GetCodeByPos(Max(a->GetCodePos() - 1,0));
if (!CPos || CPos->bccType != AB_RETURN || fJump)
{
AddBCC(AB_INT);
AddBCC(AB_RETURN);
}
// and break
Done = TRUE;
// Do not blame this function for script errors between functions
Fn = 0;
return;
AddBCC(AB_NIL);
AddBCC(AB_RETURN);
}
throw new C4AulParseError(this, "no '{' found for '}'");
// and break
Done = TRUE;
// Do not blame this function for script errors between functions
Fn = 0;
return;
}
case ATT_EOF:
{
@ -1967,23 +1788,11 @@ void C4AulParseState::Parse_Statement()
}
else if (SEqual(Idtf, C4AUL_Return)) // return
{
bool multi_params_hack = false;
Shift();
if (TokenType == ATT_BOPEN && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
if(TokenType == ATT_SCOLON)
{
// parse return(retvals) - return(retval, unused, parameters, ...) allowed for backwards compatibility
if (Parse_Params(1, NULL) == 1)
{
// return (1 + 1) * 3 returns 6, not 2
Parse_Expression2();
}
else
multi_params_hack = true;
}
else if(TokenType == ATT_SCOLON)
{
// allow return; without return value (implies 0)
AddBCC(AB_INT);
// allow return; without return value (implies nil)
AddBCC(AB_NIL);
}
else
{
@ -1993,15 +1802,6 @@ void C4AulParseState::Parse_Statement()
if(!Fn->bReturnRef)
SetNoRef();
AddBCC(AB_RETURN);
if (multi_params_hack && TokenType != ATT_SCOLON)
{
// return (1, 1) * 3 returns 1
// but warn about it, the * 3 won't get executed and a stray ',' could lead to unexpected results
Warn("';' expected, but found ", GetTokenName(TokenType));
AddBCC(AB_STACK, +1);
Parse_Expression2();
AddBCC(AB_STACK, -1);
}
}
else if (SEqual(Idtf, C4AUL_this)) // this on top level
{
@ -2017,7 +1817,7 @@ void C4AulParseState::Parse_Statement()
// Must be inside a loop
if(!pLoopStack)
{
Strict2Error("'break' is only allowed inside loops");
Error("'break' is only allowed inside loops");
}
else
{
@ -2037,7 +1837,7 @@ void C4AulParseState::Parse_Statement()
// Must be inside a loop
if(!pLoopStack)
{
Strict2Error("'continue' is only allowed inside loops");
Error("'continue' is only allowed inside loops");
}
else
{
@ -2093,23 +1893,14 @@ void C4AulParseState::Parse_Statement()
}
else
{
bool gotohack = false;
// none of these? then it's a function
// if it's a label, it will be missinterpreted here, which will be corrected later
// it may be the first goto() found? (old syntax only!)
if (SEqual(Idtf, C4AUL_Goto) && !Fn->pOrgScript->Strict)
// add AB_RETURN later on
gotohack=true;
C4AulFunc *FoundFn;
// old syntax: do not allow recursive calls in overloaded functions
if (!Fn->pOrgScript->Strict && Fn->OwnerOverloaded && SEqual(Idtf, Fn->Name))
FoundFn = Fn->OwnerOverloaded;
// get regular function
if(Fn->Owner == &::ScriptEngine)
FoundFn = a->Owner->GetFuncRecursive(Idtf);
else
// get regular function
if(Fn->Owner == &::ScriptEngine)
FoundFn = a->Owner->GetFuncRecursive(Idtf);
else
FoundFn = a->GetFuncRecursive(Idtf);
FoundFn = a->GetFuncRecursive(Idtf);
// ignore func-not-found errors in the preparser, because the function tables are not built yet
if (!FoundFn && Type == PARSER)
{
@ -2138,11 +1929,6 @@ void C4AulParseState::Parse_Statement()
if (TokenType == ATT_BOPEN || Type == PARSER)
Parse_Params(FoundFn ? FoundFn->GetParCount() : 10, FoundFn ? FoundFn->Name : Idtf, FoundFn);
AddBCC(AB_FUNC, (long) FoundFn);
if (gotohack)
{
AddBCC(AB_RETURN);
AddBCC(AB_STACK, +1);
}
Parse_Expression2();
SetNoRef();
AddBCC(AB_STACK, -1);
@ -2352,14 +2138,9 @@ void C4AulParseState::Parse_While()
// Save position for later jump back
int iStart = JumpHere();
// Execute condition
if (Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
{
Match(ATT_BOPEN);
Parse_Expression();
Match(ATT_BCLOSE);
}
else
Parse_Params(1, C4AUL_While);
Match(ATT_BOPEN);
Parse_Expression();
Match(ATT_BCLOSE);
SetNoRef();
// Check condition
int iCond = a->GetCodePos();
@ -2384,14 +2165,9 @@ void C4AulParseState::Parse_While()
void C4AulParseState::Parse_If()
{
if (Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
{
Match(ATT_BOPEN);
Parse_Expression();
Match(ATT_BCLOSE);
}
else
Parse_Params(1, C4AUL_If);
Match(ATT_BOPEN);
Parse_Expression();
Match(ATT_BCLOSE);
SetNoRef();
// create bytecode, remember position
int iCond = a->GetCodePos();
@ -2599,12 +2375,7 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
throw new C4AulParseError(this, "'for' may not be used as a parameter");
else if (SEqual(Idtf, C4AUL_Return))
{
// return: treat as regular function with special byte code
Strict2Error("return used as a parameter", 0);
Shift();
Parse_Params(1, NULL);
AddBCC(AB_RETURN);
AddBCC(AB_STACK, +1);
Error("return may not be used as a parameter", 0);
}
else if (SEqual(Idtf, C4AUL_Par))
{
@ -2616,8 +2387,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
else if (SEqual(Idtf, C4AUL_Inherited) || SEqual(Idtf, C4AUL_SafeInherited))
{
Shift();
// inherited keyword: check strict syntax
if (!Fn->pOrgScript->Strict) throw new C4AulParseError(this, "inherited disabled; use #strict syntax!");
// get function
if (Fn->OwnerOverloaded)
{
@ -2628,7 +2397,7 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
else
// not found? raise an error, if it's not a safe call
if (SEqual(Idtf, C4AUL_Inherited) && Type == PARSER)
throw new C4AulParseError(this, "inherited function not found, use _inherited to call failsafe");
throw new C4AulParseError(this, "inherited function not found (use _inherited to disable this message)");
else
{
// otherwise, parse parameters, but discard them
@ -2637,13 +2406,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
AddBCC(AB_STACK, 1);
}
}
else if (!Fn->pOrgScript->Strict && Fn->OwnerOverloaded && SEqual(Idtf, Fn->Name))
{
// old syntax: do not allow recursive calls in overloaded functions
Shift();
Parse_Params(Fn->OwnerOverloaded->GetParCount(), Fn->Name, Fn);
AddBCC(AB_FUNC, (long) Fn->OwnerOverloaded);
}
else
{
C4AulFunc *FoundFn;
@ -2701,14 +2463,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
}
}
Shift();
// now let's check whether it used old- or new-style
if (TokenType == ATT_BOPEN && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
{
// old-style usage: ignore function call
// must not use parameters here (although generating the byte code for that would be possible)
Shift();
Match(ATT_BCLOSE, "parameters not allowed in functional usage of constants");
}
}
else
{
@ -2785,9 +2539,6 @@ void C4AulParseState::Parse_Expression(int iParentPrio)
}
case ATT_BOPEN2:
{
// Arrays are not tested in non-strict mode at all
if(!Fn->pOrgScript->Strict)
throw new C4AulParseError(this, "unexpected '['");
Parse_Array();
break;
}
@ -2840,12 +2591,12 @@ void C4AulParseState::Parse_Expression2(int iParentPrio)
SetNoRef();
Shift();
if ((C4ScriptOpMap[OpID].Code == AB_And || C4ScriptOpMap[OpID].Code == AB_Or) && Fn->pOrgScript->Strict >= C4AulScript::STRICT2)
if (C4ScriptOpMap[OpID].Code == AB_JUMPAND || C4ScriptOpMap[OpID].Code == AB_JUMPOR)
{
// create bytecode, remember position
int iCond = a->GetCodePos();
// Jump or discard first parameter
AddBCC(C4ScriptOpMap[OpID].Code == AB_And ? AB_JUMPAND : AB_JUMPOR);
AddBCC(C4ScriptOpMap[OpID].Code);
// parse second expression
Parse_Expression(C4ScriptOpMap[OpID].Priority);
// set condition jump target
@ -2857,38 +2608,18 @@ void C4AulParseState::Parse_Expression2(int iParentPrio)
// expect second parameter for operator
if(!C4ScriptOpMap[OpID].NoSecondStatement)
{
switch (TokenType)
{
case ATT_IDTF: case ATT_INT: case ATT_BOOL: case ATT_STRING: case ATT_C4ID: case ATT_NIL:
case ATT_OPERATOR: case ATT_BOPEN: case ATT_BOPEN2:
Parse_Expression(C4ScriptOpMap[OpID].Priority);
// If the operator does not modify the second argument, no reference is necessary
if(C4ScriptOpMap[OpID].Type2 != C4V_pC4Value)
SetNoRef();
break;
default:
// Stuff like foo(42+,1) used to silently work
Strict2Error(FormatString("Operator %s: Second expression expected, but %s found",
C4ScriptOpMap[OpID].Identifier, GetTokenName(TokenType)).getData(), NULL);
AddBCC(AB_INT, 0);
break;
}
Parse_Expression(C4ScriptOpMap[OpID].Priority);
// If the operator does not modify the second argument, no reference is necessary
if(C4ScriptOpMap[OpID].Type2 != C4V_pC4Value)
SetNoRef();
}
// write byte code, with a few backward compat changes
if (C4ScriptOpMap[OpID].Code == AB_Equal && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
AddBCC(AB_EqualIdent, OpID);
else if (C4ScriptOpMap[OpID].Code == AB_NotEqual && Fn->pOrgScript->Strict < C4AulScript::STRICT2)
AddBCC(AB_NotEqualIdent, OpID);
else
AddBCC(C4ScriptOpMap[OpID].Code, OpID);
// write byte code
AddBCC(C4ScriptOpMap[OpID].Code, OpID);
}
break;
}
case ATT_BOPEN2:
{
// Arrays are not tested in non-strict mode at all
if(!Fn->pOrgScript->Strict)
throw new C4AulParseError(this, "unexpected '['");
// Access the array
Shift();
Parse_Expression();
@ -3073,10 +2804,10 @@ void C4AulParseState::Parse_Static()
UnexpectedToken("variable name");
// global variable definition
// check: symbol already in use?
if(a->Engine->GetFuncRecursive(Idtf)) throw new C4AulParseError(this, "variable definition: name already in use");
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Strict2Error("constant and variable with name ", Idtf);
if (a->Engine->GetFuncRecursive(Idtf)) Error("function and variable with name ", Idtf);
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Error("constant and variable with name ", Idtf);
// insert variable if not defined already
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) == -1)
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) == -1)
a->Engine->GlobalNamedNames.AddName(Idtf);
}
Match(ATT_IDTF);
@ -3113,9 +2844,9 @@ void C4AulParseState::Parse_Const()
// (e.g., for overloading constants such as OCF_Living() in chaos scenarios)
// it is not encouraged though, so better warn
if(a->Engine->GetFuncRecursive(Idtf))
Strict2Error("definition of constant hidden by function ", Idtf);
Error("definition of constant hidden by function ", Idtf);
if(a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
Strict2Error("constant and variable with name ", Idtf);
Error("constant and variable with name ", Idtf);
Match(ATT_IDTF);
// expect '='
if (TokenType != ATT_OPERATOR || !SEqual(C4ScriptOpMap[cInt].Identifier,"="))
@ -3309,7 +3040,7 @@ void C4AulScript::ParseDescs()
C4AulScript *C4AulScript::FindFirstNonStrictScript()
{
// self is not #strict?
if (Script && !Strict) return this;
if (Script && Strict < MAXSTRICT) return this;
// search children
C4AulScript *pNonStrScr;
for (C4AulScript *pScr=Child0; pScr; pScr=pScr->Next)

View File

@ -1,3 +1,21 @@
/*
* Copyright (c) 2009 Günther Brammer <gbrammer@gmx.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* "Clonk" is a registered trademark of Matthes Bender.
*/
#include <C4Include.h>
#include <C4PropList.h>
#include <C4GameObjects.h>

View File

@ -1911,8 +1911,6 @@ static C4Object *FnCreateObject(C4AulContext *cthr,
{
iXOffset+=cthr->Obj->GetX();
iYOffset+=cthr->Obj->GetY();
if (!cthr->Caller || !cthr->Caller->Func->Owner->Strict)
iOwner=cthr->Obj->Owner;
}
C4Object *pNewObj = Game.CreateObject(PropList,cthr->Obj,iOwner,iXOffset,iYOffset);
@ -1932,8 +1930,6 @@ static C4Object *FnCreateConstruction(C4AulContext *cthr,
{
iXOffset+=cthr->Obj->GetX();
iYOffset+=cthr->Obj->GetY();
if (!cthr->Caller || !cthr->Caller->Func->Owner->Strict)
iOwner=cthr->Obj->Owner;
}
// Check site