From 0fc6882db996d3a1acf1edd849ca6b2447376b60 Mon Sep 17 00:00:00 2001 From: Dreamy Cecil <21009796+DreamyCecil@users.noreply.github.com> Date: Fri, 24 Jan 2025 21:02:03 +0300 Subject: [PATCH] Allow specifying "+game" and "+logfile" options for any application. - Fix next option being skipped and its first argument being parsed as the option name instead. - Fix compilation errors for Visual Studio 2010. --- Sources/DedicatedServer/DedicatedServer.cpp | 2 ++ Sources/Engine/API/CommandLine.cpp | 35 ++++++++++++++++----- Sources/Engine/API/CommandLine.h | 16 +++++++--- Sources/SeriousSam/CmdLine.cpp | 15 +-------- Sources/WorldEditor/WorldEditor.cpp | 9 ------ Sources/bison.simple | 2 +- 6 files changed, 44 insertions(+), 35 deletions(-) diff --git a/Sources/DedicatedServer/DedicatedServer.cpp b/Sources/DedicatedServer/DedicatedServer.cpp index 7adec75c..1fa902ee 100644 --- a/Sources/DedicatedServer/DedicatedServer.cpp +++ b/Sources/DedicatedServer/DedicatedServer.cpp @@ -184,6 +184,8 @@ static void HandleInitialArgs(const CommandLineArgs_t &aArgs) { #endif ded_strConfig = "Scripts\\Dedicated\\" + strConfig + "\\"; + + // [Cecil] NOTE: Always empty at this point, only overriden by +logfile after these initial arguments _strLogFile = "Dedicated_" + strConfig; // Mod directory name diff --git a/Sources/Engine/API/CommandLine.cpp b/Sources/Engine/API/CommandLine.cpp index 3a1e07e8..cd3b99f1 100644 --- a/Sources/Engine/API/CommandLine.cpp +++ b/Sources/Engine/API/CommandLine.cpp @@ -15,6 +15,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "StdH.h" +// Common command line options + +static void OptionGame(const CommandLineArgs_t &aArgs) { + // [Cecil] TEMP: Use base directory for the default mod + if (aArgs[0] != "SeriousSam") { + _fnmMod = "Mods\\" + aArgs[0] + "\\"; + } +}; + +static void OptionLogFile(const CommandLineArgs_t &aArgs) { + _strLogFile = aArgs[0]; +}; + // Separate a string into multiple arguments (e.g. command line arguments) // Implemented according to the rules from Microsoft docs: // https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments?view=msvc-170 @@ -113,11 +126,18 @@ static void StringToArgs(const char *str, CommandLineArgs_t &aArgs) } }; +// Add common command line option processors +inline void AddCommonProcessors(CommandLineSetup *pCmd) { + pCmd->AddCommand("+game", &OptionGame, 1); + pCmd->AddCommand("+logfile", &OptionLogFile, 1); +}; + // Constructor for C-like command line CommandLineSetup::CommandLineSetup(int argc, char **argv) : pInitialArgs(NULL, -1), pUnknownOption(NULL) { GetArguments(argc, argv, aArgs); + AddCommonProcessors(this); // Cache the entire command line as a single string strCommandLine = ""; @@ -136,6 +156,7 @@ CommandLineSetup::CommandLineSetup(const char *strCmd) : pInitialArgs(NULL, -1), pUnknownOption(NULL) { GetArguments(strCmd, aArgs); + AddCommonProcessors(this); strCommandLine = strCmd; }; @@ -172,10 +193,13 @@ void SE_ParseCommandLine(const CommandLineSetup &cmd) { const CommandLineFunction_t *pCmdFunc = NULL; // Parse initial arguments - if (i == 0 && cmd.pInitialArgs.first != NULL) { + if (i == 0 && cmd.pInitialArgs.pFunc != NULL) { strCmd = "Program executable"; pCmdFunc = &cmd.pInitialArgs; + // Pretend that this is a real option so it pushes arguments starting from 0 + i--; + } else { // Get command name strCmd = cmd[i].ConstData(); @@ -203,15 +227,12 @@ void SE_ParseCommandLine(const CommandLineSetup &cmd) { // Get command line function from the command pCmdFunc = &itCmd->second; - - // Skip the command argument - i++; } // Get command function - FCommandLineCallback pFunc = pCmdFunc->first; + FCommandLineCallback pFunc = pCmdFunc->pFunc; - INDEX ctArgs = pCmdFunc->second; + INDEX ctArgs = pCmdFunc->ctArgs; INDEX ctLeft = ct - i; // Not enough arguments for the last command @@ -223,7 +244,7 @@ void SE_ParseCommandLine(const CommandLineSetup &cmd) { // Retrieve required amount of arguments for the command while (--ctArgs >= 0) { - aCmdArgs.Add(cmd[i++]); + aCmdArgs.Add(cmd[++i]); } // Call command function with the arguments diff --git a/Sources/Engine/API/CommandLine.h b/Sources/Engine/API/CommandLine.h index 3fe76a1f..598f2b14 100644 --- a/Sources/Engine/API/CommandLine.h +++ b/Sources/Engine/API/CommandLine.h @@ -30,7 +30,13 @@ typedef CStaticStackArray CommandLineArgs_t; typedef void (*FCommandLineCallback)(const CommandLineArgs_t &); // Command callback with argument count (e.g. if expecting "+run MyMod 0" command, then the argument count is 2) -typedef std::pair CommandLineFunction_t; +struct CommandLineFunction_t { + FCommandLineCallback pFunc; + INDEX ctArgs; + + __forceinline CommandLineFunction_t(FCommandLineCallback pSetFunc = NULL, INDEX ctSetArgs = -1) : + pFunc(pSetFunc), ctArgs(ctSetArgs) {}; +}; // Setup structure for command line arguments struct ENGINE_API CommandLineSetup { @@ -70,12 +76,14 @@ struct ENGINE_API CommandLineSetup { // Register new command callback inline void AddCommand(const CTString &strName, FCommandLineCallback pFunc, INDEX ctArguments) { - mapCommands[strName] = std::make_pair(pFunc, ctArguments); + ASSERT(ctArguments >= 0); + mapCommands[strName] = CommandLineFunction_t(pFunc, ctArguments); }; // Register initial arguments parser inline void AddInitialParser(FCommandLineCallback pFunc, INDEX ctArguments) { - pInitialArgs = std::make_pair(pFunc, ctArguments); + ASSERT(ctArguments > 0); // No point in processing initial arguments with no arguments + pInitialArgs = CommandLineFunction_t(pFunc, ctArguments); }; // Register unknown options handler @@ -89,7 +97,7 @@ struct ENGINE_API CommandLineSetup { }; // Accessor operator (equal to argv[i - 1]) - inline const CTString &operator[](size_t i) const { + inline const CTString &operator[](INDEX i) const { return aArgs[i]; }; }; diff --git a/Sources/SeriousSam/CmdLine.cpp b/Sources/SeriousSam/CmdLine.cpp index 201b9c41..30bb9291 100644 --- a/Sources/SeriousSam/CmdLine.cpp +++ b/Sources/SeriousSam/CmdLine.cpp @@ -40,13 +40,6 @@ static void OptionQuickJoin(const CommandLineArgs_t &) { cmd_bQuickJoin = TRUE; }; -static void OptionGame(const CommandLineArgs_t &aArgs) { - // Use base directory for the default mod - if (aArgs[0] != "SeriousSam") { - _fnmMod = "Mods\\" + aArgs[0] + "\\"; - } -}; - static void OptionPassword(const CommandLineArgs_t &aArgs) { cmd_strPassword = aArgs[0]; }; @@ -69,11 +62,7 @@ static void OptionScript(const CommandLineArgs_t &aArgs) { }; static void OptionGoTo(const CommandLineArgs_t &aArgs) { - aArgs[0].ScanF("%d", &cmd_iGoToMarker); -}; - -static void OptionLogFile(const CommandLineArgs_t &aArgs) { - _strLogFile = aArgs[0]; + cmd_iGoToMarker = strtol(aArgs[0].ConstData(), NULL, 10); }; // [Cecil] Register command line functions @@ -81,10 +70,8 @@ void SetupCommandLine(CommandLineSetup &cmd) { cmd.AddCommand("+level", &OptionLevel, 1); cmd.AddCommand("+server", &OptionServer, 0); cmd.AddCommand("+quickjoin", &OptionQuickJoin, 0); - cmd.AddCommand("+game", &OptionGame, 1); cmd.AddCommand("+password", &OptionPassword, 1); cmd.AddCommand("+connect", &OptionConnect, 1); cmd.AddCommand("+script", &OptionScript, 1); cmd.AddCommand("+goto", &OptionGoTo, 1); - cmd.AddCommand("+logfile", &OptionLogFile, 1); }; diff --git a/Sources/WorldEditor/WorldEditor.cpp b/Sources/WorldEditor/WorldEditor.cpp index 6f1010c2..d82399a7 100644 --- a/Sources/WorldEditor/WorldEditor.cpp +++ b/Sources/WorldEditor/WorldEditor.cpp @@ -419,14 +419,6 @@ static BOOL HandleUnknownOption(const CTString &strCmd) { return TRUE; }; -// [Cecil] Command line options as functions -static void OptionGame(const CommandLineArgs_t &aArgs) { - // Use base directory for the default mod - if (aArgs[0] != "SeriousSam") { - _fnmMod = "Mods\\" + aArgs[0] + "\\"; - } -}; - BOOL CWorldEditorApp::SubInitInstance() { // required for visual styles @@ -453,7 +445,6 @@ BOOL CWorldEditorApp::SubInitInstance() // [Cecil] Parse command line arguments CommandLineSetup cmd(strCmdCopy.ConstData()); cmd.AddUnknownHandler(&HandleUnknownOption); - cmd.AddCommand("+game", &OptionGame, 1); SE_ParseCommandLine(cmd); } diff --git a/Sources/bison.simple b/Sources/bison.simple index d3f068e3..45bea8ec 100644 --- a/Sources/bison.simple +++ b/Sources/bison.simple @@ -261,7 +261,7 @@ yyparse(YYPARSE_PARAM) yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - yyval = {}; /* [Cecil] Prevent runtime assertion */ + yyval = YYSTYPE(); /* [Cecil] Prevent runtime assertion */ /* Initialize stack pointers. Waste one element of value and location stack