using std::cerr;
using std::endl;
using std::vector;
+using std::cin;
#define NEW_DEFAULT_MODEL_HZ 120
static int
fgOptLogLevel( const char *arg )
{
- fgSetString("/sim/logging/classes", "all");
fgSetString("/sim/logging/priority", arg);
-
- string priority = arg;
- logbuf::set_log_classes(SG_ALL);
- if (priority == "bulk") {
- logbuf::set_log_priority(SG_BULK);
- } else if (priority == "debug") {
- logbuf::set_log_priority(SG_DEBUG);
- } else if (priority == "info") {
- logbuf::set_log_priority(SG_INFO);
- } else if (priority == "warn") {
- logbuf::set_log_priority(SG_WARN);
- } else if (priority == "alert") {
- logbuf::set_log_priority(SG_ALERT);
- } else {
- SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
- }
- SG_LOG(SG_GENERAL, SG_DEBUG, "Logging priority is " << priority);
+ setLoggingPriority(arg);
return FG_OPTIONS_OK;
}
+static int
+fgOptLogClasses( const char *arg )
+{
+ fgSetString("/sim/logging/classes", arg);
+ setLoggingClasses (arg);
+
+ return FG_OPTIONS_OK;
+}
static int
fgOptTraceWrite( const char *arg )
{"hud-tris", false, OPTION_STRING, "/sim/hud/frame-stat-type", false, "tris", 0 },
{"hud-culled", false, OPTION_STRING, "/sim/hud/frame-stat-type", false, "culled", 0 },
{"atcsim", true, OPTION_CHANNEL, "", false, "dummy", 0 },
- {"atlas", true, OPTION_CHANNEL, "", false, "", 0 },
+ {"atlas", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
{"httpd", true, OPTION_CHANNEL, "", false, "", 0 },
#ifdef FG_JPEG_SERVER
{"jpg-httpd", true, OPTION_CHANNEL, "", false, "", 0 },
{"jsclient", true, OPTION_CHANNEL, "", false, "", 0 },
{"proxy", true, OPTION_FUNC, "", false, "", fgSetupProxy },
{"callsign", true, OPTION_FUNC, "", false, "", fgOptCallSign},
- {"multiplay", true, OPTION_CHANNEL, "", false, "", 0 },
+ {"multiplay", true, OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
#ifdef FG_HAVE_HLA
{"hla", true, OPTION_CHANNEL, "", false, "", 0 },
#endif
{"trace-read", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptTraceRead },
{"trace-write", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptTraceWrite },
{"log-level", true, OPTION_FUNC, "", false, "", fgOptLogLevel },
+ {"log-class", true, OPTION_FUNC, "", false, "", fgOptLogClasses },
{"view-offset", true, OPTION_FUNC | OPTION_MULTI, "", false, "", fgOptViewOffset },
{"visibility", true, OPTION_FUNC, "", false, "", fgOptVisibilityMeters },
{"visibility-miles", true, OPTION_FUNC, "", false, "", fgOptVisibilityMiles },
{
OptionValueVec::const_iterator it = values.begin();
for (; it != values.end(); ++it) {
+ if (!it->desc) {
+ continue; // ignore markers
+ }
+
if (it->desc->option == key) {
return it;
}
int processOption(OptionDesc* desc, const string& arg_value)
{
+ if (!desc) {
+ return FG_OPTIONS_OK; // tolerate marker options
+ }
+
switch ( desc->type & 0xffff ) {
case OPTION_BOOL:
fgSetBool( desc->property, desc->b_param );
return FG_OPTIONS_OK;
}
+
+ /**
+ * insert a marker value into the values vector. This is necessary
+ * when processing options, to ensure the correct ordering, where we scan
+ * for marker values in reverse, and then forwards within each group.
+ */
+ void insertGroupMarker()
+ {
+ values.push_back(OptionValue(NULL, "-"));
+ }
+
+ /**
+ * given a current iterator into the values, find the preceeding group marker,
+ * or return the beginning of the value vector.
+ */
+ OptionValueVec::const_iterator rfindGroup(OptionValueVec::const_iterator pos) const
+ {
+ while (--pos != values.begin()) {
+ if (pos->desc == NULL) {
+ return pos; // found a marker, we're done
+ }
+ }
+
+ return pos;
+ }
bool showHelp,
verbose,
showAircraft;
+
OptionDescDict options;
OptionValueVec values;
simgear::PathList propertyFiles;
p->propertyFiles.push_back(f);
}
} // of arguments iteration
+ p->insertGroupMarker(); // command line is one group
// then config files
SGPath config;
in >> skipcomment;
}
+ p->insertGroupMarker(); // each config file is a group
}
int Options::parseOption(const string& s)
{
OptionDesc* desc = p->findOption(key);
if (!desc) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "unknown option:" << key);
return FG_OPTIONS_ERROR;
}
string_list result;
OptionValueVec::const_iterator it = p->values.begin();
for (; it != p->values.end(); ++it) {
+ if (!it->desc) {
+ continue; // ignore marker values
+ }
+
if (it->desc->option == key) {
result.push_back(it->value);
}
exit(0);
}
- // proces options in LIFO order, so earlier (first in) options are processed
- // after, and hence override, later specified options.
- OptionValueVec::const_reverse_iterator it = p->values.rbegin();
- for (; it != p->values.rend(); ++it) {
- int result = p->processOption(it->desc, it->value);
- if (result == FG_OPTIONS_ERROR) {
- showUsage();
- exit(-1);
+ // processing order is complicated. We must process groups LIFO, but the
+ // values *within* each group in FIFO order, to retain consistency with
+ // older versions of FG, and existing user configs.
+ // in practice this means system.fgfsrc must be *processed* before
+ // .fgfsrc, which must be processed before the command line args, and so on.
+ OptionValueVec::const_iterator groupEnd = p->values.end();
+
+ while (groupEnd != p->values.begin()) {
+ OptionValueVec::const_iterator groupBegin = p->rfindGroup(groupEnd);
+ // run over the group in FIFO order
+ OptionValueVec::const_iterator it;
+ for (it = groupBegin; it != groupEnd; ++it) {
+ int result = p->processOption(it->desc, it->value);
+ if (result == FG_OPTIONS_ERROR) {
+ showUsage();
+ exit(-1);
+ }
}
+
+ groupEnd = groupBegin;
}
-
+
BOOST_FOREACH(const SGPath& file, p->propertyFiles) {
if (!file.exists()) {
SG_LOG(SG_GENERAL, SG_ALERT, "config file not found:" << file.str());
cout << "For a complete list of options use --help --verbose" << endl;
}
#ifdef _MSC_VER
- cout << "Hit a key to continue..." << endl;
- cin.get();
+ std::cout << "Hit a key to continue..." << std::endl;
+ std::cin.get();
#endif
}