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

Reply via email to