123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "console/console.h"
- #include "console/consoleInternal.h"
- #include "console/ast.h"
- #include "io/resource/resourceManager.h"
- #include "io/fileStream.h"
- #include "console/compiler.h"
- #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_OSX)
- #include <ifaddrs.h>
- #include <arpa/inet.h>
- #endif
- // Buffer for expanding script filenames.
- static char pathBuffer[1024];
- static U32 execDepth = 0;
- extern S32 QSORT_CALLBACK ACRCompare(const void *aptr, const void *bptr);
- ConsoleFunctionGroupBegin(MetaScripting, "Functions that let you manipulate the scripting engine programmatically.");
- /*! @defgroup MetaScriptingFunctions Meta-Scripting
- @ingroup TorqueScriptFunctions
- @{
- */
- /*! Use the call function to dynamically build and call a function.
- @param funcName A string containing the unadorned name of a function to be executed.
- @param args .. - Any arguments that should be passed to the function.
- @return Returns a string containing the results from the function that is built and called.
- @sa eval
- */
- ConsoleFunctionWithDocs(call, ConsoleString, 2, 0, ( funcName, [args ... ]?))
- {
- return Con::execute(argc - 1, argv + 1);
- }
- static StringTableEntry getDSOPath(const char *scriptPath)
- {
- const char *slash = dStrrchr(scriptPath, '/');
- return StringTable->insertn(scriptPath, (U32)(slash - scriptPath), true);
- }
- /*! Returns the DSO path of the given filename
- @param scriptFileName A string contains the file to search for
- @return Returns either the requested pathname as a string, or an empty string if not found.
- */
- ConsoleFunctionWithDocs(getDSOPath, ConsoleString, 2, 2, (scriptFileName))
- {
- Con::expandPath(pathBuffer, sizeof(pathBuffer), argv[1]);
- const char *filename = getDSOPath(pathBuffer);
- if(filename == NULL || *filename == 0)
- return "";
- return filename;
- }
- /*! Use the compile function to pre-compile a script file without executing the contents.
- @param fileName A path to the script to compile.
- @return Returns 1 if the script compiled without errors and 0 if the file did not compile correctly or if the path is wrong. Also, ff the path is invalid, an error will print to the console.
- @sa exec
- */
- ConsoleFunctionWithDocs(compile, ConsoleBool, 2, 2, ( fileName ))
- {
- TORQUE_UNUSED( argc );
- char nameBuffer[512];
- char* script = NULL;
- U32 scriptSize = 0;
- FileTime comModifyTime, scrModifyTime;
- Con::expandPath(pathBuffer, sizeof(pathBuffer), argv[1]);
- // Figure out where to put DSOs
- StringTableEntry dsoPath = getDSOPath(pathBuffer);
- // If the script file extention is '.ed.cs' then compile it to a different compiled extention
- bool isEditorScript = false;
- const char *ext = dStrrchr( pathBuffer, '.' );
- if( ext && ( dStricmp( ext, ".cs" ) == 0 ) )
- {
- const char* ext2 = ext - 3;
- if( dStricmp( ext2, ".ed.cs" ) == 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(pathBuffer, '/');
- if(filenameOnly)
- ++filenameOnly;
- else
- filenameOnly = pathBuffer;
- if( isEditorScript )
- dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".edso", NULL);
- else
- dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".dso", NULL);
-
- ResourceObject *rScr = ResourceManager->find(pathBuffer);
- ResourceObject *rCom = ResourceManager->find(nameBuffer);
- if(rCom)
- rCom->getFileTimes(NULL, &comModifyTime);
- if(rScr)
- rScr->getFileTimes(NULL, &scrModifyTime);
- Stream *s = ResourceManager->openStream(pathBuffer);
- if(s)
- {
- scriptSize = ResourceManager->getSize(pathBuffer);
- script = new char [scriptSize+1];
- s->read(scriptSize, script);
- ResourceManager->closeStream(s);
- script[scriptSize] = 0;
- }
- if (!scriptSize || !script)
- {
- delete [] script;
- Con::errorf(ConsoleLogEntry::Script, "compile: invalid script file %s.", pathBuffer);
- return false;
- }
- // compile this baddie.
- // -Mat reducing console noise
- #if defined(TORQUE_DEBUG)
- Con::printf("Compiling %s...", pathBuffer);
- #endif
- CodeBlock *code = new CodeBlock();
- code->compile(nameBuffer, pathBuffer, script);
- delete code;
- code = NULL;
- delete[] script;
- return true;
- }
- /*!
- */
- ConsoleFunctionWithDocs(compilePath, ConsoleString, 2, 2, ( path ))
- {
- if ( !Con::expandPath(pathBuffer, sizeof(pathBuffer), argv[1]) )
- return "-1 0";
-
- const char *compileArgs[2] = { "compile", NULL };
-
- S32 failedScripts = 0;
- S32 totalScripts = 0;
- ResourceObject *match = NULL;
-
- while ( (match = ResourceManager->findMatch( pathBuffer, &compileArgs[1], match )) )
- {
- if ( !ccompile( NULL, 1, compileArgs ) )
- failedScripts++;
-
- totalScripts++;
- }
-
- char* result = Con::getReturnBuffer(32);
- dSprintf( result, 32, "%d %d", failedScripts, totalScripts );
- return result;
- }
- static bool scriptExecutionEcho = false;
- /*! Whether to echo script file execution or not.
- */
- ConsoleFunctionWithDocs(setScriptExecEcho, ConsoleVoid, 2, 2, (echo?))
- {
- scriptExecutionEcho = dAtob(argv[1]);
- }
- /*! Use the exec function to compile and execute a normal script, or a special journal script.
- If $Pref::ignoreDSOs is set to true, the system will use .cs before a .dso file if both are found.
- @param fileName A string containing a path to the script to be compiled and executed.
- @param nocalls A boolean value. If this value is set to true, then all function calls encountered while executing the script file will be skipped and not called. This allows us to re-define function definitions found in a script file, without re-executing other worker scripts in the same file.
- @param journalScript A boolean value. If this value is set tot true, and if a journal is being played, the engine will attempt to read this script from the journal stream. If no journal is playing, this field is ignored.
- @return Returns true if the file compiled and executed w/o errors, false otherwise.
- @sa compile
- */
- ConsoleFunctionWithDocs(exec, ConsoleBool, 2, 4, ( fileName, [nocalls]?, [journalScript ]?))
- {
- execDepth++;
- #ifdef TORQUE_ALLOW_JOURNALING
- bool journal = false;
- if(journalDepth >= execDepth)
- journalDepth = execDepth + 1;
- else
- journal = true;
- #endif //TORQUE_ALLOW_JOURNALING
- bool noCalls = false;
- bool ret = false;
- if(argc >= 3 && dAtoi(argv[2]))
- noCalls = true;
- #ifdef TORQUE_ALLOW_JOURNALING
- if(argc >= 4 && dAtoi(argv[3]) && !journal)
- {
- journal = true;
- journalDepth = execDepth;
- }
- #endif //TORQUE_ALLOW_JOURNALING
- // Determine the filename we actually want...
- Con::expandPath(pathBuffer, sizeof(pathBuffer), argv[1]);
- // Figure out where to put DSOs
- StringTableEntry dsoPath = getDSOPath(pathBuffer);
- const char *ext = dStrrchr(pathBuffer, '.');
- if(!ext)
- {
- // We need an extension!
- Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file name %s.", pathBuffer);
- execDepth--;
- return false;
- }
- // Check Editor Extensions
- bool isEditorScript = false;
- #ifdef TORQUE_ALLOW_DSO_GENERATION
- // 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;
- }
- #endif //TORQUE_ALLOW_DSO_GENERATION
- // rdbhack: if we can't find the script file in the game directory, look for it
- // in the Application Data directory. This makes it possible to keep the user
- // ignorant of where the files are actually saving to, thus eliminating the need
- // for the script functions: execPrefs, getUserDataDirectory, etc.
- //
- // This works because we know that script files located in the prefs path will
- // not have compiled versions (it checks for this further down). Otherwise this
- // would be a big problem!
-
- StringTableEntry scriptFileName = StringTable->EmptyString;
- //Luma : This is redundant, we wont be building dso's on the device -
- //plus saving dso to the user directory when attempting build for the
- //release tests on iPhone is irrelevant.
- #ifdef TORQUE_ALLOW_DSO_GENERATION
- if(!ResourceManager->find(pathBuffer))
- {
- // NOTE: this code is pretty much a duplication of code much further down in this
- // function...
- // our work just got a little harder.. if we couldn't find the .cs, then we need to
- // also look for the .dso BEFORE we can try the prefs path.. UGH
- const char *filenameOnly = dStrrchr(pathBuffer, '/');
- if(filenameOnly)
- ++filenameOnly;
- else
- filenameOnly = pathBuffer;
- // we could skip this step and rid ourselves of a bunch of nonsense but we can't be
- // certain the dso path is the same as the path given to use in scriptFileNameBuffer
- char pathAndFilename[1024];
- Platform::makeFullPathName(filenameOnly, pathAndFilename, sizeof(pathAndFilename), dsoPath);
- char nameBuffer[1024];
- if( isEditorScript ) // this should never be the case since we are a PLAYER not a TOOL, but you never know
- dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".edso", NULL);
- else
- dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".dso", NULL);
- if(!ResourceManager->find(nameBuffer))
- scriptFileName = Platform::getPrefsPath(Platform::stripBasePath(pathBuffer));
- else
- scriptFileName = StringTable->insert(pathBuffer);
- }
- else
- scriptFileName = StringTable->insert(pathBuffer);
- #else //TORQUE_ALLOW_DSO_GENERATION
- //Luma : Just insert the file name.
- scriptFileName = StringTable->insert(pathBuffer);
- #endif //TORQUE_ALLOW_DSO_GENERATION
- //Luma : Something screwed up so get out early
- if(scriptFileName == NULL || *scriptFileName == 0)
- {
- execDepth--;
- return false;
- }
- #ifdef TORQUE_ALLOW_JOURNALING
-
- bool compiled = dStricmp(ext, ".mis") && !journal && !Con::getBoolVariable("Scripts::ignoreDSOs");
- #else
- bool compiled = dStricmp(ext, ".mis") && !Con::getBoolVariable("Scripts::ignoreDSOs");
- #endif //TORQUE_ALLOW_JOURNALING
- // [tom, 12/5/2006] stripBasePath() messes up if the filename is not in the exe
- // path, current directory or prefs path. Thus, getDSOFilename() will also mess
- // up and so this allows the scripts to still load but without a DSO.
- if(Platform::isFullPath(Platform::stripBasePath(pathBuffer)))
- 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.
- #ifdef TORQUE_ALLOW_DSO_GENERATION
- // Is this a file we should compile? (anything in the prefs path should not be compiled)
- StringTableEntry prefsPath = Platform::getPrefsPath();
- if( dStrlen(prefsPath) > 0 && dStrnicmp(scriptFileName, prefsPath, dStrlen(prefsPath)) == 0)
- compiled = false;
- #endif //TORQUE_ALLOW_DSO_GENERATION
- // If we're in a journaling mode, then we will read the script
- // from the journal file.
- #ifdef TORQUE_ALLOW_JOURNALING
- if(journal && Game->isJournalReading())
- {
- char fileNameBuf[256];
- bool fileRead;
- U32 fileSize;
- Game->getJournalStream()->readString(fileNameBuf);
- Game->getJournalStream()->read(&fileRead);
- if(!fileRead)
- {
- Con::errorf(ConsoleLogEntry::Script, "Journal script read (failed) for %s", fileNameBuf);
- execDepth--;
- return false;
- }
- Game->journalRead(&fileSize);
- char *script = new char[fileSize + 1];
- Game->journalRead(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;
- }
- #endif //TORQUE_ALLOW_JOURNALING
- // Ok, we let's try to load and compile the script.
- ResourceObject *rScr = ResourceManager->find(scriptFileName);
- ResourceObject *rCom = NULL;
- char nameBuffer[512];
- char* script = NULL;
- U32 scriptSize = 0;
- U32 version;
- Stream *compiledStream = NULL;
- FileTime comModifyTime, scrModifyTime;
- // Check here for .edso
- //bool edso = false;
- //if( dStricmp( ext, ".edso" ) == 0 && rScr )
- //{
- // edso = true;
- // rCom = rScr;
- // rScr = NULL;
- // rCom->getFileTimes( NULL, &comModifyTime );
- // 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; //remove the / at the front
- 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);
- rCom = ResourceManager->find(nameBuffer);
- if(rCom)
- rCom->getFileTimes(NULL, &comModifyTime);
- if(rScr)
- rScr->getFileTimes(NULL, &scrModifyTime);
- }
- // If we had a DSO, let's check to see if we should be reading from it.
- if((compiled && rCom) && (!rScr || Platform::compareFileTimes(comModifyTime, scrModifyTime) >= 0))
- {
- compiledStream = ResourceManager->openStream(nameBuffer);
- if (compiledStream)
- {
- // Check the version!
- compiledStream->read(&version);
- if(version != DSO_VERSION)
- {
- Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, DSO_VERSION);
- ResourceManager->closeStream(compiledStream);
- compiledStream = NULL;
- }
- }
- }
- #ifdef TORQUE_ALLOW_JOURNALING
- // If we're journalling, let's write some info out.
- if(journal && Game->isJournalWriting())
- Game->getJournalStream()->writeString(scriptFileName);
- #endif //TORQUE_ALLOW_JOURNALING
- if(rScr && !compiledStream)
- {
- // If we have source but no compiled version, then we need to compile
- // (and journal as we do so, if that's required).
- //Con::errorf( "No DSO found! : %s", scriptFileName );
-
- Stream *s = ResourceManager->openStream(scriptFileName);
-
- #ifdef TORQUE_ALLOW_JOURNALING
- if(journal && Game->isJournalWriting())
- Game->getJournalStream()->write(bool(s != NULL));
- #endif //TORQUE_ALLOW_JOURNALING
- if(s)
- {
- scriptSize = ResourceManager->getSize(scriptFileName);
- script = new char [scriptSize+1];
- s->read(scriptSize, script);
- #ifdef TORQUE_ALLOW_JOURNALING
- if(journal && Game->isJournalWriting())
- {
- Game->journalWrite(scriptSize);
- Game->journalWrite(scriptSize, script);
- }
- #endif //TORQUE_ALLOW_JOURNALING
- ResourceManager->closeStream(s);
- script[scriptSize] = 0;
- }
- if (!scriptSize || !script)
- {
- delete [] script;
- Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file %s.", scriptFileName);
- execDepth--;
- return false;
- }
- //Luma: Sven -
- // no dsos in the editor, seems to fail with so many console changes and version crap. Leaving it to
- // work with cs files as is, as they are included with the source either way.
- //Also, no DSO generation on iPhone
- #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID) || defined(TORQUE_OS_EMSCRIPTEN)
- if(false)
- #else
- if(compiled)
- #endif
- {
- // compile this baddie.
- #if defined(TORQUE_DEBUG)
- Con::printf("Compiling %s...", scriptFileName);
- #endif
- CodeBlock *code = new CodeBlock();
- code->compile(nameBuffer, scriptFileName, script);
- delete code;
- code = NULL;
- compiledStream = ResourceManager->openStream(nameBuffer);
- if(compiledStream)
- {
- compiledStream->read(&version);
- }
- else
- {
- // We have to exit out here, as otherwise we get double error reports.
- delete [] script;
- execDepth--;
- return false;
- }
- }
- }
- else
- {
- #ifdef TORQUE_ALLOW_JOURNALING
- if(journal && Game->isJournalWriting())
- Game->getJournalStream()->write(bool(false));
- #endif //TORQUE_ALLOW_JOURNALING
- }
-
- //Luma : Load compiled script here
- 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.
-
- //Luma: Profile script executions
- F32 st1 = (F32)Platform::getRealMilliseconds();
- CodeBlock *code = new CodeBlock;
- code->read(scriptFileName, *compiledStream);
- ResourceManager->closeStream(compiledStream);
- code->exec(0, scriptFileName, NULL, 0, NULL, noCalls, NULL, 0);
- F32 et1 = (F32)Platform::getRealMilliseconds();
-
- F32 etf = et1 - st1;
- if ( scriptExecutionEcho )
- Con::printf("Loaded compiled script %s. Took %.0f ms", scriptFileName, etf);
- ret = true;
- }
- else if(rScr) //Luma : Load normal cs file here.
- {
- // No compiled script, let's just try executing it
- // directly... this is either a mission file, or maybe
- // we're on a readonly volume.
-
- CodeBlock *newCodeBlock = new CodeBlock();
- StringTableEntry name = StringTable->insert(scriptFileName);
-
- //Luma: Profile script executions
- F32 st1 = (F32)Platform::getRealMilliseconds();
-
- newCodeBlock->compileExec(name, script, noCalls, 0);
- F32 et1 = (F32)Platform::getRealMilliseconds();
- F32 etf = et1 - st1;
-
- if ( scriptExecutionEcho )
- Con::printf("Executed %s. Took %.0f ms", scriptFileName, etf);
- ret = true;
- }
- else
- {
- // Don't have anything.
- Con::warnf(ConsoleLogEntry::Script, "Missing file: %s!", pathBuffer);
- ret = false;
- }
- delete [] script;
- execDepth--;
- return ret;
- }
- /*! Use the eval function to execute any valid script statement.
- If you choose to eval a multi-line statement, be sure that there are no comments or comment blocks embedded in the script string.
- @param script A string containing a valid script statement. This may be a single line statement or multiple lines concatenated together with new-line characters.
- @return Returns the result of executing the script statement.
- @sa call
- */
- ConsoleFunctionWithDocs(eval, ConsoleString, 2, 2, ( script ))
- {
- TORQUE_UNUSED( argc );
- return Con::evaluate(argv[1], false, NULL);
- }
- /*! Grabs the relevant data for the variable represented by the given string
- @param varName A String representing the variable to check
- @return Returns a string containing component data for the requested variable or an empty string if not found.
- */
- ConsoleFunctionWithDocs(getVariable, ConsoleString, 2, 2, (string varName))
- {
- return Con::getVariable(argv[1]);
- }
- /*! Checks whether given name represents a current valid function.
- @param funcName The name of the function to check.
- @return Returns either true if the string represents a valid function or false if not.
- */
- ConsoleFunctionWithDocs(isFunction, ConsoleBool, 2, 2, (string funcName))
- {
- return Con::isFunction(argv[1]);
- }
- /*! Checks whether the given method name represents a valid method within the given namespace.
- @param namespace A string representing the namespace in which the method should reside.
- @param method The name of the method in question.
- @return Returns a boolean value which is true if the given mathod name represents a valid method in the namespace and false otherwise.
- */
- ConsoleFunctionWithDocs(isMethod, ConsoleBool, 3, 3, (string namespace, string method))
- {
- Namespace* ns = Namespace::find( StringTable->insert( argv[1] ) );
- Namespace::Entry* nse = ns->lookup( StringTable->insert( argv[2] ) );
- if( !nse )
- return false;
- return true;
- }
- /*! Attempts to extract a mod directory from path. Returns empty string on failure.
- */
- ConsoleFunctionWithDocs(getModNameFromPath, ConsoleString, 2, 2, (string path))
- {
- StringTableEntry modPath = Con::getModNameFromPath(argv[1]);
- return modPath ? modPath : "";
- }
- //----------------------------------------------------------------
- /*!
- */
- ConsoleFunctionWithDocs(getPrefsPath, ConsoleString, 1, 2, ([fileName]?))
- {
- const char *filename = Platform::getPrefsPath(argc > 1 ? argv[1] : NULL);
- if(filename == NULL || *filename == 0)
- return "";
-
- return filename;
- }
- /*!
- */
- ConsoleFunctionWithDocs(execPrefs, ConsoleBool, 2, 4, (fileName, [nocalls]?, [journalScript]?))
- {
- const char *filename = Platform::getPrefsPath(argv[1]);
- if (filename == NULL || *filename == 0)
- return false;
- if ( !Platform::isFile(filename) )
- return false;
- argv[0] = "exec";
- argv[1] = filename;
- return dAtob(Con::execute(argc, argv));
- }
- /*! Use the export function to save all global variables matching the specified name pattern in wildCard to a file, either appending to that file or over-writing it.
- @param wildCard A string identifying what variable(s) to export. All characters used to create a global are allowed and the special symbol \*\, meaning 0 or more instances of any character.
- @param fileName A string containing a path to a file in which to save the globals and their definitions.
- @param append A boolean value. If this value is true, the file will be appended to if it exists, otherwise it will be created/over-written.
- @return No return value
- */
- ConsoleFunctionWithDocs(export, ConsoleVoid, 2, 4, ( wildCard, [fileName]?, [append]?))
- {
- // Fetch the wildcard.
- const char* pWildcard = argv[1];
- // Fetch the filename.
- const char* pFilename = NULL;
- if ( argc >= 3 )
- {
- Con::expandPath( pathBuffer, sizeof(pathBuffer), argv[2] );
- pFilename = pathBuffer;
- }
- // Fetch append flag.
- const bool append = argc >= 4 ? dAtob(argv[3] ) : false;
- // Export the variables.
- gEvalState.globalVars.exportVariables( pWildcard, pFilename, append );
- }
- /*! Use the deleteVariables function to delete any global variable matching the wildCard statement.
- @param wildCard A string identifying what variable(s) to delete. All characters used to create a global are allowed and the special symbol \*\, meaning 0 or more instances of any character.
- @return No return value
- */
- ConsoleFunctionWithDocs(deleteVariables, ConsoleVoid, 2, 2, ( wildCard ))
- {
- TORQUE_UNUSED( argc );
- gEvalState.globalVars.deleteVariables(argv[1]);
- }
- //----------------------------------------------------------------
- /*! Use the trace function to enable (or disable) function call tracing. If enabled, tracing will print a message every time a function is entered, showing what arguments it received, and it will print a message every time a function is exited, showing the return value (or last value of last statement) for that function.
- @param enable A boolean value. If set to true, tracing is enabled, otherwise it is disabled.
- @return No return value
- */
- ConsoleFunctionWithDocs(trace, ConsoleVoid, 2, 2, ( enable ))
- {
- TORQUE_UNUSED( argc );
- gEvalState.traceOn = dAtob(argv[1]);
- Con::printf("Console trace is %s", gEvalState.traceOn ? "on." : "off.");
- }
- //----------------------------------------------------------------
- /*! Use the trace function to enable (or disable) function call tracing. If enabled, tracing will print a message every time a function is entered, showing what arguments it received, and it will print a message every time a function is exited, showing the return value (or last value of last statement) for that function.
- @param enable A boolean value. If set to true, tracing is enabled, otherwise it is disabled.
- @return No return value
- */
- ConsoleFunctionWithDocs(editorMode, ConsoleVoid, 2, 2, (enable))
- {
- TORQUE_UNUSED(argc);
- gEvalState.editorModeOn = dAtob(argv[1]);
- }
- //----------------------------------------------------------------
- #if defined(TORQUE_DEBUG) || defined(INTERNAL_RELEASE)
- /*! Use the debug function to cause the engine to issue a debug break and to break into an active debugger.
- For this to work, the engine must have been compiled with either TORQUE_DEBUG, or INTERNAL_RELEASE defined
- @return No return value.
- */
- ConsoleFunctionWithDocs(debug, ConsoleVoid, 1, 1, ())
- {
- TORQUE_UNUSED( argc );
- TORQUE_UNUSED( argv );
- Platform::debugBreak();
- }
- #endif
- #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_OSX)
- //Some code for allowing torsion to connect, this code returns the ipads local ip address
- //code was obtained from http://blog.zachwaugh.com/post/309927273/programmatically-retrieving-ip-address-of-iphone
- //adapted to iT2D by me
- /*! Gets the Apple hardware local IP on wifi. Should work on OS X and iOS
- */
- ConsoleFunctionWithDocs(getAppleDeviceIPAddress, ConsoleString, 1, 1, ())
- {
- char *address = Con::getReturnBuffer(32);
- dStrcpy(address, "error");
- struct ifaddrs *interfaces = NULL;
- struct ifaddrs *temp_addr = NULL;
- int success = 0;
- // retrieve the current interfaces - returns 0 on success
- success = getifaddrs(&interfaces);
- if (success == 0)
- {
- // Loop through linked list of interfaces
- temp_addr = interfaces;
- while(temp_addr != NULL)
- {
- if(temp_addr->ifa_addr->sa_family == AF_INET)
- {
- // Check if interface is en0 which is the wifi connection on the iPhone
- // Note: Could be different on MacOSX and simulator and may need modifying
- if(dStrcmp(temp_addr->ifa_name, "en0") == 0)
- {
- dStrcpy(address, inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
- }
- }
- temp_addr = temp_addr->ifa_next;
- }
- }
- // Free memory
- freeifaddrs(interfaces);
- return address;
- }
- #endif
- //----------------------------------------------------------------
- /*!
- */
- ConsoleFunctionWithDocs( enumerateConsoleClasses, ConsoleString, 1, 2, ([baseClass]?))
- {
- AbstractClassRep *base = NULL;
- if(argc > 1)
- {
- base = AbstractClassRep::findClassRep(argv[1]);
- if(!base)
- return "";
- }
-
- Vector<AbstractClassRep*> classes;
- U32 bufSize = 0;
- for(AbstractClassRep *rep = AbstractClassRep::getClassList(); rep; rep = rep->getNextClass())
- {
- if( !base || rep->isClass(base))
- {
- classes.push_back(rep);
- bufSize += dStrlen(rep->getClassName()) + 1;
- }
- }
-
- if(!classes.size())
- return "";
- dQsort(classes.address(), classes.size(), sizeof(AbstractClassRep*), ACRCompare);
- char* ret = Con::getReturnBuffer(bufSize);
- dStrcpy( ret, classes[0]->getClassName());
- for( U32 i=0; i< (U32)classes.size(); i++)
- {
- dStrcat( ret, "\t" );
- dStrcat( ret, classes[i]->getClassName() );
- }
-
- return ret;
- }
- /*! @} */ // group MetaScriptFunctions
|