1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3 http://www.boost.org/
4
5 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
6 Software License, Version 1.0. (See accompanying file
7 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9
10#if !defined(BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP)
11#define BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP
12
13#include <string>
14#include <fstream>
15#include <vector>
16
17#include <boost/config.hpp>
18#include <boost/assert.hpp>
19#include <boost/any.hpp>
20
21///////////////////////////////////////////////////////////////////////////////
22// forward declarations only
23namespace cmd_line_utils
24{
25 class include_paths;
26}
27
28namespace boost { namespace program_options
29{
30 void validate(boost::any &v, std::vector<std::string> const &s,
31 cmd_line_utils::include_paths *, int);
32}} // boost::program_options
33
34///////////////////////////////////////////////////////////////////////////////
35#include <boost/program_options.hpp>
36
37///////////////////////////////////////////////////////////////////////////////
38namespace cmd_line_utils {
39
40 namespace po = boost::program_options;
41
42 ///////////////////////////////////////////////////////////////////////////
43 // Additional command line parser which interprets '@something' as an
44 // option "config-file" with the value "something".
45 inline std::pair<std::string, std::string>
46 at_option_parser(std::string const& s)
47 {
48 if ('@' == s[0])
49 return std::make_pair(x: std::string("config-file"), y: s.substr(pos: 1));
50 else
51 return std::pair<std::string, std::string>();
52 }
53
54 ///////////////////////////////////////////////////////////////////////////
55 // class, which keeps the include file information read from the options
56 class include_paths
57 {
58 public:
59 include_paths() : seen_separator(false) {}
60
61 std::vector<std::string> paths; // stores user paths
62 std::vector<std::string> syspaths; // stores system paths
63 bool seen_separator; // options contain a '-I-' option
64
65 // Function which validates additional tokens from the given option.
66 static void
67 validate(boost::any &v, std::vector<std::string> const &tokens)
68 {
69 if (v.empty())
70 v = boost::any(include_paths());
71
72 include_paths *p = boost::any_cast<include_paths>(operand: &v);
73 BOOST_ASSERT(NULL != p);
74
75 // Assume only one path per '-I' occurrence.
76 std::string const& t = po::validators::get_single_string(v: tokens);
77 if (t == "-") {
78 // found -I- option, so switch behaviour
79 p->seen_separator = true;
80 }
81 else if (p->seen_separator) {
82 // store this path as a system path
83 p->syspaths.push_back(x: t);
84 }
85 else {
86 // store this path as an user path
87 p->paths.push_back(x: t);
88 }
89 }
90 };
91
92 ///////////////////////////////////////////////////////////////////////////
93 // Read all options from a given config string, parse and add them to the
94 // given variables_map
95 inline void
96 read_config_options(int debuglevel, std::string const &indata,
97 po::options_description const &desc, po::variables_map &vm)
98 {
99 if (9 == debuglevel) {
100 std::cerr << "read_config_options: reading config options"
101 << std::endl;
102 }
103
104 std::istringstream istrm(indata);
105
106 std::vector<std::string> options;
107 std::string line;
108
109 while (std::getline(is&: istrm, str&: line)) {
110 // skip empty lines
111 std::string::size_type pos = line.find_first_not_of(s: " \t");
112 if (pos == std::string::npos)
113 continue;
114
115 // skip comment lines
116 if ('#' != line[pos])
117 options.push_back(x: line);
118 }
119
120 if (options.size() > 0) {
121 if (9 == debuglevel) {
122 std::cerr << "read_config_options: options size is: "
123 << (int)options.size() << std::endl;
124 }
125
126 // (the (int) cast is to make the True64 compiler happy)
127 using namespace boost::program_options::command_line_style;
128 po::store(options: po::command_line_parser(options)
129 .options(desc).style(xstyle: (int)unix_style).run(), m&: vm);
130 po::notify(m&: vm);
131 }
132
133 if (9 == debuglevel) {
134 std::cerr << "read_config_options: succeeded to read config options"
135 << std::endl;
136 }
137 }
138
139 ///////////////////////////////////////////////////////////////////////////
140 // Read all options from a given config file, parse and add them to the
141 // given variables_map
142 inline bool
143 read_config_file(int debuglevel, std::string const &filename,
144 po::options_description const &desc, po::variables_map &vm)
145 {
146 if (9 == debuglevel) {
147 std::cerr << "read_config_file: reading config options"
148 << std::endl;
149 }
150
151 std::ifstream ifs(filename.c_str());
152
153 if (!ifs.is_open()) {
154 std::cerr
155 << "testwave: " << filename
156 << ": command line warning: config file not found"
157 << std::endl;
158 return false;
159 }
160
161 // parse the file and extract all given arguments and options
162 std::vector<std::string> options;
163 std::string line;
164
165 while (std::getline(is&: ifs, str&: line)) {
166 // skip empty lines
167 std::string::size_type pos = line.find_first_not_of(s: " \t");
168 if (pos == std::string::npos)
169 continue;
170
171 // skip comment lines
172 if ('#' != line[pos])
173 options.push_back(x: line);
174 }
175
176 if (options.size() > 0) {
177 if (9 == debuglevel) {
178 std::cerr << "read_config_file: options size is: "
179 << (int)options.size() << std::endl;
180 }
181
182 // treat positional arguments as --input parameters
183 po::positional_options_description p;
184 p.add(name: "input", max_count: -1);
185
186 // parse the vector of lines and store the results into the given
187 // variables map
188 // (the (int) cast is to make the True64 compiler happy)
189 using namespace boost::program_options::command_line_style;
190 po::store(options: po::command_line_parser(options)
191 .options(desc).positional(desc: p).style(xstyle: (int)unix_style).run(), m&: vm);
192 po::notify(m&: vm);
193 }
194
195
196 if (9 == debuglevel) {
197 std::cerr << "read_config_file: succeeded to read config options"
198 << std::endl;
199 }
200 return true;
201 }
202
203 ///////////////////////////////////////////////////////////////////////////
204 // predicate to extract all positional arguments from the command line
205 struct is_argument
206 {
207 bool operator()(po::option const &opt)
208 {
209 return (opt.position_key == -1) ? true : false;
210 }
211 };
212
213///////////////////////////////////////////////////////////////////////////////
214} // namespace cmd_line_utils
215
216///////////////////////////////////////////////////////////////////////////////
217//
218// Special validator overload, which allows to handle the -I- syntax for
219// switching the semantics of an -I option.
220//
221// This must be injected into the boost::program_options namespace
222//
223///////////////////////////////////////////////////////////////////////////////
224namespace boost { namespace program_options {
225
226 inline void
227 validate(boost::any &v, std::vector<std::string> const &s,
228 cmd_line_utils::include_paths *, int)
229 {
230 cmd_line_utils::include_paths::validate(v, tokens: s);
231 }
232
233}} // namespace boost::program_options
234
235#endif // !defined(BOOST_WAVE_LIBS_WAVE_TEST_CMD_LINE_UTILS_HPP)
236

source code of boost/libs/wave/test/testwave/cmd_line_utils.hpp