• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Boost.Wave: A Standard compliant C++ preprocessor library
3 
4     http://www.boost.org/
5 
6     Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
7     Software License, Version 1.0. (See accompanying file
8     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 
11 #if !defined(BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED)
12 #define BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED
13 
14 #include <exception>
15 #include <string>
16 
17 #include <boost/assert.hpp>
18 #include <boost/config.hpp>
19 #include <boost/throw_exception.hpp>
20 
21 #include <boost/wave/wave_config.hpp>
22 
23 // this must occur after all of the includes and before any code appears
24 #ifdef BOOST_HAS_ABI_HEADERS
25 #include BOOST_ABI_PREFIX
26 #endif
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 // helper macro for throwing exceptions
30 #if !defined(BOOST_WAVE_LEXER_THROW)
31 #ifdef BOOST_NO_STRINGSTREAM
32 #include <strstream>
33 #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name)            \
34     {                                                                         \
35     using namespace boost::wave;                                              \
36     std::strstream stream;                                                    \
37         stream << cls::severity_text(cls::code) << ": "                       \
38         << cls::error_text(cls::code);                                        \
39     if ((msg)[0] != 0) stream << ": " << (msg);                               \
40     stream << std::ends;                                                      \
41     std::string throwmsg = stream.str(); stream.freeze(false);                \
42     boost::throw_exception(cls(throwmsg.c_str(), cls::code, line, column,     \
43         name));                                                               \
44     }                                                                         \
45     /**/
46 #else
47 #include <sstream>
48 #define BOOST_WAVE_LEXER_THROW(cls, code, msg, line, column, name)            \
49     {                                                                         \
50     using namespace boost::wave;                                              \
51     std::stringstream stream;                                                 \
52         stream << cls::severity_text(cls::code) << ": "                       \
53         << cls::error_text(cls::code);                                        \
54     if ((msg)[0] != 0) stream << ": " << (msg);                               \
55     stream << std::ends;                                                      \
56     boost::throw_exception(cls(stream.str().c_str(), cls::code, line, column, \
57         name));                                                               \
58     }                                                                         \
59     /**/
60 #endif // BOOST_NO_STRINGSTREAM
61 #endif // BOOST_WAVE_LEXER_THROW
62 
63 #if !defined(BOOST_WAVE_LEXER_THROW_VAR)
64 #ifdef BOOST_NO_STRINGSTREAM
65 #include <strstream>
66 #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name)     \
67     {                                                                         \
68     using namespace boost::wave;                                              \
69     cls::error_code code = static_cast<cls::error_code>(codearg);             \
70     std::strstream stream;                                                    \
71         stream << cls::severity_text(code) << ": "                            \
72         << cls::error_text(code);                                             \
73     if ((msg)[0] != 0) stream << ": " << (msg);                               \
74     stream << std::ends;                                                      \
75     std::string throwmsg = stream.str(); stream.freeze(false);                \
76     boost::throw_exception(cls(throwmsg.c_str(), code, line, column,          \
77         name));                                                               \
78     }                                                                         \
79     /**/
80 #else
81 #include <sstream>
82 #define BOOST_WAVE_LEXER_THROW_VAR(cls, codearg, msg, line, column, name)     \
83     {                                                                         \
84     using namespace boost::wave;                                              \
85     cls::error_code code = static_cast<cls::error_code>(codearg);             \
86     std::stringstream stream;                                                 \
87         stream << cls::severity_text(code) << ": "                            \
88         << cls::error_text(code);                                             \
89     if ((msg)[0] != 0) stream << ": " << (msg);                               \
90     stream << std::ends;                                                      \
91     boost::throw_exception(cls(stream.str().c_str(), code, line, column,      \
92         name));                                                               \
93     }                                                                         \
94     /**/
95 #endif // BOOST_NO_STRINGSTREAM
96 #endif // BOOST_WAVE_LEXER_THROW
97 
98 ///////////////////////////////////////////////////////////////////////////////
99 namespace boost {
100 namespace wave {
101 namespace cpplexer {
102 
103 ///////////////////////////////////////////////////////////////////////////////
104 // exception severity
105 namespace util {
106 
107     enum severity {
108         severity_remark = 0,
109         severity_warning,
110         severity_error,
111         severity_fatal
112     };
113 
114     inline char const *
get_severity(severity level)115     get_severity(severity level)
116     {
117         static char const *severity_text[] =
118         {
119             "remark",           // severity_remark
120             "warning",          // severity_warning
121             "error",            // severity_error
122             "fatal error"       // severity_fatal
123         };
124         BOOST_ASSERT(severity_remark <= level && level <= severity_fatal);
125         return severity_text[level];
126     }
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 //  cpplexer_exception, the base class for all specific C++ lexer exceptions
131 class BOOST_SYMBOL_VISIBLE cpplexer_exception
132 :   public std::exception
133 {
134 public:
cpplexer_exception(std::size_t line_,std::size_t column_,char const * filename_)135     cpplexer_exception(std::size_t line_, std::size_t column_, char const *filename_) throw()
136     :   line(line_), column(column_)
137     {
138         unsigned int off = 0;
139         while (off < sizeof(filename)-1 && *filename_)
140             filename[off++] = *filename_++;
141         filename[off] = 0;
142     }
~cpplexer_exception()143     ~cpplexer_exception() throw() {}
144 
145     char const *what() const throw() BOOST_OVERRIDE = 0;   // to be overloaded
146     virtual char const *description() const throw() = 0;
147     virtual int get_errorcode() const throw() = 0;
148     virtual int get_severity() const throw() = 0;
149     virtual bool is_recoverable() const throw() = 0;
150 
line_no() const151     std::size_t line_no() const throw() { return line; }
column_no() const152     std::size_t column_no() const throw() { return column; }
file_name() const153     char const *file_name() const throw() { return filename; }
154 
155 protected:
156     char filename[512];
157     std::size_t line;
158     std::size_t column;
159 };
160 
161 ///////////////////////////////////////////////////////////////////////////////
162 // lexing_exception error
163 class BOOST_SYMBOL_VISIBLE lexing_exception :
164     public cpplexer_exception
165 {
166 public:
167     enum error_code {
168         unexpected_error = 0,
169         universal_char_invalid = 1,
170         universal_char_base_charset = 2,
171         universal_char_not_allowed = 3,
172         invalid_long_long_literal = 4,
173         generic_lexing_error = 5,
174         generic_lexing_warning = 6
175     };
176 
lexing_exception(char const * what_,error_code code,std::size_t line_,std::size_t column_,char const * filename_)177     lexing_exception(char const *what_, error_code code, std::size_t line_,
178         std::size_t column_, char const *filename_) throw()
179     :   cpplexer_exception(line_, column_, filename_),
180         level(severity_level(code)), code(code)
181     {
182         unsigned int off = 0;
183         while (off < sizeof(buffer)-1 && *what_)
184             buffer[off++] = *what_++;
185         buffer[off] = 0;
186     }
~lexing_exception()187     ~lexing_exception() throw() {}
188 
what() const189     char const *what() const throw() BOOST_OVERRIDE
190     {
191         return "boost::wave::lexing_exception";
192     }
description() const193     char const *description() const throw() BOOST_OVERRIDE
194     {
195         return buffer;
196     }
get_severity() const197     int get_severity() const throw() BOOST_OVERRIDE
198     {
199         return level;
200     }
get_errorcode() const201     int get_errorcode() const throw() BOOST_OVERRIDE
202     {
203         return code;
204     }
is_recoverable() const205     bool is_recoverable() const throw() BOOST_OVERRIDE
206     {
207         switch (get_errorcode()) {
208         case lexing_exception::universal_char_invalid:
209         case lexing_exception::universal_char_base_charset:
210         case lexing_exception::universal_char_not_allowed:
211         case lexing_exception::invalid_long_long_literal:
212         case lexing_exception::generic_lexing_warning:
213         case lexing_exception::generic_lexing_error:
214             return true;    // for now allow all exceptions to be recoverable
215 
216         case lexing_exception::unexpected_error:
217         default:
218             break;
219         }
220         return false;
221     }
222 
error_text(int code)223     static char const *error_text(int code)
224     {
225     // error texts in this array must appear in the same order as the items in
226     // the error enum above
227         static char const *preprocess_exception_errors[] = {
228             "unexpected error (should not happen)",     // unexpected_error
229             "universal character name specifies an invalid character",  // universal_char_invalid
230             "a universal character name cannot designate a character in the "
231                 "basic character set",                  // universal_char_base_charset
232             "this universal character is not allowed in an identifier", // universal_char_not_allowed
233             "long long suffixes are not allowed in pure C++ mode, "
234             "enable long_long mode to allow these",     // invalid_long_long_literal
235             "generic lexer error",                      // generic_lexing_error
236             "generic lexer warning"                     // generic_lexing_warning
237         };
238         return preprocess_exception_errors[code];
239     }
240 
severity_level(int code)241     static util::severity severity_level(int code)
242     {
243         static util::severity preprocess_exception_severity[] = {
244             util::severity_fatal,               // unexpected_error
245             util::severity_error,               // universal_char_invalid
246             util::severity_error,               // universal_char_base_charset
247             util::severity_error,               // universal_char_not_allowed
248             util::severity_warning,             // invalid_long_long_literal
249             util::severity_error,               // generic_lexing_error
250             util::severity_warning              // invalid_long_long_literal
251         };
252         return preprocess_exception_severity[code];
253     }
severity_text(int code)254     static char const *severity_text(int code)
255     {
256         return util::get_severity(severity_level(code));
257     }
258 
259 private:
260     char buffer[512];
261     util::severity level;
262     error_code code;
263 };
264 
265 ///////////////////////////////////////////////////////////////////////////////
266 //
267 //  The is_recoverable() function allows to decide, whether it is possible
268 //  simply to continue after a given exception was thrown by Wave.
269 //
270 //  This is kind of a hack to allow to recover from certain errors as long as
271 //  Wave doesn't provide better means of error recovery.
272 //
273 ///////////////////////////////////////////////////////////////////////////////
274 inline bool
is_recoverable(lexing_exception const & e)275 is_recoverable(lexing_exception const& e)
276 {
277     return e.is_recoverable();
278 }
279 
280 ///////////////////////////////////////////////////////////////////////////////
281 }   // namespace cpplexer
282 }   // namespace wave
283 }   // namespace boost
284 
285 // the suffix header occurs after all of the code
286 #ifdef BOOST_HAS_ABI_HEADERS
287 #include BOOST_ABI_SUFFIX
288 #endif
289 
290 #endif // !defined(BOOST_CPPLEXER_EXCEPTIONS_HPP_1A09DE1A_6D1F_4091_AF7F_5F13AB0D31AB_INCLUDED)
291