Merge branch 'development' into style-cleanup

Conflicts:
	Engine/source/console/astNodes.cpp
	Engine/source/console/codeBlock.cpp
	Engine/source/console/compiledEval.cpp
	Engine/source/ts/collada/colladaAppMesh.cpp
	Engine/source/ts/tsShape.cpp
	Engine/source/ts/tsShapeConstruct.cpp
This commit is contained in:
Daniel Buckmaster 2014-12-15 12:15:55 +11:00
commit 33ff180593
2053 changed files with 172002 additions and 69530 deletions

View file

@ -45,6 +45,9 @@
#include "materials/materialManager.h"
#endif
// Uncomment to optimize function calls at the expense of potential invalid package lookups
//#define COMPILER_OPTIMIZE_FUNCTION_CALLS
using namespace Compiler;
enum EvalConstants {
@ -102,7 +105,11 @@ IterStackRecord iterStack[ MaxStackSize ];
F64 floatStack[MaxStackSize];
S64 intStack[MaxStackSize];
StringStack STR;
ConsoleValueStack CSTK;
U32 _FLT = 0; ///< Stack pointer for floatStack.
U32 _UINT = 0; ///< Stack pointer for intStack.
@ -188,18 +195,16 @@ namespace Con
return STR.getArgBuffer(bufferSize);
}
char *getFloatArg(F64 arg)
ConsoleValueRef getFloatArg(F64 arg)
{
char *ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%g", arg);
return ret;
ConsoleValueRef ref = arg;
return ref;
}
char *getIntArg(S32 arg)
ConsoleValueRef getIntArg(S32 arg)
{
char *ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%d", arg);
return ret;
ConsoleValueRef ref = arg;
return ref;
}
char *getStringArg( const char *arg )
@ -281,6 +286,25 @@ inline void ExprEvalState::setStringVariable(const char *val)
currentVariable->setStringValue(val);
}
inline void ExprEvalState::setCopyVariable()
{
if (copyVariable)
{
switch (copyVariable->value.type)
{
case ConsoleValue::TypeInternalInt:
currentVariable->setIntValue(copyVariable->getIntValue());
break;
case ConsoleValue::TypeInternalFloat:
currentVariable->setFloatValue(copyVariable->getFloatValue());
break;
default:
currentVariable->setStringValue(copyVariable->getStringValue());
break;
}
}
}
//------------------------------------------------------------
// Gets a component of an object's field value or a variable and returns it
@ -401,14 +425,15 @@ static void setFieldComponent( SimObject* object, StringTableEntry field, const
}
}
const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNamespace, U32 argc, const char **argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNamespace, U32 argc, ConsoleValueRef *argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
{
#ifdef TORQUE_DEBUG
U32 stackStart = STR.mStartStackSize;
U32 consoleStackStart = CSTK.mStackPos;
#endif
static char traceBuffer[1024];
U32 i;
S32 i;
U32 iterDepth = 0;
@ -422,9 +447,9 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
if(argv)
{
// assume this points into a function decl:
U32 fnArgc = mCode[ip + 5];
thisFunctionName = U32toSTE(mCode[ip]);
argc = getMin(argc-1, fnArgc); // argv[0] is func name
U32 fnArgc = mCode[ip + 2 + 6];
thisFunctionName = CodeToSTE(mCode, ip);
S32 wantedArgc = getMin(argc-1, fnArgc); // argv[0] is func name
if(gEvalState.traceOn)
{
traceBuffer[0] = 0;
@ -445,24 +470,35 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
"%s(", thisFunctionName);
}
for(i = 0; i < argc; i++)
for (i = 0; i < wantedArgc; i++)
{
dStrcat(traceBuffer, argv[i+1]);
if(i != argc - 1)
dStrcat(traceBuffer, ", ");
dStrcat(traceBuffer, argv[i + 1]);
if (i != wantedArgc - 1)
dStrcat(traceBuffer, ", ");
}
dStrcat(traceBuffer, ")");
Con::printf("%s", traceBuffer);
}
gEvalState.pushFrame(thisFunctionName, thisNamespace);
popFrame = true;
for(i = 0; i < argc; i++)
for(i = 0; i < wantedArgc; i++)
{
StringTableEntry var = U32toSTE(mCode[ip + i + 6]);
StringTableEntry var = CodeToSTE(mCode, ip + (2 + 6 + 1) + (i * 2));
gEvalState.setCurVarNameCreate(var);
gEvalState.setStringVariable(argv[i+1]);
ConsoleValueRef ref = argv[i+1];
if (argv[i+1].isString())
gEvalState.setStringVariable(argv[i+1]);
else if (argv[i+1].isInt())
gEvalState.setIntVariable(argv[i+1]);
else if (argv[i+1].isFloat())
gEvalState.setFloatVariable(argv[i+1]);
else
gEvalState.setStringVariable(argv[i+1]);
}
ip = ip + fnArgc + 6;
ip = ip + (fnArgc * 2) + (2 + 6 + 1);
curFloatTable = mFunctionFloats;
curStringTable = mFunctionStrings;
curStringTableLen = mFunctionStringsMaxLen;
@ -497,6 +533,10 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
}
}
// Reset the console stack frame which at this point will contain
// either nothing or argv[] which we just copied
CSTK.resetFrame();
// Grab the state of the telenet debugger here once
// so that the push and pop frames are always balanced.
const bool telDebuggerOn = TelDebugger && TelDebugger->isConnected();
@ -530,7 +570,7 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
char nsDocBlockClass[nsDocLength];
U32 callArgc;
const char **callArgv;
ConsoleValueRef *callArgv;
static char curFieldArray[256];
static char prevFieldArray[256];
@ -543,6 +583,10 @@ const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNam
Con::gCurrentRoot = this->mModPath;
}
const char * val;
const char *retValue;
// note: anything returned is pushed to CSTK and will be invalidated on the next exec()
ConsoleValueRef returnValue;
// The frame temp is used by the variable accessor ops (OP_SAVEFIELD_* and
// OP_LOADFIELD_*) to store temporary values for the fields.
@ -559,11 +603,11 @@ breakContinue:
case OP_FUNC_DECL:
if(!noCalls)
{
fnName = U32toSTE(mCode[ip]);
fnNamespace = U32toSTE(mCode[ip+1]);
fnPackage = U32toSTE(mCode[ip+2]);
bool hasBody = ( mCode[ ip + 3 ] & 0x01 ) != 0;
U32 lineNumber = mCode[ ip + 3 ] >> 1;
fnName = CodeToSTE(mCode, ip);
fnNamespace = CodeToSTE(mCode, ip+2);
fnPackage = CodeToSTE(mCode, ip+4);
bool hasBody = ( mCode[ ip + 6 ] & 0x01 ) != 0;
U32 lineNumber = mCode[ ip + 6 ] >> 1;
Namespace::unlinkPackages();
ns = Namespace::find(fnNamespace, fnPackage);
@ -586,18 +630,18 @@ breakContinue:
//Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip);
}
ip = mCode[ip + 4];
ip = mCode[ip + 7];
break;
case OP_CREATE_OBJECT:
{
// Read some useful info.
objParent = U32toSTE(mCode[ip ]);
bool isDataBlock = mCode[ip + 1];
bool isInternal = mCode[ip + 2];
bool isSingleton = mCode[ip + 3];
U32 lineNumber = mCode[ip + 4];
failJump = mCode[ip + 5];
objParent = CodeToSTE(mCode, ip);
bool isDataBlock = mCode[ip + 2];
bool isInternal = mCode[ip + 3];
bool isSingleton = mCode[ip + 4];
U32 lineNumber = mCode[ip + 5];
failJump = mCode[ip + 6];
// If we don't allow calls, we certainly don't allow creating objects!
// Moved this to after failJump is set. Engine was crashing when
@ -615,8 +659,8 @@ breakContinue:
objectCreationStack[ objectCreationStackIndex++ ].failJump = failJump;
// Get the constructor information off the stack.
STR.getArgcArgv(NULL, &callArgc, &callArgv);
const char* objectName = callArgv[ 2 ];
CSTK.getArgcArgv(NULL, &callArgc, &callArgv);
const char *objectName = callArgv[ 2 ];
// Con::printf("Creating object...");
@ -638,6 +682,7 @@ breakContinue:
Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare data block %s with a different class.", getFileLine(ip), objectName);
ip = failJump;
STR.popFrame();
CSTK.popFrame();
break;
}
@ -659,18 +704,19 @@ breakContinue:
break;
}
SimObject *obj = Sim::findObject( objectName );
SimObject *obj = Sim::findObject( (const char*)objectName );
if (obj /*&& !obj->isLocalName()*/)
{
if ( isSingleton )
{
// Make sure we're not trying to change types
if ( dStricmp( obj->getClassName(), callArgv[1] ) != 0 )
if ( dStricmp( obj->getClassName(), (const char*)callArgv[1] ) != 0 )
{
Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare object [%s] with a different class [%s] - was [%s].",
getFileLine(ip), objectName, callArgv[1], obj->getClassName());
getFileLine(ip), objectName, (const char*)callArgv[1], obj->getClassName());
ip = failJump;
STR.popFrame();
CSTK.popFrame();
break;
}
@ -688,13 +734,29 @@ breakContinue:
// string stack and may get stomped if deleteObject triggers
// script execution.
const char* savedArgv[ StringStack::MaxArgs ];
dMemcpy( savedArgv, callArgv, sizeof( savedArgv[ 0 ] ) * callArgc );
ConsoleValueRef savedArgv[ StringStack::MaxArgs ];
for (int i=0; i<callArgc; i++) {
savedArgv[i] = callArgv[i];
}
//dMemcpy( savedArgv, callArgv, sizeof( savedArgv[ 0 ] ) * callArgc );
// Prevent stack value corruption
CSTK.pushFrame();
STR.pushFrame();
// --
obj->deleteObject();
obj = NULL;
dMemcpy( callArgv, savedArgv, sizeof( callArgv[ 0 ] ) * callArgc );
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
//dMemcpy( callArgv, savedArgv, sizeof( callArgv[ 0 ] ) * callArgc );
for (int i=0; i<callArgc; i++) {
callArgv[i] = savedArgv[i];
}
}
else if( dStricmp( redefineBehavior, "renameNew" ) == 0 )
{
@ -723,6 +785,7 @@ breakContinue:
getFileLine(ip), newName.c_str() );
ip = failJump;
STR.popFrame();
CSTK.popFrame();
break;
}
else
@ -734,6 +797,7 @@ breakContinue:
getFileLine(ip), objectName);
ip = failJump;
STR.popFrame();
CSTK.popFrame();
break;
}
}
@ -741,16 +805,17 @@ breakContinue:
}
STR.popFrame();
CSTK.popFrame();
if(!currentNewObject)
{
// Well, looks like we have to create a new object.
ConsoleObject *object = ConsoleObject::create(callArgv[1]);
ConsoleObject *object = ConsoleObject::create((const char*)callArgv[1]);
// Deal with failure!
if(!object)
{
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-conobject class %s.", getFileLine(ip), callArgv[1]);
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-conobject class %s.", getFileLine(ip), (const char*)callArgv[1]);
ip = failJump;
break;
}
@ -766,7 +831,7 @@ breakContinue:
else
{
// They tried to make a non-datablock with a datablock keyword!
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-datablock class %s.", getFileLine(ip), callArgv[1]);
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-datablock class %s.", getFileLine(ip), (const char*)callArgv[1]);
// Clean up...
delete object;
ip = failJump;
@ -780,7 +845,7 @@ breakContinue:
// Deal with the case of a non-SimObject.
if(!currentNewObject)
{
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-SimObject class %s.", getFileLine(ip), callArgv[1]);
Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-SimObject class %s.", getFileLine(ip), (const char*)callArgv[1]);
delete object;
ip = failJump;
break;
@ -807,7 +872,7 @@ breakContinue:
else
{
if ( Con::gObjectCopyFailures == -1 )
Con::errorf(ConsoleLogEntry::General, "%s: Unable to find parent object %s for %s.", getFileLine(ip), objParent, callArgv[1]);
Con::errorf(ConsoleLogEntry::General, "%s: Unable to find parent object %s for %s.", getFileLine(ip), objParent, (const char*)callArgv[1]);
else
++Con::gObjectCopyFailures;
@ -830,15 +895,30 @@ breakContinue:
currentNewObject->setOriginalName( objectName );
}
// Prevent stack value corruption
CSTK.pushFrame();
STR.pushFrame();
// --
// Do the constructor parameters.
if(!currentNewObject->processArguments(callArgc-3, callArgv+3))
{
delete currentNewObject;
currentNewObject = NULL;
ip = failJump;
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
break;
}
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
// If it's not a datablock, allow people to modify bits of it.
if(!isDataBlock)
{
@ -848,7 +928,7 @@ breakContinue:
}
// Advance the IP past the create info...
ip += 6;
ip += 7;
break;
}
@ -863,6 +943,11 @@ breakContinue:
// Con::printf("Adding object %s", currentNewObject->getName());
// Prevent stack value corruption
CSTK.pushFrame();
STR.pushFrame();
// --
// Make sure it wasn't already added, then add it.
if(currentNewObject->isProperlyAdded() == false)
{
@ -886,6 +971,10 @@ breakContinue:
Con::warnf(ConsoleLogEntry::General, "%s: Register object failed for object %s of class %s.", getFileLine(ip), currentNewObject->getName(), currentNewObject->getClassName());
delete currentNewObject;
ip = failJump;
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
break;
}
}
@ -894,6 +983,8 @@ breakContinue:
SimDataBlock *dataBlock = dynamic_cast<SimDataBlock *>(currentNewObject);
static String errorStr;
// If so, preload it.
if(dataBlock && !dataBlock->preload(true, errorStr))
{
@ -901,6 +992,11 @@ breakContinue:
currentNewObject->getName(), errorStr.c_str());
dataBlock->deleteObject();
ip = failJump;
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
break;
}
@ -955,6 +1051,10 @@ breakContinue:
else
intStack[++_UINT] = currentNewObject->getId();
// Prevent stack value corruption
CSTK.popFrame();
STR.popFrame();
// --
break;
}
@ -1037,6 +1137,29 @@ breakContinue:
// We're falling thru here on purpose.
case OP_RETURN:
retValue = STR.getStringValue();
if( iterDepth > 0 )
{
// Clear iterator state.
while( iterDepth > 0 )
{
iterStack[ -- _ITER ].mIsStringIter = false;
-- iterDepth;
}
STR.rewind();
STR.setStringValue( retValue ); // Not nice but works.
retValue = STR.getStringValue();
}
// Previously the return value was on the stack and would be returned using STR.getStringValue().
// Now though we need to wrap it in a ConsoleValueRef
returnValue.value = CSTK.pushStackString(retValue);
goto execFinished;
case OP_RETURN_FLT:
if( iterDepth > 0 )
{
@ -1047,10 +1170,27 @@ breakContinue:
-- iterDepth;
}
const char* returnValue = STR.getStringValue();
STR.rewind();
STR.setStringValue( returnValue ); // Not nice but works.
}
returnValue.value = CSTK.pushFLT(floatStack[_FLT]);
_FLT--;
goto execFinished;
case OP_RETURN_UINT:
if( iterDepth > 0 )
{
// Clear iterator state.
while( iterDepth > 0 )
{
iterStack[ -- _ITER ].mIsStringIter = false;
-- iterDepth;
}
}
returnValue.value = CSTK.pushUINT(intStack[_UINT]);
_UINT--;
goto execFinished;
@ -1170,8 +1310,8 @@ breakContinue:
break;
case OP_SETCURVAR:
var = U32toSTE(mCode[ip]);
ip++;
var = CodeToSTE(mCode, ip);
ip += 2;
// If a variable is set, then these must be NULL. It is necessary
// to set this here so that the vector parser can appropriately
@ -1190,10 +1330,10 @@ breakContinue:
break;
case OP_SETCURVAR_CREATE:
var = U32toSTE(mCode[ip]);
ip++;
var = CodeToSTE(mCode, ip);
ip += 2;
// See OP_SETCURVAR
// See OP_SETCURVAR
prevField = NULL;
prevObject = NULL;
curObject = NULL;
@ -1250,6 +1390,11 @@ breakContinue:
STR.setStringValue(val);
break;
case OP_LOADVAR_VAR:
// Sets current source of OP_SAVEVAR_VAR
gEvalState.copyVariable = gEvalState.currentVariable;
break;
case OP_SAVEVAR_UINT:
gEvalState.setIntVariable(intStack[_UINT]);
break;
@ -1261,6 +1406,11 @@ breakContinue:
case OP_SAVEVAR_STR:
gEvalState.setStringVariable(STR.getStringValue());
break;
case OP_SAVEVAR_VAR:
// this basically handles %var1 = %var2
gEvalState.setCopyVariable();
break;
case OP_SETCUROBJECT:
// Save the previous object for parsing vector fields.
@ -1310,9 +1460,9 @@ breakContinue:
// Save the previous field for parsing vector fields.
prevField = curField;
dStrcpy( prevFieldArray, curFieldArray );
curField = U32toSTE(mCode[ip]);
curField = CodeToSTE(mCode, ip);
curFieldArray[0] = 0;
ip++;
ip += 2;
break;
case OP_SETCURFIELD_ARRAY:
@ -1448,6 +1598,10 @@ breakContinue:
_UINT--;
break;
case OP_COPYVAR_TO_NONE:
gEvalState.copyVariable = NULL;
break;
case OP_LOADIMMED_UINT:
intStack[_UINT+1] = mCode[ip++];
_UINT++;
@ -1504,28 +1658,41 @@ breakContinue:
break;
case OP_LOADIMMED_IDENT:
STR.setStringValue(U32toSTE(mCode[ip++]));
STR.setStringValue(CodeToSTE(mCode, ip));
ip += 2;
break;
case OP_CALLFUNC_RESOLVE:
// This deals with a function that is potentially living in a namespace.
fnNamespace = U32toSTE(mCode[ip+1]);
fnName = U32toSTE(mCode[ip]);
fnNamespace = CodeToSTE(mCode, ip+2);
fnName = CodeToSTE(mCode, ip);
// Try to look it up.
ns = Namespace::find(fnNamespace);
nsEntry = ns->lookup(fnName);
if(!nsEntry)
{
ip+= 3;
ip+= 5;
Con::warnf(ConsoleLogEntry::General,
"%s: Unable to find function %s%s%s",
getFileLine(ip-4), fnNamespace ? fnNamespace : "",
getFileLine(ip-7), fnNamespace ? fnNamespace : "",
fnNamespace ? "::" : "", fnName);
STR.popFrame();
CSTK.popFrame();
break;
}
#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS
// Now fall through to OP_CALLFUNC...
// Now, rewrite our code a bit (ie, avoid future lookups) and fall
// through to OP_CALLFUNC
#ifdef TORQUE_CPU_X64
*((U64*)(code+ip+2)) = ((U64)nsEntry);
#else
code[ip+2] = ((U32)nsEntry);
#endif
code[ip-1] = OP_CALLFUNC;
#endif
case OP_CALLFUNC:
{
@ -1535,7 +1702,7 @@ breakContinue:
// or just on the object.
S32 routingId = 0;
fnName = U32toSTE(mCode[ip]);
fnName = CodeToSTE(mCode, ip);
//if this is called from inside a function, append the ip and codeptr
if( gEvalState.getStackDepth() > 0 )
@ -1544,10 +1711,10 @@ breakContinue:
gEvalState.getCurrentFrame().ip = ip - 1;
}
U32 callType = mCode[ip+2];
U32 callType = mCode[ip+4];
ip += 3;
STR.getArgcArgv(fnName, &callArgc, &callArgv);
ip += 5;
CSTK.getArgcArgv(fnName, &callArgc, &callArgv);
const char *componentReturnValue = "";
@ -1555,23 +1722,32 @@ breakContinue:
{
if( !nsEntry )
{
// We must not have come from OP_CALLFUNC_RESOLVE, so figure out
// our own entry.
#ifdef COMPILER_OPTIMIZE_FUNCTION_CALLS
#ifdef TORQUE_CPU_X64
nsEntry = ((Namespace::Entry *) *((U64*)(code+ip-3)));
#else
nsEntry = ((Namespace::Entry *) *(code+ip-3));
#endif
#else
nsEntry = Namespace::global()->lookup( fnName );
#endif
ns = NULL;
}
ns = NULL;
}
else if(callType == FuncCallExprNode::MethodCall)
{
saveObject = gEvalState.thisObject;
gEvalState.thisObject = Sim::findObject(callArgv[1]);
gEvalState.thisObject = Sim::findObject((const char*)callArgv[1]);
if(!gEvalState.thisObject)
{
// Go back to the previous saved object.
gEvalState.thisObject = saveObject;
Con::warnf(ConsoleLogEntry::General,"%s: Unable to find object: '%s' attempting to call function '%s'", getFileLine(ip-4), callArgv[1], fnName);
Con::warnf(ConsoleLogEntry::General,"%s: Unable to find object: '%s' attempting to call function '%s'", getFileLine(ip-4), (const char*)callArgv[1], fnName);
STR.popFrame();
CSTK.popFrame();
STR.setStringValue("");
break;
}
@ -1618,7 +1794,7 @@ breakContinue:
{
if(!noCalls && !( routingId == MethodOnComponent ) )
{
Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-4), fnName);
Con::warnf(ConsoleLogEntry::General,"%s: Unknown command %s.", getFileLine(ip-6), fnName);
if(callType == FuncCallExprNode::MethodCall)
{
Con::warnf(ConsoleLogEntry::General, " Object %s(%d) %s",
@ -1627,6 +1803,7 @@ breakContinue:
}
}
STR.popFrame();
CSTK.popFrame();
if( routingId == MethodOnComponent )
STR.setStringValue( componentReturnValue );
@ -1637,12 +1814,33 @@ breakContinue:
}
if(nsEntry->mType == Namespace::Entry::ConsoleFunctionType)
{
const char *ret = "";
ConsoleValueRef ret;
if(nsEntry->mFunctionOffset)
ret = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);
STR.popFrame();
STR.setStringValue(ret);
// Functions are assumed to return strings, so look ahead to see if we can skip the conversion
if(mCode[ip] == OP_STR_TO_UINT)
{
ip++;
intStack[++_UINT] = (U32)((S32)ret);
}
else if(mCode[ip] == OP_STR_TO_FLT)
{
ip++;
floatStack[++_FLT] = (F32)ret;
}
else if(mCode[ip] == OP_STR_TO_NONE)
{
STR.setStringValue(ret.getStringValue());
ip++;
}
else
STR.setStringValue((const char*)ret);
// This will clear everything including returnValue
CSTK.popFrame();
STR.clearFunctionOffset();
}
else
{
@ -1652,17 +1850,18 @@ breakContinue:
// which is useful behavior when debugging so I'm ifdefing this out for debug builds.
if(nsEntry->mToolOnly && ! Con::isCurrentScriptToolScript())
{
Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-4), nsName, fnName);
Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", getFileLine(ip-6), nsName, fnName);
}
else
#endif
if((nsEntry->mMinArgs && S32(callArgc) < nsEntry->mMinArgs) || (nsEntry->mMaxArgs && S32(callArgc) > nsEntry->mMaxArgs))
{
Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).",
getFileLine(ip-4), nsName, fnName,
getFileLine(ip-6), nsName, fnName,
callArgc, nsEntry->mMinArgs, nsEntry->mMaxArgs);
Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-4), nsEntry->mUsage);
Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip-6), nsEntry->mUsage);
STR.popFrame();
CSTK.popFrame();
}
else
{
@ -1672,16 +1871,18 @@ breakContinue:
{
const char *ret = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
STR.popFrame();
CSTK.popFrame();
if(ret != STR.getStringValue())
STR.setStringValue(ret);
else
STR.setLen(dStrlen(ret));
//else
// STR.setLen(dStrlen(ret));
break;
}
case Namespace::Entry::IntCallbackType:
{
S32 result = nsEntry->cb.mIntCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
STR.popFrame();
CSTK.popFrame();
if(mCode[ip] == OP_STR_TO_UINT)
{
ip++;
@ -1704,6 +1905,7 @@ breakContinue:
{
F64 result = nsEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
STR.popFrame();
CSTK.popFrame();
if(mCode[ip] == OP_STR_TO_UINT)
{
ip++;
@ -1725,15 +1927,17 @@ breakContinue:
case Namespace::Entry::VoidCallbackType:
nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
if( mCode[ ip ] != OP_STR_TO_NONE && Con::getBoolVariable( "$Con::warnVoidAssignment", true ) )
Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-4), fnName, functionName);
Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip-6), fnName, functionName);
STR.popFrame();
CSTK.popFrame();
STR.setStringValue("");
break;
case Namespace::Entry::BoolCallbackType:
{
bool result = nsEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
STR.popFrame();
CSTK.popFrame();
if(mCode[ip] == OP_STR_TO_UINT)
{
ip++;
@ -1788,10 +1992,26 @@ breakContinue:
break;
case OP_PUSH:
STR.push();
CSTK.pushString(STR.getPreviousStringValue());
break;
case OP_PUSH_UINT:
CSTK.pushUINT(intStack[_UINT]);
_UINT--;
break;
case OP_PUSH_FLT:
CSTK.pushFLT(floatStack[_FLT]);
_FLT--;
break;
case OP_PUSH_VAR:
if (gEvalState.currentVariable)
CSTK.pushValue(gEvalState.currentVariable->value);
else
CSTK.pushString("");
break;
case OP_PUSH_FRAME:
STR.pushFrame();
CSTK.pushFrame();
break;
case OP_ASSERT:
@ -1844,8 +2064,8 @@ breakContinue:
case OP_ITER_BEGIN:
{
StringTableEntry varName = U32toSTE( mCode[ ip ] );
U32 failIp = mCode[ ip + 1 ];
StringTableEntry varName = CodeToSTE(mCode, ip);
U32 failIp = mCode[ ip + 2 ];
IterStackRecord& iter = iterStack[ _ITER ];
@ -1880,7 +2100,7 @@ breakContinue:
STR.push();
ip += 2;
ip += 3;
break;
}
@ -2021,7 +2241,8 @@ execFinished:
AssertFatal(!(STR.mStartStackSize > stackStart), "String stack not popped enough in script exec");
AssertFatal(!(STR.mStartStackSize < stackStart), "String stack popped too much in script exec");
#endif
return STR.getStringValue();
return returnValue;
}
//------------------------------------------------------------