| 1480 | } |
| 1481 | |
| 1482 | return err; |
| 1483 | } |
| 1484 | |
| 1485 | /* Duplicate the epsilon closure of the node ROOT_NODE. |
| 1486 | Note that duplicated nodes have constraint INIT_CONSTRAINT in addition |
| 1487 | to their own constraint. */ |
| 1488 | |
| 1489 | static reg_errcode_t |
| 1490 | internal_function |
| 1491 | duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, |
| 1492 | int root_node, unsigned int init_constraint) |
| 1493 | { |
| 1494 | int org_node, clone_node, ret; |
| 1495 | unsigned int constraint = init_constraint; |
| 1496 | for (org_node = top_org_node, clone_node = top_clone_node;;) |
| 1497 | { |
| 1498 | int org_dest, clone_dest; |
| 1499 | if (dfa->nodes[org_node].type == OP_BACK_REF) |
| 1500 | { |
| 1501 | /* If the back reference epsilon-transit, its destination must |
| 1502 | also have the constraint. Then duplicate the epsilon closure |
| 1503 | of the destination of the back reference, and store it in |
| 1504 | edests of the back reference. */ |
| 1505 | org_dest = dfa->nexts[org_node]; |
| 1506 | re_node_set_empty (dfa->edests + clone_node); |
| 1507 | clone_dest = duplicate_node (dfa, org_dest, constraint); |
| 1508 | if (BE (clone_dest == -1, 0)) |
| 1509 | return REG_ESPACE; |
| 1510 | dfa->nexts[clone_node] = dfa->nexts[org_node]; |
| 1511 | ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); |
| 1512 | if (BE (ret < 0, 0)) |
| 1513 | return REG_ESPACE; |
| 1514 | } |
| 1515 | else if (dfa->edests[org_node].nelem == 0) |
| 1516 | { |
| 1517 | /* In case of the node can't epsilon-transit, don't duplicate the |
| 1518 | destination and store the original destination as the |
| 1519 | destination of the node. */ |
| 1520 | dfa->nexts[clone_node] = dfa->nexts[org_node]; |
| 1521 | break; |
| 1522 | } |
| 1523 | else if (dfa->edests[org_node].nelem == 1) |
| 1524 | { |
| 1525 | /* In case of the node can epsilon-transit, and it has only one |
| 1526 | destination. */ |
| 1527 | org_dest = dfa->edests[org_node].elems[0]; |
| 1528 | re_node_set_empty (dfa->edests + clone_node); |
| 1529 | /* If the node is root_node itself, it means the epsilon clsoure |
| 1530 | has a loop. Then tie it to the destination of the root_node. */ |
| 1531 | if (org_node == root_node && clone_node != org_node) |
| 1532 | { |
| 1533 | ret = re_node_set_insert (dfa->edests + clone_node, org_dest); |
| 1534 | if (BE (ret < 0, 0)) |
| 1535 | return REG_ESPACE; |
| 1536 | break; |
| 1537 | } |
| 1538 | /* In case of the node has another constraint, add it. */ |
| 1539 | constraint |= dfa->nodes[org_node].constraint; |
no test coverage detected