]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/wave/cpplexer/re2clex/cpp_re.hpp
2c6a04a0ec62725172eb7ce3147533351810a62d
[ceph.git] / ceph / src / boost / boost / wave / cpplexer / re2clex / cpp_re.hpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 Re2C based C++ lexer
5
6 http://www.boost.org/
7
8 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
9 Software License, Version 1.0. (See accompanying file
10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 =============================================================================*/
12
13 #if !defined(CPP_RE_HPP_B76C4F5E_63E9_4B8A_9975_EC32FA6BF027_INCLUDED)
14 #define CPP_RE_HPP_B76C4F5E_63E9_4B8A_9975_EC32FA6BF027_INCLUDED
15
16 #include <boost/assert.hpp>
17
18 #include <boost/wave/wave_config.hpp>
19 #include <boost/wave/token_ids.hpp>
20 #include <boost/wave/cpplexer/cpplexer_exceptions.hpp>
21
22 // this must occur after all of the includes and before any code appears
23 #ifdef BOOST_HAS_ABI_HEADERS
24 #include BOOST_ABI_PREFIX
25 #endif
26
27 // suppress warnings about dependent classes not being exported from the dll
28 #ifdef BOOST_MSVC
29 #pragma warning(push)
30 #pragma warning(disable : 4251 4231 4660)
31 #endif
32
33 ///////////////////////////////////////////////////////////////////////////////
34
35 #define YYCTYPE uchar
36 #define YYCURSOR cursor
37 #define YYLIMIT limit
38 #define YYMARKER marker
39 #define YYFILL(n) \
40 { \
41 cursor = uchar_wrapper(fill(s, cursor), cursor.column); \
42 limit = uchar_wrapper (s->lim); \
43 } \
44 /**/
45
46 #include <iostream>
47
48 ///////////////////////////////////////////////////////////////////////////////
49 #define BOOST_WAVE_UPDATE_CURSOR() \
50 { \
51 s->line += count_backslash_newlines(s, cursor); \
52 s->curr_column = cursor.column; \
53 s->cur = cursor; \
54 s->lim = limit; \
55 s->ptr = marker; \
56 } \
57 /**/
58
59 ///////////////////////////////////////////////////////////////////////////////
60 #define BOOST_WAVE_RET(i) \
61 { \
62 BOOST_WAVE_UPDATE_CURSOR() \
63 if (s->cur > s->lim) \
64 return T_EOF; /* may happen for empty files */ \
65 return (i); \
66 } \
67 /**/
68
69 ///////////////////////////////////////////////////////////////////////////////
70
71 namespace boost {
72 namespace wave {
73 namespace cpplexer {
74 namespace re2clex {
75
76 template<typename Iterator>
77 struct Scanner;
78
79 ///////////////////////////////////////////////////////////////////////////////
80 // The scanner function to call whenever a new token is requested
81 template<typename Iterator>
82 BOOST_WAVE_DECL boost::wave::token_id scan(Scanner<Iterator> *s);
83 ///////////////////////////////////////////////////////////////////////////////
84
85 ///////////////////////////////////////////////////////////////////////////////
86 // Utility functions
87
88 #define RE2C_ASSERT BOOST_ASSERT
89
90 template<typename Iterator>
91 int get_one_char(Scanner<Iterator> *s)
92 {
93 RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
94 if (s->act < s->last)
95 return *(s->act)++;
96 return -1;
97 }
98
99 template<typename Iterator>
100 std::ptrdiff_t rewind_stream (Scanner<Iterator> *s, int cnt)
101 {
102 std::advance(s->act, cnt);
103 RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
104 return std::distance(s->first, s->act);
105 }
106
107 template<typename Iterator>
108 std::size_t get_first_eol_offset(Scanner<Iterator>* s)
109 {
110 if (!AQ_EMPTY(s->eol_offsets))
111 {
112 return s->eol_offsets->queue[s->eol_offsets->head];
113 }
114 else
115 {
116 return (unsigned int)-1;
117 }
118 }
119
120 template<typename Iterator>
121 void adjust_eol_offsets(Scanner<Iterator>* s, std::size_t adjustment)
122 {
123 aq_queue q;
124 std::size_t i;
125
126 if (!s->eol_offsets)
127 s->eol_offsets = aq_create();
128
129 q = s->eol_offsets;
130
131 if (AQ_EMPTY(q))
132 return;
133
134 i = q->head;
135 while (i != q->tail)
136 {
137 if (adjustment > q->queue[i])
138 q->queue[i] = 0;
139 else
140 q->queue[i] -= adjustment;
141 ++i;
142 if (i == q->max_size)
143 i = 0;
144 }
145 if (adjustment > q->queue[i])
146 q->queue[i] = 0;
147 else
148 q->queue[i] -= adjustment;
149 }
150
151 template<typename Iterator>
152 int count_backslash_newlines(Scanner<Iterator> *s, uchar *cursor)
153 {
154 std::size_t diff, offset;
155 int skipped = 0;
156
157 /* figure out how many backslash-newlines skipped over unknowingly. */
158 diff = cursor - s->bot;
159 offset = get_first_eol_offset(s);
160 while (offset <= diff && offset != (unsigned int)-1)
161 {
162 skipped++;
163 aq_pop(s->eol_offsets);
164 offset = get_first_eol_offset(s);
165 }
166 return skipped;
167 }
168
169 BOOST_WAVE_DECL bool is_backslash(uchar *p, uchar *end, int &len);
170
171 #define BOOST_WAVE_BSIZE 196608
172 template<typename Iterator>
173 uchar *fill(Scanner<Iterator> *s, uchar *cursor)
174 {
175 using namespace std; // some systems have memcpy etc. in namespace std
176 if(!s->eof)
177 {
178 uchar* p;
179 std::ptrdiff_t cnt = s->tok - s->bot;
180 if(cnt)
181 {
182 if (NULL == s->lim)
183 s->lim = s->top;
184 memmove(s->bot, s->tok, s->lim - s->tok);
185 s->tok = s->cur = s->bot;
186 s->ptr -= cnt;
187 cursor -= cnt;
188 s->lim -= cnt;
189 adjust_eol_offsets(s, cnt);
190 }
191
192 if((s->top - s->lim) < BOOST_WAVE_BSIZE)
193 {
194 uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BOOST_WAVE_BSIZE)*sizeof(uchar));
195 if (buf == 0)
196 {
197 (*s->error_proc)(s, lexing_exception::unexpected_error,
198 "Out of memory!");
199
200 /* get the scanner to stop */
201 *cursor = 0;
202 return cursor;
203 }
204
205 memmove(buf, s->tok, s->lim - s->tok);
206 s->tok = s->cur = buf;
207 s->ptr = &buf[s->ptr - s->bot];
208 cursor = &buf[cursor - s->bot];
209 s->lim = &buf[s->lim - s->bot];
210 s->top = &s->lim[BOOST_WAVE_BSIZE];
211 free(s->bot);
212 s->bot = buf;
213 }
214
215 cnt = std::distance(s->act, s->last);
216 if (cnt > BOOST_WAVE_BSIZE)
217 cnt = BOOST_WAVE_BSIZE;
218 uchar * dst = s->lim;
219 for (std::ptrdiff_t idx = 0; idx < cnt; ++idx)
220 {
221 *dst++ = *s->act++;
222 }
223
224 if (cnt != BOOST_WAVE_BSIZE)
225 {
226 s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';
227 }
228
229 /* backslash-newline erasing time */
230
231 /* first scan for backslash-newline and erase them */
232 for (p = s->lim; p < s->lim + cnt - 2; ++p)
233 {
234 int len = 0;
235 if (is_backslash(p, s->lim + cnt, len))
236 {
237 if (*(p+len) == '\n')
238 {
239 int offset = len + 1;
240 memmove(p, p + offset, s->lim + cnt - p - offset);
241 cnt -= offset;
242 --p;
243 aq_enqueue(s->eol_offsets, p - s->bot + 1);
244 }
245 else if (*(p+len) == '\r')
246 {
247 if (*(p+len+1) == '\n')
248 {
249 int offset = len + 2;
250 memmove(p, p + offset, s->lim + cnt - p - offset);
251 cnt -= offset;
252 --p;
253 }
254 else
255 {
256 int offset = len + 1;
257 memmove(p, p + offset, s->lim + cnt - p - offset);
258 cnt -= offset;
259 --p;
260 }
261 aq_enqueue(s->eol_offsets, p - s->bot + 1);
262 }
263 }
264 }
265
266 /* FIXME: the following code should be fixed to recognize correctly the
267 trigraph backslash token */
268
269 /* check to see if what we just read ends in a backslash */
270 if (cnt >= 2)
271 {
272 uchar last = s->lim[cnt-1];
273 uchar last2 = s->lim[cnt-2];
274 /* check \ EOB */
275 if (last == '\\')
276 {
277 int next = get_one_char(s);
278 /* check for \ \n or \ \r or \ \r \n straddling the border */
279 if (next == '\n')
280 {
281 --cnt; /* chop the final \, we've already read the \n. */
282 aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));
283 }
284 else if (next == '\r')
285 {
286 int next2 = get_one_char(s);
287 if (next2 == '\n')
288 {
289 --cnt; /* skip the backslash */
290 }
291 else
292 {
293 /* rewind one, and skip one char */
294 rewind_stream(s, -1);
295 --cnt;
296 }
297 aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));
298 }
299 else if (next != -1) /* -1 means end of file */
300 {
301 /* next was something else, so rewind the stream */
302 rewind_stream(s, -1);
303 }
304 }
305 /* check \ \r EOB */
306 else if (last == '\r' && last2 == '\\')
307 {
308 int next = get_one_char(s);
309 if (next == '\n')
310 {
311 cnt -= 2; /* skip the \ \r */
312 }
313 else
314 {
315 /* rewind one, and skip two chars */
316 rewind_stream(s, -1);
317 cnt -= 2;
318 }
319 aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));
320 }
321 /* check \ \n EOB */
322 else if (last == '\n' && last2 == '\\')
323 {
324 cnt -= 2;
325 aq_enqueue(s->eol_offsets, cnt + (s->lim - s->bot));
326 }
327 }
328
329 s->lim += cnt;
330 if (s->eof) /* eof needs adjusting if we erased backslash-newlines */
331 {
332 s->eof = s->lim;
333 *(s->eof)++ = '\0';
334 }
335 }
336 return cursor;
337 }
338 #undef BOOST_WAVE_BSIZE
339
340 ///////////////////////////////////////////////////////////////////////////////
341 // Special wrapper class holding the current cursor position
342 struct BOOST_WAVE_DECL uchar_wrapper
343 {
344 uchar_wrapper (uchar *base_cursor, std::size_t column = 1);
345
346 uchar_wrapper& operator++();
347
348 uchar_wrapper& operator--();
349
350 uchar operator* () const;
351
352 operator uchar *() const;
353
354 friend BOOST_WAVE_DECL std::ptrdiff_t
355 operator- (uchar_wrapper const& lhs, uchar_wrapper const& rhs);
356
357 uchar *base_cursor;
358 std::size_t column;
359 };
360
361
362 ///////////////////////////////////////////////////////////////////////////////
363 template<typename Iterator>
364 boost::wave::token_id scan(Scanner<Iterator> *s)
365 {
366 BOOST_ASSERT(0 != s->error_proc); // error handler must be given
367
368 uchar_wrapper cursor (s->tok = s->cur, s->column = s->curr_column);
369 uchar_wrapper marker (s->ptr);
370 uchar_wrapper limit (s->lim);
371
372 typedef BOOST_WAVE_STRINGTYPE string_type;
373 string_type rawstringdelim; // for use with C++11 raw string literals
374
375 // include the correct Re2C token definition rules
376 #if (defined (__FreeBSD__) || defined (__DragonFly__) || defined (__OpenBSD__)) && defined (T_DIVIDE)
377 #undef T_DIVIDE
378 #endif
379 #if BOOST_WAVE_USE_STRICT_LEXER != 0
380 #include "strict_cpp_re.inc"
381 #else
382 #include "cpp_re.inc"
383 #endif
384
385 } /* end of scan */
386
387 ///////////////////////////////////////////////////////////////////////////////
388
389 } // namespace re2clex
390 } // namespace cpplexer
391 } // namespace wave
392 } // namespace boost
393
394 #ifdef BOOST_MSVC
395 #pragma warning(pop)
396 #endif
397
398 #undef BOOST_WAVE_RET
399 #undef YYCTYPE
400 #undef YYCURSOR
401 #undef YYLIMIT
402 #undef YYMARKER
403 #undef YYFILL
404
405 // the suffix header occurs after all of the code
406 #ifdef BOOST_HAS_ABI_HEADERS
407 #include BOOST_ABI_SUFFIX
408 #endif
409
410 #endif // !defined(CPP_RE_HPP_B76C4F5E_63E9_4B8A_9975_EC32FA6BF027_INCLUDED)