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