From a8db57d4e68cdba5071bb38faa3027bb3a78f19f Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Tue, 6 Dec 2005 00:17:59 +0000 Subject: [PATCH] Added partial error recovery support to Wave. [SVN r31924] --- ChangeLog | 9 ++- include/boost/wave/cpp_exceptions.hpp | 69 ++++++++++++++++++- .../wave/cpplexer/cpplexer_exceptions.hpp | 11 ++- tool/cpp.cpp | 34 ++++++--- 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3eeeac4..2cf99a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -55,7 +55,14 @@ CHANGELOG - Merged the new whitespace_handling policy with the existing preprocessing hooks. The name of the new preprocessing hook ist may_skip_whitespace(). - Fixed compatibility issues for CW9.4 in the Wave test aplication. - +- Added get_errorcode() member to the wave exception classes allowing to + get back the reason for the exception. +- Added boost::wave::is_recoverable(cpp_exception const&) alowing to decide, + whether it is possible to continue after a cpp_exception has been thrown. + This is a temporary hack to overcome the current limitation of the library + not allowing to do generic error recovery. It allows to recover from 75% of + the generated errors types. + Boost V1.33.1 - Version 1.2.1 - Fixed bug reported as Sourceforge bug 1274584. diff --git a/include/boost/wave/cpp_exceptions.hpp b/include/boost/wave/cpp_exceptions.hpp index c180df7..e59e11d 100644 --- a/include/boost/wave/cpp_exceptions.hpp +++ b/include/boost/wave/cpp_exceptions.hpp @@ -110,6 +110,7 @@ public: virtual char const *what() const throw() = 0; // to be overloaded virtual char const *description() const throw() = 0; + virtual int get_errorcode() const = 0; int line_no() const throw() { return line; } int column_no() const throw() { return column; } @@ -170,7 +171,8 @@ public: 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)) + : cpp_exception(line_, column_, filename_), level(severity_level(code)), + code(code) { unsigned int off = 0; while (off < sizeof(buffer) && *what_) @@ -187,11 +189,15 @@ public: { return buffer; } - util::severity get_severity() + util::severity get_severity() const { return level; } - + int get_errorcode() const + { + return code; + } + static char const *error_text(int code) { // error texts in this array must appear in the same order as the items in @@ -300,8 +306,65 @@ public: private: char buffer[512]; util::severity level; + error_code code; }; +/////////////////////////////////////////////////////////////////////////////// +// +// The is_recoverable() function allows to decide, whether it is possible +// simply to continue after a given exception was thrown by Wave. +// +// This is kind of a hack to allow to recover from certain errors as long as +// Wave doesn't provide better means of error recovery. +// +/////////////////////////////////////////////////////////////////////////////// +inline bool +is_recoverable(cpp_exception const& e) +{ + switch (e.get_errorcode()) { + // these are the exceptions thrown during processing not supposed to + // produce any tokens on the context::iterator level + case preprocess_exception::macro_redefinition: + case preprocess_exception::macro_insertion_error: + case preprocess_exception::bad_macro_definition: + case preprocess_exception::illegal_redefinition: + case preprocess_exception::duplicate_parameter_name: + case preprocess_exception::invalid_macroname: + case preprocess_exception::bad_include_file: + case preprocess_exception::bad_include_statement: + case preprocess_exception::ill_formed_directive: + case preprocess_exception::error_directive: + case preprocess_exception::warning_directive: + case preprocess_exception::ill_formed_expression: + case preprocess_exception::missing_matching_if: + case preprocess_exception::missing_matching_endif: + case preprocess_exception::unbalanced_if_endif: + case preprocess_exception::bad_define_statement: + case preprocess_exception::bad_line_statement: + case preprocess_exception::bad_undefine_statement: + case preprocess_exception::division_by_zero: + case preprocess_exception::integer_overflow: + case preprocess_exception::ill_formed_integer_literal: + case preprocess_exception::ill_formed_character_literal: + case preprocess_exception::character_literal_out_of_range: + case preprocess_exception::last_line_not_terminated: + case preprocess_exception::include_nesting_too_deep: + case preprocess_exception::illegal_operator_redefinition: + return true; + + case preprocess_exception::unexpected_error: + case preprocess_exception::ill_formed_operator: + case preprocess_exception::too_few_macroarguments: + case preprocess_exception::too_many_macroarguments: + case preprocess_exception::empty_macroarguments: + case preprocess_exception::improperly_terminated_macro: + case preprocess_exception::invalid_concat: + case preprocess_exception::ill_formed_pragma_option: + break; + } + return false; +} + /////////////////////////////////////////////////////////////////////////////// } // namespace wave } // namespace boost diff --git a/include/boost/wave/cpplexer/cpplexer_exceptions.hpp b/include/boost/wave/cpplexer/cpplexer_exceptions.hpp index 8b887ea..c8e313d 100644 --- a/include/boost/wave/cpplexer/cpplexer_exceptions.hpp +++ b/include/boost/wave/cpplexer/cpplexer_exceptions.hpp @@ -134,7 +134,7 @@ public: lexing_exception(char const *what_, error_code code, int line_, int column_, char const *filename_) throw() : cpplexer_exception(line_, column_, filename_), - level(severity_level(code)) + level(severity_level(code)), code(code) { unsigned int off = 0; while (off < sizeof(buffer) && *what_) @@ -151,11 +151,15 @@ public: { return buffer; } - util::severity get_severity() + util::severity get_severity() const { return level; } - + int get_errorcode() const + { + return code; + } + static char const *error_text(int code) { // error texts in this array must appear in the same order as the items in @@ -193,6 +197,7 @@ public: private: char buffer[512]; util::severity level; + error_code code; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/tool/cpp.cpp b/tool/cpp.cpp index a3ac6f4..971af99 100644 --- a/tool/cpp.cpp +++ b/tool/cpp.cpp @@ -543,16 +543,34 @@ boost::wave::util::file_position_type current_position; // >>>>>>>>>>>>> Here happens the actual preprocessing. <<<<<<<<<<<<<<<<<<< // loop over all generated tokens outputting the generated text - while (first != last) { - // store the last known good token position - current_position = (*first).get_position(); + bool finished = false; + + do { + try { + while (first != last) { + // store the last known good token position + current_position = (*first).get_position(); - // print out the current token value - output << (*first).get_value(); + // print out the current token value + output << (*first).get_value(); - // advance to the next token - ++first; - } + // advance to the next token + ++first; + } + finished = true; + } + catch (boost::wave::cpp_exception const &e) { + // some preprocessing error + if (!boost::wave::is_recoverable(e)) { + cerr + << e.file_name() << "(" << e.line_no() << "): " + << e.description() << endl; + } + else { + throw; // re-throw for non-recoverable errors + } + } + } while (!finished); } catch (boost::wave::cpp_exception const &e) { // some preprocessing error