forked from speed-dreams/speed-dreams-code
patch for catch (by Scott)
git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@6926 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: b5c1d77b003ea626ebbaa73eb21d29bde5004cee Former-commit-id: a31f1f43364b08de9638477112da11319adca7ea
This commit is contained in:
parent
ffeb2061a1
commit
7ae1fa574e
1 changed files with 398 additions and 398 deletions
|
@ -16,8 +16,8 @@
|
||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
Application base
|
Application base
|
||||||
@version $Id$
|
@version $Id$
|
||||||
@ingroup tgf
|
@ingroup tgf
|
||||||
*/
|
*/
|
||||||
|
@ -47,499 +47,499 @@ GfApplication* GfApplication::_pSelf = 0;
|
||||||
|
|
||||||
GfApplication& GfApplication::self()
|
GfApplication& GfApplication::self()
|
||||||
{
|
{
|
||||||
if (!_pSelf)
|
if (!_pSelf)
|
||||||
{
|
{
|
||||||
GfLogError("GfApplication not yet created ; exiting");
|
GfLogError("GfApplication not yet created ; exiting");
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *_pSelf;
|
return *_pSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
GfApplication::GfApplication(const char* pszName, const char* pszVersion, const char* pszDesc)
|
GfApplication::GfApplication(const char* pszName, const char* pszVersion, const char* pszDesc)
|
||||||
: _strName(pszName ? pszName : "GfApplication"), _strDesc(pszDesc ? pszDesc : ""),
|
: _strName(pszName ? pszName : "GfApplication"), _strDesc(pszDesc ? pszDesc : ""),
|
||||||
_strVersion(pszVersion ? pszVersion : ""), _pEventLoop(0)
|
_strVersion(pszVersion ? pszVersion : ""), _pEventLoop(0)
|
||||||
{
|
{
|
||||||
// Check that we are the only instance.
|
// Check that we are the only instance.
|
||||||
if (_pSelf)
|
if (_pSelf)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "More than one GfApplication instance ; exiting\n");
|
fprintf(stderr, "More than one GfApplication instance ; exiting\n");
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register oneself as the one.
|
// Register oneself as the one.
|
||||||
_pSelf = this;
|
_pSelf = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::initialize(bool bLoggingEnabled, int argc, char **argv)
|
void GfApplication::initialize(bool bLoggingEnabled, int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Store the command line args.
|
// Store the command line args.
|
||||||
if (argv)
|
if (argv)
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
_lstArgs.push_back(argv[i]);
|
_lstArgs.push_back(argv[i]);
|
||||||
|
|
||||||
// Initialize the gaming framework (beware: only GfLogDefault booted).
|
// Initialize the gaming framework (beware: only GfLogDefault booted).
|
||||||
GfInit(bLoggingEnabled);
|
GfInit(bLoggingEnabled);
|
||||||
|
|
||||||
// Trace app. information.
|
// Trace app. information.
|
||||||
GfLogInfo("%s %s", _strName.c_str(), _strVersion.c_str());
|
GfLogInfo("%s %s", _strName.c_str(), _strVersion.c_str());
|
||||||
if (!_strDesc.empty())
|
if (!_strDesc.empty())
|
||||||
GfLogInfo(" (%s)", _strDesc.c_str());
|
GfLogInfo(" (%s)", _strDesc.c_str());
|
||||||
GfLogInfo("\n");
|
GfLogInfo("\n");
|
||||||
|
|
||||||
// Register the command line options (to be parsed).
|
// Register the command line options (to be parsed).
|
||||||
registerOption("h", "help", /* nHasValue = */ false);
|
registerOption("h", "help", /* nHasValue = */ false);
|
||||||
registerOption("v", "version", /* nHasValue = */ false);
|
registerOption("v", "version", /* nHasValue = */ false);
|
||||||
registerOption("lc", "localdir", /* nHasValue = */ true);
|
registerOption("lc", "localdir", /* nHasValue = */ true);
|
||||||
registerOption("ld", "libdir", /* nHasValue = */ true);
|
registerOption("ld", "libdir", /* nHasValue = */ true);
|
||||||
registerOption("bd", "bindir", /* nHasValue = */ true);
|
registerOption("bd", "bindir", /* nHasValue = */ true);
|
||||||
registerOption("dd", "datadir", /* nHasValue = */ true);
|
registerOption("dd", "datadir", /* nHasValue = */ true);
|
||||||
registerOption("tl", "tracelevel", /* nHasValue = */ true);
|
registerOption("tl", "tracelevel", /* nHasValue = */ true);
|
||||||
registerOption("ts", "tracestream", /* nHasValue = */ true);
|
registerOption("ts", "tracestream", /* nHasValue = */ true);
|
||||||
registerOption("nr", "norandom", /* nHasValue = */ false);
|
registerOption("nr", "norandom", /* nHasValue = */ false);
|
||||||
|
|
||||||
// Help about the command line options.
|
// Help about the command line options.
|
||||||
addOptionsHelpSyntaxLine("[-v|--version]");
|
addOptionsHelpSyntaxLine("[-v|--version]");
|
||||||
addOptionsHelpSyntaxLine("[-h|--help]");
|
addOptionsHelpSyntaxLine("[-h|--help]");
|
||||||
addOptionsHelpSyntaxLine("[-lc|--localdir <dir path>] [-ld|--libdir <dir path>]");
|
addOptionsHelpSyntaxLine("[-lc|--localdir <dir path>] [-ld|--libdir <dir path>]");
|
||||||
addOptionsHelpSyntaxLine("[-bd|--bindir <dir path>] [-dd|--datadir <dir path>]");
|
addOptionsHelpSyntaxLine("[-bd|--bindir <dir path>] [-dd|--datadir <dir path>]");
|
||||||
#ifdef TRACE_OUT
|
#ifdef TRACE_OUT
|
||||||
addOptionsHelpSyntaxLine("[-tl|--tracelevel <integer>]"
|
addOptionsHelpSyntaxLine("[-tl|--tracelevel <integer>]"
|
||||||
" [-ts|--tracestream stdout|stderr|<file name>]");
|
" [-ts|--tracestream stdout|stderr|<file name>]");
|
||||||
#endif
|
#endif
|
||||||
addOptionsHelpSyntaxLine("[-nr|--norandom]");
|
addOptionsHelpSyntaxLine("[-nr|--norandom]");
|
||||||
|
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- locadir : Root dir of the tree where user settings files are stored");
|
("- locadir : Root dir of the tree where user settings files are stored");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
(" (default=" SD_LOCALDIR ")");
|
(" (default=" SD_LOCALDIR ")");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- libdir : Root dir of the tree where loadable modules are installed");
|
("- libdir : Root dir of the tree where loadable modules are installed");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
(" (default=" SD_LIBDIR ")");
|
(" (default=" SD_LIBDIR ")");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- bindir : Dir where the game exe and DLLs are installed");
|
("- bindir : Dir where the game exe and DLLs are installed");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
(" (default=" SD_BINDIR ")");
|
(" (default=" SD_BINDIR ")");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- datadir : Root dir of the data tree (cars, tracks, ...)");
|
("- datadir : Root dir of the data tree (cars, tracks, ...)");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
(" (default=" SD_DATADIR ")");
|
(" (default=" SD_DATADIR ")");
|
||||||
#ifdef TRACE_OUT
|
#ifdef TRACE_OUT
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- tracelevel : Maximum level of displayed traces for the default logger");
|
("- tracelevel : Maximum level of displayed traces for the default logger");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
(" (0=Fatal, 1=Error, 2=Warning, 3=Info, 4=Trace, 5=Debug, ... ; default=5)");
|
(" (0=Fatal, 1=Error, 2=Warning, 3=Info, 4=Trace, 5=Debug, ... ; default=5)");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- tracestream : Target output stream for the default logger (default=stderr)");
|
("- tracestream : Target output stream for the default logger (default=stderr)");
|
||||||
addOptionsHelpExplainLine
|
addOptionsHelpExplainLine
|
||||||
("- norandom : Force reproducible random sequences for every game session (default=off)");
|
("- norandom : Force reproducible random sequences for every game session (default=off)");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& GfApplication::name() const
|
const std::string& GfApplication::name() const
|
||||||
{
|
{
|
||||||
return _strName;
|
return _strName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& GfApplication::description() const
|
const std::string& GfApplication::description() const
|
||||||
{
|
{
|
||||||
return _strDesc;
|
return _strDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& GfApplication::version() const
|
const std::string& GfApplication::version() const
|
||||||
{
|
{
|
||||||
return _strVersion;
|
return _strVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::updateUserSettings()
|
void GfApplication::updateUserSettings()
|
||||||
{
|
{
|
||||||
GfFileSetup();
|
GfFileSetup();
|
||||||
|
|
||||||
// Complete logging system initialisation
|
|
||||||
// 1) Reparse the relevant options if present.
|
|
||||||
int nDefTraceLevel = std::numeric_limits<int>::min();
|
|
||||||
std::string strDefTraceStream;
|
|
||||||
|
|
||||||
std::list<Option>::const_iterator itOpt;
|
// Complete logging system initialisation
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
// 1) Reparse the relevant options if present.
|
||||||
{
|
int nDefTraceLevel = std::numeric_limits<int>::min();
|
||||||
// Not found in the command line => ignore / default value.
|
std::string strDefTraceStream;
|
||||||
if (!itOpt->bFound)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Trace level threshold (only #ifdef TRACE_OUT)
|
|
||||||
if (itOpt->strLongName == "tracelevel")
|
|
||||||
{
|
|
||||||
if (sscanf(itOpt->strValue.c_str(), "%d", &nDefTraceLevel) < 1)
|
|
||||||
{
|
|
||||||
printUsage("Error: Could not convert trace level to an integer.");
|
|
||||||
nDefTraceLevel = std::numeric_limits<int>::min();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Target trace stream (only #ifdef TRACE_OUT)
|
|
||||||
else if (itOpt->strLongName == "tracestream")
|
|
||||||
{
|
|
||||||
strDefTraceStream = itOpt->strValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Take the options into account.
|
std::list<Option>::const_iterator itOpt;
|
||||||
// Note: Not achieved earlier because we need one of the user settings files : logging.xml.
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
GfLogger::setup();
|
{
|
||||||
if (nDefTraceLevel != std::numeric_limits<int>::min())
|
// Not found in the command line => ignore / default value.
|
||||||
GfLogDefault.setLevelThreshold(nDefTraceLevel);
|
if (!itOpt->bFound)
|
||||||
if (!strDefTraceStream.empty())
|
continue;
|
||||||
GfLogDefault.setStream(strDefTraceStream);
|
|
||||||
|
// Trace level threshold (only #ifdef TRACE_OUT)
|
||||||
|
if (itOpt->strLongName == "tracelevel")
|
||||||
|
{
|
||||||
|
if (sscanf(itOpt->strValue.c_str(), "%d", &nDefTraceLevel) < 1)
|
||||||
|
{
|
||||||
|
printUsage("Error: Could not convert trace level to an integer.");
|
||||||
|
nDefTraceLevel = std::numeric_limits<int>::min();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Target trace stream (only #ifdef TRACE_OUT)
|
||||||
|
else if (itOpt->strLongName == "tracestream")
|
||||||
|
{
|
||||||
|
strDefTraceStream = itOpt->strValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Take the options into account.
|
||||||
|
// Note: Not achieved earlier because we need one of the user settings files : logging.xml.
|
||||||
|
GfLogger::setup();
|
||||||
|
if (nDefTraceLevel != std::numeric_limits<int>::min())
|
||||||
|
GfLogDefault.setLevelThreshold(nDefTraceLevel);
|
||||||
|
if (!strDefTraceStream.empty())
|
||||||
|
GfLogDefault.setStream(strDefTraceStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::setEventLoop(GfEventLoop* pEventLoop)
|
void GfApplication::setEventLoop(GfEventLoop* pEventLoop)
|
||||||
{
|
{
|
||||||
_pEventLoop = pEventLoop;
|
_pEventLoop = pEventLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
GfEventLoop& GfApplication::eventLoop()
|
GfEventLoop& GfApplication::eventLoop()
|
||||||
{
|
{
|
||||||
if (!_pEventLoop)
|
if (!_pEventLoop)
|
||||||
GfLogError("GfApplication has no event loop ; crashing !\n");
|
GfLogError("GfApplication has no event loop ; crashing !\n");
|
||||||
|
|
||||||
return *_pEventLoop;
|
return *_pEventLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::restart()
|
void GfApplication::restart()
|
||||||
{
|
{
|
||||||
// Shutdown the gaming framework.
|
// Shutdown the gaming framework.
|
||||||
GfShutdown();
|
GfShutdown();
|
||||||
|
|
||||||
// Delete the event loop if any.
|
// Delete the event loop if any.
|
||||||
delete _pEventLoop;
|
delete _pEventLoop;
|
||||||
_pEventLoop = 0;
|
_pEventLoop = 0;
|
||||||
|
|
||||||
// Reset the Memory Manager
|
// Reset the Memory Manager
|
||||||
#ifdef __DEBUG_MEMORYMANAGER__
|
#ifdef __DEBUG_MEMORYMANAGER__
|
||||||
(*ReleaseData)();
|
(*ReleaseData)();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Restart the process, using same command line args.
|
// Restart the process, using same command line args.
|
||||||
// 1) The process executable path-name is the 1st arg left untouched.
|
// 1) The process executable path-name is the 1st arg left untouched.
|
||||||
GfLogInfo("Restarting :\n");
|
GfLogInfo("Restarting :\n");
|
||||||
GfLogInfo(" Command : %s\n", _lstArgs.front().c_str());
|
GfLogInfo(" Command : %s\n", _lstArgs.front().c_str());
|
||||||
|
|
||||||
// 2) Allocate and populate the args array (last arg must be a null pointer).
|
// 2) Allocate and populate the args array (last arg must be a null pointer).
|
||||||
// TODO: Add an API for filtering the args (some might not be relevant for a restart).
|
// TODO: Add an API for filtering the args (some might not be relevant for a restart).
|
||||||
GfLogInfo(" Args : ");
|
GfLogInfo(" Args : ");
|
||||||
char** apszArgs = (char**)malloc(sizeof(char*) * (_lstArgs.size() + 1));
|
char** apszArgs = (char**)malloc(sizeof(char*) * (_lstArgs.size() + 1));
|
||||||
|
|
||||||
unsigned nArgInd = 0;
|
unsigned nArgInd = 0;
|
||||||
std::list<std::string>::const_iterator itArg;
|
std::list<std::string>::const_iterator itArg;
|
||||||
for (itArg = _lstArgs.begin(); itArg != _lstArgs.end(); itArg++)
|
for (itArg = _lstArgs.begin(); itArg != _lstArgs.end(); itArg++)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// execvp will not automatically surround args with spaces inside with double quotes !
|
// execvp will not automatically surround args with spaces inside with double quotes !
|
||||||
if (itArg->find(' ') != std::string::npos)
|
if (itArg->find(' ') != std::string::npos)
|
||||||
{
|
{
|
||||||
char pszArg[512];
|
char pszArg[512];
|
||||||
snprintf(pszArg, sizeof(pszArg), "\"%s\"", itArg->c_str());
|
snprintf(pszArg, sizeof(pszArg), "\"%s\"", itArg->c_str());
|
||||||
apszArgs[nArgInd] = strdup(pszArg);
|
apszArgs[nArgInd] = strdup(pszArg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
apszArgs[nArgInd] = strdup(itArg->c_str());
|
apszArgs[nArgInd] = strdup(itArg->c_str());
|
||||||
|
|
||||||
|
GfLogInfo("%s ", apszArgs[nArgInd]);
|
||||||
|
|
||||||
GfLogInfo("%s ", apszArgs[nArgInd]);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// execvp will automatically surround args with spaces inside with double quotes.
|
// execvp will automatically surround args with spaces inside with double quotes.
|
||||||
apszArgs[nArgInd] = strdup(itArg->c_str());
|
apszArgs[nArgInd] = strdup(itArg->c_str());
|
||||||
|
|
||||||
if (itArg->find(' ') != std::string::npos)
|
if (itArg->find(' ') != std::string::npos)
|
||||||
GfLogInfo("\"%s\" ", itArg->c_str());
|
GfLogInfo("\"%s\" ", itArg->c_str());
|
||||||
else
|
else
|
||||||
GfLogInfo("%s ", itArg->c_str());
|
GfLogInfo("%s ", itArg->c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Next arg.
|
// Next arg.
|
||||||
nArgInd++;
|
nArgInd++;
|
||||||
}
|
}
|
||||||
apszArgs[nArgInd] = 0;
|
apszArgs[nArgInd] = 0;
|
||||||
GfLogInfo("...\n\n");
|
GfLogInfo("...\n\n");
|
||||||
|
|
||||||
// 3) Exec the command with its args (replacing current process).
|
|
||||||
const int retcode = execvp(_lstArgs.front().c_str(), apszArgs);
|
|
||||||
|
|
||||||
// If the restart was successfull, we never get there ... But if it failed ...
|
// 3) Exec the command with its args (replacing current process).
|
||||||
GfLogError("Failed to restart (exit code %d, %s)\n", retcode, strerror(errno));
|
const int retcode = execvp(_lstArgs.front().c_str(), apszArgs);
|
||||||
for (nArgInd = 0; apszArgs[nArgInd]; nArgInd++)
|
|
||||||
free(apszArgs[nArgInd]);
|
// If the restart was successfull, we never get there ... But if it failed ...
|
||||||
free(apszArgs);
|
GfLogError("Failed to restart (exit code %d, %s)\n", retcode, strerror(errno));
|
||||||
|
for (nArgInd = 0; apszArgs[nArgInd]; nArgInd++)
|
||||||
exit(1);
|
free(apszArgs[nArgInd]);
|
||||||
|
free(apszArgs);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::printUsage(const char* pszErrMsg) const
|
void GfApplication::printUsage(const char* pszErrMsg) const
|
||||||
{
|
{
|
||||||
if (pszErrMsg)
|
if (pszErrMsg)
|
||||||
std::cout << std::endl << "Error: " << pszErrMsg << std::endl << std::endl;
|
std::cout << std::endl << "Error: " << pszErrMsg << std::endl << std::endl;
|
||||||
|
|
||||||
std::cout << "Usage: " << _lstArgs.front() << " ..." << std::endl;
|
|
||||||
|
|
||||||
std::list<std::string>::const_iterator itSynLine = _optionsHelp.lstSyntaxLines.begin();
|
std::cout << "Usage: " << _lstArgs.front() << " ..." << std::endl;
|
||||||
while (itSynLine != _optionsHelp.lstSyntaxLines.end())
|
|
||||||
{
|
|
||||||
std::cout << " " << *itSynLine << std::endl;
|
|
||||||
itSynLine++;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<std::string>::const_iterator itExplLine = _optionsHelp.lstExplainLines.begin();
|
std::list<std::string>::const_iterator itSynLine = _optionsHelp.lstSyntaxLines.begin();
|
||||||
while (itExplLine != _optionsHelp.lstExplainLines.end())
|
while (itSynLine != _optionsHelp.lstSyntaxLines.end())
|
||||||
{
|
{
|
||||||
std::cout << " " << *itExplLine << std::endl;
|
std::cout << " " << *itSynLine << std::endl;
|
||||||
itExplLine++;
|
itSynLine++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::string>::const_iterator itExplLine = _optionsHelp.lstExplainLines.begin();
|
||||||
|
while (itExplLine != _optionsHelp.lstExplainLines.end())
|
||||||
|
{
|
||||||
|
std::cout << " " << *itExplLine << std::endl;
|
||||||
|
itExplLine++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GfApplication::parseOptions()
|
bool GfApplication::parseOptions()
|
||||||
{
|
{
|
||||||
// Determine and store run-time install root dir.
|
// Determine and store run-time install root dir.
|
||||||
GfInitInstallDir(_lstArgs.front().c_str());
|
GfInitInstallDir(_lstArgs.front().c_str());
|
||||||
|
|
||||||
// Parse args, looking for registered options.
|
// Parse args, looking for registered options.
|
||||||
GfLogInfo("Parsing command line args (%d)\n", _lstArgs.size() - 1);
|
GfLogInfo("Parsing command line args (%d)\n", _lstArgs.size() - 1);
|
||||||
std::list<std::string>::const_iterator itArg = _lstArgs.begin();
|
std::list<std::string>::const_iterator itArg = _lstArgs.begin();
|
||||||
for (itArg++; itArg != _lstArgs.end(); itArg++)
|
for (itArg++; itArg != _lstArgs.end(); itArg++)
|
||||||
{
|
{
|
||||||
bool bArgEaten = false;
|
bool bArgEaten = false;
|
||||||
if (itArg->find('-') == 0)
|
if (itArg->find('-') == 0)
|
||||||
{
|
{
|
||||||
// We've probably got an option flag : check this a bit more in depth.
|
// We've probably got an option flag : check this a bit more in depth.
|
||||||
std::list<Option>::iterator itOpt;
|
std::list<Option>::iterator itOpt;
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
{
|
{
|
||||||
if (itOpt->strShortName == itArg->substr(1, std::string::npos)
|
if (itOpt->strShortName == itArg->substr(1, std::string::npos)
|
||||||
|| itOpt->strLongName == itArg->substr(2, std::string::npos))
|
|| itOpt->strLongName == itArg->substr(2, std::string::npos))
|
||||||
{
|
{
|
||||||
// We've got a registered option flag : check if there's a value arg or not.
|
// We've got a registered option flag : check if there's a value arg or not.
|
||||||
if (itOpt->bHasValue)
|
if (itOpt->bHasValue)
|
||||||
{
|
{
|
||||||
const std::string strFlag(*itArg);
|
const std::string strFlag(*itArg);
|
||||||
itArg++;
|
itArg++;
|
||||||
if (itArg != _lstArgs.end() // Some extra arg available ...
|
if (itArg != _lstArgs.end() // Some extra arg available ...
|
||||||
&& itArg->find('-') != 0) // ... and not an option flag :
|
&& itArg->find('-') != 0) // ... and not an option flag :
|
||||||
{
|
{
|
||||||
itOpt->strValue = *itArg; // We've got the value.
|
itOpt->strValue = *itArg; // We've got the value.
|
||||||
GfLogInfo(" %s %s : option '%s'\n", strFlag.c_str(),
|
GfLogInfo(" %s %s : option '%s'\n", strFlag.c_str(),
|
||||||
itArg->c_str(), itOpt->strLongName.c_str());
|
itArg->c_str(), itOpt->strLongName.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Should have a value arg, but it's not there ... error !
|
// Should have a value arg, but it's not there ... error !
|
||||||
printUsage();
|
printUsage();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GfLogInfo(" %s : option '%s'\n",
|
GfLogInfo(" %s : option '%s'\n",
|
||||||
itArg->c_str(), itOpt->strLongName.c_str());
|
itArg->c_str(), itOpt->strLongName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value or not, we've got an option, and we eat the arg(s) : done.
|
// Value or not, we've got an option, and we eat the arg(s) : done.
|
||||||
itOpt->bFound = true;
|
itOpt->bFound = true;
|
||||||
bArgEaten = true;
|
bArgEaten = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save any ignored arg in the "remaining" list.
|
// Save any ignored arg in the "remaining" list.
|
||||||
if (!bArgEaten)
|
if (!bArgEaten)
|
||||||
{
|
{
|
||||||
_vecRemArgs.push_back(*itArg);
|
_vecRemArgs.push_back(*itArg);
|
||||||
GfLogInfo(" %s : not a registered option\n", itArg->c_str());
|
GfLogInfo(" %s : not a registered option\n", itArg->c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpret the detected command line options.
|
|
||||||
const char *pszLocalDir = 0;
|
|
||||||
const char *pszLibDir = 0;
|
|
||||||
const char *pszDataDir = 0;
|
|
||||||
const char *pszBinDir = 0;
|
|
||||||
|
|
||||||
bool bTrueRandom = true;
|
// Interpret the detected command line options.
|
||||||
|
const char *pszLocalDir = 0;
|
||||||
|
const char *pszLibDir = 0;
|
||||||
|
const char *pszDataDir = 0;
|
||||||
|
const char *pszBinDir = 0;
|
||||||
|
|
||||||
std::list<Option>::const_iterator itOpt;
|
bool bTrueRandom = true;
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
|
||||||
{
|
|
||||||
// Not found in the command line => ignore / default value.
|
|
||||||
if (!itOpt->bFound)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Help about command line
|
|
||||||
if (itOpt->strLongName == "help")
|
|
||||||
{
|
|
||||||
printUsage();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Version information
|
|
||||||
else if (itOpt->strLongName == "version")
|
|
||||||
{
|
|
||||||
std::cout << _strName << ' ' << _strVersion << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Local dir (root dir of the tree where user settings files are stored)
|
|
||||||
else if (itOpt->strLongName == "localdir")
|
|
||||||
{
|
|
||||||
pszLocalDir = GfSetLocalDir(itOpt->strValue.c_str());
|
|
||||||
}
|
|
||||||
// Libraries dir (root dir of the tree where loadable modules are installed)
|
|
||||||
else if (itOpt->strLongName == "libdir")
|
|
||||||
{
|
|
||||||
pszLibDir = GfSetLibDir(itOpt->strValue.c_str());
|
|
||||||
}
|
|
||||||
// Binaries dir (the dir where the game exe and DLLs are installed)
|
|
||||||
else if (itOpt->strLongName == "bindir")
|
|
||||||
{
|
|
||||||
pszBinDir = GfSetBinDir(itOpt->strValue.c_str());
|
|
||||||
}
|
|
||||||
// Data dir (root dir of the data tree)
|
|
||||||
else if (itOpt->strLongName == "datadir")
|
|
||||||
{
|
|
||||||
pszDataDir = GfSetDataDir(itOpt->strValue.c_str());
|
|
||||||
}
|
|
||||||
// Initialize random generator or not.
|
|
||||||
else if (itOpt->strLongName == "norandom")
|
|
||||||
{
|
|
||||||
bTrueRandom = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we get here, this is normal : the derived classes might have declared
|
|
||||||
// specific options that it'll parse itself later.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any of the Speed-Dreams dirs not run-time specified / empty,
|
std::list<Option>::const_iterator itOpt;
|
||||||
// use associated compile-time variable SD_XXDIR to get default value
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
if (!(pszLocalDir && strlen(pszLocalDir)))
|
{
|
||||||
pszLocalDir = GfSetLocalDir(SD_LOCALDIR);
|
// Not found in the command line => ignore / default value.
|
||||||
if (!(pszLibDir && strlen(pszLibDir)))
|
if (!itOpt->bFound)
|
||||||
pszLibDir = GfSetLibDir(SD_LIBDIR);
|
continue;
|
||||||
if (!(pszBinDir && strlen(pszBinDir)))
|
|
||||||
pszBinDir = GfSetBinDir(SD_BINDIR);
|
|
||||||
if (!(pszDataDir && strlen(pszDataDir)))
|
|
||||||
pszDataDir = GfSetDataDir(SD_DATADIR);
|
|
||||||
|
|
||||||
// If the data dir. is not a run-time usable one, may be it's because we are running
|
// Help about command line
|
||||||
// without installing : try and use the _source_ data dir (it _is_ run-time usable).
|
if (itOpt->strLongName == "help")
|
||||||
std::string strDataDirProof(pszDataDir);
|
{
|
||||||
// A run-time usable data dir has a "config/logging.xml" file inside.
|
printUsage();
|
||||||
strDataDirProof += LOGGING_CFG;
|
return false;
|
||||||
if (pszDataDir && strlen(pszDataDir) && !GfFileExists(strDataDirProof.c_str()))
|
}
|
||||||
{
|
// Version information
|
||||||
GfLogTrace("Data dir. '%s' not run-time usable, trying source data dir.\n",
|
else if (itOpt->strLongName == "version")
|
||||||
pszDataDir);
|
{
|
||||||
pszDataDir = GfSetDataDir(SD_DATADIR_SRC);
|
std::cout << _strName << ' ' << _strVersion << std::endl;
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
// Check if ALL the Speed-dreams dirs have a usable value, and exit if not.
|
// Local dir (root dir of the tree where user settings files are stored)
|
||||||
if (!(pszLocalDir && strlen(pszLocalDir)) || !(pszLibDir && strlen(pszLibDir))
|
else if (itOpt->strLongName == "localdir")
|
||||||
|| !(pszBinDir && strlen(pszBinDir)) || !(pszDataDir && strlen(pszDataDir)))
|
{
|
||||||
{
|
pszLocalDir = GfSetLocalDir(itOpt->strValue.c_str());
|
||||||
GfLogTrace("User settings dir. : '%s'\n", GfLocalDir());
|
}
|
||||||
GfLogTrace("Libraries dir. : '%s'\n", GfLibDir());
|
// Libraries dir (root dir of the tree where loadable modules are installed)
|
||||||
GfLogTrace("Binaries dir. : '%s'\n", GfBinDir());
|
else if (itOpt->strLongName == "libdir")
|
||||||
GfLogTrace("Data dir. : '%s'\n", GfDataDir());
|
{
|
||||||
|
pszLibDir = GfSetLibDir(itOpt->strValue.c_str());
|
||||||
GfLogError("Could not start %s :"
|
}
|
||||||
" at least 1 of local/data/lib/bin dir is empty\n\n", _strName.c_str());
|
// Binaries dir (the dir where the game exe and DLLs are installed)
|
||||||
|
else if (itOpt->strLongName == "bindir")
|
||||||
return false;
|
{
|
||||||
}
|
pszBinDir = GfSetBinDir(itOpt->strValue.c_str());
|
||||||
|
}
|
||||||
|
// Data dir (root dir of the data tree)
|
||||||
|
else if (itOpt->strLongName == "datadir")
|
||||||
|
{
|
||||||
|
pszDataDir = GfSetDataDir(itOpt->strValue.c_str());
|
||||||
|
}
|
||||||
|
// Initialize random generator or not.
|
||||||
|
else if (itOpt->strLongName == "norandom")
|
||||||
|
{
|
||||||
|
bTrueRandom = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we get here, this is normal : the derived classes might have declared
|
||||||
|
// specific options that it'll parse itself later.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize random generator with "random" seed, or not (=> always same rand() sequence).
|
// If any of the Speed-Dreams dirs not run-time specified / empty,
|
||||||
if (bTrueRandom)
|
// use associated compile-time variable SD_XXDIR to get default value
|
||||||
{
|
if (!(pszLocalDir && strlen(pszLocalDir)))
|
||||||
GfLogInfo("Initializing random number generator for 'true randomness'\n");
|
pszLocalDir = GfSetLocalDir(SD_LOCALDIR);
|
||||||
srand((unsigned)time(0));
|
if (!(pszLibDir && strlen(pszLibDir)))
|
||||||
}
|
pszLibDir = GfSetLibDir(SD_LIBDIR);
|
||||||
// Note: Never calling srand is equivalent to calling it once with seed=1.
|
if (!(pszBinDir && strlen(pszBinDir)))
|
||||||
else
|
pszBinDir = GfSetBinDir(SD_BINDIR);
|
||||||
{
|
if (!(pszDataDir && strlen(pszDataDir)))
|
||||||
GfLogInfo("Not initializing random number generator, for 'repeatable randomness'\n");
|
pszDataDir = GfSetDataDir(SD_DATADIR);
|
||||||
}
|
|
||||||
|
// If the data dir. is not a run-time usable one, may be it's because we are running
|
||||||
return true;
|
// without installing : try and use the _source_ data dir (it _is_ run-time usable).
|
||||||
|
std::string strDataDirProof(pszDataDir);
|
||||||
|
// A run-time usable data dir has a "config/logging.xml" file inside.
|
||||||
|
strDataDirProof += LOGGING_CFG;
|
||||||
|
if (pszDataDir && strlen(pszDataDir) && !GfFileExists(strDataDirProof.c_str()))
|
||||||
|
{
|
||||||
|
GfLogTrace("Data dir. '%s' not run-time usable, trying source data dir.\n",
|
||||||
|
pszDataDir);
|
||||||
|
pszDataDir = GfSetDataDir(SD_DATADIR_SRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if ALL the Speed-dreams dirs have a usable value, and exit if not.
|
||||||
|
if (!(pszLocalDir && strlen(pszLocalDir)) || !(pszLibDir && strlen(pszLibDir))
|
||||||
|
|| !(pszBinDir && strlen(pszBinDir)) || !(pszDataDir && strlen(pszDataDir)))
|
||||||
|
{
|
||||||
|
GfLogTrace("User settings dir. : '%s'\n", GfLocalDir());
|
||||||
|
GfLogTrace("Libraries dir. : '%s'\n", GfLibDir());
|
||||||
|
GfLogTrace("Binaries dir. : '%s'\n", GfBinDir());
|
||||||
|
GfLogTrace("Data dir. : '%s'\n", GfDataDir());
|
||||||
|
|
||||||
|
GfLogError("Could not start %s :"
|
||||||
|
" at least 1 of local/data/lib/bin dir is empty\n\n", _strName.c_str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize random generator with "random" seed, or not (=> always same rand() sequence).
|
||||||
|
if (bTrueRandom)
|
||||||
|
{
|
||||||
|
GfLogInfo("Initializing random number generator for 'true randomness'\n");
|
||||||
|
srand((unsigned)time(0));
|
||||||
|
}
|
||||||
|
// Note: Never calling srand is equivalent to calling it once with seed=1.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GfLogInfo("Not initializing random number generator, for 'repeatable randomness'\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::registerOption(const std::string& strShortName,
|
void GfApplication::registerOption(const std::string& strShortName,
|
||||||
const std::string& strLongName,
|
const std::string& strLongName,
|
||||||
bool bHasValue)
|
bool bHasValue)
|
||||||
{
|
{
|
||||||
// Check if no already registered option has same short or long name.
|
// Check if no already registered option has same short or long name.
|
||||||
std::list<Option>::const_iterator itOpt;
|
std::list<Option>::const_iterator itOpt;
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (itOpt->strShortName == strShortName)
|
if (itOpt->strShortName == strShortName)
|
||||||
{
|
{
|
||||||
GfLogError("Can't register option -%s/--%s "
|
GfLogError("Can't register option -%s/--%s "
|
||||||
"with same short name as -%s/--%s ; ignoring.\n",
|
"with same short name as -%s/--%s ; ignoring.\n",
|
||||||
strShortName.c_str(), strLongName.c_str(),
|
strShortName.c_str(), strLongName.c_str(),
|
||||||
itOpt->strShortName.c_str(), itOpt->strLongName.c_str());
|
itOpt->strShortName.c_str(), itOpt->strLongName.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (itOpt->strLongName == strLongName)
|
else if (itOpt->strLongName == strLongName)
|
||||||
{
|
{
|
||||||
GfLogError("Can't register option -%s/--%s "
|
GfLogError("Can't register option -%s/--%s "
|
||||||
"with same long name as -%s/--%s ; ignoring.\n",
|
"with same long name as -%s/--%s ; ignoring.\n",
|
||||||
strShortName.c_str(), strLongName.c_str(),
|
strShortName.c_str(), strLongName.c_str(),
|
||||||
itOpt->strShortName.c_str(), itOpt->strLongName.c_str());
|
itOpt->strShortName.c_str(), itOpt->strLongName.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::bad_exception)
|
catch (const std::bad_exception&)
|
||||||
{
|
{
|
||||||
GfLogError("GfApplication::registerOption -%s",strShortName.c_str());
|
GfLogError("GfApplication::registerOption -%s",strShortName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All's right : register.
|
// All's right : register.
|
||||||
_lstOptions.push_back(Option(strShortName, strLongName, bHasValue));
|
_lstOptions.push_back(Option(strShortName, strLongName, bHasValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::addOptionsHelpSyntaxLine(const std::string& strTextLine)
|
void GfApplication::addOptionsHelpSyntaxLine(const std::string& strTextLine)
|
||||||
{
|
{
|
||||||
_optionsHelp.lstSyntaxLines.push_back(strTextLine);
|
_optionsHelp.lstSyntaxLines.push_back(strTextLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfApplication::addOptionsHelpExplainLine(const std::string& strTextLine)
|
void GfApplication::addOptionsHelpExplainLine(const std::string& strTextLine)
|
||||||
{
|
{
|
||||||
_optionsHelp.lstExplainLines.push_back(strTextLine);
|
_optionsHelp.lstExplainLines.push_back(strTextLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GfApplication::hasOption(const std::string& strLongName) const
|
bool GfApplication::hasOption(const std::string& strLongName) const
|
||||||
{
|
{
|
||||||
std::list<Option>::const_iterator itOpt;
|
std::list<Option>::const_iterator itOpt;
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
if (itOpt->bFound && itOpt->strLongName == strLongName)
|
if (itOpt->bFound && itOpt->strLongName == strLongName)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GfApplication::hasOption(const std::string& strLongName,
|
bool GfApplication::hasOption(const std::string& strLongName,
|
||||||
std::string& strValue) const
|
std::string& strValue) const
|
||||||
{
|
{
|
||||||
std::list<Option>::const_iterator itOpt;
|
std::list<Option>::const_iterator itOpt;
|
||||||
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
for (itOpt = _lstOptions.begin(); itOpt != _lstOptions.end(); itOpt++)
|
||||||
if (itOpt->bFound && itOpt->strLongName == strLongName)
|
if (itOpt->bFound && itOpt->strLongName == strLongName)
|
||||||
{
|
{
|
||||||
strValue = itOpt->strValue;
|
strValue = itOpt->strValue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool GfApplication::hasUnregisteredOption(const std::string& strShortName,
|
// bool GfApplication::hasUnregisteredOption(const std::string& strShortName,
|
||||||
|
@ -577,13 +577,13 @@ bool GfApplication::hasOption(const std::string& strLongName,
|
||||||
|
|
||||||
GfApplication::~GfApplication()
|
GfApplication::~GfApplication()
|
||||||
{
|
{
|
||||||
// Shutdown the gaming framework.
|
// Shutdown the gaming framework.
|
||||||
GfShutdown();
|
GfShutdown();
|
||||||
|
|
||||||
// Delete the event loop if any.
|
// Delete the event loop if any.
|
||||||
delete _pEventLoop;
|
delete _pEventLoop;
|
||||||
_pEventLoop = 0;
|
_pEventLoop = 0;
|
||||||
|
|
||||||
// Really shutdown the singleton.
|
// Really shutdown the singleton.
|
||||||
_pSelf = 0;
|
_pSelf = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue