[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: end-of-defun is fubsr.

From: Alan Mackenzie
Subject: Re: end-of-defun is fubsr.
Date: Wed, 4 Feb 2009 00:14:45 +0000
User-agent: Mutt/1.5.9i

Hi, Stefan!

On Tue, Feb 03, 2009 at 03:50:36PM -0500, Stefan Monnier wrote:

> Yes, the code should be fixed to only move one line forward if it's
> necessary (i.e. if we're not yet at a line beginning).


> >> This might be linked to the above problem.  For Elisp it seems to
> >> work correctly.

> > (ii) When point is BETWEEN two C functions (more precisely JUST AFTER
> > the end of the previous function), C-M-e doesn't move over the next
> > function.  This is because it gets its knickers in a twist, first
> > calling BOD-raw, then EOD-function, trying to check if its succeeded
> > yet, etc. .........   This is crazy!

> I don't see this problem (actually in my tests, it seems to work fine
> in C mode as well).  Can you provide a test case.

Visit src/buffer.c, goto L313 which contains the closing brace of DEFUN
Fget_file_buffer, put point AFTER the "}".  Or put point on the next line
(L314).  In either case C-M-e leaves point at BOL315.  

> > The problem is that end-of-defun calls beginning-of-defun-raw at each
> > iteration (over ARG).  It thus discards the information as to whether
> > point began in a defun or between 2 defuns.

> I don't think so.  Quite the opposite: it uses BOD and EOD to figure out
> whether we started inside a defun or between two defuns.

Doing BOD-raw then (funcall EOD-function) can leave point after where it
started, so the test which should trigger another (funcall EOD-function)

      (unless (or (> (point) pos)
                  (eq (point) retry-point))

, fails.  I'm not sure it's possible to determine in the general case,
using only BOD and EOD, whether a given position is inside a defun or

If one were to define a variable end-of-defun-RAW-function, which is
defined to leave point just after the last bit of the function, perhaps
that would work, but it would break existing 3rd party code.

> Unless by "the problem" you're talking about the performance problem, in
> which case I understand that each time we call BOD (except for the first
> call), we know that we're "outside" of a defun (unless there's nesting,
> of course) but we don't tell that to BOD which may have to redo the work
> of figuring it out.

WILL have to do the work.  There's a CC Mode function
`c-where-wrt-brace-construct' which figures it out.  It is
computationally expensive, and is called exactly once per call of

> > What's bugging the Hades out of me is that I've put a LOT of effort into
> > optimising c-\(beginning\|end\)-of-defun, and that's being rendered
> > completely useless, at least for C-M-e, by an inept way of calling these
> > functions.  Several bug reports which made this work necessary came
> > directly from Emacs Developers (for example, C-x 4 a taking a minute to
> > run, or hassle with potential K&R regions taking just as long).

> None of the above invloved EOD as far as I can tell.  These all do
> a single call to BOD.

C-x 4 a used to do, I think, 5 calls in total to c-[be]-of-defun; one or
two of these were certainly to c-end-of-defun.  Instead, it now calls
`c-defun-name' exactly once, which is all it wanted anyway.

> > Surely there's nobody here who isn't sick and fed up with this defun
> > movement business?  Surely to goodness, after 25 years, we should be able
> > to do major-mode specific defun movement as a matter of course?

> Yes, it worked fine and fast in Emacs-21.  I wasn't the one who insisted
> that we should scan the whole buffer just in order to make sure that
> we're not bumping into the super-rare case of K&R declaration.

Now, I wonder, who could that have been?  ;-)  Oh, how I'd love just to
get rid of these stupid K&R declarations, which NOBODY uses at all
nowadays, except on >20 year old code bases.  ;-)  Why don't we flush
them out of Emacs C source?  (No, you don't have to answer.)

Actually, in Emacs-21, ARG was ignored, presumed nil, when
[be]-of-defun-function were non-nil, which was even worse.

> I'd *much* rather that C-mode's BOD gets it wrong every blue moon,
> rather than the current "let's parse the whole damn thing".
> On my 800MHz machine, C-mode is often borderline unusable nowadays.
> And it's not the fault of end-of-defun.

There are one or two "it's too slow" bugs I'm desperately trying to fix.
A dearth of braces makes CC Mode very slow, right now.  I'm aware that
some things are horribly slow.  I'm doing my best to fix them, but
there's only one of me at the moment.

> > It's changed from "move to next end of function" to "move to the end of
> > the function at whose beginning we now are",

> Right.  As you may notice, the second is a subset of the first (with
> a few caveats for nested functions, of course, but that shouldn't matter
> for C-mode), so if your implementation works for the first, it should
> work for the second as well.  It's called backward compatibility.

c-end-of-defun's functionality "needs" to stay the same to support other
Emacsen.  For Emacs-23's EOD-function, It would barely need to be more
     (search-forward-regexp "{")

, except "of course", for having to move over any dangling bits at the
end like the "bar ;" of "struct BAR { .... } bar ;".  You've just got to
love C, haven't you?  ;-(

> > and its default value is `forward-sexp'.  `c-end-of-defun' was a good
> > fit for the variable as it formerly was, but is now
> > severely suboptimal.

> At most by a factor of 2.  I.e. if it's slow now, it sure wasn't
> zippy before.

By a factor a great deal more than 2, highly dependent on ARG.

> >> Not sure about restoring the previous semantics.  But I could agree to
> >> the additional ARG argument, which could even let it "take over" (so
> >> beginning-of-defun-raw is not called in that case).

> > :-)  Let's do it!

> I knew you'd like it.


> >> > 3/- end-of-defun should be restructured along the lines of
> >> > beginning-of-defun.
> >> I don't think that's a good idea.  The main reason is to deal with
> >> languages that allow nested functions.

> > Don't follow - In the upcoming CC Mode 5.32 code (in the CVS
> > repository at SourceForge), C-M-[ae] works just fine for C++ defuns
> > nested inside classes/namespaces and so on.  The mechanism is
> > entirely within CC Mode.

> Yes, but I maintain Emacs, not CC-mode, so I care to move the
> functionality to the generic code so that all modes (not just CC-modes)
> benefit.

OK.  I think I can see what you're saying, now.  Were you thinking of any
(non CC Mode) languages in particular?  Did this ever get discussed on
emacs-devel?  I might well have been asleep at the time.

I've a suspicion that changing the meaning of EOD-function, even if it's
only "restricting" how it's being called, is essentially a loss of
backward compatibility, because any such function needs to be optimised

Good night for now!

>         Stefan

Alan Mackenzie (Nuremberg, Germany).

reply via email to

[Prev in Thread] Current Thread [Next in Thread]