diff --git a/include/boost/regex/config.hpp b/include/boost/regex/config.hpp index d016c106..dd0b6eec 100644 --- a/include/boost/regex/config.hpp +++ b/include/boost/regex/config.hpp @@ -319,7 +319,7 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page(); ****************************************************************************/ #if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE) -# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) +# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)) # define BOOST_REGEX_RECURSIVE # else # define BOOST_REGEX_NON_RECURSIVE diff --git a/include/boost/regex/icu.hpp b/include/boost/regex/icu.hpp index 9910baea..b6de6dcd 100644 --- a/include/boost/regex/icu.hpp +++ b/include/boost/regex/icu.hpp @@ -728,7 +728,7 @@ OutputIterator do_regex_replace(OutputIterator out, if(i == j) { if(!(flags & regex_constants::format_no_copy)) - out = std::copy(in.first, in.second, out); + out = re_detail::copy(in.first, in.second, out); } else { @@ -736,7 +736,7 @@ OutputIterator do_regex_replace(OutputIterator out, while(i != j) { if(!(flags & regex_constants::format_no_copy)) - out = std::copy(i->prefix().first, i->prefix().second, out); + out = re_detail::copy(i->prefix().first, i->prefix().second, out); out = ::boost::re_detail::regex_format_imp(out, *i, &*f.begin(), &*f.end(), flags, e.get_traits()); last_m = (*i)[0].second; if(flags & regex_constants::format_first_only) @@ -744,7 +744,7 @@ OutputIterator do_regex_replace(OutputIterator out, ++i; } if(!(flags & regex_constants::format_no_copy)) - out = std::copy(last_m, in.second, out); + out = re_detail::copy(last_m, in.second, out); } return out; } diff --git a/include/boost/regex/v4/basic_regex_creator.hpp b/include/boost/regex/v4/basic_regex_creator.hpp index c37ee5f7..f5e3d0f0 100644 --- a/include/boost/regex/v4/basic_regex_creator.hpp +++ b/include/boost/regex/v4/basic_regex_creator.hpp @@ -435,10 +435,10 @@ re_syntax_base* basic_regex_creator::append_set( return 0; } charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) ); - std::copy(s1.begin(), s1.end(), p); + re_detail::copy(s1.begin(), s1.end(), p); p[s1.size()] = charT(0); p += s1.size() + 1; - std::copy(s2.begin(), s2.end(), p); + re_detail::copy(s2.begin(), s2.end(), p); p[s2.size()] = charT(0); } // @@ -459,7 +459,7 @@ re_syntax_base* basic_regex_creator::append_set( if(s.empty()) return 0; // invalid or unsupported equivalence class charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) ); - std::copy(s.begin(), s.end(), p); + re_detail::copy(s.begin(), s.end(), p); p[s.size()] = charT(0); ++first; } @@ -620,7 +620,7 @@ void basic_regex_creator::finalize(const charT* p1, const charT* m_pdata->m_expression_len = len; charT* ps = static_cast(m_pdata->m_data.extend(sizeof(charT) * (1 + (p2 - p1)))); m_pdata->m_expression = ps; - std::copy(p1, p2, ps); + re_detail::copy(p1, p2, ps); ps[p2 - p1] = 0; // fill in our other data... // successful parsing implies a zero status: diff --git a/include/boost/regex/v4/basic_regex_parser.hpp b/include/boost/regex/v4/basic_regex_parser.hpp index e06809fb..6684dc51 100644 --- a/include/boost/regex/v4/basic_regex_parser.hpp +++ b/include/boost/regex/v4/basic_regex_parser.hpp @@ -1422,7 +1422,15 @@ charT basic_regex_parser::unescape_character() // an octal escape sequence, the first character must be a zero // followed by up to 3 octal digits: std::ptrdiff_t len = (std::min)(::boost::re_detail::distance(m_position, m_end), static_cast(4)); - int val = this->m_traits.toi(m_position, m_position + len, 8); + const charT* bp = m_position; + int val = this->m_traits.toi(bp, bp + 1, 8); + if(val != 0) + { + // Oops not an octal escape after all: + fail(regex_constants::error_escape, m_position - m_base); + return result; + } + val = this->m_traits.toi(m_position, m_position + len, 8); if(val < 0) { fail(regex_constants::error_escape, m_position - m_base); @@ -1477,19 +1485,20 @@ template bool basic_regex_parser::parse_backref() { BOOST_ASSERT(m_position != m_end); - int i = this->m_traits.toi(m_position, m_position + 1, 10); - if((i > 0) && (this->m_backrefs & (1u << (i-1)))) - { - re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); - pb->index = i; - } - else if(i == 0) + const charT* pc = m_position; + int i = this->m_traits.toi(pc, pc + 1, 10); + if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs))) { // not a backref at all but an octal escape sequence: - --m_position; charT c = unescape_character(); this->append_literal(c); } + else if((i > 0) && (this->m_backrefs & (1u << (i-1)))) + { + m_position = pc; + re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = i; + } else { fail(regex_constants::error_backref, m_position - m_end); diff --git a/include/boost/regex/v4/match_results.hpp b/include/boost/regex/v4/match_results.hpp index 7886dce4..72538fc0 100644 --- a/include/boost/regex/v4/match_results.hpp +++ b/include/boost/regex/v4/match_results.hpp @@ -300,29 +300,73 @@ void BOOST_REGEX_CALL match_results::maybe_assign(const const_iterator p1, p2; p1 = begin(); p2 = m.begin(); - BidiIterator base = (*this)[-1].first; - std::size_t len1 = 0; - std::size_t len2 = 0; - std::size_t base1 = 0; - std::size_t base2 = 0; + // + // Distances are measured from the start of *this* match, unless this isn't + // a valid match in which case we use the start of the whole sequence. Note that + // no subsequent match-candidate can ever be to the left of the first match found. + // This ensures that when we are using bidirectional iterators, that distances + // measured are as short as possible, and therefore as efficient as possible + // to compute. Finally note that we don't use the "matched" data member to test + // whether a sub-expression is a valid match, because partial matches set this + // to false for sub-expression 0. + // + BidiIterator end = this->suffix().second; + BidiIterator base = (p1->first == end) ? this->prefix().first : (*this)[0].first; + difference_type len1 = 0; + difference_type len2 = 0; + difference_type base1 = 0; + difference_type base2 = 0; std::size_t i; - for(i = 0; i < size(); ++i) + for(i = 0; i < size(); ++i, ++p1, ++p2) { // - // leftmost takes priority over longest: + // Leftmost takes priority over longest; handle special cases + // where distances need not be computed first (an optimisation + // for bidirectional iterators: ensure that we don't accidently + // compute the length of the whole sequence, as this can be really + // expensive). + // + if(p1->first == end) + { + if(p2->first != end) + { + // p2 must be better than p1, and no need to calculate + // actual distances: + base1 = 1; + base2 = 0; + break; + } + else + { + // *p1 and *p2 are either unmatched or match end-of sequence, + // either way no need to calculate distances: + if((p1->matched == false) && (p2->matched == true)) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + continue; + } + } + else if(p2->first == end) + { + // p1 better than p2, and no need to calculate distances: + return; + } base1 = ::boost::re_detail::distance(base, p1->first); base2 = ::boost::re_detail::distance(base, p2->first); + BOOST_ASSERT(base1 >= 0); + BOOST_ASSERT(base2 >= 0); if(base1 < base2) return; if(base2 < base1) break; len1 = ::boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second); len2 = ::boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second); + BOOST_ASSERT(len1 >= 0); + BOOST_ASSERT(len2 >= 0); if((len1 != len2) || ((p1->matched == false) && (p2->matched == true))) break; if((p1->matched == true) && (p2->matched == false)) return; - ++p1; - ++p2; } if(i == size()) return; diff --git a/include/boost/regex/v4/regex_format.hpp b/include/boost/regex/v4/regex_format.hpp index bf1ca9ac..f0e327f3 100644 --- a/include/boost/regex/v4/regex_format.hpp +++ b/include/boost/regex/v4/regex_format.hpp @@ -524,6 +524,9 @@ void basic_regex_formatter::put(const sub_match template class string_out_iterator +#ifndef BOOST_NO_STD_ITERATOR + : public std::iterator +#endif { S* out; public: @@ -537,11 +540,13 @@ public: return *this; } +#ifdef BOOST_NO_STD_ITERATOR typedef std::ptrdiff_t difference_type; typedef typename S::value_type value_type; typedef value_type* pointer; typedef value_type& reference; typedef std::output_iterator_tag iterator_category; +#endif }; template @@ -554,7 +559,7 @@ OutputIterator regex_format_imp(OutputIterator out, { if(flags & regex_constants::format_literal) { - return std::copy(p1, p2, out); + return re_detail::copy(p1, p2, out); } re_detail::basic_regex_formatter< diff --git a/include/boost/regex/v4/regex_replace.hpp b/include/boost/regex/v4/regex_replace.hpp index 2293906c..a852ffec 100644 --- a/include/boost/regex/v4/regex_replace.hpp +++ b/include/boost/regex/v4/regex_replace.hpp @@ -41,7 +41,7 @@ OutputIterator regex_replace(OutputIterator out, if(i == j) { if(!(flags & regex_constants::format_no_copy)) - out = std::copy(first, last, out); + out = re_detail::copy(first, last, out); } else { @@ -49,7 +49,7 @@ OutputIterator regex_replace(OutputIterator out, while(i != j) { if(!(flags & regex_constants::format_no_copy)) - out = std::copy(i->prefix().first, i->prefix().second, out); + out = re_detail::copy(i->prefix().first, i->prefix().second, out); out = i->format(out, fmt, flags, e); last_m = (*i)[0].second; if(flags & regex_constants::format_first_only) @@ -57,7 +57,7 @@ OutputIterator regex_replace(OutputIterator out, ++i; } if(!(flags & regex_constants::format_no_copy)) - out = std::copy(last_m, last, out); + out = re_detail::copy(last_m, last, out); } return out; } diff --git a/include/boost/regex/v4/regex_workaround.hpp b/include/boost/regex/v4/regex_workaround.hpp index 0f8b42c2..c8a2fa09 100644 --- a/include/boost/regex/v4/regex_workaround.hpp +++ b/include/boost/regex/v4/regex_workaround.hpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 1998-2004 + * Copyright (c) 1998-2005 * John Maddock * * Use, modification and distribution are subject to the @@ -43,6 +43,12 @@ # include #endif +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; using ::strcpy; using ::strcat; using ::strlen; +} +#endif + namespace boost{ namespace re_detail{ #ifdef BOOST_NO_STD_DISTANCE template @@ -112,4 +118,73 @@ inline void pointer_construct(T* p, const T& t) }} // namespaces #endif +/***************************************************************************** + * + * helper function copy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace re_detail{ +#if BOOST_WORKAROUND(BOOST_MSVC,>=1400) + // + // MSVC 8 will either emit warnings or else refuse to compile + // code that makes perfectly legitimate use of std::copy, when + // the OutputIterator type is a user-defined class (apparently all user + // defined iterators are "unsafe"). This code works around that: + // + template + inline OutputIterator copy( + InputIterator first, + InputIterator last, + OutputIterator dest + ) + { + return stdext::unchecked_copy(first, last, dest); + } + + // use safe versions of strcpy etc: + using ::strcpy_s; + using ::strcat_s; +#else + using std::copy; + + inline std::size_t strcpy_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + if(std::strlen(strSource)+1 > sizeInBytes) + return 1; + std::strcpy(strDestination, strSource); + return 0; + } + inline std::size_t strcat_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + if(std::strlen(strSource) + std::strlen(strDestination) + 1 > sizeInBytes) + return 1; + std::strcat(strDestination, strSource); + return 0; + } + +#endif + + inline void overflow_error_if_not_zero(std::size_t i) + { + if(i) + { + std::overflow_error e("String buffer too small"); + boost::throw_exception(e); + } + } + +}} // namespaces +#endif + #endif // include guard + diff --git a/src/cregex.cpp b/src/cregex.cpp index 1c99ba5f..ca134265 100644 --- a/src/cregex.cpp +++ b/src/cregex.cpp @@ -33,12 +33,6 @@ typedef boost::match_flag_type match_flag_type; #endif #include -#if defined(BOOST_NO_STDC_NAMESPACE) -namespace std{ - using ::sprintf; using ::strcpy; using ::strcat; -} -#endif - namespace boost{ #ifdef __BORLANDC__ @@ -342,17 +336,17 @@ void BuildFileList(std::list* pl, const char* files, bool recurse) { // go through sub directories: char buf[MAX_PATH]; - std::strcpy(buf, start.root()); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(buf, MAX_PATH, start.root())); if(*buf == 0) { - std::strcpy(buf, "."); - std::strcat(buf, directory_iterator::separator()); - std::strcat(buf, "*"); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(buf, MAX_PATH, ".")); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, directory_iterator::separator())); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, "*")); } else { - std::strcat(buf, directory_iterator::separator()); - std::strcat(buf, "*"); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, directory_iterator::separator())); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(buf, MAX_PATH, "*")); } directory_iterator dstart(buf); directory_iterator dend; @@ -365,7 +359,11 @@ void BuildFileList(std::list* pl, const char* files, bool recurse) while(dstart != dend) { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + (::sprintf_s)(buf, sizeof(buf), "%s%s%s", dstart.path(), directory_iterator::separator(), ptr); +#else (std::sprintf)(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr); +#endif BuildFileList(pl, buf, recurse); ++dstart; } diff --git a/src/fileiter.cpp b/src/fileiter.cpp index 2ae3fb1f..cbb46c01 100644 --- a/src/fileiter.cpp +++ b/src/fileiter.cpp @@ -23,11 +23,8 @@ #include #include #include -#ifdef BOOST_REGEX_V3 -#include -#else #include -#endif +#include #include #include @@ -395,34 +392,24 @@ file_iterator::file_iterator(const char* wild) BOOST_REGEX_NOEH_ASSERT(_root) _path = new char[MAX_PATH]; BOOST_REGEX_NOEH_ASSERT(_path) - std::strcpy(_root, wild); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild)); ptr = _root; while(*ptr)++ptr; while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr; - #if 0 - *ptr = 0; - std::strcpy(_path, _root); - if(*_path == 0) - std::strcpy(_path, "."); - std::strcat(_path, _fi_sep); - ptr = _path + std::strlen(_path); - #else if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) ) { _root[1]='\0'; - std::strcpy(_path, _root); - ptr = _path + std::strlen(_path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root)); } else { *ptr = 0; - std::strcpy(_path, _root); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root)); if(*_path == 0) - std::strcpy(_path, "."); - std::strcat(_path, _fi_sep); - ptr = _path + std::strlen(_path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, ".")); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep)); } - #endif + ptr = _path + std::strlen(_path); ref = new file_iterator_ref(); BOOST_REGEX_NOEH_ASSERT(ref) @@ -436,7 +423,7 @@ file_iterator::file_iterator(const char* wild) } else { - std::strcpy(ptr, ref->_data.cFileName); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, (MAX_PATH - (ptr - _path)), ref->_data.cFileName)); if(ref->_data.dwFileAttributes & _fi_dir) next(); } @@ -463,8 +450,8 @@ file_iterator::file_iterator(const file_iterator& other) BOOST_REGEX_NOEH_ASSERT(_root) _path = new char[MAX_PATH]; BOOST_REGEX_NOEH_ASSERT(_path) - std::strcpy(_root, other._root); - std::strcpy(_path, other._path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root)); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path)); ptr = _path + (other.ptr - other._path); ref = other.ref; #ifndef BOOST_NO_EXCEPTIONS @@ -481,8 +468,8 @@ file_iterator::file_iterator(const file_iterator& other) file_iterator& file_iterator::operator=(const file_iterator& other) { - std::strcpy(_root, other._root); - std::strcpy(_path, other._path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root)); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path)); ptr = _path + (other.ptr - other._path); if(--(ref->count) == 0) { @@ -536,7 +523,7 @@ void file_iterator::next() ptr = _path; } else - std::strcpy(ptr, ref->_data.cFileName); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName)); } } @@ -583,34 +570,26 @@ directory_iterator::directory_iterator(const char* wild) BOOST_REGEX_NOEH_ASSERT(_root) _path = new char[MAX_PATH]; BOOST_REGEX_NOEH_ASSERT(_path) - std::strcpy(_root, wild); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, wild)); ptr = _root; while(*ptr)++ptr; while((ptr > _root) && (*ptr != *_fi_sep) && (*ptr != *_fi_sep_alt))--ptr; - #if 0 - *ptr = 0; - std::strcpy(_path, _root); - if(*_path == 0) - std::strcpy(_path, "."); - std::strcat(_path, _fi_sep); - ptr = _path + std::strlen(_path); - #else + if((ptr == _root) && ( (*ptr== *_fi_sep) || (*ptr==*_fi_sep_alt) ) ) { _root[1]='\0'; - std::strcpy(_path, _root); - ptr = _path + std::strlen(_path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root)); } else { *ptr = 0; - std::strcpy(_path, _root); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, _root)); if(*_path == 0) - std::strcpy(_path, "."); - std::strcat(_path, _fi_sep); - ptr = _path + std::strlen(_path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, ".")); + re_detail::overflow_error_if_not_zero(re_detail::strcat_s(_path, MAX_PATH, _fi_sep)); } - #endif + ptr = _path + std::strlen(_path); + ref = new file_iterator_ref(); BOOST_REGEX_NOEH_ASSERT(ref) ref->count = 1; @@ -622,7 +601,7 @@ directory_iterator::directory_iterator(const char* wild) } else { - std::strcpy(ptr, ref->_data.cFileName); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName)); if(((ref->_data.dwFileAttributes & _fi_dir) == 0) || (std::strcmp(ref->_data.cFileName, ".") == 0) || (std::strcmp(ref->_data.cFileName, "..") == 0)) next(); } @@ -661,8 +640,8 @@ directory_iterator::directory_iterator(const directory_iterator& other) BOOST_REGEX_NOEH_ASSERT(_root) _path = new char[MAX_PATH]; BOOST_REGEX_NOEH_ASSERT(_path) - std::strcpy(_root, other._root); - std::strcpy(_path, other._path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root)); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path)); ptr = _path + (other.ptr - other._path); ref = other.ref; #ifndef BOOST_NO_EXCEPTIONS @@ -679,8 +658,8 @@ directory_iterator::directory_iterator(const directory_iterator& other) directory_iterator& directory_iterator::operator=(const directory_iterator& other) { - std::strcpy(_root, other._root); - std::strcpy(_path, other._path); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_root, MAX_PATH, other._root)); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(_path, MAX_PATH, other._path)); ptr = _path + (other.ptr - other._path); if(--(ref->count) == 0) { @@ -723,7 +702,7 @@ void directory_iterator::next() ptr = _path; } else - std::strcpy(ptr, ref->_data.cFileName); + re_detail::overflow_error_if_not_zero(re_detail::strcpy_s(ptr, MAX_PATH - (ptr - _path), ref->_data.cFileName)); } } diff --git a/src/posix_api.cpp b/src/posix_api.cpp index d5a05516..eb82f1b9 100644 --- a/src/posix_api.cpp +++ b/src/posix_api.cpp @@ -131,7 +131,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* { result = std::strlen(names[code]) + 1; if(buf_size >= result) - std::strcpy(buf, names[code]); + re_detail::strcpy_s(buf, buf_size, names[code]); return result; } return result; @@ -145,15 +145,23 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* { if(std::strcmp(e->re_endp, names[i]) == 0) { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + (::sprintf_s)(localbuf, 5, "%d", i); +#else (std::sprintf)(localbuf, "%d", i); +#endif if(std::strlen(localbuf) < buf_size) - std::strcpy(buf, localbuf); + re_detail::strcpy_s(buf, buf_size, localbuf); return std::strlen(localbuf) + 1; } } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + (::sprintf_s)(localbuf, 5, "%d", 0); +#else (std::sprintf)(localbuf, "%d", 0); +#endif if(std::strlen(localbuf) < buf_size) - std::strcpy(buf, localbuf); + re_detail::strcpy_s(buf, buf_size, localbuf); return std::strlen(localbuf) + 1; } if(code <= (int)REG_E_UNKNOWN) @@ -168,7 +176,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* std::size_t len = p.size(); if(len < buf_size) { - std::strcpy(buf, p.c_str()); + re_detail::strcpy_s(buf, buf_size, p.c_str()); } return len + 1; } diff --git a/src/w32_regex_traits.cpp b/src/w32_regex_traits.cpp index aedf0ba5..7d850653 100644 --- a/src/w32_regex_traits.cpp +++ b/src/w32_regex_traits.cpp @@ -231,7 +231,7 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const id, // locale identifier LCMAP_SORTKEY, // mapping transformation type p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string 0, // destination buffer 0 // size of destination buffer ); @@ -242,7 +242,7 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const id, // locale identifier LCMAP_SORTKEY, // mapping transformation type p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string &*result.begin(), // destination buffer bytes // size of destination buffer ); @@ -262,7 +262,7 @@ BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const id, // locale identifier LCMAP_SORTKEY, // mapping transformation type p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string 0, // destination buffer 0 // size of destination buffer ); @@ -273,7 +273,7 @@ BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const id, // locale identifier LCMAP_SORTKEY, // mapping transformation type p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string reinterpret_cast(&*result.begin()), // destination buffer *of bytes* bytes // size of destination buffer ); @@ -295,7 +295,7 @@ BOOST_REGEX_DECL std::basic_string BOOST_REGEX_CALL w32_transfor id, // locale identifier LCMAP_SORTKEY, // mapping transformation type (LPCWSTR)p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string 0, // destination buffer 0 // size of destination buffer ); @@ -306,7 +306,7 @@ BOOST_REGEX_DECL std::basic_string BOOST_REGEX_CALL w32_transfor id, // locale identifier LCMAP_SORTKEY, // mapping transformation type (LPCWSTR)p1, // source string - p2 - p1, // number of characters in source string + static_cast(p2 - p1), // number of characters in source string reinterpret_cast(&*result.begin()), // destination buffer *of bytes* bytes // size of destination buffer ); diff --git a/src/wide_posix_api.cpp b/src/wide_posix_api.cpp index d5135f76..97a2225d 100644 --- a/src/wide_posix_api.cpp +++ b/src/wide_posix_api.cpp @@ -139,7 +139,11 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* { result = std::wcslen(wnames[code]) + 1; if(buf_size >= result) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + ::wcscpy_s(buf, buf_size, wnames[code]); +#else std::wcscpy(buf, wnames[code]); +#endif return result; } return result; @@ -156,13 +160,21 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* { (std::swprintf)(localbuf, 5, L"%d", i); if(std::wcslen(localbuf) < buf_size) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + ::wcscpy_s(buf, buf_size, localbuf); +#else std::wcscpy(buf, localbuf); +#endif return std::wcslen(localbuf) + 1; } } (std::swprintf)(localbuf, 5, L"%d", 0); if(std::wcslen(localbuf) < buf_size) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + ::wcscpy_s(buf, buf_size, localbuf); +#else std::wcscpy(buf, localbuf); +#endif return std::wcslen(localbuf) + 1; } #endif @@ -178,7 +190,7 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* std::size_t len = p.size(); if(len < buf_size) { - std::copy(p.c_str(), p.c_str() + p.size() + 1, buf); + re_detail::copy(p.c_str(), p.c_str() + p.size() + 1, buf); } return len + 1; } diff --git a/test/regress/main.cpp b/test/regress/main.cpp index fcbceee9..6cfabe5c 100644 --- a/test/regress/main.cpp +++ b/test/regress/main.cpp @@ -35,7 +35,6 @@ int cpp_main(int /*argc*/, char * /*argv*/[]) test_character_escapes(); test_assertion_escapes(); test_tricky_cases(); - test_tricky_cases2(); test_grep(); test_replace(); test_non_greedy_repeats(); diff --git a/test/regress/test_backrefs.cpp b/test/regress/test_backrefs.cpp index f58c69f8..3702b486 100644 --- a/test/regress/test_backrefs.cpp +++ b/test/regress/test_backrefs.cpp @@ -38,6 +38,22 @@ void test_backrefs() TEST_REGEX_SEARCH("(a)\\1bc*d", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2)); TEST_REGEX_SEARCH("(a)\\1bc*[ce]d", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2)); TEST_REGEX_SEARCH("^(a)\\1b(c)*cd$", perl, "aabcccd", match_default, make_array(0, 7, 0, 1, 4, 5, -2, -2)); - TEST_REGEX_SEARCH("(ab*)[ab]*\\1", extended, "ababaaa", match_default, make_array(0, 7, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbbd", match_default, make_array(0, 7, 1, 3, -2, -2)); + TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbd", match_default, make_array(-2, -2)); + TEST_REGEX_SEARCH("a\\(b*\\)c\\1d", basic, "abbcbbbd", match_default, make_array(-2, -2)); + TEST_REGEX_SEARCH("^\\(.\\)\\1", basic, "abc", match_default, make_array(-2, -2)); + TEST_REGEX_SEARCH("a\\([bc]\\)\\1d", basic, "abcdabbd", match_default, make_array(4, 8, 5, 6, -2, -2)); + // strictly speaking this is at best ambiguous, at worst wrong, this is what most + // re implimentations will match though. + TEST_REGEX_SEARCH("a\\(\\([bc]\\)\\2\\)*d", basic, "abbccd", match_default, make_array(0, 6, 3, 5, 3, 4, -2, -2)); + TEST_REGEX_SEARCH("a\\(\\([bc]\\)\\2\\)*d", basic, "abbcbd", match_default, make_array(-2, -2)); + TEST_REGEX_SEARCH("a\\(\\(b\\)*\\2\\)*d", basic, "abbbd", match_default, make_array(0, 5, 1, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("\\(a\\)\\1bcd", basic, "aabcd", match_default, make_array(0, 5, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabcd", match_default, make_array(0, 5, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabd", match_default, make_array(0, 4, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("\\(a\\)\\1bc*d", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("\\(a\\)\\1bc*[ce]d", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("^\\(a\\)\\1b\\(c\\)*cd$", basic, "aabcccd", match_default, make_array(0, 7, 0, 1, 4, 5, -2, -2)); + TEST_REGEX_SEARCH("\\(ab*\\)[ab]*\\1", basic, "ababaaa", match_default, make_array(0, 7, 0, 1, -2, -2)); } diff --git a/test/regress/test_operators.cpp b/test/regress/test_operators.cpp index e9a947c3..31b17c7b 100644 --- a/test/regress/test_operators.cpp +++ b/test/regress/test_operators.cpp @@ -12,6 +12,7 @@ #include "test.hpp" #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)\ + && !BOOST_WORKAROUND(BOOST_MSVC, == 1400)\ && !BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(55500))\ && !(defined(__GNUC__) && (__GNUC__ < 3) && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))) diff --git a/test/regress/test_tricky_cases.cpp b/test/regress/test_tricky_cases.cpp index bad30f11..6c1694b9 100644 --- a/test/regress/test_tricky_cases.cpp +++ b/test/regress/test_tricky_cases.cpp @@ -15,6 +15,9 @@ #pragma warning(disable:4127) #endif +void test_tricky_cases2(); +void test_tricky_cases3(); + void test_tricky_cases() { using namespace boost::regex_constants; @@ -98,6 +101,92 @@ void test_tricky_cases() TEST_REGEX_SEARCH("a(b|c){2,4}d", perl, "abcbcd", match_default, make_array(0, 6, 4, 5, -2, -2)); TEST_REGEX_SEARCH("a(b|c){2,}d", perl, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); TEST_REGEX_SEARCH("a(b|c){2,}d", perl, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2)); + + test_tricky_cases2(); + test_tricky_cases3(); +} + +void test_tricky_cases2() +{ + using namespace boost::regex_constants; + + TEST_REGEX_SEARCH("a(((b)))c", extended, "abc", match_default, make_array(0, 3, 1, 2, 1, 2, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|(c))d", extended, "abd", match_default, make_array(0, 3, 1, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|(c))d", extended, "acd", match_default, make_array(0, 3, 1, 2, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b*|c)d", extended, "abbd", match_default, make_array(0, 4, 1, 3, -2, -2)); + // just gotta have one DFA-buster, of course + TEST_REGEX_SEARCH("a[ab]{20}", extended, "aaaaabaaaabaaaabaaaab", match_default, make_array(0, 21, -2, -2)); + // and an inline expansion in case somebody gets tricky + TEST_REGEX_SEARCH("a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]", extended, "aaaaabaaaabaaaabaaaab", match_default, make_array(0, 21, -2, -2)); + // and in case somebody just slips in an NFA... + TEST_REGEX_SEARCH("a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)", extended, "aaaaabaaaabaaaabaaaabweeknights", match_default, make_array(0, 31, 21, 24, 24, 31, -2, -2)); + // one really big one + TEST_REGEX_SEARCH("1234567890123456789012345678901234567890123456789012345678901234567890", extended, "a1234567890123456789012345678901234567890123456789012345678901234567890b", match_default, make_array(1, 71, -2, -2)); + // fish for problems as brackets go past 8 + TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn]", extended, "xacegikmoq", match_default, make_array(1, 8, -2, -2)); + TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op]", extended, "xacegikmoq", match_default, make_array(1, 9, -2, -2)); + TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op][qr]", extended, "xacegikmoqy", match_default, make_array(1, 10, -2, -2)); + TEST_REGEX_SEARCH("[ab][cd][ef][gh][ij][kl][mn][op][q]", extended, "xacegikmoqy", match_default, make_array(1, 10, -2, -2)); + // and as parenthesis go past 9: + TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)", extended, "zabcdefghi", match_default, make_array(1, 9, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, -2, -2)); + TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)", extended, "zabcdefghij", match_default, make_array(1, 10, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, -2, -2)); + TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)", extended, "zabcdefghijk", match_default, make_array(1, 11, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, -2, -2)); + TEST_REGEX_SEARCH("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)", extended, "zabcdefghijkl", match_default, make_array(1, 12, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, -2, -2)); + TEST_REGEX_SEARCH("(a)d|(b)c", extended, "abc", match_default, make_array(1, 3, -1, -1, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("_+((www)|(ftp)|(mailto)):_*", extended, "_wwwnocolon _mailto:", match_default, make_array(12, 20, 13, 19, -1, -1, -1, -1, 13, 19, -2, -2)); + // subtleties of matching + TEST_REGEX_SEARCH("a\\(b\\)\\?c\\1d", basic|bk_plus_qm, "acd", match_default, make_array(0, 3, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b?c)+d", extended, "accd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("(wee|week)(knights|night)", extended, "weeknights", match_default, make_array(0, 10, 0, 3, 3, 10, -2, -2)); + TEST_REGEX_SEARCH(".*", extended, "abc", match_default, make_array(0, 3, -2, 3, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|(c))d", extended, "abd", match_default, make_array(0, 3, 1, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|(c))d", extended, "acd", match_default, make_array(0, 3, 1, 2, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "abbd", match_default, make_array(0, 4, 1, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "acd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b*|c|e)d", extended, "ad", match_default, make_array(0, 2, 1, 1, -2, -2)); + TEST_REGEX_SEARCH("a(b?)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b?)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2)); + TEST_REGEX_SEARCH("a(b+)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b+)c", extended, "abbbc", match_default, make_array(0, 5, 1, 4, -2, -2)); + TEST_REGEX_SEARCH("a(b*)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2)); + TEST_REGEX_SEARCH("(a|ab)(bc([de]+)f|cde)", extended, "abcdef", match_default, make_array(0, 6, 0, 1, 1, 6, 3, 5, -2, -2)); + TEST_REGEX_SEARCH("a([bc]?)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a([bc]?)c", extended, "ac", match_default, make_array(0, 2, 1, 1, -2, -2)); + TEST_REGEX_SEARCH("a([bc]+)c", extended, "abc", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a([bc]+)c", extended, "abcc", match_default, make_array(0, 4, 1, 3, -2, -2)); + TEST_REGEX_SEARCH("a([bc]+)bc", extended, "abcbc", match_default, make_array(0, 5, 1, 3, -2, -2)); + TEST_REGEX_SEARCH("a(bb+|b)b", extended, "abb", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(bbb+|bb+|b)b", extended, "abb", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(bbb+|bb+|b)b", extended, "abbb", match_default, make_array(0, 4, 1, 3, -2, -2)); + TEST_REGEX_SEARCH("a(bbb+|bb+|b)bb", extended, "abbb", match_default, make_array(0, 4, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("(.*).*", extended, "abcdef", match_default, make_array(0, 6, 0, 6, -2, 6, 6, 6, 6, -2, -2)); + TEST_REGEX_SEARCH("(a*)*", extended, "bc", match_default, make_array(0, 0, 0, 0, -2, 1, 1, 1, 1, -2, 2, 2, 2, 2, -2, -2)); + TEST_REGEX_SEARCH("xyx*xz", extended, "xyxxxxyxxxz", match_default, make_array(5, 11, -2, -2)); + // do we get the right subexpression when it is used more than once? + TEST_REGEX_SEARCH("a(b|c)*d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c)*d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c)+d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|c)+d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c?)+d", extended, "ad", match_default, make_array(0, 2, 1, 1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,0}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,1}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,1}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,2}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,}d", extended, "ad", match_default, make_array(0, 2, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){0,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){1,1}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){1,2}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){1,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){1,}d", extended, "abd", match_default, make_array(0, 3, 1, 2, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){1,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,2}d", extended, "acbd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,2}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,4}d", extended, "abcbcd", match_default, make_array(0, 6, 4, 5, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,}d", extended, "abcd", match_default, make_array(0, 4, 2, 3, -2, -2)); + TEST_REGEX_SEARCH("a(b|c){2,}d", extended, "abcbd", match_default, make_array(0, 5, 3, 4, -2, -2)); // perl only: TEST_REGEX_SEARCH("a(b|c?)+d", perl, "abcd", match_default, make_array(0, 4, 3, 3, -2, -2)); TEST_REGEX_SEARCH("a(b+|((c)*))+d", perl, "abd", match_default, make_array(0, 3, 2, 2, 2, 2, -1, -1, -2, -2)); @@ -123,12 +212,32 @@ void test_tricky_cases() // preprossor directives: TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol", match_default, make_array(0, 19, -1, -1, -2, -2)); TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol(x) #x", match_default, make_array(0, 25, -1, -1, -2, -2)); + // try to match C++ syntax elements: + // line comment: + TEST_REGEX_SEARCH("//[^\\n]*", extended&~no_escape_in_lists, "++i //here is a line comment\n", match_default, make_array(4, 28, -2, -2)); + // block comment: + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/* here is a block comment */", match_default, make_array(0, 29, 26, 27, -2, -2)); + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/**/", match_default, make_array(0, 4, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/***/", match_default, make_array(0, 5, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/****/", match_default, make_array(0, 6, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/*****/", match_default, make_array(0, 7, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("/\\*([^*]|\\*+[^*/])*\\*+/", extended&~no_escape_in_lists, "/*****/*/", match_default, make_array(0, 7, -1, -1, -2, -2)); + // preprossor directives: + TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", extended&~no_escape_in_lists, "#define some_symbol", match_default, make_array(0, 19, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", extended&~no_escape_in_lists, "#define some_symbol(x) #x", match_default, make_array(0, 25, -1, -1, -2, -2)); // perl only: TEST_REGEX_SEARCH("^[[:blank:]]*#([^\\n]*\\\\[[:space:]]+)*[^\\n]*", perl, "#define some_symbol(x) \\ \r\n foo();\\\r\n printf(#x);", match_default, make_array(0, 53, 30, 42, -2, -2)); - // literals: + // POSIX leftmost longest checks: + TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "a", match_default, make_array(0, 1, -1, -1, 0, 1, -2, -2)); + TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aa", match_default, make_array(0, 2, -1, -1, 0, 2, -2, -2)); + TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aaa", match_default, make_array(0, 3, 0, 3, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("(aaa)|(\\w+)", extended&~no_escape_in_lists, "aaaa", match_default, make_array(0, 4, -1, -1, 0, 4, -2, -2)); + TEST_REGEX_SEARCH("($)|(\\>)", extended&~no_escape_in_lists, "aaaa", match_default, make_array(4, 4, 4, 4, -1, -1, -2, -2)); + TEST_REGEX_SEARCH("($)|(\\>)", extended&~no_escape_in_lists, "aaaa", match_default|match_not_eol, make_array(4, 4, -1, -1, 4, 4, -2, -2)); + TEST_REGEX_SEARCH("(aaa)(ab)*", extended, "aaaabab", match_default, make_array(0, 7, 0, 3, 5, 7, -2, -2)); } -void test_tricky_cases2() +void test_tricky_cases3() { using namespace boost::regex_constants; TEST_REGEX_SEARCH("((0x[[:xdigit:]]+)|([[:digit:]]+))u?((int(8|16|32|64))|L)?", perl, "0xFF", match_default, make_array(0, 4, 0, 4, 0, 4, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2));