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 | } |
