LCOV - code coverage report
Current view: top level - usr/include/boost/regex/v4 - perl_matcher_non_recursive.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 820 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 130 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14