aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2011-12-13 18:47:08 +0000
committerAlan Mackenzie2011-12-13 18:47:08 +0000
commit13d49cbb266f0ead789944508ad0872129885609 (patch)
treea8515a60dfcd07275049cf07cc2ad9d68e2ad5dc
parent15e0efc7dc8e01b9416def38bc1f18fdabe70256 (diff)
downloademacs-13d49cbb266f0ead789944508ad0872129885609.tar.gz
emacs-13d49cbb266f0ead789944508ad0872129885609.zip
Large brace-block initialisation makes CC Mode slow: Fix.
Tidy up and accelerate c-in-literal, etc. by using the c-parse-state routines. Limit backward searching in c-font-lock-enclosing.decl. cc-engine.el (c-state-pp-to-literal): Return the pp-state and literal type in addition to the limits. (c-state-safe-place): New defun, extracted from c-state-literal-at. (c-state-literal-at): Use the above new defun. (c-slow-in-literal, c-fast-in-literal): Removed. (c-in-literal, c-literal-limits): Amended to use c-state-pp-to-literal. cc-fonts.el (c-font-lock-enclosing-decls): Check for being in a literal. Add a limit for backward searching. cc-mode.el (awk-mode): Don't alias c-in-literal to c-slow-in-literal.
-rw-r--r--lisp/ChangeLog22
-rw-r--r--lisp/progmodes/cc-engine.el230
-rw-r--r--lisp/progmodes/cc-fonts.el3
-rw-r--r--lisp/progmodes/cc-mode.el4
4 files changed, 116 insertions, 143 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index cc48e86efe3..f338462b2be 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,25 @@
12011-12-13 Alan Mackenzie <acm@muc.de>
2
3 Large brace-block initialisation makes CC Mode slow: Fix.
4 Tidy up and accelerate c-in-literal, etc. by using the
5 c-parse-state
6 routines. Limit backward searching in c-font-lock-enclosing.decl.
7
8 * progmodes/cc-engine.el (c-state-pp-to-literal): Return the
9 pp-state and literal type in addition to the limits.
10 (c-state-safe-place): New defun, extracted from
11 c-state-literal-at.
12 (c-state-literal-at): Use the above new defun.
13 (c-slow-in-literal, c-fast-in-literal): Removed.
14 (c-in-literal, c-literal-limits): Amended to use
15 c-state-pp-to-literal.
16
17 * progmodes/cc-fonts.el (c-font-lock-enclosing-decls): Check for
18 being in a literal. Add a limit for backward searching.
19
20 * progmodes/cc-mode.el (awk-mode): Don't alias c-in-literal to
21 c-slow-in-literal.
22
12011-12-13 Stefan Monnier <monnier@iro.umontreal.ca> 232011-12-13 Stefan Monnier <monnier@iro.umontreal.ca>
2 24
3 * progmodes/pascal.el: Declare `ind' as dyn-bound (bug#10264). 25 * progmodes/pascal.el: Declare `ind' as dyn-bound (bug#10264).
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 28e7ffae40e..0865ddfed69 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -195,9 +195,6 @@
195 (not prevstate) 195 (not prevstate)
196 (> arg 0))) 196 (> arg 0)))
197 197
198;; Dynamically bound cache for `c-in-literal'.
199(defvar c-in-literal-cache t)
200
201 198
202;; Basic handling of preprocessor directives. 199;; Basic handling of preprocessor directives.
203 200
@@ -2093,28 +2090,35 @@ comment at the start of cc-engine.el for more info."
2093;; `c-state-literal-at'. 2090;; `c-state-literal-at'.
2094 2091
2095(defsubst c-state-pp-to-literal (from to) 2092(defsubst c-state-pp-to-literal (from to)
2096 ;; Do a parse-partial-sexp from FROM to TO, returning the bounds of any 2093 ;; Do a parse-partial-sexp from FROM to TO, returning either
2097 ;; literal at TO as a cons, otherwise NIL. 2094 ;; (STATE TYPE (BEG . END)) if TO is in a literal; or
2098 ;; FROM must not be in a literal, and the buffer should already be wide 2095 ;; (STATE) otherwise,
2099 ;; enough. 2096 ;; where STATE is the parsing state at TO, TYPE is the type of the literal
2097 ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
2098 ;;
2099 ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote),
2100 ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
2101 ;; STATE are valid.
2100 (save-excursion 2102 (save-excursion
2101 (let ((s (parse-partial-sexp from to))) 2103 (let ((s (parse-partial-sexp from to))
2104 ty)
2102 (when (or (nth 3 s) (nth 4 s)) ; in a string or comment 2105 (when (or (nth 3 s) (nth 4 s)) ; in a string or comment
2106 (setq ty (cond
2107 ((nth 3 s) 'string)
2108 ((eq (nth 7 s) t) 'c++)
2109 (t 'c)))
2103 (parse-partial-sexp (point) (point-max) 2110 (parse-partial-sexp (point) (point-max)
2104 nil ; TARGETDEPTH 2111 nil ; TARGETDEPTH
2105 nil ; STOPBEFORE 2112 nil ; STOPBEFORE
2106 s ; OLDSTATE 2113 s ; OLDSTATE
2107 'syntax-table) ; stop at end of literal 2114 'syntax-table)) ; stop at end of literal
2108 (cons (nth 8 s) (point)))))) 2115 (if ty
2116 `(,s ,ty (,(nth 8 s) . ,(point)))
2117 `(,s)))))
2109 2118
2110(defun c-state-literal-at (here) 2119(defun c-state-safe-place (here)
2111 ;; If position HERE is inside a literal, return (START . END), the 2120 ;; Return a buffer position before HERE which is "safe", i.e. outside any
2112 ;; boundaries of the literal (which may be outside the accessible bit of the 2121 ;; string, comment, or macro.
2113 ;; buffer). Otherwise, return nil.
2114 ;;
2115 ;; This function is almost the same as `c-literal-limits'. It differs in
2116 ;; that it is a lower level function, and that it rigorously follows the
2117 ;; syntax from BOB, whereas `c-literal-limits' uses a "local" safe position.
2118 ;; 2122 ;;
2119 ;; NOTE: This function manipulates `c-state-nonlit-pos-cache'. This cache 2123 ;; NOTE: This function manipulates `c-state-nonlit-pos-cache'. This cache
2120 ;; MAY NOT contain any positions within macros, since macros are frequently 2124 ;; MAY NOT contain any positions within macros, since macros are frequently
@@ -2137,7 +2141,7 @@ comment at the start of cc-engine.el for more info."
2137 2141
2138 (while (<= (setq npos (+ pos c-state-nonlit-pos-interval)) 2142 (while (<= (setq npos (+ pos c-state-nonlit-pos-interval))
2139 here) 2143 here)
2140 (setq lit (c-state-pp-to-literal pos npos)) 2144 (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
2141 (setq pos (or (cdr lit) npos)) ; end of literal containing npos. 2145 (setq pos (or (cdr lit) npos)) ; end of literal containing npos.
2142 (goto-char pos) 2146 (goto-char pos)
2143 (when (and (c-beginning-of-macro) (/= (point) pos)) 2147 (when (and (c-beginning-of-macro) (/= (point) pos))
@@ -2148,9 +2152,22 @@ comment at the start of cc-engine.el for more info."
2148 2152
2149 (if (> pos c-state-nonlit-pos-cache-limit) 2153 (if (> pos c-state-nonlit-pos-cache-limit)
2150 (setq c-state-nonlit-pos-cache-limit pos)) 2154 (setq c-state-nonlit-pos-cache-limit pos))
2151 (if (< pos here) 2155 pos))))
2152 (setq lit (c-state-pp-to-literal pos here))) 2156
2153 lit)))) 2157(defun c-state-literal-at (here)
2158 ;; If position HERE is inside a literal, return (START . END), the
2159 ;; boundaries of the literal (which may be outside the accessible bit of the
2160 ;; buffer). Otherwise, return nil.
2161 ;;
2162 ;; This function is almost the same as `c-literal-limits'. Previously, it
2163 ;; differed in that it was a lower level function, and that it rigourously
2164 ;; followed the syntax from BOB. `c-literal-limits' is now (2011-12)
2165 ;; virtually identical to this function.
2166 (save-restriction
2167 (widen)
2168 (save-excursion
2169 (let ((pos (c-state-safe-place here)))
2170 (car (cddr (c-state-pp-to-literal pos here)))))))
2154 2171
2155(defsubst c-state-lit-beg (pos) 2172(defsubst c-state-lit-beg (pos)
2156 ;; Return the start of the literal containing POS, or POS itself. 2173 ;; Return the start of the literal containing POS, or POS itself.
@@ -4181,7 +4198,7 @@ comment at the start of cc-engine.el for more info."
4181 4198
4182;; Tools for handling comments and string literals. 4199;; Tools for handling comments and string literals.
4183 4200
4184(defun c-slow-in-literal (&optional lim detect-cpp) 4201(defun c-in-literal (&optional lim detect-cpp)
4185 "Return the type of literal point is in, if any. 4202 "Return the type of literal point is in, if any.
4186The return value is `c' if in a C-style comment, `c++' if in a C++ 4203The return value is `c' if in a C-style comment, `c++' if in a C++
4187style comment, `string' if in a string literal, `pound' if DETECT-CPP 4204style comment, `string' if in a string literal, `pound' if DETECT-CPP
@@ -4194,67 +4211,12 @@ The last point calculated is cached if the cache is enabled, i.e. if
4194 4211
4195Note that this function might do hidden buffer changes. See the 4212Note that this function might do hidden buffer changes. See the
4196comment at the start of cc-engine.el for more info." 4213comment at the start of cc-engine.el for more info."
4197 4214 (let* ((safe-place (c-state-safe-place (point)))
4198 (if (and (vectorp c-in-literal-cache) 4215 (lit (c-state-pp-to-literal safe-place (point))))
4199 (= (point) (aref c-in-literal-cache 0))) 4216 (or (cadr lit)
4200 (aref c-in-literal-cache 1) 4217 (and detect-cpp
4201 (let ((rtn (save-excursion 4218 (save-excursion (c-beginning-of-macro))
4202 (let* ((pos (point)) 4219 'pound))))
4203 (lim (or lim (progn
4204 (c-beginning-of-syntax)
4205 (point))))
4206 (state (parse-partial-sexp lim pos)))
4207 (cond
4208 ((elt state 3) 'string)
4209 ((elt state 4) (if (elt state 7) 'c++ 'c))
4210 ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
4211 (t nil))))))
4212 ;; cache this result if the cache is enabled
4213 (if (not c-in-literal-cache)
4214 (setq c-in-literal-cache (vector (point) rtn)))
4215 rtn)))
4216
4217;; XEmacs has a built-in function that should make this much quicker.
4218;; I don't think we even need the cache, which makes our lives more
4219;; complicated anyway. In this case, lim is only used to detect
4220;; cpp directives.
4221;;
4222;; Note that there is a bug in XEmacs's buffer-syntactic-context when used in
4223;; conjunction with syntax-table-properties. The bug is present in, e.g.,
4224;; XEmacs 21.4.4. It manifested itself thus:
4225;;
4226;; Starting with an empty AWK Mode buffer, type
4227;; /regexp/ {<C-j>
4228;; Point gets wrongly left at column 0, rather than being indented to tab-width.
4229;;
4230;; AWK Mode is designed such that when the first / is typed, it gets the
4231;; syntax-table property "string fence". When the second / is typed, BOTH /s
4232;; are given the s-t property "string". However, buffer-syntactic-context
4233;; fails to take account of the change of the s-t property on the opening / to
4234;; "string", and reports that the { is within a string started by the second /.
4235;;
4236;; The workaround for this is for the AWK Mode initialization to switch the
4237;; defalias for c-in-literal to c-slow-in-literal. This will slow down other
4238;; cc-modes in XEmacs whenever an awk-buffer has been initialized.
4239;;
4240;; (Alan Mackenzie, 2003/4/30).
4241
4242(defun c-fast-in-literal (&optional lim detect-cpp)
4243 ;; This function might do hidden buffer changes.
4244 (let ((context (buffer-syntactic-context)))
4245 (cond
4246 ((eq context 'string) 'string)
4247 ((eq context 'comment) 'c++)
4248 ((eq context 'block-comment) 'c)
4249 ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound))))
4250
4251(defalias 'c-in-literal
4252 (if (fboundp 'buffer-syntactic-context)
4253 'c-fast-in-literal ; XEmacs
4254 'c-slow-in-literal)) ; GNU Emacs
4255
4256;; The defalias above isn't enough to shut up the byte compiler.
4257(cc-bytecomp-defun c-in-literal)
4258 4220
4259(defun c-literal-limits (&optional lim near not-in-delimiter) 4221(defun c-literal-limits (&optional lim near not-in-delimiter)
4260 "Return a cons of the beginning and end positions of the comment or 4222 "Return a cons of the beginning and end positions of the comment or
@@ -4273,64 +4235,56 @@ comment at the start of cc-engine.el for more info."
4273 4235
4274 (save-excursion 4236 (save-excursion
4275 (let* ((pos (point)) 4237 (let* ((pos (point))
4276 (lim (or lim (progn 4238 (lim (or lim (c-state-safe-place pos)))
4277 (c-beginning-of-syntax) 4239 (pp-to-lit (c-state-pp-to-literal lim pos))
4278 (point)))) 4240 (state (car pp-to-lit))
4279 (state (parse-partial-sexp lim pos))) 4241 (lit-type (cadr pp-to-lit))
4280 4242 (lit-limits (car (cddr pp-to-lit))))
4281 (cond ((elt state 3) ; String.
4282 (goto-char (elt state 8))
4283 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
4284 (point-max))))
4285
4286 ((elt state 4) ; Comment.
4287 (goto-char (elt state 8))
4288 (cons (point) (progn (c-forward-single-comment) (point))))
4289
4290 ((and (not not-in-delimiter)
4291 (not (elt state 5))
4292 (eq (char-before) ?/)
4293 (looking-at "[/*]"))
4294 ;; We're standing in a comment starter.
4295 (backward-char 1)
4296 (cons (point) (progn (c-forward-single-comment) (point))))
4297
4298 (near
4299 (goto-char pos)
4300
4301 ;; Search forward for a literal.
4302 (skip-chars-forward " \t")
4303 4243
4304 (cond 4244 (cond
4305 ((looking-at c-string-limit-regexp) ; String. 4245 (lit-limits)
4306 (cons (point) (or (c-safe (c-forward-sexp 1) (point)) 4246 ((and (not not-in-delimiter)
4307 (point-max)))) 4247 (not (elt state 5))
4248 (eq (char-before) ?/)
4249 (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter. 2008-09-28.
4250 ;; We're standing in a comment starter.
4251 (backward-char 1)
4252 (cons (point) (progn (c-forward-single-comment) (point))))
4253
4254 (near
4255 (goto-char pos)
4256 ;; Search forward for a literal.
4257 (skip-chars-forward " \t")
4258 (cond
4259 ((looking-at c-string-limit-regexp) ; String.
4260 (cons (point) (or (c-safe (c-forward-sexp 1) (point))
4261 (point-max))))
4308 4262
4309 ((looking-at c-comment-start-regexp) ; Line or block comment. 4263 ((looking-at c-comment-start-regexp) ; Line or block comment.
4310 (cons (point) (progn (c-forward-single-comment) (point)))) 4264 (cons (point) (progn (c-forward-single-comment) (point))))
4311 4265
4312 (t 4266 (t
4313 ;; Search backward. 4267 ;; Search backward.
4314 (skip-chars-backward " \t") 4268 (skip-chars-backward " \t")
4315 4269
4316 (let ((end (point)) beg) 4270 (let ((end (point)) beg)
4317 (cond 4271 (cond
4318 ((save-excursion 4272 ((save-excursion
4319 (< (skip-syntax-backward c-string-syntax) 0)) ; String. 4273 (< (skip-syntax-backward c-string-syntax) 0)) ; String.
4320 (setq beg (c-safe (c-backward-sexp 1) (point)))) 4274 (setq beg (c-safe (c-backward-sexp 1) (point))))
4321 4275
4322 ((and (c-safe (forward-char -2) t) 4276 ((and (c-safe (forward-char -2) t)
4323 (looking-at "*/")) 4277 (looking-at "*/"))
4324 ;; Block comment. Due to the nature of line 4278 ;; Block comment. Due to the nature of line
4325 ;; comments, they will always be covered by the 4279 ;; comments, they will always be covered by the
4326 ;; normal case above. 4280 ;; normal case above.
4327 (goto-char end) 4281 (goto-char end)
4328 (c-backward-single-comment) 4282 (c-backward-single-comment)
4329 ;; If LIM is bogus, beg will be bogus. 4283 ;; If LIM is bogus, beg will be bogus.
4330 (setq beg (point)))) 4284 (setq beg (point))))
4331 4285
4332 (if beg (cons beg end)))))) 4286 (if beg (cons beg end))))))
4333 )))) 4287 ))))
4334 4288
4335;; In case external callers use this; it did have a docstring. 4289;; In case external callers use this; it did have a docstring.
4336(defalias 'c-literal-limits-fast 'c-literal-limits) 4290(defalias 'c-literal-limits-fast 'c-literal-limits)
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index c18789de07b..c6c8bd107f6 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1539,10 +1539,11 @@ casts and declarations are fontified. Used on level 2 and higher."
1539 ;; Fontification". 1539 ;; Fontification".
1540 (let* ((paren-state (c-parse-state)) 1540 (let* ((paren-state (c-parse-state))
1541 (start (point)) 1541 (start (point))
1542 (bod-lim (max (- (point) 500) (point-min)))
1542 decl-context bo-decl in-typedef type-type ps-elt) 1543 decl-context bo-decl in-typedef type-type ps-elt)
1543 1544
1544 ;; First, are we actually in a "local" declaration? 1545 ;; First, are we actually in a "local" declaration?
1545 (setq decl-context (c-beginning-of-decl-1) 1546 (setq decl-context (c-beginning-of-decl-1 bod-lim)
1546 bo-decl (point) 1547 bo-decl (point)
1547 in-typedef (looking-at c-typedef-key)) 1548 in-typedef (looking-at c-typedef-key))
1548 (if in-typedef (c-forward-token-2)) 1549 (if in-typedef (c-forward-token-2))
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 6a40378935c..36b95f4b3f5 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1562,10 +1562,6 @@ Key bindings:
1562 (c-common-init 'awk-mode) 1562 (c-common-init 'awk-mode)
1563 (c-awk-unstick-NL-prop) 1563 (c-awk-unstick-NL-prop)
1564 1564
1565 ;; Prevent XEmacs's buffer-syntactic-context being used. See the comment
1566 ;; in cc-engine.el, just before (defun c-fast-in-literal ...
1567 (defalias 'c-in-literal 'c-slow-in-literal)
1568
1569 (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) 1565 (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook)
1570 (c-update-modeline)) 1566 (c-update-modeline))
1571 1567