]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/wave/samples/list_includes/list_includes.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / wave / samples / list_includes / list_includes.cpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 Sample: List include dependencies of a given source file
5
6 The 'list_includes' sample shows a simple way, how to use the Wave C++
7 preprocessor library to extract a list of included files from a given
8 source file.
9 To get a hint which commandline options are supported, call it with the
10 --help option.
11
12 http://www.boost.org/
13
14 Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost
15 Software License, Version 1.0. (See accompanying file
16 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
17=============================================================================*/
18
19#include "list_includes.hpp" // config data
20
21///////////////////////////////////////////////////////////////////////////////
22// include required boost libraries
23#include <boost/assert.hpp>
24#include <boost/program_options.hpp>
25
26///////////////////////////////////////////////////////////////////////////////
27// Include Wave itself
28#include <boost/wave.hpp>
29
30///////////////////////////////////////////////////////////////////////////////
31// Include the lexer stuff
32#include <boost/wave/cpplexer/cpp_lex_token.hpp> // standard token type
33#include "lexertl_iterator.hpp" // lexertl based lexer
34
35///////////////////////////////////////////////////////////////////////////////
36// Include the default context trace policies
37#include <boost/wave/preprocessing_hooks.hpp>
38
20effc67
TL
39#include <iostream>
40
7c673cae
FG
41///////////////////////////////////////////////////////////////////////////////
42// include lexer specifics, import lexer names
43#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION == 0
44#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>
45#endif
46
47///////////////////////////////////////////////////////////////////////////////
48// import required names
49using namespace boost::spirit::classic;
50
51using std::string;
52using std::vector;
53using std::set;
54using std::cout;
55using std::cerr;
56using std::endl;
57using std::ifstream;
58using std::ostream;
59using std::istreambuf_iterator;
60
61namespace po = boost::program_options;
62
63///////////////////////////////////////////////////////////////////////////////
64namespace cmd_line_util {
65
66 // predicate to extract all positional arguments from the command line
67 struct is_argument {
68 bool operator()(po::option const &opt)
69 {
70 return (opt.position_key == -1) ? true : false;
71 }
72 };
73
74///////////////////////////////////////////////////////////////////////////////
75}
76
77///////////////////////////////////////////////////////////////////////////////
78// print the current version
79
80int print_version()
81{
82// get time of last compilation of this file
83boost::wave::util::time_conversion_helper compilation_time(__DATE__ " " __TIME__);
84
85// calculate the number of days since Jan 29 2003
86// (the day the list_includes project was started)
87std::tm first_day;
88
89 std::memset (&first_day, 0, sizeof(std::tm));
90 first_day.tm_mon = 0; // Jan
91 first_day.tm_mday = 29; // 29
92 first_day.tm_year = 103; // 2003
93
94long seconds = long(std::difftime(compilation_time.get_time(),
95 std::mktime(&first_day)));
96
97 cout
98 << LIST_INCLUDES_VERSION_MAJOR << '.'
99 << LIST_INCLUDES_VERSION_MINOR << '.'
100 << LIST_INCLUDES_VERSION_SUBMINOR << '.'
101 << seconds/(3600*24); // get number of days from seconds
102 return 1; // exit app
103}
104
105///////////////////////////////////////////////////////////////////////////////
106// policy class
107struct trace_include_files
108: public boost::wave::context_policies::default_preprocessing_hooks
109{
110 trace_include_files(set<string> &files_)
111 : files(files_), include_depth(0)
112 {}
113
114#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
115 void
116 opened_include_file(string const &relname, string const &filename,
117 std::size_t /*include_depth*/, bool is_system_include)
118#else
119 template <typename ContextT>
120 void
121 opened_include_file(ContextT const& ctx, std::string const& relname,
122 std::string const& filename, bool is_system_include)
123#endif
124 {
125 set<string>::iterator it = files.find(filename);
126 if (it == files.end()) {
127 // print indented filename
128 for (std::size_t i = 0; i < include_depth; ++i)
129 cout << " ";
130 cout << filename << endl;
131
132 files.insert(filename);
133 }
134 ++include_depth;
135 }
136
137#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
138 void returning_from_include_file()
139#else
140 template <typename ContextT>
141 void returning_from_include_file(ContextT const& ctx)
142#endif
143 {
144 --include_depth;
145 }
146
147 set<string> &files;
148 std::size_t include_depth;
149};
150
151///////////////////////////////////////////////////////////////////////////////
152//
153int
154do_actual_work(vector<string> const &arguments, po::variables_map const &vm)
155{
156// current file position is saved for exception handling
157boost::wave::util::file_position_type current_position;
158
159 try {
160 // list the included files for all arguments given
161 vector<string>::const_iterator lastfile = arguments.end();
162 for (vector<string>::const_iterator file_it = arguments.begin();
163 file_it != lastfile; ++file_it)
164 {
165 ifstream instream((*file_it).c_str());
166 string instring;
167
168 if (!instream.is_open()) {
169 cerr << "Could not open input file: " << *file_it << endl;
170 continue;
171 }
172 instream.unsetf(std::ios::skipws);
173 instring = string(istreambuf_iterator<char>(instream.rdbuf()),
174 istreambuf_iterator<char>());
175
176 // The template boost::wave::cpplexer::lex_token<> is the token type to be
177 // used by the Wave library.
178 typedef boost::wave::cpplexer::lexertl::lex_iterator<
179 boost::wave::cpplexer::lex_token<> >
180 lex_iterator_type;
181 typedef boost::wave::context<
182 std::string::iterator, lex_iterator_type,
183 boost::wave::iteration_context_policies::load_file_to_string,
184 trace_include_files
185 > context_type;
186
187 set<string> files;
188 trace_include_files trace(files);
189
190 // The preprocessor iterator shouldn't be constructed directly. It is
191 // to be generated through a wave::context<> object. This wave:context<>
192 // object is additionally to be used to initialize and define different
193 // parameters of the actual preprocessing.
194 // The preprocessing of the input stream is done on the fly behind the
195 // scenes during iteration over the context_type::iterator_type stream.
196 context_type ctx (instring.begin(), instring.end(), (*file_it).c_str(), trace);
197
198 // add include directories to the include path
199 if (vm.count("include")) {
200 vector<string> const &paths =
201 vm["include"].as<vector<string> >();
202 vector<string>::const_iterator end = paths.end();
203 for (vector<string>::const_iterator cit = paths.begin();
204 cit != end; ++cit)
205 {
206 ctx.add_include_path((*cit).c_str());
207 }
208 }
209
210 // add system include directories to the include path
211 if (vm.count("sysinclude")) {
212 vector<string> const &syspaths =
213 vm["sysinclude"].as<vector<string> >();
214 vector<string>::const_iterator end = syspaths.end();
215 for (vector<string>::const_iterator cit = syspaths.begin();
216 cit != end; ++cit)
217 {
218 ctx.add_sysinclude_path((*cit).c_str());
219 }
220 }
221
222 // analyze the actual file
223 context_type::iterator_type first = ctx.begin();
224 context_type::iterator_type last = ctx.end();
225
226 cout << "Printing dependency information for: "
227 << *file_it << endl;
228
229 while (first != last) {
230 current_position = (*first).get_position();
231 ++first;
232 }
233
234 // prepend endl before next file
235 cout << endl;
236 }
237 }
238 catch (boost::wave::cpp_exception &e) {
239 // some preprocessing error
240 cerr
241 << e.file_name() << "(" << e.line_no() << "): "
242 << e.description() << endl;
243 return 2;
244 }
245 catch (std::exception &e) {
246 // use last recognized token to retrieve the error position
247 cerr
248 << current_position.get_file()
249 << "(" << current_position.get_line() << "): "
250 << "exception caught: " << e.what()
251 << endl;
252 return 3;
253 }
254 catch (...) {
255 // use last recognized token to retrieve the error position
256 cerr
257 << current_position.get_file()
258 << "(" << current_position.get_line() << "): "
259 << "unexpected exception caught." << endl;
260 return 4;
261 }
262 return 0;
263}
264
265///////////////////////////////////////////////////////////////////////////////
266// here we go!
267int
268main (int argc, char *argv[])
269{
270 try {
271 // analyze the command line options and arguments
272 vector<string> syspathes;
273 po::options_description desc("Usage: list_includes [options] file ...");
274
275 desc.add_options()
276 ("help,h", "print out program usage (this message)")
277 ("version,v", "print the version number")
278 ("include,I", po::value<vector<string> >(),
279 "specify additional include directory")
280 ("sysinclude,S", po::value<vector<string> >(),
281 "specify additional system include directory")
282 ;
283
284 using namespace boost::program_options::command_line_style;
285
286 po::parsed_options opts = po::parse_command_line(argc, argv, desc, unix_style);
287 po::variables_map vm;
288
289 po::store(opts, vm);
290 po::notify(vm);
291
292 if (vm.count("help")) {
293 cout << desc << endl;
294 return 1;
295 }
296
297 if (vm.count("version")) {
298 return print_version();
299 }
300
301 // extract the arguments from the parsed command line
302 vector<po::option> arguments;
303
304 std::remove_copy_if(opts.options.begin(), opts.options.end(),
305 inserter(arguments, arguments.end()), cmd_line_util::is_argument());
306
307 // if there is no input file given, then exit
308 if (0 == arguments.size() || 0 == arguments[0].value.size()) {
309 cerr << "list_includes: No input file given. "
310 << "Use --help to get a hint." << endl;
311 return 5;
312 }
313
314 // iterate over all given input files
315 return do_actual_work(arguments[0].value , vm);
316 }
317 catch (std::exception &e) {
318 cout << "list_includes: exception caught: " << e.what() << endl;
319 return 6;
320 }
321 catch (...) {
322 cerr << "list_includes: unexpected exception caught." << endl;
323 return 7;
324 }
325}
326