diff options
Diffstat (limited to 'gl/regcomp.c')
-rw-r--r-- | gl/regcomp.c | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/gl/regcomp.c b/gl/regcomp.c index 8827e03c..b114b4d1 100644 --- a/gl/regcomp.c +++ b/gl/regcomp.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* Extended regular expression matching and search library. | 1 | /* Extended regular expression matching and search library. |
2 | Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. | 2 | Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 |
3 | Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | 4 | This file is part of the GNU C Library. |
4 | Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. | 5 | Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>. |
5 | 6 | ||
@@ -333,8 +334,8 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, | |||
333 | && dfa->nodes[node].mb_partial) | 334 | && dfa->nodes[node].mb_partial) |
334 | *p++ = dfa->nodes[node].opr.c; | 335 | *p++ = dfa->nodes[node].opr.c; |
335 | memset (&state, '\0', sizeof (state)); | 336 | memset (&state, '\0', sizeof (state)); |
336 | if (mbrtowc (&wc, (const char *) buf, p - buf, | 337 | if (__mbrtowc (&wc, (const char *) buf, p - buf, |
337 | &state) == p - buf | 338 | &state) == p - buf |
338 | && (__wcrtomb ((char *) buf, towlower (wc), &state) | 339 | && (__wcrtomb ((char *) buf, towlower (wc), &state) |
339 | != (size_t) -1)) | 340 | != (size_t) -1)) |
340 | re_set_fastmap (fastmap, false, buf[0]); | 341 | re_set_fastmap (fastmap, false, buf[0]); |
@@ -356,45 +357,65 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, | |||
356 | #ifdef RE_ENABLE_I18N | 357 | #ifdef RE_ENABLE_I18N |
357 | else if (type == COMPLEX_BRACKET) | 358 | else if (type == COMPLEX_BRACKET) |
358 | { | 359 | { |
359 | Idx i; | ||
360 | re_charset_t *cset = dfa->nodes[node].opr.mbcset; | 360 | re_charset_t *cset = dfa->nodes[node].opr.mbcset; |
361 | if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes | 361 | Idx i; |
362 | || cset->nranges || cset->nchar_classes) | 362 | |
363 | { | ||
364 | # ifdef _LIBC | 363 | # ifdef _LIBC |
365 | if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) | 364 | /* See if we have to try all bytes which start multiple collation |
365 | elements. | ||
366 | e.g. In da_DK, we want to catch 'a' since "aa" is a valid | ||
367 | collation element, and don't catch 'b' since 'b' is | ||
368 | the only collation element which starts from 'b' (and | ||
369 | it is caught by SIMPLE_BRACKET). */ | ||
370 | if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0 | ||
371 | && (cset->ncoll_syms || cset->nranges)) | ||
366 | { | 372 | { |
367 | /* In this case we want to catch the bytes which are | ||
368 | the first byte of any collation elements. | ||
369 | e.g. In da_DK, we want to catch 'a' since "aa" | ||
370 | is a valid collation element, and don't catch | ||
371 | 'b' since 'b' is the only collation element | ||
372 | which starts from 'b'. */ | ||
373 | const int32_t *table = (const int32_t *) | 373 | const int32_t *table = (const int32_t *) |
374 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); | 374 | _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); |
375 | for (i = 0; i < SBC_MAX; ++i) | 375 | for (i = 0; i < SBC_MAX; ++i) |
376 | if (table[i] < 0) | 376 | if (table[i] < 0) |
377 | re_set_fastmap (fastmap, icase, i); | 377 | re_set_fastmap (fastmap, icase, i); |
378 | } | 378 | } |
379 | # else | 379 | # endif /* _LIBC */ |
380 | if (dfa->mb_cur_max > 1) | 380 | |
381 | for (i = 0; i < SBC_MAX; ++i) | 381 | /* See if we have to start the match at all multibyte characters, |
382 | if (__btowc (i) == WEOF) | 382 | i.e. where we would not find an invalid sequence. This only |
383 | re_set_fastmap (fastmap, icase, i); | 383 | applies to multibyte character sets; for single byte character |
384 | # endif /* not _LIBC */ | 384 | sets, the SIMPLE_BRACKET again suffices. */ |
385 | if (dfa->mb_cur_max > 1 | ||
386 | && (cset->nchar_classes || cset->non_match | ||
387 | # ifdef _LIBC | ||
388 | || cset->nequiv_classes | ||
389 | # endif /* _LIBC */ | ||
390 | )) | ||
391 | { | ||
392 | unsigned char c = 0; | ||
393 | do | ||
394 | { | ||
395 | mbstate_t mbs; | ||
396 | memset (&mbs, 0, sizeof (mbs)); | ||
397 | if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) | ||
398 | re_set_fastmap (fastmap, false, (int) c); | ||
399 | } | ||
400 | while (++c != 0); | ||
385 | } | 401 | } |
386 | for (i = 0; i < cset->nmbchars; ++i) | 402 | |
403 | else | ||
387 | { | 404 | { |
388 | char buf[256]; | 405 | /* ... Else catch all bytes which can start the mbchars. */ |
389 | mbstate_t state; | 406 | for (i = 0; i < cset->nmbchars; ++i) |
390 | memset (&state, '\0', sizeof (state)); | ||
391 | if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) | ||
392 | re_set_fastmap (fastmap, icase, *(unsigned char *) buf); | ||
393 | if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) | ||
394 | { | 407 | { |
395 | if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) | 408 | char buf[256]; |
396 | != (size_t) -1) | 409 | mbstate_t state; |
397 | re_set_fastmap (fastmap, false, *(unsigned char *) buf); | 410 | memset (&state, '\0', sizeof (state)); |
411 | if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) | ||
412 | re_set_fastmap (fastmap, icase, *(unsigned char *) buf); | ||
413 | if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) | ||
414 | { | ||
415 | if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) | ||
416 | != (size_t) -1) | ||
417 | re_set_fastmap (fastmap, false, *(unsigned char *) buf); | ||
418 | } | ||
398 | } | 419 | } |
399 | } | 420 | } |
400 | } | 421 | } |
@@ -776,7 +797,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, | |||
776 | __libc_lock_init (dfa->lock); | 797 | __libc_lock_init (dfa->lock); |
777 | 798 | ||
778 | err = re_string_construct (®exp, pattern, length, preg->translate, | 799 | err = re_string_construct (®exp, pattern, length, preg->translate, |
779 | syntax & RE_ICASE, dfa); | 800 | (syntax & RE_ICASE) != 0, dfa); |
780 | if (BE (err != REG_NOERROR, 0)) | 801 | if (BE (err != REG_NOERROR, 0)) |
781 | { | 802 | { |
782 | re_compile_internal_free_return: | 803 | re_compile_internal_free_return: |
@@ -1057,7 +1078,9 @@ optimize_utf8 (re_dfa_t *dfa) | |||
1057 | case BUF_LAST: | 1078 | case BUF_LAST: |
1058 | break; | 1079 | break; |
1059 | default: | 1080 | default: |
1060 | /* Word anchors etc. cannot be handled. */ | 1081 | /* Word anchors etc. cannot be handled. It's okay to test |
1082 | opr.ctx_type since constraints (for all DFA nodes) are | ||
1083 | created by ORing one or more opr.ctx_type values. */ | ||
1061 | return; | 1084 | return; |
1062 | } | 1085 | } |
1063 | break; | 1086 | break; |
@@ -1344,6 +1367,8 @@ calc_first (void *extra, bin_tree_t *node) | |||
1344 | node->node_idx = re_dfa_add_node (dfa, node->token); | 1367 | node->node_idx = re_dfa_add_node (dfa, node->token); |
1345 | if (BE (node->node_idx == REG_MISSING, 0)) | 1368 | if (BE (node->node_idx == REG_MISSING, 0)) |
1346 | return REG_ESPACE; | 1369 | return REG_ESPACE; |
1370 | if (node->token.type == ANCHOR) | ||
1371 | dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; | ||
1347 | } | 1372 | } |
1348 | return REG_NOERROR; | 1373 | return REG_NOERROR; |
1349 | } | 1374 | } |
@@ -1473,21 +1498,18 @@ duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, | |||
1473 | destination. */ | 1498 | destination. */ |
1474 | org_dest = dfa->edests[org_node].elems[0]; | 1499 | org_dest = dfa->edests[org_node].elems[0]; |
1475 | re_node_set_empty (dfa->edests + clone_node); | 1500 | re_node_set_empty (dfa->edests + clone_node); |
1476 | if (dfa->nodes[org_node].type == ANCHOR) | 1501 | clone_dest = search_duplicated_node (dfa, org_dest, constraint); |
1502 | /* If the node is root_node itself, it means the epsilon closure | ||
1503 | has a loop. Then tie it to the destination of the root_node. */ | ||
1504 | if (org_node == root_node && clone_node != org_node) | ||
1477 | { | 1505 | { |
1478 | /* In case of the node has another constraint, append it. */ | 1506 | ok = re_node_set_insert (dfa->edests + clone_node, org_dest); |
1479 | if (org_node == root_node && clone_node != org_node) | 1507 | if (BE (! ok, 0)) |
1480 | { | 1508 | return REG_ESPACE; |
1481 | /* ...but if the node is root_node itself, it means the | 1509 | break; |
1482 | epsilon closure have a loop, then tie it to the | ||
1483 | destination of the root_node. */ | ||
1484 | ok = re_node_set_insert (dfa->edests + clone_node, org_dest); | ||
1485 | if (BE (! ok, 0)) | ||
1486 | return REG_ESPACE; | ||
1487 | break; | ||
1488 | } | ||
1489 | constraint |= dfa->nodes[org_node].opr.ctx_type; | ||
1490 | } | 1510 | } |
1511 | /* In case the node has another constraint, append it. */ | ||
1512 | constraint |= dfa->nodes[org_node].constraint; | ||
1491 | clone_dest = duplicate_node (dfa, org_dest, constraint); | 1513 | clone_dest = duplicate_node (dfa, org_dest, constraint); |
1492 | if (BE (clone_dest == REG_MISSING, 0)) | 1514 | if (BE (clone_dest == REG_MISSING, 0)) |
1493 | return REG_ESPACE; | 1515 | return REG_ESPACE; |
@@ -1505,7 +1527,7 @@ duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, | |||
1505 | clone_dest = search_duplicated_node (dfa, org_dest, constraint); | 1527 | clone_dest = search_duplicated_node (dfa, org_dest, constraint); |
1506 | if (clone_dest == REG_MISSING) | 1528 | if (clone_dest == REG_MISSING) |
1507 | { | 1529 | { |
1508 | /* There are no such a duplicated node, create a new one. */ | 1530 | /* There is no such duplicated node, create a new one. */ |
1509 | reg_errcode_t err; | 1531 | reg_errcode_t err; |
1510 | clone_dest = duplicate_node (dfa, org_dest, constraint); | 1532 | clone_dest = duplicate_node (dfa, org_dest, constraint); |
1511 | if (BE (clone_dest == REG_MISSING, 0)) | 1533 | if (BE (clone_dest == REG_MISSING, 0)) |
@@ -1520,7 +1542,7 @@ duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, | |||
1520 | } | 1542 | } |
1521 | else | 1543 | else |
1522 | { | 1544 | { |
1523 | /* There are a duplicated node which satisfy the constraint, | 1545 | /* There is a duplicated node which satisfy the constraint, |
1524 | use it to avoid infinite loop. */ | 1546 | use it to avoid infinite loop. */ |
1525 | ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); | 1547 | ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); |
1526 | if (BE (! ok, 0)) | 1548 | if (BE (! ok, 0)) |
@@ -1569,8 +1591,7 @@ duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) | |||
1569 | if (BE (dup_idx != REG_MISSING, 1)) | 1591 | if (BE (dup_idx != REG_MISSING, 1)) |
1570 | { | 1592 | { |
1571 | dfa->nodes[dup_idx].constraint = constraint; | 1593 | dfa->nodes[dup_idx].constraint = constraint; |
1572 | if (dfa->nodes[org_idx].type == ANCHOR) | 1594 | dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint; |
1573 | dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; | ||
1574 | dfa->nodes[dup_idx].duplicated = 1; | 1595 | dfa->nodes[dup_idx].duplicated = 1; |
1575 | 1596 | ||
1576 | /* Store the index of the original node. */ | 1597 | /* Store the index of the original node. */ |
@@ -1652,7 +1673,6 @@ static reg_errcode_t | |||
1652 | calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) | 1673 | calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) |
1653 | { | 1674 | { |
1654 | reg_errcode_t err; | 1675 | reg_errcode_t err; |
1655 | unsigned int constraint; | ||
1656 | Idx i; | 1676 | Idx i; |
1657 | bool incomplete; | 1677 | bool incomplete; |
1658 | bool ok; | 1678 | bool ok; |
@@ -1666,15 +1686,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) | |||
1666 | We reference this value to avoid infinite loop. */ | 1686 | We reference this value to avoid infinite loop. */ |
1667 | dfa->eclosures[node].nelem = REG_MISSING; | 1687 | dfa->eclosures[node].nelem = REG_MISSING; |
1668 | 1688 | ||
1669 | constraint = ((dfa->nodes[node].type == ANCHOR) | 1689 | /* If the current node has constraints, duplicate all nodes |
1670 | ? dfa->nodes[node].opr.ctx_type : 0); | 1690 | since they must inherit the constraints. */ |
1671 | /* If the current node has constraints, duplicate all nodes. | 1691 | if (dfa->nodes[node].constraint |
1672 | Since they must inherit the constraints. */ | ||
1673 | if (constraint | ||
1674 | && dfa->edests[node].nelem | 1692 | && dfa->edests[node].nelem |
1675 | && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) | 1693 | && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) |
1676 | { | 1694 | { |
1677 | err = duplicate_node_closure (dfa, node, node, node, constraint); | 1695 | err = duplicate_node_closure (dfa, node, node, node, |
1696 | dfa->nodes[node].constraint); | ||
1678 | if (BE (err != REG_NOERROR, 0)) | 1697 | if (BE (err != REG_NOERROR, 0)) |
1679 | return err; | 1698 | return err; |
1680 | } | 1699 | } |