unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Ordering in `source' property, and auto-loading of c-lang-defconsts
@ 2014-08-28 14:09 Stefan Monnier
  2014-08-31 21:23 ` Alan Mackenzie
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-08-28 14:09 UTC (permalink / raw)
  To: Martin Stjernholm, Alan Mackenzie; +Cc: emacs-devel


I'm trying to understand some of cc-defs.el and cc-langs.el code and
while there are very many questions, I'll stick to a fairly limited subset
for now.  Hopefully once that's cleared, it'll be easier for me to guess
what the rest is about:

- What the relationship between the `source' property and the
  `symbol-value' of the symbols that are in the c-lang-constants obarray?

- Do those symbols hold other information (I don't see another property
  being used, nor does the symbol-function slot seem to be used, but
  maybe I just missed it)?

- It seems that the `source' property contain an list of (FILE . LANG-ALIST)
  entries (where each LANG-ALIST is a list of (MODES . CODE)).  Right?

Here's the main question:
- Why is this FILE needed?  Why is it important to preserve ordering
  between various FILEs?  Why do we sometimes `load' those FILEs (in
  c-find-assignment-for-mode)?  Which kind of concrete situation is this
  supposed to address?

My vague understanding is that we want to allow c-lang-defconst to be
called (for the same variable) from different files for different
major modes.  Of course, for those modes supported natively by CC-mode,
they're all in cc-langs.el so there's only ever a single FILE there and
it never needs to be (auto)loaded.  But even for modes distributed
separately [BTW, it'd be good to try and keep track of them to some
extent, which reminds me I should do the same for SMIE], I don't see why
ordering is important (I mean I understand why ordering is important
w.r.t the derivation hierarchy, but not w.r.t FILEs) nor in which
circumstance you'd already know about the existence of a call to
c-lang-defconst in some FILE yet that FILE isn't loaded yet
(i.e. why/when would you know and need to (auto)load FILE from
c-find-assignment-for-mode)?


        Stefan

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Ordering in `source' property, and auto-loading of c-lang-defconsts
  2014-08-28 14:09 Ordering in `source' property, and auto-loading of c-lang-defconsts Stefan Monnier
@ 2014-08-31 21:23 ` Alan Mackenzie
  2014-09-01  0:52   ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Mackenzie @ 2014-08-31 21:23 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

Hi, Stefan.

On Thu, Aug 28, 2014 at 10:09:13AM -0400, Stefan Monnier wrote:

> I'm trying to understand some of cc-defs.el and cc-langs.el code and
> while there are very many questions, I'll stick to a fairly limited subset
> for now.  Hopefully once that's cleared, it'll be easier for me to guess
> what the rest is about:

If you haven't already done so, I'd recommend M-x load-file cc-langs.elc,
then typing something like the following into *scratch* and evaluating it
after byte-compiling various cc-files.el:

(let ((sym (intern "c-identifier-start" c-lang-constants)))
  (list
   (symbol-name sym)
   (symbol-value sym)
   (symbol-plist sym)
   ;; (symbol-function sym)
   ))

> - What the relationship between the `source' property and the
>   `symbol-value' of the symbols that are in the c-lang-constants obarray?

The `source' property holds a cons of the source file (as a symbol, e.g.
`cc-langs') and the source code of the c-lang-defconst (somewhat
processed for uniformity by c-lang-defconst).

The symbol-value is an alist of elements which look like, e.g., (c-mode .
"[[:alpha:]_]"), there being a separate element for each language.  It is
generated by byte-compiling cc-mode.el, and contains the final value of
the c-lang-defconsts, used in generating the c-lang-defvars (which are
ordinary variables in the standard obarray).

> - Do those symbols hold other information (I don't see another property
>   being used, nor does the symbol-function slot seem to be used, but
>   maybe I just missed it)?

The symbol-function is not used (there is no occurrence of
"symbol-function" in cc-defs.el).  Some other properties stored in the
obarray are `variable-documentation' and `dependents', the latter being a
list of `c-lang-defconst's which use the current `c-lang-defconst' (the
list can contain the current `c-lang-defconst' "recursively").  I don't
think there are any more.

> - It seems that the `source' property contain an list of (FILE . LANG-ALIST)
>   entries (where each LANG-ALIST is a list of (MODES . CODE)).  Right?

Yes.

> Here's the main question:
> - Why is this FILE needed?  Why is it important to preserve ordering
>   between various FILEs?  Why do we sometimes `load' those FILEs (in
>   c-find-assignment-for-mode)?  Which kind of concrete situation is this
>   supposed to address?

I'm not unconfused enough to say.  Sorry.  But it seems it will have to
do with modes derived from CC Mode using c-add-language.  I'm trying to
work out why we need to load the source files when all the information is
already contained in the c-lang-constants obarray.

> My vague understanding is that we want to allow c-lang-defconst to be
> called (for the same variable) from different files for different
> major modes.  Of course, for those modes supported natively by CC-mode,
> they're all in cc-langs.el .....

There are some c-lang-defconsts in cc-fonts.el.

> .... so there's only ever a single FILE there and it never needs to be
> (auto)loaded.  But even for modes distributed separately [BTW, it'd be
> good to try and keep track of them to some extent, which reminds me I
> should do the same for SMIE], I don't see why ordering is important (I
> mean I understand why ordering is important w.r.t the derivation
> hierarchy, but not w.r.t FILEs) nor in which circumstance you'd already
> know about the existence of a call to c-lang-defconst in some FILE yet
> that FILE isn't loaded yet (i.e. why/when would you know and need to
> (auto)load FILE from c-find-assignment-for-mode)?


>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Ordering in `source' property, and auto-loading of c-lang-defconsts
  2014-08-31 21:23 ` Alan Mackenzie
@ 2014-09-01  0:52   ` Stefan Monnier
  2014-09-01 22:43     ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-09-01  0:52 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

Thanks, Alan.

> The symbol-value is an alist of elements which look like, e.g., (c-mode .
> "[[:alpha:]_]"), there being a separate element for each language.  It is
> generated by byte-compiling cc-mode.el, and contains the final value of
> the c-lang-defconsts, used in generating the c-lang-defvars (which are
> ordinary variables in the standard obarray).

Right, in the mean time I figured this part, indeed.  t doesn't hold
"the final alist" but rather "an alist of final values" (i.e. only
contains the final value for those major modes for which it's been
computed).

Basically, we evaluate those values lazily and memoize the result in
these alists.

>> - Do those symbols hold other information (I don't see another property
>> being used, nor does the symbol-function slot seem to be used, but
>> maybe I just missed it)?

> The symbol-function is not used (there is no occurrence of
> "symbol-function" in cc-defs.el).  Some other properties stored in the
> obarray are `variable-documentation' and `dependents', the latter being a
> list of `c-lang-defconst's which use the current `c-lang-defconst' (the
> list can contain the current `c-lang-defconst' "recursively").  I don't
> think there are any more.

Ah, yes, I see it now, thanks.  It seems the `variable-documentation'
property is only used to transfer the docstring from the c-lang-defconst
to a corresponding c-lang-defvar.  And the `dependents' seems to be only
used to track which vars need to be recomputed (which part of the
memoization table needs to be flushed) when a c-lang-defconst is
re-evaluated (I guess typically be M-C-x or by re-loading cc-langs, so
it's really only used for development purposes).

>> Here's the main question:
>> - Why is this FILE needed?  Why is it important to preserve ordering
>> between various FILEs?  Why do we sometimes `load' those FILEs (in
>> c-find-assignment-for-mode)?  Which kind of concrete situation is this
>> supposed to address?

> I'm not unconfused enough to say.  Sorry.  But it seems it will have to
> do with modes derived from CC Mode using c-add-language.  I'm trying to
> work out why we need to load the source files when all the information is
> already contained in the c-lang-constants obarray.

I can't figure out when we'd (auto)load a file based on this FILE info.
OTOH I did figure out why we otherwise need this FILE info: if
a "c-lang-const" is defined by various c-lang-defconst (as is the
case if you have an unbundled amjor mode that uses the CC-mode engine),
this lets you correctly handle the reloading of a file that calls
c-lang-defconst, only replacing the part of the definition that this
file had provided.  So again (like `dependents') this seems to be mostly
useful for development purposes.

>> My vague understanding is that we want to allow c-lang-defconst to be
>> called (for the same variable) from different files for different
>> major modes.  Of course, for those modes supported natively by CC-mode,
>> they're all in cc-langs.el .....
> There are some c-lang-defconsts in cc-fonts.el.

Thanks for the heads up, I hadn't noticed them.  I'll take a look (tho
expect it won't make much difference in the sense that these vars are
still defined in only one file for the bundled code.  I.e. the `source'
property is still a single-entry list).

Looking at `source-pos', I think I see one reason why ordering matters:
in order for the definition of a variable to be able to refer to the
definition of that same variable but in its parent major-mode, it is
necessary for the two definitions to appear in the right order.  This is
not inherent, but is an artifact of the way the lookup is done to try
and make it work without bumping into an infinite cycle.

If my analysis is right, then I think I see a way to make it a bit more
robust and cleaner, getting rid of those ordering constraints.


        Stefan

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts)
  2014-09-01  0:52   ` Stefan Monnier
@ 2014-09-01 22:43     ` Stefan Monnier
  2014-09-04  2:38       ` Avoiding loading cc-langs Stefan Monnier
  2014-09-06 10:12       ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Alan Mackenzie
  0 siblings, 2 replies; 11+ messages in thread
From: Stefan Monnier @ 2014-09-01 22:43 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

In my attempt to understand a bit more how cc-mode works, here's the
next question:

- why do we work so hard to try and make cc-langs unnecessary at run-time?

I mean, if you look at c-lang-const, or c-make-init-lang-vars-fun,
you'll see we have up to 3 different ways to do the same thing in
different circumstances.

Is it only for performance reasons?


        Stefan



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-01 22:43     ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Stefan Monnier
@ 2014-09-04  2:38       ` Stefan Monnier
  2014-09-06 11:10         ` Alan Mackenzie
  2014-09-06 10:12       ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Alan Mackenzie
  1 sibling, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-09-04  2:38 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

> In my attempt to understand a bit more how cc-mode works, here's the
> next question:
> - why do we work so hard to try and make cc-langs unnecessary at run-time?
> I mean, if you look at c-lang-const, or c-make-init-lang-vars-fun,
> you'll see we have up to 3 different ways to do the same thing in
> different circumstances.
> Is it only for performance reasons?

Digging further into this: I have now a patch which gets rid of this
"pre-compute cc-langs stuff and hardcode it into cc-mode.elc and
cc-fonts.elc", by computing those things dynamically at
run-time instead.

The naive way to do that leads to a problem, tho: some of the computed
elements are functions which are then byte-compiled, so if we do that
dynamically, we end up calling the byte-compiler at run-time, which
increases the startup time significantly (almost double for an empty
c-mode file).

Luckily, it turns out that those functions we dynamically byte-compile
don't run noticeably slower when not byte-compiled (99% of their
run-time is spent in other functions, e.g. the regexp-matcher).

So if we refrain from byte-compiling them, the result is a simpler setup
that starts just a bit slower (on my test machine, enabling c-mode for
the first time, in an empty buffer takes 0.56s instead of 0.47s).

One of the main benefits I see of those two changes (setting things up
more dynamically and not calling the byte-compiler explicitly) is that
it should make most of the cc-bytecomp horror completely useless (some
of its main purpose is to propagate a compiling environment from one
place to another, e.g. to the compiler called explicitly).  I haven't
yet investigated this part, tho, admittedly.

It should also make cc-mode's build dependencies sufficiently normal
that we don't need any special Makefile.in rules for cc-mode any more.


        Stefan



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts)
  2014-09-01 22:43     ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Stefan Monnier
  2014-09-04  2:38       ` Avoiding loading cc-langs Stefan Monnier
@ 2014-09-06 10:12       ` Alan Mackenzie
  2014-09-08  1:51         ` Avoiding loading cc-langs Stefan Monnier
  1 sibling, 1 reply; 11+ messages in thread
From: Alan Mackenzie @ 2014-09-06 10:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

Hello, Stefan.

On Mon, Sep 01, 2014 at 06:43:37PM -0400, Stefan Monnier wrote:
> In my attempt to understand a bit more how cc-mode works, here's the
> next question:

> - why do we work so hard to try and make cc-langs unnecessary at run-time?

I think it more likely that when Martin created the c-lang-defvar
mechanism, he partitioned the code such that what was not needed at
run-time was placed in the separate file cc-langs.el, so as not to
burden the run-time store occupancy needlessly.

> I mean, if you look at c-lang-const, or c-make-init-lang-vars-fun,
> you'll see we have up to 3 different ways to do the same thing in
> different circumstances.

I think all these functions are cooperating to achieve one thing.  I'm
not sure what you mean here by "the same thing".

> Is it only for performance reasons?

I don't think so.  As I said, I think it [the not loading of cc-langs at
run time] is to reduce store occupancy.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-04  2:38       ` Avoiding loading cc-langs Stefan Monnier
@ 2014-09-06 11:10         ` Alan Mackenzie
  0 siblings, 0 replies; 11+ messages in thread
From: Alan Mackenzie @ 2014-09-06 11:10 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

Hello, Stefan.

On Wed, Sep 03, 2014 at 10:38:09PM -0400, Stefan Monnier wrote:
> > In my attempt to understand a bit more how cc-mode works, here's the
> > next question:
> > - why do we work so hard to try and make cc-langs unnecessary at run-time?
> > I mean, if you look at c-lang-const, or c-make-init-lang-vars-fun,
> > you'll see we have up to 3 different ways to do the same thing in
> > different circumstances.
> > Is it only for performance reasons?

> Digging further into this: I have now a patch which gets rid of this
> "pre-compute cc-langs stuff and hardcode it into cc-mode.elc and
> cc-fonts.elc", by computing those things dynamically at
> run-time instead.

Would that be Daniel Colascione's patch (or something derived from it)
which he proposed in May?  That proposal is still open.  As far as I
know, it hasn't yet been tested with derived modes (those using
c-add-language).

> The naive way to do that leads to a problem, tho: some of the computed
> elements are functions which are then byte-compiled, so if we do that
> dynamically, we end up calling the byte-compiler at run-time, which
> increases the startup time significantly (almost double for an empty
> c-mode file).

> Luckily, it turns out that those functions we dynamically byte-compile
> don't run noticeably slower when not byte-compiled (99% of their
> run-time is spent in other functions, e.g. the regexp-matcher).

> So if we refrain from byte-compiling them, the result is a simpler setup
> that starts just a bit slower (on my test machine, enabling c-mode for
> the first time, in an empty buffer takes 0.56s instead of 0.47s).

> One of the main benefits I see of those two changes (setting things up
> more dynamically and not calling the byte-compiler explicitly) is that
> it should make most of the cc-bytecomp horror completely useless (some
> of its main purpose is to propagate a compiling environment from one
> place to another, e.g. to the compiler called explicitly).  I haven't
> yet investigated this part, tho, admittedly.

You're proposing a change whereby CC Mode would only be partially
compiled at build time, and at each mode initialisation, a bit more
would be compiled, but not everything.  The modes would be a bit slower
to start, and a bit slower at run-time.  They would occupy more store at
run-time.

I honestly can't see this as a good change.

If we were starting from that position and wondering whether or not to
put in the extra effort completely to compile CC Mode at build time, I
could understand somebody saying it wasn't worth the trouble.  But the
code for this complete compilation exists and is extraordinarily
reliable, even though complicated.  It cannot make sense to cut down its
functionality.

> It should also make cc-mode's build dependencies sufficiently normal
> that we don't need any special Makefile.in rules for cc-mode any more.


>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-06 10:12       ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Alan Mackenzie
@ 2014-09-08  1:51         ` Stefan Monnier
  2014-09-08 15:46           ` Glenn Morris
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-09-08  1:51 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Alan Mackenzie, Martin Stjernholm, emacs-devel

>> In my attempt to understand a bit more how cc-mode works, here's the
>> next question:
>> - why do we work so hard to try and make cc-langs unnecessary at run-time?
> I think it more likely that when Martin created the c-lang-defvar
> mechanism, he partitioned the code such that what was not needed at
> run-time was placed in the separate file cc-langs.el, so as not to
> burden the run-time store occupancy needlessly.

Actually, a lot of what's in cc-langs.el *is* needed at run-time, but
it's copied into cc-mode.elc (and maybe cc-fonts.elc) so that
cc-langs.elc is not needed.
What proportion exactly, I don't know, admittedly.

>> I mean, if you look at c-lang-const, or c-make-init-lang-vars-fun,
>> you'll see we have up to 3 different ways to do the same thing in
>> different circumstances.
> I think all these functions are cooperating to achieve one thing.  I'm
> not sure what you mean here by "the same thing".

They each have several alternative implementations: one for interpreted
case, one for the compiled case, one for the "compiled but the
version is changed so we can't use the pre-computed stuff", maybe yet
another one for when we're used within a c-lang-defconst, etc...

The way things like c-lang-const-expansion and c-langs-are-parametric
affect the semantics of other macros is still very unclear to me.

It's not at all obvious that the resulting semantics is always exactly
the same in all 3 cases (e.g. in c-major-mode-is, one of the 3 cases
(the one that falls back on c-lang-major-mode-is) seems to pay attention
to major-mode inheritance, whereas the other two cases don't seem to
handle it).

>> Is it only for performance reasons?
> I don't think so.  As I said, I think it [the not loading of cc-langs at
> run time] is to reduce store occupancy.

Ah, right, that would also be something to look at.  I'll take a look at
that aspect, thanks.

>> Digging further into this: I have now a patch which gets rid of this
>> "pre-compute cc-langs stuff and hardcode it into cc-mode.elc and
>> cc-fonts.elc", by computing those things dynamically at
>> run-time instead.
> Would that be Daniel Colascione's patch (or something derived from it)
> which he proposed in May?  That proposal is still open.  As far as I
> know, it hasn't yet been tested with derived modes (those using
> c-add-language).

No, actually it's completely unrelated to Daniel's code (which I haven't
really looked at yet).  And my code is also untested so far with derived
modes (I did do a web search for derived modes, tho, and saw that there
are quite a number of them).  It's not even really tested at all so far.

> You're proposing a change whereby CC Mode would only be partially
> compiled at build time,

Actually, my recently installed changes to c-lang-defconst compiles
a bit more of the code at build-time (and I have similar changes for
c-lang-defvar).

So the effect is more that we don't *precompute* as many values.
And also, some of those precomputed values are functions, which we
currently manually byte-compile, whereas my patch leaves
them interpreted.  So in that part, we indeed compile less.

> and at each mode initialisation, a bit more would be compiled, but
> not everything.

No, compiling at mode initialization is too costly, so I just punt on it.

> The modes would be a bit slower to start, and a bit slower at
> run-time.

So far, the runtime is not affected.  But yes, the startup time is
slightly increased currently.

> They would occupy more store at run-time.

I haven't looked at it, so it might indeed be the case.  This said,
cc-mode.elc shrinks by 120KB and cc-fonts.elc shrinks by 100KB, so just
the fact of loading the 90KB of cc-langs.elc is not enough to make the
new situation worse.  Of course the dynamic generation of the mode
values is likely to require more memory.  As said, I haven't looked at
it yet, but it's indeed an important point.

> I honestly can't see this as a good change.

The code as it stands is a liability (seen from the point of view of
the maintainer, whose main task I think is to make sure the code can be
maintained in the long run).

If we can get rid of those optimizations without any significant impact on
(cpu&memory) performance, then I think we should.


        Stefan

------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-08  1:51         ` Avoiding loading cc-langs Stefan Monnier
@ 2014-09-08 15:46           ` Glenn Morris
  2014-09-08 18:45             ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Glenn Morris @ 2014-09-08 15:46 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: Alan Mackenzie, Alan Mackenzie, Martin Stjernholm, emacs-devel

Stefan Monnier wrote:

>> run-time was placed in the separate file cc-langs.el, so as not to
>> burden the run-time store occupancy needlessly.
>
> Actually, a lot of what's in cc-langs.el *is* needed at run-time

And as reported in http://debbugs.gnu.org/17463, in semi-recent Emacs,
cc-langs gets loaded at runtime anyway. The whole thing is so complex
that no-one shows any signs of figuring out why; can't say I blame them.
I really hope this can be simplified.






^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-08 15:46           ` Glenn Morris
@ 2014-09-08 18:45             ` Stefan Monnier
  2014-09-08 18:52               ` Glenn Morris
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-09-08 18:45 UTC (permalink / raw)
  To: Glenn Morris
  Cc: Alan Mackenzie, Alan Mackenzie, Martin Stjernholm, emacs-devel

>>> run-time was placed in the separate file cc-langs.el, so as not to
>>> burden the run-time store occupancy needlessly.
>> Actually, a lot of what's in cc-langs.el *is* needed at run-time
> And as reported in http://debbugs.gnu.org/17463, in semi-recent Emacs,
> cc-langs gets loaded at runtime anyway. The whole thing is so complex
> that no-one shows any signs of figuring out why; can't say I blame them.
> I really hope this can be simplified.

This can be simplified, of course.  It does come with a performance
cost, tho.

My measurements with a work-in-progress patch indicate the following:

- the startup performance is the most affected: starting Emacs, opening
  an empty C++ file twice, and exiting takes about 22% additional time
  (we're talking 0.705s vs 0.577s on a nettop).
- the run-time performance (tested by font-locking the last 40KB of
  xdisp.c) is basically unchanged, tho repeated measurements to filter
  out the noise indicate a slowdown of about 1%.
- on the flip side, the heap size is smaller if we initialize "the normal
  way" rather than "the current way": M-x memory-usage indicates that
  "the normal way" uses about 10KB more cons cells, but makes up for it
  by using fewer strings and vectors.  This is probably due to the fact
  that "the current way" ends up preloading the computed settings for
  all supported major modes, hence extra strings and vectors.
- the .elc files get smaller by not incorporating the precomputed values
  (about 100KB saved in cc-fonts.elc, and even a bit more in cc-mode.elc).

For those interested, the corresponding patch is below (includes various
random cleanups not directly related).


        Stefan


=== modified file 'lisp/progmodes/cc-awk.el'
--- lisp/progmodes/cc-awk.el	2014-02-10 01:34:22 +0000
+++ lisp/progmodes/cc-awk.el	2014-09-08 16:44:34 +0000
@@ -40,28 +40,8 @@
 
 ;;; Code:
 
-(eval-when-compile
-  (let ((load-path
-	 (if (and (boundp 'byte-compile-dest-file)
-		  (stringp byte-compile-dest-file))
-	     (cons (file-name-directory byte-compile-dest-file) load-path)
-	   load-path)))
-    (load "cc-bytecomp" nil t)))
-
-(cc-require 'cc-defs)
-
-;; Silence the byte compiler.
-(cc-bytecomp-defvar font-lock-mode)	; Checked with boundp before use.
-(cc-bytecomp-defvar c-new-BEG)
-(cc-bytecomp-defvar c-new-END)
-
-;; Some functions in cc-engine that are used below.  There's a cyclic
-;; dependency so it can't be required here.  (Perhaps some functions
-;; could be moved to cc-engine to avoid it.)
-(cc-bytecomp-defun c-backward-token-1)
-(cc-bytecomp-defun c-beginning-of-statement-1)
-(cc-bytecomp-defun c-backward-sws)
-(cc-bytecomp-defun c-forward-sws)
+(require 'cc-defs)
+(require 'cc-engine)
 
 (defvar awk-mode-syntax-table
   (let ((st (make-syntax-table)))
@@ -782,30 +762,30 @@
             (t nil)))))                 ; Unterminated regexp at EOB
 
 (defun c-awk-set-syntax-table-properties (lim)
-;;     Scan the buffer text between point and LIM, setting (and clearing) the
-;; syntax-table property where necessary.
-;;
-;; This function is designed to be called as the FUNCTION in a MATCHER in
-;; font-lock-syntactic-keywords, and it always returns NIL (to inhibit
-;; repeated calls from font-lock: See elisp info page "Search-based
-;; Fontification").  It also gets called, with a bit of glue, from
-;; after-change-functions when font-lock isn't active.  Point is left
-;; "undefined" after this function exits.  THE BUFFER SHOULD HAVE BEEN
-;; WIDENED, AND ANY PRECIOUS MATCH-DATA SAVED BEFORE CALLING THIS ROUTINE.
-;;
-;; We need to set/clear the syntax-table property on:
-;; (i) / - It is set to "string" on a / which is the opening or closing
-;;     delimiter of the properly terminated regexp (and left unset on a
-;;     division sign).
-;; (ii) the opener of an unterminated string/regexp, we set the property
-;;    "generic string delimiter" on both the opening " or / and the end of the
-;;    line where the closing delimiter is missing.
-;; (iii) "s inside strings/regexps (these will all be escaped "s).  They are
-;;   given the property "punctuation".  This will later allow other routines
-;;   to use the regexp "\\S\"*" to skip over the string innards.
-;; (iv) Inside a comment, all syntax-table properties are cleared.
-;;
-;; This function does hidden buffer changes.
+    "Scan the buffer text between point and LIM, setting (and clearing) the
+syntax-table property where necessary.
+
+This function is designed to be called as the FUNCTION in a MATCHER in
+font-lock-syntactic-keywords, and it always returns NIL (to inhibit
+repeated calls from font-lock: See elisp info page \"Search-based
+Fontification\").  It also gets called, with a bit of glue, from
+after-change-functions when font-lock isn't active.  Point is left
+\"undefined\" after this function exits.  THE BUFFER SHOULD HAVE BEEN
+WIDENED, AND ANY PRECIOUS MATCH-DATA SAVED BEFORE CALLING THIS ROUTINE.
+
+We need to set/clear the syntax-table property on:
+\(i) / - It is set to \"string\" on a / which is the opening or closing
+    delimiter of the properly terminated regexp (and left unset on a
+    division sign).
+\(ii) the opener of an unterminated string/regexp, we set the property
+   \"generic string delimiter\" on both the opening \" or / and the end of the
+   line where the closing delimiter is missing.
+\(iii) \"s inside strings/regexps (these will all be escaped \"s).  They are
+  given the property \"punctuation\".  This will later allow other routines
+  to use the regexp \"\\\\S\\\"*\" to skip over the string innards.
+\(iv) Inside a comment, all syntax-table properties are cleared.
+
+This function does hidden buffer changes."
   (let (anchor
 	(anchor-state-/div nil)) ; t means a following / would be a div sign.
     (c-awk-beginning-of-logical-line) ; ACM 2002/7/21.  This is probably redundant.
@@ -875,22 +855,25 @@
 ;; Don't overlook the possibility of the buffer change being the "recapturing"
 ;; of a previously escaped newline.
 
+(defvar c-new-BEG)
+(defvar c-new-END)
+
 ;; ACM 2008-02-05:
 (defun c-awk-extend-and-syntax-tablify-region (beg end old-len)
-  ;; Expand the region (BEG END) as needed to (c-new-BEG c-new-END) then put
-  ;; `syntax-table' properties on this region.
-  ;;
-  ;; This function is called from an after-change function, BEG END and
-  ;; OLD-LEN being the standard parameters.
-  ;;
-  ;; Point is undefined both before and after this function call, the buffer
-  ;; has been widened, and match-data saved.  The return value is ignored.
-  ;;
-  ;; It prepares the buffer for font
-  ;; locking, hence must get called before `font-lock-after-change-function'.
-  ;;
-  ;; This function is the AWK value of `c-before-font-lock-function'.
-  ;; It does hidden buffer changes.
+  "Expand the region (BEG END) as needed to (c-new-BEG c-new-END) then put
+`syntax-table' properties on this region.
+
+This function is called from an after-change function, BEG END and
+OLD-LEN being the standard parameters.
+
+Point is undefined both before and after this function call, the buffer
+has been widened, and match-data saved.  The return value is ignored.
+
+It prepares the buffer for font
+locking, hence must get called before `font-lock-after-change-function'.
+
+This function is the AWK value of `c-before-font-lock-function'.
+It does hidden buffer changes."
   (c-save-buffer-state ()
     (setq c-new-END (c-awk-end-of-change-region beg end old-len))
     (setq c-new-BEG (c-awk-beginning-of-logical-line beg))
@@ -1145,6 +1128,5 @@
          (goto-char (min start-point end-point)))))))
 
 \f
-(cc-provide 'cc-awk)			; Changed from 'awk-mode, ACM 2002/5/21
-
+(provide 'cc-awk)
 ;;; awk-mode.el ends here

=== modified file 'lisp/progmodes/cc-defs.el'
--- lisp/progmodes/cc-defs.el	2014-08-28 20:37:13 +0000
+++ lisp/progmodes/cc-defs.el	2014-09-08 16:03:02 +0000
@@ -195,7 +195,7 @@
 to it is returned.  This function does not modify the point or the mark."
 
   (if (eq (car-safe position) 'quote)
-      (let ((position (eval position)))
+      (let ((position (nth 1 position)))
 	(cond
 
 	 ((eq position 'bol)
@@ -885,7 +885,7 @@
       `(c-lang-major-mode-is ,mode)
 
     (if (eq (car-safe mode) 'quote)
-	(let ((mode (eval mode)))
+	(let ((mode (nth 1 mode)))
 	  (if (listp mode)
 	      `(memq c-buffer-is-cc-mode ',mode)
 	    `(eq c-buffer-is-cc-mode ',mode)))
@@ -900,26 +900,10 @@
 ;; properties set on a single character and that never spread to any
 ;; other characters.
 
-(eval-and-compile
-  ;; Constant used at compile time to decide whether or not to use
-  ;; XEmacs extents.  Check all the extent functions we'll use since
-  ;; some packages might add compatibility aliases for some of them in
-  ;; Emacs.
-  (defconst c-use-extents (and (cc-bytecomp-fboundp 'extent-at)
-			       (cc-bytecomp-fboundp 'set-extent-property)
-			       (cc-bytecomp-fboundp 'set-extent-properties)
-			       (cc-bytecomp-fboundp 'make-extent)
-			       (cc-bytecomp-fboundp 'extent-property)
-			       (cc-bytecomp-fboundp 'delete-extent)
-			       (cc-bytecomp-fboundp 'map-extents))))
-
 ;; `c-put-char-property' is complex enough in XEmacs and Emacs < 21 to
 ;; make it a function.
 (defalias 'c-put-char-property-fun
-  (cc-eval-when-compile
-    (cond (c-use-extents
-	   ;; XEmacs.
-	   (byte-compile
+  (cond ((featurep 'xemacs)
 	    (lambda (pos property value)
 	      (let ((ext (extent-at pos nil property)))
 		(if ext
@@ -928,20 +912,19 @@
 					 (cons property
 					       (cons value
 						     '(start-open t
-						       end-open t)))))))))
+                                                    end-open t))))))))
 
 	  ((not (cc-bytecomp-boundp 'text-property-default-nonsticky))
 	   ;; In Emacs < 21 we have to mess with the `rear-nonsticky' property.
-	   (byte-compile
 	    (lambda (pos property value)
 	      (put-text-property pos (1+ pos) property value)
 	      (let ((prop (get-text-property pos 'rear-nonsticky)))
 		(or (memq property prop)
 		    (put-text-property pos (1+ pos)
 				       'rear-nonsticky
-				       (cons property prop)))))))
+                                    (cons property prop))))))
 	  ;; This won't be used for anything.
-	  (t 'ignore))))
+        (t #'ignore)))
 (cc-bytecomp-defun c-put-char-property-fun) ; Make it known below.
 
 (defmacro c-put-char-property (pos property value)
@@ -956,42 +939,38 @@
   ;; 21) then it's assumed that the property is present on it.
   ;;
   ;; This macro does a hidden buffer change.
-  (setq property (eval property))
-  (if (or c-use-extents
+  (if (or (featurep 'xemacs)
 	  (not (cc-bytecomp-boundp 'text-property-default-nonsticky)))
       ;; XEmacs and Emacs < 21.
-      `(c-put-char-property-fun ,pos ',property ,value)
+      `(c-put-char-property-fun ,pos ,property ,value)
     ;; In Emacs 21 we got the `rear-nonsticky' property covered
     ;; by `text-property-default-nonsticky'.
     `(let ((-pos- ,pos))
-       (put-text-property -pos- (1+ -pos-) ',property ,value))))
+       (put-text-property -pos- (1+ -pos-) ,property ,value))))
 
 (defmacro c-get-char-property (pos property)
   ;; Get the value of the given property on the character at POS if
   ;; it's been put there by `c-put-char-property'.  PROPERTY is
   ;; assumed to be constant.
-  (setq property (eval property))
-  (if c-use-extents
+  (if (featurep 'xemacs)
       ;; XEmacs.
-      `(let ((ext (extent-at ,pos nil ',property)))
-	 (if ext (extent-property ext ',property)))
+      `(let ((ext (extent-at ,pos nil ,property)))
+	 (if ext (extent-property ext ,property)))
     ;; Emacs.
-    `(get-text-property ,pos ',property)))
+    `(get-text-property ,pos ,property)))
 
 ;; `c-clear-char-property' is complex enough in Emacs < 21 to make it
 ;; a function, since we have to mess with the `rear-nonsticky' property.
 (defalias 'c-clear-char-property-fun
-  (cc-eval-when-compile
-    (unless (or c-use-extents
+  (unless (or (featurep 'xemacs)
 		(cc-bytecomp-boundp 'text-property-default-nonsticky))
-      (byte-compile
        (lambda (pos property)
 	 (when (get-text-property pos property)
 	   (remove-text-properties pos (1+ pos) (list property nil))
 	   (put-text-property pos (1+ pos)
 			      'rear-nonsticky
 			      (delq property (get-text-property
-					      pos 'rear-nonsticky)))))))))
+                                           pos 'rear-nonsticky)))))))
 (cc-bytecomp-defun c-clear-char-property-fun) ; Make it known below.
 
 (defmacro c-clear-char-property (pos property)
@@ -1000,8 +979,10 @@
   ;; constant.
   ;;
   ;; This macro does a hidden buffer change.
-  (setq property (eval property))
-  (cond (c-use-extents
+  (if (eq 'quote (car-safe property))
+      (setq property (nth 1 property))
+    (error "`property' should be a quoted constant"))
+  (cond ((featurep 'xemacs)
 	 ;; XEmacs.
 	 `(let ((ext (extent-at ,pos nil ',property)))
 	    (if ext (delete-extent ext))))
@@ -1026,8 +1007,10 @@
   ;; `syntax-table'.
   ;;
   ;; This macro does hidden buffer changes.
-  (setq property (eval property))
-  (if c-use-extents
+  (if (eq 'quote (car-safe property))
+      (setq property (nth 1 property))
+    (error "`property' should be a quoted constant"))
+  (if (featurep 'xemacs)
       ;; XEmacs.
       `(map-extents (lambda (ext ignored)
 		      (delete-extent ext))
@@ -1097,7 +1080,7 @@
 which have the value VALUE, as tested by `equal'.  These
 properties are assumed to be over individual characters, having
 been put there by c-put-char-property.  POINT remains unchanged."
-  (if c-use-extents
+  (if (featurep 'xemacs)
     ;; XEmacs
       `(let ((-property- ,property))
 	 (map-extents (lambda (ext val)
@@ -1816,8 +1799,6 @@
 and other miscellaneous data.  The obarray might also contain
 various other symbols, but those don't have any variable bindings.")
 
-(defvar c-lang-const-expansion nil)
-
 (defsubst c-get-current-file ()
   ;; Return the base name of the current file.
   (let ((file (cond
@@ -1881,25 +1862,7 @@
 constant.  A file is identified by its base name."
 
   (let* ((sym (intern (symbol-name name) c-lang-constants))
-	 ;; Make `c-lang-const' expand to a straightforward call to
-	 ;; `c-get-lang-constant' in `macroexpand-all' below.
-	 ;;
-	 ;; (The default behavior, i.e. to expand to a call inside
-	 ;; `eval-when-compile' should be equivalent, since that macro
-	 ;; should only expand to its content if it's used inside a
-	 ;; form that's already evaluated at compile time.  It's
-	 ;; however necessary to use our cover macro
-	 ;; `cc-eval-when-compile' due to bugs in `eval-when-compile',
-	 ;; and it expands to a bulkier form that in this case only is
-	 ;; unnecessary garbage that we don't want to store in the
-	 ;; language constant source definitions.)
-	 (c-lang-const-expansion 'call)
-	 (c-langs-are-parametric t)
-	 bindings
-	 pre-files)
-
-    (or (symbolp name)
-	(error "Not a symbol: %S" name))
+	 bindings)
 
     (when (stringp (car-safe args))
       ;; The docstring is hardly used anywhere since there's no normal
@@ -1937,30 +1900,13 @@
 	(setq args (cdr args)
 	      val (car args))
 
-	;; Emacs has a weird bug where it seems to fail to read
-	;; backquote lists from byte compiled files correctly (,@
-	;; forms, to be specific), so make sure the bindings in the
-	;; expansion below don't contain any backquote stuff.
-	;; (XEmacs handles it correctly and doesn't need this for that
-	;; reason, but we also use this expansion handle
-	;; `c-lang-defconst-eval-immediately' and to register
-	;; dependencies on the `c-lang-const's in VAL.)
-	(setq val (macroexpand-all val))
+        (let ((c-langs-are-parametric t))
+          (setq val (macroexpand-all val)))
 
 	(setq bindings `(cons (cons ',assigned-mode (lambda () ,val)) ,bindings)
 	      args (cdr args))))
 
-    ;; Compile in the other files that have provided source
-    ;; definitions for this symbol, to make sure the order in the
-    ;; `source' property is correct even when files are loaded out of
-    ;; order.
-    (setq pre-files (nreverse
-		     ;; Reverse to get the right load order.
-		     (mapcar 'car (get sym 'source))))
-
-    `(eval-and-compile
-       (c-define-lang-constant ',name ,bindings
-			       ,@(and pre-files `(',pre-files))))))
+    `(c-define-lang-constant ',name ,bindings)))
 
 (put 'c-lang-defconst 'lisp-indent-function 1)
 ;(eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
@@ -1968,7 +1914,7 @@
 (def-edebug-spec c-lang-defconst
   (&define name [&optional stringp] [&rest sexp def-form]))
 
-(defun c-define-lang-constant (name bindings &optional pre-files)
+(defun c-define-lang-constant (name bindings)
   ;; Used by `c-lang-defconst'.
 
   (let* ((sym (intern (symbol-name name) c-lang-constants))
@@ -1985,10 +1931,6 @@
     ;; `c-lang-defconst' reverses the bindings, this reverses the
     ;; order between files so that the last to evaluate comes first.
     (unless elem
-      (while pre-files
-	(unless (assq (car pre-files) source)
-	  (setq source (cons (list (car pre-files)) source)))
-	(setq pre-files (cdr pre-files)))
       (put sym 'source (cons (setq elem (list file)) source)))
 
     (setcdr elem bindings)
@@ -2023,11 +1965,6 @@
 language.  NAME and LANG are not evaluated so they should not be
 quoted."
 
-  (or (symbolp name)
-      (error "Not a symbol: %S" name))
-  (or (symbolp lang)
-      (error "Not a symbol: %S" lang))
-
   (let ((sym (intern (symbol-name name) c-lang-constants))
 	(mode (when lang (intern (concat (symbol-name lang) "-mode")))))
 
@@ -2035,53 +1972,11 @@
         (error "Unknown language %S: no `c-mode-prefix' property"
                lang))
 
-    (if (eq c-lang-const-expansion 'immediate)
-	;; No need to find out the source file(s) when we evaluate
-	;; immediately since all the info is already there in the
-	;; `source' property.
-	`',(c-get-lang-constant name nil mode)
-
-      (let ((source-files
-             (let ((file (c-get-current-file)))
-               (if file (setq file (intern file)))
-               ;; Get the source file(s) that must be loaded to get the value
-               ;; of the constant.  If the symbol isn't defined yet we assume
-               ;; that its definition will come later in this file, and thus
-               ;; are no file dependencies needed.
-               (nreverse
-                ;; Reverse to get the right load order.
-                (apply 'nconc
-                       (mapcar (lambda (elem)
-                                 (if (eq file (car elem))
-                                     nil ; Exclude our own file.
-                                   (list (car elem))))
-                               (get sym 'source))))))
-            ;; Make some effort to do a compact call to
+    (let (;; Make some effort to do a compact call to
             ;; `c-get-lang-constant' since it will be compiled in.
-            (args (and mode `(',mode))))
-
-        (if (or source-files args)
-            (push (and source-files `',source-files) args))
+          (args (and mode `(nil ',mode))))
 
-        (if (or (eq c-lang-const-expansion 'call)
-                (and (not c-lang-const-expansion)
-                     (not mode))
-                load-in-progress
-                (not (boundp 'byte-compile-dest-file))
-                (not (stringp byte-compile-dest-file)))
-            ;; Either a straight call is requested in the context, or
-            ;; we're in an "uncontrolled" context and got no language,
-            ;; or we're not being byte compiled so the compile time
-            ;; stuff below is unnecessary.
-            `(c-get-lang-constant ',name ,@args)
-
-          ;; Being compiled.  If the loading and compiling version is
-          ;; the same we use a value that is evaluated at compile time,
-          ;; otherwise it's evaluated at runtime.
-          `(if (eq c-version-sym ',c-version-sym)
-               (cc-eval-when-compile
-                 (c-get-lang-constant ',name ,@args))
-             (c-get-lang-constant ',name ,@args)))))))
+      `(c-get-lang-constant ',name ,@args))))
 
 (defvar c-lang-constants-under-evaluation nil
   "Alist of constants in the process of being evaluated.
@@ -2092,7 +1987,7 @@
 
 (defconst c-lang--novalue "novalue")
 
-(defun c-get-lang-constant (name &optional source-files mode)
+(defun c-get-lang-constant (name &optional _source-files mode)
   ;; Used by `c-lang-const'.
 
   (or mode
@@ -2111,19 +2006,6 @@
       (or (memq eval-in-sym (get sym 'dependents))
 	  (put sym 'dependents (cons eval-in-sym (get sym 'dependents)))))
 
-    ;; Make sure the source files have entries on the `source'
-    ;; property so that loading will take place when necessary.
-    (while source-files
-      (unless (assq (car source-files) source)
-	(put sym 'source
-	     (setq source (cons (list (car source-files)) source)))
-	;; Might pull in more definitions which affect the value.  The
-	;; clearing of dependent values etc is done when the
-	;; definition is encountered during the load; this is just to
-	;; jump past the check for a cached value below.
-	(set sym nil))
-      (setq source-files (cdr source-files)))
-
     (if (and (boundp sym)
 	     (setq elem (assq mode (symbol-value sym))))
 	(cdr elem)
@@ -2208,34 +2090,15 @@
 	  (assignment-entry (elt source-pos 1))
 	  assignment)
 
-      (while (if assignment-entry
-		 t
+      (while (or assignment-entry
 	       ;; Handled the last assignment from one file, begin on the
 	       ;; next.  Due to the check in `c-lang-defconst', we know
 	       ;; there's at least one.
 	       (when file-entry
-
 		 (unless (aset source-pos 1
 			       (setq assignment-entry (cdar file-entry)))
-		   ;; The file containing the source definitions has not
-		   ;; been loaded.
-		   (let ((file (symbol-name (caar file-entry)))
-			 (c-lang-constants-under-evaluation nil))
-		     ;;(message (concat "Loading %s to get the source "
-		     ;;			"value for language constant %s")
-		     ;;		file name)
-		     (load file nil t))
-
-		   (unless (setq assignment-entry (cdar file-entry))
-		     ;; The load didn't fill in the source for the
-		     ;; constant as expected.  The situation is
-		     ;; probably that a derived mode was written for
-		     ;; and compiled with another version of CC Mode,
-		     ;; and the requested constant isn't in the
-		     ;; currently loaded one.  Put in a dummy
-		     ;; assignment that matches no language.
-		     (setcdr (car file-entry)
-			     (setq assignment-entry (list (list nil))))))
+                     (error "Missing c-lang-const data from file %S"
+                            (caar file-entry)))
 
 		 (aset source-pos 0 (setq file-entry (cdr file-entry)))
 		 t))

=== modified file 'lisp/progmodes/cc-engine.el'
--- lisp/progmodes/cc-engine.el	2014-08-24 20:50:11 +0000
+++ lisp/progmodes/cc-engine.el	2014-09-08 15:42:16 +0000
@@ -144,24 +144,10 @@
     (load "cc-bytecomp" nil t)))
 
 (cc-require 'cc-defs)
-(cc-require-when-compile 'cc-langs)
+(cc-require 'cc-langs)
 (cc-require 'cc-vars)
 
 \f
-;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
-
-(defmacro c-declare-lang-variables ()
-  `(progn
-     ,@(apply 'nconc
-	      (mapcar (lambda (init)
-			`(,(if (elt init 2)
-			       `(defvar ,(car init) nil ,(elt init 2))
-			     `(defvar ,(car init) nil))
-			  (make-variable-buffer-local ',(car init))))
-		      (cdr c-lang-variable-inits)))))
-(c-declare-lang-variables)
-
-\f
 ;;; Internal state variables.
 
 ;; Internal state of hungry delete key feature
@@ -4119,10 +4105,10 @@
 				 (c-end-of-current-token last-token-end-pos))
 			       (setq last-token-end-pos (point))))))
 		 ;; Inside a token.
-		 (if lookbehind-submatch
+		 (goto-char (if lookbehind-submatch
 		     ;; See the NOTE above.
-		     (goto-char state-pos)
-		   (goto-char (min last-token-end-pos bound))))
+				state-pos
+			      (min last-token-end-pos bound))))
 
 		(t
 		 ;; A real match.

=== modified file 'lisp/progmodes/cc-fonts.el'
--- lisp/progmodes/cc-fonts.el	2014-08-24 20:50:11 +0000
+++ lisp/progmodes/cc-fonts.el	2014-09-08 15:42:16 +0000
@@ -64,6 +64,8 @@
 ;; o  `font-lock-keyword-face' and the face in `c-label-face-name' are
 ;;    never overlaid with other faces.
 
+(eval-when-compile (require 'cl))
+
 (eval-when-compile
   (let ((load-path
 	 (if (and (boundp 'byte-compile-dest-file)
@@ -73,7 +75,7 @@
     (load "cc-bytecomp" nil t)))
 
 (cc-require 'cc-defs)
-(cc-require-when-compile 'cc-langs)
+(cc-require 'cc-langs)
 (cc-require 'cc-vars)
 (cc-require 'cc-engine)
 (cc-require-when-compile 'cc-awk) ; Change from cc-require, 2003/6/18 to
@@ -201,18 +203,13 @@
   :version "24.1"
   :group 'c)
 
-(eval-and-compile
-  ;; We need the following definitions during compilation since they're
-  ;; used when the `c-lang-defconst' initializers are evaluated.  Define
-  ;; them at runtime too for the sake of derived modes.
-
-  ;; This indicates the "font locking context", and is set just before
-  ;; fontification is done.  If non-nil, it says, e.g., point starts
-  ;; from within a #if preprocessor construct.
-  (defvar c-font-lock-context nil)
-  (make-variable-buffer-local 'c-font-lock-context)
+;; This indicates the "font locking context", and is set just before
+;; fontification is done.  If non-nil, it says, e.g., point starts
+;; from within a #if preprocessor construct.
+(defvar c-font-lock-context nil)
+(make-variable-buffer-local 'c-font-lock-context)
 
-  (defmacro c-put-font-lock-face (from to face)
+(defmacro c-put-font-lock-face (from to face)
     ;; Put a face on a region (overriding any existing face) in the way
     ;; font-lock would do it.  In XEmacs that means putting an
     ;; additional font-lock property, or else the font-lock package
@@ -226,7 +223,7 @@
 	`(font-lock-set-face ,from ,to ,face)
       `(put-text-property ,from ,to 'face ,face)))
 
-  (defmacro c-remove-font-lock-face (from to)
+(defmacro c-remove-font-lock-face (from to)
     ;; This is the inverse of `c-put-font-lock-face'.
     ;;
     ;; This function does a hidden buffer change.
@@ -234,7 +231,7 @@
 	`(font-lock-remove-face ,from ,to)
       `(remove-text-properties ,from ,to '(face nil))))
 
-  (defmacro c-put-font-lock-string-face (from to)
+(defmacro c-put-font-lock-string-face (from to)
     ;; Put `font-lock-string-face' on a string.  The surrounding
     ;; quotes are included in Emacs but not in XEmacs.  The passed
     ;; region should include them.
@@ -244,7 +241,7 @@
 	`(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face)
       `(c-put-font-lock-face ,from ,to 'font-lock-string-face)))
 
-  (defmacro c-fontify-types-and-refs (varlist &rest body)
+(defmacro c-fontify-types-and-refs (varlist &rest body)
     ;; Like `let', but additionally activates `c-record-type-identifiers'
     ;; and `c-record-ref-identifiers', and fontifies the recorded ranges
     ;; accordingly on exit.
@@ -255,9 +252,9 @@
 	   ,@varlist)
        (prog1 (progn ,@body)
 	 (c-fontify-recorded-types-and-refs))))
-  (put 'c-fontify-types-and-refs 'lisp-indent-function 1)
+(put 'c-fontify-types-and-refs 'lisp-indent-function 1)
 
-  (defun c-skip-comments-and-strings (limit)
+(defun c-skip-comments-and-strings (limit)
     ;; If the point is within a region fontified as a comment or
     ;; string literal skip to the end of it or to LIMIT, whichever
     ;; comes first, and return t.  Otherwise return nil.  The match
@@ -272,7 +269,19 @@
 		    (c-got-face-at (point) c-literal-faces))))
       t))
 
-  (defun c-make-syntactic-matcher (regexp)
+(defvar c-font-byte-compile nil
+  "If non-nil, byte-compile the dynamically-generated functions.
+It defaults to nil, since in practice, byte-compiling them gives no
+speed advantage anyway.")
+
+(defun c--compile (exp)
+  (cond
+   ((byte-code-function-p exp) (error "Already byte-compiled: %S" exp))
+   ((not (eq (car-safe exp) 'lambda)) (error "Expected a (lambda ..): %S" exp))
+   (c-font-byte-compile (byte-compile exp))
+   (t (eval (macroexpand-all exp)))))
+
+(defun c-make-syntactic-matcher (regexp)
     ;; Returns a byte compiled function suitable for use in place of a
     ;; regexp string in a `font-lock-keywords' matcher, except that
     ;; only matches outside comments and string literals count.
@@ -280,10 +289,10 @@
     ;; This function does not do any hidden buffer changes, but the
     ;; generated functions will.  (They are however used in places
     ;; covered by the font-lock context.)
-    (byte-compile
-     `(lambda (limit)
+  (lexical-let ((regexp regexp))
+    (lambda (limit)
 	(let (res)
-	  (while (and (setq res (re-search-forward ,regexp limit t))
+        (while (and (setq res (re-search-forward regexp limit t))
 		      (progn
 			(goto-char (match-beginning 0))
 			(or (c-skip-comments-and-strings limit)
@@ -292,7 +301,7 @@
 			      nil)))))
 	  res))))
 
-  (defun c-make-font-lock-search-form (regexp highlights)
+(defun c-make-font-lock-search-form (regexp highlights)
     ;; Return a lisp form which will fontify every occurrence of REGEXP
     ;; (a regular expression, NOT a function) between POINT and `limit'
     ;; with HIGHLIGHTS, a list of highlighters as specified on page
@@ -331,7 +340,7 @@
 		   ,(nth 2 highlight))))
 	    highlights))))
 
-  (defun c-make-font-lock-search-function (regexp &rest highlights)
+(defun c-make-font-lock-search-function (regexp &rest highlights)
     ;; This function makes a byte compiled function that works much like
     ;; a matcher element in `font-lock-keywords'.  It cuts out a little
     ;; bit of the overhead compared to a real matcher.  The main reason
@@ -359,7 +368,7 @@
 
     ;; Note: Replace `byte-compile' with `eval' to debug the generated
     ;; lambda more easily.
-    (byte-compile
+  (c--compile
      `(lambda (limit)
 	(let ( ;; The font-lock package in Emacs is known to clobber
 	      ;; `parse-sexp-lookup-properties' (when it exists).
@@ -401,7 +410,7 @@
 
 	nil)))
 
-  (defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights)
+(defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights)
     ;; This function makes a byte compiled function that first moves back
     ;; to the beginning of the current declaration (if any), then searches
     ;; forward for matcher elements (as in `font-lock-keywords') and
@@ -439,7 +448,7 @@
 
     ;; Note: Replace `byte-compile' with `eval' to debug the generated
     ;; lambda more easily.
-    (byte-compile
+  (c--compile
      `(lambda (limit)
 	(let ( ;; The font-lock package in Emacs is known to clobber
 	      ;; `parse-sexp-lookup-properties' (when it exists).
@@ -456,7 +465,7 @@
 	  ,(c-make-font-lock-search-form regexp highlights))
 	nil)))
 
-  (defun c-make-font-lock-context-search-function (normal &rest state-stanzas)
+(defun c-make-font-lock-context-search-function (normal &rest state-stanzas)
     ;; This function makes a byte compiled function that works much like
     ;; a matcher element in `font-lock-keywords', with the following
     ;; enhancement: the generated function will test for particular "font
@@ -490,7 +499,7 @@
     ;;
     ;; Note: Replace `byte-compile' with `eval' to debug the generated
     ;; lambda more easily.
-    (byte-compile
+  (c--compile
      `(lambda (limit)
 	(let ( ;; The font-lock package in Emacs is known to clobber
 	      ;; `parse-sexp-lookup-properties' (when it exists).
@@ -511,15 +520,15 @@
 	  ,(c-make-font-lock-search-form (car normal) (cdr normal))
 	  nil))))
 
-;  (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
-;    '(progn
-  (def-edebug-spec c-fontify-types-and-refs let*)
-  (def-edebug-spec c-make-syntactic-matcher t)
-  ;; If there are literal quoted or backquoted highlight specs in
-  ;; the call to `c-make-font-lock-search-function' then let's
-  ;; instrument the forms in them.
-  (def-edebug-spec c-make-font-lock-search-function
-    (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form)));))
+;; (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
+;;    '(progn
+(def-edebug-spec c-fontify-types-and-refs let*)
+(def-edebug-spec c-make-syntactic-matcher t)
+;; If there are literal quoted or backquoted highlight specs in
+;; the call to `c-make-font-lock-search-function' then let's
+;; instrument the forms in them.
+(def-edebug-spec c-make-font-lock-search-function
+  (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form));))
 
 (defun c-fontify-recorded-types-and-refs ()
   ;; Convert the ranges recorded on `c-record-type-identifiers' and
@@ -581,7 +590,7 @@
 
 		       ;; Use an anchored matcher to put paren syntax
 		       ;; on the brackets.
-		       (,(byte-compile
+		       (,(c--compile
 			  `(lambda (limit)
 			     (let ((beg (match-beginning
 					 ,(+ ncle-depth re-depth sws-depth 1)))
@@ -683,7 +692,7 @@
 			 "\\)")
 		 `(,(1+ ncle-depth) c-preprocessor-face-name t)))
 
-	      (eval . (list ,(c-make-syntactic-matcher
+	      (eval . (list ',(c-make-syntactic-matcher
 			      (concat noncontinued-line-end
 				      (c-lang-const c-opt-cpp-prefix)
 				      "if\\(n\\)def\\>"))
@@ -745,11 +754,11 @@
       ;; this, but it doesn't give the control we want since any
       ;; fontification done inside the function will be
       ;; unconditionally overridden.
-      ,(c-make-font-lock-search-function
+      (,(c-make-font-lock-search-function
 	;; Match a char before the string starter to make
 	;; `c-skip-comments-and-strings' work correctly.
 	(concat ".\\(" c-string-limit-regexp "\\)")
-	'((c-font-lock-invalid-string)))
+         '((c-font-lock-invalid-string))))
 
       ;; Fontify keyword constants.
       ,@(when (c-lang-const c-constant-kwds)
@@ -801,7 +810,8 @@
 				    (c-backward-syntactic-ws)
 				    (setq id-end (point))
 				    (< (skip-chars-backward
-					,(c-lang-const c-symbol-chars)) 0))
+					,(c-lang-const c-symbol-chars))
+                                       0))
 				  (not (get-text-property (point) 'face)))
 			(c-put-font-lock-face (point) id-end
 					      c-reference-face-name)
@@ -809,7 +819,7 @@
 		    nil
 		    (goto-char (match-end 0)))))
 
-	    `((,(byte-compile
+	    `((,(c--compile
 		 ;; Must use a function here since we match longer than
 		 ;; we want to move before doing a new search.  This is
 		 ;; not necessary for XEmacs since it restarts the
@@ -1564,9 +1574,7 @@
   ;; Note that this function won't attempt to fontify beyond the end of the
   ;; current enum block, if any.
   (let* ((paren-state (c-parse-state))
-	 (encl-pos (c-most-enclosing-brace paren-state))
-	 (start (point))
-	)
+	 (encl-pos (c-most-enclosing-brace paren-state)))
     (when (and
 	   encl-pos
 	   (eq (char-after encl-pos) ?\{)
@@ -1617,8 +1625,7 @@
   t `(;; Objective-C methods.
       ,@(when (c-major-mode-is 'objc-mode)
 	  `((,(c-lang-const c-opt-method-key)
-	     (,(byte-compile
-		(lambda (limit)
+	     (,(lambda (limit)
 		  (let (;; The font-lock package in Emacs is known to clobber
 			;; `parse-sexp-lookup-properties' (when it exists).
 			(parse-sexp-lookup-properties
@@ -1627,7 +1634,7 @@
 		    (save-restriction
 		      (narrow-to-region (point-min) limit)
 		      (c-font-lock-objc-method)))
-		  nil))
+                 nil)
 	      (goto-char (match-end 1))))))
 
       ;; Fontify all type names and the identifiers in the
@@ -1742,7 +1749,7 @@
 
       ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct").
       ,@(when (c-lang-const c-type-prefix-kwds)
-	  `((,(byte-compile
+	  `((,(c--compile
 	       `(lambda (limit)
 		  (c-fontify-types-and-refs
 		      ((c-promote-possible-types t)
@@ -2295,7 +2302,7 @@
      limit
      "[-+]"
      nil
-     (lambda (match-pos inside-macro)
+     (lambda (_match-pos _inside-macro)
        (forward-char)
        (c-font-lock-objc-method))))
   nil)

=== modified file 'lisp/progmodes/cc-langs.el'
--- lisp/progmodes/cc-langs.el	2014-08-24 20:50:11 +0000
+++ lisp/progmodes/cc-langs.el	2014-09-08 15:53:43 +0000
@@ -137,24 +137,13 @@
 \f
 ;;; Setup for the `c-lang-defvar' system.
 
-(eval-and-compile
-  ;; These are used to collect the init forms from the subsequent
-  ;; `c-lang-defvar' and `c-lang-setvar'.  They are used to build the
-  ;;  lambda in `c-make-init-lang-vars-fun' below, and to build `defvar's
-  ;;  and `make-variable-buffer-local's in cc-engine and
-  ;;  `make-local-variable's in `c-init-language-vars-for'.
-  (defvar c-lang-variable-inits nil)
-  (defvar c-lang-variable-inits-tail nil)
-  (setq c-lang-variable-inits (list nil)
-	c-lang-variable-inits-tail c-lang-variable-inits)
-  (defvar c-emacs-variable-inits nil)
-  (defvar c-emacs-variable-inits-tail nil)
-  (setq c-emacs-variable-inits (list nil)
-	c-emacs-variable-inits-tail c-emacs-variable-inits))
+(defvar c-lang--vars nil
+  "List of vars that need to be initialized buffer-locally.")
+
 
 (defmacro c-lang-defvar (var val &optional doc)
-  "Declares the buffer local variable VAR to get the value VAL.  VAL is
-evaluated and assigned at mode initialization.  More precisely, VAL is
+  "Declare the buffer local variable VAR to get the value VAL.
+VAL is evaluated and assigned at mode initialization.  More precisely, VAL is
 evaluated and bound to VAR when the result from the macro
 `c-init-language-vars' is evaluated.
 
@@ -162,10 +151,10 @@
 language being initialized, and such calls will be macro expanded to
 the evaluated constant value at compile time."
 
-  (when (and (not doc)
-	     (eq (car-safe val) 'c-lang-const)
+  (let ((use-const (and (eq (car-safe val) 'c-lang-const)
 	     (eq (nth 1 val) var)
-	     (not (nth 2 val)))
+                        (not (nth 2 val)))))
+    (when (and (not doc) use-const)
     ;; Special case: If there's no docstring and the value is a
     ;; simple (c-lang-const foo) where foo is the same name as VAR
     ;; then take the docstring from the language constant foo.
@@ -174,33 +163,14 @@
   (or (stringp doc)
       (setq doc nil))
 
-  (let ((elem (assq var (cdr c-lang-variable-inits))))
-    (if elem
-	(setcdr elem (list val doc))
-      (setcdr c-lang-variable-inits-tail (list (list var val doc)))
-      (setq c-lang-variable-inits-tail (cdr c-lang-variable-inits-tail))))
-
-  ;; Return the symbol, like the other def* forms.
-  `',var)
-
-(defmacro c-lang-setvar (var val)
-  "Causes the variable VAR to be made buffer local and to get set to the
-value VAL.  VAL is evaluated and assigned at mode initialization.  More
-precisely, VAL is evaluated and bound to VAR when the result from the
-macro `c-init-language-vars' is evaluated.  VAR is typically a standard
-Emacs variable like `comment-start'.
-
-`c-lang-const' is typically used in VAL to get the right value for the
-language being initialized, and such calls will be macro expanded to
-the evaluated constant value at compile time."
-  (let ((elem (assq var (cdr c-emacs-variable-inits))))
-    (if elem
-	(setcdr elem (list val)) ; Maybe remove "list", sometime. 2006-07-19
-      (setcdr c-emacs-variable-inits-tail (list (list var val)))
-      (setq c-emacs-variable-inits-tail (cdr c-emacs-variable-inits-tail))))
-
+    `(progn
+       (defvar ,var nil ,doc)
+       (make-variable-buffer-local ',var)
+       ,@(unless use-const
+           `((put ',var 'c-initialize-function (lambda () ,val))))
+       (add-to-list 'c-lang--vars ',var)
   ;; Return the symbol, like the other def* forms.
-  `',var)
+       ',var)))
 
 (put 'c-lang-defvar 'lisp-indent-function 'defun)
 ; (eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
@@ -214,44 +184,42 @@
 ;(declare-function delete-duplicates "cl-seq" (cl-seq &rest cl-keys) t)
 ;(declare-function mapcan "cl-extra" (cl-func cl-seq &rest cl-rest) t)
 
-(eval-and-compile
-  ;; Some helper functions used when building the language constants.
+;; Some helper functions used when building the language constants.
 
-  (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
-    ;; Extract a subset of the operators in the list OPS in a DWIM:ey
-    ;; way.  The return value is a plain list of operators:
-    ;;
-    ;; OPS either has the structure of `c-operators', is a single
-    ;; group in `c-operators', or is a plain list of operators.
-    ;;
-    ;; OPGROUP-FILTER specifies how to select the operator groups.  It
-    ;; can be t to choose all groups, a list of group type symbols
-    ;; (such as 'prefix) to accept, or a function which will be called
-    ;; with the group symbol for each group and should return non-nil
-    ;; if that group is to be included.
-    ;;
-    ;; If XLATE is given, it's a function which is called for each
-    ;; matching operator and its return value is collected instead.
-    ;; If it returns a list, the elements are spliced directly into
-    ;; the final result, which is returned as a list with duplicates
-    ;; removed using `equal'.
-    ;;
-    ;; `c-mode-syntax-table' for the current mode is in effect during
-    ;; the whole procedure.
+(defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
+  "Extract a subset of the operators in the list OPS in a DWIM:ey way.
+The return value is a plain list of operators:
+
+OPS either has the structure of `c-operators', is a single
+group in `c-operators', or is a plain list of operators.
+
+OPGROUP-FILTER specifies how to select the operator groups.  It
+can be t to choose all groups, a list of group type symbols
+\(such as 'prefix) to accept, or a function which will be called
+with the group symbol for each group and should return non-nil
+if that group is to be included.
+
+If XLATE is given, it's a function which is called for each
+matching operator and its return value is collected instead.
+If it returns a list, the elements are spliced directly into
+the final result, which is returned as a list with duplicates
+removed using `equal'.
+
+`c-mode-syntax-table' for the current mode is in effect during
+the whole procedure."
     (unless (listp (car-safe ops))
       (setq ops (list ops)))
-    (cond ((eq opgroup-filter t)
-	   (setq opgroup-filter (lambda (opgroup) t)))
+  (let ((opgroup-filter
+         (cond ((eq opgroup-filter t) (lambda (opgroup) t))
 	  ((not (functionp opgroup-filter))
-	   (setq opgroup-filter `(lambda (opgroup)
-				   (memq opgroup ',opgroup-filter)))))
-    (cond ((eq op-filter t)
-	   (setq op-filter (lambda (op) t)))
-	  ((stringp op-filter)
-	   (setq op-filter `(lambda (op)
-			      (string-match ,op-filter op)))))
+                `(lambda (opgroup) (memq opgroup ',opgroup-filter)))
+               (t opgroup-filter)))
+        (op-filter
+         (cond ((eq op-filter t) (lambda (op) t))
+               ((stringp op-filter) `(lambda (op) (string-match ,op-filter op)))
+               (t op-filter))))
     (unless xlate
-      (setq xlate 'identity))
+      (setq xlate #'identity))
     (c-with-syntax-table (c-lang-const c-mode-syntax-table)
       (cl-delete-duplicates
        (cl-mapcan (lambda (opgroup)
@@ -266,7 +234,7 @@
 				 (if (listp res) res (list res)))))
 			   opgroup)))
 	       ops)
-       :test 'equal))))
+       :test #'equal))))
 
 \f
 ;;; Various mode specific values that aren't language related.
@@ -368,18 +336,18 @@
 (c-lang-defconst c-make-mode-syntax-table
   "Functions that generates the mode specific syntax tables.
 The syntax tables aren't stored directly since they're quite large."
-  t `(lambda ()
+  t (lambda ()
        (let ((table (make-syntax-table)))
 	 (c-populate-syntax-table table)
 	 ;; Mode specific syntaxes.
-	 ,(cond ((or (c-major-mode-is 'objc-mode) (c-major-mode-is 'java-mode))
+	 (cond ((or (c-major-mode-is 'objc-mode) (c-major-mode-is 'java-mode))
 		 ;; Let '@' be part of symbols in ObjC to cope with
 		 ;; its compiler directives as single keyword tokens.
 		 ;; This is then necessary since it's assumed that
 		 ;; every keyword is a single symbol.
-		 `(modify-syntax-entry ?@ "_" table))
+                (modify-syntax-entry ?@ "_" table))
 		((c-major-mode-is 'pike-mode)
-		 `(modify-syntax-entry ?@ "." table)))
+                (modify-syntax-entry ?@ "." table)))
 	 table)))
 
 (c-lang-defconst c-mode-syntax-table
@@ -387,7 +355,7 @@
   ;; the constants in this file are evaluated.
   t (funcall (c-lang-const c-make-mode-syntax-table)))
 
-(c-lang-defconst c++-make-template-syntax-table
+(c-lang-defconst c++-template-syntax-table
   ;; A variant of `c++-mode-syntax-table' that defines `<' and `>' as
   ;; parenthesis characters.  Used temporarily when template argument
   ;; lists are parsed.  Note that this encourages incorrect parsing of
@@ -397,14 +365,13 @@
   ;; THIS SYNTAX TABLE IS CURRENT, `c-parse-state' MUST _NOT_ BE
   ;; CALLED!!!
   t   nil
-  (java c++) `(lambda ()
-	 (let ((table (funcall ,(c-lang-const c-make-mode-syntax-table))))
+  (java c++)
+  (let ((table (funcall (c-lang-const c-make-mode-syntax-table))))
 	   (modify-syntax-entry ?< "(>" table)
 	   (modify-syntax-entry ?> ")<" table)
-	   table)))
+    table))
 (c-lang-defvar c++-template-syntax-table
-  (and (c-lang-const c++-make-template-syntax-table)
-       (funcall (c-lang-const c++-make-template-syntax-table))))
+  (c-lang-const c++-template-syntax-table))
 
 (c-lang-defconst c-no-parens-syntax-table
   ;; A variant of the standard syntax table which is used to find matching
@@ -414,18 +381,17 @@
   ;; even when there's unbalanced other parens inside them.
   ;;
   ;; This variable is nil for languages which don't have template stuff.
-  t  `(lambda ()
-	(if (c-lang-const c-recognize-<>-arglists)
-	    (let ((table (funcall ,(c-lang-const c-make-mode-syntax-table))))
+  t  (if (c-lang-const c-recognize-<>-arglists)
+         (let ((table (funcall (c-lang-const c-make-mode-syntax-table))))
 	      (modify-syntax-entry ?\( "." table)
 	      (modify-syntax-entry ?\) "." table)
 	      (modify-syntax-entry ?\[ "." table)
 	      (modify-syntax-entry ?\] "." table)
 	      (modify-syntax-entry ?\{ "." table)
 	      (modify-syntax-entry ?\} "." table)
-	      table))))
+           table)))
 (c-lang-defvar c-no-parens-syntax-table
-	       (funcall (c-lang-const c-no-parens-syntax-table)))
+	       (c-lang-const c-no-parens-syntax-table))
 
 (c-lang-defconst c-identifier-syntax-modifications
   "A list that describes the modifications that should be done to the
@@ -1192,7 +1158,7 @@
 	 "=\\([^=]\\|$\\)"
 	 "\\|"
 	 (c-make-keywords-re nil
-	   (set-difference (c-lang-const c-assignment-operators)
+	   (cl-set-difference (c-lang-const c-assignment-operators)
 			   '("=")
 			   :test 'string-equal)))
       "\\<\\>"))
@@ -1244,7 +1210,7 @@
   ;; multicharacter tokens that begin with ">" except for those beginning with
   ;; ">>".
   t (c-make-keywords-re nil
-      (set-difference
+      (cl-set-difference
        (c-lang-const c->-op-cont-tokens)
        (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
 		     t
@@ -1387,7 +1353,6 @@
   ;; In C we still default to the block comment style since line
   ;; comments aren't entirely portable.
   c "/* ")
-(c-lang-setvar comment-start (c-lang-const comment-start))
 
 (c-lang-defconst comment-end
   "String that ends comments inserted with M-; etc.
@@ -1400,7 +1365,6 @@
 		      (c-lang-const comment-start))
 	(concat " " (c-lang-const c-block-comment-ender))
       ""))
-(c-lang-setvar comment-end (c-lang-const comment-end))
 
 (c-lang-defconst comment-start-skip
   "Regexp to match the start of a comment plus everything up to its body.
@@ -1416,7 +1380,6 @@
 			   (c-lang-const c-block-comment-starter)))
 	     "\\|")
 	    "\\)\\s *"))
-(c-lang-setvar comment-start-skip (c-lang-const comment-start-skip))
 
 (c-lang-defconst c-syntactic-ws-start
   ;; Regexp matching any sequence that can start syntactic whitespace.
@@ -1596,14 +1559,11 @@
   "Function to which beginning-of-defun-function will be set."
   t 'c-beginning-of-defun
   awk 'c-awk-beginning-of-defun)
-(c-lang-setvar beginning-of-defun-function
-	       (c-lang-const beginning-of-defun-function))
 
 (c-lang-defconst end-of-defun-function
   "Function to which end-of-defun-function will be set."
   t 'c-end-of-defun
   awk 'c-awk-end-of-defun)
-(c-lang-setvar end-of-defun-function (c-lang-const end-of-defun-function))
 \f
 ;;; In-comment text handling.
 
@@ -2018,7 +1978,7 @@
   ;; ambiguous with types or type prefixes.  These are the keywords (like
   ;; extern, namespace, but NOT template) that can modify a declaration.
   t (c-make-keywords-re t
-      (set-difference (c-lang-const c-prefix-spec-kwds)
+      (cl-set-difference (c-lang-const c-prefix-spec-kwds)
 		      (append (c-lang-const c-type-start-kwds)
 			      (c-lang-const c-<>-arglist-kwds))
 		      :test 'string-equal)))
@@ -2034,7 +1994,7 @@
   ;; Adorned regexp matching all keywords that can't appear at the
   ;; start of a declaration.
   t (c-make-keywords-re t
-      (set-difference (c-lang-const c-keywords)
+      (cl-set-difference (c-lang-const c-keywords)
 		      (append (c-lang-const c-type-start-kwds)
 			      (c-lang-const c-prefix-spec-kwds)
 			      (c-lang-const c-typeof-kwds))
@@ -2044,7 +2004,7 @@
 
 (c-lang-defconst c-not-primitive-type-keywords
   "List of all keywords apart from primitive types (like \"int\")."
-  t (set-difference (c-lang-const c-keywords)
+  t (cl-set-difference (c-lang-const c-keywords)
 		    (c-lang-const c-primitive-type-kwds)
 		    :test 'string-equal)
   ;; The "more" for C++ is the QT keyword (as in "more slots:").
@@ -2431,10 +2391,10 @@
   t (let* ((decl-kwds (append (c-lang-const c-class-decl-kwds)
 			      (c-lang-const c-other-block-decl-kwds)
 			      (c-lang-const c-inexpr-class-kwds)))
-	   (unambiguous (set-difference decl-kwds
+	   (unambiguous (cl-set-difference decl-kwds
 					(c-lang-const c-type-start-kwds)
 					:test 'string-equal))
-	   (ambiguous (intersection decl-kwds
+	   (ambiguous (cl-intersection decl-kwds
 				    (c-lang-const c-type-start-kwds)
 				    :test 'string-equal)))
       (if ambiguous
@@ -2469,27 +2429,24 @@
 
 ;; Note: No `*-kwds' language constants may be defined below this point.
 
-(eval-and-compile
-  (defconst c-kwds-lang-consts
+(defconst c-kwds-lang-consts
     ;; List of all the language constants that contain keyword lists.
     (let (list)
       (mapatoms (lambda (sym)
-		  (when (and (boundp sym)
+                (when (and ;; (boundp sym)
 			     (string-match "-kwds\\'" (symbol-name sym)))
 		    ;; Make the list of globally interned symbols
 		    ;; instead of ones interned in `c-lang-constants'.
 		    (setq list (cons (intern (symbol-name sym)) list))))
 		c-lang-constants)
-      list)))
+    list))
 
 (c-lang-defconst c-keywords
   ;; All keywords as a list.
   t (cl-delete-duplicates
-     (c-lang-defconst-eval-immediately
-      `(append ,@(mapcar (lambda (kwds-lang-const)
-			   `(c-lang-const ,kwds-lang-const))
-			 c-kwds-lang-consts)
-	       nil))
+     (apply #'append (mapcar (lambda (kwds-lang-const)
+                              (c-get-lang-constant kwds-lang-const))
+                            c-kwds-lang-consts))
      :test 'string-equal))
 
 (c-lang-defconst c-keywords-regexp
@@ -2501,18 +2458,10 @@
   ;; An alist with all the keywords in the cars.  The cdr for each
   ;; keyword is a list of the symbols for the `*-kwds' lists that
   ;; contains it.
-  t (let ((kwd-list-alist
-	   (c-lang-defconst-eval-immediately
-	    `(list ,@(mapcar (lambda (kwds-lang-const)
-			       `(cons ',kwds-lang-const
-				      (c-lang-const ,kwds-lang-const)))
-			     c-kwds-lang-consts))))
-	  lang-const kwd-list kwd
+  t (let (kwd-list kwd
 	  result-alist elem)
-      (while kwd-list-alist
-	(setq lang-const (caar kwd-list-alist)
-	      kwd-list (cdar kwd-list-alist)
-	      kwd-list-alist (cdr kwd-list-alist))
+      (dolist (lang-const c-kwds-lang-consts)
+	(setq kwd-list (c-get-lang-constant lang-const))
 	(while kwd-list
 	  (setq kwd (car kwd-list)
 		kwd-list (cdr kwd-list))
@@ -2560,7 +2509,7 @@
   ;; Adorned regexp matching all keywords that should be fontified
   ;; with the keywords face.  I.e. that aren't types or constants.
   t (c-make-keywords-re t
-      (set-difference (c-lang-const c-keywords)
+      (cl-set-difference (c-lang-const c-keywords)
 		      (append (c-lang-const c-primitive-type-kwds)
 			      (c-lang-const c-constant-kwds))
 		      :test 'string-equal)))
@@ -2598,12 +2547,13 @@
 			    right-assoc-sequence)
 			  t))
 
-	   (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops
-						   in-or-postfix-ops
-						   :test 'string-equal))
-	   (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops
-					       in-or-postfix-ops
-					       :test 'string-equal)))
+	   ;; (unambiguous-prefix-ops (cl-set-difference nonkeyword-prefix-ops
+	   ;;      				   in-or-postfix-ops
+	   ;;      				   :test 'string-equal))
+	   ;; (ambiguous-prefix-ops (cl-intersection nonkeyword-prefix-ops
+	   ;;      			       in-or-postfix-ops
+	   ;;      			       :test 'string-equal))
+           )
 
       (concat
        "\\("
@@ -2611,13 +2561,13 @@
        ;; first submatch from them together with `c-primary-expr-kwds'.
        (c-make-keywords-re t
 	 (append (c-lang-const c-primary-expr-kwds)
-		 (set-difference prefix-ops nonkeyword-prefix-ops
+		 (cl-set-difference prefix-ops nonkeyword-prefix-ops
 				 :test 'string-equal)))
 
        "\\|"
        ;; Match all ambiguous operators.
        (c-make-keywords-re nil
-	 (intersection nonkeyword-prefix-ops in-or-postfix-ops
+	 (cl-intersection nonkeyword-prefix-ops in-or-postfix-ops
 		       :test 'string-equal))
        "\\)"
 
@@ -2633,7 +2583,7 @@
        "\\|"
        ;; The unambiguous operators from `prefix-ops'.
        (c-make-keywords-re nil
-	 (set-difference nonkeyword-prefix-ops in-or-postfix-ops
+	 (cl-set-difference nonkeyword-prefix-ops in-or-postfix-ops
 			 :test 'string-equal))
 
        "\\|"
@@ -2779,7 +2729,7 @@
 
   ;; Default to all chars that only occurs in nonsymbol tokens outside
   ;; identifiers.
-  t (set-difference
+  t (cl-set-difference
      (c-lang-const c-nonsymbol-token-char-list)
      (c-filter-ops (append (c-lang-const c-identifier-ops)
 			   (list (cons nil
@@ -2796,25 +2746,25 @@
 
   ;; Allow cpp operations (where applicable).
   t (if (c-lang-const c-opt-cpp-prefix)
-	(set-difference (c-lang-const c-block-prefix-disallowed-chars)
+	(cl-set-difference (c-lang-const c-block-prefix-disallowed-chars)
 			'(?#))
       (c-lang-const c-block-prefix-disallowed-chars))
 
   ;; Allow ':' for inherit list starters.
-  (c++ objc idl) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+  (c++ objc idl) (cl-set-difference (c-lang-const c-block-prefix-disallowed-chars)
 				 '(?:))
 
   ;; Allow ',' for multiple inherits.
-  (c++ java) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+  (c++ java) (cl-set-difference (c-lang-const c-block-prefix-disallowed-chars)
 			     '(?,))
 
   ;; Allow parentheses for anonymous inner classes in Java and class
   ;; initializer lists in Pike.
-  (java pike) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+  (java pike) (cl-set-difference (c-lang-const c-block-prefix-disallowed-chars)
 			      '(?\( ?\)))
 
   ;; Allow '"' for extern clauses (e.g. extern "C" {...}).
-  (c c++ objc) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+  (c c++ objc) (cl-set-difference (c-lang-const c-block-prefix-disallowed-chars)
 			       '(?\" ?')))
 
 (c-lang-defconst c-block-prefix-charset
@@ -3121,7 +3071,7 @@
   t (concat
      ;; All keywords except `c-label-kwds' and `c-protection-kwds'.
      (c-make-keywords-re t
-       (set-difference (c-lang-const c-keywords)
+       (cl-set-difference (c-lang-const c-keywords)
 		       (append (c-lang-const c-label-kwds)
 			       (c-lang-const c-protection-kwds))
 		       :test 'string-equal)))
@@ -3201,123 +3151,47 @@
 \f
 ;;; Wrap up the `c-lang-defvar' system.
 
-;; Compile in the list of language variables that has been collected
-;; with the `c-lang-defvar' and `c-lang-setvar' macros.  Note that the
-;; first element of each is nil.
-(defconst c-lang-variable-inits (cc-eval-when-compile c-lang-variable-inits))
-(defconst c-emacs-variable-inits (cc-eval-when-compile c-emacs-variable-inits))
-
-;; Make the `c-lang-setvar' variables buffer local in the current buffer.
-;; These are typically standard emacs variables such as `comment-start'.
-(defmacro c-make-emacs-variables-local ()
-  `(progn
-     ,@(mapcar (lambda (init)
-		 `(make-local-variable ',(car init)))
-	       (cdr c-emacs-variable-inits))))
-
-(defun c-make-init-lang-vars-fun (mode)
-  "Create a function that initializes all the language dependent variables
-for the given mode.
-
-This function should be evaluated at compile time, so that the
-function it returns is byte compiled with all the evaluated results
-from the language constants.  Use the `c-init-language-vars' macro to
-accomplish that conveniently."
-
-  (if (and (not load-in-progress)
-	   (boundp 'byte-compile-dest-file)
-	   (stringp byte-compile-dest-file))
-
-      ;; No need to byte compile this lambda since the byte compiler is
-      ;; smart enough to detect the `funcall' construct in the
-      ;; `c-init-language-vars' macro below and compile it all straight
-      ;; into the function that contains `c-init-language-vars'.
-      `(lambda ()
-
-	 ;; This let sets up the context for `c-mode-var' and similar
-	 ;; that could be in the result from `macroexpand-all'.
-	 (let ((c-buffer-is-cc-mode ',mode)
-	       current-var source-eval)
-	   (c-make-emacs-variables-local)
-	   (condition-case err
-
-	       (if (eq c-version-sym ',c-version-sym)
-		   (setq ,@(let ((c-buffer-is-cc-mode mode)
-				 (c-lang-const-expansion 'immediate))
-			     ;; `c-lang-const' will expand to the evaluated
-			     ;; constant immediately in `macroexpand-all'
-			     ;; below.
-			      (cl-mapcan
-			       (lambda (init)
-				 `(current-var ',(car init)
-				   ,(car init) ,(macroexpand-all
-						 (elt init 1))))
-			       ;; Note: The following `append' copies the
-			       ;; first argument.  That list is small, so
-			       ;; this doesn't matter too much.
-			      (append (cdr c-emacs-variable-inits)
-				      (cdr c-lang-variable-inits)))))
-
-		 ;; This diagnostic message isn't useful for end
-		 ;; users, so it's disabled.
-		 ;;(unless (get ',mode 'c-has-warned-lang-consts)
-		 ;;  (message ,(concat "%s compiled with CC Mode %s "
-		 ;;		       "but loaded with %s - evaluating "
-		 ;;		       "language constants from source")
-		 ;;	      ',mode ,c-version c-version)
-		 ;;  (put ',mode 'c-has-warned-lang-consts t))
-
-		 (setq source-eval t)
-		 (let ((init ',(append (cdr c-emacs-variable-inits)
-				       (cdr c-lang-variable-inits))))
-		   (while init
-		     (setq current-var (caar init))
-		     (set (caar init) (eval (cadar init)))
-		     (setq init (cdr init)))))
-
-	     (error
-	      (if current-var
-		  (message "Eval error in the `c-lang-defvar' or `c-lang-setvar' for `%s'%s: %S"
-			   current-var
-			   (if source-eval
-			       (format "\
- (fallback source eval - %s compiled with CC Mode %s but loaded with %s)"
-				       ',mode ,c-version c-version)
-			     "")
-			   err)
-		(signal (car err) (cdr err)))))))
+(eval-when-compile
+  (unless (fboundp 'setq-local)
+    (defmacro setq-local (var val)
+      "Set variable VAR to value VAL in current buffer."
+      ;; Can't use backquote here, it's too early in the bootstrap.
+      (list 'set (list 'make-local-variable (list 'quote var)) val))))
+
+(defun c-emacs-variable-inits ()
+  (setq-local comment-start (c-lang-const comment-start))
+  (setq-local comment-end (c-lang-const comment-end))
+  (setq-local comment-start-skip (c-lang-const comment-start-skip))
+  (setq-local beginning-of-defun-function
+              (c-lang-const beginning-of-defun-function))
+  (setq-local end-of-defun-function (c-lang-const end-of-defun-function)))
 
-    ;; Being evaluated from source.  Always use the dynamic method to
-    ;; work well when `c-lang-defvar's in this file are reevaluated
-    ;; interactively.
-    `(lambda ()
-       (require 'cc-langs)
-       (let ((c-buffer-is-cc-mode ',mode)
-	     (init (append (cdr c-emacs-variable-inits)
-			   (cdr c-lang-variable-inits)))
+(defun c-init-language-vars-for (mode)
+  "Initialize all the language dependent variables for the given mode."
+  (let ((c-buffer-is-cc-mode mode)
 	     current-var)
-	 (c-make-emacs-variables-local)
+    (c-emacs-variable-inits)
 	 (condition-case err
-
-	     (while init
-	       (setq current-var (caar init))
-	       (set (caar init) (eval (cadar init)))
-	       (setq init (cdr init)))
-
+        (dolist (var c-lang--vars)
+          (setq current-var var)
+          (set (make-local-variable var)
+               (let ((f (get var 'c-initialize-function)))
+                 (if f (funcall f)
+                   (c-get-lang-constant var)))))
 	   (error
 	    (if current-var
 		(message
-		 "Eval error in the `c-lang-defvar' or `c-lang-setver' for `%s' (source eval): %S"
+            "Eval error in the `c-lang-defvar' for `%s': %S"
 		 current-var err)
 	      (signal (car err) (cdr err)))))))
-    ))
 
 (defmacro c-init-language-vars (mode)
   "Initialize all the language dependent variables for the given mode.
 This macro is expanded at compile time to a form tailored for the mode
 in question, so MODE must be a constant.  Therefore MODE is not
 evaluated and should not be quoted."
-  `(funcall ,(c-make-init-lang-vars-fun mode)))
+  (declare (obsolete c-init-language-vars-for "24.5"))
+  `(c-init-language-vars-for ',mode))
 
 \f
 (cc-provide 'cc-langs)

=== modified file 'lisp/progmodes/cc-mode.el'
--- lisp/progmodes/cc-mode.el	2014-03-04 04:03:34 +0000
+++ lisp/progmodes/cc-mode.el	2014-09-08 16:35:55 +0000
@@ -95,14 +95,9 @@
 (cc-require 'cc-menus)
 (cc-require 'cc-guess)
 
-;; Silence the compiler.
-(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs
-(cc-bytecomp-defun run-mode-hooks)	; Emacs 21.1
-
 ;; We set these variables during mode init, yet we don't require
 ;; font-lock.
-(cc-bytecomp-defvar font-lock-defaults)
-(cc-bytecomp-defvar font-lock-syntactic-keywords)
+(defvar font-lock-defaults)
 
 ;; Menu support for both XEmacs and Emacs.  If you don't have easymenu
 ;; with your version of Emacs, you are incompatible!
@@ -149,21 +144,6 @@
 (defun c-leave-cc-mode-mode ()
   (setq c-buffer-is-cc-mode nil))
 
-(defun c-init-language-vars-for (mode)
-  "Initialize the language variables for one of the language modes
-directly supported by CC Mode.  This can be used instead of the
-`c-init-language-vars' macro if the language you want to use is one of
-those, rather than a derived language defined through the language
-variable system (see \"cc-langs.el\")."
-  (cond ((eq mode 'c-mode)    (c-init-language-vars c-mode))
-	((eq mode 'c++-mode)  (c-init-language-vars c++-mode))
-	((eq mode 'objc-mode) (c-init-language-vars objc-mode))
-	((eq mode 'java-mode) (c-init-language-vars java-mode))
-	((eq mode 'idl-mode)  (c-init-language-vars idl-mode))
-	((eq mode 'pike-mode) (c-init-language-vars pike-mode))
-	((eq mode 'awk-mode)  (c-init-language-vars awk-mode))
-	(t (error "Unsupported mode %s" mode))))
-
 ;;;###autoload
 (defun c-initialize-cc-mode (&optional new-style-init)
   "Initialize CC Mode for use in the current buffer.
@@ -816,7 +796,7 @@
 (defmacro c-run-mode-hooks (&rest hooks)
   ;; Emacs 21.1 has introduced a system with delayed mode hooks that
   ;; requires the use of the new function `run-mode-hooks'.
-  (if (cc-bytecomp-fboundp 'run-mode-hooks)
+  (if (fboundp 'run-mode-hooks)
       `(run-mode-hooks ,@hooks)
     `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks))))
 
@@ -1232,8 +1212,8 @@
 	  (font-lock-mark-block-function
 	   . c-mark-function)))
 
-  (make-local-variable 'font-lock-fontify-region-function)
-  (setq font-lock-fontify-region-function 'c-font-lock-fontify-region)
+  (set (make-local-variable 'font-lock-fontify-region-function)
+       #'c-font-lock-fontify-region)
 
   (if (featurep 'xemacs)
       (make-local-hook 'font-lock-mode-hook))




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Avoiding loading cc-langs
  2014-09-08 18:45             ` Stefan Monnier
@ 2014-09-08 18:52               ` Glenn Morris
  0 siblings, 0 replies; 11+ messages in thread
From: Glenn Morris @ 2014-09-08 18:52 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: Alan Mackenzie, Alan Mackenzie, Martin Stjernholm, emacs-devel

Stefan Monnier wrote:

>> I really hope this can be simplified.
>
> This can be simplified, of course.  It does come with a performance
> cost, tho.

I meant: I really hope Alan will agree to such changes. :)

I think making cc-mode mode understandable is important, since this
would hopefully lead to more people being able/willing to work on it.



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-09-08 18:52 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-28 14:09 Ordering in `source' property, and auto-loading of c-lang-defconsts Stefan Monnier
2014-08-31 21:23 ` Alan Mackenzie
2014-09-01  0:52   ` Stefan Monnier
2014-09-01 22:43     ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Stefan Monnier
2014-09-04  2:38       ` Avoiding loading cc-langs Stefan Monnier
2014-09-06 11:10         ` Alan Mackenzie
2014-09-06 10:12       ` Avoiding loading cc-langs (was: Ordering in `source' property, and auto-loading of c-lang-defconsts) Alan Mackenzie
2014-09-08  1:51         ` Avoiding loading cc-langs Stefan Monnier
2014-09-08 15:46           ` Glenn Morris
2014-09-08 18:45             ` Stefan Monnier
2014-09-08 18:52               ` Glenn Morris

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).