From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Eric Scrivner Newsgroups: gmane.emacs.bugs Subject: bug#37910: CC Mode 5.33.2 (C++//l); CC-mode inconsistently indents everything as topmost-intro after a while Date: Wed, 13 Nov 2019 16:12:11 -0800 Message-ID: References: <20191027153956.GB27906@ACM> <20191110104811.GA6614@ACM> <20191113183858.GA4942@ACM> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="000000000000db65b70597435581" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="68654"; mail-complaints-to="usenet@blaine.gmane.org" Cc: 37910@debbugs.gnu.org To: Alan Mackenzie Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Nov 14 01:13:22 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iV2lF-000Hjl-Kq for geb-bug-gnu-emacs@m.gmane.org; Thu, 14 Nov 2019 01:13:21 +0100 Original-Received: from localhost ([::1]:52452 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iV2lD-0004Wm-PT for geb-bug-gnu-emacs@m.gmane.org; Wed, 13 Nov 2019 19:13:19 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:47280) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iV2l4-0004WI-LN for bug-gnu-emacs@gnu.org; Wed, 13 Nov 2019 19:13:13 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iV2l2-0000UJ-6H for bug-gnu-emacs@gnu.org; Wed, 13 Nov 2019 19:13:10 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:51672) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iV2kw-0000K0-QM; Wed, 13 Nov 2019 19:13:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iV2kw-0006qC-Hh; Wed, 13 Nov 2019 19:13:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Eric Scrivner Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org, bug-cc-mode@gnu.org Resent-Date: Thu, 14 Nov 2019 00:13:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 37910 X-GNU-PR-Package: emacs,cc-mode Original-Received: via spool by 37910-submit@debbugs.gnu.org id=B37910.157369035126258 (code B ref 37910); Thu, 14 Nov 2019 00:13:02 +0000 Original-Received: (at 37910) by debbugs.gnu.org; 14 Nov 2019 00:12:31 +0000 Original-Received: from localhost ([127.0.0.1]:60493 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iV2kQ-0006pR-Ut for submit@debbugs.gnu.org; Wed, 13 Nov 2019 19:12:31 -0500 Original-Received: from mail-il1-f182.google.com ([209.85.166.182]:34011) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iV2kO-0006pD-7q for 37910@debbugs.gnu.org; Wed, 13 Nov 2019 19:12:29 -0500 Original-Received: by mail-il1-f182.google.com with SMTP id p6so3624737ilp.1 for <37910@debbugs.gnu.org>; Wed, 13 Nov 2019 16:12:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Eh2Np1f8Y6icQKKGseAcoyaIlTxz9BYMzFvLBRVUp74=; b=RQ7sMRNxSfZ/DMzHvuW6MT+nHN38f6zhf8jT/lx6Nh3MEdr3J6fUioEV1EQ3ujyRVz QcXqbWUT2EAeouGleydtBRXSIdeqFbEbNwHJbAYtqqAYzkMtgywPJeKyACdtiPzx1KTX I/gpfxkCl4Ff1Rgf7qfz/8PgS0dWU3i3Cj4/2K1/ceg4c+AsxgnFIaj6+qXxgcmk3P6M 1s7BeSl61/Gf8RUxO9wdj/NXyRWIvXDHljgQ63rjO1B5sT09hv7/TF0Dsq2tPeBBF+5F csKO6QahANbsTnyifJMLS24J5Oa/vR7IxPXfMqldgBmWsA5GthKgMcBHfVuJWhMSdBWq Zlgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Eh2Np1f8Y6icQKKGseAcoyaIlTxz9BYMzFvLBRVUp74=; b=EbS28FAD5sCIT6iEpeALvxSvdqmPxsYKe5YT4htX8PGmQ9+aevLhMFTlH5LIzbhbYg 1TAmO9LgE2gXnMONJJjrdkqhCpGN35WVbxVXn/PoHr7c0bY8HP0o8FlWlizHKgLV57P5 0l/dD9eM5EEkr1YZC3MRE01J7sQD7f4tOF1YHiH6yTLpyiesodq4USFRuLsxz1ODaYMD hIoyryjczDfMDFko9r5YtzgKHp4YkQe6y3xq6lHG9rpXnLXRLlM61E3LEKYGIjG2hwI/ rdWdRSGhbQapFfkUBwQGQ5KPmXrnQAUMdLzSLiZRM5VHg5fr2BZJdh5P4ctd1+83qt2S 30MQ== X-Gm-Message-State: APjAAAWa9rqqtJOBFoBOxUgmSGVsydvP/8uOx1UAZrtVbQfo1bq+m2yr Le5pPb+/ESTVVmfPAEWTAJiPgNUEUYV2+S2LObnu7o0k X-Google-Smtp-Source: APXvYqw5VQdJ3QDn0CKiMSDcGKsQjAAkb5i9dqdwTA7XLk6WD9q58ySMj+0ExCoADx5j8PdxcgYfZ/D/tPXhM17ERh0= X-Received: by 2002:a92:b10:: with SMTP id b16mr6643518ilf.57.1573690342596; Wed, 13 Nov 2019 16:12:22 -0800 (PST) In-Reply-To: <20191113183858.GA4942@ACM> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:171517 Archived-At: --000000000000db65b70597435581 Content-Type: text/plain; charset="UTF-8" Hi Andrew, Thanks so much for the patch and explanation. I applied it locally and while the patch didn't seem to have much effect, setting `open-paren-in-column-0-is-defun-start` to `nil` seems to have done the trick here without any noticeable impact on performance. It seems as you've said that there may be some issues in the heuristic used for performance optimization here. I will let you know if any other issues surface, but it appears this has fixed my issue. On Wed, Nov 13, 2019 at 10:39 AM Alan Mackenzie wrote: > Hello again, Eric. > > On Sun, Nov 10, 2019 at 09:47:35 -0800, Eric Scrivner wrote: > > I've applied the patch and run emacs with it. Unfortunately, it doesn't > > seem to solve the issue. One the bright side, I believe I had buffers > which > > can reliably reproduce the issue (at least locally). I've copied one such > > file below. The issue can be reproduced by simply going to the end of > > `main` and attempting to indent the `SQL_Quit()` statement. At first it > > attempts to overindent the line as `statement-cont`, then if I go up and > > attempt to indent the `PlatformLog` in the else statement then return to > > the SDL_Quit and indent it, it has become `topmost-intro`. Apologies for > > the long length of the file, but hopefully it can help with reproduction: > > I've had a look at the bug and there was a non-sensical function in CC > Mode fouling things up. In the patch below, I've rewritten this > function. Could I ask you please to apply the new patch (to the > original Emacs 26.3 version off cc-engine.el), byte-compile it and test > it. Then please let me know how it goes. However .... > > I would strongly advise you to set the Emacs variable > open-parens-in-column-0-is-defun-start to nil. Whether for C++ Mode in > general (in a hook function), for this one file in particular (in a > Local Variables: section at the end of the file), or globally. > > With open-p......-start left at its default of t, Emacs will search > backward for the beginning of a function by searching for an open > paren/brace/bracket at column 0. It deems the found paren/brace/bracket > the start of a function even if that p/b/b is inside a string or > function. This seems likely to happen in your test file, where you've > got such braces at column 0 inside two raw strings. > > This variable codifies a difficult dilemma for Emacs. Without the paren > in column 0 heuristic, the beginning of function search would have to > scan to the beginning of the buffer every time which is somewhat slow > (perhaps less slow now on modern PCs, but still slow). With the > heuristic, analysis problems happen when there are braces at col 0 which > aren't BO functions (e.g., in C++ Mode when things inside a namespace > start at column 0, a popular convention). For a time, o-p-i-c-0-i-d-s > was spiked to nil by CC Mode, but this led to complaints of slowness. > > Anyhow, here's the improved patch. I look forward to hearing back from > you. Thanks for all the time you've spent on this bug. > > > > diff -r 2783baa48d44 cc-engine.el > --- a/cc-engine.el Fri Oct 25 20:00:14 2019 +0000 > +++ b/cc-engine.el Wed Nov 13 18:13:11 2019 +0000 > @@ -3371,19 +3371,35 @@ > (or (car (c-state-literal-at pos)) > pos)) > > -(defsubst c-state-cache-non-literal-place (pos state) > - ;; Return a position outside of a string/comment/macro at or before POS. > - ;; STATE is the parse-partial-sexp state at POS. > - (let ((res (if (or (nth 3 state) ; in a string? > - (and (nth 4 state) > - (not (eq (nth 7 state) 'syntax-table)))) ; in a > comment? > - (nth 8 state) > - pos))) > +(defun c-state-cache-lower-good-pos (here pos state) > + ;; Return a good pos (in the sense of `c-state-cache-good-pos') at the > + ;; lowest[*] position between POS and HERE which is syntactically > equivalent > + ;; to HERE. This position may be HERE itself. POS is before HERE in > the > + ;; buffer. > + ;; [*] We don't actually always determine this exact position, since > this > + ;; would require a disproportionate amount of work, given that this > function > + ;; deals only with a corner condition, and POS and HERE are typically on > + ;; adjacent lines. We actually return either POS, when POS is a good > + ;; position, HERE otherwise. Exceptionally, when POS is in a comment, > but > + ;; HERE not, we can return the position of the end of the comment. > + (let (s) > (save-excursion > - (goto-char res) > - (if (c-beginning-of-macro) > - (point) > - res)))) > + (goto-char pos) > + (when (nth 8 state) ; POS in a comment or string. Move out of > it. > + (setq s (parse-partial-sexp pos here nil nil state 'syntax-table)) > + (when (< (point) here) > + (setq pos (point) > + state s))) > + (if (eq (point) here) ; HERE is in the same literal as > POS > + pos > + (setq s (parse-partial-sexp pos here (1+ (car state)) nil state > nil)) > + (cond > + ((> (car s) (car state)) ; Moved into a paren between POS and > HERE > + here) > + ((not (eq (nth 6 s) (car state))) ; Moved out of a paren between > POS > + ; and HERE > + here) > + (t pos)))))) > > ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; > ;; Stuff to do with point-min, and coping with any literal there. > @@ -3690,7 +3706,13 @@ > ; brace pair. > (setq c-state-cache nil > c-state-cache-good-pos c-state-min-scan-pos) > - (setcdr ptr nil) > + ;; Do not alter the original `c-state-cache' structure, since > there > + ;; may be a loop suspended which is looping through that > structure. > + ;; This may have been the cause of bug #37910. > + (let ((cdr-ptr (cdr ptr))) > + (setcdr ptr nil) > + (setq c-state-cache (copy-sequence c-state-cache)) > + (setcdr ptr cdr-ptr)) > (setq c-state-cache-good-pos (1+ (c-state-cache-top-lparen)))) > ))) > > @@ -3793,11 +3815,12 @@ > (setq new-cons (cons bra (1+ ce))) > (cond > ((consp (car c-state-cache)) > - (setcar c-state-cache new-cons)) > + (setq c-state-cache (cons new-cons (cdr c-state-cache)))) > ((and (numberp (car c-state-cache)) ; probably never > happens > (< ce (car c-state-cache))) > - (setcdr c-state-cache > - (cons new-cons (cdr c-state-cache)))) > + (setq c-state-cache > + (cons (car c-state-cache) > + (cons new-cons (cdr c-state-cache))))) > (t (setq c-state-cache (cons new-cons c-state-cache))))) > > ;; We haven't found a brace pair. Record this in the cache. > @@ -3998,7 +4021,7 @@ > (when (and c-state-cache > (consp (car c-state-cache)) > (> (cdar c-state-cache) upper-lim)) > - (setcar c-state-cache (caar c-state-cache)) > + (setq c-state-cache (cons (caar c-state-cache) (cdr > c-state-cache))) > (setq scan-back-pos (car c-state-cache) > cons-separated t)) > > @@ -4135,7 +4158,7 @@ > ;; knowledge of what's inside these braces, we have no alternative > but > ;; to direct the caller to scan the buffer from the opening brace. > (setq pos (caar c-state-cache)) > - (setcar c-state-cache pos) > + (setq c-state-cache (cons pos (cdr c-state-cache))) > (list (1+ pos) pos t)) ; return value. We've just converted a > brace pair > ; entry into a { entry, so the caller needs to > ; search for a brace pair before the {. > @@ -4385,7 +4408,7 @@ > (setq c-state-cache-good-pos > (if (and bopl-state > (< good-pos (- here c-state-cache-too-far))) > - (c-state-cache-non-literal-place here-bopl bopl-state) > + (c-state-cache-lower-good-pos here here-bopl bopl-state) > good-pos))) > > ((eq strategy 'backward) > > > -- > Alan Mackenzie (Nuremberg, Germany). > --000000000000db65b70597435581 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Andrew,

Thanks so much fo= r the patch and explanation. I applied it locally and while the patch didn&= #39;t seem to have much effect, setting `open-paren-in-column-0-is-defun-st= art` to `nil` seems to have done the trick here without any noticeable impa= ct on performance. It seems as you've said that there may be some issue= s in the heuristic used for performance optimization here.

I will let you know if any other issues surface, but it appears th= is has fixed my issue.

On Wed, Nov 13, 2019 at 10:39 AM Alan Macke= nzie <acm@muc.de> wrote:
<= blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l= eft:1px solid rgb(204,204,204);padding-left:1ex">Hello again, Eric.

On Sun, Nov 10, 2019 at 09:47:35 -0800, Eric Scrivner wrote:
> I've applied the patch and run emacs with it. Unfortunately, it do= esn't
> seem to solve the issue. One the bright side, I believe I had buffers = which
> can reliably reproduce the issue (at least locally). I've copied o= ne such
> file below. The issue can be reproduced by simply going to the end of<= br> > `main` and attempting to indent the `SQL_Quit()` statement. At first i= t
> attempts to overindent the line as `statement-cont`, then if I go up a= nd
> attempt to indent the `PlatformLog` in the else statement then return = to
> the SDL_Quit and indent it, it has become `topmost-intro`. Apologies f= or
> the long length of the file, but hopefully it can help with reproducti= on:

I've had a look at the bug and there was a non-sensical function in CC<= br> Mode fouling things up.=C2=A0 In the patch below, I've rewritten this function.=C2=A0 Could I ask you please to apply the new patch (to the
original Emacs 26.3 version off cc-engine.el), byte-compile it and test
it.=C2=A0 Then please let me know how it goes.=C2=A0 However ....

I would strongly advise you to set the Emacs variable
open-parens-in-column-0-is-defun-start to nil.=C2=A0 Whether for C++ Mode i= n
general (in a hook function), for this one file in particular (in a
Local Variables: section at the end of the file), or globally.

With open-p......-start left at its default of t, Emacs will search
backward for the beginning of a function by searching for an open
paren/brace/bracket at column 0.=C2=A0 It deems the found paren/brace/brack= et
the start of a function even if that p/b/b is inside a string or
function.=C2=A0 This seems likely to happen in your test file, where you= 9;ve
got such braces at column 0 inside two raw strings.

This variable codifies a difficult dilemma for Emacs.=C2=A0 Without the par= en
in column 0 heuristic, the beginning of function search would have to
scan to the beginning of the buffer every time which is somewhat slow
(perhaps less slow now on modern PCs, but still slow).=C2=A0 With the
heuristic, analysis problems happen when there are braces at col 0 which aren't BO functions (e.g., in C++ Mode when things inside a namespace start at column 0, a popular convention).=C2=A0 For a time, o-p-i-c-0-i-d-s=
was spiked to nil by CC Mode, but this led to complaints of slowness.

Anyhow, here's the improved patch.=C2=A0 I look forward to hearing back= from
you.=C2=A0 Thanks for all the time you've spent on this bug.



diff -r 2783baa48d44 cc-engine.el
--- a/cc-engine.el=C2=A0 =C2=A0 =C2=A0 Fri Oct 25 20:00:14 2019 +0000
+++ b/cc-engine.el=C2=A0 =C2=A0 =C2=A0 Wed Nov 13 18:13:11 2019 +0000
@@ -3371,19 +3371,35 @@
=C2=A0 =C2=A0(or (car (c-state-literal-at pos))
=C2=A0 =C2=A0 =C2=A0 =C2=A0pos))

-(defsubst c-state-cache-non-literal-place (pos state)
-=C2=A0 ;; Return a position outside of a string/comment/macro at or before= POS.
-=C2=A0 ;; STATE is the parse-partial-sexp state at POS.
-=C2=A0 (let ((res (if (or (nth 3 state)=C2=A0 =C2=A0 =C2=A0; in a string?<= br> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (and= (nth 4 state)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0(not (eq (nth 7 state) 'syntax-table)))) ; in a commen= t?
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (nth 8 state)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pos)))
+(defun c-state-cache-lower-good-pos (here pos state)
+=C2=A0 ;; Return a good pos (in the sense of `c-state-cache-good-pos')= at the
+=C2=A0 ;; lowest[*] position between POS and HERE which is syntactically e= quivalent
+=C2=A0 ;; to HERE.=C2=A0 This position may be HERE itself.=C2=A0 POS is be= fore HERE in the
+=C2=A0 ;; buffer.
+=C2=A0 ;; [*] We don't actually always determine this exact position, = since this
+=C2=A0 ;; would require a disproportionate amount of work, given that this= function
+=C2=A0 ;; deals only with a corner condition, and POS and HERE are typical= ly on
+=C2=A0 ;; adjacent lines.=C2=A0 We actually return either POS, when POS is= a good
+=C2=A0 ;; position, HERE otherwise.=C2=A0 Exceptionally, when POS is in a = comment, but
+=C2=A0 ;; HERE not, we can return the position of the end of the comment.<= br> +=C2=A0 (let (s)
=C2=A0 =C2=A0 =C2=A0(save-excursion
-=C2=A0 =C2=A0 =C2=A0 (goto-char res)
-=C2=A0 =C2=A0 =C2=A0 (if (c-beginning-of-macro)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(point)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0res))))
+=C2=A0 =C2=A0 =C2=A0 (goto-char pos)
+=C2=A0 =C2=A0 =C2=A0 (when (nth 8 state)=C2=A0 =C2=A0 =C2=A0 ; POS in a co= mment or string.=C2=A0 Move out of it.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0(setq s (parse-partial-sexp pos here nil nil st= ate 'syntax-table))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0(when (< (point) here)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq pos (point)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0state s)))
+=C2=A0 =C2=A0 =C2=A0 (if (eq (point) here)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ; HERE is in the same literal as POS
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0pos
+=C2=A0 =C2=A0 =C2=A0 =C2=A0(setq s (parse-partial-sexp pos here (1+ (car s= tate)) nil state nil))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0(cond
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((> (car s) (car state))=C2=A0 ; Moved into= a paren between POS and HERE
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0here)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((not (eq (nth 6 s) (car state))) ; Moved out = of a paren between POS
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0; and HER= E
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0here)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (t pos))))))

=C2=A0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;= ;;;;
=C2=A0;; Stuff to do with point-min, and coping with any literal there.
@@ -3690,7 +3706,13 @@
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; brace pair.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq c-state-cache nil
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 c-state-cach= e-good-pos c-state-min-scan-pos)
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcdr ptr nil)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; Do not alter the original `c-state-ca= che' structure, since there
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; may be a loop suspended which is loop= ing through that structure.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0;; This may have been the cause of bug #= 37910.
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((cdr-ptr (cdr ptr)))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcdr ptr nil)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq c-state-cache (copy-sequenc= e c-state-cache))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcdr ptr cdr-ptr))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq c-state-cache-good-pos (1+ (c-stat= e-cache-top-lparen))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 )))

@@ -3793,11 +3815,12 @@
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq new-cons (con= s bra (1+ ce)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cond
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0((consp (car = c-state-cache))
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcar c-st= ate-cache new-cons))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq c-stat= e-cache (cons new-cons (cdr c-state-cache))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0((and (number= p (car c-state-cache)) ; probably never happens
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(< ce (car c-state-cache)))
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcdr c-st= ate-cache
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0(cons new-cons (cdr c-state-cache))))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq c-stat= e-cache
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(cons (car c-state-cache)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(cons new-cons (cdr c-state-cache)))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(t (setq c-st= ate-cache (cons new-cons c-state-cache)))))

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; We haven't found a brace p= air.=C2=A0 Record this in the cache.
@@ -3998,7 +4021,7 @@
=C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (and c-state-cache
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(consp= (car c-state-cache))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(> = (cdar c-state-cache) upper-lim))
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setcar c-state-cache (caar c-state-cach= e))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(setq c-state-cache (cons (caar c-state-= cache) (cdr c-state-cache)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq scan-back-pos (car c-state-cache)<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cons-separated t))<= br>
@@ -4135,7 +4158,7 @@
=C2=A0 =C2=A0 =C2=A0 =C2=A0;; knowledge of what's inside these braces, = we have no alternative but
=C2=A0 =C2=A0 =C2=A0 =C2=A0;; to direct the caller to scan the buffer from = the opening brace.
=C2=A0 =C2=A0 =C2=A0 =C2=A0(setq pos (caar c-state-cache))
-=C2=A0 =C2=A0 =C2=A0 (setcar c-state-cache pos)
+=C2=A0 =C2=A0 =C2=A0 (setq c-state-cache (cons pos (cdr c-state-cache))) =C2=A0 =C2=A0 =C2=A0 =C2=A0(list (1+ pos) pos t)) ; return value.=C2=A0 We&= #39;ve just converted a brace pair
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0; entry into a { entry, so the caller needs = to
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0; search for a brace pair before the {.
@@ -4385,7 +4408,7 @@
=C2=A0 =C2=A0 =C2=A0 =C2=A0(setq c-state-cache-good-pos
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (if (and bopl-state
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(< good-pos (- here c-state-cache-too-far)))
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(c-state-cache-non-= literal-place here-bopl bopl-state)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(c-state-cache-lowe= r-good-pos here here-bopl bopl-state)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 good-pos)))

=C2=A0 =C2=A0 =C2=A0 ((eq strategy 'backward)


--
Alan Mackenzie (Nuremberg, Germany).
--000000000000db65b70597435581--