From 9084e81bc1fd80a55c6a3483037f52dfb5612b5a Mon Sep 17 00:00:00 2001 From: JeffR Date: Sun, 22 Feb 2026 18:18:42 -0600 Subject: [PATCH] Shifted CodeBlock::smCurrentLineText to be a const char* so it's use is clearer Ensured CodeBlock::smCurrentLineText is cleared at the end of execution Tweaked and cleaned up the context lines passed along for further debugging data in the event of a script assert --- Engine/source/T3D/SubScene.cpp | 11 ++++- Engine/source/T3D/missionMarker.cpp | 12 ++++- Engine/source/T3D/trigger.cpp | 45 ++++++++++++++++--- .../source/console/torquescript/astNodes.cpp | 2 +- .../source/console/torquescript/codeBlock.cpp | 8 +++- .../source/console/torquescript/codeBlock.h | 2 +- .../source/console/torquescript/compiler.cpp | 34 +++++++++++--- .../gui/controls/guiGameListMenuCtrl.cpp | 2 +- .../gui/controls/guiGameSettingsCtrl.cpp | 2 +- Engine/source/gui/core/guiControl.cpp | 10 ++++- Engine/source/sim/actionMap.cpp | 2 +- 11 files changed, 107 insertions(+), 23 deletions(-) diff --git a/Engine/source/T3D/SubScene.cpp b/Engine/source/T3D/SubScene.cpp index effda500f..4dca81595 100644 --- a/Engine/source/T3D/SubScene.cpp +++ b/Engine/source/T3D/SubScene.cpp @@ -225,7 +225,16 @@ bool SubScene::evaluateCondition() Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mLoadIf + ";"; - Con::evaluatef(command.c_str()); + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context); return Con::getBoolVariable(resVar.c_str()); } return true; diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index 69ae9ab81..9acf4c61c 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -367,7 +367,17 @@ bool SpawnSphere::testCondition() String resVar = getIdString() + String(".result"); Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mSpawnIf + ";"; - Con::evaluatef(command.c_str()); + + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index 5df83f681..95a331851 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -704,7 +704,17 @@ bool Trigger::testCondition() String resVar = getIdString() + String(".result"); Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mTripIf + ";"; - Con::evaluatef(command.c_str()); + + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; @@ -743,8 +753,15 @@ void Trigger::potentialEnterObject(GameBase* enter) String command = String("%obj = ") + enter->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mEnterCommand; - StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); - String context = String::ToString("%s, %s", getGroup(), objectName); + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); Con::evaluate(command.c_str(), false, context); } @@ -795,8 +812,15 @@ void Trigger::processTick(const Move* move) String command = String("%obj = ") + remove->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mLeaveCommand; - StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); - String context = String::ToString("%s, %s", getGroup(), objectName); + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); Con::evaluate(command.c_str(), false, context); } if (testTrippable() && testCondition()) @@ -807,8 +831,15 @@ void Trigger::processTick(const Move* move) if (evalCmD(&mTickCommand)) { - StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getIdString(); - String context = String::ToString("%s, %s", getGroup(), objectName); + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup()->getName(); + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); Con::evaluate(mTickCommand.c_str(), false, context); } diff --git a/Engine/source/console/torquescript/astNodes.cpp b/Engine/source/console/torquescript/astNodes.cpp index e1f3f6224..c20a0b975 100644 --- a/Engine/source/console/torquescript/astNodes.cpp +++ b/Engine/source/console/torquescript/astNodes.cpp @@ -60,7 +60,7 @@ inline FuncVars* getFuncVars(S32 lineNumber) if (gFuncVars == &gGlobalScopeFuncVars) { const char* lineTxt = CodeBlock::smCurrentLineText; - const char* str = avar("Attemping to use local variable in global scope. File: %s Line Num: %d \nLine: %s", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); + const char* str = avar("Attemping to use local variable in global scope. File: %s\nLine Num: %d\nLine: \"%s\"", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); scriptErrorHandler(str); } return gFuncVars; diff --git a/Engine/source/console/torquescript/codeBlock.cpp b/Engine/source/console/torquescript/codeBlock.cpp index cd324767d..d3bf6b3f5 100644 --- a/Engine/source/console/torquescript/codeBlock.cpp +++ b/Engine/source/console/torquescript/codeBlock.cpp @@ -35,7 +35,7 @@ using namespace Compiler; bool CodeBlock::smInFunction = false; CodeBlock * CodeBlock::smCodeBlockList = NULL; -StringTableEntry CodeBlock::smCurrentLineText = StringTable->EmptyString(); +const char* CodeBlock::smCurrentLineText = "\0"; TorqueScriptParser *CodeBlock::smCurrentParser = NULL; extern FuncVars gEvalFuncVars; @@ -625,6 +625,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in if (!Script::gStatementList) { + smCurrentLineText = "\0"; delete this; return Con::EvalResult(Con::getVariable("$ScriptError")); } @@ -670,7 +671,10 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); // repurpose argc as local register counter for global state - return (exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); + Con::EvalResult execResult = (exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); + + smCurrentLineText = "\0"; + return execResult; } //------------------------------------------------------------------------- diff --git a/Engine/source/console/torquescript/codeBlock.h b/Engine/source/console/torquescript/codeBlock.h index cef6d2683..33404d9a6 100644 --- a/Engine/source/console/torquescript/codeBlock.h +++ b/Engine/source/console/torquescript/codeBlock.h @@ -61,7 +61,7 @@ private: public: static bool smInFunction; static TorqueScriptParser * smCurrentParser; - static StringTableEntry smCurrentLineText; + static const char* smCurrentLineText; static CodeBlock *getCodeBlockList() { diff --git a/Engine/source/console/torquescript/compiler.cpp b/Engine/source/console/torquescript/compiler.cpp index 24e9135cc..206f7d679 100644 --- a/Engine/source/console/torquescript/compiler.cpp +++ b/Engine/source/console/torquescript/compiler.cpp @@ -160,8 +160,16 @@ S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, if (found->second.isConstant) { - const char* lineTxt = CodeBlock::smCurrentLineText; - const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); + const char* lineText = CodeBlock::smCurrentLineText; + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber - 1].c_str(); + + const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); } return found->second.reg; @@ -180,8 +188,16 @@ S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { - const char* lineTxt = CodeBlock::smCurrentLineText; - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); + const char* lineText = CodeBlock::smCurrentLineText; + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber - 1].c_str(); + + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); return assign(var, TypeReqString, lineNumber, false); @@ -197,7 +213,15 @@ TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { const char* lineText = CodeBlock::smCurrentLineText; - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line Num: %d \nLine: %s", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber-1].c_str(); + + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); assign(var, TypeReqString, lineNumber, false); diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index a81551d0e..2509c8cbd 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -975,7 +975,7 @@ void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command) { setThisControl(); StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); - String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); Con::evaluate(command, false, context); } } diff --git a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp index ea3fd2ece..778c3c7b7 100644 --- a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp +++ b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp @@ -495,7 +495,7 @@ void GuiGameSettingsCtrl::doScriptCommand(StringTableEntry command) { setThisControl(); StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); - String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); Con::evaluate(command, false, context); } } diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 406a803d4..b7b272612 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2495,8 +2495,14 @@ void GuiControl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent const char* GuiControl::evaluate( const char* str ) { smThisControl = this; - StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); - String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + StringTableEntry objectName = getName(); + if (getName() == NULL) + objectName = getInternalName(); + StringTableEntry fileName = getFilename(); + if (fileName != NULL) + fileName = Platform::makeRelativePathName(fileName, NULL); + + String context = String::ToString("%s\nObject: %s", fileName, objectName); const char* result = Con::evaluate(str, false, context).value; smThisControl = NULL; diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index d392ab3d2..e492752f5 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -1485,7 +1485,7 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) if (pNode->makeConsoleCommand) { StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); - String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); Con::evaluate(pNode->makeConsoleCommand, false, context); } }