/* =====================================================================================
* Copyright (c) 2011, Jonas Maaskola
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* =====================================================================================
*
* Filename: main.cpp
*
* Description: Executable for the HMM package
*
* Created: Thu Aug 4 22:12:31 2011 +0200
*
* Author: Jonas Maaskola
*
* =====================================================================================
*/
#include "cli.hpp"
#include "log.hpp"
#include
#include
#include
#include "terminal.hpp"
using namespace std;
namespace po = boost::program_options;
const std::string default_error_msg
= "Please inspect the command line help with -h or --help.";
po::options_description gen_generic_options(string &config_path, size_t cols) {
po::options_description generic_options("Generic options", cols);
generic_options.add_options()
("config", po::value(&config_path), "Read options from a configuration file. ")
("help,h", "Produce help message. Combine with -v or -V for additional commands.")
("version", "Print out the version. Also show git SHA1 with -v.")
("verbose,v", "Be verbose about the progress.")
("noisy,V", "Be very verbose about the progress.")
;
return generic_options;
}
int process_cli_options(
int argc, const char **argv, ExecutionInformation &exec_info,
const std::string &usage_string,
boost::program_options::options_description &cli_options,
bool use_positional_options,
boost::program_options::positional_options_description
&positional_options) {
namespace po = boost::program_options;
exec_info = ExecutionInformation(argv[0], GIT_DESCRIPTION, GIT_BRANCH,
BUILD_TYPE, argc, argv);
const size_t MIN_COLS = 60;
const size_t MAX_COLS = 80;
size_t cols = get_terminal_width();
if (cols < MIN_COLS)
cols = MIN_COLS;
if (cols > MAX_COLS)
cols = MAX_COLS;
po::variables_map vm;
try {
if (not use_positional_options)
po::store(po::command_line_parser(argc, argv).options(cli_options).run(),
vm);
else
po::store(po::command_line_parser(argc, argv)
.options(cli_options)
.positional(positional_options)
.run(),
vm);
} catch (po::unknown_option &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Option " << e.get_option_name() << " not known.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::ambiguous_option &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Option " << e.get_option_name() << " is ambiguous.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::multiple_values &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Option " << e.get_option_name() << " was specified multiple times.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::multiple_occurrences &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Option " << e.get_option_name() << " was specified multiple times.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::invalid_option_value &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "The value specified for option " << e.get_option_name()
<< " has an invalid format.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::too_many_positional_options_error &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Too many positional options were specified.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::invalid_command_line_syntax &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Invalid command line syntax.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::invalid_command_line_style &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "There is a programming error related to command line style.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::reading_file &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "The config file can not be read.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::validation_error &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "Validation of option " << e.get_option_name() << " failed.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::error &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "No further information as to the nature of this error is "
"available, please check your command line arguments.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (std::exception &e) {
LOG(fatal) << "An error occurred while parsing command line options.";
LOG(fatal) << e.what();
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
}
if (vm.count("verbose"))
verbosity = Verbosity::verbose;
if (vm.count("noisy"))
verbosity = Verbosity::debug;
if (vm.count("version") and not vm.count("help")) {
std::cout << exec_info.name_and_version() << std::endl;
if (verbosity >= Verbosity::verbose)
std::cout << GIT_SHA1 << std::endl;
return EXIT_SUCCESS;
}
if (vm.count("help")) {
std::cout << exec_info.program_name << " " << exec_info.program_version
<< std::endl;
std::cout
<< "Copyright (C) 2015 Jonas Maaskola\n"
"Provided under GNU General Public License Version 3 or later.\n"
"See the file COPYING provided with this software for details of "
"the license.\n"
<< std::endl;
std::cout << usage_string << std::endl << std::endl;
std::cout << cli_options << std::endl;
return EXIT_SUCCESS;
}
try {
po::notify(vm);
} catch (po::required_option &e) {
LOG(fatal) << "Error while parsing command line options:";
LOG(fatal) << "The required option " << e.get_option_name() << " was not specified.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
}
if (vm.count("config")) {
std::string config_path = vm["config"].as();
std::ifstream ifs(config_path.c_str());
if (!ifs) {
LOG(fatal) << "Error: can not open config file: " << config_path;
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} else {
try {
store(parse_config_file(ifs, cli_options), vm);
} catch (po::multiple_occurrences &e) {
LOG(fatal) << "Error while parsing config file:";
LOG(fatal) << "Option " << e.get_option_name() << " was specified multiple times.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::unknown_option &e) {
LOG(fatal) << "Error while parsing config file:";
LOG(fatal) << "Option " << e.get_option_name() << " not known.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
} catch (po::invalid_option_value &e) {
LOG(fatal) << "Error while parsing config file:";
LOG(fatal) << "The value specified for option " << e.get_option_name() << " has an invalid format.";
LOG(fatal) << default_error_msg;
return EXIT_FAILURE;
}
notify(vm);
}
}
return PROCESSING_SUCCESSFUL;
}