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:
torcs-ng 2020-04-19 23:22:42 +00:00
parent ffeb2061a1
commit 7ae1fa574e

View file

@ -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;
} }