⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testwave_app.cpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*=============================================================================    Boost.Wave: A Standard compliant C++ preprocessor library    http://www.boost.org/    Copyright (c) 2001-2008 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)=============================================================================*/// system headers#include <string>#include <iostream>#include <vector>// include boost#include <boost/config.hpp>#include <boost/throw_exception.hpp>#include <boost/filesystem/path.hpp>#include <boost/filesystem/operations.hpp>#include <boost/detail/workaround.hpp>//  include Wave // always use new hooks#define BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS 0#include <boost/wave.hpp>//  include the lexer related stuff#include <boost/wave/cpplexer/cpp_lex_token.hpp>      // token type#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>   // lexer type//  test application related headers#include "cmd_line_utils.hpp"#include "testwave_app.hpp"#include "collect_hooks_information.hpp"namespace po = boost::program_options;namespace fs = boost::filesystem;///////////////////////////////////////////////////////////////////////////////// testwave version definitions#define TESTWAVE_VERSION_MAJOR           0#define TESTWAVE_VERSION_MINOR           5#define TESTWAVE_VERSION_SUBMINOR        0namespace {    ///////////////////////////////////////////////////////////////////////////    template <typename Iterator>    inline bool     handle_next_token(Iterator &it, Iterator const& end,         std::string &result)    {        typedef typename Iterator::value_type token_type;                token_type tok = *it++;            result = result + tok.get_value().c_str();        return (it == end) ? false : true;    }    ///////////////////////////////////////////////////////////////////////////    template <typename String>    String const& handle_quoted_filepath(String &name)    {        using boost::wave::util::impl::unescape_lit;                String unesc_name = unescape_lit(name.substr(1, name.size()-2));        fs::path p (unesc_name.c_str(), fs::native);        name = String("\"") + p.leaf().c_str() + String("\"");        return name;    }    ///////////////////////////////////////////////////////////////////////////    template <typename Iterator>    bool handle_line_directive(Iterator &it, Iterator const& end,         std::string &result)    {        typedef typename Iterator::value_type token_type;        typedef typename token_type::string_type string_type;                if (!handle_next_token(it, end, result) ||  // #line            !handle_next_token(it, end, result) ||  // whitespace            !handle_next_token(it, end, result) ||  // number            !handle_next_token(it, end, result))    // whitespace        {            return false;        }                using boost::wave::util::impl::unescape_lit;                token_type filename = *it;        string_type name = filename.get_value();        handle_quoted_filepath(name);        result = result + name.c_str();        return true;    }    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)            boost::throw_exception(boost::bad_any_cast());        return *r;#else        return v.as<T>();#endif    }}///////////////////////////////////////////////////////////////////////////////  This function compares the real result and the expected one but first //  replaces all occurrences in the expected result of //      $E: to the result of preprocessing the given expression//      $F: to the passed full filepath //      $P: to the full path//      $B: to the full path (same as $P, but using forward slash '/' on Windows)//      $V: to the current Boost version number/////////////////////////////////////////////////////////////////////////////bool testwave_app::got_expected_result(std::string const& filename,     std::string const& result, std::string& expected){    using boost::wave::util::impl::escape_lit;        std::string full_result;    std::string::size_type pos = 0;    std::string::size_type pos1 = expected.find_first_of("$");        if (pos1 != std::string::npos) {        do {            switch(expected[pos1+1]) {            case 'E':       // preprocess the given token sequence                {                    if ('(' == expected[pos1+2]) {                        std::size_t p = expected.find_first_of(")", pos1+1);                        if (std::string::npos == p) {                            std::cerr                                 << "testwave: unmatched parenthesis in $E"                                    " directive" << std::endl;                            return false;                        }                        std::string source = expected.substr(pos1+3, p-pos1-3);                        std::string result, error, hooks;                        bool pp_result = preprocess_file(filename, source,                             result, error, hooks, true);                        if (!pp_result) {                            std::cerr                                 << "testwave: preprocessing error in $E directive: "                                 << error << std::endl;                            return false;                        }                        full_result = full_result +                             expected.substr(pos, pos1-pos) + result;                        pos1 = expected.find_first_of ("$",                             pos = pos1 + 4 + source.size());                    }                }                break;                            case 'F':       // insert base file name                full_result = full_result +                     expected.substr(pos, pos1-pos) + escape_lit(filename);                pos1 = expected.find_first_of ("$", pos = pos1 + 2);                break;            case 'P':       // insert full path            case 'B':       // same as 'P', but forward slashs on Windows                {                    fs::path fullpath (                        fs::complete(                            fs::path(filename, fs::native), fs::current_path())                        );                                            if ('(' == expected[pos1+2]) {                    // the $P(basename) syntax is used                        std::size_t p = expected.find_first_of(")", pos1+1);                        if (std::string::npos == p) {                            std::cerr                                 << "testwave: unmatched parenthesis in $P"                                    " directive" << std::endl;                            return false;                        }                        std::string base = expected.substr(pos1+3, p-pos1-3);                        fullpath = fullpath.branch_path() /                             fs::path(base, fs::native);                        full_result += expected.substr(pos, pos1-pos);                        if ('P' == expected[pos1+1]) {                            full_result +=                                 escape_lit(fullpath.normalize().native_file_string());                        }                        else {                            full_result +=                                 escape_lit(fullpath.normalize().string());                        }                        pos1 = expected.find_first_of ("$",                             pos = pos1 + 4 + base.size());                    }                    else {                    // the $P is used on its own                        full_result += expected.substr(pos, pos1-pos);                        if ('P' == expected[pos1+1]) {                            full_result +=                                 escape_lit(fullpath.native_file_string());                        }                        else {                            full_result +=                                 escape_lit(fullpath.string());                        }                        pos1 = expected.find_first_of ("$", pos = pos1 + 2);                    }                }                break;                            case 'V':       // insert Boost version                full_result = full_result +                     expected.substr(pos, pos1-pos) + BOOST_LIB_VERSION;                pos1 = expected.find_first_of ("$", pos = pos1 + 2);                break;                            default:                full_result = full_result +                    expected.substr(pos, pos1-pos);                pos1 = expected.find_first_of ("$", (pos = pos1) + 1);                break;            }        } while(pos1 != std::string::npos);        full_result += expected.substr(pos);    }    else {        full_result = expected;    }        expected = full_result;    return full_result == result;}///////////////////////////////////////////////////////////////////////////////testwave_app::testwave_app(po::variables_map const& vm):   debuglevel(1), desc_options("Preprocessor configuration options"),     global_vm(vm){    desc_options.add_options()        ("include,I", po::value<cmd_line_utils::include_paths>()->composing(),             "specify an additional include directory")        ("sysinclude,S", po::value<std::vector<std::string> >()->composing(),             "specify an additional system include directory")        ("define,D", po::value<std::vector<std::string> >()->composing(),             "specify a macro to define (as macro[=[value]])")        ("predefine,P", po::value<std::vector<std::string> >()->composing(),             "specify a macro to predefine (as macro[=[value]])")        ("undefine,U", po::value<std::vector<std::string> >()->composing(),             "specify a macro to undefine")        ("nesting,n", po::value<int>(),             "specify a new maximal include nesting depth")        ("long_long", "enable long long support in C++ mode")        ("preserve", "preserve comments")#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0        ("variadics", "enable certain C99 extensions in C++ mode")        ("c99", "enable C99 mode (implies --variadics)")#endif #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0        ("noguard,G", "disable include guard detection")#endif    ;}///////////////////////////////////////////////////////////////////////////////////  Test the given file (i.e. preprocess the file and compare the result //  against the embedded 'R' comments, if an error occurs compare the error//  message against the given 'E' comments, if no error occurred, compare the//  generated hooks result against the given 'H' comments)./////////////////////////////////////////////////////////////////////////////////bool testwave_app::test_a_file(std::string filename){// read the input file into a string    std::string instr;    if (!read_file(filename, instr))         return false;     // error was reported already    bool test_hooks = true;    if (global_vm.count("hooks"))        test_hooks = variables_map_as(global_vm["hooks"], (bool *)NULL);    // extract expected output, preprocess the data and compare results    std::string expected, expected_hooks;    if (extract_expected_output(filename, instr, expected, expected_hooks)) {        bool retval = true;   // assume success        bool printed_result = false;        std::string result, error, hooks;        bool pp_result = preprocess_file(filename, instr, result, error, hooks);        if (pp_result || !result.empty()) {        // did we expect an error?            std::string expected_error;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -