]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/wave/src/cpplexer/re2clex/cpp_re.cpp
1 /*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
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)
10 It also may be necessary to add $ to identifiers, for asm.
12 have some easier way to parse strings instead of files (done)
13 =============================================================================*/
15 #define BOOST_WAVE_SOURCE 1
17 // disable stupid compiler warnings
18 #include <boost/config/warning_disable.hpp>
24 #include <sys/types.h>
28 #include <boost/wave/wave_config.hpp> // configuration data
30 #if defined(BOOST_HAS_UNISTD_H)
36 #include <boost/assert.hpp>
37 #include <boost/detail/workaround.hpp>
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>
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
50 ///////////////////////////////////////////////////////////////////////////////
51 #if defined(BOOST_MSVC)
52 #pragma warning (disable: 4101) // 'foo' : unreferenced local variable
53 #pragma warning (disable: 4102) // 'foo' : unreferenced label
56 ///////////////////////////////////////////////////////////////////////////////
57 #define BOOST_WAVE_BSIZE 196608
60 #define YYCURSOR cursor
62 #define YYMARKER marker
65 cursor = uchar_wrapper(fill(s, cursor), cursor.column); \
66 limit = uchar_wrapper (s->lim); \
72 ///////////////////////////////////////////////////////////////////////////////
73 #define BOOST_WAVE_UPDATE_CURSOR() \
75 s->line += count_backslash_newlines(s, cursor); \
76 s->curr_column = cursor.column; \
83 ///////////////////////////////////////////////////////////////////////////////
84 #define BOOST_WAVE_RET(i) \
86 BOOST_WAVE_UPDATE_CURSOR() \
87 if (s->cur > s->lim) \
88 return T_EOF; /* may happen for empty files */ \
93 ///////////////////////////////////////////////////////////////////////////////
99 #define RE2C_ASSERT BOOST_ASSERT
101 int get_one_char(Scanner
*s
)
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
)
112 std::ptrdiff_t rewind_stream (Scanner
*s
, int cnt
)
115 RE2C_ASSERT(s
->first
!= 0 && s
->last
!= 0);
117 RE2C_ASSERT(s
->first
<= s
->act
&& s
->act
<= s
->last
);
118 return s
->act
- s
->first
;
123 std::size_t get_first_eol_offset(Scanner
* s
)
125 if (!AQ_EMPTY(s
->eol_offsets
))
127 return s
->eol_offsets
->queue
[s
->eol_offsets
->head
];
131 return (unsigned int)-1;
135 void adjust_eol_offsets(Scanner
* s
, std::size_t adjustment
)
141 s
->eol_offsets
= aq_create();
151 if (adjustment
> q
->queue
[i
])
154 q
->queue
[i
] -= adjustment
;
156 if (i
== q
->max_size
)
159 if (adjustment
> q
->queue
[i
])
162 q
->queue
[i
] -= adjustment
;
165 int count_backslash_newlines(Scanner
*s
, uchar
*cursor
)
167 std::size_t diff
, offset
;
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)
176 aq_pop(s
->eol_offsets
);
177 offset
= get_first_eol_offset(s
);
182 bool is_backslash(uchar
*p
, uchar
*end
, int &len
)
188 else if (*p
== '?' && *(p
+1) == '?' && (p
+2 < end
&& *(p
+2) == '/')) {
195 uchar
*fill(Scanner
*s
, uchar
*cursor
)
197 using namespace std
; // some systems have memcpy etc. in namespace std
201 std::ptrdiff_t cnt
= s
->tok
- s
->bot
;
206 memmove(s
->bot
, s
->tok
, s
->lim
- s
->tok
);
207 s
->tok
= s
->cur
= s
->bot
;
211 adjust_eol_offsets(s
, cnt
);
214 if((s
->top
- s
->lim
) < BOOST_WAVE_BSIZE
)
216 uchar
*buf
= (uchar
*) malloc(((s
->lim
- s
->bot
) + BOOST_WAVE_BSIZE
)*sizeof(uchar
));
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
,
225 printf("Out of memory!\n");
227 /* get the scanner to stop */
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
];
243 cnt
= s
->last
- s
->act
;
244 if (cnt
> BOOST_WAVE_BSIZE
)
245 cnt
= BOOST_WAVE_BSIZE
;
246 memmove(s
->lim
, s
->act
, cnt
);
248 if (cnt
!= BOOST_WAVE_BSIZE
)
250 s
->eof
= &s
->lim
[cnt
]; *(s
->eof
)++ = '\0';
254 /* backslash-newline erasing time */
256 /* first scan for backslash-newline and erase them */
257 for (p
= s
->lim
; p
< s
->lim
+ cnt
- 2; ++p
)
260 if (is_backslash(p
, s
->lim
+ cnt
, len
))
262 if (*(p
+len
) == '\n')
264 int offset
= len
+ 1;
265 memmove(p
, p
+ offset
, s
->lim
+ cnt
- p
- offset
);
268 aq_enqueue(s
->eol_offsets
, p
- s
->bot
+ 1);
270 else if (*(p
+len
) == '\r')
272 if (*(p
+len
+1) == '\n')
274 int offset
= len
+ 2;
275 memmove(p
, p
+ offset
, s
->lim
+ cnt
- p
- offset
);
281 int offset
= len
+ 1;
282 memmove(p
, p
+ offset
, s
->lim
+ cnt
- p
- offset
);
286 aq_enqueue(s
->eol_offsets
, p
- s
->bot
+ 1);
291 /* FIXME: the following code should be fixed to recognize correctly the
292 trigraph backslash token */
294 /* check to see if what we just read ends in a backslash */
297 uchar last
= s
->lim
[cnt
-1];
298 uchar last2
= s
->lim
[cnt
-2];
302 int next
= get_one_char(s
);
303 /* check for \ \n or \ \r or \ \r \n straddling the border */
306 --cnt
; /* chop the final \, we've already read the \n. */
307 aq_enqueue(s
->eol_offsets
, cnt
+ (s
->lim
- s
->bot
));
309 else if (next
== '\r')
311 int next2
= get_one_char(s
);
314 --cnt
; /* skip the backslash */
318 /* rewind one, and skip one char */
319 rewind_stream(s
, -1);
322 aq_enqueue(s
->eol_offsets
, cnt
+ (s
->lim
- s
->bot
));
324 else if (next
!= -1) /* -1 means end of file */
326 /* next was something else, so rewind the stream */
327 rewind_stream(s
, -1);
331 else if (last
== '\r' && last2
== '\\')
333 int next
= get_one_char(s
);
336 cnt
-= 2; /* skip the \ \r */
340 /* rewind one, and skip two chars */
341 rewind_stream(s
, -1);
344 aq_enqueue(s
->eol_offsets
, cnt
+ (s
->lim
- s
->bot
));
347 else if (last
== '\n' && last2
== '\\')
350 aq_enqueue(s
->eol_offsets
, cnt
+ (s
->lim
- s
->bot
));
355 if (s
->eof
) /* eof needs adjusting if we erased backslash-newlines */
364 ///////////////////////////////////////////////////////////////////////////////
365 // Special wrapper class holding the current cursor position
368 uchar_wrapper (uchar
*base_cursor
, std::size_t column
= 1)
369 : base_cursor(base_cursor
), column(column
)
372 uchar_wrapper
& operator++()
379 uchar_wrapper
& operator--()
386 uchar
operator* () const
391 operator uchar
*() const
396 friend std::ptrdiff_t
397 operator- (uchar_wrapper
const& lhs
, uchar_wrapper
const& rhs
)
399 return lhs
.base_cursor
- rhs
.base_cursor
;
406 ///////////////////////////////////////////////////////////////////////////////
407 boost::wave::token_id
scan(Scanner
*s
)
409 BOOST_ASSERT(0 != s
->error_proc
); // error handler must be given
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
);
415 // include the correct Re2C token definition rules
416 #if BOOST_WAVE_USE_STRICT_LEXER != 0
417 #include "strict_cpp_re.inc"
419 #include "cpp_re.inc"
424 ///////////////////////////////////////////////////////////////////////////////
425 } // namespace re2clex
426 } // namespace cpplexer
430 #undef BOOST_WAVE_RET
431 #undef BOOST_WAVE_BSIZE
438 // the suffix header occurs after all of the code
439 #ifdef BOOST_HAS_ABI_HEADERS
440 #include BOOST_ABI_SUFFIX