Redo command line parsing

This commit is contained in:
Tamás Bálint Misius 2022-12-31 10:48:44 +01:00
parent 1da7438e39
commit edab57887d
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2

View File

@ -2,6 +2,7 @@
#include "common/tpt-minmax.h"
#include <map>
#include <optional>
#include <ctime>
#include <climits>
#ifdef WIN
@ -296,109 +297,6 @@ unsigned int GetTicks()
return SDL_GetTicks();
}
std::map<ByteString, ByteString> readArguments(int argc, char * argv[])
{
std::map<ByteString, ByteString> arguments;
//Defaults
arguments["scale"] = "";
arguments["proxy"] = "";
arguments["cafile"] = "";
arguments["capath"] = "";
arguments["nohud"] = "false"; //the nohud, sound, and scripts commands currently do nothing.
arguments["sound"] = "false";
arguments["kiosk"] = "false";
arguments["redirect"] = "false";
arguments["nobluescreen"] = "false";
arguments["scripts"] = "false";
arguments["open"] = "";
arguments["ddir"] = "";
arguments["ptsave"] = "";
for (int i=1; i<argc; i++)
{
if (!strncmp(argv[i], "scale:", 6) && argv[i][6])
{
arguments["scale"] = &argv[i][6];
}
else if (!strncmp(argv[i], "proxy:", 6))
{
if(argv[i][6])
arguments["proxy"] = &argv[i][6];
else
arguments["proxy"] = "false";
}
else if (!strncmp(argv[i], "cafile:", 7))
{
if(argv[i][7])
arguments["cafile"] = &argv[i][7];
else
arguments["cafile"] = "false";
}
else if (!strncmp(argv[i], "capath:", 7))
{
if(argv[i][7])
arguments["capath"] = &argv[i][7];
else
arguments["capath"] = "false";
}
else if (!strncmp(argv[i], "nohud", 5))
{
arguments["nohud"] = "true";
}
else if (!strncmp(argv[i], "kiosk", 5))
{
arguments["kiosk"] = "true";
}
else if (!strncmp(argv[i], "redirect", 8))
{
arguments["redirect"] = "true";
}
else if (!strncmp(argv[i], "nobluescreen", 12))
{
arguments["nobluescreen"] = "true";
}
else if (!strncmp(argv[i], "sound", 5))
{
arguments["sound"] = "true";
}
else if (!strncmp(argv[i], "scripts", 8))
{
arguments["scripts"] = "true";
}
else if (!strncmp(argv[i], "file:", 5) && strlen(argv[i]) >= 7)
{
arguments["open"] = format::URLDecode(argv[i] + 7); // skip "file://"
}
else if (!strncmp(argv[i], "open", 5) && i+1<argc)
{
arguments["open"] = argv[i+1];
i++;
}
else if (!strncmp(argv[i], "ddir", 5) && i+1<argc)
{
arguments["ddir"] = argv[i+1];
i++;
}
else if (!strncmp(argv[i], "ptsave:", 7) && strlen(argv[i]) >= 8)
{
arguments["ptsave"] = argv[i];
break;
}
else if (!strncmp(argv[i], "ptsave", 7) && i+1<argc)
{
arguments["ptsave"] = argv[i+1];
i++;
break;
}
else if (!strncmp(argv[i], "disable-network", 16))
{
arguments["disable-network"] = "true";
}
}
return arguments;
}
int elapsedTime = 0, currentTime = 0, lastTime = 0, currentFrame = 0;
unsigned int lastTick = 0;
unsigned int lastFpsUpdate = 0;
@ -731,14 +629,53 @@ int main(int argc, char * argv[])
Platform::originalCwd = Platform::GetCwd();
std::map<ByteString, ByteString> arguments = readArguments(argc, argv);
using Argument = std::optional<ByteString>;
std::map<ByteString, Argument> arguments;
if (arguments["ddir"].length())
for (auto i = 1; i < argc; ++i)
{
auto str = ByteString(argv[i]);
if (str.BeginsWith("file://"))
{
arguments.insert({ "open", format::URLDecode(str.substr(7 /* length of the "file://" prefix */)) });
}
else if (str.BeginsWith("ptsave:"))
{
arguments.insert({ "ptsave", str });
}
else if (auto split = str.SplitBy(':'))
{
arguments.insert({ split.Before(), split.After() });
}
else if (auto split = str.SplitBy('='))
{
arguments.insert({ split.Before(), split.After() });
}
else if (str == "open" || str == "ptsave" || str == "ddir")
{
if (i + 1 < argc)
{
arguments.insert({ str, argv[i + 1] });
i += 1;
}
else
{
std::cerr << "no value provided for command line parameter " << str << std::endl;
}
}
else
{
arguments.insert({ str, "" }); // so .has_value() is true
}
}
auto ddirArg = arguments["ddir"];
if (ddirArg.has_value())
{
#ifdef WIN
int failure = _chdir(arguments["ddir"].c_str());
int failure = _chdir(ddirArg.value().c_str());
#else
int failure = chdir(arguments["ddir"].c_str());
int failure = chdir(ddirArg.value().c_str());
#endif
if (!failure)
Platform::sharedCwd = Platform::GetCwd();
@ -787,14 +724,27 @@ int main(int argc, char * argv[])
momentumScroll = Client::Ref().GetPrefBool("MomentumScroll", true);
showAvatars = Client::Ref().GetPrefBool("ShowAvatars", true);
auto true_string = [](ByteString str) {
str = str.ToLower();
return str == "true" ||
str == "t" ||
str == "on" ||
str == "yes" ||
str == "y" ||
str == ""; // standalone "redirect" or "disable-bluescreen" or similar arguments
};
auto true_arg = [&true_string](Argument arg) {
return arg.has_value() && true_string(arg.value());
};
if(arguments["kiosk"] == "true")
auto kioskArg = arguments["kiosk"];
if (kioskArg.has_value())
{
fullscreen = true;
fullscreen = true_string(kioskArg.value());
Client::Ref().SetPref("Fullscreen", fullscreen);
}
if(arguments["redirect"] == "true")
if (true_arg(arguments["redirect"]))
{
FILE *new_stdout = freopen("stdout.log", "w", stdout);
FILE *new_stderr = freopen("stderr.log", "w", stderr);
@ -804,26 +754,33 @@ int main(int argc, char * argv[])
}
}
if(arguments["scale"].length())
auto scaleArg = arguments["scale"];
if (scaleArg.has_value())
{
scale = arguments["scale"].ToNumber<int>();
Client::Ref().SetPref("Scale", scale);
try
{
scale = scaleArg.value().ToNumber<int>();
Client::Ref().SetPref("Scale", scale);
}
catch (const std::runtime_error &e)
{
std::cerr << "failed to set scale: " << e.what() << std::endl;
}
}
auto clientConfig = [](ByteString cmdlineValue, ByteString configName, ByteString defaultValue) {
auto clientConfig = [](Argument arg, ByteString name, ByteString defaultValue) {
ByteString value;
if (cmdlineValue.length())
if (arg.has_value())
{
value = cmdlineValue;
if (value == "false")
if (value == "")
{
value = defaultValue;
}
Client::Ref().SetPref(configName, value);
Client::Ref().SetPref(name, value);
}
else
{
value = Client::Ref().GetPrefByteString(configName, defaultValue);
value = Client::Ref().GetPrefByteString(name, defaultValue);
}
return value;
};
@ -831,9 +788,7 @@ int main(int argc, char * argv[])
ByteString cafileString = clientConfig(arguments["cafile"], "CAFile", "");
ByteString capathString = clientConfig(arguments["capath"], "CAPath", "");
bool disableNetwork = false;
if (arguments.find("disable-network") != arguments.end())
disableNetwork = true;
bool disableNetwork = true_arg(arguments["disable-network"]);
Client::Ref().Initialise(proxyString, cafileString, capathString, disableNetwork);
@ -871,11 +826,7 @@ int main(int argc, char * argv[])
engine->SetFastQuit(Client::Ref().GetPrefBool("FastQuit", true));
#if !defined(DEBUG)
bool enableBluescreen = true;
if(arguments["nobluescreen"] == "true")
{
enableBluescreen = false;
}
bool enableBluescreen = !true_arg(arguments["disable-bluescreen"]);
if (enableBluescreen)
{
//Get ready to catch any dodgy errors
@ -899,23 +850,24 @@ int main(int argc, char * argv[])
gameController = new GameController();
engine->ShowWindow(gameController->GetView());
if(arguments["open"].length())
auto openArg = arguments["open"];
if (openArg.has_value())
{
#ifdef DEBUG
std::cout << "Loading " << arguments["open"] << std::endl;
std::cout << "Loading " << openArg.value() << std::endl;
#endif
if (Platform::FileExists(arguments["open"]))
if (Platform::FileExists(openArg.value()))
{
try
{
std::vector<char> gameSaveData;
if (!Platform::ReadFile(gameSaveData, arguments["open"]))
if (!Platform::ReadFile(gameSaveData, openArg.value()))
{
new ErrorMessage("Error", "Could not read file");
}
else
{
SaveFile * newFile = new SaveFile(arguments["open"]);
SaveFile * newFile = new SaveFile(openArg.value());
GameSave * newSave = new GameSave(std::move(gameSaveData));
newFile->SetGameSave(newSave);
gameController->LoadSaveFile(newFile);
@ -934,18 +886,18 @@ int main(int argc, char * argv[])
}
}
if (arguments["ptsave"].length())
auto ptsaveArg = arguments["ptsave"];
if (ptsaveArg.has_value())
{
engine->g->fillrect((engine->GetWidth()/2)-101, (engine->GetHeight()/2)-26, 202, 52, 0, 0, 0, 210);
engine->g->drawrect((engine->GetWidth()/2)-100, (engine->GetHeight()/2)-25, 200, 50, 255, 255, 255, 180);
engine->g->drawtext((engine->GetWidth()/2)-(Graphics::textwidth("Loading save...")/2), (engine->GetHeight()/2)-5, "Loading save...", style::Colour::InformationTitle.Red, style::Colour::InformationTitle.Green, style::Colour::InformationTitle.Blue, 255);
blit(engine->g->vid);
ByteString ptsaveArg = arguments["ptsave"];
try
{
ByteString saveIdPart;
if (ByteString::Split split = arguments["ptsave"].SplitBy(':'))
if (ByteString::Split split = ptsaveArg.value().SplitBy(':'))
{
if (split.Before() != "ptsave")
throw std::runtime_error("Not a ptsave link");