]> git.lyx.org Git - lyx.git/blob - boost/boost/regex/v4/perl_matcher_common.hpp
Update to latest from boost 1.34 cvs release branch
[lyx.git] / boost / boost / regex / v4 / perl_matcher_common.hpp
1 /*
2  *
3  * Copyright (c) 2002
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the 
7  * Boost Software License, Version 1.0. (See accompanying file 
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE         perl_matcher_common.cpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Definitions of perl_matcher member functions that are 
17   *                common to both the recursive and non-recursive versions.
18   */
19
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP
21 #define BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP
22
23 #ifdef BOOST_HAS_ABI_HEADERS
24 #  include BOOST_ABI_PREFIX
25 #endif
26
27 #ifdef __BORLANDC__
28 #  pragma option push -w-8008 -w-8066
29 #endif
30
31 namespace boost{
32 namespace re_detail{
33
34 template <class BidiIterator, class Allocator, class traits>
35 void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_regex<char_type, traits>& e, match_flag_type f)
36
37    typedef typename regex_iterator_traits<BidiIterator>::iterator_category category;
38    typedef typename basic_regex<char_type, traits>::flag_type expression_flag_type;
39    
40    if(e.empty())
41    {
42       // precondition failure: e is not a valid regex.
43       std::invalid_argument ex("Invalid regular expression object");
44       boost::throw_exception(ex);
45    }
46    pstate = 0;
47    m_match_flags = f;
48    estimate_max_state_count(static_cast<category*>(0));
49    expression_flag_type re_f = re.flags();
50    icase = re_f & regex_constants::icase;
51    if(!(m_match_flags & (match_perl|match_posix)))
52    {
53       if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0)
54          m_match_flags |= match_perl;
55       else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
56          m_match_flags |= match_perl;
57       else
58          m_match_flags |= match_posix;
59    }
60    if(m_match_flags & match_posix)
61    {
62       m_temp_match.reset(new match_results<BidiIterator, Allocator>());
63       m_presult = m_temp_match.get();
64    }
65    else
66       m_presult = &m_result;
67 #ifdef BOOST_REGEX_NON_RECURSIVE
68    m_stack_base = 0;
69    m_backup_state = 0;
70 #endif
71    // find the value to use for matching word boundaries:
72    m_word_mask = re.get_data().m_word_mask; 
73    // find bitmask to use for matching '.':
74    match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? re_detail::test_not_newline : re_detail::test_newline);
75 }
76
77 template <class BidiIterator, class Allocator, class traits>
78 void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*)
79 {
80    static const difference_type k = 100000;
81    difference_type dist = boost::re_detail::distance(base, last);
82    traits_size_type states = static_cast<traits_size_type>(re.size());
83    states *= states;
84    difference_type lim = ((std::numeric_limits<difference_type>::max)() - k) / states;
85    if(dist >= lim)
86       max_state_count = (std::numeric_limits<difference_type>::max)();
87    else
88       max_state_count = k + states * dist;
89 }
90
91 template <class BidiIterator, class Allocator, class traits>
92 inline void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*)
93 {
94    // we don't know how long the sequence is:
95    max_state_count = BOOST_REGEX_MAX_STATE_COUNT;
96 }
97
98 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
99 template <class BidiIterator, class Allocator, class traits>
100 inline bool perl_matcher<BidiIterator, Allocator, traits>::protected_call(
101    protected_proc_type proc)
102 {
103    ::boost::re_detail::concrete_protected_call
104       <perl_matcher<BidiIterator, Allocator, traits> >
105       obj(this, proc);
106    return obj.execute();
107
108 }
109 #endif
110
111 template <class BidiIterator, class Allocator, class traits>
112 inline bool perl_matcher<BidiIterator, Allocator, traits>::match()
113 {
114 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
115    return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::match_imp);
116 #else
117    return match_imp();
118 #endif
119 }
120
121 template <class BidiIterator, class Allocator, class traits>
122 bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
123 {
124    // initialise our stack if we are non-recursive:
125 #ifdef BOOST_REGEX_NON_RECURSIVE
126    save_state_init init(&m_stack_base, &m_backup_state);
127    used_block_count = BOOST_REGEX_MAX_BLOCKS;
128 #if !defined(BOOST_NO_EXCEPTIONS)
129    try{
130 #endif
131 #endif
132
133    // reset our state machine:
134    position = base;
135    search_base = base;
136    state_count = 0;
137    m_match_flags |= regex_constants::match_all;
138    m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last);
139    m_presult->set_base(base);
140    if(m_match_flags & match_posix)
141       m_result = *m_presult;
142    verify_options(re.flags(), m_match_flags);
143    if(0 == match_prefix())
144       return false;
145    return m_result[0].second == last;
146
147 #if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS)
148    }
149    catch(...)
150    {
151       // unwind all pushed states, apart from anything else this
152       // ensures that all the states are correctly destructed
153       // not just the memory freed.
154       while(unwind(true)){}
155       throw;
156    }
157 #endif
158 }
159
160 template <class BidiIterator, class Allocator, class traits>
161 inline bool perl_matcher<BidiIterator, Allocator, traits>::find()
162 {
163 #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD
164    return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::find_imp);
165 #else
166    return find_imp();
167 #endif
168 }
169
170 template <class BidiIterator, class Allocator, class traits>
171 bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
172 {
173    static matcher_proc_type const s_find_vtable[7] = 
174    {
175       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_any,
176       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_word,
177       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_line,
178       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf,
179       &perl_matcher<BidiIterator, Allocator, traits>::match_prefix,
180       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
181       &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
182    };
183
184    // initialise our stack if we are non-recursive:
185 #ifdef BOOST_REGEX_NON_RECURSIVE
186    save_state_init init(&m_stack_base, &m_backup_state);
187    used_block_count = BOOST_REGEX_MAX_BLOCKS;
188 #if !defined(BOOST_NO_EXCEPTIONS)
189    try{
190 #endif
191 #endif
192
193    state_count = 0;
194    if((m_match_flags & regex_constants::match_init) == 0)
195    {
196       // reset our state machine:
197       search_base = position = base;
198       pstate = re.get_first_state();
199       m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), base, last);
200       m_presult->set_base(base);
201       m_match_flags |= regex_constants::match_init;
202    }
203    else
204    {
205       // start again:
206       search_base = position = m_result[0].second;
207       // If last match was null and match_not_null was not set then increment
208       // our start position, otherwise we go into an infinite loop:
209       if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0))
210       {
211          if(position == last)
212             return false;
213          else 
214             ++position;
215       }
216       // reset $` start:
217       m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last);
218       //if((base != search_base) && (base == backstop))
219       //   m_match_flags |= match_prev_avail;
220    }
221    if(m_match_flags & match_posix)
222    {
223       m_result.set_size(re.mark_count(), base, last);
224       m_result.set_base(base);
225    }
226
227    verify_options(re.flags(), m_match_flags);
228    // find out what kind of expression we have:
229    unsigned type = (m_match_flags & match_continuous) ? 
230       static_cast<unsigned int>(regbase::restart_continue) 
231          : static_cast<unsigned int>(re.get_restart_type());
232
233    // call the appropriate search routine:
234    matcher_proc_type proc = s_find_vtable[type];
235    return (this->*proc)();
236
237 #if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS)
238    }
239    catch(...)
240    {
241       // unwind all pushed states, apart from anything else this
242       // ensures that all the states are correctly destructed
243       // not just the memory freed.
244       while(unwind(true)){}
245       throw;
246    }
247 #endif
248 }
249
250 template <class BidiIterator, class Allocator, class traits>
251 bool perl_matcher<BidiIterator, Allocator, traits>::match_prefix()
252 {
253    m_has_partial_match = false;
254    m_has_found_match = false;
255    pstate = re.get_first_state();
256    m_presult->set_first(position);
257    restart = position;
258    match_all_states();
259    if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial))
260    {
261       m_has_found_match = true;
262       m_presult->set_second(last, 0, false);
263       position = last;
264    }
265 #ifdef BOOST_REGEX_MATCH_EXTRA
266    if(m_has_found_match && (match_extra & m_match_flags))
267    {
268       //
269       // we have a match, reverse the capture information:
270       //
271       for(unsigned i = 0; i < m_presult->size(); ++i)
272       {
273          typename sub_match<BidiIterator>::capture_sequence_type & seq = ((*m_presult)[i]).get_captures();
274          std::reverse(seq.begin(), seq.end());
275       }
276    }
277 #endif
278    if(!m_has_found_match)
279       position = restart; // reset search postion
280    return m_has_found_match;
281 }
282
283 template <class BidiIterator, class Allocator, class traits>
284 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
285 {
286    int index = static_cast<const re_brace*>(pstate)->index;
287    if(index > 0)
288    {
289       if((m_match_flags & match_nosubs) == 0)
290          m_presult->set_second(position, index);
291    }
292    else if((index < 0) && (index != -4))
293    {
294       // matched forward lookahead:
295       pstate = 0;
296       return true;
297    }
298    pstate = pstate->next.p;
299    return true;
300 }
301
302 template <class BidiIterator, class Allocator, class traits>
303 bool perl_matcher<BidiIterator, Allocator, traits>::match_literal()
304 {
305    unsigned int len = static_cast<const re_literal*>(pstate)->length;
306    const char_type* what = reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
307    //
308    // compare string with what we stored in
309    // our records:
310    for(unsigned int i = 0; i < len; ++i, ++position)
311    {
312       if((position == last) || (traits_inst.translate(*position, icase) != what[i]))
313          return false;
314    }
315    pstate = pstate->next.p;
316    return true;
317 }
318
319 template <class BidiIterator, class Allocator, class traits>
320 bool perl_matcher<BidiIterator, Allocator, traits>::match_start_line()
321 {
322    if(position == backstop)
323    {
324       if((m_match_flags & match_prev_avail) == 0)
325       {
326          if((m_match_flags & match_not_bol) == 0)
327          {
328             pstate = pstate->next.p;
329             return true;
330          }
331          return false;
332       }
333    }
334    else if(m_match_flags & match_single_line)
335       return false;
336
337    // check the previous value character:
338    BidiIterator t(position);
339    --t;
340    if(position != last)
341    {
342       if(is_separator(*t) && !((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) )
343       {
344          pstate = pstate->next.p;
345          return true;
346       }
347    }
348    else if(is_separator(*t))
349    {
350       pstate = pstate->next.p;
351       return true;
352    }
353    return false;
354 }
355
356 template <class BidiIterator, class Allocator, class traits>
357 bool perl_matcher<BidiIterator, Allocator, traits>::match_end_line()
358 {
359    if(position != last)
360    {
361       if(m_match_flags & match_single_line)
362          return false;
363       // we're not yet at the end so *first is always valid:
364       if(is_separator(*position))
365       {
366          if((position != backstop) || (m_match_flags & match_prev_avail))
367          {
368             // check that we're not in the middle of \r\n sequence
369             BidiIterator t(position);
370             --t;
371             if((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n')))
372             {
373                return false;
374             }
375          }
376          pstate = pstate->next.p;
377          return true;
378       }
379    }
380    else if((m_match_flags & match_not_eol) == 0)
381    {
382       pstate = pstate->next.p;
383       return true;
384    }
385    return false;
386 }
387
388 template <class BidiIterator, class Allocator, class traits>
389 bool perl_matcher<BidiIterator, Allocator, traits>::match_wild()
390 {
391    if(position == last) 
392       return false;
393    if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0))
394       return false;
395    if((*position == char_type(0)) && (m_match_flags & match_not_dot_null))
396       return false;
397    pstate = pstate->next.p;
398    ++position;
399    return true;
400 }
401
402 template <class BidiIterator, class Allocator, class traits>
403 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
404 {
405    if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
406       return false;
407    if((m_match_flags & match_all) && (position != last))
408       return false;
409    if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
410       return false;
411    m_presult->set_second(position);
412    pstate = 0;
413    m_has_found_match = true;
414    if((m_match_flags & match_posix) == match_posix)
415    {
416       m_result.maybe_assign(*m_presult);
417       if((m_match_flags & match_any) == 0)
418          return false;
419    }
420 #ifdef BOOST_REGEX_MATCH_EXTRA
421    if(match_extra & m_match_flags)
422    {
423       for(unsigned i = 0; i < m_presult->size(); ++i)
424          if((*m_presult)[i].matched)
425             ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
426    }
427 #endif
428    return true;
429 }
430
431 template <class BidiIterator, class Allocator, class traits>
432 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary()
433 {
434    bool b; // indcates whether next character is a word character
435    if(position != last)
436    {
437       // prev and this character must be opposites:
438    #if defined(BOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
439       b = traits::isctype(*position, m_word_mask);
440    #else
441       b = traits_inst.isctype(*position, m_word_mask);
442    #endif
443    }
444    else
445    {
446       b = (m_match_flags & match_not_eow) ? true : false;
447    }
448    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
449    {
450       if(m_match_flags & match_not_bow)
451          b ^= true;
452       else
453          b ^= false;
454    }
455    else
456    {
457       --position;
458       b ^= traits_inst.isctype(*position, m_word_mask);
459       ++position;
460    }
461    if(b)
462    {
463       pstate = pstate->next.p;
464       return true;
465    }
466    return false; // no match if we get to here...
467 }
468
469 template <class BidiIterator, class Allocator, class traits>
470 bool perl_matcher<BidiIterator, Allocator, traits>::match_within_word()
471 {
472    if(position == last)
473       return false;
474    // both prev and this character must be m_word_mask:
475    if(traits_inst.isctype(*position, m_word_mask))
476    {
477       bool b;
478       if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) 
479          return false;
480       else
481       {
482          --position;
483          b = traits_inst.isctype(*position, m_word_mask);
484          ++position;
485       }
486       if(b)
487       {
488          pstate = pstate->next.p;
489          return true;
490       }
491    }
492    return false;
493 }
494
495 template <class BidiIterator, class Allocator, class traits>
496 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_start()
497 {
498    if(position == last)
499       return false; // can't be starting a word if we're already at the end of input
500    if(!traits_inst.isctype(*position, m_word_mask))
501       return false; // next character isn't a word character
502    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
503    {
504       if(m_match_flags & match_not_bow)
505          return false; // no previous input
506    }
507    else
508    {
509       // otherwise inside buffer:
510       BidiIterator t(position);
511       --t;
512       if(traits_inst.isctype(*t, m_word_mask))
513          return false; // previous character not non-word
514    }
515    // OK we have a match:
516    pstate = pstate->next.p;
517    return true;
518 }
519
520 template <class BidiIterator, class Allocator, class traits>
521 bool perl_matcher<BidiIterator, Allocator, traits>::match_word_end()
522 {
523    if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
524       return false;  // start of buffer can't be end of word
525    BidiIterator t(position);
526    --t;
527    if(traits_inst.isctype(*t, m_word_mask) == false)
528       return false;  // previous character wasn't a word character
529
530    if(position == last)
531    {
532       if(m_match_flags & match_not_eow)
533          return false; // end of buffer but not end of word
534    }
535    else
536    {
537       // otherwise inside buffer:
538       if(traits_inst.isctype(*position, m_word_mask))
539          return false; // next character is a word character
540    }
541    pstate = pstate->next.p;
542    return true;      // if we fall through to here then we've succeeded
543 }
544
545 template <class BidiIterator, class Allocator, class traits>
546 bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start()
547 {
548    if((position != backstop) || (m_match_flags & match_not_bob))
549       return false;
550    // OK match:
551    pstate = pstate->next.p;
552    return true;
553 }
554
555 template <class BidiIterator, class Allocator, class traits>
556 bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end()
557 {
558    if((position != last) || (m_match_flags & match_not_eob))
559       return false;
560    // OK match:
561    pstate = pstate->next.p;
562    return true;
563 }
564
565 template <class BidiIterator, class Allocator, class traits>
566 bool perl_matcher<BidiIterator, Allocator, traits>::match_backref()
567 {
568    //
569    // Compare with what we previously matched.
570    // Note that this succeeds if the backref did not partisipate
571    // in the match, this is in line with ECMAScript, but not Perl
572    // or PCRE.
573    //
574    BidiIterator i = (*m_presult)[static_cast<const re_brace*>(pstate)->index].first;
575    BidiIterator j = (*m_presult)[static_cast<const re_brace*>(pstate)->index].second;
576    while(i != j)
577    {
578       if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase)))
579          return false;
580       ++i;
581       ++position;
582    }
583    pstate = pstate->next.p;
584    return true;
585 }
586
587 template <class BidiIterator, class Allocator, class traits>
588 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
589 {
590    typedef typename traits::char_class_type char_class_type;
591    // let the traits class do the work:
592    if(position == last)
593       return false;
594    BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase);
595    if(t != position)
596    {
597       pstate = pstate->next.p;
598       position = t;
599       return true;
600    }
601    return false;
602 }
603
604 template <class BidiIterator, class Allocator, class traits>
605 bool perl_matcher<BidiIterator, Allocator, traits>::match_set()
606 {
607    if(position == last)
608       return false;
609    if(static_cast<const re_set*>(pstate)->_map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
610    {
611       pstate = pstate->next.p;
612       ++position;
613       return true;
614    }
615    return false;
616 }
617
618 template <class BidiIterator, class Allocator, class traits>
619 bool perl_matcher<BidiIterator, Allocator, traits>::match_jump()
620 {
621    pstate = static_cast<const re_jump*>(pstate)->alt.p;
622    return true;
623 }
624
625 template <class BidiIterator, class Allocator, class traits>
626 bool perl_matcher<BidiIterator, Allocator, traits>::match_combining()
627 {
628    if(position == last)
629       return false;
630    if(is_combining(traits_inst.translate(*position, icase)))
631       return false;
632    ++position;
633    while((position != last) && is_combining(traits_inst.translate(*position, icase)))
634       ++position;
635    pstate = pstate->next.p;
636    return true;
637 }
638
639 template <class BidiIterator, class Allocator, class traits>
640 bool perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end()
641 {
642    if(m_match_flags & match_not_eob)
643       return false;
644    BidiIterator p(position);
645    while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p;
646    if(p != last)
647       return false;
648    pstate = pstate->next.p;
649    return true;
650 }
651
652 template <class BidiIterator, class Allocator, class traits>
653 bool perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue()
654 {
655    if(position == search_base)
656    {
657       pstate = pstate->next.p;
658       return true;
659    }
660    return false;
661 }
662
663 template <class BidiIterator, class Allocator, class traits>
664 bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep()
665 {
666 #ifdef BOOST_MSVC
667 #pragma warning(push)
668 #pragma warning(disable:4127)
669 #endif
670    if( ::boost::is_random_access_iterator<BidiIterator>::value)
671    {
672       std::ptrdiff_t maxlen = ::boost::re_detail::distance(backstop, position);
673       if(maxlen < static_cast<const re_brace*>(pstate)->index)
674          return false;
675       std::advance(position, -static_cast<const re_brace*>(pstate)->index);
676    }
677    else
678    {
679       int c = static_cast<const re_brace*>(pstate)->index;
680       while(c--)
681       {
682          if(position == backstop)
683             return false;
684          --position;
685       }
686    }
687    pstate = pstate->next.p;
688    return true;
689 #ifdef BOOST_MSVC
690 #pragma warning(pop)
691 #endif
692 }
693
694 template <class BidiIterator, class Allocator, class traits>
695 inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
696 {
697    // return true if marked sub-expression N has been matched:
698    bool result = (*m_presult)[static_cast<const re_brace*>(pstate)->index].matched;
699    pstate = pstate->next.p;
700    return result;
701 }
702
703 template <class BidiIterator, class Allocator, class traits>
704 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
705 {
706    // change our case sensitivity:
707    this->icase = static_cast<const re_case*>(pstate)->icase;
708    pstate = pstate->next.p;
709    return true;
710 }
711
712
713 template <class BidiIterator, class Allocator, class traits>
714 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
715 {
716 #ifdef BOOST_MSVC
717 #pragma warning(push)
718 #pragma warning(disable:4127)
719 #endif
720    const unsigned char* _map = re.get_map();
721    while(true)
722    {
723       // skip everything we can't match:
724       while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) )
725          ++position;
726       if(position == last)
727       {
728          // run out of characters, try a null match if possible:
729          if(re.can_be_null())
730             return match_prefix();
731          break;
732       }
733       // now try and obtain a match:
734       if(match_prefix())
735          return true;
736       if(position == last)
737          return false;
738       ++position;
739    }
740    return false;
741 #ifdef BOOST_MSVC
742 #pragma warning(pop)
743 #endif
744 }
745
746 template <class BidiIterator, class Allocator, class traits>
747 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_word()
748 {
749 #ifdef BOOST_MSVC
750 #pragma warning(push)
751 #pragma warning(disable:4127)
752 #endif
753    // do search optimised for word starts:
754    const unsigned char* _map = re.get_map();
755    if((m_match_flags & match_prev_avail) || (position != base))
756       --position;
757    else if(match_prefix())
758       return true;
759    do
760    {
761       while((position != last) && traits_inst.isctype(*position, m_word_mask))
762          ++position;
763       while((position != last) && !traits_inst.isctype(*position, m_word_mask))
764          ++position;
765       if(position == last)
766          break;
767
768       if(can_start(*position, _map, (unsigned char)mask_any) )
769       {
770          if(match_prefix())
771             return true;
772       }
773       if(position == last)
774          break;
775    } while(true);
776    return false;
777 #ifdef BOOST_MSVC
778 #pragma warning(pop)
779 #endif
780 }
781
782 template <class BidiIterator, class Allocator, class traits>
783 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_line()
784 {
785    // do search optimised for line starts:
786    const unsigned char* _map = re.get_map();
787    if(match_prefix())
788       return true;
789    while(position != last)
790    {
791       while((position != last) && !is_separator(*position))
792          ++position;
793       if(position == last)
794          return false;
795       ++position;
796       if(position == last)
797       {
798          if(re.can_be_null() && match_prefix())
799             return true;
800          return false;
801       }
802
803       if( can_start(*position, _map, (unsigned char)mask_any) )
804       {
805          if(match_prefix())
806             return true;
807       }
808       if(position == last)
809          return false;
810       //++position;
811    }
812    return false;
813 }
814
815 template <class BidiIterator, class Allocator, class traits>
816 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf()
817 {
818    if((position == base) && ((m_match_flags & match_not_bob) == 0))
819       return match_prefix();
820    return false;
821 }
822
823 template <class BidiIterator, class Allocator, class traits>
824 bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit()
825 {
826 #if 0
827    if(position == last)
828       return false; // can't possibly match if we're at the end already
829
830    unsigned type = (m_match_flags & match_continuous) ? 
831       static_cast<unsigned int>(regbase::restart_continue) 
832          : static_cast<unsigned int>(re.get_restart_type());
833
834    const kmp_info<char_type>* info = access::get_kmp(re);
835    int len = info->len;
836    const char_type* x = info->pstr;
837    int j = 0; 
838    while (position != last) 
839    {
840       while((j > -1) && (x[j] != traits_inst.translate(*position, icase))) 
841          j = info->kmp_next[j];
842       ++position;
843       ++j;
844       if(j >= len) 
845       {
846          if(type == regbase::restart_fixed_lit)
847          {
848             std::advance(position, -j);
849             restart = position;
850             std::advance(restart, len);
851             m_result.set_first(position);
852             m_result.set_second(restart);
853             position = restart;
854             return true;
855          }
856          else
857          {
858             restart = position;
859             std::advance(position, -j);
860             if(match_prefix())
861                return true;
862             else
863             {
864                for(int k = 0; (restart != position) && (k < j); ++k, --restart)
865                      {} // dwa 10/20/2000 - warning suppression for MWCW
866                if(restart != last)
867                   ++restart;
868                position = restart;
869                j = 0;  //we could do better than this...
870             }
871          }
872       }
873    }
874    if((m_match_flags & match_partial) && (position == last) && j)
875    {
876       // we need to check for a partial match:
877       restart = position;
878       std::advance(position, -j);
879       return match_prefix();
880    }
881 #endif
882    return false;
883 }
884
885 } // namespace re_detail
886
887 } // namespace boost
888
889 #ifdef __BORLANDC__
890 #  pragma option pop
891 #endif
892 #ifdef BOOST_HAS_ABI_HEADERS
893 #  include BOOST_ABI_SUFFIX
894 #endif
895
896 #endif
897