Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Wave: a Standard conformant C++ preprocessor library

, 10 Jan 2004
Describes a free and fully Standard conformant C++ preprocessor library
wave_preprocessor_demo.zip
wave_preprocessor_demo1.zip
wave_preprocessor_src.zip
wave
doc
theme
bkd.gif
bkd2.gif
bullet.gif
l_arr.gif
l_arr_disabled.gif
r_arr.gif
r_arr_disabled.gif
uc.gif
u_arr.gif
wave.gif
test
boost-build.jam
cpp_tokens
Jamfile.v2
list_includes
project-root.jam
wave
Jamfile
Jamfile.v2
runtests.sh
test_files
wave
cpplexer
re2clex
cpp.re
test
lextest.in
lextest.output
run_tests.sh
test_lexer.in
test_lexer.output
slex
test
lextest.in
lextest.re2c.output
lextest.slex.output
run_tests.sh
grammars
idllexer
re2clex
idl.re
util
wave_preprocessor_src1.zip
bkd.gif
bkd2.gif
bullet.gif
l_arr.gif
l_arr_disabled.gif
r_arr.gif
r_arr_disabled.gif
u_arr.gif
uc.gif
wave.gif
boost-build.jam
Jamfile.v2
project-root.jam
Jamfile
Jamfile.v2
runtests.sh
cpp.re
lextest.in
lextest.output
run_tests.sh
test_lexer.in
test_lexer.output
lextest.in
lextest.re2c.output
lextest.slex.output
run_tests.sh
/*=============================================================================
    Wave: A Standard compliant C++ preprocessor

    Copyright (c) 2001-2003 Hartmut Kaiser
    http://spirit.sourceforge.net/

    Permission to copy, use, modify, sell and distribute this software
    is granted provided this copyright notice appears in all copies.
    This software is provided "as is" without express or implied
    warranty, and with no claim as to its suitability for any purpose.

    See Copyright.txt for full copyright notices and acknowledgements.
=============================================================================*/

#if !defined(CPP_EXCEPTIONS_HPP_5190E447_A781_4521_A275_5134FF9917D7_INCLUDED)
#define CPP_EXCEPTIONS_HPP_5190E447_A781_4521_A275_5134FF9917D7_INCLUDED

#include <exception>
#include <string>

#include <boost/assert.hpp>
#include <boost/config.hpp>

#include "wave/cpplexer/macro_scoping_tokens.hpp"

///////////////////////////////////////////////////////////////////////////////
// helper macro for throwing exceptions
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#define CPP_THROW(cls, code, msg, act_pos) \
    { \
    using namespace wave; \
    std::strstream stream; \
        stream << cls::severity_text(cls::code) << ": " \
        << cls::error_text(cls::code); \
    if ((msg)[0] != 0) stream << ": " << (msg); \
    stream << std::ends; \
    std::string throwmsg = stream.str(); stream.freeze(false); \
    throw cls(throwmsg.c_str(), cls::code, (act_pos).get_line(), \
        (act_pos).get_column(), (act_pos).get_file().c_str()); \
    } \
    /**/
#else
#include <sstream>
#define CPP_THROW(cls, code, msg, act_pos) \
    { \
    using namespace wave; \
    std::stringstream stream; \
        stream << cls::severity_text(cls::code) << ": " \
        << cls::error_text(cls::code); \
    if ((msg)[0] != 0) stream << ": " << (msg); \
    stream << std::ends; \
    throw cls(stream.str().c_str(), cls::code, (act_pos).get_line(), \
        (act_pos).get_column(), (act_pos).get_file().c_str()); \
    } \
    /**/
#endif // BOOST_NO_STRINGSTREAM

///////////////////////////////////////////////////////////////////////////////
namespace wave {

///////////////////////////////////////////////////////////////////////////////
// exception severity
namespace util {

    enum severity {
        severity_remark = 0,
        severity_warning,
        severity_error,
        severity_fatal,
        severity_commandline_error
    };
    
    inline char const *
    get_severity(severity level) 
    {
        static char const *severity_text[] = 
        {
            "remark",           // severity_remark
            "warning",          // severity_warning
            "error",            // severity_error
            "fatal error",      // severity_fatal
            "command line error"    // severity_commandline_error
        };
        BOOST_ASSERT(severity_remark <= level && 
            level <= severity_commandline_error);
        return severity_text[level];
    }
}

///////////////////////////////////////////////////////////////////////////////
//  cpp_exception, the base class for all specific C preprocessor exceptions 
class cpp_exception
:   public std::exception
{
public:
    cpp_exception(int line_, int column_, char const *filename_) throw() 
    :   line(line_), column(column_) 
    {
        unsigned int off = 0;
        while (off < sizeof(filename) && *filename_)
            filename[off++] = *filename_++;
        filename[off] = 0;
    }
    ~cpp_exception() throw() {}
    
    virtual char const *what() const throw() = 0;   // to be overloaded
    virtual char const *description() const throw() = 0;
    
    int line_no() const throw() { return line; }
    int column_no() const throw() { return column; }
    char const *file_name() const throw() { return filename; }
    
protected:
    char filename[512];
    int line;
    int column;
};

///////////////////////////////////////////////////////////////////////////////
// preprocessor error
class preprocess_exception :
    public cpp_exception
{
public:
    enum error_code {
        unexpected_error = 0,
        macro_redefinition,
        macro_insertion_error,
        bad_include_file,
        bad_include_statement,
        ill_formed_directive,
        error_directive,
        warning_directive,
        ill_formed_expression,
        missing_matching_if,
        missing_matching_endif,
        ill_formed_operator,
        bad_define_statement,
        too_few_macroarguments,
        too_many_macroarguments,
        improperly_terminated_macro,
        bad_line_statement,
        bad_undefine_statement,
        bad_macro_definition,
        illegal_redefinition,
        duplicate_parameter_name,
        invalid_concat,
        last_line_not_terminated,
        ill_formed_pragma_option,
        include_nesting_too_deep,
        misplaced_operator,
        unexpected_endregion,
        illegal_global_region,
        alreadydefined_name,
        undefined_macroname,
        invalid_macroname,
        unexpected_qualified_name
    };

    preprocess_exception(char const *what_, error_code code, int line_, 
        int column_, char const *filename_) throw() 
    :   cpp_exception(line_, column_, filename_), level(severity_level(code))
    {
        unsigned int off = 0;
        while (off < sizeof(buffer) && *what_)
            buffer[off++] = *what_++;
        buffer[off] = 0;
    }
    ~preprocess_exception() throw() {}
    
    virtual char const *what() const throw()
    {
        return "wave::preprocess_exception";
    }
    virtual char const *description() const throw()
    {
        return buffer;
    }
    util::severity get_severity()
    {
        return level;
    }

    static char const *error_text(int code)
    {
    // error texts in this array must apear in the same order as the items in
    // the error enum above
        static char const *preprocess_exception_errors[] = {
            "unexpected error (should not happen)",     // unexpected_error
            "illegal macro redefinition",               // macro_redefinition
            "macro definition failed (out of memory?)", // macro_insertion_error
            "could not find include file",              // bad_include_file
            "ill formed #include directive",            // bad_include_statement
            "ill formed preprocessor directive",        // ill_formed_directive
            "encountered #error directive or #pragma wave stop()", // error_directive
            "encountered #warning directive",           // warning_directive
            "ill formed preprocessor expression",       // ill_formed_expression
            "the #if for this directive is missing",    // missing_matching_if
            "detected at least one missing #endif directive",   // missing_matching_endif
            "ill formed preprocessing operator",        // ill_formed_operator
            "ill formed #define directive",             // bad_define_statement
            "too few macro arguments",                  // too_few_macroarguments
            "too many macro arguments",                 // too_many_macroarguments
            "improperly terminated macro invocation "
            "or replacement-list terminates in partial "
            "macro expansion (not supported yet)",      // improperly_terminated_macro
            "ill formed #line directive",               // bad_line_statement
            "#undef may not be used on this predefined name",   // bad_undefine_statement
            "invalid macro definition",                 // bad_macro_definition
            "this predefined name may not be redefined",    // illegal_redefinition
            "duplicate macro parameter name",           // duplicate_parameter_name
            "pasting the following two tokens does not "
            "give a valid preprocessing token",         // invalid_concat
            "last line of file ends without a newline", // last_line_not_terminated
            "unknown or illformed pragma option",       // ill_formed_pragma_option
            "include files nested too deep",            // include_nesting_too_deep
            "misplaced operator defined()",             // misplaced_operator
            "unexpected " WAVE_PP_ENDREGION " at global scope", // unexpected_endregion
            "a global " WAVE_PP_REGION " may not be opened "
            "inside a nameless " WAVE_PP_REGION,        // illegal_global_region
            "the name is already used in this scope as "
            "a macro or scope name",                    // alreadydefined_name
            "undefined macro or scope name may not be imported", // undefined_macroname
            "ill formed macro name or " WAVE_PP_REGION " name",  // invalid_macroname
            "qualified names are supported in C++0x mode only"   // unexpected_qualified_name
        };
        BOOST_ASSERT(unexpected_error <= code && 
            code <= unexpected_qualified_name);
        return preprocess_exception_errors[code];
    }

    static util::severity severity_level(int code)
    {
        static util::severity preprocess_exception_severity[] = {
            util::severity_fatal,              // unexpected_error
            util::severity_warning,            // macro_redefinition
            util::severity_fatal,              // macro_insertion_error
            util::severity_error,              // bad_include_file
            util::severity_error,              // bad_include_statement
            util::severity_error,              // ill_formed_directive
            util::severity_fatal,              // error_directive
            util::severity_warning,            // warning_directive
            util::severity_error,              // ill_formed_expression
            util::severity_error,              // missing_matching_if
            util::severity_error,              // missing_matching_endif
            util::severity_error,              // ill_formed_operator
            util::severity_error,              // bad_define_statement
            util::severity_warning,            // too_few_macroarguments
            util::severity_warning,            // too_many_macroarguments
            util::severity_error,              // improperly_terminated_macro
            util::severity_warning,            // bad_line_statement
            util::severity_warning,            // bad_undefine_statement
            util::severity_commandline_error,  // bad_macro_definition
            util::severity_warning,            // illegal_redefinition
            util::severity_error,              // duplicate_parameter_name
            util::severity_error,              // invalid_concat
            util::severity_warning,            // last_line_not_terminated
            util::severity_warning,            // ill_formed_pragma_option
            util::severity_fatal,              // include_nesting_too_deep
            util::severity_error,              // misplaced_operator
            util::severity_error,              // unexpected_endregion
            util::severity_error,              // illegal_global_region
            util::severity_error,              // alreadydefined_name
            util::severity_error,              // undefined_macroname
            util::severity_error,              // invalid_macroname
            util::severity_error               // unexpected_qualified_name
        };
        BOOST_ASSERT(unexpected_error <= code && 
            code <= unexpected_qualified_name);
        return preprocess_exception_severity[code];
    }
    static char const *severity_text(int code)
    {
        return util::get_severity(severity_level(code));
    }

private:
    char buffer[512];
    util::severity level;
};

///////////////////////////////////////////////////////////////////////////////
}   // namespace wave

#endif // !defined(CPP_EXCEPTIONS_HPP_5190E447_A781_4521_A275_5134FF9917D7_INCLUDED)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Hartmut Kaiser

United States United States
Actively involved in Boost and the development of the Spirit parser construction framework.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 11 Jan 2004
Article Copyright 2003 by Hartmut Kaiser
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid