📄 testwave_app.cpp
字号:
retval = false;
}
else if (debuglevel > 4) {
std::cerr
<< filename << ": succeeded" << std::endl
<< "result: " << std::endl << error << std::endl;
}
else if (debuglevel > 3) {
// caught the expected error message
std::cerr << filename << ": succeeded" << std::endl;
}
}
return retval;
}
else {
std::cerr
<< filename << ": no information about expected results found"
<< std::endl;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
//
// print the current version of this program
//
///////////////////////////////////////////////////////////////////////////////
int
testwave_app::print_version()
{
// get time of last compilation of this file
boost::wave::util::time_conversion_helper compilation_time(__DATE__ " " __TIME__);
// calculate the number of days since Feb 12 2005
// (the day the testwave project was started)
std::tm first_day;
using namespace std; // some platforms have memset in namespace std
memset (&first_day, 0, sizeof(std::tm));
first_day.tm_mon = 1; // Feb
first_day.tm_mday = 12; // 12
first_day.tm_year = 105; // 2005
long seconds = long(std::difftime(compilation_time.get_time(),
std::mktime(&first_day)));
std::cout
<< TESTWAVE_VERSION_MAJOR << '.'
<< TESTWAVE_VERSION_MINOR << '.'
<< TESTWAVE_VERSION_SUBMINOR << '.'
<< seconds/(3600*24) // get number of days from seconds
<< std::endl;
return 0; // exit app
}
///////////////////////////////////////////////////////////////////////////////
//
// print the copyright statement
//
///////////////////////////////////////////////////////////////////////////////
int
testwave_app::print_copyright()
{
char const *copyright[] = {
"",
"Testwave: A test driver for the Boost.Wave C++ preprocessor library",
"http://www.boost.org/",
"",
"Copyright (c) 2001-2005 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)",
0
};
for (int i = 0; 0 != copyright[i]; ++i)
std::cout << copyright[i] << std::endl;
return 0; // exit app
}
///////////////////////////////////////////////////////////////////////////////
//
// Read the given file into a string
//
///////////////////////////////////////////////////////////////////////////////
bool
testwave_app::read_file(std::string const& filename, std::string& instr)
{
// open the given file and report error, if appropriate
std::ifstream instream(filename.c_str());
if (!instream.is_open()) {
std::cerr << "testwave: could not open input file: "
<< filename << std::endl;
return false;
}
else if (9 == debuglevel) {
std::cerr << "read_file: succeeded to open input file: "
<< filename << std::endl;
}
instream.unsetf(std::ios::skipws);
// read the input file into a string
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
// this is known to be very slow for large files on some systems
std::copy (std::istream_iterator<char>(instream),
std::istream_iterator<char>(),
std::inserter(instr, instr.end()));
#else
instr = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
std::istreambuf_iterator<char>());
#endif
if (9 == debuglevel) {
std::cerr << "read_file: succeeded to read input file: "
<< filename << std::endl;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// This explicit template instantiation is needed for the function
// extract_expected_output below, which needs the lexer to be instantiated
// with a std::string::const_iterator template parameter.
//
///////////////////////////////////////////////////////////////////////////////
template
struct boost::wave::cpplexer::new_lexer_gen<std::string::const_iterator>;
namespace {
std::string const& trim_whitespace(std::string& value)
{
std::string::size_type first = value.find_first_not_of(" \t");
std::string::size_type last = std::string::npos;
if (std::string::npos == first)
value.clear();
else {
last = value.find_last_not_of(" \t")+1;
assert(std::string::npos != last);
value = value.substr(first, last-first);
}
return value;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Extract special information from comments marked with the given letter
//
///////////////////////////////////////////////////////////////////////////////
bool
testwave_app::extract_special_information(std::string const& filename,
std::string const& instr, char flag, std::string& content)
{
if (9 == debuglevel) {
std::cerr << "extract_special_information: extracting special information ('"
<< flag << "') from input file: " << filename << std::endl;
}
// tokenize the input data into C++ tokens using the C++ lexer
typedef boost::wave::cpplexer::lex_token<> token_type;
typedef boost::wave::cpplexer::lex_iterator<token_type> lexer_type;
typedef token_type::position_type position_type;
boost::wave::language_support const lang_opts =
(boost::wave::language_support)(
boost::wave::support_variadics | boost::wave::support_long_long |
boost::wave::support_option_no_character_validation |
boost::wave::support_option_convert_trigraphs);
position_type pos(filename.c_str());
lexer_type it = lexer_type(instr.begin(), instr.end(), pos, lang_opts);
lexer_type end = lexer_type();
try {
// look for C or C++ comments starting with the special character
for (/**/; it != end; ++it) {
using namespace boost::wave;
token_id id = token_id(*it);
if (T_CCOMMENT == id) {
std::string value = (*it).get_value().c_str();
if (flag == value[2]) {
std::string thiscontent(value.substr(3, value.size()-5));
if (9 == debuglevel) {
std::cerr << "extract_special_information: extracted: "
<< thiscontent << std::endl;
}
trim_whitespace(thiscontent);
content += thiscontent;
}
}
else if (T_CPPCOMMENT == id) {
std::string value = (*it).get_value().c_str();
if (flag == value[2]) {
std::string thiscontent(value.substr((' ' == value[3]) ? 4 : 3));
if (9 == debuglevel) {
std::cerr << "extract_special_information: extracted: "
<< thiscontent;
}
trim_whitespace(content);
content += thiscontent;
}
}
}
}
catch (boost::wave::cpplexer::lexing_exception const &e) {
// some lexing error
std::cerr
<< e.file_name() << "(" << e.line_no() << "): "
<< e.description() << std::endl;
return false;
}
if (9 == debuglevel) {
std::cerr << "extract_special_information: succeeded extracting special information ('"
<< flag << "')" << std::endl;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Extract the expected output from the given input data
//
// The expected output has to be provided inside of special comments which
// start with a capital 'R'. All such comments are concatenated and returned
// through the parameter 'expected'.
//
///////////////////////////////////////////////////////////////////////////////
inline bool
testwave_app::extract_expected_output(std::string const& filename,
std::string const& instr, std::string& expected)
{
return extract_special_information(filename, instr, 'R', expected);
}
///////////////////////////////////////////////////////////////////////////////
//
// Extracts the required preprocessing options from the given input data and
// initialises the given Wave context object accordingly.
// We allow the same (applicable) options to be used as are valid for the wave
// driver executable.
//
///////////////////////////////////////////////////////////////////////////////
template <typename Context>
bool
testwave_app::extract_options(std::string const& filename,
std::string const& instr, Context& ctx)
{
if (9 == debuglevel) {
std::cerr << "extract_options: extracting options" << std::endl;
}
// extract the required information from the comments flagged by a
// capital 'O'
std::string options;
if (!extract_special_information(filename, instr, 'O', options))
return false;
try {
// parse the configuration information into a program_options_description
// object
po::variables_map local_vm;
cmd_line_utils::read_config_options(debuglevel, options, desc_options, local_vm);
initialise_options(ctx, local_vm);
}
catch (std::exception const &e) {
std::cerr << filename << ": exception caught: " << e.what()
<< std::endl;
return false;
}
if (9 == debuglevel) {
std::cerr << "extract_options: succeeded extracting options"
<< std::endl;
}
return true;
}
namespace {
template <typename T>
inline T const&
variables_map_as(po::variable_value const& v, T*)
{
#if (__GNUC__ == 3 && (__GNUC_MINOR__ == 2 || __GNUC_MINOR__ == 3)) || \
BOOST_WORKAROUND(__MWERKS__, < 0x3200)
// gcc 3.2.x and 3.3.x choke on vm[...].as<...>()
// CW 8.3 has problems with the v.as<T>() below
T const* r = boost::any_cast<T>(&v.value());
if (!r)
throw boost::bad_any_cast();
return *r;
#else
return v.as<T>();
#endif
}
}
template <typename Context>
bool
testwave_app::initialise_options(Context& ctx, po::variables_map const& vm)
{
if (9 == debuglevel) {
std::cerr << "initialise_options: initialising options" << std::endl;
}
// initialise the given context from the parsed options
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
// enable C99 mode, if appropriate (implies variadics)
if (vm.count("c99")) {
if (9 == debuglevel) {
std::cerr << "initialise_options: option: c99" << std::endl;
}
ctx.set_language(boost::wave::support_c99);
}
else if (vm.count("variadics")) {
// enable variadics and placemarkers, if appropriate
if (9 == debuglevel) {
std::cerr << "initialise_options: option: variadics" << std::endl;
}
ctx.set_language(boost::wave::enable_variadics(ctx.get_language()));
}
#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
// enable long_long mode, if appropriate
if (vm.count("long_long")) {
if (9 == debuglevel) {
std::cerr << "initialise_options: option: long_long" << std::endl;
}
ctx.set_language(boost::wave::enable_long_long(ctx.get_language()));
}
// enable preserving comments mode, if appropriate
if (vm.count("preserve")) {
if (9 == debuglevel) {
std::cerr << "initialise_options: option: preserve" << std::endl;
}
ctx.set_language(
boost::wave::enable_preserve_comments(ctx.get_language()));
}
// enable trigraph conversion
ctx.set_language(boost::wave::set_support_options(ctx.get_language(),
(boost::wave::language_support)(
boost::wave::get_support_options(ctx.get_language()) |
boost::wave::support_option_convert_trigraphs |
boost::wave::support_option_single_line)
)
);
// add include directories to the system include search paths
if (vm.count("sysinclude")) {
std::vector<std::string> const& syspaths =
variables_map_as(vm["sysinclude"], (std::vector<std::string> *)NULL);
std::vector<std::string>::const_iterator end = syspaths.end();
for (std::vector<std::string>::const_iterator cit = syspaths.begin();
cit != end; ++cit)
{
if (9 == debuglevel) {
std::cerr << "initialise_options: option: -S" << *cit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -