Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:08:37

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   *                common to both the recursive and non-recursive versions.
0018   */
0019 
0020 #ifndef BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP
0021 #define BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP
0022 
0023 #ifdef BOOST_REGEX_MSVC
0024 #  pragma warning(push)
0025 #pragma warning(disable:4459)
0026 #if BOOST_REGEX_MSVC < 1910
0027 #pragma warning(disable:4800)
0028 #endif
0029 #endif
0030 
0031 namespace boost{
0032 namespace BOOST_REGEX_DETAIL_NS{
0033 
0034 #ifdef BOOST_REGEX_MSVC
0035 #  pragma warning(push)
0036 #pragma warning(disable:26812)
0037 #endif
0038    template <class BidiIterator, class Allocator, class traits>
0039 void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_regex<char_type, traits>& e, match_flag_type f)
0040 { 
0041    typedef typename std::iterator_traits<BidiIterator>::iterator_category category;
0042    typedef typename basic_regex<char_type, traits>::flag_type expression_flag_type;
0043    
0044    if(e.empty())
0045    {
0046       // precondition failure: e is not a valid regex.
0047       std::invalid_argument ex("Invalid regular expression object");
0048 #ifndef BOOST_REGEX_STANDALONE
0049       boost::throw_exception(ex);
0050 #else
0051       throw e;
0052 #endif
0053    }
0054    pstate = 0;
0055    m_match_flags = f;
0056    estimate_max_state_count(static_cast<category*>(0));
0057    expression_flag_type re_f = re.flags();
0058    icase = re_f & regex_constants::icase;
0059    if(!(m_match_flags & (match_perl|match_posix)))
0060    {
0061       if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0)
0062          m_match_flags |= match_perl;
0063       else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
0064          m_match_flags |= match_perl;
0065       else if((re_f & (regbase::main_option_type|regbase::literal)) == (regbase::literal))
0066          m_match_flags |= match_perl;
0067       else
0068          m_match_flags |= match_posix;
0069    }
0070    if(m_match_flags & match_posix)
0071    {
0072       m_temp_match.reset(new match_results<BidiIterator, Allocator>());
0073       m_presult = m_temp_match.get();
0074    }
0075    else
0076       m_presult = &m_result;
0077    m_stack_base = 0;
0078    m_backup_state = 0;
0079    // find the value to use for matching word boundaries:
0080    m_word_mask = re.get_data().m_word_mask; 
0081    // find bitmask to use for matching '.':
0082    match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? BOOST_REGEX_DETAIL_NS::test_not_newline : BOOST_REGEX_DETAIL_NS::test_newline);
0083    // Disable match_any if requested in the state machine:
0084    if(e.get_data().m_disable_match_any)
0085       m_match_flags &= regex_constants::match_not_any;
0086 }
0087 #ifdef BOOST_REGEX_MSVC
0088 #  pragma warning(pop)
0089 #endif
0090 
0091 template <class BidiIterator, class Allocator, class traits>
0092 void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*)
0093 {
0094    //
0095    // How many states should we allow our machine to visit before giving up?
0096    // This is a heuristic: it takes the greater of O(N^2) and O(NS^2)
0097    // where N is the length of the string, and S is the number of states
0098    // in the machine.  It's tempting to up this to O(N^2S) or even O(N^2S^2)
0099    // but these take unreasonably amounts of time to bale out in pathological
0100    // cases.
0101    //
0102    // Calculate NS^2 first:
0103    //
0104    static const std::ptrdiff_t k = 100000;
0105    std::ptrdiff_t dist = std::distance(base, last);
0106    if(dist == 0)
0107       dist = 1;
0108    std::ptrdiff_t states = re.size();
0109    if(states == 0)
0110       states = 1;
0111    if ((std::numeric_limits<std::ptrdiff_t>::max)() / states < states)
0112    {
0113       max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
0114       return;
0115    }
0116    states *= states;
0117    if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
0118    {
0119       max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
0120       return;
0121    }
0122    states *= dist;
0123    if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
0124    {
0125       max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
0126       return;
0127    }
0128    states += k;
0129 
0130    max_state_count = states;
0131 
0132    //
0133    // Now calculate N^2:
0134    //
0135    states = dist;
0136    if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
0137    {
0138       max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
0139       return;
0140    }
0141    states *= dist;
0142    if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
0143    {
0144       max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
0145       return;
0146    }
0147    states += k;
0148    //
0149    // N^2 can be a very large number indeed, to prevent things getting out
0150    // of control, cap the max states:
0151    //
0152    if(states > BOOST_REGEX_MAX_STATE_COUNT)
0153       states = BOOST_REGEX_MAX_STATE_COUNT;
0154    //
0155    // If (the possibly capped) N^2 is larger than our first estimate,
0156    // use this instead:
0157    //
0158    if(states > max_state_count)
0159       max_state_count = states;
0160 }
0161 
0162 template <class BidiIterator, class Allocator, class traits>
0163 inline void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*)
0164 {
0165    // we don't know how long the sequence is:
0166    max_state_count = BOOST_REGEX_MAX_STATE_COUNT;
0167 }
0168 
0169 template <class BidiIterator, class Allocator, class traits>
0170 inline bool perl_matcher<BidiIterator, Allocator, traits>::match()
0171 {
0172    return match_imp();
0173 }
0174 
0175 template <class BidiIterator, class Allocator, class traits>
0176 bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
0177 {
0178    // initialise our stack if we are non-recursive:
0179    save_state_init init(&m_stack_base, &m_backup_state);
0180    used_block_count = BOOST_REGEX_MAX_BLOCKS;
0181 #if !defined(BOOST_NO_EXCEPTIONS)
0182    try{
0183 #endif
0184 
0185    // reset our state machine:
0186    position = base;
0187    search_base = base;
0188    state_count = 0;
0189    m_match_flags |= regex_constants::match_all;
0190    m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
0191    m_presult->set_base(base);
0192    m_presult->set_named_subs(this->re.get_named_subs());
0193    if(m_match_flags & match_posix)
0194       m_result = *m_presult;
0195    verify_options(re.flags(), m_match_flags);
0196    if(0 == match_prefix())
0197       return false;
0198    return (m_result[0].second == last) && (m_result[0].first == base);
0199 
0200 #if !defined(BOOST_NO_EXCEPTIONS)
0201    }
0202    catch(...)
0203    {
0204       // unwind all pushed states, apart from anything else this
0205       // ensures that all the states are correctly destructed
0206       // not just the memory freed.
0207       while(unwind(true)){}
0208       throw;
0209    }
0210 #endif
0211 }
0212 
0213 template <class BidiIterator, class Allocator, class traits>
0214 inline bool perl_matcher<BidiIterator, Allocator, traits>::find()
0215 {
0216    return find_imp();
0217 }
0218 
0219 template <class BidiIterator, class Allocator, class traits>
0220 bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
0221 {
0222    static matcher_proc_type const s_find_vtable[7] = 
0223    {
0224       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_any,
0225       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_word,
0226       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_line,
0227       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf,
0228       &perl_matcher<BidiIterator, Allocator, traits>::match_prefix,
0229       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
0230       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
0231    };
0232 
0233    // initialise our stack if we are non-recursive:
0234    save_state_init init(&m_stack_base, &m_backup_state);
0235    used_block_count = BOOST_REGEX_MAX_BLOCKS;
0236 #if !defined(BOOST_NO_EXCEPTIONS)
0237    try{
0238 #endif
0239 
0240    state_count = 0;
0241    if((m_match_flags & regex_constants::match_init) == 0)
0242    {
0243       // reset our state machine:
0244       search_base = position = base;
0245       pstate = re.get_first_state();
0246       m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
0247       m_presult->set_base(base);
0248       m_presult->set_named_subs(this->re.get_named_subs());
0249       m_match_flags |= regex_constants::match_init;
0250    }
0251    else
0252    {
0253       // start again:
0254       search_base = position = m_result[0].second;
0255       // If last match was null and match_not_null was not set then increment
0256       // our start position, otherwise we go into an infinite loop:
0257       if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0))
0258       {
0259          if(position == last)
0260             return false;
0261          else 
0262             ++position;
0263       }
0264       // reset $` start:
0265       m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast<typename results_type::size_type>(1u + re.mark_count()), search_base, last);
0266       //if((base != search_base) && (base == backstop))
0267       //   m_match_flags |= match_prev_avail;
0268    }
0269    if(m_match_flags & match_posix)
0270    {
0271       m_result.set_size(static_cast<typename results_type::size_type>(1u + re.mark_count()), base, last);
0272       m_result.set_base(base);
0273    }
0274 
0275    verify_options(re.flags(), m_match_flags);
0276    // find out what kind of expression we have:
0277    unsigned type = (m_match_flags & match_continuous) ? 
0278       static_cast<unsigned int>(regbase::restart_continue) 
0279          : static_cast<unsigned int>(re.get_restart_type());
0280 
0281    // call the appropriate search routine:
0282    matcher_proc_type proc = s_find_vtable[type];
0283    return (this->*proc)();
0284 
0285 #if !defined(BOOST_NO_EXCEPTIONS)
0286    }
0287    catch(...)
0288    {
0289       // unwind all pushed states, apart from anything else this
0290       // ensures that all the states are correctly destructed
0291       // not just the memory freed.
0292       while(unwind(true)){}
0293       throw;
0294    }
0295 #endif
0296 }
0297 
0298 template <class BidiIterator, class Allocator, class traits>
0299 bool perl_matcher<BidiIterator, Allocator, traits>::match_prefix()
0300 {
0301    m_has_partial_match = false;
0302    m_has_found_match = false;
0303    pstate = re.get_first_state();
0304    m_presult->set_first(position);
0305    restart = position;
0306    match_all_states();
0307    if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial))
0308    {
0309       m_has_found_match = true;
0310       m_presult->set_second(last, 0, false);
0311       position = last;
0312       if((m_match_flags & match_posix) == match_posix)
0313       {
0314          m_result.maybe_assign(*m_presult);
0315       }
0316    }
0317 #ifdef BOOST_REGEX_MATCH_EXTRA
0318    if(m_has_found_match && (match_extra & m_match_flags))
0319    {
0320       //
0321       // we have a match, reverse the capture information:
0322       //
0323       for(unsigned i = 0; i < m_presult->size(); ++i)
0324       {
0325          typename sub_match<BidiIterator>::capture_sequence_type & seq = ((*m_presult)[i]).get_captures();
0326          std::reverse(seq.begin(), seq.end());
0327       }
0328    }
0329 #endif
0330    if(!m_has_found_match)
0331       position = restart; // reset search postion
0332    return m_has_found_match;
0333 }
0334 
0335 template <class BidiIterator, class Allocator, class traits>
0336 bool perl_matcher<BidiIterator, Allocator, traits>::match_literal()
0337 {
0338    unsigned int len = static_cast<const re_literal*>(pstate)->length;
0339    const char_type* what = reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
0340    //
0341    // compare string with what we stored in
0342    // our records:
0343    for(unsigned int i = 0; i < len; ++i, ++position)
0344    {
0345       if((position == last) || (traits_inst.translate(*position, icase) != what[i]))
0346          return false;
0347    }
0348    pstate = pstate->next.p;
0349    return true;
0350 }
0351 
0352 template <class BidiIterator, class Allocator, class traits>
0353 bool perl_matcher<BidiIterator, Allocator, traits>::match_start_line()
0354 {
0355    if(position == backstop)
0356    {
0357       if((m_match_flags & match_prev_avail) == 0)
0358       {
0359          if((m_match_flags & match_not_bol) == 0)
0360          {
0361             pstate = pstate->next.p;
0362             return true;
0363          }
0364          return false;
0365       }
0366    }
0367    else if(m_match_flags & match_single_line)
0368       return false;
0369 
0370    // check the previous value character:
0371    BidiIterator t(position);
0372    --t;
0373    if(position != last)
0374    {
0375       if(is_separator(*t) && !((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) )
0376       {
0377          pstate = pstate->next.p;
0378          return true;
0379       }
0380    }
0381    else if(is_separator(*t))
0382    {
0383       pstate = pstate->next.p;
0384       return true;
0385    }
0386    return false;
0387 }
0388 
0389 template <class BidiIterator, class Allocator, class traits>
0390 bool perl_matcher<BidiIterator, Allocator, traits>::match_end_line()
0391 {
0392    if(position != last)
0393    {
0394       if(m_match_flags & match_single_line)
0395          return false;
0396       // we're not yet at the end so *first is always valid:
0397       if(is_separator(*position))
0398       {
0399          if((position != backstop) || (m_match_flags & match_prev_avail))
0400          {
0401             // check that we're not in the middle of \r\n sequence
0402             BidiIterator t(position);
0403             --t;
0404             if((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n')))
0405             {
0406                return false;
0407             }
0408          }
0409          pstate = pstate->next.p;
0410          return true;
0411       }
0412    }
0413    else if((m_match_flags & match_not_eol) == 0)
0414    {
0415       pstate = pstate->next.p;
0416       return true;
0417    }
0418    return false;
0419 }
0420 
0421 template <class BidiIterator, class Allocator, class traits>
0422 bool perl_matcher<BidiIterator, Allocator, traits>::match_wild()
0423 {
0424    if(position == last) 
0425       return false;
0426    if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0))
0427       return false;
0428    if((*position == char_type(0)) && (m_match_flags & match_not_dot_null))
0429       return false;
0430    pstate = pstate->next.p;
0431    ++position;
0432    return true;
0433 }
0434 
0435 template <class BidiIterator, class Allocator, class traits>
0436 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary()
0437 {
0438    bool b; // indcates whether next character is a word character
0439    if(position != last)
0440    {
0441       // prev and this character must be opposites:
0442       b = traits_inst.isctype(*position, m_word_mask);
0443    }
0444    else
0445    {
0446       if (m_match_flags & match_not_eow)
0447          return false;
0448       b = false;
0449    }
0450    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
0451    {
0452       if(m_match_flags & match_not_bow)
0453          return false;
0454       else
0455          b ^= false;
0456    }
0457    else
0458    {
0459       --position;
0460       b ^= traits_inst.isctype(*position, m_word_mask);
0461       ++position;
0462    }
0463    if(b)
0464    {
0465       pstate = pstate->next.p;
0466       return true;
0467    }
0468    return false; // no match if we get to here...
0469 }
0470 
0471 template <class BidiIterator, class Allocator, class traits>
0472 bool perl_matcher<BidiIterator, Allocator, traits>::match_within_word()
0473 {
0474    bool b = !match_word_boundary();
0475    if(b)
0476       pstate = pstate->next.p;
0477    return b;
0478    /*
0479    if(position == last)
0480       return false;
0481    // both prev and this character must be m_word_mask:
0482    bool prev = traits_inst.isctype(*position, m_word_mask);
0483    {
0484       bool b;
0485       if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) 
0486          return false;
0487       else
0488       {
0489          --position;
0490          b = traits_inst.isctype(*position, m_word_mask);
0491          ++position;
0492       }
0493       if(b == prev)
0494       {
0495          pstate = pstate->next.p;
0496          return true;
0497       }
0498    }
0499    return false;
0500    */
0501 }
0502 
0503 template <class BidiIterator, class Allocator, class traits>
0504 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_start()
0505 {
0506    if(position == last)
0507       return false; // can't be starting a word if we're already at the end of input
0508    if(!traits_inst.isctype(*position, m_word_mask))
0509       return false; // next character isn't a word character
0510    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
0511    {
0512       if(m_match_flags & match_not_bow)
0513          return false; // no previous input
0514    }
0515    else
0516    {
0517       // otherwise inside buffer:
0518       BidiIterator t(position);
0519       --t;
0520       if(traits_inst.isctype(*t, m_word_mask))
0521          return false; // previous character not non-word
0522    }
0523    // OK we have a match:
0524    pstate = pstate->next.p;
0525    return true;
0526 }
0527 
0528 template <class BidiIterator, class Allocator, class traits>
0529 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_end()
0530 {
0531    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
0532       return false;  // start of buffer can't be end of word
0533    BidiIterator t(position);
0534    --t;
0535    if(traits_inst.isctype(*t, m_word_mask) == false)
0536       return false;  // previous character wasn't a word character
0537 
0538    if(position == last)
0539    {
0540       if(m_match_flags & match_not_eow)
0541          return false; // end of buffer but not end of word
0542    }
0543    else
0544    {
0545       // otherwise inside buffer:
0546       if(traits_inst.isctype(*position, m_word_mask))
0547          return false; // next character is a word character
0548    }
0549    pstate = pstate->next.p;
0550    return true;      // if we fall through to here then we've succeeded
0551 }
0552 
0553 template <class BidiIterator, class Allocator, class traits>
0554 bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start()
0555 {
0556    if((position != backstop) || (m_match_flags & match_not_bob))
0557       return false;
0558    // OK match:
0559    pstate = pstate->next.p;
0560    return true;
0561 }
0562 
0563 template <class BidiIterator, class Allocator, class traits>
0564 bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end()
0565 {
0566    if((position != last) || (m_match_flags & match_not_eob))
0567       return false;
0568    // OK match:
0569    pstate = pstate->next.p;
0570    return true;
0571 }
0572 
0573 template <class BidiIterator, class Allocator, class traits>
0574 bool perl_matcher<BidiIterator, Allocator, traits>::match_backref()
0575 {
0576    //
0577    // Compare with what we previously matched.
0578    // Note that this succeeds if the backref did not partisipate
0579    // in the match, this is in line with ECMAScript, but not Perl
0580    // or PCRE.
0581    //
0582    int index = static_cast<const re_brace*>(pstate)->index;
0583    if(index >= hash_value_mask)
0584    {
0585       named_subexpressions::range_type r = re.get_data().equal_range(index);
0586       BOOST_REGEX_ASSERT(r.first != r.second);
0587       do
0588       {
0589          index = r.first->index;
0590          ++r.first;
0591       }while((r.first != r.second) && ((*m_presult)[index].matched != true));
0592    }
0593 
0594    if((m_match_flags & match_perl) && !(*m_presult)[index].matched)
0595       return false;
0596 
0597    BidiIterator i = (*m_presult)[index].first;
0598    BidiIterator j = (*m_presult)[index].second;
0599    while(i != j)
0600    {
0601       if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase)))
0602          return false;
0603       ++i;
0604       ++position;
0605    }
0606    pstate = pstate->next.p;
0607    return true;
0608 }
0609 
0610 template <class BidiIterator, class Allocator, class traits>
0611 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
0612 {
0613    typedef typename traits::char_class_type char_class_type;
0614    // let the traits class do the work:
0615    if(position == last)
0616       return false;
0617    BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase);
0618    if(t != position)
0619    {
0620       pstate = pstate->next.p;
0621       position = t;
0622       return true;
0623    }
0624    return false;
0625 }
0626 
0627 template <class BidiIterator, class Allocator, class traits>
0628 bool perl_matcher<BidiIterator, Allocator, traits>::match_set()
0629 {
0630    if(position == last)
0631       return false;
0632    if(static_cast<const re_set*>(pstate)->_map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
0633    {
0634       pstate = pstate->next.p;
0635       ++position;
0636       return true;
0637    }
0638    return false;
0639 }
0640 
0641 template <class BidiIterator, class Allocator, class traits>
0642 bool perl_matcher<BidiIterator, Allocator, traits>::match_jump()
0643 {
0644    pstate = static_cast<const re_jump*>(pstate)->alt.p;
0645    return true;
0646 }
0647 
0648 template <class BidiIterator, class Allocator, class traits>
0649 bool perl_matcher<BidiIterator, Allocator, traits>::match_combining()
0650 {
0651    if(position == last)
0652       return false;
0653    if(is_combining(traits_inst.translate(*position, icase)))
0654       return false;
0655    ++position;
0656    while((position != last) && is_combining(traits_inst.translate(*position, icase)))
0657       ++position;
0658    pstate = pstate->next.p;
0659    return true;
0660 }
0661 
0662 template <class BidiIterator, class Allocator, class traits>
0663 bool perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end()
0664 {
0665    if(m_match_flags & match_not_eob)
0666       return false;
0667    BidiIterator p(position);
0668    while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p;
0669    if(p != last)
0670       return false;
0671    pstate = pstate->next.p;
0672    return true;
0673 }
0674 
0675 template <class BidiIterator, class Allocator, class traits>
0676 bool perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue()
0677 {
0678    if(position == search_base)
0679    {
0680       pstate = pstate->next.p;
0681       return true;
0682    }
0683    return false;
0684 }
0685 
0686 template <class BidiIterator, class Allocator, class traits>
0687 bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep()
0688 {
0689 #ifdef BOOST_REGEX_MSVC
0690 #pragma warning(push)
0691 #pragma warning(disable:4127)
0692 #endif
0693    if( ::boost::is_random_access_iterator<BidiIterator>::value)
0694    {
0695       std::ptrdiff_t maxlen = std::distance(backstop, position);
0696       if(maxlen < static_cast<const re_brace*>(pstate)->index)
0697          return false;
0698       std::advance(position, -static_cast<const re_brace*>(pstate)->index);
0699    }
0700    else
0701    {
0702       int c = static_cast<const re_brace*>(pstate)->index;
0703       while(c--)
0704       {
0705          if(position == backstop)
0706             return false;
0707          --position;
0708       }
0709    }
0710    pstate = pstate->next.p;
0711    return true;
0712 #ifdef BOOST_REGEX_MSVC
0713 #pragma warning(pop)
0714 #endif
0715 }
0716 
0717 template <class BidiIterator, class Allocator, class traits>
0718 inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
0719 {
0720    // return true if marked sub-expression N has been matched:
0721    int index = static_cast<const re_brace*>(pstate)->index;
0722    bool result = false;
0723    if(index == 9999)
0724    {
0725       // Magic value for a (DEFINE) block:
0726       return false;
0727    }
0728    else if(index > 0)
0729    {
0730       // Have we matched subexpression "index"?
0731       // Check if index is a hash value:
0732       if(index >= hash_value_mask)
0733       {
0734          named_subexpressions::range_type r = re.get_data().equal_range(index);
0735          while(r.first != r.second)
0736          {
0737             if((*m_presult)[r.first->index].matched)
0738             {
0739                result = true;
0740                break;
0741             }
0742             ++r.first;
0743          }
0744       }
0745       else
0746       {
0747          result = (*m_presult)[index].matched;
0748       }
0749       pstate = pstate->next.p;
0750    }
0751    else
0752    {
0753       // Have we recursed into subexpression "index"?
0754       // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1.
0755       int idx = -(index+1);
0756       if(idx >= hash_value_mask)
0757       {
0758          named_subexpressions::range_type r = re.get_data().equal_range(idx);
0759          int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx;
0760          while(r.first != r.second)
0761          {
0762             result |= (stack_index == r.first->index);
0763             if(result)break;
0764             ++r.first;
0765          }
0766       }
0767       else
0768       {
0769          result = !recursion_stack.empty() && ((recursion_stack.back().idx == idx) || (index == 0));
0770       }
0771       pstate = pstate->next.p;
0772    }
0773    return result;
0774 }
0775 
0776 template <class BidiIterator, class Allocator, class traits>
0777 bool perl_matcher<BidiIterator, Allocator, traits>::match_fail()
0778 {
0779    // Just force a backtrack:
0780    return false;
0781 }
0782 
0783 template <class BidiIterator, class Allocator, class traits>
0784 bool perl_matcher<BidiIterator, Allocator, traits>::match_accept()
0785 {
0786    if(!recursion_stack.empty())
0787    {
0788       return skip_until_paren(recursion_stack.back().idx);
0789    }
0790    else
0791    {
0792       return skip_until_paren(INT_MAX);
0793    }
0794 }
0795 
0796 template <class BidiIterator, class Allocator, class traits>
0797 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
0798 {
0799 #ifdef BOOST_REGEX_MSVC
0800 #pragma warning(push)
0801 #pragma warning(disable:4127)
0802 #endif
0803    const unsigned char* _map = re.get_map();
0804    while(true)
0805    {
0806       // skip everything we can't match:
0807       while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) )
0808          ++position;
0809       if(position == last)
0810       {
0811          // run out of characters, try a null match if possible:
0812          if(re.can_be_null())
0813             return match_prefix();
0814          break;
0815       }
0816       // now try and obtain a match:
0817       if(match_prefix())
0818          return true;
0819       if(position == last)
0820          return false;
0821       ++position;
0822    }
0823    return false;
0824 #ifdef BOOST_REGEX_MSVC
0825 #pragma warning(pop)
0826 #endif
0827 }
0828 
0829 template <class BidiIterator, class Allocator, class traits>
0830 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_word()
0831 {
0832 #ifdef BOOST_REGEX_MSVC
0833 #pragma warning(push)
0834 #pragma warning(disable:4127)
0835 #endif
0836    // do search optimised for word starts:
0837    const unsigned char* _map = re.get_map();
0838    if((m_match_flags & match_prev_avail) || (position != base))
0839       --position;
0840    else if(match_prefix())
0841       return true;
0842    do
0843    {
0844       while((position != last) && traits_inst.isctype(*position, m_word_mask))
0845          ++position;
0846       while((position != last) && !traits_inst.isctype(*position, m_word_mask))
0847          ++position;
0848       if(position == last)
0849          break;
0850 
0851       if(can_start(*position, _map, (unsigned char)mask_any) )
0852       {
0853          if(match_prefix())
0854             return true;
0855       }
0856       if(position == last)
0857          break;
0858    } while(true);
0859    return false;
0860 #ifdef BOOST_REGEX_MSVC
0861 #pragma warning(pop)
0862 #endif
0863 }
0864 
0865 template <class BidiIterator, class Allocator, class traits>
0866 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_line()
0867 {
0868    // do search optimised for line starts:
0869    const unsigned char* _map = re.get_map();
0870    if(match_prefix())
0871       return true;
0872    while(position != last)
0873    {
0874       while((position != last) && !is_separator(*position))
0875          ++position;
0876       if(position == last)
0877          return false;
0878       ++position;
0879       if(position == last)
0880       {
0881          if(re.can_be_null() && match_prefix())
0882             return true;
0883          return false;
0884       }
0885 
0886       if( can_start(*position, _map, (unsigned char)mask_any) )
0887       {
0888          if(match_prefix())
0889             return true;
0890       }
0891       if(position == last)
0892          return false;
0893       //++position;
0894    }
0895    return false;
0896 }
0897 
0898 template <class BidiIterator, class Allocator, class traits>
0899 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf()
0900 {
0901    if((position == base) && ((m_match_flags & match_not_bob) == 0))
0902       return match_prefix();
0903    return false;
0904 }
0905 
0906 template <class BidiIterator, class Allocator, class traits>
0907 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit()
0908 {
0909    return false;
0910 }
0911 
0912 } // namespace BOOST_REGEX_DETAIL_NS
0913 
0914 } // namespace boost
0915 
0916 #ifdef BOOST_REGEX_MSVC
0917 #  pragma warning(pop)
0918 #endif
0919 
0920 #endif
0921