mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-16 09:04:38 +00:00
Merge pull request #1585 from Areloch/execToCon
Make exec() and getDSOPath() proper Con namespace functions.
This commit is contained in:
commit
cf065ed536
3 changed files with 388 additions and 367 deletions
|
|
@ -39,7 +39,7 @@
|
||||||
#include "console/engineAPI.h"
|
#include "console/engineAPI.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "platform/threads/mutex.h"
|
#include "platform/threads/mutex.h"
|
||||||
|
#include "core/util/journal/journal.h"
|
||||||
|
|
||||||
extern StringStack STR;
|
extern StringStack STR;
|
||||||
extern ConsoleValueStack CSTK;
|
extern ConsoleValueStack CSTK;
|
||||||
|
|
@ -1138,6 +1138,321 @@ void addCommand( const char *name,BoolCallback cb,const char *usage, S32 minArgs
|
||||||
Namespace::global()->addCommand( StringTable->insert(name), cb, usage, minArgs, maxArgs, isToolOnly, header );
|
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 .cs
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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.cs' then compile it to a different compiled extension
|
||||||
|
if (dStricmp(ext, ".cs") == 0)
|
||||||
|
{
|
||||||
|
const char* ext2 = ext - 3;
|
||||||
|
if (dStricmp(ext2, ".ed.cs") == 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);
|
||||||
|
|
||||||
|
#ifndef TORQUE_OS_XENON
|
||||||
|
// 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;
|
||||||
|
#else
|
||||||
|
bool compiled = false; // Don't try to compile things on the 360, ignore DSO's when debugging
|
||||||
|
// because PC prefs will screw up stuff like SFX.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
|
ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
|
||||||
{
|
{
|
||||||
ConsoleStackFrameSaver stackSaver;
|
ConsoleStackFrameSaver stackSaver;
|
||||||
|
|
@ -2014,6 +2329,64 @@ void ensureTrailingSlash(char* pDstPath, const char* pSrcPath)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
StringTableEntry getDSOPath(const char *scriptPath)
|
||||||
|
{
|
||||||
|
#ifndef TORQUE2D_TOOLS_FIXME
|
||||||
|
|
||||||
|
// [tom, 11/17/2006] Force old behavior for the player. May not want to do this.
|
||||||
|
const char *slash = dStrrchr(scriptPath, '/');
|
||||||
|
if (slash != NULL)
|
||||||
|
return StringTable->insertn(scriptPath, slash - scriptPath, true);
|
||||||
|
|
||||||
|
slash = dStrrchr(scriptPath, ':');
|
||||||
|
if (slash != NULL)
|
||||||
|
return StringTable->insertn(scriptPath, (slash - scriptPath) + 1, true);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
char relPath[1024], dsoPath[1024];
|
||||||
|
bool isPrefs = false;
|
||||||
|
|
||||||
|
// [tom, 11/17/2006] Prefs are handled slightly differently to avoid dso name clashes
|
||||||
|
StringTableEntry prefsPath = Platform::getPrefsPath();
|
||||||
|
if (dStrnicmp(scriptPath, prefsPath, dStrlen(prefsPath)) == 0)
|
||||||
|
{
|
||||||
|
relPath[0] = 0;
|
||||||
|
isPrefs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringTableEntry strippedPath = Platform::stripBasePath(scriptPath);
|
||||||
|
dStrcpy(relPath, strippedPath);
|
||||||
|
|
||||||
|
char *slash = dStrrchr(relPath, '/');
|
||||||
|
if (slash)
|
||||||
|
*slash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *overridePath;
|
||||||
|
if (!isPrefs)
|
||||||
|
overridePath = Con::getVariable("$Scripts::OverrideDSOPath");
|
||||||
|
else
|
||||||
|
overridePath = prefsPath;
|
||||||
|
|
||||||
|
if (overridePath && *overridePath)
|
||||||
|
Platform::makeFullPathName(relPath, dsoPath, sizeof(dsoPath), overridePath);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char t[1024];
|
||||||
|
dSprintf(t, sizeof(t), "compiledScripts/%s", relPath);
|
||||||
|
Platform::makeFullPathName(t, dsoPath, sizeof(dsoPath), Platform::getPrefsPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringTable->insert(dsoPath);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize)
|
bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize)
|
||||||
{
|
{
|
||||||
// Note original destination.
|
// Note original destination.
|
||||||
|
|
|
||||||
|
|
@ -491,6 +491,7 @@ namespace Con
|
||||||
bool isBasePath(const char* SrcPath, const char* pBasePath);
|
bool isBasePath(const char* SrcPath, const char* pBasePath);
|
||||||
void ensureTrailingSlash(char* pDstPath, const char* pSrcPath);
|
void ensureTrailingSlash(char* pDstPath, const char* pSrcPath);
|
||||||
bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize);
|
bool stripRepeatSlashes(char* pDstPath, const char* pSrcPath, S32 dstSize);
|
||||||
|
StringTableEntry getDSOPath(const char *scriptPath);
|
||||||
|
|
||||||
void addPathExpando(const char* pExpandoName, const char* pPath);
|
void addPathExpando(const char* pExpandoName, const char* pPath);
|
||||||
void removePathExpando(const char* pExpandoName);
|
void removePathExpando(const char* pExpandoName);
|
||||||
|
|
@ -802,6 +803,16 @@ namespace Con
|
||||||
ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
|
ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
|
||||||
ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
|
ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef 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.
|
/// Evaluate an arbitrary chunk of code.
|
||||||
///
|
///
|
||||||
/// @param string Buffer containing code to execute.
|
/// @param string Buffer containing code to execute.
|
||||||
|
|
|
||||||
|
|
@ -2251,63 +2251,6 @@ ConsoleFunction( call, const char *, 2, 0, "( string functionName, string args..
|
||||||
static U32 execDepth = 0;
|
static U32 execDepth = 0;
|
||||||
static U32 journalDepth = 1;
|
static U32 journalDepth = 1;
|
||||||
|
|
||||||
static StringTableEntry getDSOPath(const char *scriptPath)
|
|
||||||
{
|
|
||||||
#ifndef TORQUE2D_TOOLS_FIXME
|
|
||||||
|
|
||||||
// [tom, 11/17/2006] Force old behavior for the player. May not want to do this.
|
|
||||||
const char *slash = dStrrchr(scriptPath, '/');
|
|
||||||
if(slash != NULL)
|
|
||||||
return StringTable->insertn(scriptPath, slash - scriptPath, true);
|
|
||||||
|
|
||||||
slash = dStrrchr(scriptPath, ':');
|
|
||||||
if(slash != NULL)
|
|
||||||
return StringTable->insertn(scriptPath, (slash - scriptPath) + 1, true);
|
|
||||||
|
|
||||||
return "";
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
char relPath[1024], dsoPath[1024];
|
|
||||||
bool isPrefs = false;
|
|
||||||
|
|
||||||
// [tom, 11/17/2006] Prefs are handled slightly differently to avoid dso name clashes
|
|
||||||
StringTableEntry prefsPath = Platform::getPrefsPath();
|
|
||||||
if(dStrnicmp(scriptPath, prefsPath, dStrlen(prefsPath)) == 0)
|
|
||||||
{
|
|
||||||
relPath[0] = 0;
|
|
||||||
isPrefs = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StringTableEntry strippedPath = Platform::stripBasePath(scriptPath);
|
|
||||||
dStrcpy(relPath, strippedPath);
|
|
||||||
|
|
||||||
char *slash = dStrrchr(relPath, '/');
|
|
||||||
if(slash)
|
|
||||||
*slash = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *overridePath;
|
|
||||||
if(! isPrefs)
|
|
||||||
overridePath = Con::getVariable("$Scripts::OverrideDSOPath");
|
|
||||||
else
|
|
||||||
overridePath = prefsPath;
|
|
||||||
|
|
||||||
if(overridePath && *overridePath)
|
|
||||||
Platform::makeFullPathName(relPath, dsoPath, sizeof(dsoPath), overridePath);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char t[1024];
|
|
||||||
dSprintf(t, sizeof(t), "compiledScripts/%s", relPath);
|
|
||||||
Platform::makeFullPathName(t, dsoPath, sizeof(dsoPath), Platform::getPrefsPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringTable->insert(dsoPath);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
DefineConsoleFunction( getDSOPath, const char*, ( const char* scriptFileName ),,
|
DefineConsoleFunction( getDSOPath, const char*, ( const char* scriptFileName ),,
|
||||||
"Get the absolute path to the file in which the compiled code for the given script file will be stored.\n"
|
"Get the absolute path to the file in which the compiled code for the given script file will be stored.\n"
|
||||||
"@param scriptFileName %Path to the .cs script file.\n"
|
"@param scriptFileName %Path to the .cs script file.\n"
|
||||||
|
|
@ -2320,7 +2263,7 @@ DefineConsoleFunction( getDSOPath, const char*, ( const char* scriptFileName ),,
|
||||||
{
|
{
|
||||||
Con::expandScriptFilename( scriptFilenameBuffer, sizeof(scriptFilenameBuffer), scriptFileName );
|
Con::expandScriptFilename( scriptFilenameBuffer, sizeof(scriptFilenameBuffer), scriptFileName );
|
||||||
|
|
||||||
const char* filename = getDSOPath(scriptFilenameBuffer);
|
const char* filename = Con::getDSOPath(scriptFilenameBuffer);
|
||||||
if(filename == NULL || *filename == 0)
|
if(filename == NULL || *filename == 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
|
|
@ -2347,7 +2290,7 @@ DefineEngineFunction( compile, bool, ( const char* fileName, bool overrideNoDSO
|
||||||
Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
|
Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
|
||||||
|
|
||||||
// Figure out where to put DSOs
|
// Figure out where to put DSOs
|
||||||
StringTableEntry dsoPath = getDSOPath(scriptFilenameBuffer);
|
StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
|
||||||
if(dsoPath && *dsoPath == 0)
|
if(dsoPath && *dsoPath == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -2419,313 +2362,7 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou
|
||||||
"@see eval\n"
|
"@see eval\n"
|
||||||
"@ingroup Scripting" )
|
"@ingroup Scripting" )
|
||||||
{
|
{
|
||||||
bool journal = false;
|
return Con::executeFile(fileName, noCalls, journalScript);
|
||||||
|
|
||||||
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 .cs
|
|
||||||
if(dStrEndsWith(scriptFilenameBuffer, ".dso"))
|
|
||||||
{
|
|
||||||
scriptFilenameBuffer[dStrlen(scriptFilenameBuffer) - dStrlen(".dso")] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out where to put DSOs
|
|
||||||
StringTableEntry dsoPath = getDSOPath(scriptFilenameBuffer);
|
|
||||||
|
|
||||||
const char *ext = dStrrchr(scriptFilenameBuffer, '.');
|
|
||||||
|
|
||||||
if(!ext)
|
|
||||||
{
|
|
||||||
// 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.cs' then compile it to a different compiled extension
|
|
||||||
if( dStricmp( ext, ".cs" ) == 0 )
|
|
||||||
{
|
|
||||||
const char* ext2 = ext - 3;
|
|
||||||
if( dStricmp( ext2, ".ed.cs" ) == 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);
|
|
||||||
|
|
||||||
#ifndef TORQUE_OS_XENON
|
|
||||||
// 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;
|
|
||||||
#else
|
|
||||||
bool compiled = false; // Don't try to compile things on the 360, ignore DSO's when debugging
|
|
||||||
// because PC prefs will screw up stuff like SFX.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DefineConsoleFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" )
|
DefineConsoleFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue