JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwOptions.cc
Go to the documentation of this file.
1/*!
2 * \file QwOptions.cc
3 * \brief An options class which parses command line, config file and environment
4 *
5 * \author Wouter Deconinck
6 * \date 2009-12-01
7 */
8
9#if __STDC_VERSION__ < 199901L
10# if __GNUC__ >= 2
11# define __func__ __FUNCTION__
12# else
13# define __func__ "<unknown>"
14# endif
15#endif
16
17#include "QwOptions.h"
18
19// System headers
20#include <iostream>
21#include <fstream>
22#include <cstdlib>
23#include <TROOT.h>
24// Qweak headers
25#include "QwLog.h"
26#include "QwParameterFile.h"
27
28// Qweak objects with default options
29#include "QwSubsystemArray.h"
30#include "QwEventBuffer.h"
31#include "QwEPICSEvent.h"
32#ifdef __USE_DATABASE__
33#include "QwDatabase.h"
34#endif
35#include "QwRootFile.h"
36#include "QwHistogramHelper.h"
37
38// External objects
39extern const char* const gGitInfo;
40
41// Initialize the static command line arguments to zero
43
44/**
45 * The default constructor sets up the options description object with some
46 * options that should always be there. The other options can be setup
47 * wherever this object is accessible.
48 */
50 : fArgc(0), fArgv(NULL), fParsed(false)
51{
52 // No default config files
53 fConfigFiles.clear();
54
55 // Declare the default options
56 AddDefaultOptions()("usage", "print this help message");
57 AddDefaultOptions()("help,h", "print this help message");
58 AddDefaultOptions()("version,V", "print the version string");
59 AddDefaultOptions()("config,c", po::value<std::string>(), "read ONLY this config file\n(will override default config files)");
60 AddDefaultOptions()("add-config,a", po::value<std::vector<std::string> >()->composing(), "read ALSO this config file\n(will keep the default config files)");
61}
62
63/**
64 * Define standard options on the specified options object
65 * @param options Options object
66 */
68{
69 // Define logging options (Note: only QwLog takes a pointer argument!!!)
70 QwLog::DefineOptions(&options);
71
72 // Define execution options
74#ifdef __USE_DATABASE__
75 // Define database options
77#endif //__USE_DATABASE__
78 // Define ROOT file options
80 // Define EPICS event options
82 // Define subsystem array options
84 // Define histogram helper options
86}
87
88/**
89 * Destructor where we clean up locally allocated memory
90 */
92{
93 // Clean up the copy of the command line arguments
94 // Note: only the array of arguments is allocated, the arguments themselves
95 // are still owned by main.
96 if (fArgv)
97 delete[] fArgv;
98
99 // Delete the option blocks
100 for (size_t i = 0; i < fOptionBlock.size(); i++)
101 delete fOptionBlock.at(i);
102 fOptionBlock.clear();
103}
104
105/**
106 * Make a local copy of the command line arguments so they are available
107 * for later parsing.
108 * @param argc Number of arguments
109 * @param argv[] Array of arguments
110 * @param default_config_file Flag to enable default config file named by executable
111 */
112void QwOptions::SetCommandLine(int argc, char* argv[], bool default_config_file)
113{
114 // Copy command line options
115 fArgc = argc;
116 if (fArgv) delete[] fArgv;
117 fArgv = new char*[fArgc];
118 QwDebug << "Arguments:";
119 for (int i = 0; i < argc; i++) {
120 fArgv[i] = argv[i];
121 QwDebug << " " << fArgv[i];
122 }
124
125 fParsed = false;
126
127 // Add default config file based on file name
128 if (fArgc > 0 && default_config_file) {
129 std::string path = fArgv[0];
130 QwDebug << "Invocation name: " << path << QwLog::endl;
131 // Find file name from full path
132 size_t pos = path.find_last_of('/');
133 if (pos != std::string::npos)
134 // Called with path
135 AddConfigFile(path.substr(pos+1) + ".conf");
136 else
137 // Called without path
138 AddConfigFile(path + ".conf");
139 }
140}
141
142/**
143 * Set the named configuration file as the first (and initially only)
144 * one in the list.
145 * @param configfile Name of the config file, without path
146 */
147void QwOptions::SetConfigFile(const std::string& configfile)
148{
149 QwWarning << "Overriding the default configuration files with "
150 << "user-defined configuration file "
151 << configfile.c_str() << QwLog::endl;
152 fConfigFiles.clear();
153 fConfigFiles.push_back(configfile);
154 fParsed = false;
155};
156
157/**
158 * Add the named configuration file to the list.
159 * @param configfile Name of the config file, without path
160 */
161void QwOptions::AddConfigFile(const std::string& configfile)
162{
163 Bool_t notfound = kTRUE;
164 for (size_t i = 0; i < fConfigFiles.size(); i++){
165 if (fConfigFiles.at(i) == configfile){
166 notfound=kFALSE;
167 break;
168 }
169 }
170 if (notfound){
171 QwMessage << "Adding user-defined configuration file "
172 << configfile.c_str() << QwLog::endl;
173 fConfigFiles.push_back(configfile);
174 fParsed = false;
175 }
176};
177
178/**
179 * Combine the options of the various option descriptions in one object for
180 * parsing at once. This avoids having to try/catch every single option
181 * description
182 */
183po::options_description* QwOptions::CombineOptions()
184{
185 // The options can be grouped by defining a vector fOptions of
186 // options_description objects. Each entry can have a name and
187 // will show up as a separate section in the usage information.
188 po::options_description* options = new po::options_description("options");
189 for (size_t i = 0; i < fOptionBlockName.size(); i++) {
190 // Right now every parser gets access to all options
191 options->add(*fOptionBlock.at(i));
192 }
193 return options;
194}
195
196/**
197 * Parse the command line arguments for options and warn when encountering
198 * an unknown option, then notify the variables map. Print usage instructions
199 * when no options are given, or when explicitly asked for.
200 */
202{
203 // Boost versions starting with 1.33.00 allow unrecognized options to be
204 // passed through the parser.
205 try {
206 po::options_description* command_line_options = CombineOptions();
207 po::store(po::command_line_parser(fArgc, fArgv).options(*command_line_options).allow_unregistered().run(), fVariablesMap);
208 delete command_line_options;
209 } catch (std::exception const& e) {
210 QwWarning << e.what() << " while parsing command line arguments" << QwLog::endl;
211 exit(10);
212 }
213
214 // Notify of new options
215 po::notify(fVariablesMap);
216
217 // If option help/usage, print help text
218 if (fVariablesMap.count("help") || fVariablesMap.count("usage")) {
219 Usage();
220 exit(0);
221 }
222
223 // If option version, print version string
224 if (fVariablesMap.count("version")) {
225 Version();
226 exit(0);
227 }
228
229 // If a configuration file is specified, load it.
230 if (fVariablesMap.count("config") > 0) {
231 SetConfigFile(fVariablesMap["config"].as<std::string>());
232 }
233 // If a configuration file is specified, load it.
234 if (fVariablesMap.count("add-config") > 0) {
235 AddConfigFile(fVariablesMap["add-config"].as<std::vector<std::string> >());
236 }
237}
238
239/**
240 * Parse the environment variables for options and notify the variables map.
241 */
243{
244 class name_mapper {
245 public:
246 name_mapper(const std::string& prefix, const std::string& ignore)
247 : prefix(prefix),ignore(ignore) { }
248 std::string operator()(const std::string& s) {
249 string lc;
250 if (s.find(prefix) == 0) {
251 for(string::size_type n = prefix.size(); n < s.size(); ++n) {
252 lc += static_cast<char>(tolower(s[n]));
253 }
254 }
255 if (ignore.find(lc) == std::string::npos) return lc;
256 else return "";
257 }
258 private:
259 std::string prefix, ignore;
260 } qw_name_mapper("QW_", "bin fieldmap lib lookup prminput searchtree tmp");
261
262 try {
263 po::options_description* environment_options = CombineOptions();
264 po::store(po::parse_environment(*environment_options, qw_name_mapper), fVariablesMap);
265 delete environment_options;
266 } catch (std::exception const& e) {
267 QwWarning << e.what() << " while parsing environment variables" << QwLog::endl;
268 exit(10);
269 }
270 // Notify of new options
271 po::notify(fVariablesMap);
272}
273
274/**
275 * Parse the configuration file for options and warn when encountering
276 * an unknown option, then notify the variables map.
277 */
279{
280 for (size_t i = 0; i < fConfigFiles.size(); i++) {
281 QwParameterFile configfile(fConfigFiles.at(i).c_str());
282 std::stringstream configstream;
283 configstream << configfile.rdbuf();
284
285 try {
286 // Boost version after 1.35 have bool allow_unregistered = false in
287 // their signature. This allows for unknown options in the config file.
288 po::options_description* config_file_options = CombineOptions();
289 po::store(po::parse_config_file(configstream, *config_file_options, true),
291 delete config_file_options;
292 } catch (std::exception const& e) {
293 QwWarning << e.what() << " while parsing configuration file "
294 << fConfigFiles.at(i) << QwLog::endl;
295 exit(10);
296 }
297 // Notify of new options
298 po::notify(fVariablesMap);
299
300 // If a configuration file is specified, load it.
301 if (fVariablesMap.count("add-config") > 0) {
302 AddConfigFile(fVariablesMap["add-config"].as<std::vector<std::string> >());
303 }
304 }
305}
306
307
308
309/**
310 * Print usage information
311 */
313{
315 QwMessage << "Welcome to the Qweak analyzer code." << QwLog::endl;
317 for (size_t i = 0; i < fOptionBlock.size(); i++)
318 QwMessage << *(fOptionBlock.at(i)) << QwLog::endl;
319}
320
321
322/**
323 * Print version string
324 */
326{
327 TString root_version = gROOT->GetVersion();
328 root_version += ", Date : ";
329 root_version += gROOT->GetVersionDate();
330#if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0)
331 root_version += ", SVN : ";
332 root_version += gROOT->GetSvnRevision();
333 root_version += " ";
334 root_version += gROOT->GetSvnBranch();
335#else // ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0)
336 root_version += ", GIT : ";
337 root_version += gROOT->GetGitCommit();
338 root_version += " ";
339 root_version += gROOT->GetGitBranch();
340#endif
341
342 QwMessage << "\n Qweak Analysis Framework : " << fArgv[0] << QwLog::endl;
343 QwMessage << " * GIT info: " << gGitInfo << QwLog::endl;
344 // QwMessage << " * Revision: " << QWANA_SVN_REVISION << QwLog::endl;
345 // QwMessage << " * URL: " << QWANA_SVN_URL << QwLog::endl;
346 // QwMessage << " * Last Changed Rev: " << QWANA_SVN_LASTCHANGEDREVISION << QwLog::endl;
347 QwMessage << " * ROOT " << root_version << QwLog::endl;
348}
349
350
351/**
352 * Get a pair of integers specified as a colon-separated range
353 * This function uses the utility function QwParameterFile::ParseIntRange.
354 * @param key Option key
355 * @return Pair of integers
356 */
357std::pair<int,int> QwOptions::GetIntValuePair(const std::string& key)
358{
359 std::pair<int, int> mypair;
360 mypair.first = 0;
361 mypair.second = 0;
362
363 if (fParsed == false) Parse();
364 if (fVariablesMap.count(key)) {
365 std::string range = fVariablesMap[key].as<std::string>();
366 mypair = QwParameterFile::ParseIntRange(":",range);
367 }
368
369 return mypair;
370}
A class for handling connections to the Qweak database.
Helper functions and utilities for ROOT histogram management.
An options class which parses command line, config file and environment.
A logfile class, based on an identical class in the Hermes analyzer.
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Array container for managing multiple subsystems.
ROOT file and tree management wrapper classes.
Parameter file parsing and management.
EPICS data event handling and storage.
Event buffer management for reading and processing CODA data.
const char *const gGitInfo
static void DefineOptions(QwOptions &options)
Defines available class options for QwOptions.
static void DefineOptions(QwOptions &options)
Define the configuration options.
static void DefineOptions(QwOptions &options)
static void DefineOptions(QwOptions &options)
Define the configuration options.
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
static void DefineOptions(QwOptions *options)
Define available class options for QwOptions.
Definition QwLog.cc:71
Command-line and configuration file options processor.
Definition QwOptions.h:141
void ParseCommandLine()
Parse the command line arguments.
Definition QwOptions.cc:201
static void DefineOptions(QwOptions &options)
Define the options.
Definition QwOptions.cc:67
QwOptions()
Private default constructor.
Definition QwOptions.cc:49
virtual ~QwOptions()
Default destructor.
Definition QwOptions.cc:91
void ParseConfigFile()
Parse the configuration file.
Definition QwOptions.cc:278
void SetConfigFile(const std::string &configfile)
Set a configuration file.
Definition QwOptions.cc:147
static QwOptions * fInstance
Definition QwOptions.h:144
std::vector< std::string > fOptionBlockName
Definition QwOptions.h:313
char ** fArgv
Definition QwOptions.h:306
int fArgc
Command line arguments.
Definition QwOptions.h:305
std::pair< int, int > GetIntValuePair(const std::string &key)
Get a pair of integer values.
Definition QwOptions.cc:357
bool fParsed
Definition QwOptions.h:318
void SetCommandLine(int argc, char *argv[], bool default_config_file=true)
Set the command line arguments.
Definition QwOptions.cc:112
po::options_description_easy_init AddDefaultOptions()
Add a default option.
Definition QwOptions.h:165
po::options_description * CombineOptions()
Combine the various option description in one.
Definition QwOptions.cc:183
void AddConfigFile(const std::string &configfile)
Add a configuration file.
Definition QwOptions.cc:161
void Usage()
Print usage information.
Definition QwOptions.cc:312
void Parse(bool force=false)
Parse all sources of options.
Definition QwOptions.h:218
void Version()
Print version string.
Definition QwOptions.cc:325
void ParseEnvironment()
Parse the environment variables.
Definition QwOptions.cc:242
po::variables_map fVariablesMap
Definition QwOptions.h:316
std::vector< std::string > fConfigFiles
Configuration file.
Definition QwOptions.h:297
std::vector< po::options_description * > fOptionBlock
Definition QwOptions.h:312
Configuration file parser with flexible tokenization and search capabilities.
std::streambuf * rdbuf() const
Access the streambuf pointer in the same way as on a std::ifstream.
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
static void DefineOptions(QwOptions &options)
Define the configuration options.
static void DefineOptions(QwOptions &options)
Define configuration options for global array.