]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/wave/test/testwave/testwave_app.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / wave / test / testwave / testwave_app.cpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3 http://www.boost.org/
4
5 Copyright (c) 2001-2013 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 // disable stupid compiler warnings
11 #include <boost/config/warning_disable.hpp>
12
13 // system headers
14 #include <string>
15 #include <iostream>
16 #include <vector>
17 #include <ctime>
18
19 // include boost
20 #include <boost/config.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/throw_exception.hpp>
23 #include <boost/filesystem/path.hpp>
24 #include <boost/filesystem/operations.hpp>
25 #include <boost/detail/workaround.hpp>
26
27 // include Wave
28
29 // always use new hooks
30 #define BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS 0
31
32 #include <boost/wave.hpp>
33
34 // include the lexer related stuff
35 #include <boost/wave/cpplexer/cpp_lex_token.hpp> // token type
36 #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
37
38 // test application related headers
39 #include "cmd_line_utils.hpp"
40 #include "testwave_app.hpp"
41 #include "collect_hooks_information.hpp"
42
43 # ifdef BOOST_NO_STDC_NAMESPACE
44 namespace std
45 {
46 using ::asctime; using ::gmtime; using ::localtime;
47 using ::difftime; using ::time; using ::tm; using ::mktime; using ::system;
48 }
49 # endif
50
51 namespace po = boost::program_options;
52 namespace fs = boost::filesystem;
53
54 ///////////////////////////////////////////////////////////////////////////////
55 // testwave version definitions
56 #define TESTWAVE_VERSION_MAJOR 0
57 #define TESTWAVE_VERSION_MINOR 6
58 #define TESTWAVE_VERSION_SUBMINOR 0
59
60 namespace {
61
62 ///////////////////////////////////////////////////////////////////////////
63 template <typename Iterator>
64 inline bool
65 handle_next_token(Iterator &it, Iterator const& end,
66 std::string &result)
67 {
68 typedef typename Iterator::value_type token_type;
69
70 token_type tok = *it++;
71 result = result + tok.get_value().c_str();
72 return (it == end) ? false : true;
73 }
74
75 ///////////////////////////////////////////////////////////////////////////
76 template <typename String>
77 String const& handle_quoted_filepath(String &name)
78 {
79 using boost::wave::util::impl::unescape_lit;
80
81 String unesc_name = unescape_lit(name.substr(1, name.size()-2));
82 fs::path p (boost::wave::util::create_path(unesc_name.c_str()));
83
84 name = String("\"") + boost::wave::util::leaf(p).c_str() + String("\"");
85 return name;
86 }
87
88 ///////////////////////////////////////////////////////////////////////////
89 template <typename Iterator>
90 bool handle_line_directive(Iterator &it, Iterator const& end,
91 std::string &result)
92 {
93 typedef typename Iterator::value_type token_type;
94 typedef typename token_type::string_type string_type;
95
96 if (!handle_next_token(it, end, result) || // #line
97 !handle_next_token(it, end, result) || // whitespace
98 !handle_next_token(it, end, result) || // number
99 !handle_next_token(it, end, result)) // whitespace
100 {
101 return false;
102 }
103
104 using boost::wave::util::impl::unescape_lit;
105
106 token_type filename = *it;
107 string_type name = filename.get_value();
108
109 handle_quoted_filepath(name);
110 result = result + name.c_str();
111 return true;
112 }
113
114 template <typename T>
115 inline T const&
116 variables_map_as(po::variable_value const& v, T*)
117 {
118 #if (__GNUC__ == 3 && (__GNUC_MINOR__ == 2 || __GNUC_MINOR__ == 3)) || \
119 BOOST_WORKAROUND(__MWERKS__, < 0x3200)
120 // gcc 3.2.x and 3.3.x choke on vm[...].as<...>()
121 // CW 8.3 has problems with the v.as<T>() below
122 T const* r = boost::any_cast<T>(&v.value());
123 if (!r)
124 boost::throw_exception(boost::bad_any_cast());
125 return *r;
126 #else
127 return v.as<T>();
128 #endif
129 }
130
131 }
132
133 ///////////////////////////////////////////////////////////////////////////
134 //
135 // This function compares the real result and the expected one but first
136 // replaces all occurrences in the expected result of
137 // $E: to the result of preprocessing the given expression
138 // $F: to the passed full filepath
139 // $P: to the full path
140 // $B: to the full path (same as $P, but using forward slash '/' on Windows)
141 // $V: to the current Boost version number
142 //
143 ///////////////////////////////////////////////////////////////////////////
144 bool
145 testwave_app::got_expected_result(std::string const& filename,
146 std::string const& result, std::string& expected)
147 {
148 using boost::wave::util::impl::escape_lit;
149
150 std::string full_result;
151 std::string::size_type pos = 0;
152 std::string::size_type pos1 = expected.find_first_of("$");
153
154 if (pos1 != std::string::npos) {
155 do {
156 switch(expected[pos1+1]) {
157 case 'E': // preprocess the given token sequence
158 {
159 if ('(' == expected[pos1+2]) {
160 std::size_t p = expected.find_first_of(")", pos1+1);
161 if (std::string::npos == p) {
162 std::cerr
163 << "testwave: unmatched parenthesis in $E"
164 " directive" << std::endl;
165 return false;
166 }
167 std::string source = expected.substr(pos1+3, p-pos1-3);
168 std::string result, error, hooks;
169 bool pp_result = preprocess_file(filename, source,
170 result, error, hooks, true);
171 if (!pp_result) {
172 std::cerr
173 << "testwave: preprocessing error in $E directive: "
174 << error << std::endl;
175 return false;
176 }
177 full_result = full_result +
178 expected.substr(pos, pos1-pos) + result;
179 pos1 = expected.find_first_of ("$",
180 pos = pos1 + 4 + source.size());
181 }
182 }
183 break;
184
185 case 'F': // insert base file name
186 full_result = full_result +
187 expected.substr(pos, pos1-pos) + escape_lit(filename);
188 pos1 = expected.find_first_of ("$", pos = pos1 + 2);
189 break;
190
191 case 'P': // insert full path
192 case 'B': // same as 'P', but forward slashes on Windows
193 {
194 fs::path fullpath (
195 boost::wave::util::complete_path(
196 boost::wave::util::create_path(filename),
197 boost::wave::util::current_path())
198 );
199
200 if ('(' == expected[pos1+2]) {
201 // the $P(basename) syntax is used
202 std::size_t p = expected.find_first_of(")", pos1+1);
203 if (std::string::npos == p) {
204 std::cerr
205 << "testwave: unmatched parenthesis in $P"
206 " directive" << std::endl;
207 return false;
208 }
209 std::string base = expected.substr(pos1+3, p-pos1-3);
210 fullpath = boost::wave::util::branch_path(fullpath) /
211 boost::wave::util::create_path(base);
212 full_result += expected.substr(pos, pos1-pos);
213 if ('P' == expected[pos1+1]) {
214 #if defined(BOOST_WINDOWS)
215 std::string p = replace_slashes(
216 boost::wave::util::native_file_string(
217 boost::wave::util::normalize(fullpath)),
218 "/", '\\');
219 #else
220 std::string p (
221 boost::wave::util::native_file_string(
222 boost::wave::util::normalize(fullpath)));
223 #endif
224 full_result += escape_lit(p);
225 }
226 else {
227 #if defined(BOOST_WINDOWS)
228 std::string p = replace_slashes(
229 boost::wave::util::normalize(fullpath).string());
230 #else
231 std::string p (
232 boost::wave::util::normalize(fullpath).string());
233 #endif
234 full_result += escape_lit(p);
235 }
236 pos1 = expected.find_first_of ("$",
237 pos = pos1 + 4 + base.size());
238 }
239 else {
240 // the $P is used on its own
241 full_result += expected.substr(pos, pos1-pos);
242 if ('P' == expected[pos1+1]) {
243 full_result += escape_lit(
244 boost::wave::util::native_file_string(fullpath));
245 }
246 else {
247 #if defined(BOOST_WINDOWS)
248 std::string p = replace_slashes(fullpath.string());
249 #else
250 std::string p (fullpath.string());
251 #endif
252 full_result += escape_lit(fullpath.string());
253 }
254 pos1 = expected.find_first_of ("$", pos = pos1 + 2);
255 }
256 }
257 break;
258
259 case 'R': // insert relative file name
260 case 'S': // same as 'R', but forward slashes on Windows
261 {
262 fs::path relpath;
263 boost::wave::util::as_relative_to(
264 boost::wave::util::create_path(filename),
265 boost::wave::util::current_path(),
266 relpath);
267
268 if ('(' == expected[pos1+2]) {
269 // the $R(basename) syntax is used
270 std::size_t p = expected.find_first_of(")", pos1+1);
271 if (std::string::npos == p) {
272 std::cerr
273 << "testwave: unmatched parenthesis in $R"
274 " directive" << std::endl;
275 return false;
276 }
277 std::string base = expected.substr(pos1+3, p-pos1-3);
278 relpath = boost::wave::util::branch_path(relpath) /
279 boost::wave::util::create_path(base);
280 full_result += expected.substr(pos, pos1-pos);
281 if ('R' == expected[pos1+1]) {
282 full_result += escape_lit(
283 boost::wave::util::native_file_string(
284 boost::wave::util::normalize(relpath)));
285 }
286 else {
287 #if defined(BOOST_WINDOWS)
288 std::string p = replace_slashes(
289 boost::wave::util::normalize(relpath).string());
290 #else
291 std::string p (
292 boost::wave::util::normalize(relpath).string());
293 #endif
294 full_result += escape_lit(p);
295 }
296 pos1 = expected.find_first_of ("$",
297 pos = pos1 + 4 + base.size());
298 }
299 else {
300 // the $R is used on its own
301 full_result += expected.substr(pos, pos1-pos);
302 if ('R' == expected[pos1+1]) {
303 full_result += escape_lit(
304 boost::wave::util::native_file_string(relpath));
305 }
306 else {
307 #if defined(BOOST_WINDOWS)
308 std::string p = replace_slashes(relpath.string());
309 #else
310 std::string p (relpath.string());
311 #endif
312 full_result += escape_lit(p);
313 }
314 pos1 = expected.find_first_of ("$", pos = pos1 + 2);
315 }
316 }
317 break;
318
319 case 'V': // insert Boost version
320 full_result = full_result +
321 expected.substr(pos, pos1-pos) + BOOST_LIB_VERSION;
322 pos1 = expected.find_first_of ("$", pos = pos1 + 2);
323 break;
324
325 default:
326 full_result = full_result +
327 expected.substr(pos, pos1-pos);
328 pos1 = expected.find_first_of ("$", (pos = pos1) + 1);
329 break;
330 }
331
332 } while(pos1 != std::string::npos);
333 full_result += expected.substr(pos);
334 }
335 else {
336 full_result = expected;
337 }
338
339 expected = full_result;
340 return full_result == result;
341 }
342
343 ///////////////////////////////////////////////////////////////////////////////
344 testwave_app::testwave_app(po::variables_map const& vm)
345 : debuglevel(1), desc_options("Preprocessor configuration options"),
346 global_vm(vm)
347 {
348 desc_options.add_options()
349 ("include,I", po::value<cmd_line_utils::include_paths>()->composing(),
350 "specify an additional include directory")
351 ("sysinclude,S", po::value<std::vector<std::string> >()->composing(),
352 "specify an additional system include directory")
353 ("forceinclude,F", po::value<std::vector<std::string> >()->composing(),
354 "force inclusion of the given file")
355 ("define,D", po::value<std::vector<std::string> >()->composing(),
356 "specify a macro to define (as macro[=[value]])")
357 ("predefine,P", po::value<std::vector<std::string> >()->composing(),
358 "specify a macro to predefine (as macro[=[value]])")
359 ("undefine,U", po::value<std::vector<std::string> >()->composing(),
360 "specify a macro to undefine")
361 ("nesting,n", po::value<int>(),
362 "specify a new maximal include nesting depth")
363 ("long_long", "enable long long support in C++ mode")
364 ("preserve", "preserve comments")
365 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
366 ("variadics", "enable certain C99 extensions in C++ mode")
367 ("c99", "enable C99 mode (implies --variadics)")
368 #endif
369 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
370 ("noguard,G", "disable include guard detection")
371 #endif
372 ("skipped_token_hooks", "record skipped_token hook calls")
373 #if BOOST_WAVE_SUPPORT_CPP0X != 0
374 ("c++11", "enable C++11 mode (implies --variadics and --long_long)")
375 #endif
376 ;
377 }
378
379 ///////////////////////////////////////////////////////////////////////////////
380 //
381 // Test the given file (i.e. preprocess the file and compare the result
382 // against the embedded 'R' comments, if an error occurs compare the error
383 // message against the given 'E' comments, if no error occurred, compare the
384 // generated hooks result against the given 'H' comments).
385 //
386 ///////////////////////////////////////////////////////////////////////////////
387 bool
388 testwave_app::test_a_file(std::string filename)
389 {
390 // read the input file into a string
391 std::string instr;
392 if (!read_file(filename, instr))
393 return false; // error was reported already
394
395 bool test_hooks = true;
396 if (global_vm.count("hooks"))
397 test_hooks = variables_map_as(global_vm["hooks"], (bool *)NULL);
398
399 // extract expected output, preprocess the data and compare results
400 std::string expected, expected_hooks;
401 if (extract_expected_output(filename, instr, expected, expected_hooks)) {
402 bool retval = true; // assume success
403 bool printed_result = false;
404 std::string result, error, hooks;
405 bool pp_result = preprocess_file(filename, instr, result, error, hooks);
406 if (pp_result || !result.empty()) {
407 // did we expect an error?
408 std::string expected_error;
409 if (!extract_special_information(filename, instr, 'E', expected_error))
410 return false;
411
412 if (!expected_error.empty() &&
413 !got_expected_result(filename, error, expected_error))
414 {
415 // we expected an error but got none (or a different one)
416 if (debuglevel > 2) {
417 std::cerr
418 << filename << ": failed" << std::endl
419 << "result: " << std::endl << result << std::endl;
420
421 if (!error.empty()) {
422 std::cerr << "expected result: " << std::endl
423 << expected << std::endl;
424 }
425 if (!expected_error.empty()) {
426 std::cerr << "expected error: " << std::endl
427 << expected_error << std::endl;
428 }
429 }
430 else if (debuglevel > 1) {
431 std::cerr << filename << ": failed" << std::endl;
432 }
433 retval = false;
434 }
435 else if (!got_expected_result(filename, result, expected)) {
436 // no preprocessing error encountered
437 if (debuglevel > 2) {
438 std::cerr
439 << filename << ": failed" << std::endl
440 << "result: " << std::endl << result << std::endl
441 << "expected: " << std::endl << expected << std::endl;
442 }
443 else if (debuglevel > 1) {
444 std::cerr << filename << ": failed" << std::endl;
445 }
446 retval = false;
447 }
448 else {
449 // preprocessing succeeded, check hook information, if appropriate
450 if (test_hooks && !expected_hooks.empty() &&
451 !got_expected_result(filename, hooks, expected_hooks))
452 {
453 if (debuglevel > 2) {
454 std::cerr << filename << ": failed" << std::endl
455 << "hooks result: " << std::endl << hooks
456 << std::endl;
457 std::cerr << "expected hooks result: " << std::endl
458 << expected_hooks << std::endl;
459 }
460 else if (debuglevel > 1) {
461 std::cerr << filename << ": failed" << std::endl;
462 }
463 retval = false;
464 }
465 }
466
467 // print success message, if appropriate
468 if (retval) {
469 if (debuglevel > 5) {
470 std::cerr
471 << filename << ": succeeded" << std::endl
472 << "result: " << std::endl << result << std::endl
473 << "hooks result: " << std::endl << hooks << std::endl;
474 }
475 else if (debuglevel > 4) {
476 std::cerr
477 << filename << ": succeeded" << std::endl
478 << "result: " << std::endl << result << std::endl;
479 }
480 else if (debuglevel > 3) {
481 std::cerr << filename << ": succeeded" << std::endl;
482 }
483 printed_result = true;
484 }
485 }
486
487 if (!pp_result) {
488 // there was a preprocessing error, was it expected?
489 std::string expected_error;
490 if (!extract_special_information(filename, instr, 'E', expected_error))
491 return false;
492
493 if (!got_expected_result(filename, error, expected_error)) {
494 // the error was unexpected
495 if (debuglevel > 2) {
496 std::cerr
497 << filename << ": failed" << std::endl;
498
499 if (!expected_error.empty()) {
500 std::cerr
501 << "error result: " << std::endl << error << std::endl
502 << "expected error: " << std::endl
503 << expected_error << std::endl;
504 }
505 else {
506 std::cerr << "unexpected error: " << error << std::endl;
507 }
508 }
509 else if (debuglevel > 1) {
510 std::cerr << filename << ": failed" << std::endl;
511 }
512 retval = false;
513 }
514
515 if (retval) {
516 if (debuglevel > 5) {
517 std::cerr
518 << filename << ": succeeded (caught expected error)"
519 << std::endl << "error result: " << std::endl << error
520 << std::endl;
521
522 if (!printed_result) {
523 std::cerr
524 << "hooks result: " << std::endl << hooks
525 << std::endl;
526 }
527 }
528 else if (debuglevel > 4) {
529 std::cerr
530 << filename << ": succeeded (caught expected error)"
531 << std::endl << "error result: " << std::endl << error
532 << std::endl;
533 }
534 else if (debuglevel > 3) {
535 // caught the expected error message
536 std::cerr << filename << ": succeeded" << std::endl;
537 }
538 }
539 }
540 return retval;
541 }
542 else {
543 std::cerr
544 << filename << ": no information about expected results found"
545 << std::endl;
546 }
547 return false;
548 }
549
550 ///////////////////////////////////////////////////////////////////////////////
551 //
552 // print the current version of this program
553 //
554 ///////////////////////////////////////////////////////////////////////////////
555 int
556 testwave_app::print_version()
557 {
558 // get time of last compilation of this file
559 boost::wave::util::time_conversion_helper compilation_time(__DATE__ " " __TIME__);
560
561 // calculate the number of days since Feb 12 2005
562 // (the day the testwave project was started)
563 std::tm first_day;
564
565 using namespace std; // some platforms have memset in namespace std
566 memset (&first_day, 0, sizeof(std::tm));
567 first_day.tm_mon = 1; // Feb
568 first_day.tm_mday = 12; // 12
569 first_day.tm_year = 105; // 2005
570
571 long seconds = long(std::difftime(compilation_time.get_time(),
572 std::mktime(&first_day)));
573
574 std::cout
575 << TESTWAVE_VERSION_MAJOR << '.'
576 << TESTWAVE_VERSION_MINOR << '.'
577 << TESTWAVE_VERSION_SUBMINOR << '.'
578 << seconds/(3600*24) // get number of days from seconds
579 << std::endl;
580 return 0; // exit app
581 }
582
583 ///////////////////////////////////////////////////////////////////////////////
584 //
585 // print the copyright statement
586 //
587 ///////////////////////////////////////////////////////////////////////////////
588 int
589 testwave_app::print_copyright()
590 {
591 char const *copyright[] = {
592 "",
593 "Testwave: A test driver for the Boost.Wave C++ preprocessor library",
594 "http://www.boost.org/",
595 "",
596 "Copyright (c) 2001-2012 Hartmut Kaiser, Distributed under the Boost",
597 "Software License, Version 1.0. (See accompanying file",
598 "LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)",
599 0
600 };
601
602 for (int i = 0; 0 != copyright[i]; ++i)
603 std::cout << copyright[i] << std::endl;
604
605 return 0; // exit app
606 }
607
608 ///////////////////////////////////////////////////////////////////////////////
609 //
610 // Read the given file into a string
611 //
612 ///////////////////////////////////////////////////////////////////////////////
613 bool
614 testwave_app::read_file(std::string const& filename, std::string& instr)
615 {
616 // open the given file and report error, if appropriate
617 std::ifstream instream(filename.c_str());
618 if (!instream.is_open()) {
619 std::cerr << "testwave: could not open input file: "
620 << filename << std::endl;
621 return false;
622 }
623 else if (9 == debuglevel) {
624 std::cerr << "read_file: succeeded to open input file: "
625 << filename << std::endl;
626 }
627 instream.unsetf(std::ios::skipws);
628
629 // read the input file into a string
630
631 #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
632 // this is known to be very slow for large files on some systems
633 std::copy (std::istream_iterator<char>(instream),
634 std::istream_iterator<char>(),
635 std::inserter(instr, instr.end()));
636 #else
637 instr = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
638 std::istreambuf_iterator<char>());
639 #endif
640
641 if (9 == debuglevel) {
642 std::cerr << "read_file: succeeded to read input file: "
643 << filename << std::endl;
644 }
645 return true;
646 }
647
648 ///////////////////////////////////////////////////////////////////////////////
649 namespace {
650
651 std::string const& trim_whitespace(std::string& value)
652 {
653 std::string::size_type first = value.find_first_not_of(" \t");
654 if (std::string::npos == first)
655 value.clear();
656 else {
657 std::string::size_type last = value.find_last_not_of(" \t");
658 BOOST_ASSERT(std::string::npos != last);
659 value = value.substr(first, last-first+1);
660 }
661 return value;
662 }
663 }
664
665 ///////////////////////////////////////////////////////////////////////////////
666 //
667 // Extract special information from comments marked with the given letter
668 //
669 ///////////////////////////////////////////////////////////////////////////////
670 bool
671 testwave_app::extract_special_information(std::string const& filename,
672 std::string const& instr, char flag, std::string& content)
673 {
674 if (9 == debuglevel) {
675 std::cerr << "extract_special_information: extracting special information ('"
676 << flag << "') from input file: " << filename << std::endl;
677 }
678
679 // tokenize the input data into C++ tokens using the C++ lexer
680 typedef boost::wave::cpplexer::lex_token<> token_type;
681 typedef boost::wave::cpplexer::lex_iterator<token_type> lexer_type;
682 typedef token_type::position_type position_type;
683
684 boost::wave::language_support const lang_opts =
685 (boost::wave::language_support)(
686 boost::wave::support_option_variadics |
687 boost::wave::support_option_long_long |
688 boost::wave::support_option_no_character_validation |
689 boost::wave::support_option_convert_trigraphs |
690 boost::wave::support_option_insert_whitespace);
691
692 position_type pos(filename.c_str());
693 lexer_type it = lexer_type(instr.begin(), instr.end(), pos, lang_opts);
694 lexer_type end = lexer_type();
695
696 try {
697 // look for C or C++ comments starting with the special character
698 for (/**/; it != end; ++it) {
699 using namespace boost::wave;
700 token_id id = token_id(*it);
701 if (T_CCOMMENT == id) {
702 std::string value = (*it).get_value().c_str();
703 if (flag == value[2]) {
704 if (value.size() > 3 && '(' == value[3]) {
705 std::size_t p = value.find_first_of(")");
706 if (std::string::npos == p) {
707 std::cerr
708 << "testwave: missing closing parenthesis in '"
709 << flag << "()' directive" << std::endl;
710 return false;
711 }
712 std::string source = value.substr(4, p-4);
713 std::string result, error, hooks;
714 bool pp_result = preprocess_file(filename, source,
715 result, error, hooks, true);
716 if (!pp_result) {
717 std::cerr
718 << "testwave: preprocessing error in '" << flag
719 << "()' directive: " << error << std::endl;
720 return false;
721 }
722
723 // include this text into the extracted information
724 // only if the result is not zero
725 using namespace std; // some system have atoi in namespace std
726 if (0 != atoi(result.c_str())) {
727 std::string thiscontent(value.substr(p+1));
728 if (9 == debuglevel) {
729 std::cerr << "extract_special_information: extracted: "
730 << thiscontent << std::endl;
731 }
732 trim_whitespace(thiscontent);
733 content += thiscontent;
734 }
735 }
736 else {
737 std::string thiscontent(value.substr(3, value.size()-5));
738 if (9 == debuglevel) {
739 std::cerr << "extract_special_information: extracted: "
740 << thiscontent << std::endl;
741 }
742 trim_whitespace(thiscontent);
743 content += thiscontent;
744 }
745 }
746 }
747 else if (T_CPPCOMMENT == id) {
748 std::string value = (*it).get_value().c_str();
749 if (flag == value[2]) {
750 if (value.size() > 3 && '(' == value[3]) {
751 std::size_t p = value.find_first_of(")");
752 if (std::string::npos == p) {
753 std::cerr
754 << "testwave: missing closing parenthesis in '"
755 << flag << "()' directive" << std::endl;
756 return false;
757 }
758 std::string source = value.substr(4, p-4);
759 std::string result, error, hooks;
760 bool pp_result = preprocess_file(filename, source,
761 result, error, hooks, true);
762 if (!pp_result) {
763 std::cerr
764 << "testwave: preprocessing error in '" << flag
765 << "()' directive: " << error << std::endl;
766 return false;
767 }
768
769 // include this text into the extracted information
770 // only if the result is not zero
771 using namespace std; // some system have atoi in namespace std
772 if (0 != atoi(result.c_str())) {
773 std::string thiscontent(value.substr((' ' == value[p+1]) ? p+2 : p+1));
774 if (9 == debuglevel) {
775 std::cerr << "extract_special_information: extracted: "
776 << thiscontent << std::endl;
777 }
778 trim_whitespace(thiscontent);
779 content += thiscontent;
780 }
781 }
782 else {
783 std::string thiscontent(value.substr((' ' == value[3]) ? 4 : 3));
784 if (9 == debuglevel) {
785 std::cerr << "extract_special_information: extracted: "
786 << thiscontent;
787 }
788 trim_whitespace(content);
789 content += thiscontent;
790 }
791 }
792 }
793 }
794 }
795 catch (boost::wave::cpplexer::lexing_exception const &e) {
796 // some lexing error
797 std::cerr
798 << e.file_name() << "(" << e.line_no() << "): "
799 << e.description() << std::endl;
800 return false;
801 }
802
803 if (9 == debuglevel) {
804 std::cerr << "extract_special_information: succeeded extracting special information ('"
805 << flag << "')" << std::endl;
806 }
807 return true;
808 }
809
810 ///////////////////////////////////////////////////////////////////////////////
811 //
812 // Extract the expected output from the given input data
813 //
814 // The expected output has to be provided inside of special comments which
815 // start with a capital 'R'. All such comments are concatenated and returned
816 // through the parameter 'expected'.
817 //
818 ///////////////////////////////////////////////////////////////////////////////
819 inline bool
820 testwave_app::extract_expected_output(std::string const& filename,
821 std::string const& instr, std::string& expected, std::string& expectedhooks)
822 {
823 return extract_special_information(filename, instr, 'R', expected) &&
824 extract_special_information(filename, instr, 'H', expectedhooks);
825 }
826
827 ///////////////////////////////////////////////////////////////////////////////
828 //
829 // Extracts the required preprocessing options from the given input data and
830 // initialises the given Wave context object accordingly.
831 // We allow the same (applicable) options to be used as are valid for the wave
832 // driver executable.
833 //
834 ///////////////////////////////////////////////////////////////////////////////
835 template <typename Context>
836 bool
837 testwave_app::extract_options(std::string const& filename,
838 std::string const& instr, Context& ctx, bool single_line,
839 po::variables_map& vm)
840 {
841 if (9 == debuglevel) {
842 std::cerr << "extract_options: extracting options" << std::endl;
843 }
844
845 // extract the required information from the comments flagged by a
846 // capital 'O'
847 std::string options;
848 if (!extract_special_information(filename, instr, 'O', options))
849 return false;
850
851 try {
852 // parse the configuration information into a program_options_description
853 // object
854 cmd_line_utils::read_config_options(debuglevel, options, desc_options, vm);
855 initialise_options(ctx, vm, single_line);
856 }
857 catch (std::exception const &e) {
858 std::cerr << filename << ": exception caught: " << e.what()
859 << std::endl;
860 return false;
861 }
862
863 if (9 == debuglevel) {
864 std::cerr << "extract_options: succeeded extracting options"
865 << std::endl;
866 }
867
868 return true;
869 }
870
871 template <typename Context>
872 bool
873 testwave_app::initialise_options(Context& ctx, po::variables_map const& vm,
874 bool single_line)
875 {
876 if (9 == debuglevel) {
877 std::cerr << "initialise_options: initializing options" << std::endl;
878 }
879
880 if (vm.count("skipped_token_hooks")) {
881 if (9 == debuglevel) {
882 std::cerr << "initialise_options: option: skipped_token_hooks" << std::endl;
883 }
884 ctx.get_hooks().set_skipped_token_hooks(true);
885 }
886
887 // initialize the given context from the parsed options
888 #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
889 // enable C99 mode, if appropriate (implies variadics)
890 if (vm.count("c99")) {
891 if (9 == debuglevel) {
892 std::cerr << "initialise_options: option: c99" << std::endl;
893 }
894 ctx.set_language(
895 boost::wave::language_support(
896 boost::wave::support_c99
897 | boost::wave::support_option_emit_line_directives
898 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
899 | boost::wave::support_option_include_guard_detection
900 #endif
901 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
902 | boost::wave::support_option_emit_pragma_directives
903 #endif
904 | boost::wave::support_option_insert_whitespace
905 ));
906 }
907 else if (vm.count("variadics")) {
908 // enable variadics and placemarkers, if appropriate
909 if (9 == debuglevel) {
910 std::cerr << "initialise_options: option: variadics" << std::endl;
911 }
912 ctx.set_language(boost::wave::enable_variadics(ctx.get_language()));
913 }
914 #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
915
916 #if BOOST_WAVE_SUPPORT_CPP0X
917 if (vm.count("c++11")) {
918 if (9 == debuglevel) {
919 std::cerr << "initialise_options: option: c++11" << std::endl;
920 }
921 ctx.set_language(
922 boost::wave::language_support(
923 boost::wave::support_cpp0x
924 | boost::wave::support_option_convert_trigraphs
925 | boost::wave::support_option_long_long
926 | boost::wave::support_option_emit_line_directives
927 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
928 | boost::wave::support_option_include_guard_detection
929 #endif
930 #if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
931 | boost::wave::support_option_emit_pragma_directives
932 #endif
933 | boost::wave::support_option_insert_whitespace
934 ));
935 }
936 #endif
937
938 // enable long_long mode, if appropriate
939 if (vm.count("long_long")) {
940 if (9 == debuglevel) {
941 std::cerr << "initialise_options: option: long_long" << std::endl;
942 }
943 ctx.set_language(boost::wave::enable_long_long(ctx.get_language()));
944 }
945
946 // enable preserving comments mode, if appropriate
947 if (vm.count("preserve")) {
948 if (9 == debuglevel) {
949 std::cerr << "initialise_options: option: preserve" << std::endl;
950 }
951 ctx.set_language(
952 boost::wave::enable_preserve_comments(ctx.get_language()));
953 }
954
955 // disable automatic include guard detection
956 if (vm.count("noguard")) {
957 if (9 == debuglevel) {
958 std::cerr << "initialise_options: option: guard" << std::endl;
959 }
960 ctx.set_language(
961 boost::wave::enable_include_guard_detection(ctx.get_language(), false));
962 }
963
964 // enable trigraph conversion
965 if (9 == debuglevel) {
966 std::cerr << "initialise_options: option: convert_trigraphs" << std::endl;
967 }
968 ctx.set_language(boost::wave::enable_convert_trigraphs(ctx.get_language()));
969
970 // enable single_line mode
971 if (single_line) {
972 if (9 == debuglevel) {
973 std::cerr << "initialise_options: option: single_line" << std::endl;
974 }
975 ctx.set_language(boost::wave::enable_single_line(ctx.get_language()));
976 ctx.set_language(boost::wave::enable_emit_line_directives(ctx.get_language(), false));
977 }
978
979 // add include directories to the system include search paths
980 if (vm.count("sysinclude")) {
981 std::vector<std::string> const& syspaths =
982 variables_map_as(vm["sysinclude"], (std::vector<std::string> *)NULL);
983
984 std::vector<std::string>::const_iterator end = syspaths.end();
985 for (std::vector<std::string>::const_iterator cit = syspaths.begin();
986 cit != end; ++cit)
987 {
988 if (9 == debuglevel) {
989 std::cerr << "initialise_options: option: -S" << *cit
990 << std::endl;
991 }
992 ctx.add_sysinclude_path((*cit).c_str());
993 }
994 }
995
996 // add include directories to the user include search paths
997 if (vm.count("include")) {
998 cmd_line_utils::include_paths const &ip =
999 variables_map_as(vm["include"], (cmd_line_utils::include_paths*)NULL);
1000 std::vector<std::string>::const_iterator end = ip.paths.end();
1001
1002 for (std::vector<std::string>::const_iterator cit = ip.paths.begin();
1003 cit != end; ++cit)
1004 {
1005 if (9 == debuglevel) {
1006 std::cerr << "initialise_options: option: -I" << *cit
1007 << std::endl;
1008 }
1009 ctx.add_include_path((*cit).c_str());
1010 }
1011
1012 // if on the command line was given -I- , this has to be propagated
1013 if (ip.seen_separator) {
1014 if (9 == debuglevel) {
1015 std::cerr << "initialise_options: option: -I-" << std::endl;
1016 }
1017 ctx.set_sysinclude_delimiter();
1018 }
1019
1020 // add system include directories to the include path
1021 std::vector<std::string>::const_iterator sysend = ip.syspaths.end();
1022 for (std::vector<std::string>::const_iterator syscit = ip.syspaths.begin();
1023 syscit != sysend; ++syscit)
1024 {
1025 if (9 == debuglevel) {
1026 std::cerr << "initialise_options: option: -S" << *syscit
1027 << std::endl;
1028 }
1029 ctx.add_sysinclude_path((*syscit).c_str());
1030 }
1031 }
1032
1033 // add additional defined macros
1034 if (vm.count("define")) {
1035 std::vector<std::string> const &macros =
1036 variables_map_as(vm["define"], (std::vector<std::string>*)NULL);
1037 std::vector<std::string>::const_iterator end = macros.end();
1038 for (std::vector<std::string>::const_iterator cit = macros.begin();
1039 cit != end; ++cit)
1040 {
1041 if (9 == debuglevel) {
1042 std::cerr << "initialise_options: option: -D" << *cit
1043 << std::endl;
1044 }
1045 ctx.add_macro_definition(*cit, true);
1046 }
1047 }
1048
1049 // add additional predefined macros
1050 if (vm.count("predefine")) {
1051 std::vector<std::string> const &predefmacros =
1052 variables_map_as(vm["predefine"], (std::vector<std::string>*)NULL);
1053 std::vector<std::string>::const_iterator end = predefmacros.end();
1054 for (std::vector<std::string>::const_iterator cit = predefmacros.begin();
1055 cit != end; ++cit)
1056 {
1057 if (9 == debuglevel) {
1058 std::cerr << "initialise_options: option: -P" << *cit
1059 << std::endl;
1060 }
1061 ctx.add_macro_definition(*cit, true);
1062 }
1063 }
1064
1065 // undefine specified macros
1066 if (vm.count("undefine")) {
1067 std::vector<std::string> const &undefmacros =
1068 variables_map_as(vm["undefine"], (std::vector<std::string>*)NULL);
1069 std::vector<std::string>::const_iterator end = undefmacros.end();
1070 for (std::vector<std::string>::const_iterator cit = undefmacros.begin();
1071 cit != end; ++cit)
1072 {
1073 if (9 == debuglevel) {
1074 std::cerr << "initialise_options: option: -U" << *cit
1075 << std::endl;
1076 }
1077 ctx.remove_macro_definition(*cit);
1078 }
1079 }
1080
1081 // maximal include nesting depth
1082 if (vm.count("nesting")) {
1083 int max_depth = variables_map_as(vm["nesting"], (int*)NULL);
1084 if (max_depth < 1 || max_depth > 100000) {
1085 std::cerr << "testwave: bogus maximal include nesting depth: "
1086 << max_depth << std::endl;
1087 return false;
1088 }
1089 else if (9 == debuglevel) {
1090 std::cerr << "initialise_options: option: -n" << max_depth
1091 << std::endl;
1092 }
1093 ctx.set_max_include_nesting_depth(max_depth);
1094 }
1095
1096 if (9 == debuglevel) {
1097 std::cerr << "initialise_options: succeeded to initialize options"
1098 << std::endl;
1099 }
1100 return true;
1101 }
1102
1103 ///////////////////////////////////////////////////////////////////////////////
1104 // construct a SIZEOF macro definition string and predefine this macro
1105 template <typename Context>
1106 inline bool
1107 testwave_app::add_sizeof_definition(Context& ctx, char const *name, int value)
1108 {
1109 BOOST_WAVETEST_OSSTREAM strm;
1110 strm << "__TESTWAVE_SIZEOF_" << name << "__=" << value;
1111
1112 std::string macro(BOOST_WAVETEST_GETSTRING(strm));
1113 if (!ctx.add_macro_definition(macro, true)) {
1114 std::cerr << "testwave: failed to predefine macro: " << macro
1115 << std::endl;
1116 return false;
1117 }
1118 else if (9 == debuglevel) {
1119 std::cerr << "add_sizeof_definition: predefined macro: " << macro
1120 << std::endl;
1121 }
1122 return true;
1123 }
1124
1125 // construct a MIN macro definition string and predefine this macro
1126 template <typename T, typename Context>
1127 inline bool
1128 testwave_app::add_min_definition(Context& ctx, char const *name)
1129 {
1130 BOOST_WAVETEST_OSSTREAM strm;
1131 if (!std::numeric_limits<T>::is_signed) {
1132 strm << "__TESTWAVE_" << name << "_MIN__="
1133 << "0x" << std::hex
1134 << (std::numeric_limits<T>::min)() << "U";
1135 }
1136 else {
1137 strm << "__TESTWAVE_" << name << "_MIN__=( "
1138 << (std::numeric_limits<T>::min)()+1 << "-1)";
1139 }
1140
1141 std::string macro(BOOST_WAVETEST_GETSTRING(strm));
1142 if (!ctx.add_macro_definition(macro, true)) {
1143 std::cerr << "testwave: failed to predefine macro: " << macro
1144 << std::endl;
1145 return false;
1146 }
1147 else if (9 == debuglevel) {
1148 std::cerr << "add_min_definition: predefined macro: " << macro
1149 << std::endl;
1150 }
1151 return true;
1152 }
1153
1154 // construct a MAX macro definition string and predefine this macro
1155 template <typename T, typename Context>
1156 inline bool
1157 testwave_app::add_max_definition(Context& ctx, char const *name)
1158 {
1159 BOOST_WAVETEST_OSSTREAM strm;
1160 if (!std::numeric_limits<T>::is_signed) {
1161 strm << "__TESTWAVE_" << name << "_MAX__="
1162 << "0x" << std::hex
1163 << (std::numeric_limits<T>::max)() << "U";
1164 }
1165 else {
1166 strm << "__TESTWAVE_" << name << "_MAX__="
1167 << (std::numeric_limits<T>::max)();
1168 }
1169
1170 std::string macro(BOOST_WAVETEST_GETSTRING(strm));
1171 if (!ctx.add_macro_definition(macro, true)) {
1172 std::cerr << "testwave: failed to predefine macro: " << macro
1173 << std::endl;
1174 return false;
1175 }
1176 else if (9 == debuglevel) {
1177 std::cerr << "add_max_definition: predefined macro: " << macro
1178 << std::endl;
1179 }
1180 return true;
1181 }
1182
1183 // Predefine __TESTWAVE_HAS_STRICT_LEXER__
1184 template <typename Context>
1185 inline bool
1186 testwave_app::add_strict_lexer_definition(Context& ctx)
1187 {
1188 std::string macro("__TESTWAVE_HAS_STRICT_LEXER__=1");
1189 if (!ctx.add_macro_definition(macro, true)) {
1190 std::cerr << "testwave: failed to predefine macro: " << macro
1191 << std::endl;
1192 return false;
1193 }
1194 else if (9 == debuglevel) {
1195 std::cerr << "add_strict_lexer_definition: predefined macro: " << macro
1196 << std::endl;
1197 }
1198 return true;
1199 }
1200
1201 #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS
1202 // Predefine __TESTWAVE_SUPPORT_MS_EXTENSIONS__
1203 template <typename Context>
1204 inline bool
1205 testwave_app::add_support_ms_extensions_definition(Context& ctx)
1206 {
1207 std::string macro("__TESTWAVE_SUPPORT_MS_EXTENSIONS__=1");
1208 if (!ctx.add_macro_definition(macro, true)) {
1209 std::cerr << "testwave: failed to predefine macro: " << macro
1210 << std::endl;
1211 return false;
1212 }
1213 else if (9 == debuglevel) {
1214 std::cerr << "add_support_ms_extensions_definition: predefined macro: "
1215 << macro
1216 << std::endl;
1217 }
1218 return true;
1219 }
1220 #endif
1221
1222 ///////////////////////////////////////////////////////////////////////////////
1223 //
1224 // Add special predefined macros to the context object.
1225 //
1226 // This adds a lot of macros to the test environment, which allows to adjust
1227 // the test cases for different platforms.
1228 //
1229 ///////////////////////////////////////////////////////////////////////////////
1230 template <typename Context>
1231 bool
1232 testwave_app::add_predefined_macros(Context& ctx)
1233 {
1234 // add the __TESTWAVE_SIZEOF_<type>__ macros
1235 if (!add_sizeof_definition(ctx, "CHAR", sizeof(char)) ||
1236 !add_sizeof_definition(ctx, "SHORT", sizeof(short)) ||
1237 !add_sizeof_definition(ctx, "INT", sizeof(int)) ||
1238 #if defined(BOOST_HAS_LONG_LONG)
1239 !add_sizeof_definition(ctx, "LONGLONG", sizeof(boost::long_long_type)) ||
1240 #endif
1241 !add_sizeof_definition(ctx, "LONG", sizeof(long)))
1242 {
1243 std::cerr << "testwave: failed to add a predefined macro (SIZEOF)."
1244 << std::endl;
1245 return false;
1246 }
1247
1248 // add the __TESTWAVE_<type>_MIN__ macros
1249 if (/*!add_min_definition<char>(ctx, "CHAR") ||*/
1250 /*!add_min_definition<unsigned char>(ctx, "UCHAR") ||*/
1251 !add_min_definition<short>(ctx, "SHORT") ||
1252 !add_min_definition<unsigned short>(ctx, "USHORT") ||
1253 !add_min_definition<int>(ctx, "INT") ||
1254 !add_min_definition<unsigned int>(ctx, "UINT") ||
1255 #if defined(BOOST_HAS_LONG_LONG)
1256 !add_min_definition<boost::long_long_type>(ctx, "LONGLONG") ||
1257 !add_min_definition<boost::ulong_long_type>(ctx, "ULONGLONG") ||
1258 #endif
1259 !add_min_definition<long>(ctx, "LONG") ||
1260 !add_min_definition<unsigned long>(ctx, "ULONG"))
1261 {
1262 std::cerr << "testwave: failed to add a predefined macro (MIN)."
1263 << std::endl;
1264 }
1265
1266 // add the __TESTWAVE_<type>_MAX__ macros
1267 if (/*!add_max_definition<char>(ctx, "CHAR") ||*/
1268 /*!add_max_definition<unsigned char>(ctx, "UCHAR") ||*/
1269 !add_max_definition<short>(ctx, "SHORT") ||
1270 !add_max_definition<unsigned short>(ctx, "USHORT") ||
1271 !add_max_definition<int>(ctx, "INT") ||
1272 !add_max_definition<unsigned int>(ctx, "UINT") ||
1273 #if defined(BOOST_HAS_LONG_LONG)
1274 !add_max_definition<boost::long_long_type>(ctx, "LONGLONG") ||
1275 !add_max_definition<boost::ulong_long_type>(ctx, "ULONGLONG") ||
1276 #endif
1277 !add_max_definition<long>(ctx, "LONG") ||
1278 !add_max_definition<unsigned long>(ctx, "ULONG"))
1279 {
1280 std::cerr << "testwave: failed to add a predefined macro (MAX)."
1281 << std::endl;
1282 }
1283
1284 #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS
1285 // Predefine __TESTWAVE_SUPPORT_MS_EXTENSIONS__
1286 if (!add_support_ms_extensions_definition(ctx))
1287 {
1288 std::cerr << "testwave: failed to add a predefined macro "
1289 "(__TESTWAVE_SUPPORT_MS_EXTENSIONS__)."
1290 << std::endl;
1291 }
1292 #endif
1293
1294 #if BOOST_WAVE_USE_STRICT_LEXER != 0
1295 return add_strict_lexer_definition(ctx);
1296 #else
1297 return true;
1298 #endif
1299 }
1300
1301 ///////////////////////////////////////////////////////////////////////////////
1302 //
1303 // Preprocess the given input data and return the generated output through
1304 // the parameter 'result'.
1305 //
1306 ///////////////////////////////////////////////////////////////////////////////
1307 bool
1308 testwave_app::preprocess_file(std::string filename, std::string const& instr,
1309 std::string& result, std::string& error, std::string& hooks,
1310 bool single_line)
1311 {
1312 // create the wave::context object and initialize it from the file to
1313 // preprocess (may contain options inside of special comments)
1314 typedef boost::wave::cpplexer::lex_token<> token_type;
1315 typedef boost::wave::cpplexer::lex_iterator<token_type> lexer_type;
1316 typedef boost::wave::context<
1317 std::string::const_iterator, lexer_type,
1318 boost::wave::iteration_context_policies::load_file_to_string,
1319 collect_hooks_information<token_type> >
1320 context_type;
1321
1322 if (9 == debuglevel) {
1323 std::cerr << "preprocess_file: preprocessing input file: " << filename
1324 << std::endl;
1325 }
1326
1327 try {
1328 // create preprocessing context
1329 context_type ctx(instr.begin(), instr.end(), filename.c_str(),
1330 collect_hooks_information<token_type>(hooks));
1331
1332 // initialize the context from the options given on the command line
1333 if (!initialise_options(ctx, global_vm, single_line))
1334 return false;
1335
1336 // extract the options from the input data and initialize the context
1337 boost::program_options::variables_map local_vm;
1338 if (!extract_options(filename, instr, ctx, single_line, local_vm))
1339 return false;
1340
1341 // add special predefined macros
1342 if (!add_predefined_macros(ctx))
1343 return false;
1344
1345 // preprocess the input, loop over all generated tokens collecting the
1346 // generated text
1347 context_type::iterator_type it = ctx.begin();
1348 context_type::iterator_type end = ctx.end();
1349
1350 if (local_vm.count("forceinclude")) {
1351 // add the filenames to force as include files in _reverse_ order
1352 // the second parameter 'is_last' of the force_include function should
1353 // be set to true for the last (first given) file.
1354 std::vector<std::string> const &force =
1355 local_vm["forceinclude"].as<std::vector<std::string> >();
1356 std::vector<std::string>::const_reverse_iterator rend = force.rend();
1357 for (std::vector<std::string>::const_reverse_iterator cit = force.rbegin();
1358 cit != rend; /**/)
1359 {
1360 std::string forceinclude(*cit);
1361 if (9 == debuglevel) {
1362 std::cerr << "preprocess_file: option: forceinclude ("
1363 << forceinclude << ")" << std::endl;
1364 }
1365 it.force_include(forceinclude.c_str(), ++cit == rend);
1366 }
1367 }
1368
1369 // perform actual preprocessing
1370 for (/**/; it != end; ++it)
1371 {
1372 using namespace boost::wave;
1373
1374 if (T_PP_LINE == token_id(*it)) {
1375 // special handling of the whole #line directive is required to
1376 // allow correct file name matching
1377 if (!handle_line_directive(it, end, result))
1378 return false; // unexpected eof
1379 }
1380 else {
1381 // add the value of the current token
1382 result = result + (*it).get_value().c_str();
1383 }
1384 }
1385 error.clear();
1386 }
1387 catch (boost::wave::cpplexer::lexing_exception const& e) {
1388 // some lexer error
1389 BOOST_WAVETEST_OSSTREAM strm;
1390 std::string filename = e.file_name();
1391 strm
1392 << handle_filepath(filename) << "(" << e.line_no() << "): "
1393 << e.description() << std::endl;
1394
1395 error = BOOST_WAVETEST_GETSTRING(strm);
1396 return false;
1397 }
1398 catch (boost::wave::cpp_exception const& e) {
1399 // some preprocessing error
1400 BOOST_WAVETEST_OSSTREAM strm;
1401 std::string filename = e.file_name();
1402 strm
1403 << handle_filepath(filename) << "(" << e.line_no() << "): "
1404 << e.description() << std::endl;
1405
1406 error = BOOST_WAVETEST_GETSTRING(strm);
1407 return false;
1408 }
1409
1410 if (9 == debuglevel) {
1411 std::cerr << "preprocess_file: succeeded to preprocess input file: "
1412 << filename << std::endl;
1413 }
1414
1415 return true;
1416 }
1417