mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 07:04:36 +00:00
Fix stack balancing problems by refactoring execution calls
- Con::executef now uses a template - All public execution functions now restore the console stack upon return - Fixed bad parameters on some callbacks - Reverts get*Arg behavior
This commit is contained in:
parent
b1ad72692c
commit
f44a3f27d6
43 changed files with 1781 additions and 358 deletions
|
|
@ -181,6 +181,7 @@ public:
|
|||
fval = 0;
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
type = TypeInternalString;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
|
|
@ -203,9 +204,8 @@ class ConsoleValueRef
|
|||
{
|
||||
public:
|
||||
ConsoleValue *value;
|
||||
const char *stringStackValue;
|
||||
|
||||
ConsoleValueRef() : value(0), stringStackValue(0) { ; }
|
||||
ConsoleValueRef() : value(0) { ; }
|
||||
~ConsoleValueRef() { ; }
|
||||
|
||||
ConsoleValueRef(const ConsoleValueRef &ref);
|
||||
|
|
@ -216,8 +216,9 @@ public:
|
|||
ConsoleValueRef(F32 value);
|
||||
ConsoleValueRef(F64 value);
|
||||
|
||||
static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; }
|
||||
|
||||
const char *getStringValue() { return value ? value->getStringValue() : ""; }
|
||||
const char *getStringArgValue();
|
||||
|
||||
inline U32 getIntValue() { return value ? value->getIntValue() : 0; }
|
||||
inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; }
|
||||
|
|
@ -229,6 +230,7 @@ public:
|
|||
inline operator U32() { return getIntValue(); }
|
||||
inline operator S32() { return getSignedIntValue(); }
|
||||
inline operator F32() { return getFloatValue(); }
|
||||
inline operator bool() { return getBoolValue(); }
|
||||
|
||||
inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStackString : true; }
|
||||
inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; }
|
||||
|
|
@ -281,6 +283,7 @@ public:
|
|||
class StringStackConsoleWrapper
|
||||
{
|
||||
public:
|
||||
ConsoleValue *argvValue;
|
||||
ConsoleValueRef *argv;
|
||||
int argc;
|
||||
|
||||
|
|
@ -753,23 +756,9 @@ namespace Con
|
|||
/// char* argv[] = {"abs", "-9"};
|
||||
/// char* result = execute(2, argv);
|
||||
/// @endcode
|
||||
const char *execute(S32 argc, const char* argv[]);
|
||||
const char *execute(S32 argc, ConsoleValueRef argv[]);
|
||||
|
||||
/// @see execute(S32 argc, const char* argv[])
|
||||
// Note: this can't be ConsoleValueRef& since the compiler will confuse it with SimObject*
|
||||
#define ARG ConsoleValueRef
|
||||
const char *executef( ARG);
|
||||
const char *executef( ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
#undef ARG
|
||||
/// NOTE: this function restores the console stack on return.
|
||||
ConsoleValueRef execute(S32 argc, const char* argv[]);
|
||||
ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[]);
|
||||
|
||||
/// Call a Torque Script member function of a SimObject from C/C++ code.
|
||||
/// @param object Object on which to execute the method call.
|
||||
|
|
@ -783,35 +772,23 @@ namespace Con
|
|||
/// char* argv[] = {"setMode", "", "2"};
|
||||
/// char* result = execute(mysimobject, 3, argv);
|
||||
/// @endcode
|
||||
const char *execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly = false);
|
||||
const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
|
||||
|
||||
/// @see execute(SimObject *, S32 argc, ConsoleValueRef argv[])
|
||||
#define ARG ConsoleValueRef
|
||||
const char *executef(SimObject *, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
|
||||
#undef ARG
|
||||
/// NOTE: this function restores the console stack on return.
|
||||
ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
|
||||
ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
|
||||
|
||||
/// 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.
|
||||
const char *evaluate(const char* string, bool echo = false, const char *fileName = NULL);
|
||||
/// NOTE: This function restores the console stack on return.
|
||||
ConsoleValueRef 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.
|
||||
const char *evaluatef(const char* string, ...);
|
||||
/// NOTE: This function restores the console stack on return.
|
||||
ConsoleValueRef evaluatef(const char* string, ...);
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
@ -831,14 +808,12 @@ namespace Con
|
|||
char* getReturnBuffer( const StringBuilder& str );
|
||||
|
||||
char* getArgBuffer(U32 bufferSize);
|
||||
ConsoleValueRef getFloatArg(F64 arg);
|
||||
ConsoleValueRef getIntArg (S32 arg);
|
||||
char* getStringArg( const char *arg );
|
||||
char* getFloatArg(F64 arg);
|
||||
char* getIntArg (S32 arg);
|
||||
char* getStringArg( const char* arg );
|
||||
char* getStringArg( const String& arg );
|
||||
/// @}
|
||||
|
||||
void resetStackFrame();
|
||||
|
||||
/// @name Namespaces
|
||||
/// @{
|
||||
|
||||
|
|
@ -872,21 +847,47 @@ namespace Con
|
|||
/// @name Dynamic Type System
|
||||
/// @{
|
||||
|
||||
///
|
||||
/* void registerType( const char *typeName, S32 type, S32 size, GetDataFunction gdf, SetDataFunction sdf, bool isDatablockType = false );
|
||||
void registerType( const char* typeName, S32 type, S32 size, bool isDatablockType = false );
|
||||
void registerTypeGet( S32 type, GetDataFunction gdf );
|
||||
void registerTypeSet( S32 type, SetDataFunction sdf );
|
||||
|
||||
const char *getTypeName(S32 type);
|
||||
bool isDatablockType( S32 type ); */
|
||||
|
||||
void setData(S32 type, void *dptr, S32 index, S32 argc, const char **argv, const EnumTable *tbl = NULL, BitSet32 flag = 0);
|
||||
const char *getData(S32 type, void *dptr, S32 index, const EnumTable *tbl = NULL, BitSet32 flag = 0);
|
||||
const char *getFormattedData(S32 type, const char *data, const EnumTable *tbl = NULL, BitSet32 flag = 0);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
struct _EngineConsoleCallbackHelper;
|
||||
template<typename P1> struct _EngineConsoleExecCallbackHelper;
|
||||
|
||||
namespace Con
|
||||
{
|
||||
/// @name Console Execution - executef
|
||||
/// {
|
||||
///
|
||||
/// Implements a script function thunk which automatically converts parameters to relevant console types.
|
||||
/// Can be used as follows:
|
||||
/// - Con::executef("functionName", ...);
|
||||
/// - Con::executef(mySimObject, "functionName", ...);
|
||||
///
|
||||
/// NOTE: if you get a rather cryptic template error coming through here, most likely you are trying to
|
||||
/// convert a parameter which EngineMarshallType does not have a specialization for.
|
||||
/// Another problem can occur if you do not include "console/simBase.h" and "console/engineAPI.h"
|
||||
/// since _EngineConsoleExecCallbackHelper and SimConsoleThreadExecCallback are required.
|
||||
///
|
||||
/// @see _EngineConsoleExecCallbackHelper
|
||||
///
|
||||
template<typename A> ConsoleValueRef executef(A a) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(); }
|
||||
template<typename A, typename B> ConsoleValueRef executef(A a, B b) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b); }
|
||||
template<typename A, typename B, typename C> ConsoleValueRef executef(A a, B b, C c) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c); }
|
||||
template<typename A, typename B, typename C, typename D> ConsoleValueRef executef(A a, B b, C c, D d) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d); }
|
||||
template<typename A, typename B, typename C, typename D, typename E> ConsoleValueRef executef(A a, B b, C c, D d, E e) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f, g); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f, g, h); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f, g, h, i); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j, k); }
|
||||
/// }
|
||||
};
|
||||
|
||||
extern void expandEscape(char *dest, const char *src);
|
||||
extern bool collapseEscape(char *buf);
|
||||
extern U32 HashPointer(StringTableEntry ptr);
|
||||
|
|
@ -1103,6 +1104,28 @@ struct ConsoleDocFragment
|
|||
};
|
||||
|
||||
|
||||
/// Utility class to save and restore the current console stack frame
|
||||
///
|
||||
class ConsoleStackFrameSaver
|
||||
{
|
||||
public:
|
||||
|
||||
bool mSaved;
|
||||
|
||||
ConsoleStackFrameSaver() : mSaved(false)
|
||||
{
|
||||
}
|
||||
|
||||
~ConsoleStackFrameSaver()
|
||||
{
|
||||
restore();
|
||||
}
|
||||
|
||||
void save();
|
||||
void restore();
|
||||
};
|
||||
|
||||
|
||||
/// @name Global Console Definition Macros
|
||||
///
|
||||
/// @note If TORQUE_DEBUG is defined, then we gather documentation information, and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue