📄 compiledeval.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "core/resManager.h"
#include "core/findMatch.h"
#include "console/consoleInternal.h"
#include "core/fileStream.h"
#include "console/compiler.h"
#include "console/simBase.h"
#include "console/telnetDebugger.h"
#include "sim/netStringTable.h"
#include "console/stringStack.h"
using namespace Compiler;
enum EvalConstants {
MaxStackSize = 1024
};
namespace Con
{
// Current script file name and root, these are registered as
// console variables.
extern StringTableEntry gCurrentFile;
extern StringTableEntry gCurrentRoot;
}
F64 floatStack[MaxStackSize];
U32 intStack[MaxStackSize];
StringStack STR;
U32 g_uFloatIP = 0;
U32 g_uIntIP = 0;
static const char *getNamespaceList(Namespace *ns)
{
U32 size = 1;
Namespace * walk;
for(walk = ns; walk; walk = walk->mParent)
size += dStrlen(walk->mName) + 4;
char *ret = Con::getReturnBuffer(size);
ret[0] = 0;
for(walk = ns; walk; walk = walk->mParent)
{
dStrcat(ret, walk->mName);
if(walk->mParent)
dStrcat(ret, " -> ");
}
return ret;
}
//------------------------------------------------------------
F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line)
{
F64 val = dAtof(str);
if(val != 0)
return val;
else if(!dStricmp(str, "true"))
return 1;
else if(!dStricmp(str, "false"))
return 0;
else if(file)
{
Con::warnf(ConsoleLogEntry::General, "%s (%d): string always evaluates to 0.", file, line);
return 0;
}
return 0;
}
//------------------------------------------------------------
#ifdef TGE_RPG_SCRIPT
#define TGE_USE_STACK
struct VStrSect
{
char* pSection;
bool bContent;
int cType;
};
static bool processVString(char* vStr,const char*& pOutput)
{
char *pPercent;
pOutput = vStr;
//pPercent = dStrstr(vStr,(const char*)"%");
//if(pPercent == 0)
// return false;
/*/////////////////////////////////////////////
%var
%f.var
/*/////////////////////////////////////////////
static Vector<VStrSect> s_arSection;
char *pCurrent,
// *pPrev,
*pVar,
*pVar2,
*pNew,
*pContent;
U32 nLen,nMax,n,nBufSize(0);
char szVar[256];
char cType;
#ifdef TGE_USE_STACK
static StringStack s_strStack;
s_strStack.clear();
#endif
s_arSection.clear();
nMax = dStrlen(vStr);
pCurrent = vStr;
pPercent = vStr;
///*pPrev*/ = pCurrent;
//for(; pPercent ; pPercent = dStrstr(pPercent,(const char*)"%") )
for(; pPercent<vStr + nMax;)
{
if(*pPercent != '%' && *pPercent != '$')
{
pPercent++;
continue;
}
if(!dIsalpha(pPercent[1]) && pPercent[1] != '_')
{
pPercent += (pPercent[1] != 0? 2 : 1);
continue;
}
nLen = pPercent - pCurrent;
if(*pPercent == '%')
pPercent ++; //跳过%符,$符不用跳
//处理 %f.var格式
if(pPercent[0] && pPercent[1] == '.')
{
cType = pPercent[0];
pPercent += 2;
}
else
cType = 0;
//变量处理
if(dIsalpha(pPercent[0]) || pPercent[0] == '_'|| pPercent[0] == '%' || pPercent[0] == '$' )
pVar = pPercent;
else
{
//pPrev = pCurrent;
//pCurrent = pPercent+2;
pPercent++;
continue;
}
if(pPercent[0] == '%' && cType == 0)
nLen++;
if(nLen)
{
//保存%前的原字符串内容
#ifdef TGE_USE_STACK
//s_strStack.advance();
pNew = s_strStack.getStrBuffer(nLen+1);
#else
pNew = new char[nLen+1];
pNew[nLen] = 0;
#endif
dStrncpy(pNew,pCurrent,nLen);
nBufSize += nLen;
s_arSection.increment();
VStrSect& last = s_arSection.last();
last.pSection = pNew;
last.bContent = false;
last.cType = 0;
}
//%%转义符处理
if(pPercent[0] == '%' && cType == 0)
{
//pCurrent = pPercent+2;
//pPrev = pCurrent;
pPercent ++;
pCurrent = pPercent;
continue;
}
////////////////////////////////////
//截取变量
if(pVar[0] == '$')
pVar2 = pVar+1;
else
pVar2=pVar;
for(;pVar2[0] != 0 && (dIsalnum(pVar2[0]) || pVar2[0] == '_' || pVar2[0] == ':');pVar2++);
nLen = pVar2 - pVar;
dStrncpy(szVar,pVar,nLen);
szVar[nLen] = 0;
//获取变量内容
if(szVar[0] == '$')
{
pContent = (char*)Con::getVariable((const char*)szVar);
}
else
{
//gEvalState.setCurVarNameCreate(szVar);
//pContent = (char*)gEvalState.getStringVariable();
pContent = (char*)Con::getLocalVariable((const char*)szVar);
if(pContent == 0 || pContent[0] == 0)
pContent = (char*)Con::getVariable((const char*)szVar);
}
//添加内容
if(pContent)
{
s_arSection.increment();
VStrSect& last = s_arSection.last();
last.pSection = pContent;
last.bContent = true;
last.cType = cType;
nBufSize += dStrlen(pContent);
}
///*pPrev*/ = pCurrent;
pCurrent = pVar2;
pPercent = pVar2;
}//for
//直接返回,没有变量替换的话
if(pCurrent == vStr)
return true;
//保存最的一段内容
s_arSection.increment();
VStrSect& last = s_arSection.last();
last.pSection = pCurrent;
last.bContent = true;
last.cType = 0;
nBufSize += dStrlen(pCurrent);
//consoleAlloc();
///////////////////////////////////
//内容连接
#ifdef TGE_USE_STACK
//直接把内容写到STR中
pContent = STR.getStrBuffer(nBufSize+1,false);
#else
pContent = new char[nBufSize+1];
pContent[nBufSize] = 0;
#endif
pCurrent = pContent;
for(n=0; n<s_arSection.size(); n++)
{
pVar = s_arSection[n].pSection;
switch(s_arSection[n].cType)
{
case 'b':
dStrcpy(pCurrent,dAtob(pVar)?"true":"false");
break;
case 'd':
case 'i':
dSprintf(pCurrent,nBufSize - (pCurrent-pContent),"%d",dAtoi(pVar));
break;
case 'f':
case 'g':
dSprintf(pCurrent,nBufSize - (pCurrent-pContent),"%g",dAtof(pVar));
break;
case 's':
default:
dStrcpy(pCurrent,pVar);
break;
}
pCurrent += dStrlen(pCurrent);
}
#ifdef TGE_USE_STACK
return false; //已经保存到STR中,无须再重做
#else
//清除
for(n=0; n<s_arSection.size(); n++)
{
if(!s_arSection[n].bContent)
{
//s_strStack.rewind();
delete[] s_arSection[n].pSection;
}
}
pOutput = pContent;
return true;
#endif
}
#endif
//------------------------------------------------------------
namespace Con
{
char *getReturnBuffer(U32 bufferSize)
{
return STR.getReturnBuffer(bufferSize);
}
char *getArgBuffer(U32 bufferSize)
{
return STR.getArgBuffer(bufferSize);
}
char *getFloatArg(F64 arg)
{
char *ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%g", arg);
return ret;
}
char *getIntArg(S32 arg)
{
char *ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%d", arg);
return ret;
}
}
//------------------------------------------------------------
inline void ExprEvalState::setCurVarName(StringTableEntry name)
{
if(name[0] == '$')
currentVariable = globalVars.lookup(name);
else if(stack.size())
currentVariable = stack.last()->lookup(name);
if(!currentVariable && gWarnUndefinedScriptVariables)
Con::warnf(ConsoleLogEntry::Script, "Variable referenced before assignment: %s", name);
}
inline void ExprEvalState::setCurVarNameCreate(StringTableEntry name)
{
if(name[0] == '$')
currentVariable = globalVars.add(name);
else if(stack.size())
currentVariable = stack.last()->add(name);
else
{
currentVariable = NULL;
Con::warnf(ConsoleLogEntry::Script, "Accessing local variable in global scope... failed: %s", name);
}
}
//------------------------------------------------------------
inline S32 ExprEvalState::getIntVariable()
{
return currentVariable ? currentVariable->getIntValue() : 0;
}
inline F64 ExprEvalState::getFloatVariable()
{
return currentVariable ? currentVariable->getFloatValue() : 0;
}
inline const char *ExprEvalState::getStringVariable()
{
return currentVariable ? currentVariable->getStringValue() : "";
}
//------------------------------------------------------------
inline void ExprEvalState::setIntVariable(S32 val)
{
AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
currentVariable->setIntValue(val);
}
inline void ExprEvalState::setFloatVariable(F64 val)
{
AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
currentVariable->setFloatValue(val);
}
inline void ExprEvalState::setStringVariable(const char *val)
{
AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
currentVariable->setStringValue(val);
}
//------------------------------------------------------------
void CodeBlock::getFunctionArgs(char buffer[1024], U32 ip)
{
U32 fnArgc = code[ip + 5];
buffer[0] = 0;
for(U32 i = 0; i < fnArgc; i++)
{
StringTableEntry var = U32toSTE(code[ip + i + 6]);
// Add a comma so it looks nice!
if(i != 0)
dStrcat(buffer, ", ");
dStrcat(buffer, "var ");
// Try to capture junked parameters
if(var[0])
dStrcat(buffer, var+1);
else
dStrcat(buffer, "JUNK");
}
}
const char *CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNamespace, U32 argc, const char **argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
{
static char traceBuffer[1024];
U32 i;
incRefCount();
F64 *curFloatTable;
char *curStringTable;
STR.clearFunctionOffset();
StringTableEntry thisFunctionName = NULL;
bool popFrame = false;
if(argv)
{
// assume this points into a function decl:
U32 fnArgc = code[ip + 5];
thisFunctionName = U32toSTE(code[ip]);
argc = getMin(argc-1, fnArgc); // argv[0] is func name
if(gEvalState.traceOn)
{
traceBuffer[0] = 0;
dStrcat(traceBuffer, "Entering ");
if(packageName)
{
dStrcat(traceBuffer, "[");
dStrcat(traceBuffer, packageName);
dStrcat(traceBuffer, "]");
}
if(thisNamespace && thisNamespace->mName)
{
dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
"%s::%s(", thisNamespace->mName, thisFunctionName);
}
else
{
dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
"%s(", thisFunctionName);
}
for(i = 0; i < argc; i++)
{
dStrcat(traceBuffer, argv[i+1]);
if(i != argc - 1)
dStrcat(traceBuffer, ", ");
}
dStrcat(traceBuffer, ")");
Con::printf("%s", traceBuffer);
}
gEvalState.pushFrame(thisFunctionName, thisNamespace);
popFrame = true;
for(i = 0; i < argc; i++)
{
StringTableEntry var = U32toSTE(code[ip + i + 6]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -