Merge pull request #1004 from lukaspj/console-refactor

Console Refactor
This commit is contained in:
Brian Roberts 2023-09-13 08:21:41 -05:00 committed by GitHub
commit ec8a8290b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
89 changed files with 1943 additions and 1733 deletions

View file

@ -33,12 +33,12 @@ endif (APPLE)
# When on Windows, we need to link against winsock and windows codecs
if (WIN32)
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_WIN_SOURCES})
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_WIN_SOURCES})
endif (WIN32)
# Linux requires X11 & freetype
if (UNIX AND NOT APPLE)
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_X11_SOURCES})
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_X11_SOURCES})
find_package(Freetype REQUIRED)
set(TORQUE_INCLUDE_DIRECTORIES ${TORQUE_INCLUDE_DIRECTORIES} ${FREETYPE_INCLUDE_DIRS})
endif (UNIX AND NOT APPLE)
@ -50,11 +50,12 @@ torqueAddSourceDirectories("app" "app/net")
# Handle console
torqueAddSourceDirectories("console")
torqueAddSourceDirectories("console/torquescript")
# Handle Platform
torqueAddSourceDirectories("platform" "platform/threads" "platform/async"
"platform/input" "platform/output")
torqueAddSourceDirectories("platform/nativeDialogs")
# Handle T3D
@ -291,7 +292,7 @@ endforeach()
# Prepare Windows RC file
if (WIN32)
set(APPLICATION_ICON_PATH "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.ico")
configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/torque-win.rc.in" "${CMAKE_BINARY_DIR}/temp/torque.rc")
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} "${CMAKE_BINARY_DIR}/temp/torque.rc")
endif (WIN32)
@ -300,7 +301,7 @@ endif (WIN32)
if (APPLE)
set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_MAC_SOURCES} "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns")
set_source_files_properties("${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(EXECUTABLE_NAME "${TORQUE_APP_NAME}")
configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/Info.plist.in" "${CMAKE_BINARY_DIR}/temp/Info.plist" COPYONLY)
endif (APPLE)
@ -348,25 +349,25 @@ if (APPLE)
set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks")
elseif (WIN32)
add_executable(${TORQUE_APP_NAME} WIN32 ${TORQUE_SOURCE_FILES})
set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS /MP /Ob2 /Oi /Ot /Oy /GT /Zi /W4 /nologo /GF /EHsc /GS- /Gy- /Qpar- /fp:precise /fp:except- /GR /Zc:wchar_t-" )
if( TORQUE_CPU_X32 )
set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} /arch:SSE2")
endif()
set(TORQUE_CXX_FLAGS_COMMON ${TORQUE_CXX_FLAGS_COMMON_DEFAULT} CACHE STRING "")
mark_as_advanced(TORQUE_CXX_FLAGS_COMMON)
set(TORQUE_CXX_FLAGS_EXECUTABLES "/wd4018 /wd4100 /wd4121 /wd4127 /wd4130 /wd4244 /wd4245 /wd4389 /wd4511 /wd4512 /wd4800 /wd4995" CACHE STRING "")
mark_as_advanced(TORQUE_CXX_FLAGS_EXECUTABLES)
set(TORQUE_CXX_FLAGS "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} ${TORQUE_CXX_FLAGS_EXECUTABLES}" CACHE STRING "")
mark_as_advanced(TORQUE_CXX_FLAGS)
# NOTE: On Windows, /Zc:wchar_t- is necessary otherwise you get unicode errors
set_target_properties(${TORQUE_APP_NAME} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS}")
else()
add_executable(${TORQUE_APP_NAME} ${TORQUE_SOURCE_FILES})
# NOTE: On Linux, we set the rpath to ./ so that shared objects next to the executable are used
set_target_properties(${TORQUE_APP_NAME} PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
endif()
@ -423,9 +424,9 @@ if (UNIX)
# For eg. OSX some links are not valid targets - for example frameworks provided by OS
if (TARGET ${GAME_LINK_LIBRARY})
get_target_property(LINK_LIBRARY_TYPE ${GAME_LINK_LIBRARY} TYPE)
# Only pay attention to shared libraries and make them output to the app resources
if ("${LINK_LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
if ("${LINK_LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
if (APPLE)
set_target_properties(${GAME_LINK_LIBRARY} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.app/Contents/Frameworks")
else()
@ -434,4 +435,4 @@ if (UNIX)
endif()
endif()
endforeach()
endif (UNIX)
endif (UNIX)

View file

@ -41,6 +41,7 @@
#endif
// Debug Profiling.
#include "console/script.h"
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
@ -140,7 +141,7 @@ void CubemapAsset::initializeAsset()
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
}
@ -148,7 +149,7 @@ void CubemapAsset::onAssetRefresh()
{
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
}

View file

@ -41,6 +41,7 @@
#endif
// Debug Profiling.
#include "console/script.h"
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
@ -118,12 +119,12 @@ void GUIAsset::initializeAsset()
{
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
if (Torque::FS::IsScriptFile(mGUIPath))
if (Con::isScriptFile(mGUIPath))
Con::executeFile(mGUIPath, false, false);
}
@ -131,12 +132,12 @@ void GUIAsset::onAssetRefresh()
{
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
if (Torque::FS::IsScriptFile(mGUIPath))
if (Con::isScriptFile(mGUIPath))
Con::executeFile(mGUIPath, false, false);
}

View file

@ -41,6 +41,7 @@
#endif
// Debug Profiling.
#include "console/script.h"
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
@ -134,7 +135,7 @@ void GameObjectAsset::initializeAsset()
//Ensure we have an expanded filepath
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
mTAMLPath = getOwned() ? expandAssetFilePath(mTAMLFile) : mTAMLPath;
@ -145,7 +146,7 @@ void GameObjectAsset::onAssetRefresh()
//Ensure we have an expanded filepath
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
mTAMLPath = getOwned() ? expandAssetFilePath(mTAMLFile) : mTAMLPath;

View file

@ -40,6 +40,7 @@
#include "assets/assetPtr.h"
#endif
#include "console/script.h"
#include "T3D/assets/assetImporter.h"
StringTableEntry MaterialAsset::smNoMaterialAssetFallback = NULL;
@ -179,7 +180,7 @@ void MaterialAsset::initializeAsset()
{
mLoadedState = EmbeddedDefinition;
}
else if (Torque::FS::IsScriptFile(mScriptPath))
else if (Con::isScriptFile(mScriptPath))
{
if (!Sim::findObject(mMatDefinitionName))
{
@ -211,7 +212,7 @@ void MaterialAsset::onAssetRefresh()
return;
}
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
{
//Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
//But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior

View file

@ -41,6 +41,7 @@
#endif
// Debug Profiling.
#include "console/script.h"
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
@ -137,7 +138,7 @@ void PostEffectAsset::initializeAsset()
mHLSLShaderPath = getOwned() ? expandAssetFilePath(mHLSLShaderFile) : mHLSLShaderPath;
mGLSLShaderPath = getOwned() ? expandAssetFilePath(mGLSLShaderFile) : mGLSLShaderPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
}
@ -147,7 +148,7 @@ void PostEffectAsset::onAssetRefresh()
mHLSLShaderPath = getOwned() ? expandAssetFilePath(mHLSLShaderFile) : mHLSLShaderPath;
mGLSLShaderPath = getOwned() ? expandAssetFilePath(mGLSLShaderFile) : mGLSLShaderPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
Con::executeFile(mScriptPath, false, false);
}

View file

@ -40,6 +40,7 @@
#endif
// Debug Profiling.
#include "console/script.h"
#include "platform/profiler.h"
//-----------------------------------------------------------------------------
@ -140,7 +141,7 @@ void ScriptAsset::initializeAsset()
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
{
//We're initialized properly, so we'll go ahead and kick along any dependencies we may have as well
AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
@ -170,7 +171,7 @@ void ScriptAsset::onAssetRefresh()
{
mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
{
//Refresh any dependencies we may have
for (U32 i = 0; i < mScriptAssetDependencies.size(); i++)
@ -215,7 +216,7 @@ bool ScriptAsset::execScript()
if (handle)
return true;
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
{
return Con::executeFile(mScriptPath, false, false);
}

View file

@ -40,6 +40,7 @@
#include "assets/assetPtr.h"
#endif
#include "console/script.h"
#include "T3D/assets/assetImporter.h"
StringTableEntry TerrainMaterialAsset::smNoTerrainMaterialAssetFallback = NULL;
@ -182,7 +183,7 @@ void TerrainMaterialAsset::initializeAsset()
{
mLoadedState = EmbeddedDefinition;
}
else if (Torque::FS::IsScriptFile(mScriptPath))
else if (Con::isScriptFile(mScriptPath))
{
if (!Sim::findObject(mMatDefinitionName))
{
@ -214,7 +215,7 @@ void TerrainMaterialAsset::onAssetRefresh()
return;
}
if (Torque::FS::IsScriptFile(mScriptPath))
if (Con::isScriptFile(mScriptPath))
{
//Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
//But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior

View file

@ -31,6 +31,7 @@
#include "console/consoleTypes.h"
#include "core/volume.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "T3D/physics/physicsShape.h"
#include "core/util/path.h"
@ -344,7 +345,7 @@ void Prefab::_loadFile( bool addFileNotify )
if ( mFilename == StringTable->EmptyString())
return;
if ( !Torque::FS::IsScriptFile( mFilename ) )
if ( !Con::isScriptFile( mFilename ) )
{
Con::errorf( "Prefab::_loadFile() - file %s was not found.", mFilename );
return;

View file

@ -27,6 +27,7 @@
#include "console/consoleTypes.h"
#include "console/engineAPI.h"
#include "collision/boxConvex.h"
#include "console/script.h"
#include "core/stream/bitStream.h"
#include "math/mathIO.h"

View file

@ -22,6 +22,7 @@
//-----------------------------------------------------------------------------
#include "Verve/Core/VDataTable.h"
#include "console/script.h"
#include "console/simObject.h"
//-----------------------------------------------------------------------------
@ -228,7 +229,7 @@ bool VDataTable::getValue( SimObject *pObject, const String &pFieldName, String
case VDataTable::k_TypeExpression :
{
// Evaluate.
pValue = Con::evaluate( fieldValue, false ).getString();
pValue = Con::evaluate( fieldValue, false ).value.getString();
} break;

View file

@ -26,6 +26,7 @@
#include "Verve/Extension/Script/VScriptEvent.h"
#include "console/consoleTypes.h"
#include "console/script.h"
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT( VScriptEvent );

View file

@ -26,9 +26,9 @@
#include "afx/arcaneFX.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "T3D/gameBase/gameConnection.h"
#include "math/mathIO.h"
#include "console/compiler.h"
#include "afx/afxConstraint.h"
#include "afx/afxChoreographer.h"
@ -108,12 +108,11 @@ bool afxChoreographerData::preload(bool server, String &errorStr)
if (!server && client_script_file != ST_NULLSTRING)
{
Compiler::gSyntaxError = false;
Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0);
if (Compiler::gSyntaxError)
Con::EvalResult result = Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0);
if (!result.valid)
{
Con::errorf("afxChoreographerData: failed to exec clientScriptFile \"%s\" -- syntax error", client_script_file);
Compiler::gSyntaxError = false;
}
}

View file

@ -31,8 +31,9 @@
#include "T3D/gameBase/gameProcess.h"
#include "T3D/player.h"
#include "math/mathUtils.h"
#include "console/compiler.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "afx/afxChoreographer.h"
#include "afx/afxSelectron.h"
@ -672,7 +673,7 @@ DefineEngineFunction(wasSyntaxError, bool, (),,
"for detecting syntax errors after reloading a script.\n\n"
"@ingroup AFX")
{
return Compiler::gSyntaxError;
return Con::getLastEvalResult().valid == false;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//

View file

@ -26,8 +26,8 @@
#include <typeinfo>
#include "afx/arcaneFX.h"
#include "console/compiler.h"
#include "T3D/player.h"
#include "console/script.h"
#include "afx/afxEffectDefs.h"
#include "afx/afxPhrase.h"
@ -314,13 +314,10 @@ void afxEA_PhraseEffect::trigger_new_phrase()
}
b[0] = '\0';
Compiler::gSyntaxError = false;
//Con::errorf("EVAL [%s]", avar("%s;", buffer));
Con::evaluate(avar("%s;", buffer), false, 0);
if (Compiler::gSyntaxError)
Con::EvalResult result = Con::evaluate(avar("%s;", buffer), false, 0);
if (!result.valid)
{
Con::errorf("onTriggerCommand \"%s\" -- syntax error", phrase_fx_data->on_trig_cmd);
Compiler::gSyntaxError = false;
}
}

View file

@ -61,6 +61,7 @@
// For the TickMs define... fix this for T2D...
#include "T3D/gameBase/processList.h"
#include "cinterface/cinterface.h"
#include "console/script.h"
#ifdef TORQUE_ENABLE_VFS
#include "platform/platformVFS.h"

View file

@ -107,6 +107,7 @@
#include "sim/netInterface.h"
// cafTODO: breaks T2D
#include "console/script.h"
#include "T3D/gameBase/gameConnection.h"
// This is basically the server query protocol version now:
@ -2020,7 +2021,7 @@ static void handleGameInfoRequest( const NetAddress* address, U32 key, U8 flags
out->writeString( Con::getVariable( "pref::Server::Info" ) );
else
writeCString( out, Con::getVariable( "pref::Server::Info" ) );
writeLongCString( out, Con::evaluate( "onServerInfoQuery();" ) );
writeLongCString( out, Con::executef( "onServerInfoQuery" ) );
BitStream::sendPacketStream(address);
}

View file

@ -23,6 +23,7 @@
#include "c_controlInterface.h"
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
#include "console/simSet.h"
#include "app/mainLoop.h"
#include "windowManager/platformWindow.h"
@ -50,7 +51,7 @@ extern "C" {
// reset the engine, unloading any current level and returning to the main menu
void torque_reset()
{
Con::evaluate("disconnect();");
Con::executef("disconnect");
}
// initialize Torque 3D including argument handling
@ -119,7 +120,7 @@ extern "C" {
// signal an engine shutdown (as with the quit(); console command)
void torque_enginesignalshutdown()
{
Con::evaluate("quit();");
Con::executef("quit");
}
// shutdown the engine

View file

@ -21,7 +21,6 @@
//-----------------------------------------------------------------------------
#include "cinterface.h"
#include "console/compiler.h"
#include "windowManager/platformWindow.h"
CInterface& CInterface::GetCInterface()

View file

@ -28,16 +28,16 @@
#include "console/consoleObject.h"
#include "console/consoleParser.h"
#include "core/stream/fileStream.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "console/consoleTypes.h"
#include "console/telnetDebugger.h"
#include "console/simBase.h"
#include "console/compiler.h"
#include "console/stringStack.h"
#include "console/ICallMethod.h"
#include "console/engineAPI.h"
#include <stdarg.h>
#include "returnBuffer.h"
#include "platform/threads/mutex.h"
#include "core/util/journal/journal.h"
#include "cinterface/cinterface.h"
@ -72,13 +72,10 @@ char* ConsoleValue::convertToBuffer() const
const char* ConsoleValue::getConsoleData() const
{
return Con::getData(type, ct->dataPtr, 0, ct->enumTable);
return Con::getData(ct->consoleType, ct->dataPtr, 0, ct->enumTable);
}
ConsoleDocFragment* ConsoleDocFragment::smFirst;
ExprEvalState gEvalState;
StmtNode *gStatementList;
StmtNode *gAnonFunctionList;
U32 gAnonFunctionID = 0;
ConsoleConstructor *ConsoleConstructor::mFirst = NULL;
bool gWarnUndefinedScriptVariables;
@ -565,7 +562,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw
// In the global namespace, we can complete on global vars as well as functions.
if (inputBuffer[completionBaseStart] == '$')
{
newText = gEvalState.globalVars.tabComplete(inputBuffer + completionBaseStart, completionBaseLen, forwardTab);
newText = gGlobalVars.tabComplete(inputBuffer + completionBaseStart, completionBaseLen, forwardTab);
}
else
{
@ -665,9 +662,9 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co
char buffer[8192] = {};
U32 offset = 0;
if( gEvalState.traceOn && gEvalState.getStackDepth() > 0 )
if( gTraceOn && !getFrameStack().empty())
{
offset = gEvalState.getStackDepth() * 3;
offset = getFrameStack().size() * 3;
for(U32 i = 0; i < offset; i++)
buffer[i] = ' ';
}
@ -831,41 +828,25 @@ bool getVariableObjectField(const char *name, SimObject **object, const char **f
return false;
}
Dictionary::Entry *getLocalVariableEntry(const char *name)
{
name = prependPercent(name);
return gEvalState.getCurrentFrame().lookup(StringTable->insert(name));
}
Dictionary::Entry *getVariableEntry(const char *name)
{
name = prependDollar(name);
return gEvalState.globalVars.lookup(StringTable->insert(name));
return gGlobalVars.lookup(StringTable->insert(name));
}
Dictionary::Entry *addVariableEntry(const char *name)
{
name = prependDollar(name);
return gEvalState.globalVars.add(StringTable->insert(name));
return gGlobalVars.add(StringTable->insert(name));
}
Dictionary::Entry *getAddVariableEntry(const char *name)
{
name = prependDollar(name);
StringTableEntry stName = StringTable->insert(name);
Dictionary::Entry *entry = gEvalState.globalVars.lookup(stName);
Dictionary::Entry *entry = gGlobalVars.lookup(stName);
if (!entry)
entry = gEvalState.globalVars.add(stName);
return entry;
}
Dictionary::Entry *getAddLocalVariableEntry(const char *name)
{
name = prependPercent(name);
StringTableEntry stName = StringTable->insert(name);
Dictionary::Entry *entry = gEvalState.getCurrentFrame().lookup(stName);
if (!entry)
entry = gEvalState.getCurrentFrame().add(stName);
entry = gGlobalVars.add(stName);
return entry;
}
@ -881,7 +862,7 @@ void setVariable(const char *name, const char *value)
else
{
name = prependDollar(name);
gEvalState.globalVars.setVariable(StringTable->insert(name), value);
gGlobalVars.setVariable(StringTable->insert(name), value);
}
}
@ -988,7 +969,7 @@ void stripColorChars(char* line)
}
}
//
//
const char *getObjectTokenField(const char *name)
{
const char *dot = dStrchr(name, '.');
@ -1046,7 +1027,7 @@ const char *getLocalVariable(const char *name)
{
name = prependPercent(name);
return gEvalState.getCurrentFrame().getVariable(StringTable->insert(name));
return Con::getCurrentStackFrame()->getVariable(StringTable->insert(name));
}
bool getBoolVariable(const char *varName, bool def)
@ -1099,7 +1080,7 @@ void addVariable( const char *name,
void *dptr,
const char* usage )
{
gEvalState.globalVars.addVariable( name, type, dptr, usage );
gGlobalVars.addVariable( name, type, dptr, usage );
}
void addConstant( const char *name,
@ -1107,24 +1088,24 @@ void addConstant( const char *name,
const void *dptr,
const char* usage )
{
Dictionary::Entry* entry = gEvalState.globalVars.addVariable( name, type, const_cast< void* >( dptr ), usage );
Dictionary::Entry* entry = gGlobalVars.addVariable( name, type, const_cast< void* >( dptr ), usage );
entry->mIsConstant = true;
}
bool removeVariable(const char *name)
{
name = StringTable->lookup(prependDollar(name));
return name!=0 && gEvalState.globalVars.removeVariable(name);
return name!=0 && gGlobalVars.removeVariable(name);
}
void addVariableNotify( const char *name, const NotifyDelegate &callback )
{
gEvalState.globalVars.addVariableNotify( name, callback );
gGlobalVars.addVariableNotify( name, callback );
}
void removeVariableNotify( const char *name, const NotifyDelegate &callback )
{
gEvalState.globalVars.removeVariableNotify( name, callback );
gGlobalVars.removeVariableNotify( name, callback );
}
//---------------------------------------------------------------------------
@ -1206,359 +1187,6 @@ void addCommand( const char *name,BoolCallback cb,const char *usage, S32 minArgs
Namespace::global()->addCommand( StringTable->insert(name), cb, usage, minArgs, maxArgs, isToolOnly, header );
}
bool executeFile(const char* fileName, bool noCalls, bool journalScript)
{
bool journal = false;
char scriptFilenameBuffer[1024];
U32 execDepth = 0;
U32 journalDepth = 1;
execDepth++;
if (journalDepth >= execDepth)
journalDepth = execDepth + 1;
else
journal = true;
bool ret = false;
if (journalScript && !journal)
{
journal = true;
journalDepth = execDepth;
}
// Determine the filename we actually want...
Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), fileName);
// since this function expects a script file reference, if it's a .dso
// lets terminate the string before the dso so it will act like a .tscript
if (dStrEndsWith(scriptFilenameBuffer, ".dso"))
{
scriptFilenameBuffer[dStrlen(scriptFilenameBuffer) - dStrlen(".dso")] = '\0';
}
// Figure out where to put DSOs
StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
const char *ext = dStrrchr(scriptFilenameBuffer, '.');
if (!ext)
{
// Try appending the default script extension and see if that succeeds
if (executeFile(fileName + String("." TORQUE_SCRIPT_EXTENSION), noCalls, journalScript))
{
return true;
}
// We need an extension!
Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file name %s.", scriptFilenameBuffer);
execDepth--;
return false;
}
// Check Editor Extensions
bool isEditorScript = false;
// If the script file extension is '.ed.tscript' then compile it to a different compiled extension
if (dStricmp(ext, "." TORQUE_SCRIPT_EXTENSION) == 0)
{
const char* ext2 = ext - 3;
if (dStricmp(ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0)
isEditorScript = true;
}
else if (dStricmp(ext, ".gui") == 0)
{
const char* ext2 = ext - 3;
if (dStricmp(ext2, ".ed.gui") == 0)
isEditorScript = true;
}
StringTableEntry scriptFileName = StringTable->insert(scriptFilenameBuffer);
// Is this a file we should compile? (anything in the prefs path should not be compiled)
StringTableEntry prefsPath = Platform::getPrefsPath();
bool compiled = dStricmp(ext, ".mis") && !journal && !Con::getBoolVariable("Scripts::ignoreDSOs");
// [tom, 12/5/2006] stripBasePath() fucks up if the filename is not in the exe
// path, current directory or prefs path. Thus, getDSOFilename() will also screw
// up and so this allows the scripts to still load but without a DSO.
if (Platform::isFullPath(Platform::stripBasePath(scriptFilenameBuffer)))
compiled = false;
// [tom, 11/17/2006] It seems to make sense to not compile scripts that are in the
// prefs directory. However, getDSOPath() can handle this situation and will put
// the dso along with the script to avoid name clashes with tools/game dsos.
if ((dsoPath && *dsoPath == 0) || (prefsPath && prefsPath[0] && dStrnicmp(scriptFileName, prefsPath, dStrlen(prefsPath)) == 0))
compiled = false;
// If we're in a journaling mode, then we will read the script
// from the journal file.
if (journal && Journal::IsPlaying())
{
char fileNameBuf[256];
bool fileRead = false;
U32 fileSize;
Journal::ReadString(fileNameBuf);
Journal::Read(&fileRead);
if (!fileRead)
{
Con::errorf(ConsoleLogEntry::Script, "Journal script read (failed) for %s", fileNameBuf);
execDepth--;
return false;
}
Journal::Read(&fileSize);
char *script = new char[fileSize + 1];
Journal::Read(fileSize, script);
script[fileSize] = 0;
Con::printf("Executing (journal-read) %s.", scriptFileName);
CodeBlock *newCodeBlock = new CodeBlock();
newCodeBlock->compileExec(scriptFileName, script, noCalls, 0);
delete[] script;
delete newCodeBlock;
execDepth--;
return true;
}
// Ok, we let's try to load and compile the script.
Torque::FS::FileNodeRef scriptFile = Torque::FS::GetFileNode(scriptFileName);
Torque::FS::FileNodeRef dsoFile;
// ResourceObject *rScr = gResourceManager->find(scriptFileName);
// ResourceObject *rCom = NULL;
char nameBuffer[512];
char* script = NULL;
U32 version;
Stream *compiledStream = NULL;
Torque::Time scriptModifiedTime, dsoModifiedTime;
// Check here for .edso
bool edso = false;
if (dStricmp(ext, ".edso") == 0 && scriptFile != NULL)
{
edso = true;
dsoFile = scriptFile;
scriptFile = NULL;
dsoModifiedTime = dsoFile->getModifiedTime();
dStrcpy(nameBuffer, scriptFileName, 512);
}
// If we're supposed to be compiling this file, check to see if there's a DSO
if (compiled && !edso)
{
const char *filenameOnly = dStrrchr(scriptFileName, '/');
if (filenameOnly)
++filenameOnly;
else
filenameOnly = scriptFileName;
char pathAndFilename[1024];
Platform::makeFullPathName(filenameOnly, pathAndFilename, sizeof(pathAndFilename), dsoPath);
if (isEditorScript)
dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".edso", NULL);
else
dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".dso", NULL);
dsoFile = Torque::FS::GetFileNode(nameBuffer);
if (scriptFile != NULL)
scriptModifiedTime = scriptFile->getModifiedTime();
if (dsoFile != NULL)
dsoModifiedTime = dsoFile->getModifiedTime();
}
// Let's do a sanity check to complain about DSOs in the future.
//
// MM: This doesn't seem to be working correctly for now so let's just not issue
// the warning until someone knows how to resolve it.
//
//if(compiled && rCom && rScr && Platform::compareFileTimes(comModifyTime, scrModifyTime) < 0)
//{
//Con::warnf("exec: Warning! Found a DSO from the future! (%s)", nameBuffer);
//}
// If we had a DSO, let's check to see if we should be reading from it.
//MGT: fixed bug with dsos not getting recompiled correctly
//Note: Using Nathan Martin's version from the forums since its easier to read and understand
if (compiled && dsoFile != NULL && (scriptFile == NULL || (dsoModifiedTime >= scriptModifiedTime)))
{ //MGT: end
compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
if (compiledStream)
{
// Check the version!
compiledStream->read(&version);
if (version != Con::DSOVersion)
{
Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
delete compiledStream;
compiledStream = NULL;
}
}
}
// If we're journalling, let's write some info out.
if (journal && Journal::IsRecording())
Journal::WriteString(scriptFileName);
if (scriptFile != NULL && !compiledStream)
{
// If we have source but no compiled version, then we need to compile
// (and journal as we do so, if that's required).
void *data;
U32 dataSize = 0;
Torque::FS::ReadFile(scriptFileName, data, dataSize, true);
if (journal && Journal::IsRecording())
Journal::Write(bool(data != NULL));
if (data == NULL)
{
Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file %s.", scriptFileName);
execDepth--;
return false;
}
else
{
if (!dataSize)
{
execDepth--;
return false;
}
script = (char *)data;
if (journal && Journal::IsRecording())
{
Journal::Write(dataSize);
Journal::Write(dataSize, data);
}
}
#ifndef TORQUE_NO_DSO_GENERATION
if (compiled)
{
// compile this baddie.
#ifdef TORQUE_DEBUG
Con::printf("Compiling %s...", scriptFileName);
#endif
CodeBlock *code = new CodeBlock();
code->compile(nameBuffer, scriptFileName, script);
delete code;
code = NULL;
compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
if (compiledStream)
{
compiledStream->read(&version);
}
else
{
// We have to exit out here, as otherwise we get double error reports.
delete[] script;
execDepth--;
return false;
}
}
#endif
}
else
{
if (journal && Journal::IsRecording())
Journal::Write(bool(false));
}
if (compiledStream)
{
// Delete the script object first to limit memory used
// during recursive execs.
delete[] script;
script = 0;
// We're all compiled, so let's run it.
#ifdef TORQUE_DEBUG
Con::printf("Loading compiled script %s.", scriptFileName);
#endif
CodeBlock *code = new CodeBlock;
code->read(scriptFileName, *compiledStream);
delete compiledStream;
code->exec(0, scriptFileName, NULL, 0, NULL, noCalls, NULL, 0);
delete code;
ret = true;
}
else
if (scriptFile)
{
// No compiled script, let's just try executing it
// directly... this is either a mission file, or maybe
// we're on a readonly volume.
#ifdef TORQUE_DEBUG
Con::printf("Executing %s.", scriptFileName);
#endif
CodeBlock *newCodeBlock = new CodeBlock();
StringTableEntry name = StringTable->insert(scriptFileName);
newCodeBlock->compileExec(name, script, noCalls, 0);
ret = true;
}
else
{
// Don't have anything.
Con::warnf(ConsoleLogEntry::Script, "Missing file: %s!", scriptFileName);
ret = false;
}
delete[] script;
execDepth--;
return ret;
}
ConsoleValue evaluate(const char* string, bool echo, const char *fileName)
{
ConsoleStackFrameSaver stackSaver;
stackSaver.save();
if (echo)
{
if (string[0] == '%')
Con::printf("%s", string);
else
Con::printf("%s%s", getVariable( "$Con::Prompt" ), string);
}
if(fileName)
fileName = StringTable->insert(fileName);
CodeBlock *newCodeBlock = new CodeBlock();
return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
}
//------------------------------------------------------------------------------
ConsoleValue evaluatef(const char* string, ...)
{
ConsoleStackFrameSaver stackSaver;
stackSaver.save();
char buffer[4096];
va_list args;
va_start(args, string);
dVsprintf(buffer, sizeof(buffer), string, args);
va_end(args);
CodeBlock *newCodeBlock = new CodeBlock();
return newCodeBlock->compileExec(NULL, buffer, false, 0);
}
//------------------------------------------------------------------------------
// Internal execute for global function which does not save the stack
@ -1598,7 +1226,7 @@ ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[])
return std::move(ConsoleValue());
}
return std::move(ent->execute(argc, argv, &gEvalState));
return std::move(ent->execute(argc, argv, NULL));
}
ConsoleValue execute(S32 argc, ConsoleValue argv[])
@ -1701,10 +1329,7 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a
// Twiddle %this argument
argv[1].setInt(ident);
SimObject *save = gEvalState.thisObject;
gEvalState.thisObject = object;
ConsoleValue ret = std::move(ent->execute(argc, argv, &gEvalState));
gEvalState.thisObject = save;
ConsoleValue ret = std::move(ent->execute(argc, argv, object));
// Twiddle it back
argv[1].setString(oldIdent);
@ -1810,6 +1435,84 @@ void setLogMode(S32 newMode)
}
}
//------------------------------------------------------------------------------
ReturnBuffer retBuffer;
char* getReturnBuffer(U32 bufferSize)
{
return retBuffer.getBuffer(bufferSize);
}
char* getReturnBuffer(const char* stringToCopy)
{
U32 len = dStrlen(stringToCopy) + 1;
char* ret = retBuffer.getBuffer(len);
dMemcpy(ret, stringToCopy, len);
return ret;
}
char* getReturnBuffer(const String& str)
{
const U32 size = str.size();
char* ret = retBuffer.getBuffer(size);
dMemcpy(ret, str.c_str(), size);
return ret;
}
char* getReturnBuffer(const StringBuilder& str)
{
char* buffer = Con::getReturnBuffer(str.length() + 1);
str.copy(buffer);
buffer[str.length()] = '\0';
return buffer;
}
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;
}
char* getBoolArg(bool arg)
{
char* ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%d", arg);
return ret;
}
char* getStringArg(const char* arg)
{
U32 len = dStrlen(arg) + 1;
char* ret = STR.getArgBuffer(len);
dMemcpy(ret, arg, len);
return ret;
}
char* getStringArg(const String& arg)
{
const U32 size = arg.size();
char* ret = STR.getArgBuffer(size);
dMemcpy(ret, arg.c_str(), size);
return ret;
}
//------------------------------------------------------------------------------
Namespace *lookupNamespace(const char *ns)
{
if(!ns)
@ -1911,7 +1614,7 @@ bool isCurrentScriptToolScript()
#ifndef TORQUE_TOOLS
return false;
#else
const StringTableEntry cbFullPath = CodeBlock::getCurrentCodeBlockFullPath();
const StringTableEntry cbFullPath = getCurrentScriptModulePath();
if(cbFullPath == NULL)
return false;
const StringTableEntry exePath = Platform::getMainDotCsDir();
@ -1922,6 +1625,20 @@ bool isCurrentScriptToolScript()
//------------------------------------------------------------------------------
bool isScriptFile(const char* pFilePath)
{
return (Torque::FS::IsFile(pFilePath)
|| Torque::FS::IsFile(pFilePath + String(".dso"))
|| Torque::FS::IsFile(pFilePath + String(".mis"))
|| Torque::FS::IsFile(pFilePath + String(".mis.dso"))
|| Torque::FS::IsFile(pFilePath + String(".gui"))
|| Torque::FS::IsFile(pFilePath + String(".gui.dso"))
|| Torque::FS::IsFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION))
|| Torque::FS::IsFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION) + String(".dso")));
}
//------------------------------------------------------------------------------
StringTableEntry getModNameFromPath(const char *path)
{
if(path == NULL || *path == 0)
@ -2248,7 +1965,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
if (leadingToken == '.')
{
// Fetch the code-block file-path.
const StringTableEntry codeblockFullPath = CodeBlock::getCurrentCodeBlockFullPath();
const StringTableEntry codeblockFullPath = getCurrentScriptModulePath();
// Do we have a code block full path?
if (codeblockFullPath == NULL)

View file

@ -128,6 +128,7 @@ enum ConsoleValueType
struct ConsoleValueConsoleType
{
S32 consoleType;
void* dataPtr;
EnumTable* enumTable;
};
@ -340,8 +341,8 @@ public:
TORQUE_FORCEINLINE void setConsoleData(S32 consoleType, void* dataPtr, const EnumTable* enumTable)
{
cleanupData();
type = ConsoleValueType::cvSTEntry;
ct = new ConsoleValueConsoleType{ dataPtr, const_cast<EnumTable*>(enumTable) };
type = ConsoleValueType::cvConsoleValueType;
ct = new ConsoleValueConsoleType{ consoleType, dataPtr, const_cast<EnumTable*>(enumTable) };
}
TORQUE_FORCEINLINE S32 getType() const
@ -364,6 +365,18 @@ public:
return type >= ConsoleValueType::cvConsoleValueType;
}
TORQUE_FORCEINLINE ConsoleValueConsoleType* getConsoleType() const
{
if(type >= ConsoleValueType::cvConsoleValueType)
{
return ct;
}
else
{
return NULL;
}
}
TORQUE_FORCEINLINE void setFastFloat(F64 flt)
{
type = ConsoleValueType::cvFloat;
@ -626,6 +639,7 @@ namespace Con
StringTableEntry getPathExpandoValue(U32 expandoIndex);
bool isCurrentScriptToolScript();
bool isScriptFile(const char* path);
StringTableEntry getModNameFromPath(const char *path);
@ -918,30 +932,6 @@ namespace Con
ConsoleValue execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly = false);
/// Executes a script file and compiles it for use in script.
///
/// @param string File name that is the script to be executed and compiled.
/// @param fileName Path to the file to execute
/// @param noCalls Deprecated
/// @param journalScript Deprecated
///
/// @return True if the script was successfully executed, false if not.
bool executeFile(const char* fileName, bool noCalls, bool journalScript);
/// Evaluate an arbitrary chunk of code.
///
/// @param string Buffer containing code to execute.
/// @param echo Should we echo the string to the console?
/// @param fileName Indicate what file this code is coming from; used in error reporting and such.
/// NOTE: This function restores the console stack on return.
ConsoleValue evaluate(const char* string, bool echo = false, const char *fileName = NULL);
/// Evaluate an arbitrary line of script.
///
/// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
/// NOTE: This function restores the console stack on return.
ConsoleValue evaluatef(const char* string, ...);
/// @}
/// @name Console Function Implementation Helpers

View file

@ -23,14 +23,12 @@
#include "platform/platform.h"
#include "console/console.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "core/strings/findMatch.h"
#include "console/consoleInternal.h"
#include "console/consoleObject.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "core/frameAllocator.h"
#include "console/engineAPI.h"
@ -272,7 +270,7 @@ void Namespace::printNamespaceEntries(Namespace * g, bool dumpScript, bool dumpE
}
else if(ewalk->mFunctionOffset) // If it's a builtin function...
{
String args = ewalk->mCode->getFunctionArgs(ewalk->mFunctionOffset);
String args = ewalk->mModule->getFunctionArgs(ewalk->mFunctionName, ewalk->mFunctionOffset);
printClassMethod(false, typeNames[ewalk->mType], ewalk->mFunctionName, args, "");
}
else

View file

@ -24,18 +24,17 @@
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
#include "console/ast.h"
#ifndef _CONSOLFUNCTIONS_H_
#include "console/consoleFunctions.h"
#endif
#include "script.h"
#include "cinterface/cinterface.h"
#include "core/strings/findMatch.h"
#include "core/strings/stringUnit.h"
#include "core/strings/unicode.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "platform/platformInput.h"
#include "core/util/journal/journal.h"
#include "gfx/gfxEnums.h"
@ -43,6 +42,7 @@
#include "core/color.h"
#include "math/mPoint3.h"
#include "math/mathTypes.h"
#include "torquescript/runtime.h"
// This is a temporary hack to get tools using the library to
// link in this module which contains no other references.
@ -2330,63 +2330,7 @@ DefineEngineFunction( compile, bool, ( const char* fileName, bool overrideNoDSO
"@see exec\n"
"@ingroup Scripting" )
{
Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
// Figure out where to put DSOs
StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
if(dsoPath && *dsoPath == 0)
return false;
// If the script file extention is '.ed.tscript' then compile it to a different compiled extention
bool isEditorScript = false;
const char *ext = dStrrchr( scriptFilenameBuffer, '.' );
if( ext && ( dStricmp( ext, "." TORQUE_SCRIPT_EXTENSION) == 0 ) )
{
const char* ext2 = ext - 3;
if( dStricmp( ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0 )
isEditorScript = true;
}
else if( ext && ( dStricmp( ext, ".gui" ) == 0 ) )
{
const char* ext2 = ext - 3;
if( dStricmp( ext2, ".ed.gui" ) == 0 )
isEditorScript = true;
}
const char *filenameOnly = dStrrchr(scriptFilenameBuffer, '/');
if(filenameOnly)
++filenameOnly;
else
filenameOnly = scriptFilenameBuffer;
char nameBuffer[512];
if( isEditorScript )
dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".edso", NULL);
else
dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".dso", NULL);
void *data = NULL;
U32 dataSize = 0;
Torque::FS::ReadFile(scriptFilenameBuffer, data, dataSize, true);
if(data == NULL)
{
Con::errorf(ConsoleLogEntry::Script, "compile: invalid script file %s.", scriptFilenameBuffer);
return false;
}
const char *script = static_cast<const char *>(data);
#ifdef TORQUE_DEBUG
Con::printf("Compiling %s...", scriptFilenameBuffer);
#endif
CodeBlock *code = new CodeBlock();
code->compile(nameBuffer, scriptFilenameBuffer, script, overrideNoDSO);
delete code;
delete[] script;
return true;
return TorqueScript::getRuntime()->compile(fileName, overrideNoDSO);
}
//-----------------------------------------------------------------------------
@ -2410,12 +2354,12 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou
DefineEngineFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" )
{
ConsoleValue returnValue = Con::evaluate(consoleString, false, NULL);
Con::EvalResult returnValue = Con::evaluate(consoleString, false, NULL);
return Con::getReturnBuffer(returnValue.getString());
return Con::getReturnBuffer(returnValue.value.getString());
}
DefineEngineFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n"
DefineEngineFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n"
"@brief Returns the value of the named variable or an empty string if not found.\n\n"
"@varName Name of the variable to search for\n"
"@return Value contained by varName, \"\" if the variable does not exist\n"
@ -2589,15 +2533,15 @@ DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varVal
else if (name[0] == '%')
{
// Look up a local variable
if( gEvalState.getStackDepth() > 0 )
if( Con::getFrameStack().size() > 0 )
{
Dictionary::Entry* ent = gEvalState.getCurrentFrame().lookup(name);
Dictionary::Entry* ent = Con::getCurrentStackFrame()->lookup(name);
if (ent)
return true;
else if (!String::isEmpty(varValue))
{
gEvalState.getCurrentFrame().setVariable(name, varValue);
Con::getCurrentStackFrame()->setVariable(name, varValue);
}
}
else
@ -2606,13 +2550,13 @@ DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varVal
else if (name[0] == '$')
{
// Look up a global value
Dictionary::Entry* ent = gEvalState.globalVars.lookup(name);
Dictionary::Entry* ent = Con::gGlobalVars.lookup(name);
if (ent)
return true;
else if (!String::isEmpty(varValue))
{
gEvalState.globalVars.setVariable(name, varValue);
Con::gGlobalVars.setVariable(name, varValue);
}
}
else
@ -2739,7 +2683,7 @@ DefineEngineFunction( export, void, ( const char* pattern, const char* filename,
else
filename = NULL;
gEvalState.globalVars.exportVariables( pattern, filename, append );
Con::gGlobalVars.exportVariables( pattern, filename, append );
}
//-----------------------------------------------------------------------------
@ -2756,7 +2700,7 @@ DefineEngineFunction( deleteVariables, void, ( const char* pattern ),,
"@see strIsMatchExpr\n"
"@ingroup Scripting" )
{
gEvalState.globalVars.deleteVariables( pattern );
Con::gGlobalVars.deleteVariables( pattern );
}
//-----------------------------------------------------------------------------
@ -2769,8 +2713,8 @@ DefineEngineFunction( trace, void, ( bool enable ), ( true ),
"@param enable New setting for script trace execution, on by default.\n"
"@ingroup Debugging" )
{
gEvalState.traceOn = enable;
Con::printf( "Console trace %s", gEvalState.traceOn ? "enabled." : "disabled." );
Con::gTraceOn = enable;
Con::printf( "Console trace %s", Con::gTraceOn ? "enabled." : "disabled." );
}
//-----------------------------------------------------------------------------

View file

@ -25,13 +25,11 @@
#include "platform/platform.h"
#include "console/console.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "core/strings/findMatch.h"
#include "console/consoleInternal.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "console/engineAPI.h"
//#define DEBUG_SPEW
@ -183,13 +181,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
for (s = sortList.begin(); s != sortList.end(); s++)
{
switch ((*s)->type)
switch ((*s)->value.getType())
{
case Entry::TypeInternalInt:
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
case ConsoleValueType::cvInteger:
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->getIntValue(), cat);
break;
case Entry::TypeInternalFloat:
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
case ConsoleValueType::cvFloat:
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->getFloatValue(), cat);
break;
default:
expandEscape(expandBuffer, (*s)->getStringValue());
@ -243,7 +241,7 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
if (values)
{
switch ((*s)->type)
switch ((*s)->value.getType())
{
case ConsoleValueType::cvInteger:
case ConsoleValueType::cvFloat:
@ -375,18 +373,16 @@ Dictionary::Dictionary()
#pragma warning( disable : 4355 )
ownHashTable(this), // Warning with VC++ but this is safe.
#pragma warning( default : 4355 )
exprState(NULL),
scopeName(NULL),
scopeNamespace(NULL),
code(NULL),
module(NULL),
ip(0)
{
setState(NULL);
}
void Dictionary::setState(ExprEvalState *state, Dictionary* ref)
void Dictionary::setState(Dictionary* ref)
{
exprState = state;
if (ref)
{
hashTable = ref->hashTable;
@ -439,7 +435,7 @@ void Dictionary::reset()
scopeName = NULL;
scopeNamespace = NULL;
code = NULL;
module = NULL;
ip = 0;
}
@ -465,19 +461,11 @@ const char *Dictionary::tabComplete(const char *prevText, S32 baseLen, bool fFor
Dictionary::Entry::Entry(StringTableEntry in_name)
{
name = in_name;
type = TypeInternalString;
notify = NULL;
nextEntry = NULL;
mUsage = NULL;
mIsConstant = false;
mNext = NULL;
ival = 0;
fval = 0;
sval = NULL;
bufferLen = 0;
dataPtr = NULL;
enumTable = NULL;
}
Dictionary::Entry::~Entry()
@ -488,73 +476,11 @@ Dictionary::Entry::~Entry()
void Dictionary::Entry::reset()
{
name = NULL;
if (type <= TypeInternalString && sval != NULL)
dFree(sval);
value.reset();
if (notify)
delete notify;
}
void Dictionary::Entry::setStringValue(const char* value)
{
if (mIsConstant)
{
Con::errorf("Cannot assign value to constant '%s'.", name);
return;
}
if (type <= TypeInternalString)
{
// Let's not remove empty-string-valued global vars from the dict.
// If we remove them, then they won't be exported, and sometimes
// it could be necessary to export such a global. There are very
// few empty-string global vars so there's no performance-related
// need to remove them from the dict.
/*
if(!value[0] && name[0] == '$')
{
gEvalState.globalVars.remove(this);
return;
}
*/
U32 stringLen = dStrlen(value);
// If it's longer than 256 bytes, it's certainly not a number.
//
// (This decision may come back to haunt you. Shame on you if it
// does.)
if (stringLen < 256)
{
fval = dAtof(value);
ival = dAtoi(value);
}
else
{
fval = 0.f;
ival = 0;
}
type = TypeInternalString;
// may as well pad to the next cache line
U32 newLen = ((stringLen + 1) + 15) & ~15;
if (sval == NULL)
sval = (char*)dMalloc(newLen);
else if (newLen > bufferLen)
sval = (char*)dRealloc(sval, newLen);
bufferLen = newLen;
dStrcpy(sval, value, newLen);
}
else
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
// Fire off the notification if we have one.
if (notify)
notify->trigger();
}
const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
{
Entry *ent = lookup(name);
@ -630,17 +556,12 @@ Dictionary::Entry* Dictionary::addVariable(const char *name,
Entry *ent = add(StringTable->insert(name));
if (ent->type <= Entry::TypeInternalString && ent->sval != NULL)
dFree(ent->sval);
ent->mUsage = usage;
ent->type = type;
ent->dataPtr = dataPtr;
// Fetch enum table, if any.
ConsoleBaseType* conType = ConsoleBaseType::getType(type);
AssertFatal(conType, "Dictionary::addVariable - invalid console type");
ent->enumTable = conType->getEnumTable();
ent->value.setConsoleData(type, dataPtr, conType->getEnumTable());
return ent;
}
@ -680,158 +601,15 @@ void Dictionary::validate()
"Dictionary::validate() - Dictionary not owner of own hashtable!");
}
void ExprEvalState::pushFrame(StringTableEntry frameName, Namespace *ns, S32 registerCount)
Con::Module* Con::findScriptModuleForFile(const char* fileName)
{
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Pushing new frame for '%s' at %i",
frameName, mStackDepth);
#endif
if (mStackDepth + 1 > stack.size())
for (Con::Module* module : gScriptModules)
{
#ifdef DEBUG_SPEW
Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
#endif
stack.push_back(new Dictionary);
if (module->getName() == fileName) {
return module;
}
}
Dictionary& newFrame = *(stack[mStackDepth]);
newFrame.setState(this);
newFrame.scopeName = frameName;
newFrame.scopeNamespace = ns;
mStackDepth++;
currentVariable = NULL;
AssertFatal(!newFrame.getCount(), "ExprEvalState::pushFrame - Dictionary not empty!");
ConsoleValue* consoleValArray = new ConsoleValue[registerCount]();
localStack.push_back(ConsoleValueFrame(consoleValArray, false));
currentRegisterArray = &localStack.last();
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::popFrame()
{
AssertFatal(mStackDepth > 0, "ExprEvalState::popFrame - Stack Underflow!");
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Popping %sframe at %i",
getCurrentFrame().isOwner() ? "" : "shared ", mStackDepth - 1);
#endif
mStackDepth--;
stack[mStackDepth]->reset();
currentVariable = NULL;
const ConsoleValueFrame& frame = localStack.last();
localStack.pop_back();
if (!frame.isReference)
delete[] frame.values;
currentRegisterArray = localStack.size() ? &localStack.last() : NULL;
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::pushFrameRef(S32 stackIndex)
{
AssertFatal(stackIndex >= 0 && stackIndex < mStackDepth, "You must be asking for a valid frame!");
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Cloning frame from %i to %i",
stackIndex, mStackDepth);
#endif
if (mStackDepth + 1 > stack.size())
{
#ifdef DEBUG_SPEW
Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
#endif
stack.push_back(new Dictionary);
}
Dictionary& newFrame = *(stack[mStackDepth]);
newFrame.setState(this, stack[stackIndex]);
mStackDepth++;
currentVariable = NULL;
ConsoleValue* values = localStack[stackIndex].values;
localStack.push_back(ConsoleValueFrame(values, true));
currentRegisterArray = &localStack.last();
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::pushDebugFrame(S32 stackIndex)
{
pushFrameRef(stackIndex);
Dictionary& newFrame = *(stack[mStackDepth - 1]);
// debugger needs to know this info...
newFrame.scopeName = stack[stackIndex]->scopeName;
newFrame.scopeNamespace = stack[stackIndex]->scopeNamespace;
newFrame.code = stack[stackIndex]->code;
newFrame.ip = stack[stackIndex]->ip;
}
ExprEvalState::ExprEvalState()
{
VECTOR_SET_ASSOCIATION(stack);
globalVars.setState(this);
thisObject = NULL;
traceOn = false;
currentVariable = NULL;
mStackDepth = 0;
stack.reserve(64);
mShouldReset = false;
mResetLocked = false;
copyVariable = NULL;
currentRegisterArray = NULL;
}
ExprEvalState::~ExprEvalState()
{
// Delete callframes.
while (!stack.empty())
{
delete stack.last();
stack.decrement();
}
}
void ExprEvalState::validate()
{
AssertFatal(mStackDepth <= stack.size(),
"ExprEvalState::validate() - Stack depth pointing beyond last stack frame!");
for (U32 i = 0; i < stack.size(); ++i)
stack[i]->validate();
return NULL;
}
DefineEngineFunction(backtrace, void, (), ,
@ -842,35 +620,37 @@ DefineEngineFunction(backtrace, void, (), ,
{
U32 totalSize = 1;
for (U32 i = 0; i < gEvalState.getStackDepth(); i++)
for (U32 i = 0; i < Con::getFrameStack().size(); i++)
{
if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage)
totalSize += dStrlen(gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage) + 2;
if (gEvalState.stack[i]->scopeName)
totalSize += dStrlen(gEvalState.stack[i]->scopeName) + 3;
if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
totalSize += dStrlen(gEvalState.stack[i]->scopeNamespace->mName) + 2;
const Con::ConsoleFrame* frame = Con::getStackFrame(i);
if (frame->scopeNamespace && frame->scopeNamespace->mEntryList->mPackage)
totalSize += dStrlen(frame->scopeNamespace->mEntryList->mPackage) + 2;
if (frame->scopeName)
totalSize += dStrlen(frame->scopeName) + 3;
if (frame->scopeNamespace && frame->scopeNamespace->mName)
totalSize += dStrlen(frame->scopeNamespace->mName) + 2;
}
char *buf = Con::getReturnBuffer(totalSize);
buf[0] = 0;
for (U32 i = 0; i < gEvalState.getStackDepth(); i++)
for (U32 i = 0; i < Con::getFrameStack().size(); i++)
{
const Con::ConsoleFrame* frame = Con::getStackFrame(i);
dStrcat(buf, "->", totalSize);
if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage)
if (frame->scopeNamespace && frame->scopeNamespace->mEntryList->mPackage)
{
dStrcat(buf, "[", totalSize);
dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage, totalSize);
dStrcat(buf, frame->scopeNamespace->mEntryList->mPackage, totalSize);
dStrcat(buf, "]", totalSize);
}
if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
if (frame->scopeNamespace && frame->scopeNamespace->mName)
{
dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName, totalSize);
dStrcat(buf, frame->scopeNamespace->mName, totalSize);
dStrcat(buf, "::", totalSize);
}
if (gEvalState.stack[i]->scopeName)
dStrcat(buf, gEvalState.stack[i]->scopeName, totalSize);
if (frame->scopeName)
dStrcat(buf, frame->scopeName, totalSize);
}
Con::printf("BackTrace: %s", buf);
@ -878,7 +658,7 @@ DefineEngineFunction(backtrace, void, (), ,
Namespace::Entry::Entry()
{
mCode = NULL;
mModule = NULL;
mType = InvalidFunctionType;
mUsage = NULL;
mHeader = NULL;
@ -896,10 +676,10 @@ Namespace::Entry::Entry()
void Namespace::Entry::clear()
{
if (mCode)
if (mModule)
{
mCode->decRefCount();
mCode = NULL;
mModule->decRefCount();
mModule = NULL;
}
// Clean up usage strings generated for script functions.
@ -1233,15 +1013,15 @@ Namespace::Entry *Namespace::createLocalEntry(StringTableEntry name)
return ent;
}
void Namespace::addFunction(StringTableEntry name, CodeBlock *cb, U32 functionOffset, const char* usage, U32 lineNumber)
void Namespace::addFunction(StringTableEntry name, Con::Module *cb, U32 functionOffset, const char* usage, U32 lineNumber)
{
Entry *ent = createLocalEntry(name);
trashCache();
ent->mUsage = usage;
ent->mCode = cb;
ent->mModule = cb;
ent->mFunctionOffset = functionOffset;
ent->mCode->incRefCount();
ent->mModule->incRefCount();
ent->mType = Entry::ConsoleFunctionType;
ent->mFunctionLineNumber = lineNumber;
}
@ -1366,9 +1146,7 @@ void Namespace::markGroup(const char* name, const char* usage)
ent->cb.mGroupName = name;
}
extern S32 executeBlock(StmtNode *block, ExprEvalState *state);
ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalState *state)
ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject *thisObj)
{
STR.clearFunctionOffset();
@ -1376,7 +1154,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalSta
{
if (mFunctionOffset)
{
return std::move(mCode->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage));
return std::move(mModule->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage).value);
}
else
{
@ -1406,21 +1184,21 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalSta
{
case StringCallbackType:
{
const char* str = cb.mStringCallbackFunc(state->thisObject, argc, argv);
const char* str = cb.mStringCallbackFunc(thisObj, argc, argv);
result.setString(str);
break;
}
case IntCallbackType:
result.setInt(cb.mIntCallbackFunc(state->thisObject, argc, argv));
result.setInt(cb.mIntCallbackFunc(thisObj, argc, argv));
break;
case FloatCallbackType:
result.setFloat(cb.mFloatCallbackFunc(state->thisObject, argc, argv));
result.setFloat(cb.mFloatCallbackFunc(thisObj, argc, argv));
break;
case VoidCallbackType:
cb.mVoidCallbackFunc(state->thisObject, argc, argv);
cb.mVoidCallbackFunc(thisObj, argc, argv);
break;
case BoolCallbackType:
result.setBool(cb.mBoolCallbackFunc(state->thisObject, argc, argv));
result.setBool(cb.mBoolCallbackFunc(thisObj, argc, argv));
break;
}
@ -1704,7 +1482,7 @@ String Namespace::Entry::getArgumentsString() const
if (sFindArgumentListSubstring(mUsage, argListStart, argListEnd))
str.append(argListStart, argListEnd - argListStart);
else if (mType == ConsoleFunctionType && mCode)
else if (mType == ConsoleFunctionType && mModule)
{
// This isn't correct but the nonsense console stuff is set up such that all
// functions that have no function bodies are keyed to offset 0 to indicate "no code."
@ -1716,7 +1494,7 @@ String Namespace::Entry::getArgumentsString() const
if (!mFunctionOffset)
return "()";
String args = mCode->getFunctionArgs(mFunctionOffset);
String args = mModule->getFunctionArgs(mFunctionName, mFunctionOffset);
if (args.isEmpty())
return "()";

View file

@ -38,12 +38,12 @@
#ifndef _DATACHUNKER_H_
#include "core/dataChunker.h"
#endif
#include "module.h"
/// @ingroup console_system Console System
/// @{
class ExprEvalState;
struct FunctionDecl;
class CodeBlock;
class AbstractClassRep;
@ -125,7 +125,7 @@ public:
ConsoleFunctionHeader* mHeader;
/// The compiled script code if this is a script function.
CodeBlock* mCode;
Con::Module* mModule;
/// The offset in the compiled script code at which this function begins.
U32 mFunctionOffset;
@ -150,7 +150,7 @@ public:
void clear();
///
ConsoleValue execute(S32 argc, ConsoleValue* argv, ExprEvalState* state);
ConsoleValue execute(S32 argc, ConsoleValue* argv, SimObject* thisObj);
/// Return a one-line documentation text string for the function.
String getBriefDescription(String* outRemainingDocText = NULL) const;
@ -181,7 +181,7 @@ public:
Namespace();
~Namespace();
void addFunction(StringTableEntry name, CodeBlock* cb, U32 functionOffset, const char* usage = NULL, U32 lineNumber = 0);
void addFunction(StringTableEntry name, Con::Module* cb, U32 functionOffset, const char* usage = NULL, U32 lineNumber = 0);
void addCommand(StringTableEntry name, StringCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
void addCommand(StringTableEntry name, IntCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
void addCommand(StringTableEntry name, FloatCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
@ -286,16 +286,8 @@ public:
{
friend class Dictionary;
enum
{
TypeInternalInt = -3,
TypeInternalFloat = -2,
TypeInternalString = -1,
};
StringTableEntry name;
Entry *nextEntry;
S32 type;
typedef Signal<void()> NotifySignal;
@ -309,58 +301,17 @@ public:
/// Whether this is a constant that cannot be assigned to.
bool mIsConstant;
protected:
// NOTE: This is protected to ensure no one outside
// of this structure is messing with it.
#pragma warning( push )
#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
// An variable is either a real dynamic type or
// its one exposed from C++ using a data pointer.
//
// We use this nameless union and struct setup
// to optimize the memory usage.
union
{
struct
{
char* sval;
U32 ival; // doubles as strlen when type is TypeInternalString
F32 fval;
U32 bufferLen;
};
struct
{
/// The real data pointer.
void* dataPtr;
/// The enum lookup table for enumerated types.
const EnumTable* enumTable;
};
};
#pragma warning( pop ) // C4201
ConsoleValue value;
public:
Entry() {
name = NULL;
type = TypeInternalString;
notify = NULL;
nextEntry = NULL;
mUsage = NULL;
mIsConstant = false;
mNext = NULL;
ival = 0;
fval = 0;
sval = NULL;
bufferLen = 0;
dataPtr = NULL;
enumTable = NULL;
}
Entry(StringTableEntry name);
@ -370,32 +321,21 @@ public:
void reset();
inline ConsoleValue getValue() { return std::move(value); }
inline U32 getIntValue()
{
if (type <= TypeInternalString)
return ival;
else
return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
return value.getInt();
}
inline F32 getFloatValue()
{
if (type <= TypeInternalString)
return fval;
else
return dAtof(Con::getData(type, dataPtr, 0, enumTable));
return value.getFloat();
}
inline const char *getStringValue()
{
if (type == TypeInternalString)
return sval;
if (type == TypeInternalFloat)
return Con::getData(TypeF32, &fval, 0);
else if (type == TypeInternalInt)
return Con::getData(TypeS32, &ival, 0);
else
return Con::getData(type, dataPtr, 0, enumTable);
return value.getString();
}
void setIntValue(U32 val)
@ -406,21 +346,15 @@ public:
return;
}
if (type <= TypeInternalString)
if (value.isConsoleType())
{
fval = (F32)val;
ival = val;
if (sval != NULL)
{
dFree(sval);
sval = NULL;
}
type = TypeInternalInt;
const char* dptr = Con::getData(TypeS32, &val, 0);
ConsoleValueConsoleType* cvt = value.getConsoleType();
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
}
else
{
const char* dptr = Con::getData(TypeS32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
value.setInt(val);
}
// Fire off the notification if we have one.
@ -436,21 +370,15 @@ public:
return;
}
if (type <= TypeInternalString)
if (value.isConsoleType())
{
fval = val;
ival = static_cast<U32>(val);
if (sval != NULL)
{
dFree(sval);
sval = NULL;
}
type = TypeInternalFloat;
const char* dptr = Con::getData(TypeF32, &val, 0);
ConsoleValueConsoleType* cvt = value.getConsoleType();
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
}
else
{
const char* dptr = Con::getData(TypeF32, &val, 0);
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
value.setFloat(val);
}
// Fire off the notification if we have one.
@ -458,7 +386,29 @@ public:
notify->trigger();
}
void setStringValue(const char* value);
void setStringValue(const char* val)
{
if (mIsConstant)
{
Con::errorf("Cannot assign value to constant '%s'.", name);
return;
}
if (value.isConsoleType())
{
ConsoleValueConsoleType* cvt = value.getConsoleType();
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &val, cvt->enumTable);
}
else
{
value.setString(val);
}
// Fire off the notification if we have one.
if (notify)
notify->trigger();
}
};
struct HashTableData
@ -475,11 +425,10 @@ public:
HashTableData* hashTable;
HashTableData ownHashTable;
ExprEvalState *exprState;
StringTableEntry scopeName;
Namespace *scopeNamespace;
CodeBlock *code;
Con::Module *module;
U32 ip;
Dictionary();
@ -487,7 +436,7 @@ public:
Entry *lookup(StringTableEntry name);
Entry *add(StringTableEntry name);
void setState(ExprEvalState *state, Dictionary* ref = NULL);
void setState(Dictionary* ref = NULL);
void remove(Entry *);
void reset();
@ -547,126 +496,35 @@ struct ConsoleValueFrame
}
};
class ExprEvalState
{
public:
/// @name Expression Evaluation
/// @{
///
SimObject *thisObject;
Dictionary::Entry *currentVariable;
Dictionary::Entry *copyVariable;
bool traceOn;
U32 mStackDepth;
bool mShouldReset; ///< Designates if the value stack should be reset
bool mResetLocked; ///< mShouldReset will be set at the end
ExprEvalState();
~ExprEvalState();
/// @}
/// @name Stack Management
/// @{
/// The stack of callframes. The extra redirection is necessary since Dictionary holds
/// an interior pointer that will become invalid when the object changes address.
Vector< Dictionary* > stack;
S32 getTopOfStack() { return (S32)mStackDepth; }
Vector< ConsoleValueFrame > localStack;
ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
///
Dictionary globalVars;
void setCurVarName(StringTableEntry name);
void setCurVarNameCreate(StringTableEntry name);
S32 getIntVariable();
F64 getFloatVariable();
const char *getStringVariable();
void setIntVariable(S32 val);
void setFloatVariable(F64 val);
void setStringVariable(const char *str);
TORQUE_FORCEINLINE S32 getLocalIntVariable(S32 reg)
{
return currentRegisterArray->values[reg].getInt();
}
TORQUE_FORCEINLINE F64 getLocalFloatVariable(S32 reg)
{
return currentRegisterArray->values[reg].getFloat();
}
TORQUE_FORCEINLINE const char* getLocalStringVariable(S32 reg)
{
return currentRegisterArray->values[reg].getString();
}
TORQUE_FORCEINLINE void setLocalIntVariable(S32 reg, S64 val)
{
currentRegisterArray->values[reg].setInt(val);
}
TORQUE_FORCEINLINE void setLocalFloatVariable(S32 reg, F64 val)
{
currentRegisterArray->values[reg].setFloat(val);
}
TORQUE_FORCEINLINE void setLocalStringVariable(S32 reg, const char* val, S32 len)
{
currentRegisterArray->values[reg].setString(val, len);
}
TORQUE_FORCEINLINE void setLocalStringTableEntryVariable(S32 reg, StringTableEntry val)
{
currentRegisterArray->values[reg].setStringTableEntry(val);
}
TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val)
{
currentRegisterArray->values[reg] = std::move(val);
}
void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
void popFrame();
/// Puts a reference to an existing stack frame
/// on the top of the stack.
void pushFrameRef(S32 stackIndex);
void pushDebugFrame(S32 stackIndex);
U32 getStackDepth() const
{
return mStackDepth;
}
Dictionary& getCurrentFrame()
{
return *(stack[mStackDepth - 1]);
}
Dictionary& getFrameAt(S32 depth)
{
return *(stack[depth]);
}
/// @}
/// Run integrity checks for debugging.
void validate();
};
namespace Con
{
/// The current $instantGroup setting.
extern String gInstantGroup;
/// Global variable storage
inline Dictionary gGlobalVars;
typedef Dictionary ConsoleFrame;
typedef Vector<ConsoleFrame*> ConsoleStack;
inline ConsoleStack gFrameStack;
inline ConsoleStack getFrameStack() { return gFrameStack; }
inline void pushStackFrame(ConsoleFrame* frame) { gFrameStack.push_back(frame); }
inline ConsoleFrame* popStackFrame() { ConsoleFrame* last = gFrameStack.last(); gFrameStack.pop_back(); return last; }
inline ConsoleFrame* getCurrentStackFrame() { return getFrameStack().empty() ? NULL : gFrameStack.last(); }
inline ConsoleFrame* getStackFrame(S32 idx) { return gFrameStack[idx]; }
inline Vector<Con::Module*> gScriptModules;
inline Vector<Con::Module*> getAllScriptModules() { return gScriptModules; }
Con::Module* findScriptModuleForFile(const char* fileName);
// Convenience functions for getting the execution context
inline const char* getCurrentScriptModulePath() { return getCurrentStackFrame() && getCurrentStackFrame()->module ? getCurrentStackFrame()->module->getPath() : NULL; }
inline const char* getCurrentScriptModuleName() { return getCurrentStackFrame() && getCurrentStackFrame()->module ? getCurrentStackFrame()->module->getName() : NULL; }
inline Con::Module* getCurrentScriptModule() { return getCurrentStackFrame() ? getCurrentStackFrame()->module : NULL; }
inline bool gTraceOn;
}
/// @}

View file

@ -26,7 +26,6 @@
#include "console/engineAPI.h"
#include "core/stream/fileStream.h"
#include "console/consoleInternal.h"
#include "console/compiler.h"
#define USE_UNDOCUMENTED_GROUP
@ -113,10 +112,10 @@ static void dumpVariable( Stream& stream,
const char* inClass = NULL )
{
// Skip variables defined in script.
if( entry->type <= Dictionary::Entry::TypeInternalString )
if( entry->value.getType() <= ConsoleValueType::cvString )
return;
// Skip internals... don't export them.
if ( entry->mUsage &&
( dStrstr( entry->mUsage, "@hide" ) || dStrstr( entry->mUsage, "@internal" ) ) )
@ -146,10 +145,10 @@ static void dumpVariable( Stream& stream,
if( nameComponents.size() > 1 && Con::lookupNamespace( nameComponents.first().c_str() + 1 )->mClassRep )
return;
}
// Skip variables for which we can't decipher their type.
ConsoleBaseType* type = ConsoleBaseType::getType( entry->type );
ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.getConsoleType()->consoleType );
if( !type )
{
Con::errorf( "Can't find type for variable '%s'", entry->name );
@ -204,9 +203,9 @@ static void dumpVariable( Stream& stream,
static void dumpVariables( Stream& stream, const char* inClass = NULL )
{
const U32 hashTableSize = gEvalState.globalVars.hashTable->size;
const U32 hashTableSize = Con::gGlobalVars.hashTable->size;
for( U32 i = 0; i < hashTableSize; ++ i )
for( Dictionary::Entry* entry = gEvalState.globalVars.hashTable->data[ i ]; entry != NULL; entry = entry->nextEntry )
for( Dictionary::Entry* entry = Con::gGlobalVars.hashTable->data[ i ]; entry != NULL; entry = entry->nextEntry )
dumpVariable( stream, entry, inClass );
}

View file

@ -24,9 +24,7 @@
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
#include "console/ast.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "platform/platformInput.h"
#include "torqueConfig.h"
#include "core/frameAllocator.h"
@ -420,7 +418,7 @@ DefineEngineFunction(isScriptFile, bool, (const char* fileName), ,
"@ingroup FileSystem")
{
return Torque::FS::IsScriptFile(fileName);
return Con::isScriptFile(fileName);
}
DefineEngineFunction( IsDirectory, bool, ( const char* directory ),,

View file

@ -0,0 +1,45 @@
#ifndef _SCRIPT_MODULE_H_
#define _SCRIPT_MODULE_H_
#include "runtime.h"
#include "console/console.h"
#include "platform/types.h"
namespace Con
{
class Module
{
private:
S32 mRefCount = 0;
public:
Module() = default;
virtual ~Module() = default;
void incRefCount() { mRefCount++; }
void decRefCount() { mRefCount--; if (!mRefCount) delete this; }
virtual const char* getFunctionArgs(StringTableEntry functionName, U32 functionOffset) = 0;
virtual const char* getPath() = 0;
virtual const char* getName() = 0;
virtual EvalResult exec(U32 offset, const char* fnName, Namespace* ns, U32 argc,
ConsoleValue* argv, bool noCalls, StringTableEntry packageName,
S32 setFrame = -1) = 0;
virtual void findBreakLine(U32 ip, U32& line, U32& instruction) = 0;
virtual const char *getFileLine(U32 ip) = 0;
/// Returns the first breakable line or 0 if none was found.
/// @param lineNumber The one based line number.
virtual U32 findFirstBreakLine(U32 lineNumber) = 0;
/// Set a OP_BREAK instruction on a line. If a break
/// is not possible on that line it returns false.
/// @param lineNumber The one based line number.
virtual bool setBreakpoint(U32 lineNumber) = 0;
virtual void setAllBreaks() = 0;
virtual void clearAllBreaks() = 0;
virtual void clearBreakpoint(U32 lineNumber) = 0;
virtual Vector<U32> getBreakableLines() = 0;
};
}
#endif

View file

@ -35,8 +35,6 @@
// Property system includes:
#include "console/propertyParsing.h"
extern ExprEvalState gEvalState;
namespace PropertyInfo
{
//-----------------------------------------------------------------------------

View file

@ -0,0 +1,112 @@
#ifndef _RUNTIME_H_
#define _RUNTIME_H_
#include "console/console.h"
namespace Con
{
struct EvalResult
{
bool valid;
ConsoleValue value;
String error;
public:
EvalResult() {}
EvalResult(ConsoleValue&& pValue)
{
valid = true;
value = (ConsoleValue&&)pValue;
}
EvalResult(String errorMessage)
{
valid = false;
error = errorMessage;
}
};
struct Error
{
const char* message;
};
struct SyntaxError : Error {};
class Stack
{
class Frame
{
public:
ConsoleValue* lookup(const char*);
};
public:
S32 getDepth();
Frame getFrame(S32 idx);
};
class Runtime
{
private:
Stack mStack;
public:
virtual ~Runtime() = default;
virtual Stack getStack() { return mStack; }
/// Convert from a relative script path to an absolute script path.
///
/// This is used in (among other places) the exec() script function, which
/// takes a parameter indicating a script file and executes it. Script paths
/// can be one of:
/// - <b>Absolute:</b> <i>fps/foo/bar.tscript</i> Paths of this sort are passed
/// through.
/// - <b>Mod-relative:</b> <i>~/foo/bar.tscript</i> Paths of this sort have their
/// replaced with the name of the current mod.
/// - <b>File-relative:</b> <i>./baz/blip.tscript</i> Paths of this sort are
/// calculated relative to the path of the current scripting file.
///
/// @note This function determines paths relative to the currently executing
/// CodeBlock. Calling it outside of script execution will result in
/// it directly copying src to filename, since it won't know to what the
/// path is relative!
///
/// @param filename Pointer to string buffer to fill with absolute path.
/// @param size Size of buffer pointed to by filename.
/// @param src Original, possibly relative script path.
bool expandScriptFilename(char *filename, U32 size, const char *src);
bool expandToolScriptFilename(char *filename, U32 size, const char *src);
bool collapseScriptFilename(char *filename, U32 size, const char *src);
virtual void expandEscapedCharacters(char* dest, const char* src) = 0;
virtual bool collapseEscapedCharacters(char* buf) = 0;
/// Evaluate an arbitrary chunk of code.
///
/// @param string Buffer containing code to execute.
/// @param echo Should we echo the string to the console?
/// @param fileName Indicate what file this code is coming from; used in error reporting and such.
/// NOTE: This function restores the console stack on return.
virtual EvalResult evaluate(const char* string, bool echo = false, const char *fileName = NULL) = 0;
virtual EvalResult evaluate(const char* string, S32 frame, bool echo = false, const char *fileName = NULL) = 0;
/// Evaluate an arbitrary line of script.
///
/// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
/// NOTE: This function restores the console stack on return.
virtual EvalResult evaluatef(const char* string, ...) = 0;
/// Executes a script file and compiles it for use in script.
///
/// @param fileName File name that is the script to be executed and compiled.
/// @param noCalls Deprecated
/// @param journalScript Deprecated
///
/// @return True if the script was successfully executed, false if not.
virtual bool executeFile(const char* fileName, bool noCalls, bool journalScript) = 0;
};
}
#endif

View file

@ -0,0 +1,71 @@
#ifndef _SCRIPT_H_
#define _SCRIPT_H_
#include "runtime.h"
#include "core/stream/stream.h"
#include "module.h"
#include "core/util/tDictionary.h"
namespace Con
{
inline EvalResult gLastEvalResult;
inline EvalResult setLastEvalResult(EvalResult pLastEvalResult)
{
gLastEvalResult.valid = pLastEvalResult.valid;
gLastEvalResult.error = pLastEvalResult.error;
gLastEvalResult.value.setString(pLastEvalResult.value.getString());
return std::move(pLastEvalResult);
}
inline EvalResult getLastEvalResult() { return setLastEvalResult(std::move(gLastEvalResult)); };
bool runStream(Stream* byteCode, const char* fileName);
bool isCurrentScriptToolScript();
Module* getCurrentModule();
inline HashMap<S32, Runtime*> gRuntimes;
inline Runtime* getRuntime(S32 pRuntimeId = 0) { return gRuntimes[pRuntimeId]; }
inline void registerRuntime(S32 pRuntimeId, Runtime* pRuntime)
{
AssertFatal(gRuntimes[pRuntimeId] == NULL, "A runtime with that ID already exists");
gRuntimes[pRuntimeId] = pRuntime;
}
/// Evaluate an arbitrary chunk of code.
///
/// @param script Buffer containing code to execute.
/// @param echo Should we echo the string to the console?
/// @param fileName Indicate what file this code is coming from; used in error reporting and such.
/// NOTE: This function restores the console stack on return.
inline EvalResult evaluate(const char* script, bool echo = false, const char *fileName = NULL) { return setLastEvalResult(getRuntime()->evaluate(script, echo, fileName)); };
inline EvalResult evaluate(const char* script, S32 frame, bool echo = false, const char *fileName = NULL) { return setLastEvalResult(getRuntime()->evaluate(script, frame, echo, fileName)); };
/// Evaluate an arbitrary line of script.
///
/// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
/// NOTE: This function restores the console stack on return.
inline EvalResult evaluatef(const char* string, ...)
{
va_list args;
va_start(args, string);
EvalResult result = setLastEvalResult(getRuntime()->evaluatef(string, args));
va_end(args);
return result;
};
/// Executes a script file and compiles it for use in script.
///
/// @param string File name that is the script to be executed and compiled.
/// @param fileName Path to the file to execute
/// @param noCalls Deprecated
/// @param journalScript Deprecated
///
/// @return True if the script was successfully executed, false if not.
inline bool executeFile(const char* fileName, bool noCalls, bool journalScript) { return getRuntime()->executeFile(fileName, noCalls, journalScript); };
}
#endif

View file

@ -23,12 +23,12 @@
#include "platform/platform.h"
#include "console/scriptFilename.h"
#include "consoleInternal.h"
#include "core/frameAllocator.h"
#include "core/tSimpleHashTable.h"
#include "core/strings/stringFunctions.h"
#include "core/stringTable.h"
#include "console/engineAPI.h"
#include "console/compiler.h"
namespace Con
@ -88,8 +88,8 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src)
// same way the old code did as it is now possible that something could
// be expanded if the name or mod is NULL. This was previously not the case.
const StringTableEntry cbMod = CodeBlock::getCurrentCodeBlockModName();
const StringTableEntry cbFullPath = CodeBlock::getCurrentCodeBlockFullPath();
const StringTableEntry cbMod = Con::getCurrentScriptModuleName();
const StringTableEntry cbFullPath = Con::getCurrentScriptModulePath();
char varBuf[1024], modBuf[1024];
const char *ptr = src;
@ -216,7 +216,8 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src)
bool expandOldScriptFilename(char *filename, U32 size, const char *src)
{
const StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName();
const StringTableEntry cbName = Con::getCurrentScriptModuleName();
if (!cbName)
{
dStrcpy(filename, src, size);

View file

@ -27,6 +27,7 @@
#include "platform/platform.h"
#include "console/simDatablock.h"
#include "script.h"
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
@ -34,7 +35,6 @@
#include "T3D/gameBase/gameConnection.h"
#include "core/stream/bitStream.h"
#include "console/compiler.h"
IMPLEMENT_CO_DATABLOCK_V1(SimDataBlock);
SimObjectId SimDataBlock::sNextObjectId = DataBlockObjectIdFirst;
@ -252,17 +252,14 @@ void SimDataBlock::performSubstitutions(SimDataBlock* dblock, const SimObject* o
b[0] = '\0';
// perform the statement evaluation
Compiler::gSyntaxError = false;
//Con::errorf("EVAL [%s]", avar("return %s;", buffer));
const char *result = Con::evaluate(avar("return %s;", buffer), false, 0);
if (Compiler::gSyntaxError)
Con::EvalResult evalResult = Con::evaluate(avar("return %s;", buffer), false, 0);
if (evalResult.valid)
{
Con::errorf("Field Substitution Failed: field=\"%s\" substitution=\"%s\" -- syntax error",
substitutions[i]->mSlot, substitutions[i]->mValue);
Compiler::gSyntaxError = false;
return;
}
const char* result = evalResult.value;
// output a runtime console error when a substitution produces and empty result.
if (result == 0 || result[0] == '\0')

View file

@ -25,9 +25,6 @@
#include "platform/threads/semaphore.h"
#include "console/simEvents.h"
// Stupid globals not declared in a header
extern ExprEvalState gEvalState;
SimConsoleEvent::SimConsoleEvent(S32 argc, ConsoleValue *argv, bool onObject)
{
mOnObject = onObject;
@ -79,7 +76,7 @@ void SimConsoleEvent::process(SimObject* object)
Namespace::Entry* nse = ns->lookup( StringTable->insert( func ) );
if( nse )
// Execute.
nse->execute( mArgc, mArgv, &gEvalState );
nse->execute( mArgc, mArgv, object );
}
}

View file

@ -20,6 +20,7 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "script.h"
#include "platform/platform.h"
#include "platform/threads/mutex.h"
#include "console/simBase.h"
@ -36,8 +37,6 @@
#include "platform/profiler.h"
#include "math/mMathFn.h"
extern ExprEvalState gEvalState;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
@ -341,9 +340,9 @@ SimObject* findObject(const char* name)
if (c == '%')
{
if (gEvalState.getStackDepth())
if (!Con::getFrameStack().empty())
{
Dictionary::Entry* ent = gEvalState.getCurrentFrame().lookup(StringTable->insert(name));
Dictionary::Entry* ent = Con::getCurrentStackFrame()->lookup(StringTable->insert(name));
if (ent)
return Sim::findObject(ent->getIntValue());

View file

@ -35,7 +35,6 @@
#include "console/simPersistID.h"
#include "console/typeValidators.h"
#include "console/arrayObject.h"
#include "console/codeBlock.h"
#include "core/frameAllocator.h"
#include "core/stream/fileStream.h"
#include "core/fileObject.h"
@ -2479,7 +2478,7 @@ static void sEnumCallback( EngineObject* object )
if( !simObject )
return;
Con::evaluatef( "%s( %i );", sEnumCallbackFunction, simObject->getId() );
Con::executef(sEnumCallbackFunction, simObject->getId());
}
DefineEngineFunction( debugEnumInstances, void, ( const char* className, const char* functionName ),,
@ -2645,10 +2644,10 @@ DefineEngineMethod( SimObject, dumpMethods, ArrayObject*, (),,
str.append( e->getPrototypeString() );
str.append( '\n' );
if( e->mCode && e->mCode->fullPath )
str.append( e->mCode->fullPath );
if( e->mModule && e->mModule->getPath() )
str.append( e->mModule->getPath() );
str.append( '\n' );
if( e->mCode )
if( e->mModule )
str.append( String::ToString( e->mFunctionLineNumber ) );
str.append( '\n' );

View file

@ -23,6 +23,7 @@
#include "platform/platform.h"
#include "console/simObjectMemento.h"
#include "script.h"
#include "console/simObject.h"
#include "console/simDatablock.h"
#include "core/stream/memStream.h"
@ -95,7 +96,7 @@ SimObject *SimObjectMemento::restore() const
// Read the object.
const UTF8* result = Con::evaluate( mState );
const UTF8* result = Con::evaluate( mState ).value;
// Restore the redefine behavior.

View file

@ -28,10 +28,9 @@
#include "console/engineAPI.h"
#include "core/stringTable.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
#include "console/compiler.h"
#include "core/util/journal/process.h"
#include "core/module.h"
#include "script.h"
MODULE_BEGIN( TelnetDebugger )
@ -169,7 +168,7 @@ TelnetDebugger::TelnetDebugger()
// Add the version number in a global so that
// scripts can detect the presence of the
// "enhanced" debugger features.
Con::evaluatef( "$dbgVersion = %d;", Version );
Con::setIntVariable("dbgVersion", Version);
}
TelnetDebugger::Breakpoint **TelnetDebugger::findBreakpoint(StringTableEntry fileName, S32 lineNumber)
@ -380,7 +379,7 @@ void TelnetDebugger::checkDebugRecv()
}
}
void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
void TelnetDebugger::executionStopped(Con::Module *module, U32 lineNumber)
{
if(mProgramPaused)
return;
@ -392,13 +391,13 @@ void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
return;
}
Breakpoint **bp = findBreakpoint(code->name, lineNumber);
Breakpoint **bp = findBreakpoint(module->getName(), lineNumber);
if(!bp)
return;
Breakpoint *brk = *bp;
mProgramPaused = true;
Con::evaluatef("$Debug::result = %s;", brk->testExpression);
Con::setVariable("$Debug::result", brk->testExpression);
if(Con::getBoolVariable("$Debug::result"))
{
brk->curCount++;
@ -406,7 +405,7 @@ void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
{
brk->curCount = 0;
if(brk->clearOnHit)
removeBreakpoint(code->name, lineNumber);
removeBreakpoint(module->getName(), lineNumber);
breakProcess();
}
}
@ -418,8 +417,8 @@ void TelnetDebugger::pushStackFrame()
if(mState == NotConnected)
return;
if(mBreakOnNextStatement && mStackPopBreakIndex > -1 &&
gEvalState.getStackDepth() > mStackPopBreakIndex)
if(mBreakOnNextStatement && mStackPopBreakIndex > -1 &&
Con::getFrameStack().size() > mStackPopBreakIndex)
setBreakOnNextStatement( false );
}
@ -428,7 +427,7 @@ void TelnetDebugger::popStackFrame()
if(mState == NotConnected)
return;
if(mStackPopBreakIndex > -1 && gEvalState.getStackDepth()-1 <= mStackPopBreakIndex)
if(mStackPopBreakIndex > -1 && Con::getFrameStack().size()-1 <= mStackPopBreakIndex)
setBreakOnNextStatement( true );
}
@ -461,14 +460,14 @@ void TelnetDebugger::sendBreak()
S32 last = 0;
for(S32 i = (S32) gEvalState.getStackDepth() - 1; i >= last; i--)
for(S32 i = (S32) Con::getFrameStack().size() - 1; i >= last; i--)
{
CodeBlock *code = gEvalState.stack[i]->code;
Con::Module *module = Con::getStackFrame(i)->module;
const char *file = "<none>";
if (code && code->name && code->name[0])
file = code->name;
if (module && module->getName() && module->getName()[0])
file = module->getName();
Namespace *ns = gEvalState.stack[i]->scopeNamespace;
Namespace *ns = Con::getStackFrame(i)->scopeNamespace;
scope[0] = 0;
if ( ns ) {
@ -482,15 +481,15 @@ void TelnetDebugger::sendBreak()
}
}
const char *function = gEvalState.stack[i]->scopeName;
const char *function = Con::getStackFrame(i)->scopeName;
if ((!function) || (!function[0]))
function = "<none>";
dStrcat( scope, function, MaxCommandSize );
U32 line=0, inst;
U32 ip = gEvalState.stack[i]->ip;
if (code)
code->findBreakLine(ip, line, inst);
U32 ip = Con::getStackFrame(i)->ip;
if (module)
module->findBreakLine(ip, line, inst);
dSprintf(buffer, MaxCommandSize, " %s %d %s", file, line, scope);
send(buffer);
}
@ -579,7 +578,7 @@ void TelnetDebugger::removeVariableBreakpoint(const char*)
send("removeVariableBreakpoint\r\n");
}
void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
void TelnetDebugger::addAllBreakpoints(Con::Module *module)
{
if(mState == NotConnected)
return;
@ -590,14 +589,14 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
{
// TODO: This assumes that the OS file names are case
// insensitive... Torque needs a dFilenameCmp() function.
if( dStricmp( cur->fileName, code->name ) == 0 )
if( dStricmp( cur->fileName, module->getName() ) == 0 )
{
cur->code = code;
cur->module = module;
// Find the fist breakline starting from and
// including the requested breakline.
S32 newLine = code->findFirstBreakLine(cur->lineNumber);
if (newLine <= 0)
S32 newLine = module->findFirstBreakLine(cur->lineNumber);
if (newLine <= 0)
{
char buffer[MaxCommandSize];
dSprintf(buffer, MaxCommandSize, "BRKCLR %s %d\r\n", cur->fileName, cur->lineNumber);
@ -638,7 +637,7 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
cur->lineNumber = newLine;
}
code->setBreakpoint(cur->lineNumber);
module->setBreakpoint(cur->lineNumber);
}
cur = cur->next;
@ -646,7 +645,7 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
// Enable all breaks if a break next was set.
if (mBreakOnNextStatement)
code->setAllBreaks();
module->setAllBreaks();
}
void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S32 passCount, const char *evalString)
@ -668,12 +667,12 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
{
// Note that if the code block is not already
// loaded it is handled by addAllBreakpoints.
CodeBlock* code = CodeBlock::find(fileName);
if (code)
Con::Module* module = Con::findScriptModuleForFile(fileName);
if (module)
{
// Find the fist breakline starting from and
// including the requested breakline.
S32 newLine = code->findFirstBreakLine(line);
S32 newLine = module->findFirstBreakLine(line);
if (newLine <= 0)
{
char buffer[MaxCommandSize];
@ -703,11 +702,11 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
line = newLine;
}
code->setBreakpoint(line);
module->setBreakpoint(line);
}
Breakpoint *brk = new Breakpoint;
brk->code = code;
brk->module = module;
brk->fileName = fileName;
brk->lineNumber = line;
brk->passCount = passCount;
@ -719,13 +718,13 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
}
}
void TelnetDebugger::removeBreakpointsFromCode(CodeBlock *code)
void TelnetDebugger::removeBreakpointsFromCode(Con::Module *code)
{
Breakpoint **walk = &mBreakpoints;
Breakpoint *cur;
while((cur = *walk) != NULL)
{
if(cur->code == code)
if(cur->module == code)
{
dFree(cur->testExpression);
*walk = cur->next;
@ -744,8 +743,8 @@ void TelnetDebugger::removeBreakpoint(const char *fileName, S32 line)
{
Breakpoint *brk = *bp;
*bp = brk->next;
if ( brk->code )
brk->code->clearBreakpoint(brk->lineNumber);
if ( brk->module )
brk->module->clearBreakpoint(brk->lineNumber);
dFree(brk->testExpression);
delete brk;
}
@ -757,8 +756,8 @@ void TelnetDebugger::removeAllBreakpoints()
while(walk)
{
Breakpoint *temp = walk->next;
if ( walk->code )
walk->code->clearBreakpoint(walk->lineNumber);
if ( walk->module )
walk->module->clearBreakpoint(walk->lineNumber);
dFree(walk->testExpression);
delete walk;
walk = temp;
@ -781,23 +780,24 @@ void TelnetDebugger::debugContinue()
void TelnetDebugger::setBreakOnNextStatement( bool enabled )
{
Vector<Con::Module*> modules = Con::getAllScriptModules();
if ( enabled )
{
// Apply breaks on all the code blocks.
for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
walk->setAllBreaks();
for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
(*walk)->setAllBreaks();
mBreakOnNextStatement = true;
}
else if ( !enabled )
{
// Clear all the breaks on the codeblocks
// then go reapply the breakpoints.
for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
walk->clearAllBreaks();
for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
(*walk)->clearAllBreaks();
for(Breakpoint *w = mBreakpoints; w; w = w->next)
{
if ( w->code )
w->code->setBreakpoint(w->lineNumber);
if ( w->module )
w->module->setBreakpoint(w->lineNumber);
}
mBreakOnNextStatement = false;
}
@ -838,7 +838,7 @@ void TelnetDebugger::debugStepOver()
return;
setBreakOnNextStatement( true );
mStackPopBreakIndex = gEvalState.getStackDepth();
mStackPopBreakIndex = Con::getFrameStack().size();
mProgramPaused = false;
send("RUNNING\r\n");
}
@ -849,7 +849,7 @@ void TelnetDebugger::debugStepOut()
return;
setBreakOnNextStatement( false );
mStackPopBreakIndex = gEvalState.getStackDepth() - 1;
mStackPopBreakIndex = Con::getFrameStack().size() - 1;
if ( mStackPopBreakIndex == 0 )
mStackPopBreakIndex = -1;
mProgramPaused = false;
@ -858,84 +858,39 @@ void TelnetDebugger::debugStepOut()
void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *evalBuffer)
{
// Make sure we're passing a valid frame to the eval.
if ( frame > gEvalState.getStackDepth() )
frame = gEvalState.getStackDepth() - 1;
if ( frame < 0 )
frame = 0;
// Build a buffer just big enough for this eval.
const char* format = "return %s;";
S32 len = dStrlen( format ) + dStrlen( evalBuffer );
char* buffer = new char[ len ];
dSprintf( buffer, len, format, evalBuffer );
Con::EvalResult evalResult = Con::evaluate(buffer, frame);
delete buffer;
// Local variables use their own memory management and can't be queried by just executing
// TorqueScript, we have to go digging into the interpreter.
S32 evalBufferLen = dStrlen(evalBuffer);
bool isEvaluatingLocalVariable = evalBufferLen > 0 && evalBuffer[0] == '%';
if (isEvaluatingLocalVariable)
if (!evalResult.valid)
{
// See calculation of current frame in pushing a reference frame for console exec, we need access
// to the proper scope.
//frame = gEvalState.getTopOfStack() - frame - 1;
S32 stackIndex = gEvalState.getTopOfStack() - frame - 1;
const char* format = "EVALOUT %s %s\r\n";
gEvalState.pushDebugFrame(stackIndex);
Dictionary& stackFrame = gEvalState.getCurrentFrame();
StringTableEntry functionName = stackFrame.scopeName;
StringTableEntry namespaceName = stackFrame.scopeNamespace->mName;
StringTableEntry varToLookup = StringTable->insert(evalBuffer);
S32 registerId = stackFrame.code->variableRegisterTable.lookup(namespaceName, functionName, varToLookup);
if (registerId == -1)
{
// ERROR, can't read the variable!
send("EVALOUT \"\" \"\"");
return;
}
const char* varResult = gEvalState.getLocalStringVariable(registerId);
gEvalState.popFrame();
S32 len = dStrlen(format) + dStrlen(tag) + dStrlen(varResult);
char* buffer = new char[len];
dSprintf(buffer, len, format, tag, varResult[0] ? varResult : "\"\"");
send(buffer);
delete[] buffer;
// ERROR, can't read the variable!
send("EVALOUT \"\" \"\"");
return;
}
// Build a buffer just big enough for this eval.
const char* format = "return %s;";
dsize_t len = dStrlen( format ) + dStrlen( evalBuffer );
char* buffer = new char[ len ];
dSprintf( buffer, len, format, evalBuffer );
// Execute the eval.
CodeBlock *newCodeBlock = new CodeBlock();
ConsoleValue result = newCodeBlock->compileExec( NULL, buffer, false, frame );
delete [] buffer;
// Create a new buffer that fits the result.
format = "EVALOUT %s %s\r\n";
len = dStrlen( format ) + dStrlen( tag ) + dStrlen( result.getString() );
buffer = new char[ len ];
dSprintf( buffer, len, format, tag, result.getString()[0] ? result.getString() : "\"\"" );
send( buffer );
delete newCodeBlock;
delete [] buffer;
len = dStrlen(format) + dStrlen(tag) + dStrlen(evalResult.value);
buffer = new char[len];
dSprintf(buffer, len, format, tag, evalResult.value[0] ? evalResult.value : "\"\"");
send(buffer);
delete[] buffer;
}
void TelnetDebugger::dumpFileList()
{
send("FILELISTOUT ");
for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
Vector<Con::Module*> modules = Con::getAllScriptModules();
for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
{
send(walk->name);
if(walk->nextFile)
send((*walk)->getName());
if((walk + 1) != modules.end())
send(" ");
}
send("\r\n");
@ -944,15 +899,15 @@ void TelnetDebugger::dumpFileList()
void TelnetDebugger::dumpBreakableList(const char *fileName)
{
fileName = StringTable->insert(fileName);
CodeBlock *file = CodeBlock::find(fileName);
Con::Module *file = Con::findScriptModuleForFile(fileName);
char buffer[MaxCommandSize];
if(file)
{
dSprintf(buffer, MaxCommandSize, "BREAKLISTOUT %s %d", fileName, file->breakListSize >> 1);
dSprintf(buffer, MaxCommandSize, "BREAKLISTOUT %s %d", fileName, file->getBreakableLines().size() >> 1);
send(buffer);
for(U32 i = 0; i < file->breakListSize; i += 2)
for(U32 i = 0; i < file->getBreakableLines().size(); i += 2)
{
dSprintf(buffer, MaxCommandSize, " %d %d", file->breakList[i], file->breakList[i+1]);
dSprintf(buffer, MaxCommandSize, " %d %d", file->getBreakableLines()[i], file->getBreakableLines()[i+1]);
send(buffer);
}
send("\r\n");
@ -962,14 +917,14 @@ void TelnetDebugger::dumpBreakableList(const char *fileName)
}
void TelnetDebugger::clearCodeBlockPointers(CodeBlock *code)
void TelnetDebugger::clearCodeBlockPointers(Con::Module *code)
{
Breakpoint **walk = &mBreakpoints;
Breakpoint *cur;
while((cur = *walk) != NULL)
{
if(cur->code == code)
cur->code = NULL;
if(cur->module == code)
cur->module = NULL;
walk = &cur->next;
}

View file

@ -26,8 +26,7 @@
#ifndef _PLATFORM_PLATFORMNET_H_
#include "platform/platformNet.h"
#endif
class CodeBlock;
#include "module.h"
/// Telnet debug service implementation.
///
@ -75,7 +74,7 @@ class TelnetDebugger
struct Breakpoint
{
StringTableEntry fileName;
CodeBlock *code;
Con::Module *module;
U32 lineNumber;
S32 passCount;
S32 curCount;
@ -105,7 +104,7 @@ class TelnetDebugger
void evaluateExpression(const char *tag, S32 frame, const char *evalBuffer);
void dumpFileList();
void dumpBreakableList(const char *fileName);
void removeBreakpointsFromCode(CodeBlock *code);
void removeBreakpointsFromCode(Con::Module *code);
void checkDebugRecv();
void processLineBuffer(S32);
@ -121,13 +120,13 @@ public:
void process();
void popStackFrame();
void pushStackFrame();
void addAllBreakpoints(CodeBlock *code);
void addAllBreakpoints(Con::Module *module);
void clearCodeBlockPointers(CodeBlock *code);
void clearCodeBlockPointers(Con::Module *code);
void breakProcess();
void executionStopped(CodeBlock *code, U32 lineNumber);
void executionStopped(Con::Module *module, U32 lineNumber);
void send(const char *s);
void setDebugParameters(S32 port, const char *password, bool waitForClient);
void processConsoleLine(const char *consoleLine);

View file

@ -29,6 +29,10 @@
#include <stdio.h>
#include "compiler.h"
#include "runtime.h"
#include "console/script.h"
/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
@ -551,11 +555,9 @@ char *yytext;
#define YYLMAX 4096
#define YY_NO_UNISTD_H
#include <stdio.h>
#include "platform/platform.h"
#include "core/stringTable.h"
#include "console/console.h"
#include "console/compiler.h"
#include "console/dynamicTypes.h"
#include "core/strings/stringFunctions.h"
@ -576,10 +578,7 @@ inline Token< T > MakeToken( T value, U32 lineNumber )
return result;
}
#include "console/cmdgram.h"
// HACK: C++17 and beyond can't use register keyword
#define register
#include "cmdgram.h"
using namespace Compiler;
@ -634,7 +633,7 @@ void CMDerror(const char * s, ...);
// Reset the parser.
void CMDrestart(FILE *in);
#line 638 "CMDscan.cpp"
#line 635 "CMDscan.cpp"
/* Macros after this point can all be overridden by user definitions in
* section 1.
@ -777,14 +776,14 @@ YY_MALLOC_DECL
YY_DECL
{
register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;
yy_state_type yy_current_state;
char *yy_cp, *yy_bp;
int yy_act;
#line 108 "CMDscan.l"
#line 105 "CMDscan.l"
;
#line 788 "CMDscan.cpp"
#line 785 "CMDscan.cpp"
if ( yy_init )
{
@ -826,7 +825,7 @@ YY_DECL
yy_match:
do
{
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
@ -869,187 +868,187 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
#line 110 "CMDscan.l"
#line 107 "CMDscan.l"
{ }
YY_BREAK
case 2:
YY_RULE_SETUP
#line 111 "CMDscan.l"
#line 108 "CMDscan.l"
{ return(Sc_ScanDocBlock()); }
YY_BREAK
case 3:
YY_RULE_SETUP
#line 112 "CMDscan.l"
#line 109 "CMDscan.l"
;
YY_BREAK
case 4:
YY_RULE_SETUP
#line 113 "CMDscan.l"
#line 110 "CMDscan.l"
;
YY_BREAK
case 5:
YY_RULE_SETUP
#line 114 "CMDscan.l"
#line 111 "CMDscan.l"
{lineIndex++;}
YY_BREAK
case 6:
YY_RULE_SETUP
#line 115 "CMDscan.l"
#line 112 "CMDscan.l"
{ return(Sc_ScanString(STRATOM)); }
YY_BREAK
case 7:
YY_RULE_SETUP
#line 116 "CMDscan.l"
#line 113 "CMDscan.l"
{ return(Sc_ScanString(TAGATOM)); }
YY_BREAK
case 8:
YY_RULE_SETUP
#line 117 "CMDscan.l"
#line 114 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opEQ, lineIndex ); return opEQ; }
YY_BREAK
case 9:
YY_RULE_SETUP
#line 118 "CMDscan.l"
#line 115 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opNE, lineIndex ); return opNE; }
YY_BREAK
case 10:
YY_RULE_SETUP
#line 119 "CMDscan.l"
#line 116 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opGE, lineIndex ); return opGE; }
YY_BREAK
case 11:
YY_RULE_SETUP
#line 120 "CMDscan.l"
#line 117 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opLE, lineIndex ); return opLE; }
YY_BREAK
case 12:
YY_RULE_SETUP
#line 121 "CMDscan.l"
#line 118 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opAND, lineIndex ); return opAND; }
YY_BREAK
case 13:
YY_RULE_SETUP
#line 122 "CMDscan.l"
#line 119 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opOR, lineIndex ); return opOR; }
YY_BREAK
case 14:
YY_RULE_SETUP
#line 123 "CMDscan.l"
#line 120 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opCOLONCOLON, lineIndex ); return opCOLONCOLON; }
YY_BREAK
case 15:
YY_RULE_SETUP
#line 124 "CMDscan.l"
#line 121 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opMINUSMINUS, lineIndex ); return opMINUSMINUS; }
YY_BREAK
case 16:
YY_RULE_SETUP
#line 125 "CMDscan.l"
#line 122 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opPLUSPLUS, lineIndex ); return opPLUSPLUS; }
YY_BREAK
case 17:
YY_RULE_SETUP
#line 126 "CMDscan.l"
#line 123 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSTREQ, lineIndex ); return opSTREQ; }
YY_BREAK
case 18:
YY_RULE_SETUP
#line 127 "CMDscan.l"
#line 124 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSTRNE, lineIndex ); return opSTRNE; }
YY_BREAK
case 19:
YY_RULE_SETUP
#line 128 "CMDscan.l"
#line 125 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSHL, lineIndex ); return opSHL; }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 129 "CMDscan.l"
#line 126 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSHR, lineIndex ); return opSHR; }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 130 "CMDscan.l"
#line 127 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opPLASN, lineIndex ); return opPLASN; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 131 "CMDscan.l"
#line 128 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opMIASN, lineIndex ); return opMIASN; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 132 "CMDscan.l"
#line 129 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opMLASN, lineIndex ); return opMLASN; }
YY_BREAK
case 24:
YY_RULE_SETUP
#line 133 "CMDscan.l"
#line 130 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opDVASN, lineIndex ); return opDVASN; }
YY_BREAK
case 25:
YY_RULE_SETUP
#line 134 "CMDscan.l"
#line 131 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opMODASN, lineIndex ); return opMODASN; }
YY_BREAK
case 26:
YY_RULE_SETUP
#line 135 "CMDscan.l"
#line 132 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opANDASN, lineIndex ); return opANDASN; }
YY_BREAK
case 27:
YY_RULE_SETUP
#line 136 "CMDscan.l"
#line 133 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opXORASN, lineIndex ); return opXORASN; }
YY_BREAK
case 28:
YY_RULE_SETUP
#line 137 "CMDscan.l"
#line 134 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opORASN, lineIndex ); return opORASN; }
YY_BREAK
case 29:
YY_RULE_SETUP
#line 138 "CMDscan.l"
#line 135 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSLASN, lineIndex ); return opSLASN; }
YY_BREAK
case 30:
YY_RULE_SETUP
#line 139 "CMDscan.l"
#line 136 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opSRASN, lineIndex ); return opSRASN; }
YY_BREAK
case 31:
YY_RULE_SETUP
#line 140 "CMDscan.l"
#line 137 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opINTNAME, lineIndex ); return opINTNAME; }
YY_BREAK
case 32:
YY_RULE_SETUP
#line 141 "CMDscan.l"
#line 138 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( opINTNAMER, lineIndex ); return opINTNAMER; }
YY_BREAK
case 33:
YY_RULE_SETUP
#line 142 "CMDscan.l"
#line 139 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( '\n', lineIndex ); return '@'; }
YY_BREAK
case 34:
YY_RULE_SETUP
#line 143 "CMDscan.l"
#line 140 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( '\t', lineIndex ); return '@'; }
YY_BREAK
case 35:
YY_RULE_SETUP
#line 144 "CMDscan.l"
#line 141 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( ' ', lineIndex ); return '@'; }
YY_BREAK
case 36:
YY_RULE_SETUP
#line 145 "CMDscan.l"
#line 142 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( 0, lineIndex ); return '@'; }
YY_BREAK
case 37:
YY_RULE_SETUP
#line 146 "CMDscan.l"
#line 143 "CMDscan.l"
{ /* this comment stops syntax highlighting from getting messed up when editing the lexer in TextPad */
int c = 0, l;
for ( ; ; )
@ -1075,222 +1074,222 @@ YY_RULE_SETUP
}
YY_BREAK
case 38:
#line 170 "CMDscan.l"
#line 167 "CMDscan.l"
case 39:
#line 171 "CMDscan.l"
#line 168 "CMDscan.l"
case 40:
#line 172 "CMDscan.l"
#line 169 "CMDscan.l"
case 41:
#line 173 "CMDscan.l"
#line 170 "CMDscan.l"
case 42:
#line 174 "CMDscan.l"
#line 171 "CMDscan.l"
case 43:
#line 175 "CMDscan.l"
#line 172 "CMDscan.l"
case 44:
#line 176 "CMDscan.l"
#line 173 "CMDscan.l"
case 45:
#line 177 "CMDscan.l"
#line 174 "CMDscan.l"
case 46:
#line 178 "CMDscan.l"
#line 175 "CMDscan.l"
case 47:
#line 179 "CMDscan.l"
#line 176 "CMDscan.l"
case 48:
#line 180 "CMDscan.l"
#line 177 "CMDscan.l"
case 49:
#line 181 "CMDscan.l"
#line 178 "CMDscan.l"
case 50:
#line 182 "CMDscan.l"
#line 179 "CMDscan.l"
case 51:
#line 183 "CMDscan.l"
#line 180 "CMDscan.l"
case 52:
#line 184 "CMDscan.l"
#line 181 "CMDscan.l"
case 53:
#line 185 "CMDscan.l"
#line 182 "CMDscan.l"
case 54:
#line 186 "CMDscan.l"
#line 183 "CMDscan.l"
case 55:
#line 187 "CMDscan.l"
#line 184 "CMDscan.l"
case 56:
#line 188 "CMDscan.l"
#line 185 "CMDscan.l"
case 57:
#line 189 "CMDscan.l"
#line 186 "CMDscan.l"
case 58:
#line 190 "CMDscan.l"
#line 187 "CMDscan.l"
case 59:
#line 191 "CMDscan.l"
#line 188 "CMDscan.l"
case 60:
#line 192 "CMDscan.l"
#line 189 "CMDscan.l"
case 61:
YY_RULE_SETUP
#line 192 "CMDscan.l"
#line 189 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( CMDtext[ 0 ], lineIndex ); return CMDtext[ 0 ]; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 193 "CMDscan.l"
#line 190 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwIN, lineIndex ); return(rwIN); }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 194 "CMDscan.l"
#line 191 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwCASEOR, lineIndex ); return(rwCASEOR); }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 195 "CMDscan.l"
#line 192 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwBREAK, lineIndex ); return(rwBREAK); }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 196 "CMDscan.l"
#line 193 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwRETURN, lineIndex ); return(rwRETURN); }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 197 "CMDscan.l"
#line 194 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwELSE, lineIndex ); return(rwELSE); }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 198 "CMDscan.l"
#line 195 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwASSERT, lineIndex ); return(rwASSERT); }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 199 "CMDscan.l"
#line 196 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwWHILE, lineIndex ); return(rwWHILE); }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 200 "CMDscan.l"
#line 197 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDO, lineIndex ); return(rwDO); }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 201 "CMDscan.l"
#line 198 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwIF, lineIndex ); return(rwIF); }
YY_BREAK
case 71:
YY_RULE_SETUP
#line 202 "CMDscan.l"
#line 199 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwFOREACHSTR, lineIndex ); return(rwFOREACHSTR); }
YY_BREAK
case 72:
YY_RULE_SETUP
#line 203 "CMDscan.l"
#line 200 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwFOREACH, lineIndex ); return(rwFOREACH); }
YY_BREAK
case 73:
YY_RULE_SETUP
#line 204 "CMDscan.l"
#line 201 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwFOR, lineIndex ); return(rwFOR); }
YY_BREAK
case 74:
YY_RULE_SETUP
#line 205 "CMDscan.l"
#line 202 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwCONTINUE, lineIndex ); return(rwCONTINUE); }
YY_BREAK
case 75:
YY_RULE_SETUP
#line 206 "CMDscan.l"
#line 203 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDEFINE, lineIndex ); return(rwDEFINE); }
YY_BREAK
case 76:
YY_RULE_SETUP
#line 207 "CMDscan.l"
#line 204 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDECLARE, lineIndex ); return(rwDECLARE); }
YY_BREAK
case 77:
YY_RULE_SETUP
#line 208 "CMDscan.l"
#line 205 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDECLARESINGLETON, lineIndex ); return(rwDECLARESINGLETON); }
YY_BREAK
case 78:
YY_RULE_SETUP
#line 209 "CMDscan.l"
#line 206 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDATABLOCK, lineIndex ); return(rwDATABLOCK); }
YY_BREAK
case 79:
YY_RULE_SETUP
#line 210 "CMDscan.l"
#line 207 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwCASE, lineIndex ); return(rwCASE); }
YY_BREAK
case 80:
YY_RULE_SETUP
#line 211 "CMDscan.l"
#line 208 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwSWITCHSTR, lineIndex ); return(rwSWITCHSTR); }
YY_BREAK
case 81:
YY_RULE_SETUP
#line 212 "CMDscan.l"
#line 209 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwSWITCH, lineIndex ); return(rwSWITCH); }
YY_BREAK
case 82:
YY_RULE_SETUP
#line 213 "CMDscan.l"
#line 210 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwDEFAULT, lineIndex ); return(rwDEFAULT); }
YY_BREAK
case 83:
YY_RULE_SETUP
#line 214 "CMDscan.l"
#line 211 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwPACKAGE, lineIndex ); return(rwPACKAGE); }
YY_BREAK
case 84:
YY_RULE_SETUP
#line 215 "CMDscan.l"
#line 212 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( rwNAMESPACE, lineIndex ); return(rwNAMESPACE); }
YY_BREAK
case 85:
YY_RULE_SETUP
#line 216 "CMDscan.l"
#line 213 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( 1, lineIndex ); return INTCONST; }
YY_BREAK
case 86:
YY_RULE_SETUP
#line 217 "CMDscan.l"
#line 214 "CMDscan.l"
{ CMDlval.i = MakeToken< int >( 0, lineIndex ); return INTCONST; }
YY_BREAK
case 87:
YY_RULE_SETUP
#line 218 "CMDscan.l"
#line 215 "CMDscan.l"
{ return(Sc_ScanVar()); }
YY_BREAK
case 88:
YY_RULE_SETUP
#line 220 "CMDscan.l"
#line 216 "CMDscan.l"
{ return Sc_ScanIdent(); }
YY_BREAK
case 89:
YY_RULE_SETUP
#line 221 "CMDscan.l"
#line 217 "CMDscan.l"
return(Sc_ScanHex());
YY_BREAK
case 90:
YY_RULE_SETUP
#line 222 "CMDscan.l"
#line 218 "CMDscan.l"
{ CMDtext[CMDleng] = 0; CMDlval.i = MakeToken< int >( dAtoi(CMDtext), lineIndex ); return INTCONST; }
YY_BREAK
case 91:
YY_RULE_SETUP
#line 223 "CMDscan.l"
#line 219 "CMDscan.l"
return Sc_ScanNum();
YY_BREAK
case 92:
YY_RULE_SETUP
#line 224 "CMDscan.l"
#line 220 "CMDscan.l"
return(ILLEGAL_TOKEN);
YY_BREAK
case 93:
YY_RULE_SETUP
#line 225 "CMDscan.l"
#line 221 "CMDscan.l"
return(ILLEGAL_TOKEN);
YY_BREAK
case 94:
YY_RULE_SETUP
#line 226 "CMDscan.l"
#line 222 "CMDscan.l"
ECHO;
YY_BREAK
#line 1294 "CMDscan.cpp"
#line 1291 "CMDscan.cpp"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1433,9 +1432,9 @@ case YY_STATE_EOF(INITIAL):
static int yy_get_next_buffer()
{
register char *dest = yy_current_buffer->yy_ch_buf;
register char *source = yytext_ptr;
register int number_to_move, i;
char *dest = yy_current_buffer->yy_ch_buf;
char *source = yytext_ptr;
int number_to_move, i;
int ret_val;
if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
@ -1563,14 +1562,14 @@ static int yy_get_next_buffer()
static yy_state_type yy_get_previous_state()
{
register yy_state_type yy_current_state;
register char *yy_cp;
yy_state_type yy_current_state;
char *yy_cp;
yy_current_state = yy_start;
for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
{
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
@ -1602,10 +1601,10 @@ static yy_state_type yy_try_NUL_trans( yy_current_state )
yy_state_type yy_current_state;
#endif
{
register int yy_is_jam;
register char *yy_cp = yy_c_buf_p;
int yy_is_jam;
char *yy_cp = yy_c_buf_p;
register YY_CHAR yy_c = 1;
YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
@ -1626,14 +1625,14 @@ yy_state_type yy_current_state;
#ifndef YY_NO_UNPUT
#ifdef YY_USE_PROTOS
static void yyunput( int c, register char *yy_bp )
static void yyunput( int c, char *yy_bp )
#else
static void yyunput( c, yy_bp )
int c;
register char *yy_bp;
char *yy_bp;
#endif
{
register char *yy_cp = yy_c_buf_p;
char *yy_cp = yy_c_buf_p;
/* undo effects of setting up yytext */
*yy_cp = yy_hold_char;
@ -1641,10 +1640,10 @@ register char *yy_bp;
if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
register int number_to_move = yy_n_chars + 2;
register char *dest = &yy_current_buffer->yy_ch_buf[
int number_to_move = yy_n_chars + 2;
char *dest = &yy_current_buffer->yy_ch_buf[
yy_current_buffer->yy_buf_size + 2];
register char *source =
char *source =
&yy_current_buffer->yy_ch_buf[number_to_move];
while ( source > yy_current_buffer->yy_ch_buf )
@ -2098,7 +2097,7 @@ yyconst char *s2;
int n;
#endif
{
register int i;
int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@ -2150,7 +2149,7 @@ int main()
return 0;
}
#endif
#line 226 "CMDscan.l"
#line 222 "CMDscan.l"
static const char *scanBuffer;
@ -2341,7 +2340,7 @@ static int Sc_ScanDocBlock()
static int Sc_ScanString(int ret)
{
CMDtext[CMDleng - 1] = 0;
if(!collapseEscape(CMDtext+1))
if(!TorqueScript::getRuntime()->collapseEscapedCharacters(CMDtext+1))
return -1;
dsize_t bufferLen = dStrlen( CMDtext );

View file

@ -23,8 +23,9 @@
#ifndef _AST_H_
#define _AST_H_
class ExprEvalState;
class Namespace;
#include "evalState.h"
#include "platform/types.h"
class SimObject;
class SimGroup;
class CodeStream;
@ -101,7 +102,7 @@ struct StmtNode
#ifndef DEBUG_AST_NODES
# define DBG_STMT_TYPE(s) virtual const char* dbgStmtType() const { return "#s"; }
#else
# define DBG_STMT_TYPE(s)
# define DBG_STMT_TYPE(s)
#endif
struct BreakStmtNode : StmtNode
@ -592,7 +593,14 @@ struct FunctionDeclStmtNode : StmtNode
DBG_STMT_TYPE(FunctionDeclStmtNode);
};
extern StmtNode* gStatementList;
extern ExprEvalState gEvalState;
namespace Script
{
inline ExprEvalState gEvalState;
inline StmtNode *gStatementList;
inline StmtNode *gAnonFunctionList;
inline U32 gAnonFunctionID = 0;
}
#endif

View file

@ -21,7 +21,7 @@
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/compiler.h"
#include "compiler.h"
#include "console/consoleInternal.h"
using namespace Compiler;

View file

@ -22,15 +22,10 @@
#include "platform/platform.h"
#include "console/console.h"
#include "console/telnetDebugger.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "ast.h"
#include "core/strings/findMatch.h"
#include "console/consoleInternal.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "compiler.h"
#include "console/simBase.h"
@ -40,7 +35,7 @@ struct Token
T value;
S32 lineNumber;
};
#include "console/cmdgram.h"
#include "cmdgram.h"
namespace Compiler
{

View file

@ -95,7 +95,7 @@
#include <stdlib.h>
#include <stdio.h>
#include "console/console.h"
#include "console/compiler.h"
#include "compiler.h"
#include "console/consoleInternal.h"
#include "core/strings/stringFunctions.h"
@ -1581,7 +1581,7 @@ case 2:
break;}
case 3:
#line 169 "cmdgram.y"
{ if(!gStatementList) { gStatementList = yyvsp[0].stmt; } else { gStatementList->append(yyvsp[0].stmt); } ;
{ if(!Script::gStatementList) { Script::gStatementList = yyvsp[0].stmt; } else { Script::gStatementList->append(yyvsp[0].stmt); } ;
break;}
case 4:
#line 174 "cmdgram.y"
@ -2390,5 +2390,3 @@ yyerrhandle:
goto yynewstate;
}
#line 617 "cmdgram.y"

View file

@ -1,3 +1,6 @@
#ifndef _CMDGRAM_H_
#define _CMDGRAM_H_
typedef union {
Token< char > c;
Token< int > i;
@ -90,3 +93,5 @@ typedef union {
extern YYSTYPE CMDlval;
#endif

View file

@ -21,10 +21,11 @@
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/compiler.h"
#include "console/codeBlock.h"
#include "compiler.h"
#include "codeBlock.h"
#include "ast.h"
#include "console/telnetDebugger.h"
#include "console/ast.h"
#include "core/strings/unicode.h"
#include "core/strings/stringFunctions.h"
#include "core/stringTable.h"
@ -34,8 +35,7 @@ using namespace Compiler;
bool CodeBlock::smInFunction = false;
CodeBlock * CodeBlock::smCodeBlockList = NULL;
CodeBlock * CodeBlock::smCurrentCodeBlock = NULL;
ConsoleParser *CodeBlock::smCurrentParser = NULL;
TorqueScriptParser *CodeBlock::smCurrentParser = NULL;
extern FuncVars gEvalFuncVars;
extern FuncVars gGlobalScopeFuncVars;
@ -52,8 +52,6 @@ CodeBlock::CodeBlock()
globalFloats = NULL;
functionFloats = NULL;
lineBreakPairs = NULL;
breakList = NULL;
breakListSize = 0;
refCount = 0;
code = NULL;
@ -68,7 +66,7 @@ CodeBlock::CodeBlock()
CodeBlock::~CodeBlock()
{
// Make sure we aren't lingering in the current code block...
AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
AssertFatal(Con::getCurrentScriptModule() != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
if (name)
removeFromCodeList();
@ -81,35 +79,10 @@ CodeBlock::~CodeBlock()
delete[] globalFloats;
delete[] functionFloats;
delete[] code;
delete[] breakList;
}
//-------------------------------------------------------------------------
StringTableEntry CodeBlock::getCurrentCodeBlockName()
{
if (CodeBlock::getCurrentBlock())
return CodeBlock::getCurrentBlock()->name;
else
return NULL;
}
StringTableEntry CodeBlock::getCurrentCodeBlockFullPath()
{
if (CodeBlock::getCurrentBlock())
return CodeBlock::getCurrentBlock()->fullPath;
else
return NULL;
}
StringTableEntry CodeBlock::getCurrentCodeBlockModName()
{
if (CodeBlock::getCurrentBlock())
return CodeBlock::getCurrentBlock()->modPath;
else
return NULL;
}
CodeBlock *CodeBlock::find(StringTableEntry name)
{
for (CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
@ -309,8 +282,7 @@ void CodeBlock::calcBreakList()
if (seqCount)
size++;
breakList = new U32[size+3]; //lineBreakPairs plus pad
breakListSize = size;
breakList.setSize(size+3); //lineBreakPairs plus pad
line = -1;
seqCount = 0;
size = 0;
@ -502,10 +474,10 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
STEtoCode = compileSTEtoCode;
gStatementList = NULL;
Script::gStatementList = NULL;
// Set up the parser.
smCurrentParser = getParserForFile(fileName);
smCurrentParser = new TorqueScriptParser();
AssertISV(smCurrentParser, avar("CodeBlock::compile - no parser available for '%s'!", fileName));
// Now do some parsing.
@ -536,9 +508,9 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
CodeStream codeStream;
U32 lastIp;
if (gStatementList)
if (Script::gStatementList)
{
lastIp = compileBlock(gStatementList, codeStream, 0) + 1;
lastIp = compileBlock(Script::gStatementList, codeStream, 0) + 1;
}
else
{
@ -594,7 +566,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
return true;
}
ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
{
AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
@ -634,14 +606,14 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
if (name)
addToCodeList();
gStatementList = NULL;
Script::gStatementList = NULL;
// we are an eval compile if we don't have a file name associated (no exec)
gIsEvalCompile = fileName == NULL;
gFuncVars = gIsEvalCompile ? &gEvalFuncVars : &gGlobalScopeFuncVars;
// Set up the parser.
smCurrentParser = getParserForFile(fileName);
smCurrentParser = new TorqueScriptParser();
AssertISV(smCurrentParser, avar("CodeBlock::compile - no parser available for '%s'!", fileName));
// Now do some parsing.
@ -649,10 +621,10 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
smCurrentParser->restart(NULL);
smCurrentParser->parse();
if (!gStatementList)
if (!Script::gStatementList)
{
delete this;
return std::move(ConsoleValue());
return Con::EvalResult(Con::getVariable("$ScriptError"));
}
resetTables();
@ -660,7 +632,7 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
smInFunction = false;
CodeStream codeStream;
U32 lastIp = compileBlock(gStatementList, codeStream, 0);
U32 lastIp = compileBlock(Script::gStatementList, codeStream, 0);
lineBreakPairCount = codeStream.getNumLineBreaks();
@ -677,7 +649,7 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
codeStream.emit(OP_RETURN_VOID);
codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
S32 localRegisterCount = gIsEvalCompile ? gEvalFuncVars.count() : gGlobalScopeFuncVars.count();
consoleAllocReset();
@ -701,20 +673,6 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
//-------------------------------------------------------------------------
void CodeBlock::incRefCount()
{
refCount++;
}
void CodeBlock::decRefCount()
{
refCount--;
if (!refCount)
delete this;
}
//-------------------------------------------------------------------------
String CodeBlock::getFunctionArgs(U32 ip)
{
StringBuilder str;

View file

@ -26,6 +26,9 @@
#include <vector>
#include <unordered_map>
#include "parser.h"
#include "console/runtime.h"
struct CompilerLocalVariableToRegisterMappingTable
{
struct RemappingTable
@ -42,8 +45,7 @@ struct CompilerLocalVariableToRegisterMappingTable
void write(Stream& stream);
};
#include "console/compiler.h"
#include "console/consoleParser.h"
#include "compiler.h"
class Stream;
class ConsoleValue;
@ -51,33 +53,24 @@ class ConsoleValue;
/// Core TorqueScript code management class.
///
/// This class represents a block of code, usually mapped directly to a file.
class CodeBlock
class CodeBlock : Con::Module
{
private:
static CodeBlock* smCodeBlockList;
static CodeBlock* smCurrentCodeBlock;
public:
static bool smInFunction;
static Compiler::ConsoleParser * smCurrentParser;
static CodeBlock* getCurrentBlock()
{
return smCurrentCodeBlock;
}
static TorqueScriptParser * smCurrentParser;
static CodeBlock *getCodeBlockList()
{
return smCodeBlockList;
}
static StringTableEntry getCurrentCodeBlockName();
static StringTableEntry getCurrentCodeBlockFullPath();
static StringTableEntry getCurrentCodeBlockModName();
static CodeBlock *find(StringTableEntry);
CodeBlock();
~CodeBlock();
~CodeBlock() override;
StringTableEntry name;
StringTableEntry fullPath;
@ -100,59 +93,55 @@ public:
U32 refCount;
U32 lineBreakPairCount;
U32 *lineBreakPairs;
U32 breakListSize;
U32 *breakList;
Vector<U32> breakList;
CodeBlock *nextFile;
void addToCodeList();
void removeFromCodeList();
void calcBreakList();
void clearAllBreaks();
void setAllBreaks();
void clearAllBreaks() override;
void setAllBreaks() override;
void dumpInstructions(U32 startIp = 0, bool upToReturn = false);
/// Returns the first breakable line or 0 if none was found.
/// @param lineNumber The one based line number.
U32 findFirstBreakLine(U32 lineNumber);
U32 findFirstBreakLine(U32 lineNumber) override;
void clearBreakpoint(U32 lineNumber);
void clearBreakpoint(U32 lineNumber) override;
/// Set a OP_BREAK instruction on a line. If a break
/// Set a OP_BREAK instruction on a line. If a break
/// is not possible on that line it returns false.
/// @param lineNumber The one based line number.
bool setBreakpoint(U32 lineNumber);
bool setBreakpoint(U32 lineNumber) override;
void findBreakLine(U32 ip, U32 &line, U32 &instruction);
const char *getFileLine(U32 ip);
void findBreakLine(U32 ip, U32 &line, U32 &instruction) override;
const char *getFileLine(U32 ip) override;
///
///
String getFunctionArgs(U32 offset);
bool read(StringTableEntry fileName, Stream &st);
bool compile(const char *dsoName, StringTableEntry fileName, const char *script, bool overrideNoDso = false);
void incRefCount();
void decRefCount();
/// Compiles and executes a block of script storing the compiled code in this
/// CodeBlock. If there is no filename breakpoints will not be generated and
/// the CodeBlock will not be added to the linked list of loaded CodeBlocks.
/// CodeBlock. If there is no filename breakpoints will not be generated and
/// the CodeBlock will not be added to the linked list of loaded CodeBlocks.
/// Note that if the script contains no executable statements the CodeBlock
/// will delete itself on return an empty string. The return string is any
/// will delete itself on return an empty string. The return string is any
/// result of the code executed, if any, or an empty string.
///
/// @param fileName The file name, including path and extension, for the
/// @param fileName The file name, including path and extension, for the
/// block of code or an empty string.
/// @param script The script code to compile and execute.
/// @param noCalls Skips calling functions from the script.
/// @param setFrame A zero based index of the stack frame to execute the code
/// @param setFrame A zero based index of the stack frame to execute the code
/// with, zero being the top of the stack. If the the index is
/// -1 a new frame is created. If the index is out of range the
/// top stack frame is used.
ConsoleValue compileExec(StringTableEntry fileName, const char *script,
Con::EvalResult compileExec(StringTableEntry fileName, const char *script,
bool noCalls, S32 setFrame = -1);
/// Executes the existing code in the CodeBlock. The return string is any
/// Executes the existing code in the CodeBlock. The return string is any
/// result of the code executed, if any, or an empty string.
///
/// @param offset The instruction offset to start executing from.
@ -162,14 +151,20 @@ public:
/// zero to execute code outside of a function.
/// @param argv The function parameter list.
/// @param noCalls Skips calling functions from the script.
/// @param setFrame A zero based index of the stack frame to execute the code
/// @param setFrame A zero based index of the stack frame to execute the code
/// with, zero being the top of the stack. If the the index is
/// -1 a new frame is created. If the index is out of range the
/// top stack frame is used.
/// @param packageName The code package name or null.
ConsoleValue exec(U32 offset, const char *fnName, Namespace *ns, U32 argc,
ConsoleValue *argv, bool noCalls, StringTableEntry packageName,
S32 setFrame = -1);
Con::EvalResult exec(U32 offset, const char* fnName, Namespace* ns, U32 argc,
ConsoleValue* argv, bool noCalls, StringTableEntry packageName,
S32 setFrame = -1) override;
const char* getFunctionArgs(StringTableEntry functionName, U32 functionOffset) override { return getFunctionArgs(functionOffset); }
const char* getPath() override { return fullPath; }
const char* getName() override { return name; }
Vector<U32> getBreakableLines() override { return breakList; }
};
#endif

View file

@ -23,31 +23,25 @@
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "ast.h"
#include "compiler.h"
#include "core/strings/findMatch.h"
#include "core/strings/stringUnit.h"
#include "console/consoleInternal.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "console/simBase.h"
#include "console/telnetDebugger.h"
#include "sim/netStringTable.h"
#include "console/ICallMethod.h"
#include "console/stringStack.h"
#include "util/messaging/message.h"
#include "core/frameAllocator.h"
#include "console/returnBuffer.h"
#include "console/consoleValueStack.h"
#include "console/telnetDebugger.h"
#ifndef TORQUE_TGB_ONLY
#include "materials/materialDefinition.h"
#include "materials/materialManager.h"
#endif
using namespace Compiler;
@ -116,6 +110,13 @@ U32 _ITER = 0; ///< Stack pointer for iterStack.
ConsoleValue stack[MaxStackSize];
S32 _STK = 0;
ReturnBuffer retBuffer;
char *getReturnBuffer(U32 bufferSize)
{
return retBuffer.getBuffer(bufferSize);
}
const char* tsconcat(const char* strA, const char* strB, S32& outputLen)
{
S32 lenA = dStrlen(strA);
@ -150,7 +151,7 @@ namespace Con
Namespace * walk;
for (walk = ns; walk; walk = walk->mParent)
size += dStrlen(walk->mName) + 4;
char *ret = Con::getReturnBuffer(size);
char *ret = getReturnBuffer(size);
ret[0] = 0;
for (walk = ns; walk; walk = walk->mParent)
{
@ -169,9 +170,9 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c
if (object && field)
prevVal = object->getDataField(field, array);
else if (currentLocalRegister != -1)
prevVal = gEvalState.getLocalStringVariable(currentLocalRegister);
else if (gEvalState.currentVariable)
prevVal = gEvalState.getStringVariable();
prevVal = Script::gEvalState.getLocalStringVariable(currentLocalRegister);
else if (Script::gEvalState.currentVariable)
prevVal = Script::gEvalState.getStringVariable();
// Make sure we got a value.
if (prevVal && *prevVal)
@ -192,7 +193,7 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c
StringTable->insert("a")
};
// Translate xyzw and rgba into the indexed component
// Translate xyzw and rgba into the indexed component
// of the variable or field.
if (subField == xyzw[0] || subField == rgba[0])
dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"), 128);
@ -225,10 +226,10 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
if (object && field)
prevVal = object->getDataField(field, array);
else if (currentLocalRegister != -1)
prevVal = gEvalState.getLocalStringVariable(currentLocalRegister);
prevVal = Script::gEvalState.getLocalStringVariable(currentLocalRegister);
// Set the value on a variable.
else if (gEvalState.currentVariable)
prevVal = gEvalState.getStringVariable();
else if (Script::gEvalState.currentVariable)
prevVal = Script::gEvalState.getStringVariable();
// Ensure that the variable has a value
if (!prevVal)
@ -250,7 +251,7 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
StringTable->insert("a")
};
// Insert the value into the specified
// Insert the value into the specified
// component of the string.
if (subField == xyzw[0] || subField == rgba[0])
dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"), 128);
@ -270,9 +271,9 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
if (object && field)
object->setDataField(field, 0, val);
else if (currentLocalRegister != -1)
gEvalState.setLocalStringVariable(currentLocalRegister, val, dStrlen(val));
else if (gEvalState.currentVariable)
gEvalState.setStringVariable(val);
Script::gEvalState.setLocalStringVariable(currentLocalRegister, val, dStrlen(val));
else if (Script::gEvalState.currentVariable)
Script::gEvalState.setStringVariable(val);
}
}
@ -295,83 +296,26 @@ F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line)
return 0;
}
//------------------------------------------------------------
namespace Con
SimObject* getThisObject(ConsoleValue& simObjectLookupValue)
{
ReturnBuffer retBuffer;
SimObject* thisObject = NULL;
char *getReturnBuffer(U32 bufferSize)
// Optimization: If we're an integer, we can lookup the value by SimObjectId
if (simObjectLookupValue.getType() == ConsoleValueType::cvInteger)
thisObject = Sim::findObject(static_cast<SimObjectId>(simObjectLookupValue.getFastInt()));
else
{
return retBuffer.getBuffer(bufferSize);
SimObject *foundObject = Sim::findObject(simObjectLookupValue.getString());
// Optimization: If we're not an integer, let's make it so that the fast path exists
// on the first argument of the method call (speeds up future usage of %this, for example)
if (foundObject != NULL)
simObjectLookupValue.setInt(static_cast<S64>(foundObject->getId()));
thisObject = foundObject;
}
char *getReturnBuffer(const char *stringToCopy)
{
U32 len = dStrlen(stringToCopy) + 1;
char *ret = retBuffer.getBuffer(len);
dMemcpy(ret, stringToCopy, len);
return ret;
}
char* getReturnBuffer(const String& str)
{
const U32 size = str.size();
char* ret = retBuffer.getBuffer(size);
dMemcpy(ret, str.c_str(), size);
return ret;
}
char* getReturnBuffer(const StringBuilder& str)
{
char* buffer = Con::getReturnBuffer(str.length() + 1);
str.copy(buffer);
buffer[str.length()] = '\0';
return buffer;
}
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;
}
char* getBoolArg(bool arg)
{
char *ret = STR.getArgBuffer(32);
dSprintf(ret, 32, "%d", arg);
return ret;
}
char *getStringArg(const char *arg)
{
U32 len = dStrlen(arg) + 1;
char *ret = STR.getArgBuffer(len);
dMemcpy(ret, arg, len);
return ret;
}
char* getStringArg(const String& arg)
{
const U32 size = arg.size();
char* ret = STR.getArgBuffer(size);
dMemcpy(ret, arg.c_str(), size);
return ret;
}
return thisObject;
}
//------------------------------------------------------------
@ -379,7 +323,7 @@ namespace Con
void ExprEvalState::setCurVarName(StringTableEntry name)
{
if (name[0] == '$')
currentVariable = globalVars.lookup(name);
currentVariable = Con::gGlobalVars.lookup(name);
else if (getStackDepth() > 0)
currentVariable = getCurrentFrame().lookup(name);
if (!currentVariable && gWarnUndefinedScriptVariables)
@ -389,7 +333,7 @@ void ExprEvalState::setCurVarName(StringTableEntry name)
void ExprEvalState::setCurVarNameCreate(StringTableEntry name)
{
if (name[0] == '$')
currentVariable = globalVars.add(name);
currentVariable = Con::gGlobalVars.add(name);
else if (getStackDepth() > 0)
currentVariable = getCurrentFrame().add(name);
else
@ -605,7 +549,7 @@ TORQUE_FORCEINLINE void doIntOperation()
//-----------------------------------------------------------------------------
U32 gExecCount = 0;
ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
{
#ifdef TORQUE_DEBUG
U32 stackStart = _STK;
@ -633,7 +577,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
U32 regCount = code[ip + 2 + 7];
thisFunctionName = CodeToSTE(code, ip);
S32 wantedArgc = getMin(argc - 1, fnArgc); // argv[0] is func name
if (gEvalState.traceOn)
if (Con::gTraceOn)
{
traceBuffer[0] = 0;
dStrcat(traceBuffer, "Entering ", TRACE_BUFFER_SIZE);
@ -662,13 +606,13 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
dStrcat(traceBuffer, ")", TRACE_BUFFER_SIZE);
Con::printf("%s", traceBuffer);
}
gEvalState.pushFrame(thisFunctionName, thisNamespace, regCount);
Script::gEvalState.pushFrame(thisFunctionName, thisNamespace, regCount);
popFrame = true;
for (i = 0; i < wantedArgc; i++)
{
S32 reg = code[ip + (2 + 6 + 1 + 1) + i];
ConsoleValue& value = argv[i + 1];
gEvalState.moveConsoleValue(reg, std::move(value));
Script::gEvalState.moveConsoleValue(reg, std::move(value));
}
ip = ip + fnArgc + (2 + 6 + 1 + 1);
curFloatTable = functionFloats;
@ -684,7 +628,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// If requested stack frame isn't available, request a new one
// (this prevents assert failures when creating local
// variables without a stack frame)
if (gEvalState.getStackDepth() <= setFrame)
if (Script::gEvalState.getStackDepth() <= setFrame)
setFrame = -1;
// Do we want this code to execute using a new stack frame?
@ -692,8 +636,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (setFrame <= 0)
{
// argc is the local count for eval
gEvalState.pushFrame(NULL, NULL, argc);
popFrame = true;
Script::gEvalState.pushFrame(NULL, NULL, argc);
}
else
{
@ -701,12 +644,16 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// on to the top of the stack. Any change that occurs to
// the locals during this new frame will also occur in the
// original frame.
S32 stackIndex = gEvalState.getTopOfStack() - setFrame - 1;
gEvalState.pushFrameRef(stackIndex);
popFrame = true;
S32 stackIndex = Script::gEvalState.getTopOfStack() - setFrame - 1;
Script::gEvalState.pushFrameRef(stackIndex);
}
popFrame = true;
}
Script::gEvalState.getCurrentFrame().module = this;
Script::gEvalState.getCurrentFrame().ip = ip;
// 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();
@ -730,7 +677,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
StringTableEntry curField = NULL;
SimObject* prevObject = NULL;
SimObject* curObject = NULL;
SimObject* saveObject = NULL;
SimObject* thisObject = NULL;
Namespace::Entry* nsEntry;
Namespace* ns = NULL;
const char* curFNDocBlock = NULL;
@ -744,8 +691,6 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
static char curFieldArray[256];
static char prevFieldArray[256];
CodeBlock* saveCodeBlock = smCurrentCodeBlock;
smCurrentCodeBlock = this;
if (this->name)
{
Con::gCurrentFile = this->name;
@ -1402,7 +1347,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
case OP_INC:
reg = code[ip++];
currentRegister = reg;
gEvalState.setLocalFloatVariable(reg, gEvalState.getLocalFloatVariable(reg) + 1.0);
Script::gEvalState.setLocalFloatVariable(reg, Script::gEvalState.getLocalFloatVariable(reg) + 1.0);
break;
case OP_SETCURVAR:
@ -1420,7 +1365,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// set a global, we aren't active
currentRegister = -1;
gEvalState.setCurVarName(var);
Script::gEvalState.setCurVarName(var);
// In order to let docblocks work properly with variables, we have
// clear the current docblock when we do an assign. This way it
@ -1442,7 +1387,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// set a global, we aren't active
currentRegister = -1;
gEvalState.setCurVarNameCreate(var);
Script::gEvalState.setCurVarNameCreate(var);
// See OP_SETCURVAR for why we do this.
curFNDocBlock = NULL;
@ -1461,7 +1406,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// set a global, we aren't active
currentRegister = -1;
gEvalState.setCurVarName(var);
Script::gEvalState.setCurVarName(var);
// See OP_SETCURVAR for why we do this.
curFNDocBlock = NULL;
@ -1480,7 +1425,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
// set a global, we aren't active
currentRegister = -1;
gEvalState.setCurVarNameCreate(var);
Script::gEvalState.setCurVarNameCreate(var);
// See OP_SETCURVAR for why we do this.
curFNDocBlock = NULL;
@ -1489,32 +1434,32 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
case OP_LOADVAR_UINT:
currentRegister = -1;
stack[_STK + 1].setInt(gEvalState.getIntVariable());
stack[_STK + 1].setInt(Script::gEvalState.getIntVariable());
_STK++;
break;
case OP_LOADVAR_FLT:
currentRegister = -1;
stack[_STK + 1].setFloat(gEvalState.getFloatVariable());
stack[_STK + 1].setFloat(Script::gEvalState.getFloatVariable());
_STK++;
break;
case OP_LOADVAR_STR:
currentRegister = -1;
stack[_STK + 1].setString(gEvalState.getStringVariable());
stack[_STK + 1].setString(Script::gEvalState.getStringVariable());
_STK++;
break;
case OP_SAVEVAR_UINT:
gEvalState.setIntVariable(stack[_STK].getInt());
Script::gEvalState.setIntVariable(stack[_STK].getInt());
break;
case OP_SAVEVAR_FLT:
gEvalState.setFloatVariable(stack[_STK].getFloat());
Script::gEvalState.setFloatVariable(stack[_STK].getFloat());
break;
case OP_SAVEVAR_STR:
gEvalState.setStringVariable(stack[_STK].getString());
Script::gEvalState.setStringVariable(stack[_STK].getString());
break;
case OP_LOAD_LOCAL_VAR_UINT:
@ -1526,7 +1471,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
stack[_STK + 1].setInt(gEvalState.getLocalIntVariable(reg));
stack[_STK + 1].setInt(Script::gEvalState.getLocalIntVariable(reg));
_STK++;
break;
@ -1539,7 +1484,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
stack[_STK + 1].setFloat(gEvalState.getLocalFloatVariable(reg));
stack[_STK + 1].setFloat(Script::gEvalState.getLocalFloatVariable(reg));
_STK++;
break;
@ -1552,7 +1497,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
val = gEvalState.getLocalStringVariable(reg);
val = Script::gEvalState.getLocalStringVariable(reg);
stack[_STK + 1].setString(val);
_STK++;
break;
@ -1566,7 +1511,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
gEvalState.setLocalIntVariable(reg, stack[_STK].getInt());
Script::gEvalState.setLocalIntVariable(reg, stack[_STK].getInt());
break;
case OP_SAVE_LOCAL_VAR_FLT:
@ -1578,7 +1523,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
gEvalState.setLocalFloatVariable(reg, stack[_STK].getFloat());
Script::gEvalState.setLocalFloatVariable(reg, stack[_STK].getFloat());
break;
case OP_SAVE_LOCAL_VAR_STR:
@ -1591,7 +1536,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
prevObject = NULL;
curObject = NULL;
gEvalState.setLocalStringVariable(reg, val, (S32)dStrlen(val));
Script::gEvalState.setLocalStringVariable(reg, val, (S32)dStrlen(val));
break;
case OP_SETCUROBJECT:
@ -1820,10 +1765,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
U32 callType = code[ip + 4];
//if this is called from inside a function, append the ip and codeptr
if (!gEvalState.stack.empty())
if (!Script::gEvalState.stack.empty())
{
gEvalState.getCurrentFrame().code = this;
gEvalState.getCurrentFrame().ip = ip - 1;
Script::gEvalState.getCurrentFrame().module = this;
Script::gEvalState.getCurrentFrame().ip = ip - 1;
}
ip += 5;
@ -1868,25 +1813,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
else if (callType == FuncCallExprNode::MethodCall)
{
saveObject = gEvalState.thisObject;
ConsoleValue& simObjectLookupValue = callArgv[1];
thisObject = getThisObject(simObjectLookupValue);
// Optimization: If we're an integer, we can lookup the value by SimObjectId
const ConsoleValue& simObjectLookupValue = callArgv[1];
if (simObjectLookupValue.getType() == ConsoleValueType::cvInteger)
gEvalState.thisObject = Sim::findObject(static_cast<SimObjectId>(simObjectLookupValue.getFastInt()));
else
{
SimObject *foundObject = Sim::findObject(simObjectLookupValue.getString());
// Optimization: If we're not an integer, let's make it so that the fast path exists
// on the first argument of the method call (speeds up future usage of %this, for example)
if (foundObject != NULL)
callArgv[1].setInt(static_cast<S64>(foundObject->getId()));
gEvalState.thisObject = foundObject;
}
if (gEvalState.thisObject == NULL)
if (thisObject == NULL)
{
Con::warnf(
ConsoleLogEntry::General,
@ -1902,7 +1832,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
break;
}
ns = gEvalState.thisObject->getNamespace();
ns = thisObject->getNamespace();
if (ns)
nsEntry = ns->lookup(fnName);
else
@ -1910,6 +1840,25 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
else // it's a ParentCall
{
ConsoleValue& simObjectLookupValue = callArgv[1];
thisObject = getThisObject(simObjectLookupValue);
if (thisObject == NULL)
{
Con::warnf(
ConsoleLogEntry::General,
"%s: Unable to find object: '%s' attempting to call function '%s'",
getFileLine(ip - 6),
simObjectLookupValue.getString(),
fnName
);
gCallStack.popFrame();
stack[_STK + 1].setEmptyString();
_STK++;
break;
}
if (thisNamespace)
{
ns = thisNamespace->mParent;
@ -1933,8 +1882,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (callType == FuncCallExprNode::MethodCall)
{
Con::warnf(ConsoleLogEntry::General, " Object %s(%d) %s",
gEvalState.thisObject->getName() ? gEvalState.thisObject->getName() : "",
gEvalState.thisObject->getId(), Con::getNamespaceList(ns));
thisObject->getName() ? thisObject->getName() : "",
thisObject->getId(), Con::getNamespaceList(ns));
}
}
gCallStack.popFrame();
@ -1946,7 +1895,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
{
if (nsEntry->mFunctionOffset)
{
ConsoleValue returnFromFn = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);
ConsoleValue returnFromFn = nsEntry->mModule->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage).value;
stack[_STK + 1] = std::move(returnFromFn);
}
else // no body
@ -1972,7 +1921,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
{
case Namespace::Entry::StringCallbackType:
{
const char* result = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
const char* result = nsEntry->cb.mStringCallbackFunc(thisObject, callArgc, callArgv);
gCallStack.popFrame();
stack[_STK + 1].setString(result);
_STK++;
@ -1980,7 +1929,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
case Namespace::Entry::IntCallbackType:
{
S64 result = nsEntry->cb.mIntCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
S64 result = nsEntry->cb.mIntCallbackFunc(thisObject, callArgc, callArgv);
gCallStack.popFrame();
if (code[ip] == OP_POP_STK)
@ -1995,7 +1944,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
case Namespace::Entry::FloatCallbackType:
{
F64 result = nsEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
F64 result = nsEntry->cb.mFloatCallbackFunc(thisObject, callArgc, callArgv);
gCallStack.popFrame();
if (code[ip] == OP_POP_STK)
@ -2010,7 +1959,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
case Namespace::Entry::VoidCallbackType:
{
nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
nsEntry->cb.mVoidCallbackFunc(thisObject, callArgc, callArgv);
gCallStack.popFrame();
if (code[ip] == OP_POP_STK)
@ -2023,7 +1972,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
{
Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip - 4), fnName, functionName);
}
stack[_STK + 1].setEmptyString();
_STK++;
@ -2031,7 +1980,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
case Namespace::Entry::BoolCallbackType:
{
bool result = nsEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
bool result = nsEntry->cb.mBoolCallbackFunc(thisObject, callArgc, callArgv);
gCallStack.popFrame();
if (code[ip] == OP_POP_STK)
@ -2048,9 +1997,6 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
}
}
}
if (callType == FuncCallExprNode::MethodCall)
gEvalState.thisObject = saveObject;
break;
}
@ -2122,9 +2068,9 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
case OP_BREAK:
{
//append the ip and codeptr before managing the breakpoint!
AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
gEvalState.getCurrentFrame().code = this;
gEvalState.getCurrentFrame().ip = ip - 1;
AssertFatal(!Script::gEvalState.stack.empty(), "Empty eval stack on break!");
Script::gEvalState.getCurrentFrame().module = this;
Script::gEvalState.getCurrentFrame().ip = ip - 1;
U32 breakLine;
findBreakLine(ip - 1, breakLine, instruction);
@ -2153,7 +2099,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (isGlobal)
{
StringTableEntry varName = CodeToSTE(code, ip + 1);
iter.mVar.mVariable = gEvalState.globalVars.add(varName);
iter.mVar.mVariable = Con::gGlobalVars.add(varName);
}
else
{
@ -2227,7 +2173,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (iter.mIsGlobalVariable)
iter.mVar.mVariable->setStringValue(&str[startIndex]);
else
gEvalState.setLocalStringVariable(iter.mVar.mRegister, &str[startIndex], endIndex - startIndex);
Script::gEvalState.setLocalStringVariable(iter.mVar.mRegister, &str[startIndex], endIndex - startIndex);
const_cast<char*>(str)[endIndex] = savedChar;
}
@ -2236,7 +2182,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (iter.mIsGlobalVariable)
iter.mVar.mVariable->setStringValue("");
else
gEvalState.setLocalStringVariable(iter.mVar.mRegister, "", 0);
Script::gEvalState.setLocalStringVariable(iter.mVar.mRegister, "", 0);
}
// Skip separator.
@ -2261,7 +2207,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
if (iter.mIsGlobalVariable)
iter.mVar.mVariable->setIntValue(id);
else
gEvalState.setLocalIntVariable(iter.mVar.mRegister, id);
Script::gEvalState.setLocalIntVariable(iter.mVar.mRegister, id);
iter.mData.mObj.mIndex = index + 1;
}
@ -2296,12 +2242,12 @@ execFinished:
if (popFrame)
{
gEvalState.popFrame();
Script::gEvalState.popFrame();
}
if (argv)
{
if (gEvalState.traceOn)
if (Con::gTraceOn)
{
traceBuffer[0] = 0;
dStrcat(traceBuffer, "Leaving ", TRACE_BUFFER_SIZE);
@ -2332,11 +2278,11 @@ execFinished:
globalStrings = NULL;
globalFloats = NULL;
}
smCurrentCodeBlock = saveCodeBlock;
if (saveCodeBlock && saveCodeBlock->name)
if (Con::getCurrentScriptModuleName())
{
Con::gCurrentFile = saveCodeBlock->name;
Con::gCurrentRoot = saveCodeBlock->modPath;
Con::gCurrentFile = Con::getCurrentScriptModuleName();
Con::gCurrentRoot = Con::getModNameFromPath(Con::getCurrentScriptModulePath());
}
decRefCount();
@ -2346,7 +2292,7 @@ execFinished:
AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec");
#endif
return returnValue;
return Con::EvalResult(std::move(returnValue));
}
//------------------------------------------------------------

View file

@ -22,16 +22,8 @@
#include "platform/platform.h"
#include "console/console.h"
#include "console/telnetDebugger.h"
#include "console/ast.h"
#include "core/tAlgorithm.h"
#include "core/strings/findMatch.h"
#include "console/consoleInternal.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "compiler.h"
#include "console/simBase.h"
extern FuncVars gEvalFuncVars;
@ -178,15 +170,15 @@ S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber,
S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber)
{
std::unordered_map<StringTableEntry, Var>::iterator found = vars.find(var);
if (found == vars.end())
{
const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber);
scriptErrorHandler(str);
return assign(var, TypeReqString, lineNumber, false);
}
return found->second.reg;
}
@ -198,11 +190,11 @@ TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber)
{
const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber);
scriptErrorHandler(str);
assign(var, TypeReqString, lineNumber, false);
return vars.find(var)->second.currentType;
}
return found->second.currentType;
}
@ -561,4 +553,3 @@ void CodeStream::reset()
mCodeHead = mCode;
}
}

View file

@ -33,12 +33,14 @@
#include <string>
#include <unordered_map>
class CodeStream;
struct StmtNode;
class Stream;
class DataChunker;
#include "platform/platform.h"
#include "console/ast.h"
#include "console/codeBlock.h"
#include "ast.h"
#include "codeBlock.h"
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
@ -297,13 +299,13 @@ public:
S32 lookup(StringTableEntry var, S32 lineNumber);
TypeReq lookupType(StringTableEntry var, S32 lineNumber);
inline S32 count() { return counter; }
std::unordered_map<S32, StringTableEntry> variableNameMap;
void clear();
private:
std::unordered_map<StringTableEntry, Var> vars;
S32 counter = 0;

View file

@ -0,0 +1,157 @@

#include "evalState.h"
void ExprEvalState::pushFrame(StringTableEntry frameName, Namespace *ns, S32 registerCount)
{
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Pushing new frame for '%s' at %i",
frameName, mStackDepth);
#endif
if (mStackDepth + 1 > stack.size())
{
#ifdef DEBUG_SPEW
Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
#endif
stack.push_back(new Dictionary);
}
Dictionary& newFrame = *(stack[mStackDepth]);
newFrame.setState();
newFrame.scopeName = frameName;
newFrame.scopeNamespace = ns;
Con::pushStackFrame(stack[mStackDepth]);
mStackDepth++;
currentVariable = NULL;
AssertFatal(!newFrame.getCount(), "ExprEvalState::pushFrame - Dictionary not empty!");
ConsoleValue* consoleValArray = new ConsoleValue[registerCount]();
localStack.push_back(ConsoleValueFrame(consoleValArray, false));
currentRegisterArray = &localStack.last();
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::popFrame()
{
AssertFatal(mStackDepth > 0, "ExprEvalState::popFrame - Stack Underflow!");
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Popping %sframe at %i",
getCurrentFrame().isOwner() ? "" : "shared ", mStackDepth - 1);
#endif
Con::popStackFrame();
mStackDepth--;
stack[mStackDepth]->reset();
currentVariable = NULL;
const ConsoleValueFrame& frame = localStack.last();
localStack.pop_back();
if (!frame.isReference)
delete[] frame.values;
currentRegisterArray = localStack.size() ? &localStack.last() : NULL;
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::pushFrameRef(S32 stackIndex)
{
AssertFatal(stackIndex >= 0 && stackIndex < mStackDepth, "You must be asking for a valid frame!");
#ifdef DEBUG_SPEW
validate();
Platform::outputDebugString("[ConsoleInternal] Cloning frame from %i to %i",
stackIndex, mStackDepth);
#endif
if (mStackDepth + 1 > stack.size())
{
#ifdef DEBUG_SPEW
Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
#endif
stack.push_back(new Dictionary);
}
Dictionary& newFrame = *(stack[mStackDepth]);
newFrame.setState(stack[stackIndex]);
Con::pushStackFrame(stack[mStackDepth]);
mStackDepth++;
currentVariable = NULL;
ConsoleValue* values = localStack[stackIndex].values;
localStack.push_back(ConsoleValueFrame(values, true));
currentRegisterArray = &localStack.last();
AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
#ifdef DEBUG_SPEW
validate();
#endif
}
void ExprEvalState::pushDebugFrame(S32 stackIndex)
{
pushFrameRef(stackIndex);
Dictionary& newFrame = *(stack[mStackDepth - 1]);
// debugger needs to know this info...
newFrame.scopeName = stack[stackIndex]->scopeName;
newFrame.scopeNamespace = stack[stackIndex]->scopeNamespace;
newFrame.module = stack[stackIndex]->module;
newFrame.ip = stack[stackIndex]->ip;
}
ExprEvalState::ExprEvalState()
{
VECTOR_SET_ASSOCIATION(stack);
currentVariable = NULL;
mStackDepth = 0;
stack.reserve(64);
mShouldReset = false;
mResetLocked = false;
copyVariable = NULL;
currentRegisterArray = NULL;
}
ExprEvalState::~ExprEvalState()
{
// Delete callframes.
while (!stack.empty())
{
delete stack.last();
stack.decrement();
}
}
void ExprEvalState::validate()
{
AssertFatal(mStackDepth <= stack.size(),
"ExprEvalState::validate() - Stack depth pointing beyond last stack frame!");
for (U32 i = 0; i < stack.size(); ++i)
stack[i]->validate();
}

View file

@ -0,0 +1,119 @@
#ifndef _EVALSTATE_H
#define _EVALSTATE_H
#include "console/consoleInternal.h"
class ExprEvalState
{
public:
/// @name Expression Evaluation
/// @{
///
Dictionary::Entry *currentVariable;
Dictionary::Entry *copyVariable;
U32 mStackDepth;
bool mShouldReset; ///< Designates if the value stack should be reset
bool mResetLocked; ///< mShouldReset will be set at the end
ExprEvalState();
~ExprEvalState();
/// @}
/// @name Stack Management
/// @{
/// The stack of callframes. The extra redirection is necessary since Dictionary holds
/// an interior pointer that will become invalid when the object changes address.
Vector< Dictionary* > stack;
S32 getTopOfStack() { return (S32)mStackDepth; }
Vector< ConsoleValueFrame > localStack;
ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
///
void setCurVarName(StringTableEntry name);
void setCurVarNameCreate(StringTableEntry name);
S32 getIntVariable();
F64 getFloatVariable();
const char *getStringVariable();
void setIntVariable(S32 val);
void setFloatVariable(F64 val);
void setStringVariable(const char *str);
TORQUE_FORCEINLINE S32 getLocalIntVariable(S32 reg)
{
return currentRegisterArray->values[reg].getInt();
}
TORQUE_FORCEINLINE F64 getLocalFloatVariable(S32 reg)
{
return currentRegisterArray->values[reg].getFloat();
}
TORQUE_FORCEINLINE const char* getLocalStringVariable(S32 reg)
{
return currentRegisterArray->values[reg].getString();
}
TORQUE_FORCEINLINE void setLocalIntVariable(S32 reg, S64 val)
{
currentRegisterArray->values[reg].setInt(val);
}
TORQUE_FORCEINLINE void setLocalFloatVariable(S32 reg, F64 val)
{
currentRegisterArray->values[reg].setFloat(val);
}
TORQUE_FORCEINLINE void setLocalStringVariable(S32 reg, const char* val, S32 len)
{
currentRegisterArray->values[reg].setString(val, len);
}
TORQUE_FORCEINLINE void setLocalStringTableEntryVariable(S32 reg, StringTableEntry val)
{
currentRegisterArray->values[reg].setStringTableEntry(val);
}
TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val)
{
currentRegisterArray->values[reg] = std::move(val);
}
void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
void popFrame();
/// Puts a reference to an existing stack frame
/// on the top of the stack.
void pushFrameRef(S32 stackIndex);
void pushDebugFrame(S32 stackIndex);
U32 getStackDepth() const
{
return mStackDepth;
}
Dictionary& getCurrentFrame()
{
return *(stack[mStackDepth - 1]);
}
Dictionary& getFrameAt(S32 depth)
{
return *(stack[depth]);
}
/// @}
/// Run integrity checks for debugging.
void validate();
};
#endif

View file

@ -21,8 +21,7 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/codeBlock.h"
#include "codeBlock.h"
static bool isLiteralNumber(ExprNode* node)
{
@ -85,7 +84,7 @@ bool IntBinaryExprNode::optimize()
S32 val = getIntValue(right);
switch (val)
{
case 2:
case 2:
op = '&';
optimizedNode = IntNode::alloc(dbgLineNumber, 1);
return true;

View file

@ -0,0 +1,49 @@
#ifndef _TORQUESCRIPT_PARSER_H_
#define _TORQUESCRIPT_PARSER_H_
#include <cstdio>
#include "platform/types.h"
const char* CMDGetCurrentFile();
S32 CMDGetCurrentLine();
S32 CMDparse();
void CMDrestart(FILE* in);
void CMDSetScanBuffer(const char *sb, const char *fn);
extern void expandEscape(char *dest, const char *src);
extern bool collapseEscape(char *buf);
class TorqueScriptParser
{
public:
TorqueScriptParser() = default;
const char* mExtension;
//-----------------------------------------------------------------------------
/// \brief Function for GetCurrentFile from the lexer
//-----------------------------------------------------------------------------
const char* getCurrentFile() { return CMDGetCurrentFile(); }
//-----------------------------------------------------------------------------
/// \brief Function for GetCurrentLine from the lexer
//-----------------------------------------------------------------------------
S32 getCurrentLine() { return CMDGetCurrentLine(); }
//-----------------------------------------------------------------------------
/// \brief Function for Parse from the lexer
//-----------------------------------------------------------------------------
S32 parse() { return CMDparse(); }
//-----------------------------------------------------------------------------
/// \brief Function for Restart from the lexer
//-----------------------------------------------------------------------------
void restart(FILE *pInputFile) { CMDrestart(pInputFile); }
//-----------------------------------------------------------------------------
/// \brief Function for SetScanBuffer from the lexer
//-----------------------------------------------------------------------------
void setScanBuffer(const char* sb, const char* fn) { CMDSetScanBuffer(sb, fn); }
};
#endif

View file

@ -0,0 +1,486 @@
#include "runtime.h"
#include "codeBlock.h"
#include "console/script.h"
#include "console/runtime.h"
#include "core/volume.h"
#include "core/stream/fileStream.h"
#include "core/util/timeClass.h"
namespace TorqueScript
{
// Buffer for expanding script filenames.
static char scriptFilenameBuffer[1024];
TorqueScriptRuntime::TorqueScriptRuntime()
{
Con::registerRuntime(0, this);
}
TorqueScriptRuntime::~TorqueScriptRuntime()
{
}
Con::EvalResult TorqueScriptRuntime::evaluate(const char* string, bool echo, const char* fileName)
{
ConsoleStackFrameSaver stackSaver;
stackSaver.save();
if (echo)
{
if (string[0] == '%')
Con::printf("%s", string);
else
Con::printf("%s%s", Con::getVariable("$Con::Prompt"), string);
}
if (fileName)
fileName = StringTable->insert(fileName);
CodeBlock* newCodeBlock = new CodeBlock();
return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
}
Con::EvalResult TorqueScriptRuntime::evaluate(const char* script, S32 frame, bool echo, const char* fileName)
{
// Make sure we're passing a valid frame to the eval.
if (frame > Script::gEvalState.getStackDepth())
frame = Script::gEvalState.getStackDepth() - 1;
if (frame < 0)
frame = 0;
// Local variables use their own memory management and can't be queried by just executing
// TorqueScript, we have to go digging into the interpreter.
S32 evalBufferLen = dStrlen(script);
bool isEvaluatingLocalVariable = evalBufferLen > 0 && script[0] == '%';
if (isEvaluatingLocalVariable)
{
// See calculation of current frame in pushing a reference frame for console exec, we need access
// to the proper scope.
//frame = gEvalState.getTopOfStack() - frame - 1;
S32 stackIndex = Script::gEvalState.getStackDepth() - frame - 1;
Script::gEvalState.pushDebugFrame(stackIndex);
Dictionary& stackFrame = Script::gEvalState.getCurrentFrame();
StringTableEntry functionName = stackFrame.scopeName;
StringTableEntry namespaceName = stackFrame.scopeNamespace->mName;
StringTableEntry varToLookup = StringTable->insert(script);
S32 registerId = ((CodeBlock*)stackFrame.module)->variableRegisterTable.lookup(namespaceName, functionName, varToLookup);
if (registerId == -1)
{
// ERROR, can't read the variable!
return Con::EvalResult("variable not found");
}
const char* varResult = Script::gEvalState.getLocalStringVariable(registerId);
Script::gEvalState.popFrame();
ConsoleValue val;
val.setString(varResult);
return Con::EvalResult("variable not found");
}
// Execute the eval.
CodeBlock* newCodeBlock = new CodeBlock();
Con::EvalResult result = newCodeBlock->compileExec(NULL, script, false, frame);
return result;
}
//------------------------------------------------------------------------------
Con::EvalResult TorqueScriptRuntime::evaluatef(const char* string, ...)
{
char buffer[4096];
va_list args;
va_start(args, string);
dVsprintf(buffer, sizeof(buffer), string, args);
va_end(args);
return evaluate(buffer);
}
bool TorqueScriptRuntime::executeFile(const char* fileName, bool noCalls, bool journalScript)
{
bool journal = false;
U32 execDepth = 0;
U32 journalDepth = 1;
execDepth++;
if (journalDepth >= execDepth)
journalDepth = execDepth + 1;
else
journal = true;
bool ret = false;
if (journalScript && !journal)
{
journal = true;
journalDepth = execDepth;
}
// Determine the filename we actually want...
Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), fileName);
// since this function expects a script file reference, if it's a .dso
// lets terminate the string before the dso so it will act like a .tscript
if (dStrEndsWith(scriptFilenameBuffer, ".dso"))
{
scriptFilenameBuffer[dStrlen(scriptFilenameBuffer) - dStrlen(".dso")] = '\0';
}
// Figure out where to put DSOs
StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
const char* ext = dStrrchr(scriptFilenameBuffer, '.');
if (!ext)
{
// Try appending the default script extension and see if that succeeds
if (executeFile(fileName + String("." TORQUE_SCRIPT_EXTENSION), noCalls, journalScript))
{
return true;
}
// We need an extension!
Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file name %s.", scriptFilenameBuffer);
execDepth--;
return false;
}
// Check Editor Extensions
bool isEditorScript = false;
// If the script file extension is '.ed.tscript' then compile it to a different compiled extension
if (dStricmp(ext, "." TORQUE_SCRIPT_EXTENSION) == 0)
{
const char* ext2 = ext - 3;
if (dStricmp(ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0)
isEditorScript = true;
}
else if (dStricmp(ext, ".gui") == 0)
{
const char* ext2 = ext - 3;
if (dStricmp(ext2, ".ed.gui") == 0)
isEditorScript = true;
}
StringTableEntry scriptFileName = StringTable->insert(scriptFilenameBuffer);
// Is this a file we should compile? (anything in the prefs path should not be compiled)
StringTableEntry prefsPath = Platform::getPrefsPath();
bool compiled = dStricmp(ext, ".mis") && !journal && !Con::getBoolVariable("Scripts::ignoreDSOs");
// [tom, 12/5/2006] stripBasePath() fucks up if the filename is not in the exe
// path, current directory or prefs path. Thus, getDSOFilename() will also screw
// up and so this allows the scripts to still load but without a DSO.
if (Platform::isFullPath(Platform::stripBasePath(scriptFilenameBuffer)))
compiled = false;
// [tom, 11/17/2006] It seems to make sense to not compile scripts that are in the
// prefs directory. However, getDSOPath() can handle this situation and will put
// the dso along with the script to avoid name clashes with tools/game dsos.
if ((dsoPath && *dsoPath == 0) || (prefsPath && prefsPath[0] && dStrnicmp(
scriptFileName, prefsPath, dStrlen(prefsPath)) == 0))
compiled = false;
// If we're in a journaling mode, then we will read the script
// from the journal file.
if (journal && Journal::IsPlaying())
{
char fileNameBuf[256];
bool fileRead = false;
U32 fileSize;
Journal::ReadString(fileNameBuf);
Journal::Read(&fileRead);
if (!fileRead)
{
Con::errorf(ConsoleLogEntry::Script, "Journal script read (failed) for %s", fileNameBuf);
execDepth--;
return false;
}
Journal::Read(&fileSize);
char* script = new char[fileSize + 1];
Journal::Read(fileSize, script);
script[fileSize] = 0;
Con::printf("Executing (journal-read) %s.", scriptFileName);
CodeBlock *newCodeBlock = new CodeBlock();
newCodeBlock->compileExec(scriptFileName, script, noCalls, 0);
delete newCodeBlock;
delete[] script;
execDepth--;
return true;
}
// Ok, we let's try to load and compile the script.
Torque::FS::FileNodeRef scriptFile = Torque::FS::GetFileNode(scriptFileName);
Torque::FS::FileNodeRef dsoFile;
// ResourceObject *rScr = gResourceManager->find(scriptFileName);
// ResourceObject *rCom = NULL;
char nameBuffer[512];
char* script = NULL;
U32 version;
Stream* compiledStream = NULL;
Torque::Time scriptModifiedTime, dsoModifiedTime;
// Check here for .edso
bool edso = false;
if (dStricmp(ext, ".edso") == 0 && scriptFile != NULL)
{
edso = true;
dsoFile = scriptFile;
scriptFile = NULL;
dsoModifiedTime = dsoFile->getModifiedTime();
dStrcpy(nameBuffer, scriptFileName, 512);
}
// If we're supposed to be compiling this file, check to see if there's a DSO
if (compiled && !edso)
{
const char* filenameOnly = dStrrchr(scriptFileName, '/');
if (filenameOnly)
++filenameOnly;
else
filenameOnly = scriptFileName;
char pathAndFilename[1024];
Platform::makeFullPathName(filenameOnly, pathAndFilename, sizeof(pathAndFilename), dsoPath);
if (isEditorScript)
dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".edso", NULL);
else
dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".dso", NULL);
dsoFile = Torque::FS::GetFileNode(nameBuffer);
if (scriptFile != NULL)
scriptModifiedTime = scriptFile->getModifiedTime();
if (dsoFile != NULL)
dsoModifiedTime = dsoFile->getModifiedTime();
}
// Let's do a sanity check to complain about DSOs in the future.
//
// MM: This doesn't seem to be working correctly for now so let's just not issue
// the warning until someone knows how to resolve it.
//
//if(compiled && rCom && rScr && Platform::compareFileTimes(comModifyTime, scrModifyTime) < 0)
//{
//Con::warnf("exec: Warning! Found a DSO from the future! (%s)", nameBuffer);
//}
// If we had a DSO, let's check to see if we should be reading from it.
//MGT: fixed bug with dsos not getting recompiled correctly
//Note: Using Nathan Martin's version from the forums since its easier to read and understand
if (compiled && dsoFile != NULL && (scriptFile == NULL || (dsoModifiedTime >= scriptModifiedTime)))
{
//MGT: end
compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
if (compiledStream)
{
// Check the version!
compiledStream->read(&version);
if (version != Con::DSOVersion)
{
Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
delete compiledStream;
compiledStream = NULL;
}
}
}
// If we're journalling, let's write some info out.
if (journal && Journal::IsRecording())
Journal::WriteString(scriptFileName);
if (scriptFile != NULL && !compiledStream)
{
// If we have source but no compiled version, then we need to compile
// (and journal as we do so, if that's required).
void* data;
U32 dataSize = 0;
Torque::FS::ReadFile(scriptFileName, data, dataSize, true);
if (journal && Journal::IsRecording())
Journal::Write(bool(data != NULL));
if (data == NULL)
{
Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file %s.", scriptFileName);
execDepth--;
return false;
}
else
{
if (!dataSize)
{
execDepth--;
return false;
}
script = (char*)data;
if (journal && Journal::IsRecording())
{
Journal::Write(dataSize);
Journal::Write(dataSize, data);
}
}
#ifndef TORQUE_NO_DSO_GENERATION
if (compiled)
{
// compile this baddie.
#ifdef TORQUE_DEBUG
Con::printf("Compiling %s...", scriptFileName);
#endif
CodeBlock *code = new CodeBlock();
code->compile(nameBuffer, scriptFileName, script);
delete code;
code = NULL;
compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
if (compiledStream)
{
compiledStream->read(&version);
}
else
{
// We have to exit out here, as otherwise we get double error reports.
delete[] script;
execDepth--;
return false;
}
}
#endif
}
else
{
if (journal && Journal::IsRecording())
Journal::Write(bool(false));
}
if (compiledStream)
{
// Delete the script object first to limit memory used
// during recursive execs.
delete[] script;
script = 0;
// We're all compiled, so let's run it.
#ifdef TORQUE_DEBUG
Con::printf("Loading compiled script %s.", scriptFileName);
#endif
CodeBlock* code = new CodeBlock;
code->read(scriptFileName, *compiledStream);
delete compiledStream;
code->exec(0, scriptFileName, NULL, 0, NULL, noCalls, NULL, 0);
delete code;
ret = true;
}
else if (scriptFile)
{
// No compiled script, let's just try executing it
// directly... this is either a mission file, or maybe
// we're on a readonly volume.
#ifdef TORQUE_DEBUG
Con::printf("Executing %s.", scriptFileName);
#endif
CodeBlock *newCodeBlock = new CodeBlock();
StringTableEntry name = StringTable->insert(scriptFileName);
newCodeBlock->compileExec(name, script, noCalls, 0);
ret = true;
}
else
{
// Don't have anything.
Con::warnf(ConsoleLogEntry::Script, "Missing file: %s!", scriptFileName);
ret = false;
}
delete[] script;
execDepth--;
return ret;
}
bool TorqueScriptRuntime::compile(const char* fileName, bool overrideNoDso)
{
Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
// Figure out where to put DSOs
StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
if(dsoPath && *dsoPath == 0)
return false;
// If the script file extention is '.ed.tscript' then compile it to a different compiled extention
bool isEditorScript = false;
const char *ext = dStrrchr( scriptFilenameBuffer, '.' );
if( ext && ( dStricmp( ext, "." TORQUE_SCRIPT_EXTENSION) == 0 ) )
{
const char* ext2 = ext - 3;
if( dStricmp( ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0 )
isEditorScript = true;
}
else if( ext && ( dStricmp( ext, ".gui" ) == 0 ) )
{
const char* ext2 = ext - 3;
if( dStricmp( ext2, ".ed.gui" ) == 0 )
isEditorScript = true;
}
const char *filenameOnly = dStrrchr(scriptFilenameBuffer, '/');
if(filenameOnly)
++filenameOnly;
else
filenameOnly = scriptFilenameBuffer;
char nameBuffer[512];
if( isEditorScript )
dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".edso", NULL);
else
dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".dso", NULL);
void *data = NULL;
U32 dataSize = 0;
Torque::FS::ReadFile(scriptFilenameBuffer, data, dataSize, true);
if(data == NULL)
{
Con::errorf(ConsoleLogEntry::Script, "compile: invalid script file %s.", scriptFilenameBuffer);
return false;
}
const char *script = static_cast<const char *>(data);
#ifdef TORQUE_DEBUG
Con::printf("Compiling %s...", scriptFilenameBuffer);
#endif
CodeBlock *code = new CodeBlock();
code->compile(nameBuffer, scriptFilenameBuffer, script, overrideNoDso);
delete code;
delete[] script;
return true;
}
}

View file

@ -0,0 +1,27 @@
#ifndef _TORQUESCRIPT_RUNTIME_H_
#define _TORQUESCRIPT_RUNTIME_H_
#include "ast.h"
#include "console/runtime.h"
namespace TorqueScript
{
class TorqueScriptRuntime : public Con::Runtime
{
public:
TorqueScriptRuntime();
~TorqueScriptRuntime() override;
void expandEscapedCharacters(char* dest, const char* src) override { expandEscape(dest, src); }
bool collapseEscapedCharacters(char* buf) override { return collapseEscape(buf); }
Con::EvalResult evaluate(const char* string, bool echo = false, const char* fileName = NULL) override;
Con::EvalResult evaluate(const char* script, S32 frame, bool echo = false, const char *fileName = NULL) override;
Con::EvalResult evaluatef(const char* string, ...) override;
bool executeFile(const char* fileName, bool noCalls, bool journalScript) override;
bool compile(const char* fileName, bool overrideNoDso);
};
inline TorqueScriptRuntime* gRuntime = new TorqueScriptRuntime();
inline TorqueScriptRuntime* getRuntime() { return gRuntime; }
}
#endif

View file

@ -1234,18 +1234,6 @@ bool IsFile(const Path &path)
return sgMountSystem.isFile(path);
}
bool IsScriptFile(const char* pFilePath)
{
return (sgMountSystem.isFile(pFilePath)
|| sgMountSystem.isFile(pFilePath + String(".dso"))
|| sgMountSystem.isFile(pFilePath + String(".mis"))
|| sgMountSystem.isFile(pFilePath + String(".mis.dso"))
|| sgMountSystem.isFile(pFilePath + String(".gui"))
|| sgMountSystem.isFile(pFilePath + String(".gui.dso"))
|| sgMountSystem.isFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION))
|| sgMountSystem.isFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION) + String(".dso")));
}
bool IsDirectory(const Path &path)
{
return sgMountSystem.isDirectory(path);

View file

@ -567,7 +567,6 @@ bool CreatePath(const Path &path);
bool IsReadOnly(const Path &path);
bool IsDirectory(const Path &path);
bool IsFile(const Path &path);
bool IsScriptFile(const char* pFilePath);
bool VerifyWriteAccess(const Path &path);
/// This returns a unique file path from the components

View file

@ -25,6 +25,7 @@
#include "console/console.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "core/volume.h"
// NOTE: The script class docs are in

View file

@ -1,5 +1,6 @@
#include "gui/core/guiCanvas.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "gfx/gfxDebugEvent.h"
#include "gfx/gl/gfxGLDevice.h"

View file

@ -25,6 +25,7 @@
#include "console/consoleTypes.h"
#include "console/console.h"
#include "console/script.h"
#include "core/color.h"
#include "gfx/gfxDrawUtil.h"
#include "gui/core/guiDefaultControlRender.h"

View file

@ -24,6 +24,7 @@
#include "console/consoleTypes.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "gfx/gfxDrawUtil.h"
#include "gui/containers/guiScrollCtrl.h"
#include "sim/actionMap.h"

View file

@ -24,6 +24,7 @@
#include "console/consoleTypes.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "gfx/gfxDrawUtil.h"
#include "gui/containers/guiScrollCtrl.h"
#include "core/strings/stringUnit.h"

View file

@ -22,6 +22,7 @@
#include "gui/controls/guiListBoxCtrl.h"
#include "gfx/gfxDrawUtil.h"
#include "console/engineAPI.h"
#include "console/script.h"
IMPLEMENT_CONOBJECT(GuiListBoxCtrl);
@ -165,7 +166,7 @@ GuiListBoxCtrl::GuiListBoxCtrl()
mColorBullet = true;
mItemSize = Point2I(10,20);
mLastClickItem = NULL;
mRenderTooltipDelegate.bind( this, &GuiListBoxCtrl::renderTooltip );
}
@ -469,11 +470,11 @@ void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
{
// Clear our return vector
Items.clear();
// If there are no selected items, return an empty vector
if( mSelectedItems.empty() )
return;
for( S32 i = 0; i < mItems.size(); i++ )
if( mItems[i]->isSelected )
Items.push_back( i );
@ -882,8 +883,8 @@ StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
Con::warnf( "GuiListBoxCtrl::getItemText - index out of range!" );
return StringTable->lookup("");
}
return mItems[ index ]->itemText;
return mItems[ index ]->itemText;
}
DefineEngineMethod( GuiListBoxCtrl, getItemObject, const char*, (S32 index),,
@ -917,7 +918,7 @@ SimObject* GuiListBoxCtrl::getItemObject( S32 index )
SimObject *outObj;
Sim::findObject( (SimObjectId)(uintptr_t)(mItems[ index ]->itemData), outObj );
return outObj;
return outObj;
}
DefineEngineMethod( GuiListBoxCtrl, setItemText, void, (S32 index, const char* newtext),,
@ -974,7 +975,7 @@ DefineEngineMethod( GuiListBoxCtrl, setItemTooltip, void, (S32 index, const char
Con::errorf( "GuiListBoxCtrl::setItemTooltip - index '%i' out of range", index );
return;
}
object->mItems[ index ]->itemTooltip = text;
}
@ -1104,7 +1105,7 @@ bool GuiListBoxCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& curs
S32 hitItemIndex;
if( hitTest( hoverPos, hitItemIndex ) )
tipText = mItems[ hitItemIndex ]->itemTooltip;
return defaultTooltipRender( hoverPos, cursorPos, tipText );
}
@ -1115,7 +1116,7 @@ bool GuiListBoxCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& curs
bool GuiListBoxCtrl::hitTest( const Point2I& point, S32& outItem )
{
Point2I localPoint = globalToLocalCoord( point );
S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
if ( itemHit >= mItems.size() || itemHit == -1 )
return false;
@ -1123,7 +1124,7 @@ bool GuiListBoxCtrl::hitTest( const Point2I& point, S32& outItem )
LBItem *hitItem = mItems[ itemHit ];
if ( hitItem == NULL )
return false;
outItem = itemHit;
return true;
}
@ -1144,7 +1145,7 @@ void GuiListBoxCtrl::onMouseDown( const GuiEvent &event )
S32 itemHit;
if( !hitTest( event.mousePoint, itemHit ) )
return;
LBItem* hitItem = mItems[ itemHit ];
// If we're not a multiple selection listbox, we simply select/unselect an item
@ -1172,7 +1173,7 @@ void GuiListBoxCtrl::onMouseDown( const GuiEvent &event )
return;
}
// Deal with multiple selections
if( event.modifier & SI_MULTISELECT)
{
@ -1219,7 +1220,7 @@ void GuiListBoxCtrl::onMouseUp( const GuiEvent& event )
// Execute console command
execConsoleCallback();
Parent::onMouseUp( event );
}
@ -1268,7 +1269,7 @@ U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
// Yes...
search = 0;
break;
}
}
}
// Found a seperator?
@ -1300,7 +1301,7 @@ U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
// Yes...
search = 0;
break;
}
}
}
// Found Seperator?
@ -1357,7 +1358,7 @@ const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 in
// Yes...
search = 0;
break;
}
}
}
// Found a seperator?
@ -1396,7 +1397,7 @@ const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 in
// Yes...
search = 0;
break;
}
}
}
// Found Seperator?
@ -1446,19 +1447,19 @@ void GuiListBoxCtrl::_mirror()
// Allow script to filter out objects if desired.
Vector<SimObjectId> workingSet;
Vector<SimObjectId> workingSet;
// If the method is not defined we assume user wants us to add
// all objects.
bool isObjMirroredDefined = isMethod( "isObjectMirrored" );
for ( S32 i = 0; i < mirrorSet->size(); i++ )
{
bool addObj = true;
if ( isObjMirroredDefined )
addObj = isObjectMirrored_callback(mirrorSet->at(i)->getIdString());
addObj = isObjectMirrored_callback(mirrorSet->at(i)->getIdString());
if ( addObj )
workingSet.push_back( mirrorSet->at(i)->getId() );
}
@ -1481,8 +1482,8 @@ void GuiListBoxCtrl::_mirror()
if ( curObj )
{
if ( workingSet.contains( curId ) )
{
mItems[i]->itemText = _makeMirrorItemName( curObj );
{
mItems[i]->itemText = _makeMirrorItemName( curObj );
keep = true;
}
}
@ -1492,7 +1493,7 @@ void GuiListBoxCtrl::_mirror()
deleteItem( i );
i--;
}
}
}
// Add items that are in the SimSet but not yet in the list.
@ -1512,7 +1513,7 @@ void GuiListBoxCtrl::_mirror()
break;
}
}
for ( U32 j = 0; j < mFilteredItems.size(); j++ )
{
if ( (SimObjectId)(uintptr_t)(mFilteredItems[j]->itemData) == curId )
@ -1523,8 +1524,8 @@ void GuiListBoxCtrl::_mirror()
}
if ( !found )
{
addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );
{
addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );
}
}
}
@ -1537,12 +1538,12 @@ StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj )
{
Con::setIntVariable( "$ThisControl", getId() );
Con::setIntVariable( "$ThisObject", inObj->getId() );
outName = StringTable->insert( Con::evaluate( mMakeNameCallback ), true );
outName = StringTable->insert( Con::evaluate( mMakeNameCallback ).value, true );
}
else if ( inObj->getName() )
outName = StringTable->insert( inObj->getName() );
if ( !outName || !outName[0] )
outName = StringTable->insert( "(no name)" );
@ -1582,22 +1583,22 @@ DefineEngineMethod( GuiListBoxCtrl, addFilteredItem, void, (const char* newItem)
void GuiListBoxCtrl::addFilteredItem( String item )
{
// Delete from selected items list
for ( S32 i = 0; i < mSelectedItems.size(); i++ )
for ( S32 i = 0; i < mSelectedItems.size(); i++ )
{
String itemText = mSelectedItems[i]->itemText;
if ( String::compare( itemText.c_str(), item.c_str() ) == 0 )
if ( String::compare( itemText.c_str(), item.c_str() ) == 0 )
{
mSelectedItems.erase_fast( i );
break;
}
}
for ( S32 i = 0; i < mItems.size(); i++ )
for ( S32 i = 0; i < mItems.size(); i++ )
{
String itemText = mItems[i]->itemText;
if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
{
mItems[i]->isSelected = false;
{
mItems[i]->isSelected = false;
mFilteredItems.push_front( mItems[i] );
mItems.erase( &mItems[i] );
break;
@ -1625,11 +1626,11 @@ DefineEngineMethod( GuiListBoxCtrl, removeFilteredItem, void, ( const char* item
void GuiListBoxCtrl::removeFilteredItem( String item )
{
for ( S32 i = 0; i < mFilteredItems.size(); i++ )
for ( S32 i = 0; i < mFilteredItems.size(); i++ )
{
String itemText = mFilteredItems[i]->itemText;
if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
{
{
mItems.push_front( mFilteredItems[i] );
mFilteredItems.erase( &mFilteredItems[i] );
break;

View file

@ -28,6 +28,7 @@
#include "core/stringBuffer.h"
#include "gfx/gfxDrawUtil.h"
#include "console/engineAPI.h"
#include "console/script.h"
IMPLEMENT_CONOBJECT(GuiMLTextEditCtrl);

View file

@ -32,7 +32,7 @@
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
#include "console/codeBlock.h"
#include "console/script.h"
#include "gfx/bitmap/gBitmap.h"
#include "sim/actionMap.h"
#include "gui/core/guiCanvas.h"
@ -2489,7 +2489,7 @@ void GuiControl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent
const char* GuiControl::evaluate( const char* str )
{
smThisControl = this;
const char* result = Con::evaluate(str, false);
const char* result = Con::evaluate(str, false).value;
smThisControl = NULL;
return result;

View file

@ -31,6 +31,7 @@
#include "gui/containers/guiScrollCtrl.h"
#include "core/strings/stringUnit.h"
#include "console/engineAPI.h"
#include "console/script.h"
IMPLEMENT_CONOBJECT( GuiEditCtrl );

View file

@ -25,6 +25,7 @@
#include "gui/editor/inspector/dynamicGroup.h"
#include "gui/editor/inspector/dynamicField.h"
#include "console/engineAPI.h"
#include "console/script.h"
IMPLEMENT_CONOBJECT(GuiInspectorDynamicGroup);

View file

@ -23,6 +23,8 @@
#include "console/engineAPI.h"
#include "platform/platform.h"
#include "gui/editor/inspector/field.h"
#include "console/script.h"
#include "gui/buttons/guiIconButtonCtrl.h"
#include "gui/editor/guiInspector.h"
#include "core/util/safeDelete.h"
@ -321,7 +323,7 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
{
char buffer[ 2048 ];
expandEscape( buffer, newValue );
evaluationResult = Con::evaluatef("$f = \"%s\"; return ( %s );", oldValue.c_str(), buffer);
evaluationResult = Con::evaluatef("$f = \"%s\"; return ( %s );", oldValue.c_str(), buffer).value;
newValue = evaluationResult.getString();
Con::evaluatef("$f=0;");
}
@ -359,7 +361,7 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
expandEscape( buffer, newComponentExpr );
evaluationResult = Con::evaluatef("$f = \"%s\"; $v = \"%s\"; return ( %s );",
oldComponentVal, oldValue.c_str(), buffer);
oldComponentVal, oldValue.c_str(), buffer).value;
Con::evaluatef("$f=0;$v=0;");
if( !isFirst )

View file

@ -22,6 +22,8 @@
#include "gui/editor/guiInspector.h"
#include "gui/editor/inspector/group.h"
#include "console/script.h"
#include "gui/editor/inspector/dynamicField.h"
#include "gui/editor/inspector/datablockField.h"
#include "gui/buttons/guiIconButtonCtrl.h"

View file

@ -25,8 +25,7 @@
#include "gui/editor/guiInspector.h"
#include "gui/buttons/guiIconButtonCtrl.h"
#include "console/consoleInternal.h"
extern ExprEvalState gEvalState;
#include "console/script.h"
//-----------------------------------------------------------------------------
// GuiInspectorVariableGroup
@ -65,7 +64,7 @@ bool GuiInspectorVariableGroup::inspectGroup()
{
Vector<String> names;
gEvalState.globalVars.exportVariables(mSearchString, &names, NULL);
Con::gGlobalVars.exportVariables(mSearchString, &names, NULL);
for (U32 i = 0; i < names.size(); i++)
{

View file

@ -21,6 +21,7 @@
//-----------------------------------------------------------------------------
#include "gui/shiny/guiAudioCtrl.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "sfx/sfxSystem.h"
#include "sfx/sfxTrack.h"
#include "sfx/sfxSource.h"

View file

@ -25,8 +25,6 @@
#include "core/stream/fileStream.h"
#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
#include "console/compiler.h"
#include "core/util/safeDelete.h"
#include "console/engineAPI.h"
@ -102,7 +100,7 @@ bool LangFile::load(Stream *s)
bool LangFile::save(const UTF8 *filename)
{
FileStream *fs;
if(!isLoaded())
return false;
@ -168,7 +166,7 @@ void LangFile::setLangName(const UTF8 *newName)
{
if(mLangName)
delete [] mLangName;
dsize_t langNameLen = dStrlen(newName) + 1;
mLangName = new UTF8 [langNameLen];
dStrcpy(mLangName, newName, langNameLen);
@ -178,7 +176,7 @@ void LangFile::setLangFile(const UTF8 *langFile)
{
if(mLangFile)
delete [] mLangFile;
dsize_t langFileLen = dStrlen(langFile) + 1;
mLangFile = new UTF8 [langFileLen];
dStrcpy(mLangFile, langFile, langFileLen);
@ -211,7 +209,7 @@ IMPLEMENT_CONOBJECT(LangTable);
ConsoleDocClass( LangTable,
"@brief Provides the code necessary to handle the low level management "
"of the string tables for localization\n\n"
"One LangTable is created for each mod, as well as one for the C++ code. "
"LangTable is responsible for obtaining the correct strings from each "
"and relaying it to the appropriate controls.\n\n"
@ -260,7 +258,7 @@ S32 LangTable::addLanguage(const UTF8 *filename, const UTF8 *name /* = NULL */)
if(Torque::FS::IsFile(filename))
{
lang->setLangFile(filename);
S32 ret = addLanguage(lang);
if(ret >= 0)
return ret;
@ -287,7 +285,7 @@ const U32 LangTable::getStringLength(const U32 id) const
const UTF8 *s = getString(id);
if(s)
return dStrlen(s);
return 0;
}
@ -299,7 +297,7 @@ void LangTable::setDefaultLanguage(S32 langid)
{
if(mDefaultLang >= 0)
mLangTable[mDefaultLang]->deactivateLanguage();
mDefaultLang = langid;
}
}
@ -329,7 +327,7 @@ void LangTable::setCurrentLanguage(S32 langid)
DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""),
DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""),
"(string filename, [string languageName])"
"@brief Adds a language to the table\n\n"
"@param filename Name and path to the language file\n"
@ -338,12 +336,12 @@ DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languag
)
{
UTF8 scriptFilenameBuffer[1024];
Con::expandScriptFilename((char*)scriptFilenameBuffer, sizeof(scriptFilenameBuffer), filename);
return object->addLanguage(scriptFilenameBuffer, (const UTF8*)languageName);
}
DefineEngineMethod(LangTable, getString, const char *, (U32 id), ,
DefineEngineMethod(LangTable, getString, const char *, (U32 id), ,
"(string filename)"
"@brief Grabs a string from the specified table\n\n"
"If an invalid is passed, the function will attempt to "
@ -359,7 +357,7 @@ DefineEngineMethod(LangTable, getString, const char *, (U32 id), ,
dStrcpy(ret, str, retLen);
return ret;
}
return "";
}
@ -370,7 +368,7 @@ DefineEngineMethod(LangTable, setDefaultLanguage, void, (S32 langId), , "(int la
object->setDefaultLanguage(langId);
}
DefineEngineMethod(LangTable, setCurrentLanguage, void, (S32 langId), ,
DefineEngineMethod(LangTable, setCurrentLanguage, void, (S32 langId), ,
"(int language)"
"@brief Sets the current language table for grabbing text\n\n"
"@param language ID of the table\n")
@ -398,7 +396,7 @@ DefineEngineMethod(LangTable, getLangName, const char *, (S32 langId), , "(int l
dStrcpy(ret, str, retLen);
return ret;
}
return "";
}
@ -420,9 +418,9 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize)
*buffer = 0;
return NULL;
}
dStrcpy(buffer, (const UTF8*)"I18N::", bufsize);
UTF8 *dptr = buffer + 6;
const UTF8 *sptr = varName;
while(*sptr)
@ -435,27 +433,27 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize)
*dptr++ = '_';
sptr++;
}
if((dptr - buffer) >= (bufsize - 1))
break;
}
*dptr = 0;
return buffer;
}
UTF8 *getCurrentModVarName(UTF8 *buffer, U32 bufsize)
{
char varName[256];
StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName();
StringTableEntry cbName = Con::getCurrentScriptModuleName();
const UTF8 *slash = (const UTF8*)dStrchr(cbName, '/');
if (slash == NULL)
{
Con::errorf("Illegal CodeBlock path detected in sanitiseVarName() (no mod directory): %s", cbName);
return NULL;
}
dStrncpy(varName, cbName, slash - (const UTF8*)cbName);
varName[slash - (const UTF8*)cbName] = 0;
@ -465,7 +463,7 @@ UTF8 *getCurrentModVarName(UTF8 *buffer, U32 bufsize)
const LangTable *getCurrentModLangTable()
{
UTF8 saneVarName[256];
if(getCurrentModVarName(saneVarName, sizeof(saneVarName)))
{
const LangTable *lt = dynamic_cast<LangTable *>(Sim::findObject(Con::getIntVariable((const char*)saneVarName)));
@ -508,7 +506,7 @@ bool compiledFileNeedsUpdate(UTF8* filename)
return false;
}
DefineEngineFunction(CompileLanguage, void, (const char* inputFile, bool createMap), (false),
DefineEngineFunction(CompileLanguage, void, (const char* inputFile, bool createMap), (false),
"@brief Compiles a LSO language file."
" if createIndex is true, will also create languageMap." TORQUE_SCRIPT_EXTENSION " with"
" the global variables for each string index."

View file

@ -22,6 +22,8 @@
#include "platform/platform.h"
#include "postFx/postEffectVis.h"
#include "console/script.h"
#include "gui/containers/guiWindowCtrl.h"
#include "gui/controls/guiBitmapCtrl.h"
#include "gui/core/guiCanvas.h"

View file

@ -37,6 +37,8 @@
#include "core/module.h"
#include "math/mathIO.h"
#include "math/mathTypes.h"
#include "console/simBase.h"
#include "console/engineAPI.h"
IMPLEMENT_CO_DATABLOCK_V1( SFXDescription );
@ -455,7 +457,7 @@ bool SFXDescription::onAdd()
const char* channelValue = getDataField( sChannel, NULL );
if( channelValue && channelValue[ 0 ] )
{
ConsoleValue result = Con::evaluatef( "return sfxOldChannelToGroup( %s );", channelValue );
ConsoleValue result = Con::executef("sfxOldChannelToGroup", channelValue);
const char* group = result.getString();
if( !Sim::findObject( group, mSourceGroup ) )
Con::errorf( "SFXDescription::onAdd - could not resolve channel '%s' to SFXSource", channelValue );

View file

@ -28,6 +28,7 @@
#include "core/stream/fileStream.h"
#include "math/mMathFn.h"
#include "console/engineAPI.h"
#include "console/script.h"
#include "math/mQuat.h"
#include "math/mAngAxis.h"

View file

@ -26,12 +26,13 @@
#include "console/simBase.h"
#include "console/engineAPI.h"
#include "math/mMath.h"
#include "console/script.h"
#include "console/stringStack.h"
#include "gui/buttons/guiIconButtonCtrl.h"
inline ConsoleValue RunScript(const char* str)
{
return std::move(Con::evaluate(str, false, NULL));
return std::move(Con::evaluate(str, false, NULL).value);
}
using ::testing::Matcher;

View file

@ -7,12 +7,10 @@
#include "console/simBase.h"
#include "console/engineAPI.h"
#include "math/mMath.h"
#include "console/script.h"
#include "console/stringStack.h"
#include "console/consoleInternal.h"
// Stupid globals not declared in a header
extern ExprEvalState gEvalState;
using ::testing::Matcher;
using ::testing::TypedEq;
@ -25,10 +23,10 @@ protected:
void SetUp() override
{
}
};
TEST_F(ConsoleTest, executef)
@ -176,7 +174,7 @@ TEST_F(ConsoleTest, execute)
{
Con::evaluate("function testScriptExecuteFunction(%a,%b) {return %a SPC %b;}\nfunction testScriptExecuteFunction(%a,%b,%this) {return %a SPC %b;}\r\n", false, "testExecute");
U32 startStackPos = gEvalState.getStackDepth();
U32 startStackPos = Con::getFrameStack().size();
U32 startStringStackPos = STR.mStart;
// const char* versions of execute should maintain stack
@ -187,7 +185,7 @@ TEST_F(ConsoleTest, execute)
EXPECT_STREQ(returnValue, "1 2") <<
"execute should return 1 2";
EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
EXPECT_EQ(Con::getFrameStack().size(), startStackPos) <<
"execute should restore stack";
returnValue = Con::execute(4, argvObject);
@ -195,6 +193,6 @@ TEST_F(ConsoleTest, execute)
EXPECT_STREQ(returnValue, "1 2") <<
"execute should return 1 2";
EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
EXPECT_EQ(Con::getFrameStack().size(), startStackPos) <<
"execute should restore stack";
}

View file

@ -7,6 +7,7 @@
#include "console/simBase.h"
#include "console/engineAPI.h"
#include "math/mMath.h"
#include "console/script.h"
using ::testing::Matcher;
using ::testing::TypedEq;

View file

@ -25,6 +25,7 @@
#include "console/simBase.h"
#include "console/consoleTypes.h"
#include "console/runtimeClassRep.h"
#include "console/script.h"
class RuntimeRegisteredSimObject : public SimObject
{

View file

@ -23,7 +23,7 @@
#include "app/mainLoop.h"
#include "console/console.h"
#include "console/codeBlock.h"
#include "console/script.h"
#include "console/engineAPI.h"
#include "console/consoleInternal.h"
#include "gfx/gfxInit.h"
@ -32,6 +32,8 @@
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#endif
//-----------------------------------------------------------------------------
class TorqueUnitTestListener : public ::testing::EmptyTestEventListener
@ -195,9 +197,9 @@ DefineEngineFunction(addUnitTest, void, (const char* function), ,
U32 ln = __LINE__;
if (entry != NULL)
{
file = entry->mCode->name;
file = entry->mModule->getName();
U32 inst;
entry->mCode->findBreakLine(entry->mFunctionOffset, ln, inst);
entry->mModule->findBreakLine(entry->mFunctionOffset, ln, inst);
}
else
{
@ -210,9 +212,9 @@ DefineEngineFunction(addUnitTest, void, (const char* function), ,
String scriptFileMessage(const char* message)
{
Dictionary* frame = &gEvalState.getCurrentFrame();
CodeBlock* code = frame->code;
const char* scriptLine = code->getFileLine(frame->ip);
Dictionary* frame = Con::getCurrentStackFrame();
Con::Module* module = frame->module;
const char* scriptLine = module->getFileLine(frame->ip);
return String::ToString("at %s: %s", scriptLine, message);
}

View file

@ -29,12 +29,13 @@
#include "console/console.h"
#include "ts/tsShapeInstance.h"
#include "collision/convex.h"
#include "console/consoleInternal.h"
#include "console/script.h"
#include "materials/matInstance.h"
#include "materials/materialManager.h"
#include "math/mathIO.h"
#include "core/util/endian.h"
#include "core/stream/fileStream.h"
#include "console/compiler.h"
#include "core/fileObject.h"
#ifdef TORQUE_COLLADA
@ -2144,7 +2145,7 @@ template<> void *Resource<TSShape>::create(const Torque::Path &path)
scriptPath.setExtension(TORQUE_SCRIPT_EXTENSION);
// Don't execute the script if we're already doing so!
StringTableEntry currentScript = Platform::stripBasePath(CodeBlock::getCurrentCodeBlockFullPath());
StringTableEntry currentScript = Platform::stripBasePath(Con::getCurrentScriptModulePath());
if (!scriptPath.getFullPath().equal(currentScript))
{
Torque::Path scriptPathDSO(scriptPath);

View file

@ -650,7 +650,7 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
_updateMonitorFromMove(evt);
// If display device has changed, make sure window params are compatible with the new device.
if (oldDisplay != Con::getIntVariable("pref::Video::deviceId", 0))
Con::evaluate("configureCanvas();");
Con::executef("configureCanvas");
break;
}
case SDL_WINDOWEVENT_RESIZED:

View file

@ -21,6 +21,8 @@
//-----------------------------------------------------------------------------
#include "windowManager/windowInputGenerator.h"
#include "console/script.h"
#include "windowManager/platformWindow.h"
#include "sim/actionMap.h"
#include "platform/input/IProcessInput.h"