diff options
author | Alan Mackenzie <acm@muc.de> | 2011-12-13 18:47:08 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2011-12-13 18:47:08 +0000 |
commit | 13d49cbb266f0ead789944508ad0872129885609 (patch) | |
tree | a8515a60dfcd07275049cf07cc2ad9d68e2ad5dc /lisp | |
parent | 15e0efc7dc8e01b9416def38bc1f18fdabe70256 (diff) | |
download | emacs-13d49cbb266f0ead789944508ad0872129885609.tar.gz |
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.
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/ChangeLog | 22 | ||||
-rw-r--r-- | lisp/progmodes/cc-engine.el | 230 | ||||
-rw-r--r-- | lisp/progmodes/cc-fonts.el | 3 | ||||
-rw-r--r-- | lisp/progmodes/cc-mode.el | 4 |
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 @@ +2011-12-13 Alan Mackenzie <acm@muc.de> + + 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. + + * progmodes/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. + + * progmodes/cc-fonts.el (c-font-lock-enclosing-decls): Check for + being in a literal. Add a limit for backward searching. + + * progmodes/cc-mode.el (awk-mode): Don't alias c-in-literal to + c-slow-in-literal. + 2011-12-13 Stefan Monnier <monnier@iro.umontreal.ca> * 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 @@ (not prevstate) (> arg 0))) -;; Dynamically bound cache for `c-in-literal'. -(defvar c-in-literal-cache t) - ;; Basic handling of preprocessor directives. @@ -2093,28 +2090,35 @@ comment at the start of cc-engine.el for more info." ;; `c-state-literal-at'. (defsubst c-state-pp-to-literal (from to) - ;; Do a parse-partial-sexp from FROM to TO, returning the bounds of any - ;; literal at TO as a cons, otherwise NIL. - ;; FROM must not be in a literal, and the buffer should already be wide - ;; enough. + ;; Do a parse-partial-sexp from FROM to TO, returning either + ;; (STATE TYPE (BEG . END)) if TO is in a literal; or + ;; (STATE) otherwise, + ;; where STATE is the parsing state at TO, TYPE is the type of the literal + ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal. + ;; + ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), + ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of + ;; STATE are valid. (save-excursion - (let ((s (parse-partial-sexp from to))) + (let ((s (parse-partial-sexp from to)) + ty) (when (or (nth 3 s) (nth 4 s)) ; in a string or comment + (setq ty (cond + ((nth 3 s) 'string) + ((eq (nth 7 s) t) 'c++) + (t 'c))) (parse-partial-sexp (point) (point-max) nil ; TARGETDEPTH nil ; STOPBEFORE s ; OLDSTATE - 'syntax-table) ; stop at end of literal - (cons (nth 8 s) (point)))))) + 'syntax-table)) ; stop at end of literal + (if ty + `(,s ,ty (,(nth 8 s) . ,(point))) + `(,s))))) -(defun c-state-literal-at (here) - ;; If position HERE is inside a literal, return (START . END), the - ;; boundaries of the literal (which may be outside the accessible bit of the - ;; buffer). Otherwise, return nil. - ;; - ;; This function is almost the same as `c-literal-limits'. It differs in - ;; that it is a lower level function, and that it rigorously follows the - ;; syntax from BOB, whereas `c-literal-limits' uses a "local" safe position. +(defun c-state-safe-place (here) + ;; Return a buffer position before HERE which is "safe", i.e. outside any + ;; string, comment, or macro. ;; ;; NOTE: This function manipulates `c-state-nonlit-pos-cache'. This cache ;; 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." (while (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) - (setq lit (c-state-pp-to-literal pos npos)) + (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) (setq pos (or (cdr lit) npos)) ; end of literal containing npos. (goto-char pos) (when (and (c-beginning-of-macro) (/= (point) pos)) @@ -2148,9 +2152,22 @@ comment at the start of cc-engine.el for more info." (if (> pos c-state-nonlit-pos-cache-limit) (setq c-state-nonlit-pos-cache-limit pos)) - (if (< pos here) - (setq lit (c-state-pp-to-literal pos here))) - lit)))) + pos)))) + +(defun c-state-literal-at (here) + ;; If position HERE is inside a literal, return (START . END), the + ;; boundaries of the literal (which may be outside the accessible bit of the + ;; buffer). Otherwise, return nil. + ;; + ;; This function is almost the same as `c-literal-limits'. Previously, it + ;; differed in that it was a lower level function, and that it rigourously + ;; followed the syntax from BOB. `c-literal-limits' is now (2011-12) + ;; virtually identical to this function. + (save-restriction + (widen) + (save-excursion + (let ((pos (c-state-safe-place here))) + (car (cddr (c-state-pp-to-literal pos here))))))) (defsubst c-state-lit-beg (pos) ;; 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." ;; Tools for handling comments and string literals. -(defun c-slow-in-literal (&optional lim detect-cpp) +(defun c-in-literal (&optional lim detect-cpp) "Return the type of literal point is in, if any. The return value is `c' if in a C-style comment, `c++' if in a C++ style 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 Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." - - (if (and (vectorp c-in-literal-cache) - (= (point) (aref c-in-literal-cache 0))) - (aref c-in-literal-cache 1) - (let ((rtn (save-excursion - (let* ((pos (point)) - (lim (or lim (progn - (c-beginning-of-syntax) - (point)))) - (state (parse-partial-sexp lim pos))) - (cond - ((elt state 3) 'string) - ((elt state 4) (if (elt state 7) 'c++ 'c)) - ((and detect-cpp (c-beginning-of-macro lim)) 'pound) - (t nil)))))) - ;; cache this result if the cache is enabled - (if (not c-in-literal-cache) - (setq c-in-literal-cache (vector (point) rtn))) - rtn))) - -;; XEmacs has a built-in function that should make this much quicker. -;; I don't think we even need the cache, which makes our lives more -;; complicated anyway. In this case, lim is only used to detect -;; cpp directives. -;; -;; Note that there is a bug in XEmacs's buffer-syntactic-context when used in -;; conjunction with syntax-table-properties. The bug is present in, e.g., -;; XEmacs 21.4.4. It manifested itself thus: -;; -;; Starting with an empty AWK Mode buffer, type -;; /regexp/ {<C-j> -;; Point gets wrongly left at column 0, rather than being indented to tab-width. -;; -;; AWK Mode is designed such that when the first / is typed, it gets the -;; syntax-table property "string fence". When the second / is typed, BOTH /s -;; are given the s-t property "string". However, buffer-syntactic-context -;; fails to take account of the change of the s-t property on the opening / to -;; "string", and reports that the { is within a string started by the second /. -;; -;; The workaround for this is for the AWK Mode initialization to switch the -;; defalias for c-in-literal to c-slow-in-literal. This will slow down other -;; cc-modes in XEmacs whenever an awk-buffer has been initialized. -;; -;; (Alan Mackenzie, 2003/4/30). - -(defun c-fast-in-literal (&optional lim detect-cpp) - ;; This function might do hidden buffer changes. - (let ((context (buffer-syntactic-context))) - (cond - ((eq context 'string) 'string) - ((eq context 'comment) 'c++) - ((eq context 'block-comment) 'c) - ((and detect-cpp (save-excursion (c-beginning-of-macro lim))) 'pound)))) - -(defalias 'c-in-literal - (if (fboundp 'buffer-syntactic-context) - 'c-fast-in-literal ; XEmacs - 'c-slow-in-literal)) ; GNU Emacs - -;; The defalias above isn't enough to shut up the byte compiler. -(cc-bytecomp-defun c-in-literal) + (let* ((safe-place (c-state-safe-place (point))) + (lit (c-state-pp-to-literal safe-place (point)))) + (or (cadr lit) + (and detect-cpp + (save-excursion (c-beginning-of-macro)) + 'pound)))) (defun c-literal-limits (&optional lim near not-in-delimiter) "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." (save-excursion (let* ((pos (point)) - (lim (or lim (progn - (c-beginning-of-syntax) - (point)))) - (state (parse-partial-sexp lim pos))) - - (cond ((elt state 3) ; String. - (goto-char (elt state 8)) - (cons (point) (or (c-safe (c-forward-sexp 1) (point)) - (point-max)))) - - ((elt state 4) ; Comment. - (goto-char (elt state 8)) - (cons (point) (progn (c-forward-single-comment) (point)))) - - ((and (not not-in-delimiter) - (not (elt state 5)) - (eq (char-before) ?/) - (looking-at "[/*]")) - ;; We're standing in a comment starter. - (backward-char 1) - (cons (point) (progn (c-forward-single-comment) (point)))) - - (near - (goto-char pos) - - ;; Search forward for a literal. - (skip-chars-forward " \t") + (lim (or lim (c-state-safe-place pos))) + (pp-to-lit (c-state-pp-to-literal lim pos)) + (state (car pp-to-lit)) + (lit-type (cadr pp-to-lit)) + (lit-limits (car (cddr pp-to-lit)))) - (cond - ((looking-at c-string-limit-regexp) ; String. - (cons (point) (or (c-safe (c-forward-sexp 1) (point)) - (point-max)))) + (cond + (lit-limits) + ((and (not not-in-delimiter) + (not (elt state 5)) + (eq (char-before) ?/) + (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter. 2008-09-28. + ;; We're standing in a comment starter. + (backward-char 1) + (cons (point) (progn (c-forward-single-comment) (point)))) + + (near + (goto-char pos) + ;; Search forward for a literal. + (skip-chars-forward " \t") + (cond + ((looking-at c-string-limit-regexp) ; String. + (cons (point) (or (c-safe (c-forward-sexp 1) (point)) + (point-max)))) - ((looking-at c-comment-start-regexp) ; Line or block comment. - (cons (point) (progn (c-forward-single-comment) (point)))) + ((looking-at c-comment-start-regexp) ; Line or block comment. + (cons (point) (progn (c-forward-single-comment) (point)))) - (t - ;; Search backward. - (skip-chars-backward " \t") + (t + ;; Search backward. + (skip-chars-backward " \t") - (let ((end (point)) beg) - (cond - ((save-excursion - (< (skip-syntax-backward c-string-syntax) 0)) ; String. - (setq beg (c-safe (c-backward-sexp 1) (point)))) - - ((and (c-safe (forward-char -2) t) - (looking-at "*/")) - ;; Block comment. Due to the nature of line - ;; comments, they will always be covered by the - ;; normal case above. - (goto-char end) - (c-backward-single-comment) - ;; If LIM is bogus, beg will be bogus. - (setq beg (point)))) - - (if beg (cons beg end)))))) - )))) + (let ((end (point)) beg) + (cond + ((save-excursion + (< (skip-syntax-backward c-string-syntax) 0)) ; String. + (setq beg (c-safe (c-backward-sexp 1) (point)))) + + ((and (c-safe (forward-char -2) t) + (looking-at "*/")) + ;; Block comment. Due to the nature of line + ;; comments, they will always be covered by the + ;; normal case above. + (goto-char end) + (c-backward-single-comment) + ;; If LIM is bogus, beg will be bogus. + (setq beg (point)))) + + (if beg (cons beg end)))))) + )))) ;; In case external callers use this; it did have a docstring. (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." ;; Fontification". (let* ((paren-state (c-parse-state)) (start (point)) + (bod-lim (max (- (point) 500) (point-min))) decl-context bo-decl in-typedef type-type ps-elt) ;; First, are we actually in a "local" declaration? - (setq decl-context (c-beginning-of-decl-1) + (setq decl-context (c-beginning-of-decl-1 bod-lim) bo-decl (point) in-typedef (looking-at c-typedef-key)) (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: (c-common-init 'awk-mode) (c-awk-unstick-NL-prop) - ;; Prevent XEmacs's buffer-syntactic-context being used. See the comment - ;; in cc-engine.el, just before (defun c-fast-in-literal ... - (defalias 'c-in-literal 'c-slow-in-literal) - (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) (c-update-modeline)) |