Merge changes in Trunk:

Simplify regex_timer to eliminate regression failure.
  Rename extern "C" function to have a "boost_" prefix.
  Fix recursive-expression related bug, and update tests to match.

[SVN r58885]
This commit is contained in:
John Maddock
2010-01-11 09:55:40 +00:00
parent e41acbc33f
commit fc6408426d
9 changed files with 74 additions and 19 deletions

View File

@ -103,6 +103,7 @@ istream& getline(istream& is, std::string& s)
char c = static_cast<char>(is.get()); char c = static_cast<char>(is.get());
while(c != '\n') while(c != '\n')
{ {
BOOST_ASSERT(is.good());
s.append(1, c); s.append(1, c);
c = static_cast<char>(is.get()); c = static_cast<char>(is.get());
} }
@ -123,16 +124,17 @@ istream& getline(istream& is, std::string& s)
int main(int argc, char**argv) int main(int argc, char**argv)
{ {
ifstream ifs; ifstream ifs;
streambuf* pbuf = 0; std::istream* p_in = &std::cin;
if(argc == 2) if(argc == 2)
{ {
ifs.open(argv[1]); ifs.open(argv[1]);
if(ifs.bad()) ifs.peek();
if(!ifs.good())
{ {
cout << "Bad filename: " << argv[1] << endl; cout << "Bad filename: " << argv[1] << endl;
return -1; return -1;
} }
pbuf = cin.rdbuf(ifs.rdbuf()); p_in = &ifs;
} }
boost::regex ex; boost::regex ex;
@ -152,12 +154,12 @@ int main(int argc, char**argv)
double tim; double tim;
int result = 0; int result = 0;
unsigned iters = 100; unsigned iters = 100;
double wait_time = (std::min)(t.elapsed_min() * 1000, 1.0); double wait_time = (std::min)(t.elapsed_min() * 1000, 0.5);
while(true) while(true)
{ {
cout << "Enter expression (or \"quit\" to exit): "; cout << "Enter expression (or \"quit\" to exit): ";
boost::getline(cin, s1); boost::getline(*p_in, s1);
if(argc == 2) if(argc == 2)
cout << endl << s1 << endl; cout << endl << s1 << endl;
if(s1 == "quit") if(s1 == "quit")
@ -191,7 +193,7 @@ int main(int argc, char**argv)
while(true) while(true)
{ {
cout << "Enter string to search (or \"quit\" to exit): "; cout << "Enter string to search (or \"quit\" to exit): ";
boost::getline(cin, s2); boost::getline(*p_in, s2);
if(argc == 2) if(argc == 2)
cout << endl << s2 << endl; cout << endl << s2 << endl;
if(s2 == "quit") if(s2 == "quit")
@ -365,12 +367,6 @@ int main(int argc, char**argv)
regfreeA(&r); regfreeA(&r);
} }
if(pbuf)
{
cin.rdbuf(pbuf);
ifs.close();
}
return 0; return 0;
} }

View File

@ -140,7 +140,7 @@ inline bool scoped_static_mutex_lock::locked()const
namespace boost{ namespace boost{
class BOOST_REGEX_DECL scoped_static_mutex_lock; class BOOST_REGEX_DECL scoped_static_mutex_lock;
extern "C" BOOST_REGEX_DECL void free_static_mutex(); extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex();
class BOOST_REGEX_DECL static_mutex class BOOST_REGEX_DECL static_mutex
{ {

View File

@ -811,8 +811,43 @@ void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state)
{ {
if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == id)) if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == id))
{ {
//
// We've found the target of the recursion, set the jump target:
//
static_cast<re_jump*>(state)->alt.p = p; static_cast<re_jump*>(state)->alt.p = p;
ok = true; ok = true;
//
// Now scan the target for nested repeats:
//
p = p->next.p;
int next_rep_id = 0;
while(p)
{
switch(p->type)
{
case syntax_element_rep:
case syntax_element_dot_rep:
case syntax_element_char_rep:
case syntax_element_short_set_rep:
case syntax_element_long_set_rep:
next_rep_id = static_cast<re_repeat*>(p)->state_id;
break;
case syntax_element_endmark:
if(static_cast<const re_brace*>(p)->index == id)
next_rep_id = -1;
break;
default:
break;
}
if(next_rep_id)
break;
p = p->next.p;
}
if(next_rep_id > 0)
{
static_cast<re_recurse*>(state)->state_id = next_rep_id - 1;
}
break; break;
} }
p = p->next.p; p = p->next.p;

View File

@ -1939,7 +1939,9 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
} }
insert_recursion: insert_recursion:
pb->index = markid = 0; pb->index = markid = 0;
static_cast<re_jump*>(this->append_state(syntax_element_recurse, sizeof(re_jump)))->alt.i = v; re_recurse* pr = static_cast<re_recurse*>(this->append_state(syntax_element_recurse, sizeof(re_recurse)));
pr->alt.i = v;
pr->state_id = 0;
static_cast<re_case*>( static_cast<re_case*>(
this->append_state(syntax_element_toggle_case, sizeof(re_case)) this->append_state(syntax_element_toggle_case, sizeof(re_case))
)->icase = this->flags() & regbase::icase; )->icase = this->flags() & regbase::icase;

View File

@ -277,10 +277,15 @@ public:
else else
{ {
repeater_count* p = next; repeater_count* p = next;
while(p->state_id != state_id) while(p && (p->state_id != state_id))
p = p->next; p = p->next;
count = p->count; if(p)
start_pos = p->start_pos; {
count = p->count;
start_pos = p->start_pos;
}
else
count = 0;
} }
} }
~repeater_count() ~repeater_count()

View File

@ -904,10 +904,15 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
} }
recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; recursion_stack[recursion_stack_position].preturn_address = pstate->next.p;
recursion_stack[recursion_stack_position].results = *m_presult; recursion_stack[recursion_stack_position].results = *m_presult;
if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
}
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index;
++recursion_stack_position; ++recursion_stack_position;
//BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id); //BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id);
return true; return true;
} }

View File

@ -248,6 +248,14 @@ struct re_repeat : public re_alt
bool greedy; // True if this is a greedy repeat bool greedy; // True if this is a greedy repeat
}; };
/*** struct re_recurse ************************************************
Recurse to a particular subexpression.
**********************************************************************/
struct re_recurse : public re_jump
{
int state_id; // identifier of first nested repeat within the recursion.
};
/*** enum re_jump_size_type ******************************************* /*** enum re_jump_size_type *******************************************
Provides compiled size of re_jump structure (allowing for trailing alignment). Provides compiled size of re_jump structure (allowing for trailing alignment).
We provide this so we know how manybytes to insert when constructing the machine We provide this so we know how manybytes to insert when constructing the machine

View File

@ -124,7 +124,7 @@ void scoped_static_mutex_lock::unlock()
boost::recursive_mutex* static_mutex::m_pmutex = 0; boost::recursive_mutex* static_mutex::m_pmutex = 0;
boost::once_flag static_mutex::m_once = BOOST_ONCE_INIT; boost::once_flag static_mutex::m_once = BOOST_ONCE_INIT;
extern "C" BOOST_REGEX_DECL void free_static_mutex() extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex()
{ {
delete static_mutex::m_pmutex; delete static_mutex::m_pmutex;
static_mutex::m_pmutex = 0; static_mutex::m_pmutex = 0;
@ -133,7 +133,7 @@ extern "C" BOOST_REGEX_DECL void free_static_mutex()
void static_mutex::init() void static_mutex::init()
{ {
m_pmutex = new boost::recursive_mutex(); m_pmutex = new boost::recursive_mutex();
int r = atexit(free_static_mutex); int r = atexit(boost_regex_free_static_mutex);
BOOST_ASSERT(0 == r); BOOST_ASSERT(0 == r);
} }

View File

@ -892,5 +892,9 @@ void test_recursion()
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.0.0.0", match_default, make_array(0, 8, 6, 8, -1, -1, -2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.0.0.0", match_default, make_array(0, 8, 6, 8, -1, -1, -2, -2));
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.6", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.6", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "455.3.4.5", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "455.3.4.5", match_default, make_array(-2, -2));
// Bugs:
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(); } }", match_default, make_array(0, 46, 10, 13, 14, 46, -2, -2));
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(){} } { {{{ } } } } {}}", match_default, make_array(0, 64, 10, 13, 14, 64, -2, -2));
} }