regexpr2.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:210k
源码类别:

模拟服务器

开发平台:

C/C++

  1.         return m_pgroup->match_group_base<CI>::iterative_rematch_this_( param );
  2.     }
  3.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  4.     {
  5.         return m_pgroup->match_group_base<CI>::iterative_rematch_this_c( param );
  6.     }
  7.     virtual width_type width_this( width_param<CI> & ) 
  8.     {
  9.         return zero_width;
  10.     }
  11. };
  12. // Behaves like a lookahead assertion if m_cgroup is -1, or like
  13. // an independent group otherwise.
  14. template< typename CI >
  15. class independent_group_base : public match_group_base<CI>
  16. {
  17.     independent_group_base & operator=( independent_group_base const & );
  18.     template< typename CSTRINGS >
  19.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  20.     {
  21.         backref_tag<CI> * prgbr = NULL;
  22.         // Copy onto the stack the part of the backref vector that could
  23.         // be modified by the lookahead.
  24.         if( m_extent.second )
  25.         {
  26.             prgbr = static_cast<backref_tag<CI>*>( alloca( m_extent.second * sizeof( backref_tag<CI> ) ) );
  27.             std::copy( param.prgbackrefs->begin() + m_extent.first,
  28.                        param.prgbackrefs->begin() + m_extent.first + m_extent.second,
  29.                        std::raw_storage_iterator<backref_tag<CI>*, backref_tag<CI> >( prgbr ) );
  30.         }
  31.         // Match until the end of this group and then return
  32.         // BUGBUG can the compiler optimize this?
  33.         bool const fdomatch = CSTRINGS::value ?
  34.             match_group_base<CI>::recursive_match_all_c( param, icur ) :
  35.             match_group_base<CI>::recursive_match_all_( param, icur );
  36.         if( m_fexpected == fdomatch )
  37.         {
  38.             // If m_cgroup != 1, then this is not a zero-width assertion.
  39.             if( fdomatch && size_t( -1 ) != m_cgroup )
  40.                 icur = ( *param.prgbackrefs )[ m_cgroup ].second;
  41.             if( recursive_match_next_( param, icur, CSTRINGS() ) )
  42.                 return true;
  43.         }
  44.         // if match_group::recursive_match_all_ returned true, the backrefs must be restored
  45.         if( m_extent.second && fdomatch )
  46.             std::copy( prgbr, prgbr + m_extent.second, param.prgbackrefs->begin() + m_extent.first );
  47.         return false;
  48.     }
  49.     template< typename CSTRINGS >
  50.     bool _iterative_match_this( match_param<CI> & param, CSTRINGS ) const
  51.     {
  52.         group_wrapper<CI> expr( this );
  53.         _push_frame( param );
  54.         CI istart = param.icur;
  55.         bool const fdomatch = matcher_helper<CI>::_Do_match_iterative( &expr, param, param.icur, CSTRINGS() );
  56.         if( m_fexpected == fdomatch )
  57.         {
  58.             // If m_cgroup == -1, then this is a zero-width assertion.
  59.             if( fdomatch && size_t( -1 ) == m_cgroup )
  60.                 param.icur = istart;
  61.             param.next = next();
  62.             return true;
  63.         }
  64.         _pop_frame( param );
  65.         return false;
  66.     }
  67.     bool _iterative_rematch_this( match_param<CI> & param ) const
  68.     {
  69.         _pop_frame( param );
  70.         return false;
  71.     }
  72. public:
  73.     independent_group_base( size_t cgroup, regex_arena & arena )
  74.         : match_group_base<CI>( cgroup, arena ),
  75.           m_fexpected( true ), m_extent( 0, 0 ) 
  76.     {
  77.     }
  78.     virtual void set_extent( extent const & ex )
  79.     {
  80.         m_extent = ex;
  81.     }
  82.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  83.     {
  84.         return _recursive_match_all( param, icur, false_t() );
  85.     }
  86.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  87.     {
  88.         return _recursive_match_all( param, icur, true_t() );
  89.     }
  90.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  91.     {
  92.         return _iterative_match_this( param, false_t() );
  93.     }
  94.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  95.     {
  96.         return _iterative_match_this( param, true_t() );
  97.     }
  98.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  99.     {
  100.         return _iterative_rematch_this( param );
  101.     }
  102.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  103.     {
  104.         return _iterative_rematch_this( param );
  105.     }
  106. protected:
  107.     void _push_frame( match_param<CI> & param ) const
  108.     {
  109.         unsafe_stack * pstack = param.pstack;
  110.         typedef typename match_param<CI>::backref_vector::const_iterator VCI;
  111.         VCI istart = param.prgbackrefs->begin() + m_extent.first;
  112.         VCI iend   = istart + m_extent.second;
  113.         for( ; iend != istart; ++istart )
  114.         {
  115.             pstack->push( *istart );
  116.         }
  117.         pstack->push( param.icur );
  118.     }
  119.     void _pop_frame( match_param<CI> & param ) const
  120.     {
  121.         unsafe_stack * pstack = param.pstack;
  122.         typedef typename match_param<CI>::backref_vector::iterator VI;
  123.         VI istart = param.prgbackrefs->begin() + m_extent.first;
  124.         VI iend   = istart + m_extent.second;
  125.         pstack->pop( param.icur );
  126.         while( iend != istart )
  127.         {
  128.             pstack->pop( *--iend );
  129.         }
  130.     }
  131.     independent_group_base( bool const fexpected, regex_arena & arena )
  132.         : match_group_base<CI>( size_t( -1 ), arena ), m_fexpected( fexpected ) 
  133.     {
  134.     }
  135.     bool const m_fexpected;
  136.     extent     m_extent;
  137. };
  138. template< typename CI >
  139. class independent_group : public independent_group_base<CI>
  140. {
  141.     independent_group & operator=( independent_group const & );
  142. public:
  143.     independent_group( size_t cgroup, regex_arena & arena )
  144.         : independent_group_base<CI>( cgroup, arena ), m_end_group( this ) 
  145.     {
  146.     }
  147.     virtual ~independent_group()
  148.     {
  149.         _cleanup();
  150.     }
  151.     virtual sub_expr<CI> * quantify( size_t lbound, size_t ubound, bool greedy, regex_arena & arena )
  152.     {
  153.         if( greedy )
  154.             return new( arena ) max_group_quantifier<CI>( this, lbound, ubound );
  155.         else
  156.             return new( arena ) min_group_quantifier<CI>( this, lbound, ubound );
  157.     }
  158. protected:
  159.     independent_group( bool const fexpected, regex_arena & arena )
  160.         : independent_group_base<CI>( fexpected, arena ),
  161.           m_end_group( this ) 
  162.     {
  163.     }
  164.     bool _call_back( match_param<CI> & param, CI icur ) const
  165.     {
  166.         if( size_t( -1 ) != m_cgroup )
  167.         {
  168.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_cgroup ];
  169.             br.first   = br.reserved1;
  170.             br.second  = icur;
  171.             br.matched = true;
  172.         }
  173.         return true;
  174.     }
  175.     class end_group : public indestructable_sub_expr<CI, end_group>
  176.     {
  177.         independent_group<CI> const *const m_pgroup;
  178.         end_group & operator=( end_group const & );
  179.         bool _iterative_match_this( match_param<CI> & param ) const
  180.         {
  181.             size_t cgroup = m_pgroup->group_number();
  182.             if( size_t( -1 ) != cgroup )
  183.             {
  184.                 backref_tag<CI> & br = ( *param.prgbackrefs )[ cgroup ];
  185.                 br.first   = br.reserved1;
  186.                 br.second  = param.icur;
  187.                 br.matched = true;
  188.             }
  189.             param.next = NULL;
  190.             return true;
  191.         }
  192.     public:
  193.         end_group( independent_group<CI> const * pgroup = NULL )
  194.             : m_pgroup( pgroup ) 
  195.         {
  196.         }
  197.         virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  198.         {
  199.             return m_pgroup->_call_back( param, icur );
  200.         }
  201.         virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  202.         {
  203.             return m_pgroup->_call_back( param, icur );
  204.         }
  205.         virtual bool iterative_match_this_( match_param<CI> & param ) const
  206.         {
  207.             return _iterative_match_this( param );
  208.         }
  209.         virtual bool iterative_match_this_c( match_param<CI> & param ) const
  210.         {
  211.             return _iterative_match_this( param );
  212.         }
  213.         virtual width_type width_this( width_param<CI> & )
  214.         {
  215.             return zero_width;
  216.         }
  217.     } m_end_group;
  218.     friend class end_group;
  219.     virtual sub_expr<CI> * _get_end_group()
  220.     {
  221.         return & m_end_group;
  222.     }
  223. };
  224. template< typename CI >
  225. class lookahead_assertion : public independent_group<CI>
  226. {
  227.     lookahead_assertion & operator=( lookahead_assertion const & );
  228. public:
  229.     lookahead_assertion( bool const fexpected, regex_arena & arena )
  230.         : independent_group<CI>( fexpected, arena ) 
  231.     {
  232.     }
  233.     virtual sub_expr<CI> * quantify( size_t, size_t, bool, regex_arena & )
  234.     {
  235.         throw bad_regexpr( "look-ahead assertion cannot be quantified" );
  236.     }
  237.     virtual bool is_assertion() const
  238.     {
  239.         return true;
  240.     }
  241.     virtual width_type width_this( width_param<CI> & param )
  242.     {
  243.         // calculate the group's width and store it, but return zero_width
  244.         match_group_base<CI>::width_this( param );
  245.         return zero_width;
  246.     }
  247. };
  248. template< typename CI >
  249. class lookbehind_assertion : public independent_group_base<CI>
  250. {
  251.     lookbehind_assertion & operator=( lookbehind_assertion const & );
  252.     template< typename CSTRINGS >
  253.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  254.     {
  255.         // This is the room in the string from the start to the current position
  256.         size_t room = std::distance( param.ibegin, icur );
  257.         // If we don't have enough room to match the lookbehind, the match fails.
  258.         // If we wanted the match to fail, try to match the rest of the pattern.
  259.         if( m_nwidth.m_min > room )
  260.             return m_fexpected ? false : recursive_match_next_( param, icur, CSTRINGS() );
  261.         backref_tag<CI> * prgbr = NULL;
  262.         // Copy onto the stack the part of the backref vector that could
  263.         // be modified by the lookbehind.
  264.         if( m_extent.second )
  265.         {
  266.             prgbr = static_cast<backref_tag<CI>*>( alloca( m_extent.second * sizeof( backref_tag<CI> ) ) );
  267.             std::copy( param.prgbackrefs->begin() + m_extent.first,
  268.                        param.prgbackrefs->begin() + m_extent.first + m_extent.second,
  269.                        std::raw_storage_iterator<backref_tag<CI>*, backref_tag<CI> >( prgbr ) );
  270.         }
  271.         CI local_istart  = icur;
  272.         std::advance( local_istart, -int( (std::min)( m_nwidth.m_max, room ) ) );
  273.         CI local_istop = icur;
  274.         std::advance( local_istop, -int( m_nwidth.m_min - 1 ) );
  275.         // Create a local param struct that has icur as param.iend
  276.         match_param<CI> local_param( param.ibegin, param.istart, icur, param.prgbackrefs );
  277.         // Find the rightmost match that ends at icur.
  278.         for( CI local_icur = local_istart; local_icur != local_istop; ++local_icur )
  279.         {
  280.             // Match until the end of this group and then return
  281.             // Note that we're calling recursive_match_all_ regardless of the CSTRINGS switch.
  282.             // This is because for the lookbehind assertion, the termination condition is when
  283.             // icur == param.iend, not when *icur == ''
  284.             bool const fmatched = match_group_base<CI>::recursive_match_all_( local_param, local_icur );
  285.             // If the match results were what we were expecting, try to match the
  286.             // rest of the pattern. If that succeeds, return true.
  287.             if( m_fexpected == fmatched && recursive_match_next_( param, icur, CSTRINGS() ) )
  288.                 return true;
  289.             // if match_group::recursive_match_all_ returned true, the backrefs must be restored
  290.             if( fmatched )
  291.             {
  292.                 if( m_extent.second )
  293.                     std::copy( prgbr, prgbr + m_extent.second, param.prgbackrefs->begin() + m_extent.first );
  294.                 // Match succeeded. If this is a negative lookbehind, we didn't want it
  295.                 // to succeed, so return false.
  296.                 if( ! m_fexpected )
  297.                     return false;
  298.             }
  299.         }
  300.         // No variation of the lookbehind was satisfied in a way that permited
  301.         // the rest of the pattern to match successfully, so return false.
  302.         return false;
  303.     }
  304.     template< typename CSTRINGS >
  305.     bool _iterative_match_this( match_param<CI> & param, CSTRINGS ) const
  306.     {
  307.         // Save the backrefs
  308.         _push_frame( param );
  309.         // This is the room in the string from the start to the current position
  310.         size_t room = std::distance( param.ibegin, param.icur );
  311.         // If we don't have enough room to match the lookbehind, the match fails.
  312.         // If we wanted the match to fail, try to match the rest of the pattern.
  313.         if( m_nwidth.m_min > room )
  314.         {
  315.             if( m_fexpected )
  316.             {
  317.                 _pop_frame( param );
  318.                 return false;
  319.             }
  320.             param.next = next();
  321.             return true;
  322.         }
  323.         CI local_istart  = param.icur;
  324.         std::advance( local_istart, -int( (std::min)( m_nwidth.m_max, room ) ) );
  325.         CI local_istop = param.icur;
  326.         std::advance( local_istop, -int( m_nwidth.m_min - 1 ) );
  327.         // Create a local param struct that has icur as param.iend
  328.         match_param<CI> local_param( param.ibegin, param.istart, param.icur, param.prgbackrefs );
  329.         local_param.pstack = param.pstack;
  330.         group_wrapper<CI> expr( this );
  331.         // Find the rightmost match that ends at icur.
  332.         for( CI local_icur = local_istart; local_icur != local_istop; ++local_icur )
  333.         {
  334.             // Match until the end of this group and then return
  335.             // Note that we're calling _Do_match_iterative_helper regardless of the CSTRINGS switch.
  336.             // This is because for the lookbehind assertion, the termination condition is when
  337.             // icur == param.iend, not when *icur == ''
  338.             bool const fmatched = matcher_helper<CI>::_Do_match_iterative_helper( &expr, local_param, local_icur );
  339.             // If the match results were what we were expecting, try to match the
  340.             // rest of the pattern. If that succeeds, return true.
  341.             if( m_fexpected == fmatched )
  342.             {
  343.                 param.next = next();
  344.                 return true;
  345.             }
  346.             // if match_group::recursive_match_all_ returned true, the backrefs must be restored
  347.             if( fmatched )
  348.             {
  349.                 // Restore the backrefs
  350.                 _pop_frame( param );
  351.                 // Match succeeded. If this is a negative lookbehind, we didn't want it
  352.                 // to succeed, so return false.
  353.                 if( ! m_fexpected )
  354.                     return false;
  355.                 // Save the backrefs again.
  356.                 _push_frame( param );
  357.             }
  358.         }
  359.         // No variation of the lookbehind was satisfied in a way that permited
  360.         // the rest of the pattern to match successfully, so return false.
  361.         _pop_frame( param );
  362.         return false;
  363.     }
  364.     bool _iterative_rematch_this( match_param<CI> & param ) const
  365.     {
  366.         _pop_frame( param );
  367.         return false;
  368.     }
  369. public:
  370.     lookbehind_assertion( bool const fexpected, regex_arena & arena )
  371.         : independent_group_base<CI>( fexpected, arena )
  372.     {
  373.     }
  374.     virtual ~lookbehind_assertion()
  375.     {
  376.         _cleanup();
  377.     }
  378.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  379.     {
  380.         return _recursive_match_all( param, icur, false_t() );
  381.     }
  382.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  383.     {
  384.         return _recursive_match_all( param, icur, true_t() );
  385.     }
  386.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  387.     {
  388.         return _iterative_match_this( param, false_t() );
  389.     }
  390.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  391.     {
  392.         return _iterative_match_this( param, true_t() );
  393.     }
  394.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  395.     {
  396.         return _iterative_rematch_this( param );
  397.     }
  398.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  399.     {
  400.         return _iterative_rematch_this( param );
  401.     }
  402.     virtual bool is_assertion() const
  403.     {
  404.         return true;
  405.     }
  406.     virtual width_type width_this( width_param<CI> & param )
  407.     {
  408.         // calculate the group's width and store it, but return zero_width
  409.         match_group_base<CI>::width_this( param );
  410.         return zero_width;
  411.     }
  412. protected:
  413.     struct end_group : public indestructable_sub_expr<CI, end_group>
  414.     {
  415.         virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  416.         {
  417.             return param.istop == icur;
  418.         }
  419.         virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  420.         {
  421.             return param.istop == icur;
  422.         }
  423.         virtual bool iterative_match_this_( match_param<CI> & param ) const
  424.         {
  425.             param.next = NULL;
  426.             return param.istop == param.icur;
  427.         }
  428.         virtual bool iterative_match_this_c( match_param<CI> & param ) const
  429.         {
  430.             param.next = NULL;
  431.             return param.istop == param.icur;
  432.         }
  433.         virtual width_type width_this( width_param<CI> & )
  434.         {
  435.             return zero_width;
  436.         }
  437.     } m_end_group;
  438.     virtual sub_expr<CI> * _get_end_group()
  439.     {
  440.         return & m_end_group;
  441.     }
  442. };
  443. template< typename CI >
  444. class group_quantifier : public match_quantifier<CI>
  445. {
  446.     group_quantifier & operator=( group_quantifier const & );
  447.     
  448.     bool _iterative_match_this( match_param<CI> & param ) const
  449.     {
  450.         _push_frame( param );
  451.         param.next = m_psub->next(); // ptr to end_quant
  452.         return true;
  453.     }
  454.     bool _iterative_rematch_this( match_param<CI> & param ) const
  455.     {
  456.         _pop_frame( param );
  457.         return false;
  458.     }
  459. public:
  460.     group_quantifier( match_group_base<CI> * psub,
  461.                       size_t lbound, size_t ubound,
  462.                       sub_expr<CI> * pend_quant )
  463.         : match_quantifier<CI>( psub, lbound, ubound ),
  464.           m_group( *psub )
  465.     {
  466.         *psub->pnext() = pend_quant;
  467.     }
  468.     // sub-classes of group_quantifer that own the end_quant
  469.     // object must declare a destructor, and it must call _cleanup
  470.     virtual ~group_quantifier() = 0;
  471.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  472.     {
  473.         return _iterative_match_this( param );
  474.     }
  475.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  476.     {
  477.         return _iterative_match_this( param );
  478.     }
  479.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  480.     {
  481.         return _iterative_rematch_this( param );
  482.     }
  483.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  484.     {
  485.         return _iterative_rematch_this( param );
  486.     }
  487. protected:
  488.     struct old_quant
  489.     {
  490.         size_t reserved2;
  491.         bool   reserved3;
  492.         CI     reserved4;
  493.         CI     reserved5;
  494.         old_quant() 
  495.         {
  496.         }
  497.         old_quant( backref_tag<CI> const & br )
  498.           : reserved2( br.reserved2 ), reserved3( br.reserved3 ),
  499.             reserved4( br.reserved4 ), reserved5( br.reserved5 )
  500.         {
  501.         }
  502.     };
  503.     void _push_frame( match_param<CI> & param ) const
  504.     {
  505.         backref_tag<CI> & br = ( *param.prgbackrefs )[ group_number() ];
  506.         old_quant old_qt( br );
  507.         param.pstack->push( old_qt );
  508.         br.reserved2 = 0;    // nbr of times this group has matched
  509.         br.reserved3 = true; // toggle used for backtracking
  510.         br.reserved4 = static_init<CI>::value;
  511.         br.reserved5 = static_init<CI>::value;
  512.     }
  513.     void _pop_frame( match_param<CI> & param ) const
  514.     {
  515.         backref_tag<CI> & br = ( *param.prgbackrefs )[ group_number() ];
  516.         old_quant old_qt;
  517.         param.pstack->pop( old_qt );
  518.         br.reserved2 = old_qt.reserved2;
  519.         br.reserved3 = old_qt.reserved3;
  520.         br.reserved4 = old_qt.reserved4;
  521.         br.reserved5 = old_qt.reserved5;
  522.     }
  523.     size_t group_number() const
  524.     {
  525.         return m_group.group_number();
  526.     }
  527.     size_t & cmatches( match_param<CI> & param ) const
  528.     {
  529.         return ( *param.prgbackrefs )[ group_number() ].reserved2;
  530.     }
  531.     CI & highwater1( match_param<CI> & param ) const
  532.     {
  533.         return ( *param.prgbackrefs )[ group_number() ].reserved4;
  534.     }
  535.     CI & highwater2( match_param<CI> & param ) const
  536.     {
  537.         return ( *param.prgbackrefs )[ group_number() ].reserved5;
  538.     }
  539.     match_group_base<CI> const & m_group;
  540. };
  541. template< typename CI >
  542. inline group_quantifier<CI>::~group_quantifier()
  543. {
  544. }
  545. template< typename CI >
  546. class max_group_quantifier : public group_quantifier<CI>
  547. {
  548.     max_group_quantifier & operator=( max_group_quantifier const & );
  549.     
  550.     template< typename CSTRINGS >
  551.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  552.     {
  553.         CI     old_highwater1 = highwater1( param );
  554.         CI     old_highwater2 = highwater2( param );
  555.         size_t old_cmatches   = cmatches( param );
  556.         highwater1( param ) = static_init<CI>::value;
  557.         highwater2( param ) = icur;
  558.         cmatches( param )   = 0;
  559.         if( _recurse( param, icur, CSTRINGS() ) )
  560.             return true;
  561.         cmatches( param )   = old_cmatches;
  562.         highwater2( param ) = old_highwater2;
  563.         highwater1( param ) = old_highwater1;
  564.         return false;
  565.     }
  566. public:
  567.     max_group_quantifier( match_group_base<CI> * psub, size_t lbound, size_t ubound )
  568.         : group_quantifier<CI>( psub, lbound, ubound, & m_end_quant ),
  569.           m_end_quant( this ) 
  570.     {
  571.     }
  572.     virtual ~max_group_quantifier()
  573.     {
  574.         // Must call _cleanup() here before the end_quant object
  575.         // gets destroyed.
  576.         _cleanup();
  577.     }
  578.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  579.     {
  580.         return _recursive_match_all( param, icur, false_t() );
  581.     }
  582.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  583.     {
  584.         return _recursive_match_all( param, icur, true_t() );
  585.     }
  586. protected:
  587.     template< typename CSTRINGS >
  588.     bool _recurse( match_param<CI> & param, CI icur, CSTRINGS ) const
  589.     {
  590.         if( m_ubound == cmatches( param ) )
  591.             return recursive_match_next_( param, icur, CSTRINGS() );
  592.         ++cmatches( param );
  593.         if( m_psub->recursive_match_all_( param, icur, CSTRINGS() ) )
  594.             return true;
  595.         if( --cmatches( param ) < m_lbound )
  596.             return false;
  597.         return recursive_match_next_( param, icur, CSTRINGS() );
  598.     }
  599.     class end_quantifier : public indestructable_sub_expr<CI, end_quantifier>
  600.     {
  601.         max_group_quantifier<CI> const *const m_pquant;
  602.         end_quantifier & operator=( end_quantifier const & );
  603.         void _push_frame( match_param<CI> & param ) const
  604.         {
  605.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  606.             param.pstack->push( br.reserved4 );
  607.             br.reserved4 = br.reserved5;
  608.             br.reserved5 = param.icur;
  609.         }
  610.         void _pop_frame( match_param<CI> & param ) const
  611.         {
  612.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  613.             br.reserved5 = br.reserved4;
  614.             param.pstack->pop( br.reserved4 );
  615.         }
  616.         template< typename CSTRINGS >
  617.         bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  618.         {
  619.             CI old_highwater1 = m_pquant->highwater1( param );
  620.             if( icur == old_highwater1 )
  621.                 return m_pquant->recursive_match_next_( param, icur, CSTRINGS() );
  622.             m_pquant->highwater1( param ) = m_pquant->highwater2( param );
  623.             m_pquant->highwater2( param ) = icur;
  624.             if( m_pquant->_recurse( param, icur, CSTRINGS() ) )
  625.                 return true;
  626.             m_pquant->highwater2( param ) = m_pquant->highwater1( param );
  627.             m_pquant->highwater1( param ) = old_highwater1;
  628.             return false;
  629.         }
  630.         bool _iterative_match_this( match_param<CI> & param ) const
  631.         {
  632.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  633.             // forcibly break the infinite loop
  634.             if( param.icur == br.reserved4 )
  635.             {
  636.                 _push_frame( param );
  637.                 param.next = m_pquant->next();
  638.                 return true;
  639.             }
  640.             _push_frame( param );
  641.             // If we've matched the max nbr of times, move on to the next
  642.             // sub-expr. 
  643.             if( m_pquant->m_ubound == br.reserved2 )
  644.             {
  645.                 param.next = m_pquant->next();
  646.                 br.reserved3 = false;
  647.                 return true;
  648.             }
  649.             // Rematch the group.
  650.             br.reserved3 = true;
  651.             param.next = m_pquant->m_psub;
  652.             ++br.reserved2;
  653.             return true;
  654.         }
  655.         bool _iterative_rematch_this( match_param<CI> & param ) const
  656.         {
  657.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  658.             // infinite loop forcibly broken
  659.             if( param.icur == param.pstack->top( static_init<CI>::value ) )
  660.             {
  661.                 _pop_frame( param );
  662.                 return false;
  663.             }
  664.             if( br.reserved3 )
  665.             {
  666.                 --br.reserved2;
  667.                 param.next = m_pquant->next();
  668.                 if( m_pquant->m_lbound <= br.reserved2 )
  669.                 {
  670.                     br.reserved3 = false;
  671.                     return true;
  672.                 }
  673.                 _pop_frame( param );
  674.                 return false;
  675.             }
  676.             br.reserved3 = true;
  677.             _pop_frame( param );
  678.             return false;
  679.         }
  680.     public:
  681.         end_quantifier( max_group_quantifier<CI> const * pquant = NULL )
  682.             : m_pquant( pquant )
  683.         {
  684.         }
  685.         virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  686.         {
  687.             return _recursive_match_all( param, icur, false_t() );
  688.         }
  689.         virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  690.         {
  691.             return _recursive_match_all( param, icur, true_t() );
  692.         }
  693.         virtual bool iterative_match_this_( match_param<CI> & param ) const
  694.         {
  695.             return _iterative_match_this( param );
  696.         }
  697.         virtual bool iterative_match_this_c( match_param<CI> & param ) const
  698.         {
  699.             return _iterative_match_this( param );
  700.         }
  701.         virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  702.         {
  703.             return _iterative_rematch_this( param );
  704.         }
  705.         virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  706.         {
  707.             return _iterative_rematch_this( param );
  708.         }
  709.         virtual width_type width_this( width_param<CI> & )
  710.         {
  711.             return zero_width;
  712.         }
  713.     } m_end_quant;
  714.     friend class end_quantifier;
  715. };
  716. template< typename CI >
  717. class min_group_quantifier : public group_quantifier<CI>
  718. {
  719.     min_group_quantifier & operator=( min_group_quantifier const & );
  720.     template< typename CSTRINGS >
  721.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  722.     {
  723.         CI     old_highwater1 = highwater1( param );
  724.         CI     old_highwater2 = highwater2( param );
  725.         size_t old_cmatches   = cmatches( param );
  726.         highwater1( param ) = static_init<CI>::value;
  727.         highwater2( param ) = icur;
  728.         cmatches( param )   = 0;
  729.         if( _recurse( param, icur, CSTRINGS() ) )
  730.             return true;
  731.         cmatches( param )   = old_cmatches;
  732.         highwater2( param ) = old_highwater2;
  733.         highwater1( param ) = old_highwater1;
  734.         return false;
  735.     }
  736. public:
  737.     min_group_quantifier( match_group_base<CI> * psub, size_t lbound, size_t ubound )
  738.         : group_quantifier<CI>( psub, lbound, ubound, & m_end_quant ),
  739.           m_end_quant( this )
  740.     {
  741.     }
  742.     virtual ~min_group_quantifier()
  743.     {
  744.         // Must call _cleanup() here before the end_quant object
  745.         // gets destroyed.
  746.         _cleanup();
  747.     }
  748.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  749.     {
  750.         return _recursive_match_all( param, icur, false_t() );
  751.     }
  752.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  753.     {
  754.         return _recursive_match_all( param, icur, true_t() );
  755.     }
  756. protected:
  757.     template< typename CSTRINGS >
  758.     bool _recurse( match_param<CI> & param, CI icur, CSTRINGS ) const
  759.     {
  760.         if( m_lbound <= cmatches( param ) )
  761.         {
  762.             if( recursive_match_next_( param, icur, CSTRINGS() ) )
  763.                 return true;
  764.         }
  765.         if( m_ubound > cmatches( param ) )
  766.         {
  767.             ++cmatches( param );
  768.             if( m_psub->recursive_match_all_( param, icur, CSTRINGS() ) )
  769.                 return true;
  770.             --cmatches( param );
  771.         }
  772.         return false;
  773.     }
  774.     class end_quantifier : public indestructable_sub_expr<CI, end_quantifier>
  775.     {
  776.         min_group_quantifier<CI> const *const m_pquant;
  777.         end_quantifier & operator=( end_quantifier const & );
  778.         void _push_frame( match_param<CI> & param ) const
  779.         {
  780.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  781.             param.pstack->push( br.reserved4 );
  782.             br.reserved4 = br.reserved5;
  783.             br.reserved5 = param.icur;
  784.         }
  785.         void _pop_frame( match_param<CI> & param ) const
  786.         {
  787.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  788.             br.reserved5 = br.reserved4;
  789.             param.pstack->pop( br.reserved4 );
  790.         }
  791.         template< typename CSTRINGS >
  792.         bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  793.         {
  794.             CI old_highwater1 = m_pquant->highwater1( param );
  795.             if( icur == old_highwater1 )
  796.                 return m_pquant->recursive_match_next_( param, icur, CSTRINGS() );
  797.             m_pquant->highwater1( param ) = m_pquant->highwater2( param );
  798.             m_pquant->highwater2( param ) = icur;
  799.             if( m_pquant->_recurse( param, icur, CSTRINGS() ) )
  800.                 return true;
  801.             m_pquant->highwater2( param ) = m_pquant->highwater1( param );
  802.             m_pquant->highwater1( param ) = old_highwater1;
  803.             return false;
  804.         }
  805.         bool _iterative_match_this( match_param<CI> & param ) const
  806.         {
  807.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  808.             // forcibly break the infinite loop
  809.             if( param.icur == br.reserved4 )
  810.             {
  811.                 _push_frame( param );
  812.                 param.next = m_pquant->next();
  813.                 return true;
  814.             }
  815.             _push_frame( param );
  816.             if( m_pquant->m_lbound <= br.reserved2 )
  817.             {
  818.                 br.reserved3 = false;
  819.                 param.next = m_pquant->next();
  820.                 return true;
  821.             }
  822.             ++br.reserved2;
  823.             param.next = m_pquant->m_psub;
  824.             return true;
  825.         }
  826.         
  827.         bool _iterative_rematch_this( match_param<CI> & param ) const
  828.         {
  829.             backref_tag<CI> & br = ( *param.prgbackrefs )[ m_pquant->group_number() ];
  830.             // infinite loop forcibly broken
  831.             if( param.icur == param.pstack->top( static_init<CI>::value ) )
  832.             {
  833.                 _pop_frame( param );
  834.                 return false;
  835.             }
  836.             if( br.reserved3 )
  837.             {
  838.                 --br.reserved2;
  839.                 _pop_frame( param );
  840.                 return false;
  841.             }
  842.             br.reserved3 = true;
  843.             if( m_pquant->m_ubound > br.reserved2 )
  844.             {
  845.                 ++br.reserved2;
  846.                 param.next = m_pquant->m_psub;
  847.                 return true;
  848.             }
  849.             _pop_frame( param );
  850.             return false;
  851.         }
  852.     public:
  853.         end_quantifier( min_group_quantifier<CI> const * pquant = NULL )
  854.             : m_pquant( pquant )
  855.         {
  856.         }
  857.         
  858.         virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  859.         {
  860.             return _recursive_match_all( param, icur, false_t() );
  861.         }
  862.         virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  863.         {
  864.             return _recursive_match_all( param, icur, true_t() );
  865.         }
  866.         virtual bool iterative_match_this_( match_param<CI> & param ) const
  867.         {
  868.             return _iterative_match_this( param );
  869.         }
  870.         virtual bool iterative_match_this_c( match_param<CI> & param ) const
  871.         {
  872.             return _iterative_match_this( param );
  873.         }
  874.         virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  875.         {
  876.             return _iterative_rematch_this( param );
  877.         }
  878.         virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  879.         {
  880.             return _iterative_rematch_this( param );
  881.         }
  882.         virtual width_type width_this( width_param<CI> & )
  883.         {
  884.             return zero_width;
  885.         }
  886.     } m_end_quant;
  887.     friend class end_quantifier;
  888. };
  889. inline void fixup_backref( size_t & cbackref, std::list<size_t> const & invisible_groups )
  890. {
  891.     std::list<size_t>::const_iterator iter = invisible_groups.begin();
  892.     for( ; iter != invisible_groups.end() && cbackref >= *iter; ++iter )
  893.     {
  894.         ++cbackref;
  895.     }
  896. }
  897. template< typename CI >
  898. class match_backref : public sub_expr<CI>
  899. {
  900.     bool _iterative_rematch_this( match_param<CI> & param ) const
  901.     {
  902.         backref_tag<CI> const & br = ( *param.prgbackrefs )[ m_cbackref ];
  903.         ptrdiff_t dist = std::distance( br.first, br.second );
  904.         std::advance( param.icur, ( int ) - dist );
  905.         return false;
  906.     }
  907. public:
  908.     match_backref( size_t cbackref )
  909.         : m_cbackref( cbackref )
  910.     {
  911.     }
  912.     // Return the width specifications of the group to which this backref refers
  913.     virtual width_type width_this( width_param<CI> & param )
  914.     {
  915.         // fix up the backref to take into account the number of invisible groups
  916.         if( param.first_pass() )
  917.             fixup_backref( m_cbackref, param.invisible_groups );
  918.         if( m_cbackref >= param.rggroups.size() )
  919.             throw bad_regexpr( "reference to nonexistent group" );
  920.         // If the entry in the backref vector has been nulled out, then we are
  921.         // calculating the width for this group.
  922.         if( NULL == param.rggroups[ m_cbackref ] )
  923.             return worst_width; // can't tell how wide this group will be.  :-(
  924.         return param.rggroups[ m_cbackref ]->width_this( param );
  925.     }
  926.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  927.     {
  928.         return _iterative_rematch_this( param );
  929.     }
  930.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  931.     {
  932.         return _iterative_rematch_this( param );
  933.     }
  934. protected:
  935.     size_t m_cbackref;
  936. };
  937. template< typename CMP, typename CI >
  938. class match_backref_t : public match_backref<CI>
  939. {
  940. public:
  941.     match_backref_t( size_t cbackref )
  942.         : match_backref<CI>( cbackref ) 
  943.     {
  944.     }
  945.     virtual sub_expr<CI> * quantify( size_t lbound, size_t ubound, bool greedy, regex_arena & arena )
  946.     {
  947.         if( greedy )
  948.             return new( arena ) max_atom_quantifier<CI, match_backref_t<CMP, CI> >( this, lbound, ubound );
  949.         else
  950.             return new( arena ) min_atom_quantifier<CI, match_backref_t<CMP, CI> >( this, lbound, ubound );
  951.     }
  952.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  953.     {
  954.         return ( match_backref_t::recursive_match_this_( param, icur ) && recursive_match_next_( param, icur, false_t() ) );
  955.     }
  956.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  957.     {
  958.         return ( match_backref_t::recursive_match_this_c( param, icur ) && recursive_match_next_( param, icur, true_t() ) );
  959.     }
  960.     virtual bool recursive_match_this_( match_param<CI> & param, CI & icur ) const
  961.     {
  962.         return _do_match_this( param, icur, false_t() );
  963.     }
  964.     virtual bool recursive_match_this_c( match_param<CI> & param, CI & icur ) const
  965.     {
  966.         return _do_match_this( param, icur, true_t() );
  967.     }
  968.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  969.     {
  970.         param.next = next();
  971.         return _do_match_this( param, param.icur, false_t() );
  972.     }
  973.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  974.     {
  975.         param.next = next();
  976.         return _do_match_this( param, param.icur, true_t() );
  977.     }
  978. protected:
  979.     template< typename CSTRINGS >
  980.     bool _do_match_this( match_param<CI> & param, CI & icur, CSTRINGS ) const
  981.     {
  982.         // Pattern compilation should have failed if the following is false:
  983.         assert( m_cbackref < param.prgbackrefs->size() );
  984.         // Don't match a backref that hasn't match anything
  985.         if( ! ( *param.prgbackrefs )[ m_cbackref ].matched )
  986.             return false;
  987.         CI ithis       = ( *param.prgbackrefs )[ m_cbackref ].first;
  988.         CI const istop = ( *param.prgbackrefs )[ m_cbackref ].second;
  989.         CI icur_tmp    = icur;
  990.         for( ; istop != ithis; ++icur_tmp, ++ithis )
  991.         {
  992.             if( eos_t<CSTRINGS>::eval( param, icur_tmp ) || CMP::eval( *icur_tmp, *ithis ) )
  993.                 return false;
  994.         }
  995.         icur = icur_tmp;
  996.         return true;
  997.     }
  998. };
  999. template< typename CI >
  1000. inline match_backref<CI> * create_backref(
  1001.     size_t cbackref,
  1002.     REGEX_FLAGS flags, regex_arena & arena )
  1003. {
  1004.     typedef typename std::iterator_traits<CI>::value_type char_type;
  1005.     switch( NOCASE & flags )
  1006.     {
  1007.     case 0:
  1008.         return new( arena ) match_backref_t<ch_neq_t<char_type>, CI>( cbackref );
  1009.     case NOCASE:
  1010.         return new( arena ) match_backref_t<ch_neq_nocase_t<char_type>, CI>( cbackref );
  1011.     default:
  1012.         __assume( 0 ); // tells the compiler that this is unreachable
  1013.     }
  1014. }
  1015. template< typename CI >
  1016. class match_recurse : public sub_expr<CI>
  1017. {
  1018.     match_recurse & operator=( match_recurse const & );
  1019.     void _push_frame( match_param<CI> & param ) const
  1020.     {
  1021.         typedef typename match_param<CI>::backref_vector::const_iterator VCI;
  1022.         unsafe_stack * pstack = param.pstack;
  1023.         VCI istart = param.prgbackrefs->begin();
  1024.         VCI iend   = param.prgbackrefs->end();
  1025.         for( ; iend != istart; ++istart )
  1026.         {
  1027.             pstack->push( istart->reserved1 );
  1028.         }
  1029.     }
  1030.     void _pop_frame( match_param<CI> & param ) const
  1031.     {
  1032.         typedef typename match_param<CI>::backref_vector::iterator VI;
  1033.         unsafe_stack * pstack = param.pstack;
  1034.         VI istart = param.prgbackrefs->begin();
  1035.         VI iend   = param.prgbackrefs->end();
  1036.         while( iend != istart )
  1037.         {
  1038.             --iend;
  1039.             pstack->pop( iend->reserved1 );
  1040.         }
  1041.     }
  1042.     template< typename CSTRINGS >
  1043.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  1044.     {
  1045.         // Prevent infinite recursion. If icur == ( *param.prgbackrefs )[ 0 ].reserved1,
  1046.         // then the pattern has eaten 0 chars to date, and we would recurse forever.
  1047.         if( icur == ( *param.prgbackrefs )[ 0 ].reserved1 )
  1048.             return recursive_match_next_( param, icur, CSTRINGS() );
  1049.         // copy the backref vector onto the stack
  1050.         CI * prgci = static_cast<CI*>( alloca( param.prgbackrefs->size() * sizeof( CI ) ) );
  1051.         save_backrefs<CI>( *param.prgbackrefs, prgci );
  1052.         // Recurse.
  1053.         if( param.first->recursive_match_all_( param, icur, CSTRINGS() ) )
  1054.         {
  1055.             // Restore the backref vector
  1056.             restore_backrefs<CI>( *param.prgbackrefs, prgci );
  1057.             // Recursive match succeeded. Try to match the rest of the pattern
  1058.             // using the end of the recursive match as the start of the next
  1059.             return recursive_match_next_( param, ( *param.prgbackrefs )[ 0 ].second, CSTRINGS() );
  1060.         }
  1061.         // Recursion failed
  1062.         return false;
  1063.     }
  1064.     template< typename CSTRINGS >
  1065.     bool _iterative_match_this( match_param<CI> & param, CSTRINGS ) const
  1066.     {
  1067.         param.pstack->push( param.icur );
  1068.         // Prevent infine recursion
  1069.         if( param.icur == ( *param.prgbackrefs )[ 0 ].reserved1 )
  1070.         {
  1071.             param.next = next();
  1072.             return true;
  1073.         }
  1074.         _push_frame( param );
  1075.         if( matcher_helper<CI>::_Do_match_iterative( param.first, param, param.icur, CSTRINGS() ) )
  1076.         {
  1077.             _pop_frame( param );
  1078.             param.next = next();
  1079.             return true;
  1080.         }
  1081.         _pop_frame( param );
  1082.         param.pstack->pop( param.icur );
  1083.         return false;
  1084.     }
  1085.     bool _iterative_rematch_this( match_param<CI> & param ) const
  1086.     {
  1087.         param.pstack->pop( param.icur );
  1088.         return false;
  1089.     }
  1090. public:
  1091.     match_recurse()
  1092.     {
  1093.     }
  1094.     virtual sub_expr<CI> * quantify( size_t, size_t, bool, regex_arena & )
  1095.     {
  1096.         throw bad_regexpr( "recursion sub-expression cannot be quantified" );
  1097.     }
  1098.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  1099.     {
  1100.         return _recursive_match_all( param, icur, false_t() );
  1101.     }
  1102.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  1103.     {
  1104.         return _recursive_match_all( param, icur, true_t() );
  1105.     }
  1106.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  1107.     {
  1108.         return _iterative_match_this( param, false_t() );
  1109.     }
  1110.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  1111.     {
  1112.         return _iterative_match_this( param, true_t() );
  1113.     }
  1114.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  1115.     {
  1116.         return _iterative_rematch_this( param );
  1117.     }
  1118.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  1119.     {
  1120.         return _iterative_rematch_this( param );
  1121.     }
  1122.     virtual width_type width_this( width_param<CI> & param )
  1123.     {
  1124.         // We need to know how big the whole pattern is before we can say
  1125.         // how big a recursive match would be.
  1126.         if( param.first_pass() )
  1127.         {
  1128.             ++param.cookie;
  1129.             return zero_width;
  1130.         }
  1131.         width_type this_width = param.total_width;
  1132.         this_width.m_max = width_mult( this_width.m_max, size_t( -1 ) ); // could recurse forever
  1133.         return this_width;
  1134.     }
  1135. };
  1136. template< typename CI >
  1137. inline match_recurse<CI> * create_recurse( regex_arena & arena )
  1138. {
  1139.     return new( arena ) match_recurse<CI>();
  1140. }
  1141. template< typename CI >
  1142. struct backref_condition
  1143. {
  1144.     size_t m_cbackref;
  1145.     backref_condition( size_t cbackref )
  1146.         : m_cbackref( cbackref )
  1147.     {
  1148.     }
  1149.     template< typename CSTRINGS >
  1150.     bool recursive_match_this_( match_param<CI> & param, CI, CSTRINGS ) const
  1151.     {
  1152.         return m_cbackref < param.prgbackrefs->size() && ( *param.prgbackrefs )[ m_cbackref ].matched;
  1153.     }
  1154.     template< typename CSTRINGS >
  1155.     bool iterative_match_this_( match_param<CI> & param, CSTRINGS ) const
  1156.     {
  1157.         return m_cbackref < param.prgbackrefs->size() && ( *param.prgbackrefs )[ m_cbackref ].matched;
  1158.     }
  1159.     template< typename CSTRINGS >
  1160.     bool iterative_rematch_this_( match_param<CI> &, CSTRINGS ) const
  1161.     {
  1162.         return false;
  1163.     }
  1164.     void width_this( width_param<CI> & param )
  1165.     {
  1166.         // fix up the backref to take into account the number of invisible groups
  1167.         if( param.first_pass() )
  1168.             fixup_backref( m_cbackref, param.invisible_groups );
  1169.     }
  1170. };
  1171. template< typename CI >
  1172. struct assertion_condition
  1173. {
  1174.     std::auto_ptr<match_group_base<CI> > m_passert;
  1175.     assertion_condition( match_group_base<CI> * passert )
  1176.         : m_passert( passert )
  1177.     {
  1178.     }
  1179.     bool recursive_match_this_( match_param<CI> & param, CI icur, false_t ) const
  1180.     {
  1181.         return m_passert->recursive_match_all_( param, icur );
  1182.     }
  1183.     bool recursive_match_this_( match_param<CI> & param, CI icur, true_t ) const
  1184.     {
  1185.         return m_passert->recursive_match_all_c( param, icur );
  1186.     }
  1187.     bool iterative_match_this_( match_param<CI> & param, false_t ) const
  1188.     {
  1189.         return m_passert->iterative_match_this_( param );
  1190.     }
  1191.     bool iterative_match_this_( match_param<CI> & param, true_t ) const
  1192.     {
  1193.         return m_passert->iterative_match_this_c( param );
  1194.     }
  1195.     bool iterative_rematch_this_( match_param<CI> & param, false_t ) const
  1196.     {
  1197.         return m_passert->iterative_rematch_this_( param );
  1198.     }
  1199.     bool iterative_rematch_this_( match_param<CI> & param, true_t ) const
  1200.     {
  1201.         return m_passert->iterative_rematch_this_c( param );
  1202.     }
  1203.     void width_this( width_param<CI> & param )
  1204.     {
  1205.         ( void ) m_passert->width_this( param );
  1206.     }
  1207. };
  1208. template< typename CI, typename COND >
  1209. class match_conditional : public match_group<CI>
  1210. {
  1211. protected:
  1212.     typedef typename match_group<CI>::alt_list_type alt_list_type;
  1213. private:
  1214.     match_conditional & operator=( match_conditional const & );
  1215.     template< typename CSTRINGS >
  1216.     bool _recursive_match_all( match_param<CI> & param, CI icur, CSTRINGS ) const
  1217.     {
  1218.         typedef typename alt_list_type::const_iterator LCI;
  1219.         LCI ialt = m_rgalternates.begin();
  1220.         if( m_condition.recursive_match_this_( param, icur, CSTRINGS() ) || ++ialt != m_rgalternates.end() )
  1221.         {
  1222.             return (*ialt)->recursive_match_all_( param, icur, CSTRINGS() );
  1223.         }
  1224.         return recursive_match_next_( param, icur, CSTRINGS() );
  1225.     }
  1226.     template< typename CSTRINGS >
  1227.     bool _iterative_match_this( match_param<CI> & param, CSTRINGS ) const
  1228.     {
  1229.         typedef typename alt_list_type::const_iterator LCI;
  1230.         LCI ialt = m_rgalternates.begin();
  1231.         if( m_condition.iterative_match_this_( param, CSTRINGS() ) )
  1232.         {
  1233.             param.pstack->push( true );
  1234.             param.next = *ialt;
  1235.             return true;
  1236.         }
  1237.         param.pstack->push( false );
  1238.         param.next = ( ++ialt != m_rgalternates.end() ) ? *ialt : next();
  1239.         return true;
  1240.     }
  1241.     template< typename CSTRINGS >
  1242.     bool _iterative_rematch_this( match_param<CI> & param, CSTRINGS ) const
  1243.     {
  1244.         bool condition;
  1245.         param.pstack->pop( condition );
  1246.         if( condition )
  1247.             m_condition.iterative_rematch_this_( param, CSTRINGS() );
  1248.         return false;
  1249.     }
  1250. public:
  1251.     typedef COND condition_type;
  1252.     match_conditional( size_t cgroup, condition_type condition, regex_arena & arena )
  1253.         : match_group<CI>( cgroup, arena ),
  1254.           m_condition( condition )
  1255.     {
  1256.     }
  1257.     virtual bool recursive_match_all_( match_param<CI> & param, CI icur ) const
  1258.     {
  1259.         return _recursive_match_all( param, icur, false_t() );
  1260.     }
  1261.     virtual bool recursive_match_all_c( match_param<CI> & param, CI icur ) const
  1262.     {
  1263.         return _recursive_match_all( param, icur, true_t() );
  1264.     }
  1265.     virtual bool iterative_match_this_( match_param<CI> & param ) const
  1266.     {
  1267.         return _iterative_match_this( param, false_t() );
  1268.     }
  1269.     virtual bool iterative_match_this_c( match_param<CI> & param ) const
  1270.     {
  1271.         return _iterative_match_this( param, true_t() );
  1272.     }
  1273.     virtual bool iterative_rematch_this_( match_param<CI> & param ) const
  1274.     {
  1275.         return _iterative_rematch_this( param, false_t() );
  1276.     }
  1277.     virtual bool iterative_rematch_this_c( match_param<CI> & param ) const
  1278.     {
  1279.         return _iterative_rematch_this( param, true_t() );
  1280.     }
  1281.     virtual width_type width_this( width_param<CI> & param )
  1282.     {
  1283.         typedef typename alt_list_type::const_iterator LCI;
  1284.         LCI ialt = m_rgalternates.begin();
  1285.         width_type width = ( *ialt )->get_width( param );
  1286.         if( ++ialt != m_rgalternates.end() )
  1287.         {
  1288.             width_type temp_width = ( *ialt )->get_width( param );
  1289.             width.m_min = (std::min)( width.m_min, temp_width.m_min );
  1290.             width.m_max = (std::max)( width.m_max, temp_width.m_max );
  1291.         }
  1292.         else
  1293.         {
  1294.             width.m_min = 0;
  1295.         }
  1296.         // Have the condition calculate its width, too. This is important
  1297.         // if the condition is a lookbehind assertion.
  1298.         m_condition.width_this( param );
  1299.         return m_nwidth = width;
  1300.     }
  1301. protected:
  1302.     condition_type m_condition;
  1303. };
  1304. template< typename CI >
  1305. inline match_conditional<CI, backref_condition<CI> > * create_backref_conditional(
  1306.     size_t cgroup,
  1307.     size_t cbackref,
  1308.     regex_arena & arena )
  1309. {
  1310.     backref_condition<CI> cond( cbackref );
  1311.     return new( arena ) match_conditional<CI, backref_condition<CI> >(
  1312.         cgroup, cond, arena );
  1313. }
  1314. template< typename CI >
  1315. inline match_conditional<CI, assertion_condition<CI> > * create_assertion_conditional(
  1316.     size_t cgroup,
  1317.     match_group_base<CI> * passert,
  1318.     regex_arena & arena )
  1319. {
  1320.     assertion_condition<CI> cond( passert );
  1321.     return new( arena ) match_conditional<CI, assertion_condition<CI> >(
  1322.         cgroup, cond, arena );
  1323. }
  1324. // REGEX_ALLOCATOR is a #define which determines which allocator
  1325. // gets used as the STL-compliant allocator. When sub_expr objects
  1326. // contain STL containers as members, REGEX_ALLOCATOR is the allocator
  1327. // type used. (See the match_group and charset classes.) If REGEX_ALLOCATOR
  1328. // expands to regex_allocator, then *all* memory used when compiling
  1329. // a pattern ends up in a regex_arena.  In that case, destructors do
  1330. // not need to be called; we can just throw the arena away. However, if
  1331. // REGEX_ALLOCATOR expands to anything else (std::allocator, for instance)
  1332. // then some of the memory does not live in a regex_arena, and destructors
  1333. // do need to be called.  The following code enforces this logic.
  1334. template< typename AL >
  1335. struct skip_dtor_calls
  1336. {
  1337.     enum { value = false };
  1338. };
  1339. template<>
  1340. struct skip_dtor_calls< regex_allocator<char> >
  1341. {
  1342.     enum { value = true };
  1343. };
  1344. //
  1345. // From basic_rpattern_base_impl
  1346. //
  1347. template< typename CI >
  1348. REGEXPR_H_INLINE basic_rpattern_base_impl<CI>::~basic_rpattern_base_impl()
  1349. {
  1350.     if( skip_dtor_calls< REGEX_ALLOCATOR<char> >::value )
  1351.     {
  1352.         m_pfirst.release();
  1353.     }
  1354.     assign_auto_ptr( m_pfirst, static_cast<sub_expr_base<CI>const*>(0) );
  1355.     m_arena.deallocate();
  1356. }
  1357. template< typename CI >
  1358. REGEXPR_H_INLINE bool basic_rpattern_base_impl<CI>::_do_match( match_param<CI> & param, bool use_null ) const
  1359. {
  1360.     if( GLOBAL & flags() ) // do a global find
  1361.     {
  1362.         // The NOBACKREFS flag is ignored in the match method.
  1363.         bool const fAll   = ( ALLBACKREFS   == ( ALLBACKREFS   & flags() ) );
  1364.         bool const fFirst = ( FIRSTBACKREFS == ( FIRSTBACKREFS & flags() ) );
  1365.         backref_vector rgtempbackrefs;
  1366.         while( matcher_helper<CI>::_Do_match( *this, param, use_null ) )
  1367.         {
  1368.             backref_type const & br = ( *param.prgbackrefs )[0];
  1369.             // Handle specially the backref flags
  1370.             if( fFirst )
  1371.                 rgtempbackrefs.push_back( br );
  1372.             else if( fAll )
  1373.                 rgtempbackrefs.insert(
  1374.                     rgtempbackrefs.end(),
  1375.                     param.prgbackrefs->begin(),
  1376.                     param.prgbackrefs->end() );
  1377.             else
  1378.                 rgtempbackrefs.swap( *param.prgbackrefs );
  1379.             param.istart = br.second;
  1380.             param.no0len = ( br.first == br.second );
  1381.         }
  1382.         // restore the backref vectors
  1383.         param.prgbackrefs->swap( rgtempbackrefs );
  1384.         return ! param.prgbackrefs->empty();
  1385.     }
  1386.     else
  1387.         return matcher_helper<CI>::_Do_match( *this, param, use_null );
  1388. }
  1389. template< typename CI >
  1390. REGEXPR_H_INLINE bool basic_rpattern_base_impl<CI>::_do_match( match_param<CI> & param, char_type const * szbegin ) const
  1391. {
  1392.     if( RIGHTMOST & flags() )
  1393.     {
  1394.         // We need to know the end of the string if we're doing a
  1395.         // RIGHTMOST match
  1396.         param.istop = param.istart;
  1397.         std::advance( param.istop, traits_type::length( szbegin ) );
  1398.         return basic_rpattern_base_impl<CI>::_do_match( param, false );
  1399.     }
  1400.     return basic_rpattern_base_impl<CI>::_do_match( param, true );
  1401. }
  1402. template< typename CI >
  1403. REGEXPR_H_INLINE size_t basic_rpattern_base_impl<CI>::_do_count( match_param<CI> & param, bool use_null ) const
  1404. {
  1405.     size_t cmatches = 0;
  1406.     while( matcher_helper<CI>::_Do_match( *this, param, use_null ) )
  1407.     {
  1408.         backref_type const & br = ( *param.prgbackrefs )[0];
  1409.         ++cmatches;
  1410.         param.istart = br.second;
  1411.         param.no0len = ( br.first == br.second );
  1412.     }
  1413.     return cmatches;
  1414. }
  1415. template< typename CI >
  1416. REGEXPR_H_INLINE size_t basic_rpattern_base_impl<CI>::_do_count( match_param<CI> & param, char_type const * szbegin ) const
  1417. {
  1418.     if( RIGHTMOST & flags() )
  1419.     {
  1420.         // We need to know the end of the string if we're doing a
  1421.         // RIGHTMOST count
  1422.         param.istop = param.istart;
  1423.         std::advance( param.istop, traits_type::length( szbegin ) );
  1424.         return basic_rpattern_base_impl<CI>::_do_count( param, false );
  1425.     }
  1426.     return basic_rpattern_base_impl<CI>::_do_count( param, true );
  1427. }
  1428. // A helper class for automatically deallocating the arena when
  1429. // parsing the pattern results in an exception
  1430. struct deallocation_helper
  1431. {
  1432.     deallocation_helper( regex_arena & arena )
  1433.         : m_arena( arena ),
  1434.           m_fparse_successful( false )
  1435.     {
  1436.     }
  1437.     ~deallocation_helper()
  1438.     {
  1439.         if( ! m_fparse_successful )
  1440.             m_arena.deallocate();
  1441.     }
  1442.     
  1443.     void dismiss()
  1444.     {
  1445.         m_fparse_successful = true;
  1446.     }
  1447. private:
  1448.     deallocation_helper & operator=( deallocation_helper const & );
  1449.     regex_arena & m_arena;
  1450.     bool m_fparse_successful;
  1451. };
  1452. } // namespace detail
  1453. //
  1454. // Implementation of basic_rpattern_base:
  1455. //
  1456. template< typename CI, typename SY >
  1457. REGEXPR_H_INLINE void basic_rpattern_base<CI, SY>::init( string_type const & pat, REGEX_FLAGS flags, REGEX_MODE mode )
  1458. {
  1459.     basic_rpattern_base<CI, SY> temp( pat, flags, mode );
  1460.     swap( temp );
  1461. }
  1462. template< typename CI, typename SY >
  1463. REGEXPR_H_INLINE void basic_rpattern_base<CI, SY>::init( string_type const & pat, string_type const & subst, REGEX_FLAGS flags, REGEX_MODE mode )
  1464. {
  1465.     basic_rpattern_base<CI, SY> temp( pat, subst, flags, mode );
  1466.     swap( temp );
  1467. }
  1468. template< typename CI, typename SY >
  1469. REGEXPR_H_INLINE void basic_rpattern_base<CI, SY>::_common_init( REGEX_FLAGS flags )
  1470. {
  1471.     m_cgroups = 0;
  1472.     std::vector<detail::match_group_base<CI>*> rggroups;
  1473.     typename string_type::iterator ipat = m_pat->begin();
  1474.     iter_wrap iw( ipat );
  1475.     syntax_type sy( flags );
  1476.     detail::match_group_base<CI> * pgroup;
  1477.     // Set up a sentry that will free the arena memory
  1478.     // automatically on parse failure.
  1479.     {
  1480.         detail::deallocation_helper parse_sentry( m_arena );
  1481.         // This will throw on failure
  1482.         pgroup = _find_next_group( iw, NULL, sy, rggroups );
  1483.         // Note that the parse was successful
  1484.         parse_sentry.dismiss();
  1485.     }
  1486.     assert( NULL == m_pfirst.get() );
  1487.     detail::assign_auto_ptr( m_pfirst, pgroup );
  1488.     // Calculate the width of the pattern and all groups
  1489.     m_nwidth = pgroup->group_width( rggroups, m_invisible_groups );
  1490.     //
  1491.     // determine if we can get away with only calling m_pfirst->recursive_match_all_ only once
  1492.     //
  1493.     m_floop = true;
  1494.     // Optimization: if first character of pattern string is '^'
  1495.     // and we are not doing a multiline match, then we only
  1496.     // need to try recursive_match_all_ once
  1497.     typename string_type::iterator icur = m_pat->begin();
  1498.     if( MULTILINE != ( MULTILINE & m_flags ) &&
  1499.         1 == pgroup->calternates() &&
  1500.         icur != m_pat->end() &&
  1501.         BEGIN_LINE == sy.reg_token( icur, m_pat->end() ) )
  1502.     {
  1503.         m_flags = ( REGEX_FLAGS ) ( m_flags & ~RIGHTMOST );
  1504.         m_floop = false;
  1505.     }
  1506.     // Optimization: if first 2 characters of pattern string are ".*" or ".+",
  1507.     // then we only need to try recursive_match_all_ once
  1508.     icur = m_pat->begin();
  1509.     if( RIGHTMOST != ( RIGHTMOST & m_flags ) &&
  1510.         SINGLELINE == ( SINGLELINE & m_flags ) &&
  1511.         1 == pgroup->calternates() &&
  1512.         icur != m_pat->end() &&
  1513.         MATCH_ANY == sy.reg_token( icur, m_pat->end() ) &&
  1514.         icur != m_pat->end() )
  1515.     {
  1516.         switch( sy.quant_token( icur, m_pat->end() ) )
  1517.         {
  1518.         case ONE_OR_MORE:
  1519.         case ZERO_OR_MORE:
  1520.         case ONE_OR_MORE_MIN:
  1521.         case ZERO_OR_MORE_MIN:
  1522.             m_floop = false;
  1523.         }
  1524.     }
  1525. }
  1526. template< typename CI, typename SY >
  1527. REGEXPR_H_INLINE void basic_rpattern_base<CI, SY>::set_substitution( string_type const & subst )
  1528. {
  1529.     std::auto_ptr<string_type> temp_subst( new string_type( subst ) );
  1530.     detail::subst_list_type temp_subst_list;
  1531.     bool uses_backrefs = false;
  1532.     _normalize_string( *temp_subst );
  1533.     basic_rpattern_base<CI, SY>::_parse_subst( *temp_subst, uses_backrefs, temp_subst_list );
  1534.     detail::swap_auto_ptr( temp_subst, m_subst );
  1535.     std::swap( uses_backrefs, m_fuses_backrefs );
  1536.     temp_subst_list.swap( m_subst_list );
  1537. }
  1538. template< typename CI, typename SY >
  1539. inline detail::match_group_base<CI> * basic_rpattern_base<CI, SY>::_find_next_group(
  1540.     iter_wrap & iw,
  1541.     detail::match_group_base<CI> * pgroup_enclosing, syntax_type & sy,
  1542.     std::vector<detail::match_group_base<CI>*> & rggroups )
  1543. {
  1544.     std::auto_ptr<detail::match_group_base<CI> > pgroup;
  1545.     typename string_type::iterator itemp = iw.ipat;
  1546.     REGEX_FLAGS old_flags = sy.get_flags();
  1547.     TOKEN tok;
  1548.     size_t extent_start = m_cgroups;
  1549.     bool fconditional = false;
  1550.     // Look for group extensions.
  1551.     if( m_pat->end() != iw.ipat && NO_TOKEN != ( tok = sy.ext_token( iw.ipat, m_pat->end() ) ) )
  1552.     {
  1553.         if( m_pat->begin() == itemp || m_pat->end() == iw.ipat )
  1554.             throw bad_regexpr( "ill-formed regular expression" );
  1555.         // Is this a recursion element?
  1556.         if( EXT_RECURSE == tok )
  1557.         {
  1558.             pgroup_enclosing->add_item( detail::create_recurse<CI>( m_arena ) );
  1559.             // This pattern could recurse deeply. Note that fact here so that
  1560.             // we can opt to use a stack-conservative algorithm at match time.
  1561.             m_fok_to_recurse = false;
  1562.         }
  1563.         // Don't process empty groups like (?:) or (?i) or (?R)
  1564.         if( END_GROUP != sy.reg_token( itemp = iw.ipat, m_pat->end() ) )
  1565.         {
  1566.             switch( tok )
  1567.             {
  1568.             case EXT_NOBACKREF:
  1569.                 // note that this group is not visible, so we can fix
  1570.                 // up offsets into the backref vector later
  1571.                 m_invisible_groups.push_back( m_cgroups );
  1572.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::match_group<CI>( _get_next_group_nbr(), m_arena ) );
  1573.                 break;
  1574.             case EXT_INDEPENDENT:
  1575.                 m_invisible_groups.push_back( m_cgroups );
  1576.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::independent_group<CI>( _get_next_group_nbr(), m_arena ) );
  1577.                 break;
  1578.             case EXT_POS_LOOKAHEAD:
  1579.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::lookahead_assertion<CI>( true, m_arena ) );
  1580.                 break;
  1581.             case EXT_NEG_LOOKAHEAD:
  1582.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::lookahead_assertion<CI>( false, m_arena ) );
  1583.                 break;
  1584.             case EXT_POS_LOOKBEHIND:
  1585.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::lookbehind_assertion<CI>( true, m_arena ) );
  1586.                 break;
  1587.             case EXT_NEG_LOOKBEHIND:
  1588.                 detail::assign_auto_ptr( pgroup, new( m_arena ) detail::lookbehind_assertion<CI>( false, m_arena ) );
  1589.                 break;
  1590.             case EXT_CONDITION:
  1591.                 fconditional = true;
  1592.                 m_invisible_groups.push_back( m_cgroups );
  1593.                 if( size_t cbackref = detail::parse_int( iw.ipat, m_pat->end() ) &&
  1594.                     END_GROUP == sy.reg_token( iw.ipat, m_pat->end() ) )
  1595.                 {
  1596.                     detail::assign_auto_ptr( 
  1597.                         pgroup, detail::create_backref_conditional<CI>( 
  1598.                             _get_next_group_nbr(), cbackref, m_arena ) );
  1599.                 }
  1600.                 else
  1601.                 {
  1602.                     switch( sy.ext_token( itemp = iw.ipat, m_pat->end() ) )
  1603.                     {
  1604.                     case EXT_POS_LOOKAHEAD:
  1605.                     case EXT_NEG_LOOKAHEAD:
  1606.                     case EXT_POS_LOOKBEHIND:
  1607.                     case EXT_NEG_LOOKBEHIND:
  1608.                         {
  1609.                             std::auto_ptr<detail::match_group_base<CI> > pgroup_tmp( 
  1610.                                 _find_next_group( iw, NULL, sy, rggroups ) );
  1611.                             detail::assign_auto_ptr( 
  1612.                                 pgroup, detail::create_assertion_conditional<CI>( 
  1613.                                     _get_next_group_nbr(), pgroup_tmp.get(), m_arena ) );
  1614.                             pgroup_tmp.release();
  1615.                         }
  1616.                         break;
  1617.                     default:
  1618.                         throw bad_regexpr( "bad extension sequence" );
  1619.                     }
  1620.                 }
  1621.                 break;
  1622.             case EXT_COMMENT:
  1623.                 while( END_GROUP != ( tok = sy.reg_token( iw.ipat, m_pat->end() ) ) )
  1624.                 {
  1625.                     if( NO_TOKEN == tok && m_pat->end() != iw.ipat )
  1626.                         ++iw.ipat;
  1627.                     if( m_pat->end() == iw.ipat )
  1628.                         throw bad_regexpr( "Expecting end of comment" );
  1629.                 }
  1630.                 break;
  1631.             default:
  1632.                 throw bad_regexpr( "bad extension sequence" );
  1633.             }
  1634.         }
  1635.         else
  1636.         {
  1637.             // Skip over the END_GROUP token
  1638.             iw.ipat = itemp;
  1639.         }
  1640.     }
  1641.     else
  1642.     {
  1643.         detail::assign_auto_ptr( pgroup, new( m_arena ) detail::match_group<CI>( _get_next_group_nbr(), m_arena ) );
  1644.         ++m_cgroups_visible;
  1645.     }
  1646.     if( NULL != pgroup.get() )
  1647.     {
  1648.         pgroup->add_alternate();
  1649.         while( _find_next( iw, pgroup.get(), sy, rggroups ) );
  1650.         pgroup->end_alternate();
  1651.         // if this is a conditional group, then there must be at
  1652.         // most 2 alternates.
  1653.         if( fconditional && 2 < pgroup->calternates() )
  1654.             throw bad_regexpr( "Too many alternates in conditional subexpression" );
  1655.         // Add this group to the rggroups array
  1656.         if( size_t( -1 ) != pgroup->group_number() )
  1657.         {
  1658.             if( pgroup->group_number() >= rggroups.size() )
  1659.                 rggroups.resize( pgroup->group_number() + 1, NULL );
  1660.             rggroups[ pgroup->group_number() ] = pgroup.get();
  1661.         }
  1662.         // tell this group how many groups are contained within it
  1663.         pgroup->set_extent( detail::extent( extent_start, m_cgroups - extent_start ) );
  1664.         // If this is not a pattern modifier, restore the
  1665.         // flags to their previous settings.  This causes
  1666.         // pattern modifiers to have the scope of their
  1667.         // enclosing group.
  1668.         sy.set_flags( old_flags );
  1669.     }
  1670.     return pgroup.release();
  1671. }
  1672. namespace detail
  1673. {
  1674. // If we reached the end of the string before finding the end of the
  1675. // character set, then this is an ill-formed regex
  1676. template< typename CI >
  1677. inline void check_iter( CI icur, CI istop )
  1678. {
  1679.     if( istop == icur )
  1680.         throw bad_regexpr( "expecting end of character set" );
  1681. }
  1682. template< typename II, typename CI >
  1683. inline typename std::iterator_traits<CI>::value_type get_escaped_char( II & icur, CI iend, bool normalize )
  1684. {
  1685.     typedef typename std::iterator_traits<CI>::value_type CH;
  1686.     CH ch = 0, i;
  1687.     check_iter<CI>( icur, iend );
  1688.     switch( *icur )
  1689.     {
  1690.     // octal escape sequence
  1691.     case REGEX_CHAR(CH,'0'): case REGEX_CHAR(CH,'1'): case REGEX_CHAR(CH,'2'): case REGEX_CHAR(CH,'3'):
  1692.     case REGEX_CHAR(CH,'4'): case REGEX_CHAR(CH,'5'): case REGEX_CHAR(CH,'6'): case REGEX_CHAR(CH,'7'):
  1693.         ch = CH( *icur++ - REGEX_CHAR(CH,'0') );
  1694.         for( i=0; i<2 && REGEX_CHAR(CH,'0') <= *icur && REGEX_CHAR(CH,'7') >= *icur; check_iter<CI>( ++icur, iend ) )
  1695.             ch = CH( ch * 8 + ( *icur - REGEX_CHAR(CH,'0') ) );
  1696.         break;
  1697.     // bell character
  1698.     case REGEX_CHAR(CH,'a'):
  1699.         if( ! normalize )
  1700.             goto default_;
  1701.         ch = REGEX_CHAR(CH,'a');
  1702.         ++icur;
  1703.         break;
  1704.     // control character
  1705.     case REGEX_CHAR(CH,'c'):
  1706.         check_iter<CI>( ++icur, iend );
  1707.         ch = *icur++;
  1708.         if( REGEX_CHAR(CH,'a') <= ch && REGEX_CHAR(CH,'z') >= ch )
  1709.             ch = detail::regex_toupper( ch );
  1710.         ch ^= 0x40;
  1711.         break;
  1712.     // escape character
  1713.     case REGEX_CHAR(CH,'e'):
  1714.         ch = 27;
  1715.         ++icur;
  1716.         break;
  1717.     // formfeed character
  1718.     case REGEX_CHAR(CH,'f'):
  1719.         if( ! normalize )
  1720.             goto default_;
  1721.         ch = REGEX_CHAR(CH,'f');
  1722.         ++icur;
  1723.         break;
  1724.     // newline
  1725.     case REGEX_CHAR(CH,'n'):
  1726.         if( ! normalize )
  1727.             goto default_;
  1728.         ch = REGEX_CHAR(CH,'n');
  1729.         ++icur;
  1730.         break;
  1731.     // return
  1732.     case REGEX_CHAR(CH,'r'):
  1733.         if( ! normalize )
  1734.             goto default_;
  1735.         ch = REGEX_CHAR(CH,'r');
  1736.         ++icur;
  1737.         break;
  1738.     // horizontal tab
  1739.     case REGEX_CHAR(CH,'t'):
  1740.         if( ! normalize )
  1741.             goto default_;
  1742.         ch = REGEX_CHAR(CH,'t');
  1743.         ++icur;
  1744.         break;
  1745.     // vertical tab
  1746.     case REGEX_CHAR(CH,'v'):
  1747.         if( ! normalize )
  1748.             goto default_;
  1749.         ch = REGEX_CHAR(CH,'v');
  1750.         ++icur;
  1751.         break;
  1752.     // hex escape sequence
  1753.     case REGEX_CHAR(CH,'x'):
  1754.         for( ++icur, ch=i=0; i<2 && detail::regex_isxdigit( *icur ); check_iter<CI>( ++icur, iend ) )
  1755.             ch = CH( ch * 16 + detail::regex_xdigit2int( *icur ) );
  1756.         break;
  1757.     // backslash
  1758.     case REGEX_CHAR(CH,'\'):
  1759.         if( ! normalize )
  1760.             goto default_;
  1761.         ch = REGEX_CHAR(CH,'\');
  1762.         ++icur;
  1763.         break;
  1764.     // all other escaped characters represent themselves
  1765.     default: default_:
  1766.         ch = *icur;
  1767.         ++icur;
  1768.         break;
  1769.     }
  1770.     return ch;
  1771. }
  1772. template< typename CH, typename CS, typename SY >
  1773. inline void parse_charset(
  1774.     std::auto_ptr<CS> & pnew,
  1775.     typename std::basic_string<CH>::iterator & icur,
  1776.     typename std::basic_string<CH>::const_iterator iend,
  1777.     SY & sy )
  1778. {
  1779.     typedef CH char_type;
  1780.     typedef std::basic_string<CH> string_type;
  1781.     typedef typename string_type::const_iterator CI;
  1782.     typename string_type::iterator itemp = icur;
  1783.     bool const normalize = ( NORMALIZE == ( NORMALIZE & sy.get_flags() ) );
  1784.     if( iend != itemp && CHARSET_NEGATE == sy.charset_token( itemp, iend ) )
  1785.     {
  1786.         pnew->m_fcompliment = true;
  1787.         icur = itemp;
  1788.     }
  1789.     TOKEN tok;
  1790.     char_type ch_prev = 0;
  1791.     bool fhave_prev = false;
  1792.     charset const * pcharset = NULL;
  1793.     typename string_type::iterator iprev = icur;
  1794.     bool const fnocase = ( NOCASE == ( NOCASE & sy.get_flags() ) );
  1795.     check_iter<CI>( icur, iend );
  1796.     // remember the current position and grab the next token
  1797.     tok = sy.charset_token( icur, iend );
  1798.     do
  1799.     {
  1800.         check_iter<CI>( icur, iend );
  1801.         if( CHARSET_RANGE == tok && fhave_prev )
  1802.         {
  1803.             // remember the current position
  1804.             typename string_type::iterator iprev2 = icur;
  1805.             fhave_prev = false;
  1806.             // ch_prev is lower bound of a range
  1807.             switch( sy.charset_token( icur, iend ) )
  1808.             {
  1809.             case CHARSET_RANGE:
  1810.             case CHARSET_NEGATE:
  1811.                 icur = iprev2; // un-get these tokens and fall through
  1812.             case NO_TOKEN:
  1813.                 pnew->set_bit_range( ch_prev, *icur++, fnocase );
  1814.                 continue;
  1815.             case CHARSET_ESCAPE: // BUGBUG user-defined charset?
  1816.                 pnew->set_bit_range( ch_prev, get_escaped_char( icur, iend, normalize ), fnocase );
  1817.                 continue;
  1818.             case CHARSET_BACKSPACE:
  1819.                 pnew->set_bit_range( ch_prev, char_type( 8 ), fnocase ); // backspace
  1820.                 continue;
  1821.             case CHARSET_END: // fall through
  1822.             default:          // not a range.
  1823.                 icur = iprev; // backup to range token
  1824.                 pnew->set_bit( ch_prev, fnocase );
  1825.                 pnew->set_bit( *icur++, fnocase );
  1826.                 continue;
  1827.             }
  1828.         }
  1829.         if( fhave_prev )
  1830.             pnew->set_bit( ch_prev, fnocase );
  1831.         fhave_prev = false;
  1832.         switch( tok )
  1833.         {
  1834.             // None of the intrinsic charsets are case-sensitive,
  1835.             // so no special handling must be done when the NOCASE
  1836.             // flag is set.
  1837.         case CHARSET_RANGE:
  1838.         case CHARSET_NEGATE:
  1839.         case CHARSET_END:
  1840.             icur = iprev; // un-get these tokens
  1841.             ch_prev = *icur++;
  1842.             fhave_prev = true;
  1843.             continue;
  1844.         case CHARSET_BACKSPACE:
  1845.             ch_prev = char_type( 8 ); // backspace
  1846.             fhave_prev = true;
  1847.             continue;
  1848.         case ESC_DIGIT:
  1849.             *pnew |= intrinsic_charsets<char_type>::get_digit_charset();
  1850.             continue;
  1851.         case ESC_NOT_DIGIT:
  1852.             *pnew |= intrinsic_charsets<char_type>::get_not_digit_charset();
  1853.             continue;
  1854.         case ESC_SPACE:
  1855.             *pnew |= intrinsic_charsets<char_type>::get_space_charset();
  1856.             continue;
  1857.         case ESC_NOT_SPACE:
  1858.             *pnew |= intrinsic_charsets<char_type>::get_not_space_charset();
  1859.             continue;
  1860.         case ESC_WORD:
  1861.             *pnew |= intrinsic_charsets<char_type>::get_word_charset();
  1862.             continue;
  1863.         case ESC_NOT_WORD:
  1864.             *pnew |= intrinsic_charsets<char_type>::get_not_word_charset();
  1865.             continue;
  1866.         case CHARSET_ALNUM:
  1867.             pnew->m_posixcharson |= ( _ALNUM );
  1868.             continue;
  1869.         case CHARSET_NOT_ALNUM:
  1870.             pnew->m_posixcharsoff.push_back( _ALNUM );
  1871.             continue;
  1872.         case CHARSET_ALPHA:
  1873.             pnew->m_posixcharson |= ( _ALPHA );
  1874.             continue;
  1875.         case CHARSET_NOT_ALPHA:
  1876.             pnew->m_posixcharsoff.push_back( _ALPHA );
  1877.             continue;
  1878.         case CHARSET_BLANK:
  1879.             pnew->m_posixcharson |= ( _BLANK );
  1880.             continue;
  1881.         case CHARSET_NOT_BLANK:
  1882.             pnew->m_posixcharsoff.push_back( _BLANK );
  1883.             continue;
  1884.         case CHARSET_CNTRL:
  1885.             pnew->m_posixcharson |= ( _CONTROL );
  1886.             continue;
  1887.         case CHARSET_NOT_CNTRL:
  1888.             pnew->m_posixcharsoff.push_back( _CONTROL );
  1889.             continue;
  1890.         case CHARSET_DIGIT:
  1891.             pnew->m_posixcharson |= ( _DIGIT );
  1892.             continue;
  1893.         case CHARSET_NOT_DIGIT:
  1894.             pnew->m_posixcharsoff.push_back( _DIGIT );
  1895.             continue;
  1896.         case CHARSET_GRAPH:
  1897.             pnew->m_posixcharson |= ( _GRAPH );
  1898.             continue;
  1899.         case CHARSET_NOT_GRAPH:
  1900.             pnew->m_posixcharsoff.push_back( _GRAPH );
  1901.             continue;
  1902.         case CHARSET_LOWER:
  1903.             if( NOCASE == ( NOCASE & sy.get_flags() ) )
  1904.                 pnew->m_posixcharson |= ( _LOWER|_UPPER );
  1905.             else
  1906.                 pnew->m_posixcharson |= ( _LOWER );
  1907.             continue;
  1908.         case CHARSET_NOT_LOWER:
  1909.             if( NOCASE == ( NOCASE & sy.get_flags() ) )
  1910.                 pnew->m_posixcharsoff.push_back( _LOWER|_UPPER );
  1911.             else
  1912.                 pnew->m_posixcharsoff.push_back( _LOWER );
  1913.             continue;
  1914.         case CHARSET_PRINT:
  1915.             pnew->m_posixcharson |= ( _PRINT );
  1916.             continue;
  1917.         case CHARSET_NOT_PRINT:
  1918.             pnew->m_posixcharsoff.push_back( _PRINT );
  1919.             continue;
  1920.         case CHARSET_PUNCT:
  1921.             pnew->m_posixcharson |= ( _PUNCT );
  1922.             continue;
  1923.         case CHARSET_NOT_PUNCT:
  1924.             pnew->m_posixcharsoff.push_back( _PUNCT );
  1925.             continue;
  1926.         case CHARSET_SPACE:
  1927.             pnew->m_posixcharson |= ( _SPACE );
  1928.             continue;
  1929.         case CHARSET_NOT_SPACE:
  1930.             pnew->m_posixcharsoff.push_back( _SPACE );
  1931.             continue;
  1932.         case CHARSET_UPPER:
  1933.             if( NOCASE == ( NOCASE & sy.get_flags() ) )
  1934.                 pnew->m_posixcharson |= ( _UPPER|_LOWER );
  1935.             else
  1936.                 pnew->m_posixcharson |= ( _UPPER );
  1937.             continue;
  1938.         case CHARSET_NOT_UPPER:
  1939.             if( NOCASE == ( NOCASE & sy.get_flags() ) )
  1940.                 pnew->m_posixcharsoff.push_back( _UPPER|_LOWER );
  1941.             else
  1942.                 pnew->m_posixcharsoff.push_back( _UPPER );
  1943.             continue;
  1944.         case CHARSET_XDIGIT:
  1945.             pnew->m_posixcharson |= ( _HEX );
  1946.             continue;
  1947.         case CHARSET_NOT_XDIGIT:
  1948.             pnew->m_posixcharsoff.push_back( _HEX );
  1949.             continue;
  1950.         case CHARSET_ESCAPE:
  1951.             // Maybe this is a user-defined intrinsic charset
  1952.             pcharset = get_altern_charset( *icur, sy );
  1953.             if( NULL != pcharset )
  1954.             {
  1955.                  *pnew |= *pcharset;
  1956.                  ++icur;
  1957.                  continue;
  1958.             }
  1959.             else
  1960.             {
  1961.                 ch_prev = get_escaped_char( icur, iend, normalize );
  1962.                 fhave_prev = true;
  1963.             }
  1964.             continue;
  1965.         default:
  1966.             ch_prev = *icur++;
  1967.             fhave_prev = true;
  1968.             continue;
  1969.         }
  1970.     }
  1971.     while( check_iter<CI>( iprev = icur, iend ),
  1972.            CHARSET_END != ( tok = sy.charset_token( icur, iend ) ) );
  1973.     if( fhave_prev )
  1974.         pnew->set_bit( ch_prev, fnocase );
  1975.     pnew->optimize( type2type<char_type>() );
  1976. }
  1977. template< typename CH, typename SY >
  1978. inline charset const * get_altern_charset( CH ch, SY & sy )
  1979. {
  1980.     typedef std::basic_string<CH> string_type;
  1981.     charset const * pcharset = NULL;
  1982.     regex::detail::charset_map<CH> & charset_map = sy.s_charset_map;
  1983.     typename regex::detail::charset_map<CH>::iterator iter = charset_map.find( ch );
  1984.     if( charset_map.end() != iter )
  1985.     {
  1986.         bool const fnocase = ( NOCASE == ( sy.get_flags() & NOCASE ) );
  1987.         pcharset = iter->second.m_rgcharsets[ fnocase ];
  1988.         if( NULL == pcharset )
  1989.         {
  1990.             // tmp takes ownership of any ptrs.
  1991.             charset_map_node<CH> tmp = iter->second;
  1992.             charset_map.erase( iter ); // prevent possible infinite recursion
  1993.             typename string_type::iterator istart = tmp.m_str.begin();
  1994.             std::auto_ptr<charset> pnew( new charset );
  1995.             std::auto_ptr<charset const> pold( tmp.m_rgcharsets[ !fnocase ] );
  1996.             parse_charset<CH, charset>( pnew, istart, tmp.m_str.end(), sy );
  1997.             tmp.m_rgcharsets[ fnocase ] = pcharset = pnew.get();
  1998.             charset_map[ ch ] = tmp; // could throw
  1999.             // charset_map has taken ownership of these pointers now.
  2000.             pnew.release();
  2001.             pold.release();
  2002.         }
  2003.     }
  2004.     return pcharset;
  2005. }
  2006. } // namespace detail
  2007. //
  2008. // Read ahead through the pattern and treat sequential atoms
  2009. // as a single atom, making sure to handle quantification
  2010. // correctly. Warning: dense code ahead.
  2011. //
  2012. template< typename CI, typename SY >
  2013. inline void basic_rpattern_base<CI, SY>::_find_atom(
  2014.     iter_wrap & iw,
  2015.     detail::match_group_base<CI> * pgroup,
  2016.     syntax_type & sy )
  2017. {
  2018.     typename string_type::iterator itemp = iw.ipat, istart;
  2019.     size_t const nstart = std::distance( m_pat->begin(), iw.ipat );
  2020.     do
  2021.     {
  2022.         if( itemp != iw.ipat ) // Is there whitespace to skip?
  2023.         {
  2024.             size_t dist = std::distance( m_pat->begin(), iw.ipat );
  2025.             m_pat->erase( iw.ipat, itemp ); // erase the whitespace from the patttern
  2026.             std::advance( iw.ipat = m_pat->begin(), dist );
  2027.             if( m_pat->end() == ( itemp = iw.ipat ) ) // are we at the end of the pattern?
  2028.                 break;
  2029.         }
  2030.         switch( sy.quant_token( itemp, m_pat->end() ) )
  2031.         {
  2032.             // if {, } can't be interpreted as quantifiers, treat them as regular chars
  2033.         case BEGIN_RANGE:
  2034.             std::advance( istart = m_pat->begin(), nstart );
  2035.             if( istart != iw.ipat ) // treat as a quantifier
  2036.                 goto quantify;
  2037.         case NO_TOKEN:
  2038.         case END_RANGE:
  2039.         case END_RANGE_MIN:
  2040.         case RANGE_SEPARATOR:
  2041.             break;
  2042.         default:
  2043.             std::advance( istart = m_pat->begin(), nstart );
  2044.             if( istart == iw.ipat ) // must be able to quantify something.
  2045.                 throw bad_regexpr( "quantifier not expected" );
  2046. quantify:   if( istart != --iw.ipat )
  2047.                 pgroup->add_item( detail::create_literal<CI>( istart, iw.ipat, sy.get_flags(), m_arena ) );
  2048.             std::auto_ptr<detail::sub_expr<CI> > pnew( detail::create_char<CI>( *iw.ipat++, sy.get_flags(), m_arena ) );
  2049.             _quantify( pnew, iw, false, sy );
  2050.             pgroup->add_item( pnew.release() );
  2051.             return;
  2052.         }
  2053.     } while( m_pat->end() != ++iw.ipat && ! sy.reg_token( itemp = iw.ipat, m_pat->end() ) );
  2054.     std::advance( istart = m_pat->begin(), nstart );
  2055.     assert( iw.ipat != istart );
  2056.     pgroup->add_item( detail::create_literal<CI>( istart, iw.ipat, sy.get_flags(), m_arena ) );
  2057. }
  2058. template< typename CI, typename SY >
  2059. inline bool basic_rpattern_base<CI, SY>::_find_next(
  2060.     iter_wrap & iw,
  2061.     detail::match_group_base<CI> * pgroup,
  2062.     syntax_type & sy,
  2063.     std::vector<detail::match_group_base<CI>*> & rggroups )
  2064. {
  2065.     typedef char_type CH;
  2066.     std::auto_ptr<detail::sub_expr<CI> > pnew;
  2067.     std::auto_ptr<detail::custom_charset> pcs;
  2068.     typename string_type::iterator istart, itemp;
  2069.     bool fdone, is_group = false;
  2070.     bool const normalize = ( NORMALIZE == ( NORMALIZE & sy.get_flags() ) );
  2071.     if( m_pat->end() == iw.ipat )
  2072.     {
  2073.         if( 0 != pgroup->group_number() )
  2074.             throw bad_regexpr( "mismatched parenthesis" );
  2075.         return false;
  2076.     }
  2077.     switch( sy.reg_token( iw.ipat, m_pat->end() ) )
  2078.     {
  2079.     case NO_TOKEN: // not a token. Must be an atom
  2080.         if( m_pat->end() == iw.ipat )
  2081.         {
  2082.             if( 0 != pgroup->group_number() )
  2083.                 throw bad_regexpr( "mismatched parenthesis" );
  2084.             return false;
  2085.         }
  2086.         _find_atom( iw, pgroup, sy );
  2087.         return true;
  2088.     case END_GROUP:
  2089.         if( 0 == pgroup->group_number() )
  2090.             throw bad_regexpr( "mismatched parenthesis" );
  2091.         return false;
  2092.     case ALTERNATION:
  2093.         pgroup->end_alternate();
  2094.         pgroup->add_alternate();
  2095.         return true;
  2096.     case BEGIN_GROUP:
  2097.         // Find next group. could return NULL if the group is really
  2098.         // a pattern modifier, like: ( ?s-i )
  2099.         detail::assign_auto_ptr( pnew, _find_next_group( iw, pgroup, sy, rggroups ) );
  2100.         is_group = true;
  2101.         break;
  2102.     case BEGIN_LINE:
  2103.         detail::assign_auto_ptr( pnew, detail::create_bol<CI>( sy.get_flags(), m_arena ) );
  2104.         break;
  2105.     case END_LINE:
  2106.         detail::assign_auto_ptr( pnew, detail::create_eol<CI>( sy.get_flags(), m_arena ) );
  2107.         break;
  2108.     case BEGIN_CHARSET:
  2109.         detail::assign_auto_ptr( pcs, new( m_arena ) detail::custom_charset( m_arena ) );
  2110.         detail::parse_charset<char_type, detail::custom_charset>(
  2111.             pcs, iw.ipat, m_pat->end(), sy );
  2112.         detail::assign_auto_ptr( pnew,
  2113.             detail::create_custom_charset<CI>( pcs.get(), sy.get_flags(), m_arena ) );
  2114.         pcs.release();
  2115.         break;
  2116.     case MATCH_ANY:
  2117.         detail::assign_auto_ptr( pnew, detail::create_any<CI>( sy.get_flags(), m_arena ) );
  2118.         break;
  2119.     case ESC_WORD_BOUNDARY:
  2120.         detail::assign_auto_ptr( pnew, detail::create_word_boundary<CI>( true, sy.get_flags(), m_arena ) );
  2121.         break;
  2122.     case ESC_NOT_WORD_BOUNDARY:
  2123.         detail::assign_auto_ptr( pnew, detail::create_word_boundary<CI>( false, sy.get_flags(), m_arena ) );
  2124.         break;
  2125.     case ESC_WORD_START:
  2126.         detail::assign_auto_ptr( pnew, detail::create_word_start<CI>( sy.get_flags(), m_arena ) );
  2127.         break;
  2128.     case ESC_WORD_STOP:
  2129.         detail::assign_auto_ptr( pnew, detail::create_word_stop<CI>( sy.get_flags(), m_arena ) );
  2130.         break;
  2131.     case ESC_DIGIT:
  2132.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_digit_charset(), sy.get_flags(), m_arena ) );
  2133.         break;
  2134.     case ESC_NOT_DIGIT:
  2135.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_not_digit_charset(), sy.get_flags(), m_arena ) );
  2136.         break;
  2137.     case ESC_WORD:
  2138.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_word_charset(), sy.get_flags(), m_arena ) );
  2139.         break;
  2140.     case ESC_NOT_WORD:
  2141.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_not_word_charset(), sy.get_flags(), m_arena ) );
  2142.         break;
  2143.     case ESC_SPACE:
  2144.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_space_charset(), sy.get_flags(), m_arena ) );
  2145.         break;
  2146.     case ESC_NOT_SPACE:
  2147.         detail::assign_auto_ptr( pnew, detail::create_charset<CI>( detail::intrinsic_charsets<char_type>::get_not_space_charset(), sy.get_flags(), m_arena ) );
  2148.         break;
  2149.     case ESC_BEGIN_STRING:
  2150.         detail::assign_auto_ptr( pnew, detail::create_bos<CI>( sy.get_flags(), m_arena ) );
  2151.         break;
  2152.     case ESC_END_STRING:
  2153.         detail::assign_auto_ptr( pnew, detail::create_eos<CI>( sy.get_flags(), m_arena ) );
  2154.         break;
  2155.     case ESC_END_STRING_z:
  2156.         detail::assign_auto_ptr( pnew, detail::create_eoz<CI>( sy.get_flags(), m_arena ) );
  2157.         break;
  2158.     case ESCAPE:
  2159.         if( m_pat->end() == iw.ipat )
  2160.         {
  2161.             // BUGBUG what if the escape sequence is more that 1 character?
  2162.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( *--iw.ipat, sy.get_flags(), m_arena ) );
  2163.             ++iw.ipat;
  2164.         }
  2165.         else if( REGEX_CHAR(CH,'0') <= *iw.ipat && REGEX_CHAR(CH,'9') >= *iw.ipat )
  2166.         {
  2167.             // Parse at most 3 decimal digits.
  2168.             size_t nbackref = detail::parse_int( itemp = iw.ipat, m_pat->end(), 999 );
  2169.             // If the resulting number could conceivably be a backref, then it is.
  2170.             if( REGEX_CHAR(CH,'0') != *iw.ipat && ( 10 > nbackref || nbackref < _cgroups_total() ) )
  2171.             {
  2172.                 detail::assign_auto_ptr( pnew, detail::create_backref<CI>( nbackref, sy.get_flags(), m_arena ) );
  2173.                 iw.ipat = itemp;
  2174.             }
  2175.             else
  2176.             {
  2177.                 // It's an octal character escape sequence. If *ipat is 8 or 9, insert
  2178.                 // a NULL character, and leave the 8 or 9 as a character literal.
  2179.                 char_type ch = 0, i = 0;
  2180.                 for( ; i < 3 && m_pat->end() != iw.ipat && REGEX_CHAR(CH,'0') <= *iw.ipat && REGEX_CHAR(CH,'7') >= *iw.ipat; ++i, ++iw.ipat )
  2181.                     ch = CH( ch * 8 + ( *iw.ipat - REGEX_CHAR(CH,'0') ) );
  2182.                 detail::assign_auto_ptr( pnew, detail::create_char<CI>( ch, sy.get_flags(), m_arena ) );
  2183.             }
  2184.         }
  2185.         else if( REGEX_CHAR(CH,'e') == *iw.ipat )
  2186.         {
  2187.             ++iw.ipat;
  2188.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( CH( 27 ), sy.get_flags(), m_arena ) );
  2189.         }
  2190.         else if( REGEX_CHAR(CH,'x') == *iw.ipat )
  2191.         {
  2192.             char_type ch = 0, i = 0;
  2193.             for( ++iw.ipat; i < 2 && m_pat->end() != iw.ipat && detail::regex_isxdigit( *iw.ipat ); ++i, ++iw.ipat )
  2194.                 ch = CH( ch * 16 + detail::regex_xdigit2int( *iw.ipat ) );
  2195.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( ch, sy.get_flags(), m_arena ) );
  2196.         }
  2197.         else if( REGEX_CHAR(CH,'c') == *iw.ipat )
  2198.         {
  2199.             if( m_pat->end() == ++iw.ipat )
  2200.                 throw bad_regexpr( "incomplete escape sequence \c" );
  2201.             char_type ch = *iw.ipat++;
  2202.             if( REGEX_CHAR(CH,'a') <= ch && REGEX_CHAR(CH,'z') >= ch )
  2203.                 ch = detail::regex_toupper( ch );
  2204.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( CH( ch ^ 0x40 ), sy.get_flags(), m_arena ) );
  2205.         }
  2206.         else if( REGEX_CHAR(CH,'a') == *iw.ipat && normalize )
  2207.         {
  2208.             ++iw.ipat;
  2209.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'a'), sy.get_flags(), m_arena ) );
  2210.         }
  2211.         else if( REGEX_CHAR(CH,'f') == *iw.ipat && normalize )
  2212.         {
  2213.             ++iw.ipat;
  2214.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'f'), sy.get_flags(), m_arena ) );
  2215.         }
  2216.         else if( REGEX_CHAR(CH,'n') == *iw.ipat && normalize )
  2217.         {
  2218.             ++iw.ipat;
  2219.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'n'), sy.get_flags(), m_arena ) );
  2220.         }
  2221.         else if( REGEX_CHAR(CH,'r') == *iw.ipat && normalize )
  2222.         {
  2223.             ++iw.ipat;
  2224.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'r'), sy.get_flags(), m_arena ) );
  2225.         }
  2226.         else if( REGEX_CHAR(CH,'t') == *iw.ipat && normalize )
  2227.         {
  2228.             ++iw.ipat;
  2229.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'t'), sy.get_flags(), m_arena ) );
  2230.         }
  2231.         else if( REGEX_CHAR(CH,'\') == *iw.ipat && normalize )
  2232.         {
  2233.             ++iw.ipat;
  2234.             detail::assign_auto_ptr( pnew, detail::create_char<CI>( REGEX_CHAR(CH,'\'), sy.get_flags(), m_arena ) );
  2235.         }
  2236.         else
  2237.         {
  2238.             // Is this a user-defined intrinsic character set?
  2239.             detail::charset const * pcharset = detail::get_altern_charset( *iw.ipat, sy );
  2240.             if( NULL != pcharset )
  2241.                 detail::assign_auto_ptr( pnew, detail::create_charset<CI>( *pcharset, sy.get_flags(), m_arena ) );
  2242.             else
  2243.                 detail::assign_auto_ptr( pnew, detail::create_char<CI>( *iw.ipat, sy.get_flags(), m_arena ) );
  2244.             ++iw.ipat;
  2245.         }
  2246.         break;
  2247.         // If quotemeta, loop until we find quotemeta off or end of string
  2248.     case ESC_QUOTE_META_ON:
  2249.         for( istart = itemp = iw.ipat, fdone = false; !fdone && m_pat->end() != iw.ipat; )
  2250.         {
  2251.             switch( sy.reg_token( iw.ipat, m_pat->end() ) )
  2252.             {
  2253.             case ESC_QUOTE_META_OFF:
  2254.                 fdone = true;
  2255.                 break;
  2256.             case NO_TOKEN:
  2257.                 if( m_pat->end() != iw.ipat )
  2258.                     ++iw.ipat; // fallthrough
  2259.             default:
  2260.                 itemp = iw.ipat;
  2261.                 break;
  2262.             }
  2263.         }
  2264.         if( itemp != istart )
  2265.             pgroup->add_item( detail::create_literal<CI>( istart, itemp, sy.get_flags(), m_arena ) );
  2266.         // skip the quantification code below
  2267.         return true;
  2268.     // Should never get here for valid patterns
  2269.     case ESC_QUOTE_META_OFF:
  2270.         throw bad_regexpr( "quotemeta turned off, but was never turned on" );
  2271.     default:
  2272.         assert( ! "Unhandled token type" );
  2273.         break;
  2274.     }
  2275.     // If pnew is null, then the current subexpression is a no-op.
  2276.     if( pnew.get() )
  2277.     {
  2278.         // Look for quantifiers
  2279.         _quantify( pnew, iw, is_group, sy );
  2280.         // Add the item to the group
  2281.         pgroup->add_item( pnew.release() );
  2282.     }
  2283.     return true;
  2284. }
  2285. template< typename CI, typename SY >
  2286. inline void basic_rpattern_base<CI, SY>::_quantify(
  2287.     std::auto_ptr<detail::sub_expr<CI> > & pnew,
  2288.     iter_wrap & iw,
  2289.     bool is_group,
  2290.     syntax_type & sy )
  2291. {
  2292.     if( m_pat->end() != iw.ipat && ! pnew->is_assertion() )
  2293.     {
  2294.         typename string_type::iterator itemp = iw.ipat, itemp2;
  2295.         bool fmin = false;
  2296.         // Since size_t is unsigned, -1 is really the largest size_t
  2297.         size_t lbound = ( size_t )-1;
  2298.         size_t ubound = ( size_t )-1;
  2299.         size_t ubound_tmp;
  2300.         switch( sy.quant_token( itemp, m_pat->end() ) )
  2301.         {
  2302.         case ZERO_OR_MORE_MIN:
  2303.             fmin = true;
  2304.         case ZERO_OR_MORE:
  2305.             lbound = 0;
  2306.             break;
  2307.         case ONE_OR_MORE_MIN:
  2308.             fmin = true;
  2309.         case ONE_OR_MORE:
  2310.             lbound = 1;
  2311.             break;
  2312.         case ZERO_OR_ONE_MIN:
  2313.             fmin = true;
  2314.         case ZERO_OR_ONE:
  2315.             lbound = 0;
  2316.             ubound = 1;
  2317.             break;
  2318.         case BEGIN_RANGE:
  2319.             lbound = detail::parse_int( itemp, m_pat->end() );
  2320.             if( m_pat->end() == itemp )
  2321.                 return; // not a valid quantifier - treat as atom
  2322.             switch( sy.quant_token( itemp, m_pat->end() ) )
  2323.             {
  2324.             case END_RANGE_MIN:
  2325.                 fmin = true;
  2326.             case END_RANGE:
  2327.                 ubound = lbound;
  2328.                 break;
  2329.             case RANGE_SEPARATOR:
  2330.                 itemp2 = itemp;
  2331.                 ubound_tmp = detail::parse_int( itemp, m_pat->end() );
  2332.                 if( itemp != itemp2 )
  2333.                     ubound = ubound_tmp;
  2334.                 if( itemp == m_pat->end() )
  2335.                     return; // not a valid quantifier - treat as atom
  2336.                 switch( sy.quant_token( itemp, m_pat->end() ) )
  2337.                 {
  2338.                 case END_RANGE_MIN:
  2339.                     fmin = true;
  2340.                 case END_RANGE:
  2341.                     break;
  2342.                 default:
  2343.                     return; // not a valid quantifier - treat as atom
  2344.                 }
  2345.                 break;
  2346.             default:
  2347.                 return; // not a valid quantifier - treat as atom
  2348.             }
  2349.             if( ubound < lbound  )
  2350.                 throw bad_regexpr( "Can't do {n, m} with n > m" );
  2351.             break;
  2352.         }
  2353.         if( ( size_t )-1 != lbound )
  2354.         {
  2355.             // If we are quantifying a group, then this pattern could recurse
  2356.             // deeply. Note that fact here so that we can opt to use a stack-
  2357.             // conservative algorithm at match time.
  2358.             if( is_group && ubound > 16 )
  2359.                 m_fok_to_recurse = false;
  2360.             std::auto_ptr<detail::sub_expr<CI> > pquant( pnew->quantify( lbound, ubound, ! fmin, m_arena ) );
  2361.             pnew.release();
  2362.             detail::assign_auto_ptr( pnew, pquant.release() );
  2363.             iw.ipat = itemp;
  2364.         }
  2365.     }
  2366. }
  2367. template< typename CI, typename SY >
  2368. inline void basic_rpattern_base<CI, SY>::_add_subst_backref( 
  2369.     detail::subst_node & snode, 
  2370.     size_t nbackref, 
  2371.     size_t rstart,
  2372.     bool & uses_backrefs,
  2373.     detail::subst_list_type & subst_list ) const
  2374. {
  2375.     uses_backrefs = true;
  2376.     assert( detail::subst_node::SUBST_STRING == snode.stype );
  2377.     if( snode.subst_string.rlength )
  2378.         subst_list.push_back( snode );
  2379.     snode.stype = detail::subst_node::SUBST_BACKREF;
  2380.     snode.subst_backref = nbackref;
  2381.     subst_list.push_back( snode );
  2382.     // re-initialize the detail::subst_node
  2383.     snode.stype = detail::subst_node::SUBST_STRING;
  2384.     snode.subst_string.rstart = rstart;
  2385.     snode.subst_string.rlength = 0;
  2386. }
  2387. template< typename CI, typename SY >
  2388. inline void basic_rpattern_base<CI, SY>::_parse_subst(
  2389.     string_type & subst,
  2390.     bool & uses_backrefs,
  2391.     detail::subst_list_type & subst_list ) const
  2392. {
  2393.     TOKEN tok;
  2394.     detail::subst_node snode;
  2395.     typename string_type::iterator icur = subst.begin();
  2396.     size_t nbackref;
  2397.     typename string_type::iterator itemp;
  2398.     bool fdone;
  2399.     syntax_type sy( m_flags );
  2400.     uses_backrefs = false;
  2401.     // Initialize the subst_node
  2402.     snode.stype = detail::subst_node::SUBST_STRING;
  2403.     snode.subst_string.rstart = 0;
  2404.     snode.subst_string.rlength = 0;
  2405.     while( subst.end() != icur )
  2406.     {
  2407.         switch( tok = sy.subst_token( icur, subst.end() ) )
  2408.         {
  2409.         case SUBST_MATCH:
  2410.             _add_subst_backref( snode, 0, std::distance( subst.begin(), icur ), uses_backrefs, subst_list );
  2411.             break;
  2412.         case SUBST_PREMATCH:
  2413.             _add_subst_backref( snode, ( size_t )detail::subst_node::PREMATCH, std::distance( subst.begin(), icur ), uses_backrefs, subst_list );
  2414.             break;
  2415.         case SUBST_POSTMATCH:
  2416.             _add_subst_backref( snode, ( size_t )detail::subst_node::POSTMATCH, std::distance( subst.begin(), icur ), uses_backrefs, subst_list );
  2417.             break;
  2418.         case SUBST_BACKREF:
  2419.             nbackref = detail::parse_int( icur, subst.end(), cgroups() - 1 ); // always at least 1 group
  2420.             if( 0 == nbackref )
  2421.                 throw bad_regexpr( "invalid backreference in substitution" );
  2422.             _add_subst_backref( snode, nbackref, std::distance( subst.begin(), icur ), uses_backrefs, subst_list );
  2423.             break;
  2424.         case SUBST_QUOTE_META_ON:
  2425.             assert( detail::subst_node::SUBST_STRING == snode.stype );
  2426.             if( snode.subst_string.rlength )
  2427.                 subst_list.push_back( snode );
  2428.             snode.subst_string.rstart = std::distance( subst.begin(), icur );
  2429.             for( itemp = icur, fdone = false; !fdone && subst.end() != icur; )
  2430.             {
  2431.                 switch( tok = sy.subst_token( icur, subst.end() ) )
  2432.                 {
  2433.                 case SUBST_ALL_OFF:
  2434.                     fdone = true;
  2435.                     break;
  2436.                 case NO_TOKEN:
  2437.                     ++icur; // fall-through
  2438.                 default:
  2439.                     itemp = icur;
  2440.                     break;
  2441.                 }
  2442.             }
  2443.             snode.subst_string.rlength = std::distance( subst.begin(), itemp ) - snode.subst_string.rstart;
  2444.             if( snode.subst_string.rlength )
  2445.                 subst_list.push_back( snode );
  2446.             if( tok == SUBST_ALL_OFF )
  2447.             {
  2448.                 snode.stype = detail::subst_node::SUBST_OP;
  2449.                 snode.op    = detail::subst_node::ALL_OFF;
  2450.                 subst_list.push_back( snode );
  2451.             }
  2452.             // re-initialize the subst_node
  2453.             snode.stype = detail::subst_node::SUBST_STRING;
  2454.             snode.subst_string.rstart = std::distance( subst.begin(), icur );
  2455.             snode.subst_string.rlength = 0;
  2456.             break;
  2457.         case SUBST_UPPER_ON:
  2458.         case SUBST_UPPER_NEXT:
  2459.         case SUBST_LOWER_ON:
  2460.         case SUBST_LOWER_NEXT:
  2461.         case SUBST_ALL_OFF:
  2462.             assert( detail::subst_node::SUBST_STRING == snode.stype );
  2463.             if( snode.subst_string.rlength )
  2464.                 subst_list.push_back( snode );
  2465.             snode.stype = detail::subst_node::SUBST_OP;
  2466.             snode.op    = ( detail::subst_node::op_type ) tok;
  2467.             subst_list.push_back( snode );
  2468.             // re-initialize the subst_node
  2469.             snode.stype = detail::subst_node::SUBST_STRING;
  2470.             snode.subst_string.rstart = std::distance( subst.begin(), icur );
  2471.             snode.subst_string.rlength = 0;
  2472.             break;
  2473.         case SUBST_ESCAPE:
  2474.             if( subst.end() == icur )
  2475.                 throw bad_regexpr( "expecting escape sequence in substitution string" );
  2476.             assert( detail::subst_node::SUBST_STRING == snode.stype );
  2477.             if( snode.subst_string.rlength )
  2478.                 subst_list.push_back( snode );
  2479.             snode.subst_string.rstart = std::distance( subst.begin(), icur++ );
  2480.             snode.subst_string.rlength = 1;
  2481.             break;
  2482.         case NO_TOKEN:
  2483.         default:
  2484.             ++snode.subst_string.rlength;
  2485.             ++icur;
  2486.             break;
  2487.         }
  2488.     }
  2489.     assert( detail::subst_node::SUBST_STRING == snode.stype );
  2490.     if( snode.subst_string.rlength )
  2491.         subst_list.push_back( snode );
  2492. }
  2493. template< typename CH >
  2494. REGEXPR_H_INLINE void reset_intrinsic_charsets( CH )
  2495. {
  2496.     detail::intrinsic_charsets<CH>::reset();
  2497. }
  2498. typedef ::regex::detail::select
  2499. <
  2500.     REGEX_FOLD_INSTANTIATIONS &&
  2501.         detail::is_convertible<char const *,std::string::const_iterator>::value,
  2502.     std::string::const_iterator,
  2503.     char const *
  2504. >::type lpcstr_t;
  2505. typedef ::regex::detail::select
  2506. <
  2507.     REGEX_FOLD_INSTANTIATIONS &&
  2508.         detail::is_convertible<wchar_t const *,std::wstring::const_iterator>::value,
  2509.     std::wstring::const_iterator,
  2510.     wchar_t const *
  2511. >::type lpcwstr_t;
  2512. namespace
  2513. {
  2514. // Used to fake the compiler into implicitly instantiating the templates we need
  2515. bool g_regex_false;
  2516. template< typename CI, typename SY >
  2517. struct rpattern_instantiator
  2518. {
  2519.     typedef ::regex::basic_rpattern<CI,SY>      rpattern_type;
  2520.     typedef ::regex::basic_match_results<CI>    results_type;
  2521.     typedef typename rpattern_type::char_type   char_type;
  2522.     typedef typename rpattern_type::string_type string_type;
  2523.     rpattern_instantiator()
  2524.     {
  2525.         if( g_regex_false )
  2526.         {
  2527.             string_type const str;
  2528.             CI ci = CI();
  2529.             results_type res;
  2530.             rpattern_type pat;
  2531.             rpattern_type pat1( str );
  2532.             rpattern_type pat2( str, str );
  2533.             rpattern_type pat3( pat );
  2534.             pat3 = pat;
  2535.             pat.init( str );
  2536.             pat.init( str, str );
  2537.             pat.set_substitution( str );
  2538.             //pat.match( &*ci, res ); // could cause a static assert
  2539.             pat.match( ci, ci, res );
  2540.             //pat.count( &*ci ); // could cause a static assert
  2541.             pat.count( ci, ci );
  2542.             reset_intrinsic_charsets( char_type() );
  2543.             // These force VC6 to create COMDATs for set_substitution and the two init methods
  2544.             void (*preset)( char_type ) = & reset_intrinsic_charsets;
  2545.             (*preset)( char_type() );
  2546.             void (rpattern_type::*psetsub)( string_type const & ) = & rpattern_type::set_substitution;
  2547.             (pat.*psetsub)( str );
  2548.             void (rpattern_type::*pinit1)( string_type const &, REGEX_FLAGS, REGEX_MODE ) = & rpattern_type::init;
  2549.             (pat.*pinit1)( str, NOFLAGS, MODE_DEFAULT );
  2550.             void (rpattern_type::*pinit2)( string_type const &, string_type const &, REGEX_FLAGS, REGEX_MODE ) = & rpattern_type::init;
  2551.             (pat.*pinit2)( str, str, NOFLAGS, MODE_DEFAULT );
  2552.         }
  2553.     }
  2554. };
  2555. // Here is a rudimentary typelist facility to allow the REGEX_TO_INSTANTIATE
  2556. // list to recursively generate the instantiations we are interested in.
  2557. struct null_type;
  2558. template< typename H, typename T >
  2559. struct cons
  2560. {
  2561.     typedef H head;
  2562.     typedef T tail;
  2563. };
  2564. template< typename T1=null_type, typename T2=null_type, typename T3=null_type, typename T4=null_type,
  2565.           typename T5=null_type, typename T6=null_type, typename T7=null_type, typename T8=null_type >
  2566. struct typelist
  2567. {
  2568.     typedef cons< T1, typename typelist<T2,T3,T4,T5,T6,T7,T8,null_type>::type > type;
  2569. };
  2570. template<>
  2571. struct typelist<null_type,null_type,null_type,null_type,null_type,null_type,null_type,null_type>
  2572. {
  2573.     typedef null_type type;
  2574. };
  2575. // The recursive_instantiator uses typelists and the rpattern_instantiator
  2576. // to generate instantiations for all the types in the typelist.
  2577. template< typename TYPELIST >
  2578. struct recursive_instantiator
  2579. {
  2580.     // The inner struct is needed as a work-around for the lack
  2581.     // of partial template specialization.
  2582.     template< typename SY >
  2583.     struct inner
  2584.     {
  2585.         inner()
  2586.         {
  2587.             if( g_regex_false )
  2588.             {
  2589.                 typedef typename TYPELIST::head CI;
  2590.                 typedef typename ::std::iterator_traits<CI>::value_type char_type;
  2591.                 typedef typename SY::template rebind<char_type>::other syntax_type;
  2592.                 rpattern_instantiator<CI,syntax_type> dummy1;
  2593.                 ( void ) dummy1;
  2594.                 typedef typename TYPELIST::tail TYPELIST2;
  2595.                 typedef recursive_instantiator< TYPELIST2 > other;
  2596.                 typedef typename other::template inner<SY> other_inner;
  2597.                 other_inner dummy2;
  2598.                 ( void ) dummy2;
  2599.             }
  2600.         }
  2601.     };
  2602. };
  2603. template<>
  2604. struct recursive_instantiator< null_type >
  2605. {
  2606.     template< typename SY >
  2607.     struct inner
  2608.     {
  2609.     };
  2610. };
  2611. // Here is a list of types to instantiate.
  2612. #ifndef REGEX_TO_INSTANTIATE
  2613. # ifdef REGEX_WIDE_AND_NARROW
  2614. #  define REGEX_TO_INSTANTIATE std::string::const_iterator,  
  2615.                                std::wstring::const_iterator, 
  2616.                                lpcstr_t,                     
  2617.                                lpcwstr_t
  2618. # else
  2619. #  define REGEX_TO_INSTANTIATE restring::const_iterator,     
  2620.                                lpctstr_t
  2621. # endif
  2622. #endif
  2623. // Create the perl instantiations
  2624. #ifndef REGEX_NO_PERL
  2625. recursive_instantiator<typelist<REGEX_TO_INSTANTIATE>::type>::inner<perl_syntax<char> > _dummy1;
  2626. #endif
  2627. // Create the posix instantiations
  2628. #ifdef REGEX_POSIX
  2629. recursive_instantiator<typelist<REGEX_TO_INSTANTIATE>::type>::inner<posix_syntax<char> > _dummy2;
  2630. #endif
  2631. } // unnamed namespace
  2632. } // namespace regex