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

📄 testwave_app.cpp

📁 C++的一个好库。。。现在很流行
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*=============================================================================
    Boost.Wave: A Standard compliant 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)
=============================================================================*/

// system headers
#include <string>
#include <iostream>
#include <vector>

// include boost
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/detail/workaround.hpp>

//  include Wave 
#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

//  this header includes the cpplexer::new_lexer_gen template used for the 
//  explicit template specialisation below
#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>

//  test application related headers
#include "cmd_line_utils.hpp"
#include "testwave_app.hpp"

namespace po = boost::program_options;
namespace fs = boost::filesystem;

///////////////////////////////////////////////////////////////////////////////
// testwave version definitions
#define TESTWAVE_VERSION_MAJOR           0
#define TESTWAVE_VERSION_MINOR           3
#define TESTWAVE_VERSION_SUBMINOR        0

///////////////////////////////////////////////////////////////////////////////
// workaround for missing ostringstream
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#define TESTWAVE_OSSTREAM std::ostrstream
std::string TESTWAVE_GETSTRING(std::ostrstream& ss)
{
    ss << ends;
    std::string rval = ss.str();
    ss.freeze(false);
    return rval;
}
#else
#include <sstream>
#define TESTWAVE_GETSTRING(ss) ss.str()
#define TESTWAVE_OSSTREAM std::ostringstream
#endif

namespace {

    ///////////////////////////////////////////////////////////////////////////
    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 String>
    String const& handle_filepath(String &name)
    {
        using boost::wave::util::impl::unescape_lit;
        
        String unesc_name = unescape_lit(name);
        fs::path p (unesc_name.c_str(), fs::native);

        name = p.leaf().c_str();
        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;
    }
}

///////////////////////////////////////////////////////////////////////////
//
//  This function compares the real result and the expected one but first 
//  replaces all occurences 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
//      $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;
                        bool pp_result = preprocess_file(filename, source, result, error);
                        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
                {
                    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 = full_result + 
                            expected.substr(pos, pos1-pos) + 
                            escape_lit(fullpath.normalize().native_file_string());
                        pos1 = expected.find_first_of ("$", 
                            pos = pos1 + 4 + base.size());
                    }
                    else {
                    // the $P is used on its own
                        full_result = full_result + 
                            expected.substr(pos, pos1-pos) + 
                            escape_lit(fullpath.native_file_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 
    ;
}

///////////////////////////////////////////////////////////////////////////////
//
//  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).
//
///////////////////////////////////////////////////////////////////////////////
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

// extract expected output, preprocess the data and compare results
    std::string expected;
    if (extract_expected_output(filename, instr, expected)) {
        bool retval = true;   // assume success
        std::string result, error;
        bool pp_result = preprocess_file(filename, instr, result, error);
        if (pp_result || !result.empty()) {
        // did we expect an error?
            std::string expected_error;
            if (!extract_special_information(filename, instr, 'E', expected_error))
                return false;

            if (!expected_error.empty() && 
                !got_expected_result(filename, error, expected_error))
            {
            // we expected an error but got none (or a different one)
                if (debuglevel > 2) {
                    std::cerr 
                        << filename << ": failed" << std::endl
                        << "result: " << std::endl << result << std::endl;

                    if (!error.empty()) {
                        std::cerr << "expected result: " << std::endl 
                                  << expected << std::endl;
                    }
                    if (!expected_error.empty()) {
                        std::cerr << "expected error: " << std::endl 
                                  << expected_error << std::endl;
                    }
                }
                else if (debuglevel > 1) {
                    std::cerr << filename << ": failed" << std::endl;
                }
                retval = false;
            }
            else if (!got_expected_result(filename, result, expected)) {
            //  no preprocessing error encountered
                if (debuglevel > 2) {
                    std::cerr 
                        << filename << ": failed" << std::endl
                        << "result: " << std::endl << result << std::endl
                        << "expected: " << std::endl << expected << std::endl;
                }
                else if (debuglevel > 1) {
                    std::cerr << filename << ": failed" << std::endl;
                }
                retval = false;
            }
            else if (debuglevel > 4) {
                std::cerr 
                    << filename << ": succeeded" << std::endl
                    << "result: " << std::endl << result << std::endl;
            }
            else if (debuglevel > 3) {
                std::cerr << filename << ": succeeded" << std::endl;
            }
        }
        
        if (!pp_result) {
        //  there was a preprocessing error, was it expected?
            std::string expected_error;
            if (!extract_special_information(filename, instr, 'E', expected_error))
                return false;
                
            if (!got_expected_result(filename, error, expected_error)) {
            // the error was unexpected
                if (debuglevel > 2) {
                    std::cerr 
                        << filename << ": failed" << std::endl;

                    if (!expected_error.empty()) {
                        std::cerr 
                            << "result: " << std::endl << error << std::endl
                            << "expected error: " << std::endl
                            << expected_error << std::endl;
                    }
                    else {
                        std::cerr << "unexpected error: " << error << std::endl;
                    }
                }
                else if (debuglevel > 1) {
                    std::cerr << filename << ": failed" << std::endl;
                }

⌨️ 快捷键说明

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