]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/options.cxx
Merge branch 'merge-requests/1555' into next
[flightgear.git] / src / Main / options.cxx
index 62677a5fda0452fba7f7bc77b6a1f13536bcd4b0..00624af535cd206475f5b9b1fe15758da7067585 100644 (file)
@@ -80,6 +80,7 @@ using std::cout;
 using std::cerr;
 using std::endl;
 using std::vector;
+using std::cin;
 
 #define NEW_DEFAULT_MODEL_HZ 120
 
@@ -1491,7 +1492,7 @@ struct OptionDesc {
     {"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
@@ -1560,6 +1561,10 @@ public:
   {
     OptionValueVec::const_iterator it = values.begin();
     for (; it != values.end(); ++it) {
+      if (!it->desc) {
+        continue; // ignore markers
+      }
+      
       if (it->desc->option == key) {
         return it;
       }
@@ -1580,6 +1585,10 @@ public:
   
   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 );
@@ -1647,10 +1656,36 @@ public:
     
     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;
@@ -1710,6 +1745,7 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
       p->propertyFiles.push_back(f);
     }
   } // of arguments iteration
+  p->insertGroupMarker(); // command line is one group
   
 // then config files
   SGPath config;
@@ -1850,6 +1886,7 @@ void Options::readConfig(const SGPath& path)
     in >> skipcomment;
   }
 
+  p->insertGroupMarker(); // each config file is a group
 }
   
 int Options::parseOption(const string& s)
@@ -1898,6 +1935,7 @@ int Options::addOption(const string &key, const string &value)
 {
   OptionDesc* desc = p->findOption(key);
   if (!desc) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "unknown option:" << key);
     return FG_OPTIONS_ERROR;
   }
   
@@ -1934,6 +1972,10 @@ string_list Options::valuesForOption(const std::string& key) const
   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);
     }
@@ -1951,12 +1993,26 @@ void Options::processOptions()
     exit(0);
   }
   
-  BOOST_FOREACH(const OptionValue& v, p->values) {
-    int result = p->processOption(v.desc, v.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) {
@@ -2134,8 +2190,8 @@ void Options::showUsage() const
     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
 }