Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2002
4 : * John Maddock
5 : *
6 : * Use, modification and distribution are subject to the
7 : * Boost 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 :
12 : /*
13 : * LOCATION: see http://www.boost.org for most recent version.
14 : * FILE perl_matcher_common.cpp
15 : * VERSION see <boost/version.hpp>
16 : * DESCRIPTION: Definitions of perl_matcher member functions that are
17 : * specific to the non-recursive implementation.
18 : */
19 :
20 : #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
21 : #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
22 :
23 : #include <new>
24 :
25 : #ifdef BOOST_MSVC
26 : #pragma warning(push)
27 : #pragma warning(disable: 4103)
28 : #endif
29 : #ifdef BOOST_HAS_ABI_HEADERS
30 : # include BOOST_ABI_PREFIX
31 : #endif
32 : #ifdef BOOST_MSVC
33 : #pragma warning(pop)
34 : #endif
35 : #ifdef BOOST_MSVC
36 : # pragma warning(push)
37 : # pragma warning(disable: 4706)
38 : #if BOOST_MSVC < 1910
39 : #pragma warning(disable:4800)
40 : #endif
41 : #endif
42 :
43 : namespace boost{
44 : namespace BOOST_REGEX_DETAIL_NS{
45 :
46 : template <class T>
47 0 : inline void inplace_destroy(T* p)
48 : {
49 : (void)p; // warning suppression
50 0 : p->~T();
51 : }
52 :
53 : struct saved_state
54 : {
55 : union{
56 : unsigned int state_id;
57 : // this padding ensures correct alignment on 64-bit platforms:
58 : std::size_t padding1;
59 : std::ptrdiff_t padding2;
60 : void* padding3;
61 : };
62 0 : saved_state(unsigned i) : state_id(i) {}
63 : };
64 :
65 : template <class BidiIterator>
66 : struct saved_matched_paren : public saved_state
67 : {
68 : int index;
69 : sub_match<BidiIterator> sub;
70 : saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};
71 : };
72 :
73 : template <class BidiIterator>
74 : struct saved_position : public saved_state
75 : {
76 : const re_syntax_base* pstate;
77 : BidiIterator position;
78 0 : saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};
79 : };
80 :
81 : template <class BidiIterator>
82 : struct saved_assertion : public saved_position<BidiIterator>
83 : {
84 : bool positive;
85 0 : saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
86 0 : : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};
87 : };
88 :
89 : template <class BidiIterator>
90 0 : struct saved_repeater : public saved_state
91 : {
92 : repeater_count<BidiIterator> count;
93 0 : saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
94 0 : : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
95 : };
96 :
97 : struct saved_extra_block : public saved_state
98 : {
99 : saved_state *base, *end;
100 0 : saved_extra_block(saved_state* b, saved_state* e)
101 0 : : saved_state(saved_state_extra_block), base(b), end(e) {}
102 : };
103 :
104 : struct save_state_init
105 : {
106 : saved_state** stack;
107 0 : save_state_init(saved_state** base, saved_state** end)
108 0 : : stack(base)
109 : {
110 0 : *base = static_cast<saved_state*>(get_mem_block());
111 0 : *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
112 0 : --(*end);
113 0 : (void) new (*end)saved_state(0);
114 0 : BOOST_ASSERT(*end > *base);
115 0 : }
116 0 : ~save_state_init()
117 : {
118 0 : put_mem_block(*stack);
119 0 : *stack = 0;
120 : }
121 : };
122 :
123 : template <class BidiIterator>
124 : struct saved_single_repeat : public saved_state
125 : {
126 : std::size_t count;
127 : const re_repeat* rep;
128 : BidiIterator last_position;
129 0 : saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
130 0 : : saved_state(arg_id), count(c), rep(r), last_position(lp){}
131 : };
132 :
133 : template <class Results>
134 0 : struct saved_recursion : public saved_state
135 : {
136 0 : saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2)
137 0 : : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {}
138 : int recursion_id;
139 : const re_syntax_base* preturn_address;
140 : Results internal_results, prior_results;
141 : };
142 :
143 : struct saved_change_case : public saved_state
144 : {
145 : bool icase;
146 0 : saved_change_case(bool c) : saved_state(18), icase(c) {}
147 : };
148 :
149 : struct incrementer
150 : {
151 0 : incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; }
152 0 : ~incrementer() { --*m_pu; }
153 0 : bool operator > (unsigned i) { return *m_pu > i; }
154 : private:
155 : unsigned* m_pu;
156 : };
157 :
158 : template <class BidiIterator, class Allocator, class traits>
159 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
160 : {
161 : static matcher_proc_type const s_match_vtable[34] =
162 : {
163 : (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
164 : &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
165 : &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
166 : &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
167 : &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
168 : &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
169 : &perl_matcher<BidiIterator, Allocator, traits>::match_match,
170 : &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
171 : &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
172 : &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
173 : &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
174 : &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
175 : &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
176 : &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
177 : &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
178 : &perl_matcher<BidiIterator, Allocator, traits>::match_set,
179 : &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
180 : &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
181 : &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
182 : &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
183 : &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
184 : &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
185 : // Although this next line *should* be evaluated at compile time, in practice
186 : // some compilers (VC++) emit run-time initialisation which breaks thread
187 : // safety, so use a dispatch function instead:
188 : //(::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow),
189 : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
190 : &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
191 : &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
192 : &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
193 : &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
194 : &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
195 : &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
196 : &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
197 : &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
198 : &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
199 : &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
200 : &perl_matcher<BidiIterator, Allocator, traits>::match_then,
201 : };
202 0 : incrementer inc(&m_recursions);
203 0 : if(inc > 80)
204 0 : raise_error(traits_inst, regex_constants::error_complexity);
205 0 : push_recursion_stopper();
206 0 : do{
207 0 : while(pstate)
208 : {
209 0 : matcher_proc_type proc = s_match_vtable[pstate->type];
210 0 : ++state_count;
211 0 : if(!(this->*proc)())
212 : {
213 0 : if(state_count > max_state_count)
214 0 : raise_error(traits_inst, regex_constants::error_complexity);
215 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
216 0 : m_has_partial_match = true;
217 0 : bool successful_unwind = unwind(false);
218 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
219 0 : m_has_partial_match = true;
220 0 : if(false == successful_unwind)
221 0 : return m_recursive_result;
222 : }
223 : }
224 : }while(unwind(true));
225 0 : return m_recursive_result;
226 : }
227 :
228 : template <class BidiIterator, class Allocator, class traits>
229 0 : void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
230 : {
231 0 : if(used_block_count)
232 : {
233 0 : --used_block_count;
234 : saved_state* stack_base;
235 : saved_state* backup_state;
236 0 : stack_base = static_cast<saved_state*>(get_mem_block());
237 0 : backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
238 0 : saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
239 0 : --block;
240 0 : (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
241 0 : m_stack_base = stack_base;
242 0 : m_backup_state = block;
243 : }
244 : else
245 0 : raise_error(traits_inst, regex_constants::error_stack);
246 0 : }
247 :
248 : template <class BidiIterator, class Allocator, class traits>
249 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
250 : {
251 : //BOOST_ASSERT(index);
252 : saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
253 : --pmp;
254 : if(pmp < m_stack_base)
255 : {
256 : extend_stack();
257 : pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
258 : --pmp;
259 : }
260 : (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
261 : m_backup_state = pmp;
262 : }
263 :
264 : template <class BidiIterator, class Allocator, class traits>
265 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
266 : {
267 : //BOOST_ASSERT(index);
268 0 : saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
269 0 : --pmp;
270 0 : if(pmp < m_stack_base)
271 : {
272 0 : extend_stack();
273 0 : pmp = static_cast<saved_change_case*>(m_backup_state);
274 0 : --pmp;
275 : }
276 0 : (void) new (pmp)saved_change_case(c);
277 0 : m_backup_state = pmp;
278 : }
279 :
280 : template <class BidiIterator, class Allocator, class traits>
281 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
282 : {
283 0 : saved_state* pmp = m_backup_state;
284 0 : --pmp;
285 0 : if(pmp < m_stack_base)
286 : {
287 0 : extend_stack();
288 0 : pmp = m_backup_state;
289 0 : --pmp;
290 : }
291 0 : (void) new (pmp)saved_state(saved_type_recurse);
292 0 : m_backup_state = pmp;
293 0 : }
294 :
295 : template <class BidiIterator, class Allocator, class traits>
296 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
297 : {
298 0 : saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
299 0 : --pmp;
300 0 : if(pmp < m_stack_base)
301 : {
302 0 : extend_stack();
303 0 : pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
304 0 : --pmp;
305 : }
306 0 : (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
307 0 : m_backup_state = pmp;
308 0 : }
309 :
310 : template <class BidiIterator, class Allocator, class traits>
311 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
312 : {
313 0 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
314 0 : --pmp;
315 0 : if(pmp < m_stack_base)
316 : {
317 0 : extend_stack();
318 0 : pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
319 0 : --pmp;
320 : }
321 0 : (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
322 0 : m_backup_state = pmp;
323 0 : }
324 :
325 : template <class BidiIterator, class Allocator, class traits>
326 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
327 : {
328 0 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
329 0 : --pmp;
330 0 : if(pmp < m_stack_base)
331 : {
332 0 : extend_stack();
333 0 : pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
334 0 : --pmp;
335 : }
336 0 : (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
337 0 : m_backup_state = pmp;
338 0 : }
339 :
340 : template <class BidiIterator, class Allocator, class traits>
341 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
342 : {
343 0 : saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
344 0 : --pmp;
345 0 : if(pmp < m_stack_base)
346 : {
347 0 : extend_stack();
348 0 : pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
349 0 : --pmp;
350 : }
351 0 : (void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : (INT_MIN + 3));
352 0 : m_backup_state = pmp;
353 0 : }
354 :
355 : template <class BidiIterator, class Allocator, class traits>
356 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
357 : {
358 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
359 0 : --pmp;
360 0 : if(pmp < m_stack_base)
361 : {
362 0 : extend_stack();
363 0 : pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
364 0 : --pmp;
365 : }
366 0 : (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
367 0 : m_backup_state = pmp;
368 0 : }
369 :
370 : template <class BidiIterator, class Allocator, class traits>
371 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2)
372 : {
373 0 : saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
374 0 : --pmp;
375 0 : if(pmp < m_stack_base)
376 : {
377 0 : extend_stack();
378 0 : pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
379 0 : --pmp;
380 : }
381 0 : (void) new (pmp)saved_recursion<results_type>(idx, p, presults, presults2);
382 0 : m_backup_state = pmp;
383 0 : }
384 :
385 : template <class BidiIterator, class Allocator, class traits>
386 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
387 : {
388 : // change our case sensitivity:
389 0 : push_case_change(this->icase);
390 0 : this->icase = static_cast<const re_case*>(pstate)->icase;
391 0 : pstate = pstate->next.p;
392 0 : return true;
393 : }
394 :
395 : template <class BidiIterator, class Allocator, class traits>
396 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
397 : {
398 0 : int index = static_cast<const re_brace*>(pstate)->index;
399 0 : icase = static_cast<const re_brace*>(pstate)->icase;
400 0 : switch(index)
401 : {
402 0 : case 0:
403 0 : pstate = pstate->next.p;
404 0 : break;
405 0 : case -1:
406 : case -2:
407 : {
408 : // forward lookahead assert:
409 0 : const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
410 0 : pstate = pstate->next.p->next.p;
411 0 : push_assertion(next_pstate, index == -1);
412 0 : break;
413 : }
414 0 : case -3:
415 : {
416 : // independent sub-expression, currently this is always recursive:
417 0 : bool old_independent = m_independent;
418 0 : m_independent = true;
419 0 : const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
420 0 : pstate = pstate->next.p->next.p;
421 0 : bool r = false;
422 : #if !defined(BOOST_NO_EXCEPTIONS)
423 : try{
424 : #endif
425 0 : r = match_all_states();
426 0 : if(!r && !m_independent)
427 : {
428 : // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent
429 : // sub failed, need to unwind everything else:
430 0 : while(unwind(false));
431 : return false;
432 : }
433 : #if !defined(BOOST_NO_EXCEPTIONS)
434 : }
435 0 : catch(...)
436 : {
437 0 : pstate = next_pstate;
438 : // unwind all pushed states, apart from anything else this
439 : // ensures that all the states are correctly destructed
440 : // not just the memory freed.
441 0 : while(unwind(true)) {}
442 0 : throw;
443 : }
444 : #endif
445 0 : pstate = next_pstate;
446 0 : m_independent = old_independent;
447 : #ifdef BOOST_REGEX_MATCH_EXTRA
448 : if(r && (m_match_flags & match_extra))
449 : {
450 : //
451 : // our captures have been stored in *m_presult
452 : // we need to unpack them, and insert them
453 : // back in the right order when we unwind the stack:
454 : //
455 : match_results<BidiIterator, Allocator> temp_match(*m_presult);
456 : unsigned i;
457 : for(i = 0; i < temp_match.size(); ++i)
458 : (*m_presult)[i].get_captures().clear();
459 : // match everything else:
460 : #if !defined(BOOST_NO_EXCEPTIONS)
461 : try{
462 : #endif
463 : r = match_all_states();
464 : #if !defined(BOOST_NO_EXCEPTIONS)
465 : }
466 : catch(...)
467 : {
468 : pstate = next_pstate;
469 : // unwind all pushed states, apart from anything else this
470 : // ensures that all the states are correctly destructed
471 : // not just the memory freed.
472 : while(unwind(true)) {}
473 : throw;
474 : }
475 : #endif
476 : // now place the stored captures back:
477 : for(i = 0; i < temp_match.size(); ++i)
478 : {
479 : typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
480 : seq& s1 = (*m_presult)[i].get_captures();
481 : const seq& s2 = temp_match[i].captures();
482 : s1.insert(
483 : s1.end(),
484 : s2.begin(),
485 : s2.end());
486 : }
487 : }
488 : #endif
489 0 : return r;
490 : }
491 0 : case -4:
492 : {
493 : // conditional expression:
494 0 : const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
495 0 : BOOST_ASSERT(alt->type == syntax_element_alt);
496 0 : pstate = alt->next.p;
497 0 : if(pstate->type == syntax_element_assert_backref)
498 : {
499 0 : if(!match_assert_backref())
500 0 : pstate = alt->alt.p;
501 : break;
502 : }
503 : else
504 : {
505 : // zero width assertion, have to match this recursively:
506 0 : BOOST_ASSERT(pstate->type == syntax_element_startmark);
507 0 : bool negated = static_cast<const re_brace*>(pstate)->index == -2;
508 0 : BidiIterator saved_position = position;
509 0 : const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
510 0 : pstate = pstate->next.p->next.p;
511 : #if !defined(BOOST_NO_EXCEPTIONS)
512 : try{
513 : #endif
514 0 : bool r = match_all_states();
515 0 : position = saved_position;
516 0 : if(negated)
517 0 : r = !r;
518 0 : if(r)
519 0 : pstate = next_pstate;
520 : else
521 0 : pstate = alt->alt.p;
522 : #if !defined(BOOST_NO_EXCEPTIONS)
523 : }
524 0 : catch(...)
525 : {
526 0 : pstate = next_pstate;
527 : // unwind all pushed states, apart from anything else this
528 : // ensures that all the states are correctly destructed
529 : // not just the memory freed.
530 0 : while(unwind(true)){}
531 0 : throw;
532 : }
533 : #endif
534 : break;
535 : }
536 : }
537 0 : case -5:
538 : {
539 0 : push_matched_paren(0, (*m_presult)[0]);
540 0 : m_presult->set_first(position, 0, true);
541 0 : pstate = pstate->next.p;
542 0 : break;
543 : }
544 0 : default:
545 : {
546 0 : BOOST_ASSERT(index > 0);
547 0 : if((m_match_flags & match_nosubs) == 0)
548 : {
549 0 : push_matched_paren(index, (*m_presult)[index]);
550 0 : m_presult->set_first(position, index);
551 : }
552 0 : pstate = pstate->next.p;
553 0 : break;
554 : }
555 : }
556 : return true;
557 : }
558 :
559 : template <class BidiIterator, class Allocator, class traits>
560 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
561 : {
562 : bool take_first, take_second;
563 0 : const re_alt* jmp = static_cast<const re_alt*>(pstate);
564 :
565 : // find out which of these two alternatives we need to take:
566 0 : if(position == last)
567 : {
568 0 : take_first = jmp->can_be_null & mask_take;
569 0 : take_second = jmp->can_be_null & mask_skip;
570 : }
571 : else
572 : {
573 0 : take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
574 0 : take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
575 : }
576 :
577 0 : if(take_first)
578 : {
579 : // we can take the first alternative,
580 : // see if we need to push next alternative:
581 0 : if(take_second)
582 : {
583 0 : push_alt(jmp->alt.p);
584 : }
585 0 : pstate = pstate->next.p;
586 0 : return true;
587 : }
588 0 : if(take_second)
589 : {
590 0 : pstate = jmp->alt.p;
591 0 : return true;
592 : }
593 : return false; // neither option is possible
594 : }
595 :
596 : template <class BidiIterator, class Allocator, class traits>
597 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
598 : {
599 : #ifdef BOOST_MSVC
600 : #pragma warning(push)
601 : #pragma warning(disable:4127 4244)
602 : #endif
603 : #ifdef __BORLANDC__
604 : #pragma option push -w-8008 -w-8066 -w-8004
605 : #endif
606 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
607 :
608 : // find out which of these two alternatives we need to take:
609 : bool take_first, take_second;
610 0 : if(position == last)
611 : {
612 0 : take_first = rep->can_be_null & mask_take;
613 0 : take_second = rep->can_be_null & mask_skip;
614 : }
615 : else
616 : {
617 0 : take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
618 0 : take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
619 : }
620 :
621 0 : if((m_backup_state->state_id != saved_state_repeater_count)
622 0 : || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
623 0 : || (next_count->get_id() != rep->state_id))
624 : {
625 : // we're moving to a different repeat from the last
626 : // one, so set up a counter object:
627 0 : push_repeater_count(rep->state_id, &next_count);
628 : }
629 : //
630 : // If we've had at least one repeat already, and the last one
631 : // matched the NULL string then set the repeat count to
632 : // maximum:
633 : //
634 0 : next_count->check_null_repeat(position, rep->max);
635 :
636 0 : if(next_count->get_count() < rep->min)
637 : {
638 : // we must take the repeat:
639 0 : if(take_first)
640 : {
641 : // increase the counter:
642 0 : ++(*next_count);
643 0 : pstate = rep->next.p;
644 0 : return true;
645 : }
646 : return false;
647 : }
648 :
649 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
650 : if(greedy)
651 : {
652 : // try and take the repeat if we can:
653 0 : if((next_count->get_count() < rep->max) && take_first)
654 : {
655 0 : if(take_second)
656 : {
657 : // store position in case we fail:
658 0 : push_alt(rep->alt.p);
659 : }
660 : // increase the counter:
661 0 : ++(*next_count);
662 0 : pstate = rep->next.p;
663 0 : return true;
664 : }
665 0 : else if(take_second)
666 : {
667 0 : pstate = rep->alt.p;
668 0 : return true;
669 : }
670 : return false; // can't take anything, fail...
671 : }
672 : else // non-greedy
673 : {
674 : // try and skip the repeat if we can:
675 0 : if(take_second)
676 : {
677 0 : if((next_count->get_count() < rep->max) && take_first)
678 : {
679 : // store position in case we fail:
680 0 : push_non_greedy_repeat(rep->next.p);
681 : }
682 0 : pstate = rep->alt.p;
683 0 : return true;
684 : }
685 0 : if((next_count->get_count() < rep->max) && take_first)
686 : {
687 : // increase the counter:
688 0 : ++(*next_count);
689 0 : pstate = rep->next.p;
690 0 : return true;
691 : }
692 : }
693 : return false;
694 : #ifdef __BORLANDC__
695 : #pragma option pop
696 : #endif
697 : #ifdef BOOST_MSVC
698 : #pragma warning(pop)
699 : #endif
700 : }
701 :
702 : template <class BidiIterator, class Allocator, class traits>
703 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
704 : {
705 0 : std::size_t count = 0;
706 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
707 0 : re_syntax_base* psingle = rep->next.p;
708 : // match compulsary repeats first:
709 0 : while(count < rep->min)
710 : {
711 0 : pstate = psingle;
712 0 : if(!match_wild())
713 : return false;
714 0 : ++count;
715 : }
716 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
717 : if(greedy)
718 : {
719 : // repeat for as long as we can:
720 0 : while(count < rep->max)
721 : {
722 0 : pstate = psingle;
723 0 : if(!match_wild())
724 : break;
725 0 : ++count;
726 : }
727 : // remember where we got to if this is a leading repeat:
728 0 : if((rep->leading) && (count < rep->max))
729 0 : restart = position;
730 : // push backtrack info if available:
731 0 : if(count - rep->min)
732 0 : push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
733 : // jump to next state:
734 0 : pstate = rep->alt.p;
735 0 : return true;
736 : }
737 : else
738 : {
739 : // non-greedy, push state and return true if we can skip:
740 0 : if(count < rep->max)
741 0 : push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
742 0 : pstate = rep->alt.p;
743 0 : return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
744 : }
745 : }
746 :
747 : template <class BidiIterator, class Allocator, class traits>
748 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
749 : {
750 0 : if(m_match_flags & match_not_dot_null)
751 0 : return match_dot_repeat_slow();
752 0 : if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
753 0 : return match_dot_repeat_slow();
754 :
755 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
756 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
757 0 : std::size_t count = static_cast<std::size_t>((std::min)(static_cast<std::size_t>(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), greedy ? rep->max : rep->min));
758 0 : if(rep->min > count)
759 : {
760 0 : position = last;
761 0 : return false; // not enough text left to match
762 : }
763 0 : std::advance(position, count);
764 :
765 0 : if(greedy)
766 : {
767 0 : if((rep->leading) && (count < rep->max))
768 0 : restart = position;
769 : // push backtrack info if available:
770 0 : if(count - rep->min)
771 0 : push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
772 : // jump to next state:
773 0 : pstate = rep->alt.p;
774 0 : return true;
775 : }
776 : else
777 : {
778 : // non-greedy, push state and return true if we can skip:
779 0 : if(count < rep->max)
780 0 : push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
781 0 : pstate = rep->alt.p;
782 0 : return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
783 : }
784 : }
785 :
786 : template <class BidiIterator, class Allocator, class traits>
787 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
788 : {
789 : #ifdef BOOST_MSVC
790 : #pragma warning(push)
791 : #pragma warning(disable:4127)
792 : #endif
793 : #ifdef __BORLANDC__
794 : #pragma option push -w-8008 -w-8066 -w-8004
795 : #endif
796 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
797 0 : BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
798 0 : const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
799 0 : std::size_t count = 0;
800 : //
801 : // start by working out how much we can skip:
802 : //
803 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
804 0 : std::size_t desired = greedy ? rep->max : rep->min;
805 : if(::boost::is_random_access_iterator<BidiIterator>::value)
806 : {
807 0 : BidiIterator end = position;
808 : // Move end forward by "desired", preferably without using distance or advance if we can
809 : // as these can be slow for some iterator types.
810 0 : std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
811 0 : if(desired >= len)
812 0 : end = last;
813 : else
814 0 : std::advance(end, desired);
815 0 : BidiIterator origin(position);
816 0 : while((position != end) && (traits_inst.translate(*position, icase) == what))
817 : {
818 0 : ++position;
819 : }
820 0 : count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
821 : }
822 : else
823 : {
824 : while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
825 : {
826 : ++position;
827 : ++count;
828 : }
829 : }
830 :
831 0 : if(count < rep->min)
832 : return false;
833 :
834 0 : if(greedy)
835 : {
836 0 : if((rep->leading) && (count < rep->max))
837 0 : restart = position;
838 : // push backtrack info if available:
839 0 : if(count - rep->min)
840 0 : push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
841 : // jump to next state:
842 0 : pstate = rep->alt.p;
843 0 : return true;
844 : }
845 : else
846 : {
847 : // non-greedy, push state and return true if we can skip:
848 0 : if(count < rep->max)
849 0 : push_single_repeat(count, rep, position, saved_state_rep_char);
850 0 : pstate = rep->alt.p;
851 0 : return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
852 : }
853 : #ifdef __BORLANDC__
854 : #pragma option pop
855 : #endif
856 : #ifdef BOOST_MSVC
857 : #pragma warning(pop)
858 : #endif
859 : }
860 :
861 : template <class BidiIterator, class Allocator, class traits>
862 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
863 : {
864 : #ifdef BOOST_MSVC
865 : #pragma warning(push)
866 : #pragma warning(disable:4127)
867 : #endif
868 : #ifdef __BORLANDC__
869 : #pragma option push -w-8008 -w-8066 -w-8004
870 : #endif
871 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
872 0 : const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
873 0 : std::size_t count = 0;
874 : //
875 : // start by working out how much we can skip:
876 : //
877 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
878 0 : std::size_t desired = greedy ? rep->max : rep->min;
879 : if(::boost::is_random_access_iterator<BidiIterator>::value)
880 : {
881 0 : BidiIterator end = position;
882 : // Move end forward by "desired", preferably without using distance or advance if we can
883 : // as these can be slow for some iterator types.
884 0 : std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
885 0 : if(desired >= len)
886 0 : end = last;
887 : else
888 0 : std::advance(end, desired);
889 0 : BidiIterator origin(position);
890 0 : while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
891 : {
892 0 : ++position;
893 : }
894 0 : count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
895 : }
896 : else
897 : {
898 : while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
899 : {
900 : ++position;
901 : ++count;
902 : }
903 : }
904 :
905 0 : if(count < rep->min)
906 : return false;
907 :
908 0 : if(greedy)
909 : {
910 0 : if((rep->leading) && (count < rep->max))
911 0 : restart = position;
912 : // push backtrack info if available:
913 0 : if(count - rep->min)
914 0 : push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
915 : // jump to next state:
916 0 : pstate = rep->alt.p;
917 0 : return true;
918 : }
919 : else
920 : {
921 : // non-greedy, push state and return true if we can skip:
922 0 : if(count < rep->max)
923 0 : push_single_repeat(count, rep, position, saved_state_rep_short_set);
924 0 : pstate = rep->alt.p;
925 0 : return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
926 : }
927 : #ifdef __BORLANDC__
928 : #pragma option pop
929 : #endif
930 : #ifdef BOOST_MSVC
931 : #pragma warning(pop)
932 : #endif
933 : }
934 :
935 : template <class BidiIterator, class Allocator, class traits>
936 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
937 : {
938 : #ifdef BOOST_MSVC
939 : #pragma warning(push)
940 : #pragma warning(disable:4127)
941 : #endif
942 : #ifdef __BORLANDC__
943 : #pragma option push -w-8008 -w-8066 -w-8004
944 : #endif
945 : typedef typename traits::char_class_type m_type;
946 0 : const re_repeat* rep = static_cast<const re_repeat*>(pstate);
947 0 : const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
948 0 : std::size_t count = 0;
949 : //
950 : // start by working out how much we can skip:
951 : //
952 0 : bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
953 0 : std::size_t desired = greedy ? rep->max : rep->min;
954 : if(::boost::is_random_access_iterator<BidiIterator>::value)
955 : {
956 0 : BidiIterator end = position;
957 : // Move end forward by "desired", preferably without using distance or advance if we can
958 : // as these can be slow for some iterator types.
959 0 : std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
960 0 : if(desired >= len)
961 0 : end = last;
962 : else
963 0 : std::advance(end, desired);
964 0 : BidiIterator origin(position);
965 0 : while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
966 : {
967 0 : ++position;
968 : }
969 0 : count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
970 : }
971 : else
972 : {
973 : while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
974 : {
975 : ++position;
976 : ++count;
977 : }
978 : }
979 :
980 0 : if(count < rep->min)
981 : return false;
982 :
983 0 : if(greedy)
984 : {
985 0 : if((rep->leading) && (count < rep->max))
986 0 : restart = position;
987 : // push backtrack info if available:
988 0 : if(count - rep->min)
989 0 : push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
990 : // jump to next state:
991 0 : pstate = rep->alt.p;
992 0 : return true;
993 : }
994 : else
995 : {
996 : // non-greedy, push state and return true if we can skip:
997 0 : if(count < rep->max)
998 0 : push_single_repeat(count, rep, position, saved_state_rep_long_set);
999 0 : pstate = rep->alt.p;
1000 0 : return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
1001 : }
1002 : #ifdef __BORLANDC__
1003 : #pragma option pop
1004 : #endif
1005 : #ifdef BOOST_MSVC
1006 : #pragma warning(pop)
1007 : #endif
1008 : }
1009 :
1010 : template <class BidiIterator, class Allocator, class traits>
1011 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
1012 : {
1013 0 : BOOST_ASSERT(pstate->type == syntax_element_recurse);
1014 : //
1015 : // See if we've seen this recursion before at this location, if we have then
1016 : // we need to prevent infinite recursion:
1017 : //
1018 0 : for(typename std::vector<recursion_info<results_type> >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
1019 : {
1020 0 : if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
1021 : {
1022 0 : if(i->location_of_start == position)
1023 0 : return false;
1024 : break;
1025 : }
1026 : }
1027 : //
1028 : // Backup call stack:
1029 : //
1030 0 : push_recursion_pop();
1031 : //
1032 : // Set new call stack:
1033 : //
1034 0 : if(recursion_stack.capacity() == 0)
1035 : {
1036 0 : recursion_stack.reserve(50);
1037 : }
1038 0 : recursion_stack.push_back(recursion_info<results_type>());
1039 0 : recursion_stack.back().preturn_address = pstate->next.p;
1040 0 : recursion_stack.back().results = *m_presult;
1041 0 : pstate = static_cast<const re_jump*>(pstate)->alt.p;
1042 0 : recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
1043 0 : recursion_stack.back().location_of_start = position;
1044 : //if(static_cast<const re_recurse*>(pstate)->state_id > 0)
1045 : {
1046 0 : push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
1047 : }
1048 :
1049 0 : return true;
1050 : }
1051 :
1052 : template <class BidiIterator, class Allocator, class traits>
1053 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
1054 : {
1055 0 : int index = static_cast<const re_brace*>(pstate)->index;
1056 0 : icase = static_cast<const re_brace*>(pstate)->icase;
1057 0 : if(index > 0)
1058 : {
1059 0 : if((m_match_flags & match_nosubs) == 0)
1060 : {
1061 0 : m_presult->set_second(position, index);
1062 : }
1063 0 : if(!recursion_stack.empty())
1064 : {
1065 0 : if(index == recursion_stack.back().idx)
1066 : {
1067 0 : pstate = recursion_stack.back().preturn_address;
1068 0 : *m_presult = recursion_stack.back().results;
1069 0 : push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1070 0 : recursion_stack.pop_back();
1071 0 : push_repeater_count(-(2 + index), &next_count);
1072 : }
1073 : }
1074 : }
1075 0 : else if((index < 0) && (index != -4))
1076 : {
1077 : // matched forward lookahead:
1078 0 : pstate = 0;
1079 0 : return true;
1080 : }
1081 0 : pstate = pstate->next.p;
1082 0 : return true;
1083 : }
1084 :
1085 : template <class BidiIterator, class Allocator, class traits>
1086 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
1087 : {
1088 0 : if(!recursion_stack.empty())
1089 : {
1090 0 : BOOST_ASSERT(0 == recursion_stack.back().idx);
1091 0 : pstate = recursion_stack.back().preturn_address;
1092 0 : push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1093 0 : *m_presult = recursion_stack.back().results;
1094 0 : recursion_stack.pop_back();
1095 0 : return true;
1096 : }
1097 0 : if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
1098 : return false;
1099 0 : if((m_match_flags & match_all) && (position != last))
1100 : return false;
1101 0 : if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
1102 : return false;
1103 0 : m_presult->set_second(position);
1104 0 : pstate = 0;
1105 0 : m_has_found_match = true;
1106 0 : if((m_match_flags & match_posix) == match_posix)
1107 : {
1108 0 : m_result.maybe_assign(*m_presult);
1109 0 : if((m_match_flags & match_any) == 0)
1110 0 : return false;
1111 : }
1112 : #ifdef BOOST_REGEX_MATCH_EXTRA
1113 : if(match_extra & m_match_flags)
1114 : {
1115 : for(unsigned i = 0; i < m_presult->size(); ++i)
1116 : if((*m_presult)[i].matched)
1117 : ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
1118 : }
1119 : #endif
1120 : return true;
1121 : }
1122 :
1123 : template <class BidiIterator, class Allocator, class traits>
1124 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_commit()
1125 : {
1126 : // Ideally we would just junk all the states that are on the stack,
1127 : // however we might not unwind correctly in that case, so for now,
1128 : // just mark that we don't backtrack into whatever is left (or rather
1129 : // we'll unwind it unconditionally without pausing to try other matches).
1130 :
1131 0 : switch(static_cast<const re_commit*>(pstate)->action)
1132 : {
1133 0 : case commit_commit:
1134 0 : restart = last;
1135 0 : break;
1136 0 : case commit_skip:
1137 0 : if(base != position)
1138 : {
1139 0 : restart = position;
1140 : // Have to decrement restart since it will get incremented again later:
1141 0 : --restart;
1142 : }
1143 : break;
1144 : case commit_prune:
1145 : break;
1146 : }
1147 :
1148 0 : saved_state* pmp = m_backup_state;
1149 0 : --pmp;
1150 0 : if(pmp < m_stack_base)
1151 : {
1152 0 : extend_stack();
1153 0 : pmp = m_backup_state;
1154 0 : --pmp;
1155 : }
1156 0 : (void) new (pmp)saved_state(16);
1157 0 : m_backup_state = pmp;
1158 0 : pstate = pstate->next.p;
1159 0 : return true;
1160 : }
1161 :
1162 : template <class BidiIterator, class Allocator, class traits>
1163 0 : bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
1164 : {
1165 : // Just leave a mark that we need to skip to next alternative:
1166 0 : saved_state* pmp = m_backup_state;
1167 0 : --pmp;
1168 0 : if(pmp < m_stack_base)
1169 : {
1170 0 : extend_stack();
1171 0 : pmp = m_backup_state;
1172 0 : --pmp;
1173 : }
1174 0 : (void) new (pmp)saved_state(17);
1175 0 : m_backup_state = pmp;
1176 0 : pstate = pstate->next.p;
1177 0 : return true;
1178 : }
1179 :
1180 : template <class BidiIterator, class Allocator, class traits>
1181 0 : bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
1182 : {
1183 0 : while(pstate)
1184 : {
1185 0 : if(pstate->type == syntax_element_endmark)
1186 : {
1187 0 : if(static_cast<const re_brace*>(pstate)->index == index)
1188 : {
1189 0 : if(have_match)
1190 0 : return this->match_endmark();
1191 0 : pstate = pstate->next.p;
1192 0 : return true;
1193 : }
1194 : else
1195 : {
1196 : // Unenclosed closing ), occurs when (*ACCEPT) is inside some other
1197 : // parenthesis which may or may not have other side effects associated with it.
1198 0 : const re_syntax_base* sp = pstate;
1199 0 : match_endmark();
1200 0 : if(!pstate)
1201 : {
1202 0 : unwind(true);
1203 : // unwind may leave pstate NULL if we've unwound a forward lookahead, in which
1204 : // case just move to the next state and keep looking...
1205 0 : if (!pstate)
1206 0 : pstate = sp->next.p;
1207 : }
1208 : }
1209 0 : continue;
1210 : }
1211 0 : else if(pstate->type == syntax_element_match)
1212 : return true;
1213 0 : else if(pstate->type == syntax_element_startmark)
1214 : {
1215 0 : int idx = static_cast<const re_brace*>(pstate)->index;
1216 0 : pstate = pstate->next.p;
1217 0 : skip_until_paren(idx, false);
1218 0 : continue;
1219 : }
1220 0 : pstate = pstate->next.p;
1221 : }
1222 : return true;
1223 : }
1224 :
1225 : /****************************************************************************
1226 :
1227 : Unwind and associated proceedures follow, these perform what normal stack
1228 : unwinding does in the recursive implementation.
1229 :
1230 : ****************************************************************************/
1231 :
1232 : template <class BidiIterator, class Allocator, class traits>
1233 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
1234 : {
1235 : static unwind_proc_type const s_unwind_table[19] =
1236 : {
1237 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
1238 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
1239 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
1240 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
1241 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
1242 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
1243 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
1244 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
1245 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
1246 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
1247 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
1248 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
1249 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
1250 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
1251 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
1252 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
1253 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_commit,
1254 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_then,
1255 : &perl_matcher<BidiIterator, Allocator, traits>::unwind_case,
1256 : };
1257 :
1258 0 : m_recursive_result = have_match;
1259 0 : m_unwound_lookahead = false;
1260 0 : m_unwound_alt = false;
1261 : unwind_proc_type unwinder;
1262 : bool cont;
1263 : //
1264 : // keep unwinding our stack until we have something to do:
1265 : //
1266 0 : do
1267 : {
1268 0 : unwinder = s_unwind_table[m_backup_state->state_id];
1269 0 : cont = (this->*unwinder)(m_recursive_result);
1270 : }while(cont);
1271 : //
1272 : // return true if we have more states to try:
1273 : //
1274 0 : return pstate ? true : false;
1275 : }
1276 :
1277 : template <class BidiIterator, class Allocator, class traits>
1278 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
1279 : {
1280 0 : pstate = 0; // nothing left to search
1281 0 : return false; // end of stack nothing more to search
1282 : }
1283 :
1284 : template <class BidiIterator, class Allocator, class traits>
1285 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_case(bool)
1286 : {
1287 0 : saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
1288 0 : icase = pmp->icase;
1289 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1290 0 : m_backup_state = pmp;
1291 0 : return true;
1292 : }
1293 :
1294 : template <class BidiIterator, class Allocator, class traits>
1295 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
1296 : {
1297 0 : saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
1298 : // restore previous values if no match was found:
1299 0 : if(have_match == false)
1300 : {
1301 0 : m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
1302 0 : m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
1303 : }
1304 : #ifdef BOOST_REGEX_MATCH_EXTRA
1305 : //
1306 : // we have a match, push the capture information onto the stack:
1307 : //
1308 : else if(pmp->sub.matched && (match_extra & m_match_flags))
1309 : ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
1310 : #endif
1311 : // unwind stack:
1312 0 : m_backup_state = pmp+1;
1313 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1314 0 : return true; // keep looking
1315 : }
1316 :
1317 : template <class BidiIterator, class Allocator, class traits>
1318 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
1319 : {
1320 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1321 0 : pstate = 0; // nothing left to search
1322 0 : return false; // end of stack nothing more to search
1323 : }
1324 :
1325 : template <class BidiIterator, class Allocator, class traits>
1326 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
1327 : {
1328 0 : saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
1329 0 : pstate = pmp->pstate;
1330 0 : position = pmp->position;
1331 0 : bool result = (r == pmp->positive);
1332 0 : m_recursive_result = pmp->positive ? r : !r;
1333 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1334 0 : m_backup_state = pmp;
1335 0 : m_unwound_lookahead = true;
1336 0 : return !result; // return false if the assertion was matched to stop search.
1337 : }
1338 :
1339 : template <class BidiIterator, class Allocator, class traits>
1340 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
1341 : {
1342 0 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1343 0 : if(!r)
1344 : {
1345 0 : pstate = pmp->pstate;
1346 0 : position = pmp->position;
1347 : }
1348 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1349 0 : m_backup_state = pmp;
1350 0 : m_unwound_alt = !r;
1351 0 : return r;
1352 : }
1353 :
1354 : template <class BidiIterator, class Allocator, class traits>
1355 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
1356 : {
1357 0 : saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
1358 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1359 0 : m_backup_state = pmp;
1360 0 : return true; // keep looking
1361 : }
1362 :
1363 : template <class BidiIterator, class Allocator, class traits>
1364 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
1365 : {
1366 0 : saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
1367 0 : void* condemmed = m_stack_base;
1368 0 : m_stack_base = pmp->base;
1369 0 : m_backup_state = pmp->end;
1370 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1371 0 : put_mem_block(condemmed);
1372 0 : return true; // keep looking
1373 : }
1374 :
1375 : template <class BidiIterator, class Allocator, class traits>
1376 0 : inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
1377 : {
1378 0 : saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1379 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++);
1380 0 : m_backup_state = p;
1381 : }
1382 :
1383 : template <class BidiIterator, class Allocator, class traits>
1384 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
1385 : {
1386 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1387 :
1388 : // if we have a match, just discard this state:
1389 0 : if(r)
1390 : {
1391 0 : destroy_single_repeat();
1392 0 : return true;
1393 : }
1394 :
1395 0 : const re_repeat* rep = pmp->rep;
1396 0 : std::size_t count = pmp->count;
1397 0 : BOOST_ASSERT(rep->next.p != 0);
1398 0 : BOOST_ASSERT(rep->alt.p != 0);
1399 :
1400 0 : count -= rep->min;
1401 :
1402 0 : if((m_match_flags & match_partial) && (position == last))
1403 0 : m_has_partial_match = true;
1404 :
1405 0 : BOOST_ASSERT(count);
1406 0 : position = pmp->last_position;
1407 :
1408 : // backtrack till we can skip out:
1409 : do
1410 : {
1411 0 : --position;
1412 0 : --count;
1413 0 : ++state_count;
1414 0 : }while(count && !can_start(*position, rep->_map, mask_skip));
1415 :
1416 : // if we've hit base, destroy this state:
1417 0 : if(count == 0)
1418 : {
1419 0 : destroy_single_repeat();
1420 0 : if(!can_start(*position, rep->_map, mask_skip))
1421 : return true;
1422 : }
1423 : else
1424 : {
1425 0 : pmp->count = count + rep->min;
1426 0 : pmp->last_position = position;
1427 : }
1428 0 : pstate = rep->alt.p;
1429 0 : return false;
1430 : }
1431 :
1432 : template <class BidiIterator, class Allocator, class traits>
1433 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
1434 : {
1435 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1436 :
1437 : // if we have a match, just discard this state:
1438 0 : if(r)
1439 : {
1440 0 : destroy_single_repeat();
1441 0 : return true;
1442 : }
1443 :
1444 0 : const re_repeat* rep = pmp->rep;
1445 0 : std::size_t count = pmp->count;
1446 0 : BOOST_ASSERT(rep->type == syntax_element_dot_rep);
1447 0 : BOOST_ASSERT(rep->next.p != 0);
1448 0 : BOOST_ASSERT(rep->alt.p != 0);
1449 0 : BOOST_ASSERT(rep->next.p->type == syntax_element_wild);
1450 :
1451 0 : BOOST_ASSERT(count < rep->max);
1452 0 : pstate = rep->next.p;
1453 0 : position = pmp->last_position;
1454 :
1455 0 : if(position != last)
1456 : {
1457 : // wind forward until we can skip out of the repeat:
1458 : do
1459 : {
1460 0 : if(!match_wild())
1461 : {
1462 : // failed repeat match, discard this state and look for another:
1463 0 : destroy_single_repeat();
1464 0 : return true;
1465 : }
1466 0 : ++count;
1467 0 : ++state_count;
1468 0 : pstate = rep->next.p;
1469 0 : }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1470 : }
1471 0 : if(position == last)
1472 : {
1473 : // can't repeat any more, remove the pushed state:
1474 0 : destroy_single_repeat();
1475 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1476 0 : m_has_partial_match = true;
1477 0 : if(0 == (rep->can_be_null & mask_skip))
1478 : return true;
1479 : }
1480 0 : else if(count == rep->max)
1481 : {
1482 : // can't repeat any more, remove the pushed state:
1483 0 : destroy_single_repeat();
1484 0 : if(!can_start(*position, rep->_map, mask_skip))
1485 : return true;
1486 : }
1487 : else
1488 : {
1489 0 : pmp->count = count;
1490 0 : pmp->last_position = position;
1491 : }
1492 0 : pstate = rep->alt.p;
1493 0 : return false;
1494 : }
1495 :
1496 : template <class BidiIterator, class Allocator, class traits>
1497 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
1498 : {
1499 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1500 :
1501 : // if we have a match, just discard this state:
1502 0 : if(r)
1503 : {
1504 0 : destroy_single_repeat();
1505 0 : return true;
1506 : }
1507 :
1508 0 : const re_repeat* rep = pmp->rep;
1509 0 : std::size_t count = pmp->count;
1510 :
1511 0 : BOOST_ASSERT(count < rep->max);
1512 0 : position = pmp->last_position;
1513 0 : if(position != last)
1514 : {
1515 :
1516 : // wind forward until we can skip out of the repeat:
1517 : do
1518 : {
1519 0 : ++position;
1520 0 : ++count;
1521 0 : ++state_count;
1522 0 : }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1523 : }
1524 :
1525 : // remember where we got to if this is a leading repeat:
1526 0 : if((rep->leading) && (count < rep->max))
1527 0 : restart = position;
1528 0 : if(position == last)
1529 : {
1530 : // can't repeat any more, remove the pushed state:
1531 0 : destroy_single_repeat();
1532 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1533 0 : m_has_partial_match = true;
1534 0 : if(0 == (rep->can_be_null & mask_skip))
1535 : return true;
1536 : }
1537 0 : else if(count == rep->max)
1538 : {
1539 : // can't repeat any more, remove the pushed state:
1540 0 : destroy_single_repeat();
1541 0 : if(!can_start(*position, rep->_map, mask_skip))
1542 : return true;
1543 : }
1544 : else
1545 : {
1546 0 : pmp->count = count;
1547 0 : pmp->last_position = position;
1548 : }
1549 0 : pstate = rep->alt.p;
1550 0 : return false;
1551 : }
1552 :
1553 : template <class BidiIterator, class Allocator, class traits>
1554 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
1555 : {
1556 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1557 :
1558 : // if we have a match, just discard this state:
1559 0 : if(r)
1560 : {
1561 0 : destroy_single_repeat();
1562 0 : return true;
1563 : }
1564 :
1565 0 : const re_repeat* rep = pmp->rep;
1566 0 : std::size_t count = pmp->count;
1567 0 : pstate = rep->next.p;
1568 0 : const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
1569 0 : position = pmp->last_position;
1570 :
1571 0 : BOOST_ASSERT(rep->type == syntax_element_char_rep);
1572 : BOOST_ASSERT(rep->next.p != 0);
1573 0 : BOOST_ASSERT(rep->alt.p != 0);
1574 0 : BOOST_ASSERT(rep->next.p->type == syntax_element_literal);
1575 0 : BOOST_ASSERT(count < rep->max);
1576 :
1577 0 : if(position != last)
1578 : {
1579 : // wind forward until we can skip out of the repeat:
1580 : do
1581 : {
1582 0 : if(traits_inst.translate(*position, icase) != what)
1583 : {
1584 : // failed repeat match, discard this state and look for another:
1585 0 : destroy_single_repeat();
1586 0 : return true;
1587 : }
1588 0 : ++count;
1589 0 : ++ position;
1590 0 : ++state_count;
1591 0 : pstate = rep->next.p;
1592 0 : }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1593 : }
1594 : // remember where we got to if this is a leading repeat:
1595 0 : if((rep->leading) && (count < rep->max))
1596 0 : restart = position;
1597 0 : if(position == last)
1598 : {
1599 : // can't repeat any more, remove the pushed state:
1600 0 : destroy_single_repeat();
1601 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1602 0 : m_has_partial_match = true;
1603 0 : if(0 == (rep->can_be_null & mask_skip))
1604 : return true;
1605 : }
1606 0 : else if(count == rep->max)
1607 : {
1608 : // can't repeat any more, remove the pushed state:
1609 0 : destroy_single_repeat();
1610 0 : if(!can_start(*position, rep->_map, mask_skip))
1611 : return true;
1612 : }
1613 : else
1614 : {
1615 0 : pmp->count = count;
1616 0 : pmp->last_position = position;
1617 : }
1618 0 : pstate = rep->alt.p;
1619 0 : return false;
1620 : }
1621 :
1622 : template <class BidiIterator, class Allocator, class traits>
1623 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
1624 : {
1625 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1626 :
1627 : // if we have a match, just discard this state:
1628 0 : if(r)
1629 : {
1630 0 : destroy_single_repeat();
1631 0 : return true;
1632 : }
1633 :
1634 0 : const re_repeat* rep = pmp->rep;
1635 0 : std::size_t count = pmp->count;
1636 0 : pstate = rep->next.p;
1637 0 : const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
1638 0 : position = pmp->last_position;
1639 :
1640 0 : BOOST_ASSERT(rep->type == syntax_element_short_set_rep);
1641 0 : BOOST_ASSERT(rep->next.p != 0);
1642 0 : BOOST_ASSERT(rep->alt.p != 0);
1643 0 : BOOST_ASSERT(rep->next.p->type == syntax_element_set);
1644 0 : BOOST_ASSERT(count < rep->max);
1645 :
1646 0 : if(position != last)
1647 : {
1648 : // wind forward until we can skip out of the repeat:
1649 : do
1650 : {
1651 0 : if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
1652 : {
1653 : // failed repeat match, discard this state and look for another:
1654 0 : destroy_single_repeat();
1655 0 : return true;
1656 : }
1657 0 : ++count;
1658 0 : ++ position;
1659 0 : ++state_count;
1660 0 : pstate = rep->next.p;
1661 0 : }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1662 : }
1663 : // remember where we got to if this is a leading repeat:
1664 0 : if((rep->leading) && (count < rep->max))
1665 0 : restart = position;
1666 0 : if(position == last)
1667 : {
1668 : // can't repeat any more, remove the pushed state:
1669 0 : destroy_single_repeat();
1670 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1671 0 : m_has_partial_match = true;
1672 0 : if(0 == (rep->can_be_null & mask_skip))
1673 : return true;
1674 : }
1675 0 : else if(count == rep->max)
1676 : {
1677 : // can't repeat any more, remove the pushed state:
1678 0 : destroy_single_repeat();
1679 0 : if(!can_start(*position, rep->_map, mask_skip))
1680 : return true;
1681 : }
1682 : else
1683 : {
1684 0 : pmp->count = count;
1685 0 : pmp->last_position = position;
1686 : }
1687 0 : pstate = rep->alt.p;
1688 0 : return false;
1689 : }
1690 :
1691 : template <class BidiIterator, class Allocator, class traits>
1692 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
1693 : {
1694 : typedef typename traits::char_class_type m_type;
1695 0 : saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1696 :
1697 : // if we have a match, just discard this state:
1698 0 : if(r)
1699 : {
1700 0 : destroy_single_repeat();
1701 0 : return true;
1702 : }
1703 :
1704 0 : const re_repeat* rep = pmp->rep;
1705 0 : std::size_t count = pmp->count;
1706 0 : pstate = rep->next.p;
1707 0 : const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
1708 0 : position = pmp->last_position;
1709 :
1710 0 : BOOST_ASSERT(rep->type == syntax_element_long_set_rep);
1711 0 : BOOST_ASSERT(rep->next.p != 0);
1712 0 : BOOST_ASSERT(rep->alt.p != 0);
1713 0 : BOOST_ASSERT(rep->next.p->type == syntax_element_long_set);
1714 0 : BOOST_ASSERT(count < rep->max);
1715 :
1716 0 : if(position != last)
1717 : {
1718 : // wind forward until we can skip out of the repeat:
1719 : do
1720 : {
1721 0 : if(position == re_is_set_member(position, last, set, re.get_data(), icase))
1722 : {
1723 : // failed repeat match, discard this state and look for another:
1724 0 : destroy_single_repeat();
1725 0 : return true;
1726 : }
1727 0 : ++position;
1728 0 : ++count;
1729 0 : ++state_count;
1730 0 : pstate = rep->next.p;
1731 0 : }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1732 : }
1733 : // remember where we got to if this is a leading repeat:
1734 0 : if((rep->leading) && (count < rep->max))
1735 0 : restart = position;
1736 0 : if(position == last)
1737 : {
1738 : // can't repeat any more, remove the pushed state:
1739 0 : destroy_single_repeat();
1740 0 : if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1741 0 : m_has_partial_match = true;
1742 0 : if(0 == (rep->can_be_null & mask_skip))
1743 : return true;
1744 : }
1745 0 : else if(count == rep->max)
1746 : {
1747 : // can't repeat any more, remove the pushed state:
1748 0 : destroy_single_repeat();
1749 0 : if(!can_start(*position, rep->_map, mask_skip))
1750 : return true;
1751 : }
1752 : else
1753 : {
1754 0 : pmp->count = count;
1755 0 : pmp->last_position = position;
1756 : }
1757 0 : pstate = rep->alt.p;
1758 0 : return false;
1759 : }
1760 :
1761 : template <class BidiIterator, class Allocator, class traits>
1762 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
1763 : {
1764 0 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1765 0 : if(!r)
1766 : {
1767 0 : position = pmp->position;
1768 0 : pstate = pmp->pstate;
1769 0 : ++(*next_count);
1770 : }
1771 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1772 0 : m_backup_state = pmp;
1773 0 : return r;
1774 : }
1775 :
1776 : template <class BidiIterator, class Allocator, class traits>
1777 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
1778 : {
1779 : // We are backtracking back inside a recursion, need to push the info
1780 : // back onto the recursion stack, and do so unconditionally, otherwise
1781 : // we can get mismatched pushes and pops...
1782 0 : saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
1783 0 : if (!r)
1784 : {
1785 0 : recursion_stack.push_back(recursion_info<results_type>());
1786 0 : recursion_stack.back().idx = pmp->recursion_id;
1787 0 : recursion_stack.back().preturn_address = pmp->preturn_address;
1788 0 : recursion_stack.back().results = pmp->prior_results;
1789 0 : recursion_stack.back().location_of_start = position;
1790 0 : *m_presult = pmp->internal_results;
1791 : }
1792 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1793 0 : m_backup_state = pmp;
1794 0 : return true;
1795 : }
1796 :
1797 : template <class BidiIterator, class Allocator, class traits>
1798 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
1799 : {
1800 : // Backtracking out of a recursion, we must pop state off the recursion
1801 : // stack unconditionally to ensure matched pushes and pops:
1802 0 : saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1803 0 : if (!r && !recursion_stack.empty())
1804 : {
1805 0 : *m_presult = recursion_stack.back().results;
1806 0 : position = recursion_stack.back().location_of_start;
1807 0 : recursion_stack.pop_back();
1808 : }
1809 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1810 0 : m_backup_state = pmp;
1811 0 : return true;
1812 : }
1813 :
1814 : template <class BidiIterator, class Allocator, class traits>
1815 0 : void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
1816 : {
1817 0 : saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1818 0 : --pmp;
1819 0 : if(pmp < m_stack_base)
1820 : {
1821 0 : extend_stack();
1822 0 : pmp = static_cast<saved_state*>(m_backup_state);
1823 0 : --pmp;
1824 : }
1825 0 : (void) new (pmp)saved_state(15);
1826 0 : m_backup_state = pmp;
1827 : }
1828 :
1829 : template <class BidiIterator, class Allocator, class traits>
1830 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_commit(bool b)
1831 : {
1832 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1833 0 : while(unwind(b) && !m_unwound_lookahead){}
1834 0 : if(m_unwound_lookahead && pstate)
1835 : {
1836 : //
1837 : // If we stop because we just unwound an assertion, put the
1838 : // commit state back on the stack again:
1839 : //
1840 0 : m_unwound_lookahead = false;
1841 0 : saved_state* pmp = m_backup_state;
1842 0 : --pmp;
1843 0 : if(pmp < m_stack_base)
1844 : {
1845 0 : extend_stack();
1846 0 : pmp = m_backup_state;
1847 0 : --pmp;
1848 : }
1849 0 : (void) new (pmp)saved_state(16);
1850 0 : m_backup_state = pmp;
1851 : }
1852 : // This prevents us from stopping when we exit from an independent sub-expression:
1853 0 : m_independent = false;
1854 0 : return false;
1855 : }
1856 :
1857 : template <class BidiIterator, class Allocator, class traits>
1858 0 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_then(bool b)
1859 : {
1860 : // Unwind everything till we hit an alternative:
1861 0 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1862 0 : bool result = false;
1863 0 : while((result = unwind(b)) && !m_unwound_alt){}
1864 : // We're now pointing at the next alternative, need one more backtrack
1865 : // since *all* the other alternatives must fail once we've reached a THEN clause:
1866 0 : if(result && m_unwound_alt)
1867 0 : unwind(b);
1868 0 : return false;
1869 : }
1870 :
1871 : /*
1872 : template <class BidiIterator, class Allocator, class traits>
1873 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
1874 : {
1875 : saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1876 : if(!r)
1877 : {
1878 : --parenthesis_stack_position;
1879 : }
1880 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1881 : m_backup_state = pmp;
1882 : return true;
1883 : }
1884 :
1885 : template <class BidiIterator, class Allocator, class traits>
1886 : void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
1887 : {
1888 : saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1889 : --pmp;
1890 : if(pmp < m_stack_base)
1891 : {
1892 : extend_stack();
1893 : pmp = static_cast<saved_state*>(m_backup_state);
1894 : --pmp;
1895 : }
1896 : (void) new (pmp)saved_state(16);
1897 : m_backup_state = pmp;
1898 : }
1899 :
1900 : template <class BidiIterator, class Allocator, class traits>
1901 : bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
1902 : {
1903 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1904 : if(!r)
1905 : {
1906 : parenthesis_stack[parenthesis_stack_position++] = pmp->position;
1907 : }
1908 : boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1909 : m_backup_state = pmp;
1910 : return true;
1911 : }
1912 :
1913 : template <class BidiIterator, class Allocator, class traits>
1914 : inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
1915 : {
1916 : saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1917 : --pmp;
1918 : if(pmp < m_stack_base)
1919 : {
1920 : extend_stack();
1921 : pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1922 : --pmp;
1923 : }
1924 : (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
1925 : m_backup_state = pmp;
1926 : }
1927 : */
1928 : } // namespace BOOST_REGEX_DETAIL_NS
1929 : } // namespace boost
1930 :
1931 : #ifdef BOOST_MSVC
1932 : # pragma warning(pop)
1933 : #endif
1934 :
1935 : #ifdef BOOST_MSVC
1936 : #pragma warning(push)
1937 : #pragma warning(disable: 4103)
1938 : #endif
1939 : #ifdef BOOST_HAS_ABI_HEADERS
1940 : # include BOOST_ABI_SUFFIX
1941 : #endif
1942 : #ifdef BOOST_MSVC
1943 : #pragma warning(pop)
1944 : #endif
1945 :
1946 : #endif
1947 :
1948 :
|