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.

This is due to a change I suggested to re_forwsrch, that is, not moving
dot when the line is empty (re_search.c 1.35). The reason for this
change was to ensure the replacement took effect on the starting line of
a replace-regexp, even if the line was empty. Well, the patch did that but
caused this worse issue instead. <Hangs head in shame>.

Here's yet another suggested patch (3 of 3) to fix the issue:

--- re_search.c.orig    Fri Apr 12 09:32:15 2024
+++ re_search.c Fri Apr 12 14:00:54 2024
@@ -146,6 +146,11 @@
                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
@@ -220,6 +225,8 @@
            EFNUL | EFNEW | EFCR, re_pat) == NULL)
                 return (ABORT);

+       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;
                if (re_doreplace((RSIZE)plen, news) == FALSE)
@@ -231,7 +238,7 @@
        update(CMODE);
        if (!inmacro)
                ewprintf("(%d replacement(s) done)", rcnt);
-
+
        return(TRUE);
 }
mg: endless loop using replace-regexpmg: endless loop using replace-regexp
@@ -339,17 +346,24 @@
        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 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

Reply via email to