diff -u save/regcomp.c ./regcomp.c --- save/regcomp.c 2003-12-13 23:19:31.000000000 +0100 +++ ./regcomp.c 2003-12-13 23:51:18.000000000 +0100 @@ -134,7 +134,10 @@ bin_tree_t *left, bin_tree_t *right, const re_token_t *token) __attribute ((noinline)); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); +static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa, + int fl_opt); +static bin_tree_t *duplicate_tree_1 (const bin_tree_t *src, re_dfa_t *dfa, + int opt_subexp_idx); /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. @@ -2452,7 +2455,7 @@ for (i = 0; i < start; ++i) if (i != 0) { - work_tree = duplicate_tree (elem, dfa); + work_tree = duplicate_tree (elem, dfa, 0); tree = create_tree (dfa, tree, work_tree, CONCAT, 0); if (BE (work_tree == NULL || tree == NULL, 0)) goto parse_dup_op_espace; @@ -2464,7 +2467,7 @@ dup_token.type = OP_DUP_ASTERISK; if (start > 0) { - elem = duplicate_tree (elem, dfa); + elem = duplicate_tree (elem, dfa, 1); work_tree = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token); tree = create_tree (dfa, tree, work_tree, CONCAT, 0); if (BE (elem == NULL || work_tree == NULL || tree == NULL, 0)) @@ -2489,7 +2492,7 @@ dup_token.type = OP_DUP_QUESTION; if (start > 0) { - elem = duplicate_tree (elem, dfa); + elem = duplicate_tree (elem, dfa, 1); elem = re_dfa_add_tree_node (dfa, elem, NULL, &dup_token); tree = create_tree (dfa, tree, elem, CONCAT, 0); if (BE (elem == NULL || tree == NULL, 0)) @@ -2503,7 +2506,7 @@ } for (i = 1; i < end - start; ++i) { - work_tree = duplicate_tree (elem, dfa); + work_tree = duplicate_tree (elem, dfa, 1); tree = create_tree (dfa, tree, work_tree, CONCAT, 0); if (BE (work_tree == NULL || tree == NULL, 0)) { @@ -3758,9 +3761,29 @@ /* Duplicate the node SRC, and return new node. */ static bin_tree_t * -duplicate_tree (src, dfa) +duplicate_tree (src, dfa, fl_opt) const bin_tree_t *src; re_dfa_t *dfa; + int fl_opt; +{ + /* Pass an OPT_SUBEXP_IDX which is != 1 if the duplicated tree is + a subexpression. */ + if (fl_opt + && src->type == CONCAT + && src->left->type == NON_TYPE + && dfa->nodes[src->left->node_idx].type == OP_OPEN_SUBEXP) + return duplicate_tree_1 (src, dfa, dfa->nodes[src->left->node_idx].opr.idx); + else + return duplicate_tree_1 (src, dfa, -1); +} + +/* Duplicate the node SRC, and return new node. */ + +static bin_tree_t * +duplicate_tree_1 (src, dfa, opt_subexp_idx) + const bin_tree_t *src; + re_dfa_t *dfa; + int opt_subexp_idx; { bin_tree_t *left = NULL, *right = NULL, *new_tree; int new_node_idx; @@ -3768,7 +3791,7 @@ we must duplicate the left at first. */ if (src->left != NULL) { - left = duplicate_tree (src->left, dfa); + left = duplicate_tree_1 (src->left, dfa, opt_subexp_idx); if (left == NULL) return NULL; } @@ -3776,7 +3799,7 @@ /* Secondaly, duplicate the right. */ if (src->right != NULL) { - right = duplicate_tree (src->right, dfa); + right = duplicate_tree_1 (src->right, dfa, opt_subexp_idx); if (right == NULL) return NULL; } @@ -3784,10 +3807,19 @@ /* At last, duplicate itself. */ if (src->type == NON_TYPE) { - new_node_idx = re_dfa_add_node (dfa, dfa->nodes[src->node_idx], 0); - dfa->nodes[new_node_idx].duplicated = 1; + int idx = src->node_idx; + int type = dfa->nodes[idx].type; + new_node_idx = re_dfa_add_node (dfa, dfa->nodes[idx], 0); if (BE (new_node_idx == -1, 0)) return NULL; + + /* Copy the opt_subexp field, but also set it depending on the + opt_subexp_idx. */ + dfa->nodes[new_node_idx].opt_subexp = + dfa->nodes[idx].opt_subexp + || ((type == OP_OPEN_SUBEXP || type == OP_CLOSE_SUBEXP) + && dfa->nodes[idx].opr.idx == opt_subexp_idx); + dfa->nodes[new_node_idx].duplicated = 1; } else new_node_idx = src->type; diff -u save/regex_internal.h ./regex_internal.h --- save/regex_internal.h 2003-12-13 23:19:31.000000000 +0100 +++ ./regex_internal.h 2003-12-13 23:19:35.000000000 +0100 @@ -280,6 +280,7 @@ re_token_type_t type; #endif unsigned int constraint : 10; /* context constraint */ + unsigned int opt_subexp : 1; unsigned int duplicated : 1; #ifdef RE_ENABLE_I18N /* These 2 bits can be moved into the union if needed (e.g. if running out diff -u save/regexec.c ./regexec.c --- save/regexec.c 2003-12-13 23:19:31.000000000 +0100 +++ ./regexec.c 2003-12-13 23:52:12.000000000 +0100 @@ -1359,13 +1359,35 @@ return; if (type == OP_OPEN_SUBEXP) { - /* We are at the first node of this sub expression. */ - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; + if (dfa->nodes[cur_node].opt_subexp) + /* We are at the first node of a repeated subexpression. + For now, we leave it as is because we know that this + subexpression starts where the previous copy ends. */ + ; + else + { + /* We are at the first node of this sub expression. */ + pmatch[reg_num].rm_so = cur_idx; + pmatch[reg_num].rm_eo = -1; + } } else if (type == OP_CLOSE_SUBEXP) - /* We are at the first node of this sub expression. */ - pmatch[reg_num].rm_eo = cur_idx; + { + if (dfa->nodes[cur_node].opt_subexp) + { + /* We are at the last node of a repeated subexpression. + If it is not an empty match, we can set it, otherwise + we leave the previous, non-empty match. */ + if (pmatch[reg_num].rm_eo < cur_idx) + { + pmatch[reg_num].rm_so = pmatch[reg_num].rm_eo; + pmatch[reg_num].rm_eo = cur_idx; + } + } + else + /* We are at the last node of this sub expression. */ + pmatch[reg_num].rm_eo = cur_idx; + } } #define NUMBER_OF_STATE 1