/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library http://www.boost.org/ Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP) #define BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // forward declarations only namespace cmd_line_utils { class include_paths; } namespace boost { namespace program_options { void validate(boost::any &v, std::vector const &s, cmd_line_utils::include_paths *, int); }} // boost::program_options /////////////////////////////////////////////////////////////////////////////// #include /////////////////////////////////////////////////////////////////////////////// namespace cmd_line_utils { namespace po = boost::program_options; /////////////////////////////////////////////////////////////////////////// // Additional command line parser which interprets '@something' as an // option "config-file" with the value "something". inline std::pair at_option_parser(std::string const& s) { if ('@' == s[0]) return std::make_pair(std::string("config-file"), s.substr(1)); else return std::pair(); } /////////////////////////////////////////////////////////////////////////// // class, which keeps the include file information read from the options class include_paths { public: include_paths() : seen_separator(false) {} std::vector paths; // stores user paths std::vector syspaths; // stores system paths bool seen_separator; // options contain a '-I-' option // Function which validates additional tokens from the given option. static void validate(boost::any &v, std::vector const &tokens) { if (v.empty()) v = boost::any(include_paths()); include_paths *p = boost::any_cast(&v); BOOST_ASSERT(NULL != p); // Assume only one path per '-I' occurrence. std::string const& t = po::validators::get_single_string(tokens); if (t == "-") { // found -I- option, so switch behaviour p->seen_separator = true; } else if (p->seen_separator) { // store this path as a system path p->syspaths.push_back(t); } else { // store this path as an user path p->paths.push_back(t); } } }; /////////////////////////////////////////////////////////////////////////// // Read all options from a given config string, parse and add them to the // given variables_map inline void read_config_options(int debuglevel, std::string const &indata, po::options_description const &desc, po::variables_map &vm) { if (9 == debuglevel) { std::cerr << "read_config_options: reading config options" << std::endl; } std::istringstream istrm(indata); std::vector options; std::string line; while (std::getline(istrm, line)) { // skip empty lines std::string::size_type pos = line.find_first_not_of(" \t"); if (pos == std::string::npos) continue; // skip comment lines if ('#' != line[pos]) options.push_back(line); } if (options.size() > 0) { if (9 == debuglevel) { std::cerr << "read_config_options: options size is: " << (int)options.size() << std::endl; } // (the (int) cast is to make the True64 compiler happy) using namespace boost::program_options::command_line_style; po::store(po::command_line_parser(options) .options(desc).style((int)unix_style).run(), vm); po::notify(vm); } if (9 == debuglevel) { std::cerr << "read_config_options: succeeded to read config options" << std::endl; } } /////////////////////////////////////////////////////////////////////////// // Read all options from a given config file, parse and add them to the // given variables_map inline bool read_config_file(int debuglevel, std::string const &filename, po::options_description const &desc, po::variables_map &vm) { if (9 == debuglevel) { std::cerr << "read_config_file: reading config options" << std::endl; } std::ifstream ifs(filename.c_str()); if (!ifs.is_open()) { std::cerr << "testwave: " << filename << ": command line warning: config file not found" << std::endl; return false; } // parse the file and extract all given arguments and options std::vector options; std::string line; while (std::getline(ifs, line)) { // skip empty lines std::string::size_type pos = line.find_first_not_of(" \t"); if (pos == std::string::npos) continue; // skip comment lines if ('#' != line[pos]) options.push_back(line); } if (options.size() > 0) { if (9 == debuglevel) { std::cerr << "read_config_file: options size is: " << (int)options.size() << std::endl; } // treat positional arguments as --input parameters po::positional_options_description p; p.add("input", -1); // parse the vector of lines and store the results into the given // variables map // (the (int) cast is to make the True64 compiler happy) using namespace boost::program_options::command_line_style; po::store(po::command_line_parser(options) .options(desc).positional(p).style((int)unix_style).run(), vm); po::notify(vm); } if (9 == debuglevel) { std::cerr << "read_config_file: succeeded to read config options" << std::endl; } return true; } /////////////////////////////////////////////////////////////////////////// // predicate to extract all positional arguments from the command line struct is_argument { bool operator()(po::option const &opt) { return (opt.position_key == -1) ? true : false; } }; /////////////////////////////////////////////////////////////////////////////// } // namespace cmd_line_utils /////////////////////////////////////////////////////////////////////////////// // // Special validator overload, which allows to handle the -I- syntax for // switching the semantics of an -I option. // // This must be injected into the boost::program_options namespace // /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace program_options { inline void validate(boost::any &v, std::vector const &s, cmd_line_utils::include_paths *, int) { cmd_line_utils::include_paths::validate(v, s); } }} // namespace boost::program_options #endif // !defined(BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP)