Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:25

0001 /*
0002  *
0003  * Copyright (c) 2002
0004  * John Maddock
0005  *
0006  * Use, modification and distribution are subject to the 
0007  * Boost Software License, Version 1.0. (See accompanying file 
0008  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009  *
0010  */
0011 
0012  /*
0013   *   LOCATION:    see http://www.boost.org for most recent version.
0014   *   FILE         perl_matcher_common.cpp
0015   *   VERSION      see <boost/version.hpp>
0016   *   DESCRIPTION: Definitions of perl_matcher member functions that are 
0017   *                specific to the non-recursive implementation.
0018   */
0019 
0020 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
0021 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
0022 
0023 #include <boost/regex/v4/mem_block_cache.hpp>
0024 
0025 #ifdef BOOST_MSVC
0026 #pragma warning(push)
0027 #pragma warning(disable: 4103)
0028 #endif
0029 #ifdef BOOST_HAS_ABI_HEADERS
0030 #  include BOOST_ABI_PREFIX
0031 #endif
0032 #ifdef BOOST_MSVC
0033 #pragma warning(pop)
0034 #endif
0035 #ifdef BOOST_MSVC
0036 #  pragma warning(push)
0037 #  pragma warning(disable: 4706)
0038 #if BOOST_MSVC < 1910
0039 #pragma warning(disable:4800)
0040 #endif
0041 #endif
0042 
0043 namespace boost{
0044 namespace BOOST_REGEX_DETAIL_NS{
0045 
0046 template <class T>
0047 inline void inplace_destroy(T* p)
0048 {
0049    (void)p;  // warning suppression
0050    p->~T();
0051 }
0052 
0053 struct saved_state
0054 {
0055    union{
0056       unsigned int state_id;
0057       // this padding ensures correct alignment on 64-bit platforms:
0058       std::size_t padding1;
0059       std::ptrdiff_t padding2;
0060       void* padding3;
0061    };
0062    saved_state(unsigned i) : state_id(i) {}
0063 };
0064 
0065 template <class BidiIterator>
0066 struct saved_matched_paren : public saved_state
0067 {
0068    int index;
0069    sub_match<BidiIterator> sub;
0070    saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){}
0071 };
0072 
0073 template <class BidiIterator>
0074 struct saved_position : public saved_state
0075 {
0076    const re_syntax_base* pstate;
0077    BidiIterator position;
0078    saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){}
0079 };
0080 
0081 template <class BidiIterator>
0082 struct saved_assertion : public saved_position<BidiIterator>
0083 {
0084    bool positive;
0085    saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos) 
0086       : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){}
0087 };
0088 
0089 template <class BidiIterator>
0090 struct saved_repeater : public saved_state
0091 {
0092    repeater_count<BidiIterator> count;
0093    saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
0094       : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
0095 };
0096 
0097 struct saved_extra_block : public saved_state
0098 {
0099    saved_state *base, *end;
0100    saved_extra_block(saved_state* b, saved_state* e) 
0101       : saved_state(saved_state_extra_block), base(b), end(e) {}
0102 };
0103 
0104 struct save_state_init
0105 {
0106    saved_state** stack;
0107    save_state_init(saved_state** base, saved_state** end)
0108       : stack(base)
0109    {
0110       *base = static_cast<saved_state*>(get_mem_block());
0111       *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
0112       --(*end);
0113       (void) new (*end)saved_state(0);
0114       BOOST_REGEX_ASSERT(*end > *base);
0115    }
0116    ~save_state_init()
0117    {
0118       put_mem_block(*stack);
0119       *stack = 0;
0120    }
0121 };
0122 
0123 template <class BidiIterator>
0124 struct saved_single_repeat : public saved_state
0125 {
0126    std::size_t count;
0127    const re_repeat* rep;
0128    BidiIterator last_position;
0129    saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id) 
0130       : saved_state(arg_id), count(c), rep(r), last_position(lp){}
0131 };
0132 
0133 template <class Results>
0134 struct saved_recursion : public saved_state
0135 {
0136    saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2) 
0137       : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {}
0138    int recursion_id;
0139    const re_syntax_base* preturn_address;
0140    Results internal_results, prior_results;
0141 };
0142 
0143 struct saved_change_case : public saved_state
0144 {
0145    bool icase;
0146    saved_change_case(bool c) : saved_state(18), icase(c) {}
0147 };
0148 
0149 struct incrementer
0150 {
0151    incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; }
0152    ~incrementer() { --*m_pu; }
0153    bool operator > (unsigned i) { return *m_pu > i; }
0154 private:
0155    unsigned* m_pu;
0156 };
0157 
0158 template <class BidiIterator, class Allocator, class traits>
0159 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
0160 {
0161    static matcher_proc_type const s_match_vtable[34] = 
0162    {
0163       (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
0164       &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
0165       &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
0166       &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
0167       &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
0168       &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
0169       &perl_matcher<BidiIterator, Allocator, traits>::match_match,
0170       &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
0171       &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
0172       &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
0173       &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
0174       &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
0175       &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
0176       &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
0177       &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
0178       &perl_matcher<BidiIterator, Allocator, traits>::match_set,
0179       &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
0180       &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
0181       &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
0182       &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
0183       &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
0184       &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
0185       // Although this next line *should* be evaluated at compile time, in practice
0186       // some compilers (VC++) emit run-time initialisation which breaks thread
0187       // safety, so use a dispatch function instead:
0188       //(::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),
0189       &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
0190       &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
0191       &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
0192       &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
0193       &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
0194       &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
0195       &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
0196       &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
0197       &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
0198       &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
0199       &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
0200       &perl_matcher<BidiIterator, Allocator, traits>::match_then,
0201    };
0202    incrementer inc(&m_recursions);
0203    if(inc > 80)
0204       raise_error(traits_inst, regex_constants::error_complexity);
0205    push_recursion_stopper();
0206    do{
0207       while(pstate)
0208       {
0209          matcher_proc_type proc = s_match_vtable[pstate->type];
0210          ++state_count;
0211          if(!(this->*proc)())
0212          {
0213             if(state_count > max_state_count)
0214                raise_error(traits_inst, regex_constants::error_complexity);
0215             if((m_match_flags & match_partial) && (position == last) && (position != search_base))
0216                m_has_partial_match = true;
0217             bool successful_unwind = unwind(false);
0218             if((m_match_flags & match_partial) && (position == last) && (position != search_base))
0219                m_has_partial_match = true;
0220             if(!successful_unwind)
0221                return m_recursive_result;
0222          }
0223       }
0224    }while(unwind(true));
0225    return m_recursive_result;
0226 }
0227 
0228 template <class BidiIterator, class Allocator, class traits>
0229 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
0230 {
0231    if(used_block_count)
0232    {
0233       --used_block_count;
0234       saved_state* stack_base;
0235       saved_state* backup_state;
0236       stack_base = static_cast<saved_state*>(get_mem_block());
0237       backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
0238       saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
0239       --block;
0240       (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
0241       m_stack_base = stack_base;
0242       m_backup_state = block;
0243    }
0244    else
0245       raise_error(traits_inst, regex_constants::error_stack);
0246 }
0247 
0248 template <class BidiIterator, class Allocator, class traits>
0249 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
0250 {
0251    //BOOST_REGEX_ASSERT(index);
0252    saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
0253    --pmp;
0254    if(pmp < m_stack_base)
0255    {
0256       extend_stack();
0257       pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
0258       --pmp;
0259    }
0260    (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
0261    m_backup_state = pmp;
0262 }
0263 
0264 template <class BidiIterator, class Allocator, class traits>
0265 inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
0266 {
0267    //BOOST_REGEX_ASSERT(index);
0268    saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
0269    --pmp;
0270    if(pmp < m_stack_base)
0271    {
0272       extend_stack();
0273       pmp = static_cast<saved_change_case*>(m_backup_state);
0274       --pmp;
0275    }
0276    (void) new (pmp)saved_change_case(c);
0277    m_backup_state = pmp;
0278 }
0279 
0280 template <class BidiIterator, class Allocator, class traits>
0281 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
0282 {
0283    saved_state* pmp = m_backup_state;
0284    --pmp;
0285    if(pmp < m_stack_base)
0286    {
0287       extend_stack();
0288       pmp = m_backup_state;
0289       --pmp;
0290    }
0291    (void) new (pmp)saved_state(saved_type_recurse);
0292    m_backup_state = pmp;
0293 }
0294 
0295 template <class BidiIterator, class Allocator, class traits>
0296 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
0297 {
0298    saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
0299    --pmp;
0300    if(pmp < m_stack_base)
0301    {
0302       extend_stack();
0303       pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
0304       --pmp;
0305    }
0306    (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
0307    m_backup_state = pmp;
0308 }
0309 
0310 template <class BidiIterator, class Allocator, class traits>
0311 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
0312 {
0313    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0314    --pmp;
0315    if(pmp < m_stack_base)
0316    {
0317       extend_stack();
0318       pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0319       --pmp;
0320    }
0321    (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
0322    m_backup_state = pmp;
0323 }
0324 
0325 template <class BidiIterator, class Allocator, class traits>
0326 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
0327 {
0328    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0329    --pmp;
0330    if(pmp < m_stack_base)
0331    {
0332       extend_stack();
0333       pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0334       --pmp;
0335    }
0336    (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
0337    m_backup_state = pmp;
0338 }
0339 
0340 template <class BidiIterator, class Allocator, class traits>
0341 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
0342 {
0343    saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
0344    --pmp;
0345    if(pmp < m_stack_base)
0346    {
0347       extend_stack();
0348       pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
0349       --pmp;
0350    }
0351    (void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.empty() ? (INT_MIN + 3) : this->recursion_stack.back().idx);
0352    m_backup_state = pmp;
0353 }
0354 
0355 template <class BidiIterator, class Allocator, class traits>
0356 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
0357 {
0358    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
0359    --pmp;
0360    if(pmp < m_stack_base)
0361    {
0362       extend_stack();
0363       pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
0364       --pmp;
0365    }
0366    (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
0367    m_backup_state = pmp;
0368 }
0369 
0370 template <class BidiIterator, class Allocator, class traits>
0371 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2)
0372 {
0373    saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
0374    --pmp;
0375    if(pmp < m_stack_base)
0376    {
0377       extend_stack();
0378       pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
0379       --pmp;
0380    }
0381    (void) new (pmp)saved_recursion<results_type>(idx, p, presults, presults2);
0382    m_backup_state = pmp;
0383 }
0384 
0385 template <class BidiIterator, class Allocator, class traits>
0386 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
0387 {
0388    // change our case sensitivity:
0389    push_case_change(this->icase);
0390    this->icase = static_cast<const re_case*>(pstate)->icase;
0391    pstate = pstate->next.p;
0392    return true;
0393 }
0394 
0395 template <class BidiIterator, class Allocator, class traits>
0396 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
0397 {
0398    int index = static_cast<const re_brace*>(pstate)->index;
0399    icase = static_cast<const re_brace*>(pstate)->icase;
0400    switch(index)
0401    {
0402    case 0:
0403       pstate = pstate->next.p;
0404       break;
0405    case -1:
0406    case -2:
0407       {
0408          // forward lookahead assert:
0409          const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0410          pstate = pstate->next.p->next.p;
0411          push_assertion(next_pstate, index == -1);
0412          break;
0413       }
0414    case -3:
0415       {
0416          // independent sub-expression, currently this is always recursive:
0417          bool old_independent = m_independent;
0418          m_independent = true;
0419          const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0420          pstate = pstate->next.p->next.p;
0421          bool r = false;
0422 #if !defined(BOOST_NO_EXCEPTIONS)
0423       try{
0424 #endif
0425          r = match_all_states();
0426          if(!r && !m_independent)
0427          {
0428             // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent 
0429             // sub failed, need to unwind everything else:
0430             while(unwind(false));
0431             return false;
0432          }
0433 #if !defined(BOOST_NO_EXCEPTIONS)
0434       }
0435       catch(...)
0436       {
0437          pstate = next_pstate;
0438          // unwind all pushed states, apart from anything else this
0439          // ensures that all the states are correctly destructed
0440          // not just the memory freed.
0441          while(unwind(true)) {}
0442          throw;
0443       }
0444 #endif
0445       pstate = next_pstate;
0446       m_independent = old_independent;
0447 #ifdef BOOST_REGEX_MATCH_EXTRA
0448          if(r && (m_match_flags & match_extra))
0449          {
0450             //
0451             // our captures have been stored in *m_presult
0452             // we need to unpack them, and insert them
0453             // back in the right order when we unwind the stack:
0454             //
0455             match_results<BidiIterator, Allocator> temp_match(*m_presult);
0456             unsigned i;
0457             for(i = 0; i < temp_match.size(); ++i)
0458                (*m_presult)[i].get_captures().clear();
0459             // match everything else:
0460 #if !defined(BOOST_NO_EXCEPTIONS)
0461             try{
0462 #endif
0463                r = match_all_states();
0464 #if !defined(BOOST_NO_EXCEPTIONS)
0465             }
0466             catch(...)
0467             {
0468                pstate = next_pstate;
0469                // unwind all pushed states, apart from anything else this
0470                // ensures that all the states are correctly destructed
0471                // not just the memory freed.
0472                while(unwind(true)) {}
0473                throw;
0474             }
0475 #endif
0476          // now place the stored captures back:
0477             for(i = 0; i < temp_match.size(); ++i)
0478             {
0479                typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
0480                seq& s1 = (*m_presult)[i].get_captures();
0481                const seq& s2 = temp_match[i].captures();
0482                s1.insert(
0483                   s1.end(), 
0484                   s2.begin(), 
0485                   s2.end());
0486             }
0487          }
0488 #endif
0489          return r;
0490       }
0491    case -4:
0492       {
0493       // conditional expression:
0494       const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
0495       BOOST_REGEX_ASSERT(alt->type == syntax_element_alt);
0496       pstate = alt->next.p;
0497       if(pstate->type == syntax_element_assert_backref)
0498       {
0499          if(!match_assert_backref())
0500             pstate = alt->alt.p;
0501          break;
0502       }
0503       else
0504       {
0505          // zero width assertion, have to match this recursively:
0506          BOOST_REGEX_ASSERT(pstate->type == syntax_element_startmark);
0507          bool negated = static_cast<const re_brace*>(pstate)->index == -2;
0508          BidiIterator saved_position = position;
0509          const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0510          pstate = pstate->next.p->next.p;
0511 #if !defined(BOOST_NO_EXCEPTIONS)
0512          try{
0513 #endif
0514             bool r = match_all_states();
0515             position = saved_position;
0516             if(negated)
0517                r = !r;
0518             if(r)
0519                pstate = next_pstate;
0520             else
0521                pstate = alt->alt.p;
0522 #if !defined(BOOST_NO_EXCEPTIONS)
0523          }
0524          catch(...)
0525          {
0526             pstate = next_pstate;
0527             // unwind all pushed states, apart from anything else this
0528             // ensures that all the states are correctly destructed
0529             // not just the memory freed.
0530             while(unwind(true)){}
0531             throw;
0532          }
0533 #endif
0534          break;
0535       }
0536       }
0537    case -5:
0538       {
0539          push_matched_paren(0, (*m_presult)[0]);
0540          m_presult->set_first(position, 0, true);
0541          pstate = pstate->next.p;
0542          break;
0543       }
0544    default:
0545    {
0546       BOOST_REGEX_ASSERT(index > 0);
0547       if((m_match_flags & match_nosubs) == 0)
0548       {
0549          push_matched_paren(index, (*m_presult)[index]);
0550          m_presult->set_first(position, index);
0551       }
0552       pstate = pstate->next.p;
0553       break;
0554    }
0555    }
0556    return true;
0557 }
0558 
0559 template <class BidiIterator, class Allocator, class traits>
0560 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
0561 {
0562    bool take_first, take_second;
0563    const re_alt* jmp = static_cast<const re_alt*>(pstate);
0564 
0565    // find out which of these two alternatives we need to take:
0566    if(position == last)
0567    {
0568       take_first = jmp->can_be_null & mask_take;
0569       take_second = jmp->can_be_null & mask_skip;
0570    }
0571    else
0572    {
0573       take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
0574       take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
0575   }
0576 
0577    if(take_first)
0578    {
0579       // we can take the first alternative,
0580       // see if we need to push next alternative:
0581       if(take_second)
0582       {
0583          push_alt(jmp->alt.p);
0584       }
0585       pstate = pstate->next.p;
0586       return true;
0587    }
0588    if(take_second)
0589    {
0590       pstate = jmp->alt.p;
0591       return true;
0592    }
0593    return false;  // neither option is possible
0594 }
0595 
0596 template <class BidiIterator, class Allocator, class traits>
0597 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
0598 {
0599 #ifdef BOOST_MSVC
0600 #pragma warning(push)
0601 #pragma warning(disable:4127 4244)
0602 #endif
0603 #ifdef BOOST_BORLANDC
0604 #pragma option push -w-8008 -w-8066 -w-8004
0605 #endif
0606    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0607 
0608    // find out which of these two alternatives we need to take:
0609    bool take_first, take_second;
0610    if(position == last)
0611    {
0612       take_first = rep->can_be_null & mask_take;
0613       take_second = rep->can_be_null & mask_skip;
0614    }
0615    else
0616    {
0617       take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
0618       take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
0619    }
0620 
0621    if((m_backup_state->state_id != saved_state_repeater_count) 
0622       || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
0623       || (next_count->get_id() != rep->state_id))
0624    {
0625       // we're moving to a different repeat from the last
0626       // one, so set up a counter object:
0627       push_repeater_count(rep->state_id, &next_count);
0628    }
0629    //
0630    // If we've had at least one repeat already, and the last one 
0631    // matched the NULL string then set the repeat count to
0632    // maximum:
0633    //
0634    next_count->check_null_repeat(position, rep->max);
0635 
0636    if(next_count->get_count() < rep->min)
0637    {
0638       // we must take the repeat:
0639       if(take_first)
0640       {
0641          // increase the counter:
0642          ++(*next_count);
0643          pstate = rep->next.p;
0644          return true;
0645       }
0646       return false;
0647    }
0648 
0649    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0650    if(greedy)
0651    {
0652       // try and take the repeat if we can:
0653       if((next_count->get_count() < rep->max) && take_first)
0654       {
0655          if(take_second)
0656          {
0657             // store position in case we fail:
0658             push_alt(rep->alt.p);
0659          }
0660          // increase the counter:
0661          ++(*next_count);
0662          pstate = rep->next.p;
0663          return true;
0664       }
0665       else if(take_second)
0666       {
0667          pstate = rep->alt.p;
0668          return true;
0669       }
0670       return false; // can't take anything, fail...
0671    }
0672    else // non-greedy
0673    {
0674       // try and skip the repeat if we can:
0675       if(take_second)
0676       {
0677          if((next_count->get_count() < rep->max) && take_first)
0678          {
0679             // store position in case we fail:
0680             push_non_greedy_repeat(rep->next.p);
0681          }
0682          pstate = rep->alt.p;
0683          return true;
0684       }
0685       if((next_count->get_count() < rep->max) && take_first)
0686       {
0687          // increase the counter:
0688          ++(*next_count);
0689          pstate = rep->next.p;
0690          return true;
0691       }
0692    }
0693    return false;
0694 #ifdef BOOST_BORLANDC
0695 #pragma option pop
0696 #endif
0697 #ifdef BOOST_MSVC
0698 #pragma warning(pop)
0699 #endif
0700 }
0701 
0702 template <class BidiIterator, class Allocator, class traits>
0703 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
0704 {
0705    std::size_t count = 0;
0706    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0707    re_syntax_base* psingle = rep->next.p;
0708    // match compulsory repeats first:
0709    while(count < rep->min)
0710    {
0711       pstate = psingle;
0712       if(!match_wild())
0713          return false;
0714       ++count;
0715    }
0716    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0717    if(greedy)
0718    {
0719       // repeat for as long as we can:
0720       while(count < rep->max)
0721       {
0722          pstate = psingle;
0723          if(!match_wild())
0724             break;
0725          ++count;
0726       }
0727       // remember where we got to if this is a leading repeat:
0728       if((rep->leading) && (count < rep->max))
0729          restart = position;
0730       // push backtrack info if available:
0731       if(count - rep->min)
0732          push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0733       // jump to next state:
0734       pstate = rep->alt.p;
0735       return true;
0736    }
0737    else
0738    {
0739       // non-greedy, push state and return true if we can skip:
0740       if(count < rep->max)
0741          push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
0742       pstate = rep->alt.p;
0743       return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0744    }
0745 }
0746 
0747 template <class BidiIterator, class Allocator, class traits>
0748 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
0749 {
0750    if(m_match_flags & match_not_dot_null)
0751       return match_dot_repeat_slow();
0752    if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
0753       return match_dot_repeat_slow();
0754 
0755    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0756    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0757    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));
0758    if(rep->min > count)
0759    {
0760       position = last;
0761       return false;  // not enough text left to match
0762    }
0763    std::advance(position, count);
0764 
0765    if(greedy)
0766    {
0767       if((rep->leading) && (count < rep->max))
0768          restart = position;
0769       // push backtrack info if available:
0770       if(count - rep->min)
0771          push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0772       // jump to next state:
0773       pstate = rep->alt.p;
0774       return true;
0775    }
0776    else
0777    {
0778       // non-greedy, push state and return true if we can skip:
0779       if(count < rep->max)
0780          push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
0781       pstate = rep->alt.p;
0782       return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0783    }
0784 }
0785 
0786 template <class BidiIterator, class Allocator, class traits>
0787 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
0788 {
0789 #ifdef BOOST_MSVC
0790 #pragma warning(push)
0791 #pragma warning(disable:4127)
0792 #endif
0793 #ifdef BOOST_BORLANDC
0794 #pragma option push -w-8008 -w-8066 -w-8004
0795 #endif
0796    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0797    BOOST_REGEX_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
0798    const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
0799    std::size_t count = 0;
0800    //
0801    // start by working out how much we can skip:
0802    //
0803    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0804    std::size_t desired = greedy ? rep->max : rep->min;
0805    if(::boost::is_random_access_iterator<BidiIterator>::value)
0806    {
0807       BidiIterator end = position;
0808       // Move end forward by "desired", preferably without using distance or advance if we can
0809       // as these can be slow for some iterator types.
0810       std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0811       if(desired >= len)
0812          end = last;
0813       else
0814          std::advance(end, desired);
0815       BidiIterator origin(position);
0816       while((position != end) && (traits_inst.translate(*position, icase) == what))
0817       {
0818          ++position;
0819       }
0820       count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0821    }
0822    else
0823    {
0824       while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
0825       {
0826          ++position;
0827          ++count;
0828       }
0829    }
0830 
0831    if(count < rep->min)
0832       return false;
0833 
0834    if(greedy)
0835    {
0836       if((rep->leading) && (count < rep->max))
0837          restart = position;
0838       // push backtrack info if available:
0839       if(count - rep->min)
0840          push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0841       // jump to next state:
0842       pstate = rep->alt.p;
0843       return true;
0844    }
0845    else
0846    {
0847       // non-greedy, push state and return true if we can skip:
0848       if(count < rep->max)
0849          push_single_repeat(count, rep, position, saved_state_rep_char);
0850       pstate = rep->alt.p;
0851       return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0852    }
0853 #ifdef BOOST_BORLANDC
0854 #pragma option pop
0855 #endif
0856 #ifdef BOOST_MSVC
0857 #pragma warning(pop)
0858 #endif
0859 }
0860 
0861 template <class BidiIterator, class Allocator, class traits>
0862 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
0863 {
0864 #ifdef BOOST_MSVC
0865 #pragma warning(push)
0866 #pragma warning(disable:4127)
0867 #endif
0868 #ifdef BOOST_BORLANDC
0869 #pragma option push -w-8008 -w-8066 -w-8004
0870 #endif
0871    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0872    const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
0873    std::size_t count = 0;
0874    //
0875    // start by working out how much we can skip:
0876    //
0877    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0878    std::size_t desired = greedy ? rep->max : rep->min;
0879    if(::boost::is_random_access_iterator<BidiIterator>::value)
0880    {
0881       BidiIterator end = position;
0882       // Move end forward by "desired", preferably without using distance or advance if we can
0883       // as these can be slow for some iterator types.
0884       std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0885       if(desired >= len)
0886          end = last;
0887       else
0888          std::advance(end, desired);
0889       BidiIterator origin(position);
0890       while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
0891       {
0892          ++position;
0893       }
0894       count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0895    }
0896    else
0897    {
0898       while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
0899       {
0900          ++position;
0901          ++count;
0902       }
0903    }
0904 
0905    if(count < rep->min)
0906       return false;
0907 
0908    if(greedy)
0909    {
0910       if((rep->leading) && (count < rep->max))
0911          restart = position;
0912       // push backtrack info if available:
0913       if(count - rep->min)
0914          push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0915       // jump to next state:
0916       pstate = rep->alt.p;
0917       return true;
0918    }
0919    else
0920    {
0921       // non-greedy, push state and return true if we can skip:
0922       if(count < rep->max)
0923          push_single_repeat(count, rep, position, saved_state_rep_short_set);
0924       pstate = rep->alt.p;
0925       return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0926    }
0927 #ifdef BOOST_BORLANDC
0928 #pragma option pop
0929 #endif
0930 #ifdef BOOST_MSVC
0931 #pragma warning(pop)
0932 #endif
0933 }
0934 
0935 template <class BidiIterator, class Allocator, class traits>
0936 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
0937 {
0938 #ifdef BOOST_MSVC
0939 #pragma warning(push)
0940 #pragma warning(disable:4127)
0941 #endif
0942 #ifdef BOOST_BORLANDC
0943 #pragma option push -w-8008 -w-8066 -w-8004
0944 #endif
0945    typedef typename traits::char_class_type m_type;
0946    const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0947    const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
0948    std::size_t count = 0;
0949    //
0950    // start by working out how much we can skip:
0951    //
0952    bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);   
0953    std::size_t desired = greedy ? rep->max : rep->min;
0954    if(::boost::is_random_access_iterator<BidiIterator>::value)
0955    {
0956       BidiIterator end = position;
0957       // Move end forward by "desired", preferably without using distance or advance if we can
0958       // as these can be slow for some iterator types.
0959       std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0960       if(desired >= len)
0961          end = last;
0962       else
0963          std::advance(end, desired);
0964       BidiIterator origin(position);
0965       while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
0966       {
0967          ++position;
0968       }
0969       count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0970    }
0971    else
0972    {
0973       while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
0974       {
0975          ++position;
0976          ++count;
0977       }
0978    }
0979 
0980    if(count < rep->min)
0981       return false;
0982 
0983    if(greedy)
0984    {
0985       if((rep->leading) && (count < rep->max))
0986          restart = position;
0987       // push backtrack info if available:
0988       if(count - rep->min)
0989          push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0990       // jump to next state:
0991       pstate = rep->alt.p;
0992       return true;
0993    }
0994    else
0995    {
0996       // non-greedy, push state and return true if we can skip:
0997       if(count < rep->max)
0998          push_single_repeat(count, rep, position, saved_state_rep_long_set);
0999       pstate = rep->alt.p;
1000       return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
1001    }
1002 #ifdef BOOST_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 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
1012 {
1013    BOOST_REGEX_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    for(typename std::vector<recursion_info<results_type> >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
1019    {
1020       if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
1021       {
1022          if(i->location_of_start == position)
1023             return false;
1024          break;
1025       }
1026    }
1027    //
1028    // Backup call stack:
1029    //
1030    push_recursion_pop();
1031    //
1032    // Set new call stack:
1033    //
1034    if(recursion_stack.capacity() == 0)
1035    {
1036       recursion_stack.reserve(50);
1037    }
1038    recursion_stack.push_back(recursion_info<results_type>());
1039    recursion_stack.back().preturn_address = pstate->next.p;
1040    recursion_stack.back().results = *m_presult;
1041    pstate = static_cast<const re_jump*>(pstate)->alt.p;
1042    recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
1043    recursion_stack.back().location_of_start = position;
1044    //if(static_cast<const re_recurse*>(pstate)->state_id > 0)
1045    {
1046       push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
1047    }
1048 
1049    return true;
1050 }
1051 
1052 template <class BidiIterator, class Allocator, class traits>
1053 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
1054 {
1055    int index = static_cast<const re_brace*>(pstate)->index;
1056    icase = static_cast<const re_brace*>(pstate)->icase;
1057    if(index > 0)
1058    {
1059       if((m_match_flags & match_nosubs) == 0)
1060       {
1061          m_presult->set_second(position, index);
1062       }
1063       if(!recursion_stack.empty())
1064       {
1065          if(index == recursion_stack.back().idx)
1066          {
1067             pstate = recursion_stack.back().preturn_address;
1068             *m_presult = recursion_stack.back().results;
1069             push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1070             recursion_stack.pop_back();
1071             push_repeater_count(-(2 + index), &next_count);
1072          }
1073       }
1074    }
1075    else if((index < 0) && (index != -4))
1076    {
1077       // matched forward lookahead:
1078       pstate = 0;
1079       return true;
1080    }
1081    pstate = pstate->next.p;
1082    return true;
1083 }
1084 
1085 template <class BidiIterator, class Allocator, class traits>
1086 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
1087 {
1088    if(!recursion_stack.empty())
1089    {
1090       BOOST_REGEX_ASSERT(0 == recursion_stack.back().idx);
1091       pstate = recursion_stack.back().preturn_address;
1092       push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results);
1093       *m_presult = recursion_stack.back().results;
1094       recursion_stack.pop_back();
1095       return true;
1096    }
1097    if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
1098       return false;
1099    if((m_match_flags & match_all) && (position != last))
1100       return false;
1101    if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
1102       return false;
1103    m_presult->set_second(position);
1104    pstate = 0;
1105    m_has_found_match = true;
1106    if((m_match_flags & match_posix) == match_posix)
1107    {
1108       m_result.maybe_assign(*m_presult);
1109       if((m_match_flags & match_any) == 0)
1110          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 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    switch(static_cast<const re_commit*>(pstate)->action)
1132    {
1133    case commit_commit:
1134       restart = last;
1135       break;
1136    case commit_skip:
1137       if(base != position)
1138       {
1139          restart = position;
1140          // Have to decrement restart since it will get incremented again later:
1141          --restart;
1142       }
1143       break;
1144    case commit_prune:
1145       break;
1146    }
1147 
1148    saved_state* pmp = m_backup_state;
1149    --pmp;
1150    if(pmp < m_stack_base)
1151    {
1152       extend_stack();
1153       pmp = m_backup_state;
1154       --pmp;
1155    }
1156    (void) new (pmp)saved_state(16);
1157    m_backup_state = pmp;
1158    pstate = pstate->next.p;
1159    return true;
1160 }
1161 
1162 template <class BidiIterator, class Allocator, class traits>
1163 bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
1164 {
1165    // Just leave a mark that we need to skip to next alternative:
1166    saved_state* pmp = m_backup_state;
1167    --pmp;
1168    if(pmp < m_stack_base)
1169    {
1170       extend_stack();
1171       pmp = m_backup_state;
1172       --pmp;
1173    }
1174    (void) new (pmp)saved_state(17);
1175    m_backup_state = pmp;
1176    pstate = pstate->next.p;
1177    return true;
1178 }
1179 
1180 template <class BidiIterator, class Allocator, class traits>
1181 bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
1182 {
1183    while(pstate)
1184    {
1185       if(pstate->type == syntax_element_endmark)
1186       {
1187          if(static_cast<const re_brace*>(pstate)->index == index)
1188          {
1189             if(have_match)
1190                return this->match_endmark();
1191             pstate = pstate->next.p;
1192             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             const re_syntax_base* sp = pstate;
1199             match_endmark();
1200             if(!pstate)
1201             {
1202                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                if (!pstate)
1206                   pstate = sp->next.p;
1207             }
1208          }
1209          continue;
1210       }
1211       else if(pstate->type == syntax_element_match)
1212          return true;
1213       else if(pstate->type == syntax_element_startmark)
1214       {
1215          int idx = static_cast<const re_brace*>(pstate)->index;
1216          pstate = pstate->next.p;
1217          skip_until_paren(idx, false);
1218          continue;
1219       }
1220       pstate = pstate->next.p;
1221    }
1222    return true;
1223 }
1224 
1225 /****************************************************************************
1226 
1227 Unwind and associated procedures 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 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    m_recursive_result = have_match;
1259    m_unwound_lookahead = false;
1260    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    do
1267    {
1268       unwinder = s_unwind_table[m_backup_state->state_id];
1269       cont = (this->*unwinder)(m_recursive_result);
1270    }while(cont);
1271    //
1272    // return true if we have more states to try:
1273    //
1274    return pstate ? true : false;
1275 }
1276 
1277 template <class BidiIterator, class Allocator, class traits>
1278 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
1279 {
1280    pstate = 0;   // nothing left to search
1281    return false; // end of stack nothing more to search
1282 }
1283 
1284 template <class BidiIterator, class Allocator, class traits>
1285 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_case(bool)
1286 {
1287    saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
1288    icase = pmp->icase;
1289    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1290    m_backup_state = pmp;
1291    return true;
1292 }
1293 
1294 template <class BidiIterator, class Allocator, class traits>
1295 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
1296 {
1297    saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
1298    // restore previous values if no match was found:
1299    if(!have_match)
1300    {
1301       m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
1302       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    m_backup_state = pmp+1;
1313    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1314    return true; // keep looking
1315 }
1316 
1317 template <class BidiIterator, class Allocator, class traits>
1318 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
1319 {
1320    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1321    pstate = 0;   // nothing left to search
1322    return false; // end of stack nothing more to search
1323 }
1324 
1325 template <class BidiIterator, class Allocator, class traits>
1326 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
1327 {
1328    saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
1329    pstate = pmp->pstate;
1330    position = pmp->position;
1331    bool result = (r == pmp->positive);
1332    m_recursive_result = pmp->positive ? r : !r;
1333    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1334    m_backup_state = pmp;
1335    m_unwound_lookahead = true;
1336    return !result; // return false if the assertion was matched to stop search.
1337 }
1338 
1339 template <class BidiIterator, class Allocator, class traits>
1340 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
1341 {
1342    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1343    if(!r)
1344    {
1345       pstate = pmp->pstate;
1346       position = pmp->position;
1347    }
1348    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1349    m_backup_state = pmp;
1350    m_unwound_alt = !r;
1351    return r; 
1352 }
1353 
1354 template <class BidiIterator, class Allocator, class traits>
1355 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
1356 {
1357    ++used_block_count;
1358    saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
1359    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1360    m_backup_state = pmp;
1361    return true; // keep looking
1362 }
1363 
1364 template <class BidiIterator, class Allocator, class traits>
1365 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
1366 {
1367    saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
1368    void* condemmed = m_stack_base;
1369    m_stack_base = pmp->base;
1370    m_backup_state = pmp->end;
1371    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1372    put_mem_block(condemmed);
1373    return true; // keep looking
1374 }
1375 
1376 template <class BidiIterator, class Allocator, class traits>
1377 inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
1378 {
1379    saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1380    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++);
1381    m_backup_state = p;
1382 }
1383 
1384 template <class BidiIterator, class Allocator, class traits>
1385 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
1386 {
1387    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1388 
1389    // if we have a match, just discard this state:
1390    if(r) 
1391    {
1392       destroy_single_repeat();
1393       return true;
1394    }
1395 
1396    const re_repeat* rep = pmp->rep;
1397    std::size_t count = pmp->count;
1398    BOOST_REGEX_ASSERT(rep->next.p != 0);
1399    BOOST_REGEX_ASSERT(rep->alt.p != 0);
1400 
1401    count -= rep->min;
1402    
1403    if((m_match_flags & match_partial) && (position == last))
1404       m_has_partial_match = true;
1405 
1406    BOOST_REGEX_ASSERT(count);
1407    position = pmp->last_position;
1408 
1409    // backtrack till we can skip out:
1410    do
1411    {
1412       --position;
1413       --count;
1414       ++state_count;
1415    }while(count && !can_start(*position, rep->_map, mask_skip));
1416 
1417    // if we've hit base, destroy this state:
1418    if(count == 0)
1419    {
1420          destroy_single_repeat();
1421          if(!can_start(*position, rep->_map, mask_skip))
1422             return true;
1423    }
1424    else
1425    {
1426       pmp->count = count + rep->min;
1427       pmp->last_position = position;
1428    }
1429    pstate = rep->alt.p;
1430    return false;
1431 }
1432 
1433 template <class BidiIterator, class Allocator, class traits>
1434 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
1435 {
1436    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1437 
1438    // if we have a match, just discard this state:
1439    if(r) 
1440    {
1441       destroy_single_repeat();
1442       return true;
1443    }
1444 
1445    const re_repeat* rep = pmp->rep;
1446    std::size_t count = pmp->count;
1447    BOOST_REGEX_ASSERT(rep->type == syntax_element_dot_rep);
1448    BOOST_REGEX_ASSERT(rep->next.p != 0);
1449    BOOST_REGEX_ASSERT(rep->alt.p != 0);
1450    BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_wild);
1451 
1452    BOOST_REGEX_ASSERT(count < rep->max);
1453    pstate = rep->next.p;
1454    position = pmp->last_position;
1455 
1456    if(position != last)
1457    {
1458       // wind forward until we can skip out of the repeat:
1459       do
1460       {
1461          if(!match_wild())
1462          {
1463             // failed repeat match, discard this state and look for another:
1464             destroy_single_repeat();
1465             return true;
1466          }
1467          ++count;
1468          ++state_count;
1469          pstate = rep->next.p;
1470       }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1471    }   
1472    if(position == last)
1473    {
1474       // can't repeat any more, remove the pushed state: 
1475       destroy_single_repeat();
1476       if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1477          m_has_partial_match = true;
1478       if(0 == (rep->can_be_null & mask_skip))
1479          return true;
1480    }
1481    else if(count == rep->max)
1482    {
1483       // can't repeat any more, remove the pushed state: 
1484       destroy_single_repeat();
1485       if(!can_start(*position, rep->_map, mask_skip))
1486          return true;
1487    }
1488    else
1489    {
1490       pmp->count = count;
1491       pmp->last_position = position;
1492    }
1493    pstate = rep->alt.p;
1494    return false;
1495 }
1496 
1497 template <class BidiIterator, class Allocator, class traits>
1498 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
1499 {
1500    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1501 
1502    // if we have a match, just discard this state:
1503    if(r) 
1504    {
1505       destroy_single_repeat();
1506       return true;
1507    }
1508 
1509    const re_repeat* rep = pmp->rep;
1510    std::size_t count = pmp->count;
1511 
1512    BOOST_REGEX_ASSERT(count < rep->max);
1513    position = pmp->last_position;
1514    if(position != last)
1515    {
1516 
1517       // wind forward until we can skip out of the repeat:
1518       do
1519       {
1520          ++position;
1521          ++count;
1522          ++state_count;
1523       }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1524    }
1525 
1526    // remember where we got to if this is a leading repeat:
1527    if((rep->leading) && (count < rep->max))
1528       restart = position;
1529    if(position == last)
1530    {
1531       // can't repeat any more, remove the pushed state: 
1532       destroy_single_repeat();
1533       if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1534          m_has_partial_match = true;
1535       if(0 == (rep->can_be_null & mask_skip))
1536          return true;
1537    }
1538    else if(count == rep->max)
1539    {
1540       // can't repeat any more, remove the pushed state: 
1541       destroy_single_repeat();
1542       if(!can_start(*position, rep->_map, mask_skip))
1543          return true;
1544    }
1545    else
1546    {
1547       pmp->count = count;
1548       pmp->last_position = position;
1549    }
1550    pstate = rep->alt.p;
1551    return false;
1552 }
1553 
1554 template <class BidiIterator, class Allocator, class traits>
1555 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
1556 {
1557    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1558 
1559    // if we have a match, just discard this state:
1560    if(r) 
1561    {
1562       destroy_single_repeat();
1563       return true;
1564    }
1565 
1566    const re_repeat* rep = pmp->rep;
1567    std::size_t count = pmp->count;
1568    pstate = rep->next.p;
1569    const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
1570    position = pmp->last_position;
1571 
1572    BOOST_REGEX_ASSERT(rep->type == syntax_element_char_rep);
1573    BOOST_REGEX_ASSERT(rep->next.p != 0);
1574    BOOST_REGEX_ASSERT(rep->alt.p != 0);
1575    BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_literal);
1576    BOOST_REGEX_ASSERT(count < rep->max);
1577 
1578    if(position != last)
1579    {
1580       // wind forward until we can skip out of the repeat:
1581       do
1582       {
1583          if(traits_inst.translate(*position, icase) != what)
1584          {
1585             // failed repeat match, discard this state and look for another:
1586             destroy_single_repeat();
1587             return true;
1588          }
1589          ++count;
1590          ++ position;
1591          ++state_count;
1592          pstate = rep->next.p;
1593       }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1594    }   
1595    // remember where we got to if this is a leading repeat:
1596    if((rep->leading) && (count < rep->max))
1597       restart = position;
1598    if(position == last)
1599    {
1600       // can't repeat any more, remove the pushed state: 
1601       destroy_single_repeat();
1602       if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1603          m_has_partial_match = true;
1604       if(0 == (rep->can_be_null & mask_skip))
1605          return true;
1606    }
1607    else if(count == rep->max)
1608    {
1609       // can't repeat any more, remove the pushed state: 
1610       destroy_single_repeat();
1611       if(!can_start(*position, rep->_map, mask_skip))
1612          return true;
1613    }
1614    else
1615    {
1616       pmp->count = count;
1617       pmp->last_position = position;
1618    }
1619    pstate = rep->alt.p;
1620    return false;
1621 }
1622 
1623 template <class BidiIterator, class Allocator, class traits>
1624 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
1625 {
1626    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1627 
1628    // if we have a match, just discard this state:
1629    if(r) 
1630    {
1631       destroy_single_repeat();
1632       return true;
1633    }
1634 
1635    const re_repeat* rep = pmp->rep;
1636    std::size_t count = pmp->count;
1637    pstate = rep->next.p;
1638    const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
1639    position = pmp->last_position;
1640 
1641    BOOST_REGEX_ASSERT(rep->type == syntax_element_short_set_rep);
1642    BOOST_REGEX_ASSERT(rep->next.p != 0);
1643    BOOST_REGEX_ASSERT(rep->alt.p != 0);
1644    BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_set);
1645    BOOST_REGEX_ASSERT(count < rep->max);
1646    
1647    if(position != last)
1648    {
1649       // wind forward until we can skip out of the repeat:
1650       do
1651       {
1652          if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
1653          {
1654             // failed repeat match, discard this state and look for another:
1655             destroy_single_repeat();
1656             return true;
1657          }
1658          ++count;
1659          ++ position;
1660          ++state_count;
1661          pstate = rep->next.p;
1662       }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1663    }   
1664    // remember where we got to if this is a leading repeat:
1665    if((rep->leading) && (count < rep->max))
1666       restart = position;
1667    if(position == last)
1668    {
1669       // can't repeat any more, remove the pushed state: 
1670       destroy_single_repeat();
1671       if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1672          m_has_partial_match = true;
1673       if(0 == (rep->can_be_null & mask_skip))
1674          return true;
1675    }
1676    else if(count == rep->max)
1677    {
1678       // can't repeat any more, remove the pushed state: 
1679       destroy_single_repeat();
1680       if(!can_start(*position, rep->_map, mask_skip))
1681          return true;
1682    }
1683    else
1684    {
1685       pmp->count = count;
1686       pmp->last_position = position;
1687    }
1688    pstate = rep->alt.p;
1689    return false;
1690 }
1691 
1692 template <class BidiIterator, class Allocator, class traits>
1693 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
1694 {
1695    typedef typename traits::char_class_type m_type;
1696    saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1697 
1698    // if we have a match, just discard this state:
1699    if(r)
1700    {
1701       destroy_single_repeat();
1702       return true;
1703    }
1704 
1705    const re_repeat* rep = pmp->rep;
1706    std::size_t count = pmp->count;
1707    pstate = rep->next.p;
1708    const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
1709    position = pmp->last_position;
1710 
1711    BOOST_REGEX_ASSERT(rep->type == syntax_element_long_set_rep);
1712    BOOST_REGEX_ASSERT(rep->next.p != 0);
1713    BOOST_REGEX_ASSERT(rep->alt.p != 0);
1714    BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_long_set);
1715    BOOST_REGEX_ASSERT(count < rep->max);
1716 
1717    if(position != last)
1718    {
1719       // wind forward until we can skip out of the repeat:
1720       do
1721       {
1722          if(position == re_is_set_member(position, last, set, re.get_data(), icase))
1723          {
1724             // failed repeat match, discard this state and look for another:
1725             destroy_single_repeat();
1726             return true;
1727          }
1728          ++position;
1729          ++count;
1730          ++state_count;
1731          pstate = rep->next.p;
1732       }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1733    }   
1734    // remember where we got to if this is a leading repeat:
1735    if((rep->leading) && (count < rep->max))
1736       restart = position;
1737    if(position == last)
1738    {
1739       // can't repeat any more, remove the pushed state:
1740       destroy_single_repeat();
1741       if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1742          m_has_partial_match = true;
1743       if(0 == (rep->can_be_null & mask_skip))
1744          return true;
1745    }
1746    else if(count == rep->max)
1747    {
1748       // can't repeat any more, remove the pushed state: 
1749       destroy_single_repeat();
1750       if(!can_start(*position, rep->_map, mask_skip))
1751          return true;
1752    }
1753    else
1754    {
1755       pmp->count = count;
1756       pmp->last_position = position;
1757    }
1758    pstate = rep->alt.p;
1759    return false;
1760 }
1761 
1762 template <class BidiIterator, class Allocator, class traits>
1763 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
1764 {
1765    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1766    if(!r)
1767    {
1768       position = pmp->position;
1769       pstate = pmp->pstate;
1770       ++(*next_count);
1771    }
1772    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1773    m_backup_state = pmp;
1774    return r;
1775 }
1776 
1777 template <class BidiIterator, class Allocator, class traits>
1778 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
1779 {
1780    // We are backtracking back inside a recursion, need to push the info
1781    // back onto the recursion stack, and do so unconditionally, otherwise
1782    // we can get mismatched pushes and pops...
1783    saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
1784    if (!r)
1785    {
1786       recursion_stack.push_back(recursion_info<results_type>());
1787       recursion_stack.back().idx = pmp->recursion_id;
1788       recursion_stack.back().preturn_address = pmp->preturn_address;
1789       recursion_stack.back().results = pmp->prior_results;
1790       recursion_stack.back().location_of_start = position;
1791       *m_presult = pmp->internal_results;
1792    }
1793    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1794    m_backup_state = pmp;
1795    return true;
1796 }
1797 
1798 template <class BidiIterator, class Allocator, class traits>
1799 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
1800 {
1801    // Backtracking out of a recursion, we must pop state off the recursion
1802    // stack unconditionally to ensure matched pushes and pops:
1803    saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1804    if (!r && !recursion_stack.empty())
1805    {
1806       *m_presult = recursion_stack.back().results;
1807       position = recursion_stack.back().location_of_start;
1808       recursion_stack.pop_back();
1809    }
1810    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1811    m_backup_state = pmp;
1812    return true;
1813 }
1814 
1815 template <class BidiIterator, class Allocator, class traits>
1816 void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
1817 {
1818    saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1819    --pmp;
1820    if(pmp < m_stack_base)
1821    {
1822       extend_stack();
1823       pmp = static_cast<saved_state*>(m_backup_state);
1824       --pmp;
1825    }
1826    (void) new (pmp)saved_state(15);
1827    m_backup_state = pmp;
1828 }
1829 
1830 template <class BidiIterator, class Allocator, class traits>
1831 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_commit(bool b)
1832 {
1833    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1834    while(unwind(b) && !m_unwound_lookahead){}
1835    if(m_unwound_lookahead && pstate)
1836    {
1837       //
1838       // If we stop because we just unwound an assertion, put the
1839       // commit state back on the stack again:
1840       //
1841       m_unwound_lookahead = false;
1842       saved_state* pmp = m_backup_state;
1843       --pmp;
1844       if(pmp < m_stack_base)
1845       {
1846          extend_stack();
1847          pmp = m_backup_state;
1848          --pmp;
1849       }
1850       (void) new (pmp)saved_state(16);
1851       m_backup_state = pmp;
1852    }
1853    // This prevents us from stopping when we exit from an independent sub-expression:
1854    m_independent = false;
1855    return false;
1856 }
1857 
1858 template <class BidiIterator, class Allocator, class traits>
1859 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_then(bool b)
1860 {
1861    // Unwind everything till we hit an alternative:
1862    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1863    bool result = false;
1864    while((result = unwind(b)) && !m_unwound_alt){}
1865    // We're now pointing at the next alternative, need one more backtrack 
1866    // since *all* the other alternatives must fail once we've reached a THEN clause:
1867    if(result && m_unwound_alt)
1868       unwind(b);
1869    return false;
1870 }
1871 
1872 /*
1873 template <class BidiIterator, class Allocator, class traits>
1874 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
1875 {
1876    saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1877    if(!r)
1878    {
1879       --parenthesis_stack_position;
1880    }
1881    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1882    m_backup_state = pmp;
1883    return true;
1884 }
1885 
1886 template <class BidiIterator, class Allocator, class traits>
1887 void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
1888 {
1889    saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1890    --pmp;
1891    if(pmp < m_stack_base)
1892    {
1893       extend_stack();
1894       pmp = static_cast<saved_state*>(m_backup_state);
1895       --pmp;
1896    }
1897    (void) new (pmp)saved_state(16);
1898    m_backup_state = pmp;
1899 }
1900 
1901 template <class BidiIterator, class Allocator, class traits>
1902 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
1903 {
1904    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1905    if(!r)
1906    {
1907       parenthesis_stack[parenthesis_stack_position++] = pmp->position;
1908    }
1909    boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1910    m_backup_state = pmp;
1911    return true;
1912 }
1913 
1914 template <class BidiIterator, class Allocator, class traits>
1915 inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
1916 {
1917    saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1918    --pmp;
1919    if(pmp < m_stack_base)
1920    {
1921       extend_stack();
1922       pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1923       --pmp;
1924    }
1925    (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
1926    m_backup_state = pmp;
1927 }
1928 */
1929 } // namespace BOOST_REGEX_DETAIL_NS
1930 } // namespace boost
1931 
1932 #ifdef BOOST_MSVC
1933 #  pragma warning(pop)
1934 #endif
1935 
1936 #ifdef BOOST_MSVC
1937 #pragma warning(push)
1938 #pragma warning(disable: 4103)
1939 #endif
1940 #ifdef BOOST_HAS_ABI_HEADERS
1941 #  include BOOST_ABI_SUFFIX
1942 #endif
1943 #ifdef BOOST_MSVC
1944 #pragma warning(pop)
1945 #endif
1946 
1947 #endif