FACT++  1.0
Configuration.cc
Go to the documentation of this file.
1 // **************************************************************************
327 // **************************************************************************
328 #include "Configuration.h"
329 
330 #include <fstream>
331 #include <iostream>
332 #include <iomanip>
333 
334 #include <boost/filesystem.hpp>
335 
336 #ifdef HAVE_SQL
337 #include "Database.h"
338 #endif
339 
340 using namespace std;
341 
342 namespace style = boost::program_options::command_line_style;
343 
344 // --------------------------------------------------------------------------
345 //
387 //
388 #ifdef HAVE_SQL
389 po::basic_parsed_options<char>
390  Configuration::parse_database(const string &prgname, const string &database, const po::options_description& desc, bool allow_unregistered)
391 {
392  Database db(database);
393 
394  cerr << "Connected to '" << db.uri() << "' for " << prgname << endl;
395 
396  const mysqlpp::StoreQueryResult res =
397  db.query("SELECT CONCAT(fKey1,fKey2), fValue "
398  "FROM ProgramOption "
399  "WHERE fCounter=(SELECT MAX(fCounter) FROM History) "
400  "AND NOT ISNULL(fValue) "
401  "AND (fProgram='"+prgname+"' OR fProgram='*')").store();
402 
403  set<string> allowed_options;
404 
405  const vector<boost::shared_ptr<po::option_description>> &options = desc.options();
406  for (unsigned i=0; i<options.size(); ++i)
407  {
408  const po::option_description &d = *options[i];
409  if (d.long_name().empty())
410  boost::throw_exception(po::error("long name required for database"));
411 
412  allowed_options.insert(d.long_name());
413  }
414 
415  po::parsed_options result(&desc);
416 
417  for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++)
418  {
419  const string key = (*v)[0].c_str();
420  if (key.empty()) // key == > Throw exception
421  continue;
422 
423  // Check if we are allowed to accept unregistered options,
424  // i.e. options which are not in options_description &desc.
425  const bool unregistered = allowed_options.find(key)==allowed_options.end();
426  if (unregistered && allow_unregistered)
427  boost::throw_exception(po::unknown_option(key));
428 
429  // Create a key/value-pair and store whether it is a
430  // registered option of not
431  po::option n;
432  n.string_key = key;
433  // This is now identical to file parsing. What if we want
434  // to concatenate options like on the command line?
435  n.value.clear(); // Fixme: composing?
436  n.value.push_back((*v)[1].c_str());
437  //n.unregistered = unregistered;
438 
439  // If any parsing will be done in the future...
440  //n.value().original_tokens.clear();
441  //n.value().original_tokens.push_back(name);
442  //n.value().original_tokens.push_back(value);
443 
444  result.options.push_back(n);
445  }
446 
447  return result;
448 }
449 #else
450 po::basic_parsed_options<char>
451  Configuration::parse_database(const string &, const string &, const po::options_description &desc, bool)
452 {
453  return po::parsed_options(&desc);
454 }
455 #endif
456 
457 // --------------------------------------------------------------------------
458 //
460 //
461 Configuration::Configuration(const string &prgname) : fName(UnLibToolize(prgname)),
462 fNameMapper(bind1st(mem_fun(&Configuration::DefaultMapper), this)),
463 fPrintUsage(bind(&Configuration::PrintUsage, this))
464 {
465  po::options_description generic("Generic options");
466  generic.add_options()
467  ("version,V", "Print version information.")
468  ("help", "Print available commandline options.")
469  ("help-environment", "Print available environment variables.")
470  ("help-database", "Print available options retreived from the database.")
471  ("help-config", "Print available configuration file options.")
472  ("print-all", "Print all options as parsed from all the different sources.")
473  ("print", "Print options as parsed from the commandline.")
474  ("print-default", "Print options as parsed from default configuration file.")
475  ("print-database", "Print options as retrieved from the database.")
476  ("print-config", "Print options as parsed from the high priority configuration file.")
477  ("print-environment", "Print options as parsed from the environment.")
478  ("print-unknown", "Print unrecognized options.")
479  ("print-options", "Print options as passed to program.")
480  ("print-wildcards", "Print all options registered with wildcards.")
481  ("dont-check", "Do not check validity of options from files and database.")
482  ("dont-check-files", "Do not check validity of options from files.")
483  ("dont-check-database", "Do not check validity of options from database.")
484  ;
485 
486  po::options_description def_config;
487  def_config.add_options()
488  ("default", var<string>(fName+string(".rc")), "Default configuration file.")
489  ;
490 
491  po::options_description config("Configuration options");
492  config.add_options()
493  ("config,C", var<string>(), "Configuration file overwriting options retrieved from the database.")
494  ("database", var<string>(), "Database link as in\n\t[user[:password]@]server.com[:port]/database\nOverwrites options from the default configuration file.")
495  ("no-database", "Suppress any access to the database even if a database URL was set.")
496  ;
497 
498  fOptionsCommandline[kVisible].add(generic);
499  fOptionsCommandline[kVisible].add(config);
500  fOptionsCommandline[kVisible].add(def_config);
501  fOptionsConfigfile[kVisible].add(config);
502 }
503 
504 // --------------------------------------------------------------------------
505 //
507 //
508 void Configuration::PrintParsed(const po::parsed_options &parsed) const
509 {
510  const vector< po::basic_option<char> >& options = parsed.options;
511 
512  // .description -> Pointer to opt_commandline
513  // const std::vector< shared_ptr<option_description> >& options() const;
514 
515  //const std::string& key(const std::string& option) const;
516  //const std::string& long_name() const;
517  //const std::string& description() const;
518  //shared_ptr<const value_semantic> semantic() const;
519 
520  int maxlen = 0;
521  for (unsigned i=0; i<options.size(); ++i)
522  {
523  const po::basic_option<char> &opt = options[i];
524 
525  if (opt.value.size()>0 && opt.string_key[0]!='-')
526  Max(maxlen, opt.string_key.length());
527  }
528 
529  cout.setf(ios_base::left);
530 
531  // =============> Implement printing of parsed options
532  for(unsigned i=0; i<options.size(); ++i)
533  {
534  const po::basic_option<char> &opt = options[i];
535 
536  if (opt.value.size()==0 && opt.string_key[0]!='-')
537  cout << "--";
538  cout << setw(maxlen) << opt.string_key;
539  if (opt.value.size()>0)
540  cout << " = " << opt.value[0];
541 
542  //for (int j=0; j<options[i].value.size(); j++)
543  // cout << "\t = " << options[i].value[j];
544  //cout << "/" << options[i].original_tokens[0];
545 
546  ostringstream com;
547 
548  if (opt.position_key>=0)
549  com << " [position=" << opt.position_key << "]";
550  if (opt.unregistered)
551  com << " [unregistered]";
552 
553  if (!com.str().empty())
554  cout << " # " << com.str();
555 
556  cout << endl;
557  }
558 }
559 
560 template<class T>
561 string Configuration::VecAsStr(const po::variable_value &v) const
562 {
563  ostringstream str;
564 
565  const vector<T> vec = v.as<vector<T>>();
566  for (typename std::vector<T>::const_iterator s=vec.begin(); s<vec.end(); s++)
567  str << " " << *s;
568 
569  return str.str().substr(1);
570 }
571 
572 string Configuration::VarAsStr(const po::variable_value &v) const
573 {
574  if (v.value().type()==typeid(bool))
575  return v.as<bool>() ? "yes ": "no";
576 
577  if (v.value().type()==typeid(string))
578  return v.as<string>();
579 
580  if (v.value().type()==typeid(int16_t))
581  return to_string((long long int)v.as<int16_t>());
582 
583  if (v.value().type()==typeid(int32_t))
584  return to_string((long long int)v.as<int32_t>());
585 
586  if (v.value().type()==typeid(int64_t))
587  return to_string((long long int)v.as<int64_t>());
588 
589  if (v.value().type()==typeid(uint16_t))
590  return to_string((long long unsigned int)v.as<uint16_t>());
591 
592  if (v.value().type()==typeid(uint32_t))
593  return to_string((long long unsigned int)v.as<uint32_t>());
594 
595  if (v.value().type()==typeid(uint64_t))
596  return to_string((long long unsigned int)v.as<uint64_t>());
597 
598  if (v.value().type()==typeid(float))
599  return to_string((long double)v.as<float>());
600 
601  if (v.value().type()==typeid(double))
602  return to_string((long double)v.as<double>());
603 
604  if (v.value().type()==typeid(vector<string>))
605  return VecAsStr<string>(v);
606 
607  if (v.value().type()==typeid(vector<int16_t>))
608  return VecAsStr<int16_t>(v);
609 
610  if (v.value().type()==typeid(vector<int32_t>))
611  return VecAsStr<int32_t>(v);
612 
613  if (v.value().type()==typeid(vector<int64_t>))
614  return VecAsStr<int64_t>(v);
615 
616  if (v.value().type()==typeid(vector<uint16_t>))
617  return VecAsStr<uint16_t>(v);
618 
619  if (v.value().type()==typeid(vector<uint32_t>))
620  return VecAsStr<uint32_t>(v);
621 
622  if (v.value().type()==typeid(vector<uint64_t>))
623  return VecAsStr<uint64_t>(v);
624 
625  if (v.value().type()==typeid(vector<float>))
626  return VecAsStr<float>(v);
627 
628  if (v.value().type()==typeid(vector<double>))
629  return VecAsStr<double>(v);
630 
631  ostringstream str;
632  str << hex << setfill('0') << "0x";
633  if (v.value().type()==typeid(Hex<uint16_t>))
634  str << setw(4) << v.as<Hex<uint16_t>>();
635 
636  if (v.value().type()==typeid(Hex<uint32_t>))
637  str << setw(8) << v.as<Hex<uint32_t>>();
638 
639  if (v.value().type()==typeid(Hex<uint64_t>))
640  str << setw(16) << v.as<Hex<uint64_t>>();
641 
642  return str.str();
643 }
644 
645 // --------------------------------------------------------------------------
646 //
648 //
650 {
651  cout << "Options propagated to program:" << endl;
652 
653  int maxlen = 0;
654  for (map<string,po::variable_value>::const_iterator m=fVariables.begin();
655  m!=fVariables.end(); m++)
656  Max(maxlen, m->first.length());
657 
658  cout.setf(ios_base::left);
659 
660  // =============> Implement prining of options in use
661  for (map<string,po::variable_value>::const_iterator m=fVariables.begin();
662  m!=fVariables.end(); m++)
663  {
664  const po::variable_value &v = m->second;
665 
666  ostringstream str;
667 
668  if (v.value().type()==typeid(bool))
669  str << " bool";
670  if (v.value().type()==typeid(string))
671  str << " string";
672  if (v.value().type()==typeid(int16_t))
673  str << " int16_t";
674  if (v.value().type()==typeid(int32_t))
675  str << " int32_t";
676  if (v.value().type()==typeid(int64_t))
677  str << " int64_t";
678  if (v.value().type()==typeid(uint16_t))
679  str << " uint16_t";
680  if (v.value().type()==typeid(uint32_t))
681  str << " uint32_t";
682  if (v.value().type()==typeid(uint64_t))
683  str << " uint64_t";
684  if (v.value().type()==typeid(float))
685  str << " float";
686  if (v.value().type()==typeid(double))
687  str << " double";
688  if (v.value().type()==typeid(Hex<uint16_t>))
689  str << " Hex<uint16_t>";
690  if (v.value().type()==typeid(Hex<uint32_t>))
691  str << " Hex<uint32_t>";
692  if (v.value().type()==typeid(Hex<uint64_t>))
693  str << " Hex<uint64_t>";
694  if (v.value().type()==typeid(vector<string>))
695  str << " vector<string>";
696  if (v.value().type()==typeid(vector<int16_t>))
697  str << " vector<int16_t>";
698  if (v.value().type()==typeid(vector<int32_t>))
699  str << " vector<int32_t>";
700  if (v.value().type()==typeid(vector<int64_t>))
701  str << " vector<int64_t>";
702  if (v.value().type()==typeid(vector<uint16_t>))
703  str << " vector<uint16_t>";
704  if (v.value().type()==typeid(vector<uint32_t>))
705  str << " vector<uint32_t>";
706  if (v.value().type()==typeid(vector<uint64_t>))
707  str << " vector<uint64_t>";
708  if (v.value().type()==typeid(vector<float>))
709  str << " vector<float>";
710  if (v.value().type()==typeid(vector<double>))
711  str << " vector<double>";
712 
713  if (str.str().empty())
714  str << " unknown[" << v.value().type().name() << "]";
715 
716  const string var = VarAsStr(v);
717  cout << setw(maxlen) << m->first;
718  if (!var.empty())
719  cout << " = ";
720  cout << var << " #" << str.str();
721 
722  if (v.defaulted())
723  cout << " [default]";
724  if (v.empty())
725  cout << " [empty]";
726 
727  cout << endl;
728  }
729 
730  cout << endl;
731 }
732 
733 // --------------------------------------------------------------------------
734 //
736 //
737 void Configuration::PrintUnknown(const vector<string> &vec, int steps) const
738 {
739  for (vector<string>::const_iterator v=vec.begin(); v<vec.end(); v+=steps)
740  cout << " " << *v << endl;
741  cout << endl;
742 }
743 
744 multimap<string, string> Configuration::GetOptions() const
745 {
746  multimap<string,string> rc;
747 
748  for (map<string,po::variable_value>::const_iterator m=fVariables.begin();
749  m!=fVariables.end(); m++)
750  rc.insert(make_pair(m->first, VarAsStr(m->second)));
751 
752  return rc;
753 }
754 
755 // --------------------------------------------------------------------------
756 //
758 //
760 {
761  if (!fUnknownCommandline.empty())
762  {
763  cout << "Unknown commandline options:" << endl;
765  }
766 
767  if (!fUnknownConfigfile.empty())
768  {
769  cout << "Unknown options in configfile:" << endl;
771  }
772 
773  if (!fUnknownEnvironment.empty())
774  {
775  cout << "Unknown environment variables:" << endl;
777  }
778 
779  if (!fUnknownDatabase.empty())
780  {
781  cout << "Unknown database entry:" << endl;
783  }
784 }
785 
786 // --------------------------------------------------------------------------
787 //
789 //
790 void Configuration::AddOptionsCommandline(const po::options_description &cl, bool visible)
791 {
792  fOptionsCommandline[visible].add(cl);
793 }
794 
795 // --------------------------------------------------------------------------
796 //
798 //
799 void Configuration::AddOptionsConfigfile(const po::options_description &cf, bool visible)
800 {
801  fOptionsConfigfile[visible].add(cf);
802 }
803 
804 // --------------------------------------------------------------------------
805 //
807 //
808 void Configuration::AddOptionsEnvironment(const po::options_description &env, bool visible)
809 {
810  fOptionsEnvironment[visible].add(env);
811 }
812 
813 // --------------------------------------------------------------------------
814 //
816 //
817 void Configuration::AddOptionsDatabase(const po::options_description &db, bool visible)
818 {
819  fOptionsDatabase[visible].add(db);
820 }
821 
822 // --------------------------------------------------------------------------
823 //
825 //
826 void Configuration::SetArgumentPositions(const po::positional_options_description &desc)
827 {
828  fArgumentPositions = desc;
829 }
830 
831 // --------------------------------------------------------------------------
832 //
834 //
835 void Configuration::SetNameMapper(const function<string(string)> &func)
836 {
837  fNameMapper = func;
838 }
839 
841 {
842  fNameMapper = bind1st(mem_fun(&Configuration::DefaultMapper), this);
843 }
844 
845 void Configuration::SetPrintUsage(const function<void(void)> &func)
846 {
847  fPrintUsage = func;
848 }
849 
851 {
852  fPrintUsage = bind(&Configuration::PrintUsage, this);
853 }
854 
855 void Configuration::SetPrintVersion(const function<void(const string&)> &func)
856 {
857  fPrintVersion = func;
858 }
859 
861 {
862  fPrintVersion = function<void(const string&)>();
863 }
864 
865 // --------------------------------------------------------------------------
866 //
946 //
947 const po::variables_map &Configuration::Parse(int argc, const char **argv, const std::function<void()> &PrintHelp)
948 {
949  const po::positional_options_description &opt_positional = fArgumentPositions;
950 
951  // ------------------------ (0) --------------------------
952 #ifdef DEBUG
953  cout << "--0--" << endl;
954 #endif
955 
956  po::options_description opt_commandline;
957  po::options_description opt_configfile;
958  po::options_description opt_environment;
959  po::options_description opt_database;
960 
961  for (int i=0; i<2; i++)
962  {
963  opt_commandline.add(fOptionsCommandline[i]);
964  opt_configfile.add(fOptionsConfigfile[i]);
965  opt_environment.add(fOptionsEnvironment[i]);
966  opt_database.add(fOptionsDatabase[i]);
967  }
968 
969  // ------------------------ (1) --------------------------
970 #ifdef DEBUG
971  cout << "--1--" << endl;
972 #endif
973 
974  fPriorityFile = "";
975  fDefaultFile = "";
976  fDatabase = "";
977 
978  // ------------------------ (2) --------------------------
979 #ifdef DEBUG
980  cout << "--2--" << endl;
981 #endif
982 
983  po::command_line_parser parser(argc, const_cast<char**>(argv));
984  parser.options(opt_commandline);
985  parser.positional(opt_positional);
986  parser.style(style::unix_style&~style::allow_guessing);
987  //parser.allow_unregistered();
988 
989  const po::parsed_options parsed_commandline = parser.run();
990 
991  // ------------------------ (3) --------------------------
992 #ifdef DEBUG
993  cout << "--3--" << endl;
994 #endif
995 
996  po::variables_map getfiles;
997  po::store(parsed_commandline, getfiles);
998 
999  if (getfiles.count("version"))
1000  PrintVersion();
1001  if (getfiles.count("help"))
1002  {
1003  fPrintUsage();
1004  cout <<
1005  "Options:\n"
1006  "The following describes the available commandline options. "
1007  "For further details on how command line option are parsed "
1008  "and in which order which configuration sources are accessed "
1009  "please refer to the class reference of the Configuration class." << endl;
1010  cout << fOptionsCommandline[kVisible] << endl;
1011  }
1012  if (getfiles.count("help-config"))
1013  cout << fOptionsConfigfile[kVisible] << endl;
1014  if (getfiles.count("help-env"))
1015  cout << fOptionsEnvironment[kVisible] << endl;
1016  if (getfiles.count("help-database"))
1017  cout << fOptionsDatabase[kVisible] << endl;
1018 
1019 
1020 
1021  // ------------------------ (4) --------------------------
1022 #ifdef DEBUG
1023  cout << "--4--" << endl;
1024 #endif
1025 
1026  if (getfiles.count("print") || getfiles.count("print-all"))
1027  {
1028  cout << endl << "Parsed commandline options:" << endl;
1029  PrintParsed(parsed_commandline);
1030  cout << endl;
1031  }
1032 
1033  if (getfiles.count("help") || getfiles.count("help-config") ||
1034  getfiles.count("help-env") || getfiles.count("help-database"))
1035  {
1036  if (PrintHelp)
1037  PrintHelp();
1038  }
1039 
1040  // ------------------------ (5) --------------------------
1041 #ifdef DEBUG
1042  cout << "--5--" << endl;
1043 #endif
1044 
1045  const boost::filesystem::path path(GetName());
1046  const string globalfile = (path.parent_path()/boost::filesystem::path("fact++.rc")).string();
1047 
1048  cerr << "Reading global options from '" << globalfile << "'." << endl;
1049 
1050  ifstream gfile(globalfile.c_str());
1051  // ===> FIXME: Proper handling of missing file or wrong file name
1052  const po::parsed_options parsed_globalfile =
1053  !gfile ?
1054  po::parsed_options(&opt_configfile) :
1055  po::parse_config_file<char>(gfile, opt_configfile, true);
1056 
1057  // ------------------------ (6) --------------------------
1058 #ifdef DEBUG
1059  cout << "--6--" << endl;
1060 #endif
1061 
1062  // Get default file from command line
1063  if (getfiles.count("default"))
1064  {
1065  fDefaultFile = getfiles["default"].as<string>();
1066  cerr << "Reading default options from '" << fDefaultFile << "'." << endl;
1067  }
1068 
1069  const bool checkf = !getfiles.count("dont-check-files") && !getfiles.count("dont-check");
1070  const bool defaulted = getfiles.count("default") && getfiles["default"].defaulted();
1071  //const bool exists = boost::filesystem::exists(fDefaultFile);
1072 
1073  ifstream indef(fDefaultFile.c_str());
1074  // ===> FIXME: Proper handling of missing file or wrong file name
1075  const po::parsed_options parsed_defaultfile =
1076  !indef && defaulted ?
1077  po::parsed_options(&opt_configfile) :
1078  po::parse_config_file<char>(indef, opt_configfile, !checkf);
1079 
1080  // ------------------------ (7) --------------------------
1081 #ifdef DEBUG
1082  cout << "--7--" << endl;
1083 #endif
1084 
1085  if (getfiles.count("print-default") || getfiles.count("print-all"))
1086  {
1087  if (!indef.is_open() && defaulted)
1088  cout << "No configuration file by --default option specified." << endl;
1089  else
1090  {
1091  cout << endl << "Parsed options from '" << fDefaultFile << "':" << endl;
1092  PrintParsed(parsed_defaultfile);
1093  cout << endl;
1094  }
1095  }
1096 
1097  po::store(parsed_defaultfile, getfiles);
1098 
1099  // ------------------------ (8) --------------------------
1100 #ifdef DEBUG
1101  cout << "--8--" << endl;
1102 #endif
1103 
1104  // Get priority from commandline(1), defaultfile(2)
1105  if (getfiles.count("config"))
1106  {
1107  fPriorityFile = getfiles["config"].as<string>();
1108  cerr << "Reading config options from '" << fPriorityFile << "'." << endl;
1109  }
1110 
1111  ifstream inpri(fPriorityFile.c_str());
1112  // ===> FIXME: Proper handling of missing file or wrong file name
1113  const po::parsed_options parsed_priorityfile =
1114  fPriorityFile.empty() ? po::parsed_options(&opt_configfile) :
1115  po::parse_config_file<char>(inpri, opt_configfile, !checkf);
1116 
1117  // ------------------------ (9) --------------------------
1118 #ifdef DEBUG
1119  cout << "--9--" << endl;
1120 #endif
1121 
1122  if (getfiles.count("print-config") || getfiles.count("print-all"))
1123  {
1124  if (fPriorityFile.empty())
1125  cout << "No configuration file by --config option specified." << endl;
1126  else
1127  {
1128  cout << endl << "Parsed options from '" << fPriorityFile << "':" << endl;
1129  PrintParsed(parsed_priorityfile);
1130  cout << endl;
1131  }
1132  }
1133 
1134  // ------------------------ (10) -------------------------
1135 #ifdef DEBUG
1136  cout << "--10--" << endl;
1137 #endif
1138 
1139  po::variables_map getdatabase;
1140  po::store(parsed_commandline, getdatabase);
1141  po::store(parsed_priorityfile, getdatabase);
1142  po::store(parsed_defaultfile, getdatabase);
1143  po::store(parsed_globalfile, getdatabase);
1144 
1145  if (getdatabase.count("database") && !getdatabase.count("no-database"))
1146  {
1147  fDatabase = getdatabase["database"].as<string>();
1148  cerr << "Requesting options from database for '" << fName << "'" << endl;
1149  }
1150 
1151  const bool checkdb = !getdatabase.count("dont-check-database") && !getdatabase.count("dont-check");
1152 
1153  const po::parsed_options parsed_database =
1154  fDatabase.empty() ? po::parsed_options(&opt_database) :
1155 #if BOOST_VERSION < 104600
1156  parse_database(path.filename(), fDatabase, opt_database, !checkdb);
1157 #else
1158  parse_database(path.filename().string(), fDatabase, opt_database, !checkdb);
1159 #endif
1160  // ------------------------ (11) -------------------------
1161 #ifdef DEBUG
1162  cout << "--11--" << endl;
1163 #endif
1164 
1165  if (getfiles.count("print-database") || getfiles.count("print-all"))
1166  {
1167  if (fDatabase.empty())
1168  cout << "No database access requested." << endl;
1169  else
1170  {
1171  cout << endl << "Options received from '" << fDatabase << "':" << endl;
1172  PrintParsed(parsed_database);
1173  cout << endl;
1174  }
1175  }
1176 
1177  // ------------------------ (12) -------------------------
1178 #ifdef DEBUG
1179  cout << "--12--" << endl;
1180 #endif
1181 
1182  const po::parsed_options parsed_environment = po::parse_environment(opt_environment, fNameMapper);
1183 
1184  // ------------------------ (13) -------------------------
1185 #ifdef DEBUG
1186  cout << "--13--" << endl;
1187 #endif
1188 
1189  if (getfiles.count("print-environment"))
1190  {
1191  cout << "Parsed options from environment:" << endl;
1192  PrintParsed(parsed_environment);
1193  cout << endl;
1194  }
1195 
1196  // ------------------------ (14) -------------------------
1197 #ifdef DEBUG
1198  cout << "--14--" << endl;
1199 #endif
1200 
1201  po::variables_map result;
1202  po::store(parsed_commandline, result);
1203  po::store(parsed_priorityfile, result);
1204  po::store(parsed_database, result);
1205  po::store(parsed_defaultfile, result);
1206  po::store(parsed_globalfile, result);
1207  po::store(parsed_environment, result);
1208  po::notify(result);
1209 
1210  fVariables = result;
1211 
1212  // ------------------------ (15) -------------------------
1213 #ifdef DEBUG
1214  cout << "--15--" << endl;
1215 #endif
1216 
1217  const vector<string> unknown0 = collect_unrecognized(parsed_globalfile.options, po::exclude_positional);
1218  const vector<string> unknown1 = collect_unrecognized(parsed_defaultfile.options, po::exclude_positional);
1219  const vector<string> unknown2 = collect_unrecognized(parsed_priorityfile.options, po::exclude_positional);
1220 
1221  fUnknownConfigfile.clear();
1222  fUnknownConfigfile.insert(fUnknownConfigfile.end(), unknown0.begin(), unknown0.end());
1223  fUnknownConfigfile.insert(fUnknownConfigfile.end(), unknown1.begin(), unknown1.end());
1224  fUnknownConfigfile.insert(fUnknownConfigfile.end(), unknown2.begin(), unknown2.end());
1225 
1226  fUnknownCommandline = collect_unrecognized(parsed_commandline.options, po::exclude_positional);
1227  fUnknownEnvironment = collect_unrecognized(parsed_environment.options, po::exclude_positional);
1228  fUnknownDatabase = collect_unrecognized(parsed_database.options, po::exclude_positional);
1229 
1230  // ------------------------ (16) -------------------------
1231 #ifdef DEBUG
1232  cout << "--16--" << endl;
1233 #endif
1234 
1236 
1237  // ------------------------ (17) -------------------------
1238 #ifdef DEBUG
1239  cout << "--17--" << endl;
1240 #endif
1241 
1242  if (result.count("print-options"))
1243  PrintOptions();
1244 
1245  if (result.count("print-wildcards"))
1247 
1248  if (result.count("print-unknown"))
1249  PrintUnknown();
1250 
1251 #ifdef DEBUG
1252  cout << "------" << endl;
1253 #endif
1254 
1255  return fVariables;
1256 }
1257 
1258 bool Configuration::DoParse(int argc, const char **argv, const std::function<void()> &PrintHelp)
1259 {
1260  try
1261  {
1262  Parse(argc, argv, PrintHelp);
1263  }
1264 #if BOOST_VERSION > 104000
1265  catch (po::multiple_occurrences &e)
1266  {
1267  cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
1268  return false;
1269  }
1270 #endif
1271  catch (exception& e)
1272  {
1273  cerr << "Program options invalid due to: " << e.what() << endl;
1274  return false;
1275  }
1276 
1277  return !HasVersion() && !HasPrint() && !HasHelp();
1278 }
1279 
1280 // --------------------------------------------------------------------------
1281 //
1285 {
1286  po::options_description opts;
1287 
1288  for (int i=0; i<2; i++)
1289  {
1290  opts.add(fOptionsCommandline[i]);
1291  opts.add(fOptionsConfigfile[i]);
1292  opts.add(fOptionsEnvironment[i]);
1293  opts.add(fOptionsDatabase[i]);
1294  }
1295 
1296  fWildcardOptions.clear();
1297 
1298  typedef map<string,po::variable_value> Vars;
1299  typedef vector<boost::shared_ptr<po::option_description>> Descs;
1300 
1301  const Descs &desc = opts.options();
1302 
1303  for (Vars::const_iterator io=fVariables.begin(); io!=fVariables.end(); io++)
1304  {
1305  for (Descs::const_iterator id=desc.begin(); id!=desc.end(); id++)
1306 #if BOOST_VERSION > 104000
1307  if ((*id)->match(io->first, false, false, false)==po::option_description::approximate_match)
1308 #else
1309  if ((*id)->match(io->first, false)==po::option_description::approximate_match)
1310 #endif
1311  fWildcardOptions[io->first] = (*id)->long_name();
1312  }
1313 }
1314 
1315 // --------------------------------------------------------------------------
1316 //
1321 {
1322  cout << "Options registered with wildcards and not yet accessed:" << endl;
1323 
1324  size_t max = 0;
1325  for (auto it=fWildcardOptions.begin(); it!=fWildcardOptions.end(); it++)
1326  if (it->second.length()>max)
1327  max = it->second.length();
1328 
1329  cout.setf(ios_base::left);
1330  for (auto it=fWildcardOptions.begin(); it!=fWildcardOptions.end(); it++)
1331  cout << setw(max+1) << it->second << " : " << it->first <<endl;
1332 }
1333 
1334 const vector<string> Configuration::GetWildcardOptions(const std::string &opt) const
1335 {
1336  vector<string> rc;
1337 
1338  for (auto it=fWildcardOptions.begin(); it!=fWildcardOptions.end(); it++)
1339  {
1340  if (it->second == opt)
1341  rc.push_back(it->first);
1342  }
1343 
1344  return rc;
1345 }
1346 
1347 // --------------------------------------------------------------------------
1348 //
1356 string Configuration::UnLibToolize(const string &src) const
1357 {
1358  const boost::filesystem::path path(src);
1359 
1360  string pname = path.parent_path().string();
1361 #if BOOST_VERSION < 104600
1362  string fname = path.filename();
1363 #else
1364  string fname = path.filename().string();
1365 #endif
1366 
1367  // If the filename starts with "lt-" remove it from the name
1368  if (fname.substr(0, 3)=="lt-")
1369  fname = fname.substr(3);
1370 
1371  string pwd;
1372  // If no directory is contained determine the current directory
1373  if (pname.empty())
1374  pname = boost::filesystem::current_path().string();
1375 
1376  // If the directory is relative and just ".libs" forget about it
1377  if (pname==".libs")
1378  return fname;
1379 
1380 
1381  // Check if the directory is long enough to contain "/.libs"
1382  if (pname.length()>=6)
1383  {
1384  // If the directory ends with "/.libs", remove it
1385  const size_t pos = pname.length()-6;
1386  if (pname.substr(pos)=="/.libs")
1387  pname = pname.substr(0, pos);
1388  }
1389 
1390  // If the path is the local path do not return the path-name
1391  if (pname==boost::filesystem::current_path().string())
1392  return fname;
1393 
1394  return pname+'/'+fname;
1395 }
1396 
1397 // --------------------------------------------------------------------------
1398 //
1436 {
1437 #ifndef PACKAGE_STRING
1438 #define PACKAGE_STRING ""
1439 #endif
1440 
1441 #ifndef PACKAGE_URL
1442 #define PACKAGE_URL ""
1443 #endif
1444 
1445 #ifndef PACKAGE_BUGREPORT
1446 #define PACKAGE_BUGREPORT ""
1447 #endif
1448 
1449  if (fPrintVersion)
1450  {
1452  return;
1453  }
1454 
1455 #if BOOST_VERSION < 104600
1456  const std::string n = boost::filesystem::path(fName).filename();
1457 #else
1458  const std::string n = boost::filesystem::path(fName).filename().string();
1459 #endif
1460 
1461  const string name = PACKAGE_STRING;
1462  const string bugs = PACKAGE_BUGREPORT;
1463  const string url = PACKAGE_URL;
1464 
1465  cout << n;
1466  if (!name.empty())
1467  cout << " - " << name;
1468  cout <<
1469  "\n\n"
1470  "Written by Thomas Bretz et al.\n"
1471  "\n";
1472  if (!bugs.empty())
1473  cout << "Report bugs to <" << bugs << ">\n";
1474  if (!url.empty())
1475  cout << "Home page: " << url << "\n";
1476  cout <<
1477  "\n"
1478  "Copyright (C) 2011 by the FACT Collaboration.\n"
1479  "This is free software; see the source for copying conditions.\n"
1480  << std::endl;
1481 }
#define PACKAGE_BUGREPORT
#define PACKAGE_STRING
void PrintWildcardOptions() const
void AddOptionsEnvironment(const po::options_description &env, bool visible=true)
std::string fDatabase
File name of the default configuration file (usually {program}.rc)
Definition: Configuration.h:39
std::string fPriorityFile
Options which were registered using wildcards.
Definition: Configuration.h:37
Configuration(const std::string &prgname="")
int i
Definition: db_dim_client.c:21
void PrintUsage()
Definition: fact.cc:19
std::string VecAsStr(const po::variable_value &v) const
char str[80]
Definition: test_client.c:7
std::vector< std::string > fUnknownDatabase
Storage container for unrecognized options from the environment.
Definition: Configuration.h:33
void AddOptionsConfigfile(const po::options_description &cf, bool visible=true)
po::options_description fOptionsEnvironment[2]
Description of options from the database.
Definition: Configuration.h:26
po::typed_value< T > * var(T *ptr=0)
STL namespace.
void CreateWildcardOptions()
Helper for Parse to create list of used wildcard options.
void PrintHelp()
Definition: fact.cc:30
void SetNameMapper()
void SetArgumentPositions(const po::positional_options_description &desc)
std::function< std::string(std::string)> fNameMapper
Pointer to the mapper function for environment variables.
Definition: Configuration.h:50
Index for options visible in PrintParsed.
Definition: Configuration.h:16
po::positional_options_description fArgumentPositions
Description of options from the environment.
Definition: Configuration.h:28
std::multimap< std::string, std::string > GetOptions() const
po::options_description fOptionsDatabase[2]
Description of the options in the configuration file.
Definition: Configuration.h:25
void PrintParsed(const po::parsed_options &parsed) const
Print all options from a list of already parsed options.
void SetPrintUsage()
void AddOptionsDatabase(const po::options_description &db, bool visible=true)
std::function< void(const std::string &)> fPrintVersion
Definition: Configuration.h:52
void PrintUnknown() const
void PrintOptions() const
std::string fDefaultFile
File name of the priority configuration file (overwrites option from the databse) ...
Definition: Configuration.h:38
#define PACKAGE_URL
void AddOptionsCommandline(const po::options_description &cl, bool visible=true)
po::options_description fOptionsCommandline[2]
Definition: Configuration.h:23
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
std::map< std::string, std::string > fWildcardOptions
Storage container for unrecognized options retrieved from the database.
Definition: Configuration.h:35
const std::string fName
Definition: Configuration.h:19
po::options_description fOptionsConfigfile[2]
Description of the command-line options.
Definition: Configuration.h:24
std::vector< std::string > fUnknownCommandline
Description of positional command-line options (arguments)
Definition: Configuration.h:30
std::function< void()> fPrintUsage
Definition: Configuration.h:51
std::string VarAsStr(const po::variable_value &v) const
static po::basic_parsed_options< char > parse_database(const std::string &prgname, const std::string &database, const po::options_description &desc, bool allow_unregistered=false)
Retrieve data from a database and return them as options.
static void Max(int &val, const int &comp)
Helper function which return the max of the two arguments in the first argument.
Definition: Configuration.h:55
if(extraDns) new Dns
const std::map< std::string, std::string > & GetWildcardOptions() const
po::variables_map fVariables
URL for database connection (see Configuration::parse_database)
Definition: Configuration.h:41
std::string DefaultMapper(const std::string env)
Variables as compiled by the Parse-function, which will be passed to the program. ...
Definition: Configuration.h:44
virtual void PrintVersion() const
std::string UnLibToolize(const std::string &src) const
const po::variables_map & Parse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
virtual void PrintUsage() const
Definition: Configuration.h:74
std::vector< std::string > fUnknownConfigfile
Storage container for unrecognized commandline options.
Definition: Configuration.h:31
std::vector< std::string > fUnknownEnvironment
Storage container for unrecognized options from configuration files.
Definition: Configuration.h:32
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
const std::string & GetName() const
void SetPrintVersion()