On Tue, Jul 21, 2020 at 05:33:39PM +0200, Theo Buehler wrote:
> > Hmm. I get neither a seg fault nor a loop on my amd64 Lenove E595. The
> > cursor moves to different spots in X/i3 xterm vs console and in either
> > case doesn't do any replacement.
>
> I can reproduce both behaviors reliably as follows both on console and
> in xterm.
>
> $ echo 'a\n\n\nb' > /tmp/test
> $ mg /tmp/test
>
> Don't move the cursor, just do the following (what is between quotation
> marks is what you are supposed to type, the other bits are prompts):
>
> "M-x query-replace-regexp<enter>"
Aha. I was just doing "M-%" which is query-replace and not
query-replace-regexp as I thought.
> RE Query replace: "^<enter>"
> Query replace ^ with: "a<enter>"
> Query replacing ^ with a: "<enter>"
> <SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit "!"
And now I get this.
>
> After hitting "!" here, it will enter a loop and eventually print
>
> panic: Out of memory in undo code (record)
>
> and exit.
>
> If I do the exact same dance after moving the cursor to the second
> (empty) line, it will segfault.
>
> With the diff below (which is what I understood to be Hiltjo's
> suggestion), I get more or less what I would expect. I think it should
> not replace the empty line after the last newline...
>
> So I think both diffs are not quite right :)
Well, I think not quite right is much better than looping or
segfault. So I'd go ahead with either diff at your discretion.
.... Ken
>
> Index: line.c
> ===================================================================
> RCS file: /var/cvs/src/usr.bin/mg/line.c,v
> retrieving revision 1.61
> diff -u -p -r1.61 line.c
> --- line.c 29 Aug 2018 07:50:16 -0000 1.61
> +++ line.c 21 Jul 2020 14:58:49 -0000
> @@ -556,6 +556,8 @@ lreplace(RSIZE plen, char *st)
> goto done;
>
> lp = curwp->w_dotp;
> + if (ltext(lp) == NULL)
> + goto done;
> doto = curwp->w_doto;
> n = plen;
>
> Index: re_search.c
> ===================================================================
> RCS file: /var/cvs/src/usr.bin/mg/re_search.c,v
> retrieving revision 1.34
> diff -u -p -r1.34 re_search.c
> --- re_search.c 9 Jul 2020 10:42:24 -0000 1.34
> +++ re_search.c 21 Jul 2020 15:00:08 -0000
> @@ -308,7 +308,7 @@ re_doreplace(RSIZE plen, char *st)
> static int
> re_forwsrch(void)
> {
> - int tbo, tdotline, error;
> + int re_flags, tbo, tdotline, error;
> struct line *clp;
>
> clp = curwp->w_dotp;
> @@ -330,10 +330,13 @@ re_forwsrch(void)
> * always makes the last line empty so this is good.
> */
> while (clp != (curbp->b_headp)) {
> + re_flags = REG_STARTEND;
> + if (tbo != 0)
> + re_flags |= REG_NOTBOL;
> regex_match[0].rm_so = tbo;
> regex_match[0].rm_eo = llength(clp);
> error = regexec(®ex_buff, ltext(clp) ? ltext(clp) : "",
> - RE_NMATCH, regex_match, REG_STARTEND);
> + RE_NMATCH, regex_match, re_flags);
> if (error != 0) {
> clp = lforw(clp);
> tdotline++;