diff --git a/src/console/c_commandline.h b/src/console/c_commandline.h index 54d3ad0a6..88b19cc93 100644 --- a/src/console/c_commandline.h +++ b/src/console/c_commandline.h @@ -33,13 +33,13 @@ */ class FConfigFile; -struct osdfuncparm_t; +struct CCmdFuncParm; // Class that can parse command lines class FCommandLine { - friend int OSD_RegisterFunction(const char* pszName, const char* pszDesc, int (*func)(osdfuncparm_t const* const)); + friend int C_RegisterFunction(const char* name, const char* help, int (*func)(CCmdFuncParm const* const)); public: FCommandLine (const char *commandline, bool no_escapes = false); ~FCommandLine (); diff --git a/src/console/c_dispatch.cpp b/src/console/c_dispatch.cpp index 86d3837b1..98e22e1f5 100644 --- a/src/console/c_dispatch.cpp +++ b/src/console/c_dispatch.cpp @@ -58,25 +58,9 @@ #include "c_buttons.h" // MACROS ------------------------------------------------------------------ + // TYPES ------------------------------------------------------------------- -class UnsafeExecutionScope -{ - const bool wasEnabled; - -public: - explicit UnsafeExecutionScope(const bool enable = true) - : wasEnabled(UnsafeExecutionContext) - { - UnsafeExecutionContext = enable; - } - - ~UnsafeExecutionScope() - { - UnsafeExecutionContext = wasEnabled; - } -}; - class FDelayedCommand { public: @@ -182,7 +166,6 @@ void C_ClearDelayedCommands() // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static long ParseCommandLine (const char *args, int *argc, char **argv, bool no_escapes); static FConsoleCommand *FindNameInHashTable (FConsoleCommand **table, const char *name, size_t namelen); static FConsoleCommand *ScanChainForName (FConsoleCommand *start, const char *name, size_t namelen, FConsoleCommand **prev); @@ -337,18 +320,6 @@ void C_DoCommand (const char *cmd, int keynum) } } -// This is only accessible to the special menu item to run CCMDs. -DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) -{ - if (CurrentMenu == nullptr) return 0; - PARAM_PROLOGUE; - PARAM_STRING(cmd); - PARAM_BOOL(unsafe); - UnsafeExecutionScope scope(unsafe); - C_DoCommand(cmd); - return 0; -} - void AddCommandString (const char *text, int keynum) { // Operate on a local copy instead of messing around with the data that's being passed in here. @@ -508,7 +479,7 @@ FConsoleCommand::FConsoleCommand (const char *name, CCmdRun runFunc) int ag = strcmp (name, "kill"); if (ag == 0) ag=0; - m_Name = copystring (name); + m_Name = name; if (!AddToHash (Commands)) Printf ("Adding CCMD %s twice.\n", name); @@ -522,7 +493,6 @@ FConsoleCommand::~FConsoleCommand () if (m_Next) m_Next->m_Prev = m_Prev; C_RemoveTabCommand (m_Name); - delete[] m_Name; } void FConsoleCommand::Run(FCommandLine &argv, int key) @@ -620,7 +590,7 @@ FString BuildString (int argc, FString *argv) void FConsoleCommand::PrintCommand() { - Printf("%s\n", m_Name); + Printf("%s\n", m_Name.GetChars()); } FString SubstituteAliasParams (FString &command, FCommandLine &args) @@ -745,11 +715,11 @@ void FConsoleAlias::PrintAlias () { if (m_Command[0].IsNotEmpty()) { - Printf (TEXTCOLOR_YELLOW "%s : %s\n", m_Name, m_Command[0].GetChars()); + Printf (TEXTCOLOR_YELLOW "%s : %s\n", m_Name.GetChars(), m_Command[0].GetChars()); } if (m_Command[1].IsNotEmpty()) { - Printf (TEXTCOLOR_ORANGE "%s : %s\n", m_Name, m_Command[1].GetChars()); + Printf (TEXTCOLOR_ORANGE "%s : %s\n", m_Name.GetChars(), m_Command[1].GetChars()); } } @@ -846,7 +816,7 @@ CCMD (alias) } else { - Printf ("%s is a normal command\n", alias->m_Name); + Printf ("%s is a normal command\n", alias->m_Name.GetChars()); } } } @@ -862,7 +832,7 @@ CCMD (alias) } else { - Printf ("%s is a normal command\n", alias->m_Name); + Printf ("%s is a normal command\n", alias->m_Name.GetChars()); alias = NULL; } } @@ -952,7 +922,7 @@ void FConsoleAlias::Run (FCommandLine &args, int key) { if (bRunning) { - Printf ("Alias %s tried to recurse.\n", m_Name); + Printf ("Alias %s tried to recurse.\n", m_Name.GetChars()); return; } @@ -1160,6 +1130,37 @@ void C_SearchForPullins(FExecList *exec, const char *file, FCommandLine &argv) } } +static TArray dynccmds; // This needs to be explicitly deleted before shutdown - the names in here may not be valid during the exit handler. +// +// C_RegisterFunction() -- dynamically register a CCMD. +// +int C_RegisterFunction(const char* pszName, const char* pszDesc, int (*func)(CCmdFuncPtr)) +{ + FString nname = pszName; + auto callback = [nname, pszDesc, func](FCommandLine& args, int key) + { + if (args.argc() > 0) args.operator[](0); + CCmdFuncParm param = { args.argc() - 1, nname.GetChars(), (const char**)args._argv + 1, args.cmd }; + if (func(¶m) != CCMD_OK) + { + Printf("%s\n", pszDesc); + } + }; + auto ccmd = new FConsoleCommand(pszName, callback); + dynccmds.Push(ccmd); + return 0; +} + + +void C_ClearDynCCmds() +{ + for (auto ccmd : dynccmds) + { + delete ccmd; + } + dynccmds.Clear(); +} + CCMD (pullin) { // Actual handling for pullin is now completely special-cased above diff --git a/src/console/c_dispatch.h b/src/console/c_dispatch.h index bd3e4da0e..417bae3f7 100644 --- a/src/console/c_dispatch.h +++ b/src/console/c_dispatch.h @@ -35,6 +35,8 @@ #define __C_DISPATCH_H__ #include +#include +#include "c_console.h" #include "tarray.h" #include "c_commandline.h" #include "zstring.h" @@ -75,6 +77,7 @@ void C_DoCommand (const char *cmd, int keynum=0); FExecList *C_ParseExecFile(const char *file, FExecList *source); void C_SearchForPullins(FExecList *exec, const char *file, class FCommandLine &args); bool C_ExecFile(const char *file); +void C_ClearDynCCmds(); // Write out alias commands to a file for all current aliases. void C_ArchiveAliases (FConfigFile *f); @@ -85,8 +88,7 @@ void C_ClearAliases (); // build a single string out of multiple strings FString BuildString (int argc, FString *argv); -class AActor; -typedef void (*CCmdRun) (FCommandLine &argv, int key); +typedef std::function CCmdRun;; class FConsoleCommand { @@ -100,7 +102,7 @@ public: static FConsoleCommand* FindByName (const char* name); FConsoleCommand *m_Next, **m_Prev; - char *m_Name; + FString m_Name; enum { HASH_SIZE = 251 }; // Is this prime? @@ -164,9 +166,48 @@ public: virtual void Run (FCommandLine &args, int key) override; }; +class UnsafeExecutionScope +{ + const bool wasEnabled; + +public: + explicit UnsafeExecutionScope(const bool enable = true) + : wasEnabled(UnsafeExecutionContext) + { + UnsafeExecutionContext = enable; + } + + ~UnsafeExecutionScope() + { + UnsafeExecutionContext = wasEnabled; + } +}; + -#include "superfasthash.h" void execLogfile(const char *fn, bool append = false); +enum +{ + CCMD_OK = 0, + CCMD_SHOWHELP = 1 +}; + +struct CCmdFuncParm +{ + int32_t numparms; + const char* name; + const char** parms; + const char* raw; +}; + +using CCmdFuncPtr = CCmdFuncParm const* const; + +// registers a function +// name = name of the function +// help = a short help string +// func = the entry point to the function +int C_RegisterFunction(const char* name, const char* help, int (*func)(CCmdFuncPtr)); + + #endif //__C_DISPATCH_H__ diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 327c3b440..43aa71a2e 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -55,6 +55,7 @@ #include "menu/menu.h" #include "c_cvars.h" #include "c_bind.h" +#include "c_dispatch.h" DVector2 AM_GetPosition(); int Net_GetLatency(int *ld, int *ad); @@ -3393,6 +3394,18 @@ DEFINE_ACTION_FUNCTION(FKeyBindings, UnbindACommand) return 0; } +// This is only accessible to the special menu item to run CCMDs. +DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) +{ + if (CurrentMenu == nullptr) return 0; + PARAM_PROLOGUE; + PARAM_STRING(cmd); + PARAM_BOOL(unsafe); + UnsafeExecutionScope scope(unsafe); + C_DoCommand(cmd); + return 0; +} +