diff --git a/ChangeLog b/ChangeLog index fe783bc6..adf50d6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ CVS Code - two strings that had no actual words in them that should be translated. Suggested originally by Christian Rose. + - Fix subexpression replacement to work consistently. + Affects search.c:replace_regexp() and + utils.c:strstrwrapper() (David Benbennick). - cut.c: do_cut_text() - Fix incorrect cursor location when cutting long lines diff --git a/search.c b/search.c index 71415649..c6c42a7e 100644 --- a/search.c +++ b/search.c @@ -445,10 +445,10 @@ int replace_regexp(char *string, int create_flag) c++; new_size++; } else { - int num = (int)(*(c + 1) - '0'); + int num = (int) *(c + 1) - (int) '0'; if (num >= 1 && num <= 9) { - int i = regmatches[num].rm_so; + int i = regmatches[num].rm_eo - regmatches[num].rm_so; if (num > search_regexp.re_nsub) { /* Ugh, they specified a subexpression that doesn't @@ -460,12 +460,15 @@ int replace_regexp(char *string, int create_flag) c += 2; /* But add the length of the subexpression to new_size */ - new_size += regmatches[num].rm_eo - regmatches[num].rm_so; + new_size += i; /* And if create_flag is set, append the result of the * subexpression match to the new line */ - while (create_flag && i < regmatches[num].rm_eo) - *string++ = *(current->data + i++); + if (create_flag) { + strncpy(string, current->data + current_x + + regmatches[num].rm_so, i); + string += i; + } } else { if (create_flag) diff --git a/utils.c b/utils.c index 557624b7..6d3f8f11 100644 --- a/utils.c +++ b/utils.c @@ -138,50 +138,58 @@ const char *stristr(const char *haystack, const char *needle) return NULL; } +/* If we are searching backwards, we will find the last match + * that starts no later than rev_start. If we are doing a regexp search, + * then line_pos should be 0 if haystack starts at the beginning of a + * line, and positive otherwise. In the regexp case, we fill in the + * global variable regmatches with at most 9 subexpression matches. Also, + * all .rm_so elements are relative to the start of the whole match, so + * regmatches[0].rm_so == 0. */ const char *strstrwrapper(const char *haystack, const char *needle, const char *rev_start, int line_pos) { #ifdef HAVE_REGEX_H if (ISSET(USE_REGEXP)) { - if (!ISSET(REVERSE_SEARCH)) { - if (!regexec(&search_regexp, haystack, 10, regmatches, (line_pos > 0) ? REG_NOTBOL : 0)) - return haystack + regmatches[0].rm_so; - } #ifndef NANO_SMALL - else { - const char *i, *j; + if (ISSET(REVERSE_SEARCH)) { + /* When doing a backwards search, haystack is a whole line. */ + if (!regexec(&search_regexp, haystack, 1, regmatches, 0) && + haystack + regmatches[0].rm_so <= rev_start) { + const char *retval = haystack + regmatches[0].rm_so; - /* do a quick search forward first */ - if (!regexec(&search_regexp, haystack, 10, regmatches, 0)) { - /* there's a match somewhere in the line - now search for it backwards, much slower */ - for (i = rev_start; i >= haystack; --i) { - if (!regexec(&search_regexp, i, 10, regmatches, (i > haystack) ? REG_NOTBOL : 0)) { - j = i + regmatches[0].rm_so; - if (j <= rev_start) - return j; - } - } + /* Search forward until there is no more match. */ + while (!regexec(&search_regexp, retval + 1, 1, regmatches, + REG_NOTBOL) && + retval + 1 + regmatches[0].rm_so <= rev_start) + retval += 1 + regmatches[0].rm_so; + /* Finally, put the subexpression matches in global + * variable regmatches. The REG_NOTBOL flag doesn't + * matter now. */ + regexec(&search_regexp, retval, 10, regmatches, 0); + return retval; } + } else +#endif /* !NANO_SMALL */ + if (!regexec(&search_regexp, haystack, 10, regmatches, + line_pos > 0 ? REG_NOTBOL : 0)) { + const char *retval = haystack + regmatches[0].rm_so; + + regexec(&search_regexp, retval, 10, regmatches, 0); + return retval; } -#endif - return 0; + return NULL; } -#endif +#endif /* HAVE_REGEX_H */ #ifndef NANO_SMALL if (ISSET(CASE_SENSITIVE)) { if (ISSET(REVERSE_SEARCH)) return revstrstr(haystack, needle, rev_start); - else - return strstr(haystack, needle); - } else { - if (ISSET(REVERSE_SEARCH)) - return revstristr(haystack, needle, rev_start); else + return strstr(haystack, needle); + } else if (ISSET(REVERSE_SEARCH)) + return revstristr(haystack, needle, rev_start); #endif - return stristr(haystack, needle); -#ifndef NANO_SMALL - } -#endif + return stristr(haystack, needle); } /* This is a wrapper for the perror function. The wrapper takes care of