Hi Folks,
The mg command 'regexp-replace "^.*$" ""' enters an endless loop (until memory
exhausted). This behaviour also occurs in query-replace-regexp with the "!" option.
The following patch corrects the issue. Firstly, it reverts the change to
re_search.c (in re_forwsrch) made in 1.35 which causes the loop. Secondly, it
provides a method of ensuring the regexp-replace is performed consistently when
starting on a empty line.
The patch modifies re_queryrepl and re_repl to set curwp->w_doto negative when
starting on an empty line. This provides a flag to re_forwsrch to not advance the
cursor, thereby ensuring the empty line is processed.
Index: re_search.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/re_search.c,v
diff -u -p -r1.37 re_search.c
--- re_search.c 8 Mar 2023 04:43:11 -0000 1.37
+++ re_search.c 21 Oct 2024 09:04:01 -0000
@@ -146,6 +146,12 @@ re_queryrepl(int f, int n)
return (ABORT);
ewprintf("Query replacing %s with %s:", re_pat, news);
+ /* If dot on empty line, instruct re_forwsrch to not advance
+ * line
+ */
+ if (curwp->w_doto == 0 && curwp->w_dotp->l_used == 0)
+ curwp->w_doto = -1;
+
/*
* Search forward repeatedly, checking each time whether to insert
* or not. The "!" case makes the check always true, so it gets put
@@ -219,6 +225,9 @@ re_repl(int f, int n)
if (eread("Replace %s with: ", news, NPAT,
EFNUL | EFNEW | EFCR, re_pat) == NULL)
return (ABORT);
+ /* If dot on empty line, re_forwsrch() should not advance line */
+ if (curwp->w_doto == 0 && curwp->w_dotp->l_used == 0)
+ curwp->w_doto = -1;
while (re_forwsrch() == TRUE) {
plen = regex_match[0].rm_eo - regex_match[0].rm_so;
@@ -339,17 +348,24 @@ re_forwsrch(void)
tbo = curwp->w_doto;
tdotline = curwp->w_dotline;
- if (tbo == clp->l_used)
+ if (tbo == clp->l_used) {
/*
* Don't start matching past end of line -- must move to
- * beginning of next line, unless line is empty or at
- * end of file.
+ * beginning of next line, unless at end of file.
*/
- if (clp != curbp->b_headp && llength(clp) != 0) {
+ if (clp != curbp->b_headp) {
clp = lforw(clp);
tdotline++;
tbo = 0;
}
+ }
+ else if (tbo < 0) {
+ /* Don't advance to the next line when dot on empty line;
+ * reset tbo to correct value.
+ */
+ tbo = 0;
+ }
+
/*
* Note this loop does not process the last line, but this editor
* always makes the last line empty so this is good.
Best Regards,
Mark
--
Mark Willson
mark.will...@hydrus.org.uk
07579 784676