From 99bc4af9c883d0faa5a1387cb26c1cbf09feb958 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sat, 1 Jun 2019 20:08:27 +0000 Subject: [PATCH] * lisp/progmodes/cc-engine.el: Permute certain literal cacheing functions --- lisp/progmodes/cc-engine.el | 547 ++++++++++++++++++------------------ 1 file changed, 276 insertions(+), 271 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index b9d4f83f256..337271b2e67 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -2470,88 +2470,40 @@ comment at the start of cc-engine.el for more info." (c-skip-ws-forward end+1) (eq (point) end+1)))))) -;; A system for finding noteworthy parens before the point. - -(defconst c-state-cache-too-far 5000) -;; A maximum comfortable scanning distance, e.g. between -;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When -;; this distance is exceeded, we take "emergency measures", e.g. by clearing -;; the cache and starting again from point-min or a beginning of defun. This -;; value can be tuned for efficiency or set to a lower value for testing. - -(defvar c-state-cache nil) -(make-variable-buffer-local 'c-state-cache) -;; The state cache used by `c-parse-state' to cut down the amount of -;; searching. It's the result from some earlier `c-parse-state' call. See -;; `c-parse-state''s doc string for details of its structure. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; We maintain a sopisticated cache of positions which are in a literal, +;; disregarding macros (i.e. we don't distinguish between "in a macro" and +;; not). ;; -;; The use of the cached info is more effective if the next -;; `c-parse-state' call is on a line close by the one the cached state -;; was made at; the cache can actually slow down a little if the -;; cached state was made very far back in the buffer. The cache is -;; most effective if `c-parse-state' is used on each line while moving -;; forward. - -(defvar c-state-cache-good-pos 1) -(make-variable-buffer-local 'c-state-cache-good-pos) -;; This is a position where `c-state-cache' is known to be correct, or -;; nil (see below). It's a position inside one of the recorded unclosed -;; parens or the top level, but not further nested inside any literal or -;; subparen that is closed before the last recorded position. +;; This cache is in three parts: two "near" caches, which are association +;; lists of a small number (currently six) of positions and the parser states +;; there; the "far" cache (also known as "the cache"), a list of compressed +;; parser states going back to the beginning of the buffer, one entry every +;; 3000 characters. ;; -;; The exact position is chosen to try to be close to yet earlier than -;; the position where `c-state-cache' will be called next. Right now -;; the heuristic is to set it to the position after the last found -;; closing paren (of any type) before the line on which -;; `c-parse-state' was called. That is chosen primarily to work well -;; with refontification of the current line. +;; The two main callable functions embodying this cache are +;; `c-semi-pp-to-literal', which returns a `parse-partial-sexp' state at a +;; given position, together with the start of any literal enclosing it, and +;; `c-full-pp-to-literal', which additionally returns the end of such literal. +;; One of the above "near" caches is associated with each of these functions. ;; -;; 2009-07-28: When `c-state-point-min' and the last position where -;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are -;; both in the same literal, there is no such "good position", and -;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which -;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil. +;; When searching this cache, these functions first seek an exact match, then +;; a "close" match from the assiciated near cache. If neither of these +;; succeed, the nearest preceding entry in the far cache is used. ;; -;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in -;; the middle of the desert, as long as it is not within a brace pair -;; recorded in `c-state-cache' or a paren/bracket pair. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; We maintain a simple cache of positions which aren't in a literal, so as to -;; speed up testing for non-literality. -(defconst c-state-nonlit-pos-interval 3000) -;; The approximate interval between entries in `c-state-nonlit-pos-cache'. -(defvar c-state-nonlit-pos-cache nil) -(make-variable-buffer-local 'c-state-nonlit-pos-cache) -;; A list of buffer positions which are known not to be in a literal or a cpp -;; construct. This is ordered with higher positions at the front of the list. -;; Only those which are less than `c-state-nonlit-pos-cache-limit' are valid. +(defvar c-semi-lit-near-cache nil) +(make-variable-buffer-local 'c-semi-lit-near-cache) +;; A list of up to six recent results from `c-semi-pp-to-literal'. Each +;; element is a cons of the buffer position and the `parse-partial-sexp' state +;; at that position. -(defvar c-state-nonlit-pos-cache-limit 1) -(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit) -;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is +(defvar c-semi-near-cache-limit 1) +(make-variable-buffer-local 'c-semi-near-cache-limit) +;; An upper limit on valid entries in `c-semi-lit-near-cache'. This is ;; reduced by buffer changes, and increased by invocations of -;; `c-state-literal-at'. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; We also maintain a less simple cache of positions which aren't in a -;; literal, disregarding macros. -;; -;; This cache is in two parts: the "near" cache, which is an association list -;; of a small number (currently six) of positions and the parser states there; -;; the "far" cache (also known as "the cache"), a list of compressed parser -;; states going back to the beginning of the buffer, one entry every 3000 -;; characters. -;; -;; When searching this cache, `c-semi-pp-to-literal' first seeks an -;; exact match, then a "close" match from the near cache. If neither of these -;; succeed, the nearest entry in the far cache is used. -;; -;; Because either sub-cache can raise `c-lit-pos-cache-limit', -;; both of them are "trimmed" together after a buffer change to ensure -;; consistency. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; `c-semi-pp-to-literal'. (defvar c-lit-pos-cache nil) (make-variable-buffer-local 'c-lit-pos-cache) @@ -2575,27 +2527,186 @@ comment at the start of cc-engine.el for more info." ;; is reduced by buffer changes, and increased by invocations of ;; `c-parse-ps-state-below'. -(defvar c-semi-lit-near-cache nil) -(make-variable-buffer-local 'c-semi-lit-near-cache) -;; A list of up to six recent results from `c-semi-pp-to-literal'. Each -;; element is a cons of the buffer position and the `parse-partial-sexp' state -;; at that position. +;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used. +(defun c-cache-to-parse-ps-state (elt) + ;; Create a list suitable to use as the old-state parameter to + ;; `parse-partial-sexp', out of ELT, a member of + ;; `c-lit-pos-cache'. ELT is either just a number, or a list + ;; with 2, 3, or 4 members (See `c-parse-ps-state-to-cache'). That number + ;; or the car of the list is the "position element" of ELT, the position + ;; where ELT is valid. + ;; + ;; POINT is left at the postition for which the returned state is valid. It + ;; will be either the position element of ELT, or one character before + ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates + ;; its position element directly follows a potential first character of a + ;; two char construct (such as a comment opener or an escaped character).) + (if (and (consp elt) (>= (length elt) 3)) + ;; Inside a string or comment + (let ((depth 0) (containing nil) (last nil) + in-string in-comment (after-quote nil) + (min-depth 0) com-style com-str-start (intermediate nil) + (char-1 (nth 3 elt)) ; first char of poss. 2-char construct + (pos (car elt)) + (type (cadr elt))) + (setq com-str-start (car (cddr elt))) + (cond + ((or (numberp type) (eq type t)) ; A string + (setq in-string type)) + ((memq type '(c c++)) ; A comment + (setq in-comment t + com-style (if (eq type 'c++) 1 nil))) + (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state" + elt))) + (goto-char (if char-1 + (1- pos) + pos)) + (if (memq 'pps-extended-state c-emacs-features) + (list depth containing last + in-string in-comment nil + min-depth com-style com-str-start + intermediate nil) + (list depth containing last + in-string in-comment nil + min-depth com-style com-str-start + intermediate))) -(defvar c-semi-near-cache-limit 1) -(make-variable-buffer-local 'c-semi-near-cache-limit) -;; An upper limit on valid entries in `c-semi-lit-near-cache'. This is -;; reduced by buffer changes, and increased by invocations of -;; `c-semi-pp-to-literal'. + ;; Not in a string or comment. + (if (memq 'pps-extended-state c-emacs-features) + (progn + (goto-char (if (consp elt) (car elt) elt)) + (list 0 nil nil nil nil + (and (consp elt) (eq (nth 1 elt) 9)) ; 9 is syntax code for "escape". + 0 nil nil nil + (and (consp elt) (nth 1 elt)))) + (goto-char (if (consp elt) (car elt) elt)) + (if (and (consp elt) (cdr elt)) (backward-char)) + (copy-tree '(0 nil nil nil nil + nil + 0 nil nil nil))))) -(defsubst c-truncate-lit-pos-cache (pos) - ;; Truncate the upper bound of each of the three caches to POS, if it is - ;; higher than that position. - (setq c-lit-pos-cache-limit - (min c-lit-pos-cache-limit pos) - c-semi-near-cache-limit - (min c-semi-near-cache-limit pos) - c-full-near-cache-limit - (min c-full-near-cache-limit pos))) +;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used. +(defun c-parse-ps-state-to-cache (state) + ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element + ;; for the `c-lit-pos-cache' cache. This is one of + ;; o - POINT (when point is not in a literal); + ;; o - (POINT CHAR-1) (when the last character before point is potentially + ;; the first of a two-character construct + ;; o - (POINT TYPE STARTING-POS) (when in a literal); + ;; o - (POINT TYPE STARTING-POS CHAR-1) (Combination of the previous two), + ;; where TYPE is the type of the literal (either 'c, or 'c++, or the + ;; character which closes the string), STARTING-POS is the starting + ;; position of the comment or string. CHAR-1 is either the character + ;; potentially forming the first half of a two-char construct (in Emacs <= + ;; 25 and XEmacs) or the syntax of the character (in Emacs >= 26). + (if (memq 'pps-extended-state c-emacs-features) + ;; Emacs >= 26. + (let ((basic + (cond + ((nth 3 state) ; A string + (list (point) (nth 3 state) (nth 8 state))) + ((and (nth 4 state) ; A comment + (not (eq (nth 7 state) 'syntax-table))) ; but not a psuedo comment. + (list (point) + (if (eq (nth 7 state) 1) 'c++ 'c) + (nth 8 state))) + (t ; Neither string nor comment. + (point))))) + (if (nth 10 state) + (append (if (consp basic) + basic + (list basic)) + (list (nth 10 state))) + basic)) + + ;; Emacs <= 25, XEmacs. + (cond + ((nth 3 state) ; A string + (if (eq (char-before) ?\\) + (list (point) (nth 3 state) (nth 8 state) ?\\) + (list (point) (nth 3 state) (nth 8 state)))) + ((and (nth 4 state) ; comment + (not (eq (nth 7 state) 'syntax-table))) + (if (and (eq (char-before) ?*) + (> (- (point) (nth 8 state)) 2)) ; not "/*/". + (list (point) + (if (eq (nth 7 state) 1) 'c++ 'c) + (nth 8 state) + ?*) + (list (point) + (if (eq (nth 7 state) 1) 'c++ 'c) + (nth 8 state)))) + (t (if (memq (char-before) '(?/ ?\\)) + (list (point) (char-before)) + (point)))))) + +(defsubst c-ps-state-cache-pos (elt) + ;; Get the buffer position from ELT, an element from the cache + ;; `c-lit-pos-cache'. + (if (atom elt) + elt + (car elt))) + +(defun c-trim-lit-pos-cache () + ;; Trim the `c-lit-pos-cache' to take account of buffer + ;; changes, indicated by `c-lit-pos-cache-limit'. + (while (and c-lit-pos-cache + (> (c-ps-state-cache-pos (car c-lit-pos-cache)) + c-lit-pos-cache-limit)) + (setq c-lit-pos-cache (cdr c-lit-pos-cache)))) + +(defconst c-state-nonlit-pos-interval 3000) +;; The approximate interval between entries in `c-state-nonlit-pos-cache'. + +(defun c-parse-ps-state-below (here) + ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where + ;; CACHE-POS is a position not very far before HERE for which the + ;; parse-partial-sexp STATE is valid. Note that the only valid elements of + ;; STATE are those concerning comments and strings; STATE is the state of a + ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or + ;; string. + (save-excursion + (save-restriction + (widen) + (c-trim-lit-pos-cache) + (let ((c c-lit-pos-cache) + elt state npos high-elt) + (while (and c (> (c-ps-state-cache-pos (car c)) here)) + (setq high-elt (car c)) + (setq c (cdr c))) + (goto-char (or (and c (c-ps-state-cache-pos (car c))) + (point-min))) + (setq state + (if c + (c-cache-to-parse-ps-state (car c)) + (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil)))) + + (when (not high-elt) + ;; We need to extend the cache. Add an element to + ;; `c-lit-pos-cache' each iteration of the following. + (while + (<= (setq npos (+ (point) c-state-nonlit-pos-interval)) here) + (setq state (parse-partial-sexp (point) npos nil nil state)) + ;; If we're after a \ or a / or * which might be a comment + ;; delimiter half, move back a character. + (when (or (nth 5 state) ; After a quote character + (and (memq 'pps-extended-state c-emacs-features) + (nth 10 state))) ; in the middle of a 2-char seq. + (setq npos (1- npos)) + (backward-char) + (when (nth 10 state) + (setcar (nthcdr 10 state) nil)) + (when (nth 5 state) + (setcar (nthcdr 5 state) nil))) + + (setq elt (c-parse-ps-state-to-cache state)) + (setq c-lit-pos-cache + (cons elt c-lit-pos-cache)))) + + (if (> (point) c-lit-pos-cache-limit) + (setq c-lit-pos-cache-limit (point))) + + (cons (point) state))))) (defun c-semi-trim-near-cache () ;; Remove stale entries in `c-semi-lit-near-cache', i.e. those @@ -2891,6 +3002,78 @@ comment at the start of cc-engine.el for more info." (c-full-put-near-cache-entry here s nil) (list s)))))))) +(defsubst c-truncate-lit-pos-cache (pos) + ;; Truncate the upper bound of each of the three caches to POS, if it is + ;; higher than that position. + (setq c-lit-pos-cache-limit + (min c-lit-pos-cache-limit pos) + c-semi-near-cache-limit + (min c-semi-near-cache-limit pos) + c-full-near-cache-limit + (min c-full-near-cache-limit pos))) + + +;; A system for finding noteworthy parens before the point. + +(defconst c-state-cache-too-far 5000) +;; A maximum comfortable scanning distance, e.g. between +;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When +;; this distance is exceeded, we take "emergency measures", e.g. by clearing +;; the cache and starting again from point-min or a beginning of defun. This +;; value can be tuned for efficiency or set to a lower value for testing. + +(defvar c-state-cache nil) +(make-variable-buffer-local 'c-state-cache) +;; The state cache used by `c-parse-state' to cut down the amount of +;; searching. It's the result from some earlier `c-parse-state' call. See +;; `c-parse-state''s doc string for details of its structure. +;; +;; The use of the cached info is more effective if the next +;; `c-parse-state' call is on a line close by the one the cached state +;; was made at; the cache can actually slow down a little if the +;; cached state was made very far back in the buffer. The cache is +;; most effective if `c-parse-state' is used on each line while moving +;; forward. + +(defvar c-state-cache-good-pos 1) +(make-variable-buffer-local 'c-state-cache-good-pos) +;; This is a position where `c-state-cache' is known to be correct, or +;; nil (see below). It's a position inside one of the recorded unclosed +;; parens or the top level, but not further nested inside any literal or +;; subparen that is closed before the last recorded position. +;; +;; The exact position is chosen to try to be close to yet earlier than +;; the position where `c-state-cache' will be called next. Right now +;; the heuristic is to set it to the position after the last found +;; closing paren (of any type) before the line on which +;; `c-parse-state' was called. That is chosen primarily to work well +;; with refontification of the current line. +;; +;; 2009-07-28: When `c-state-point-min' and the last position where +;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are +;; both in the same literal, there is no such "good position", and +;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which +;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil. +;; +;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in +;; the middle of the desert, as long as it is not within a brace pair +;; recorded in `c-state-cache' or a paren/bracket pair. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; We maintain a simple cache of positions which aren't in a literal, so as to +;; speed up testing for non-literality. +(defvar c-state-nonlit-pos-cache nil) +(make-variable-buffer-local 'c-state-nonlit-pos-cache) +;; A list of buffer positions which are known not to be in a literal or a cpp +;; construct. This is ordered with higher positions at the front of the list. +;; Only those which are less than `c-state-nonlit-pos-cache-limit' are valid. + +(defvar c-state-nonlit-pos-cache-limit 1) +(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit) +;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is +;; reduced by buffer changes, and increased by invocations of +;; `c-state-literal-at'. + (defun c-state-pp-to-literal (from to &optional not-in-delimiter) ;; Do a parse-partial-sexp from FROM to TO, returning either ;; (STATE TYPE (BEG . END)) if TO is in a literal; or @@ -2936,184 +3119,6 @@ comment at the start of cc-engine.el for more info." (t `(,s))))))) -;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used. -(defun c-cache-to-parse-ps-state (elt) - ;; Create a list suitable to use as the old-state parameter to - ;; `parse-partial-sexp', out of ELT, a member of - ;; `c-lit-pos-cache'. ELT is either just a number, or a list - ;; with 2, 3, or 4 members (See `c-parse-ps-state-to-cache'). That number - ;; or the car of the list is the "position element" of ELT, the position - ;; where ELT is valid. - ;; - ;; POINT is left at the position for which the returned state is valid. It - ;; will be either the position element of ELT, or one character before - ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates - ;; its position element directly follows a potential first character of a - ;; two char construct (such as a comment opener or an escaped character).) - (if (and (consp elt) (>= (length elt) 3)) - ;; Inside a string or comment - (let ((depth 0) (containing nil) (last nil) - in-string in-comment (after-quote nil) - (min-depth 0) com-style com-str-start (intermediate nil) - (char-1 (nth 3 elt)) ; first char of poss. 2-char construct - (pos (car elt)) - (type (cadr elt))) - (setq com-str-start (car (cddr elt))) - (cond - ((or (numberp type) (eq type t)) ; A string - (setq in-string type)) - ((memq type '(c c++)) ; A comment - (setq in-comment t - com-style (if (eq type 'c++) 1 nil))) - (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state" - elt))) - (goto-char (if char-1 - (1- pos) - pos)) - (if (memq 'pps-extended-state c-emacs-features) - (list depth containing last - in-string in-comment nil - min-depth com-style com-str-start - intermediate nil) - (list depth containing last - in-string in-comment nil - min-depth com-style com-str-start - intermediate))) - - ;; Not in a string or comment. - (if (memq 'pps-extended-state c-emacs-features) - (progn - (goto-char (if (consp elt) (car elt) elt)) - (list 0 nil nil nil nil - (and (consp elt) (eq (nth 1 elt) 9)) ; 9 is syntax code for "escape". - 0 nil nil nil - (and (consp elt) (nth 1 elt)))) - (goto-char (if (consp elt) (car elt) elt)) - (if (and (consp elt) (cdr elt)) (backward-char)) - (copy-tree '(0 nil nil nil nil - nil - 0 nil nil nil))))) - -;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used. -(defun c-parse-ps-state-to-cache (state) - ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element - ;; for the `c-lit-pos-cache' cache. This is one of - ;; o - POINT (when point is not in a literal); - ;; o - (POINT CHAR-1) (when the last character before point is potentially - ;; the first of a two-character construct - ;; o - (POINT TYPE STARTING-POS) (when in a literal); - ;; o - (POINT TYPE STARTING-POS CHAR-1) (Combination of the previous two), - ;; where TYPE is the type of the literal (either 'c, or 'c++, or the - ;; character which closes the string), STARTING-POS is the starting - ;; position of the comment or string. CHAR-1 is either the character - ;; potentially forming the first half of a two-char construct (in Emacs <= - ;; 25 and XEmacs) or the syntax of the character (in Emacs >= 26). - (if (memq 'pps-extended-state c-emacs-features) - ;; Emacs >= 26. - (let ((basic - (cond - ((nth 3 state) ; A string - (list (point) (nth 3 state) (nth 8 state))) - ((and (nth 4 state) ; A comment - (not (eq (nth 7 state) 'syntax-table))) ; but not a pseudo comment. - (list (point) - (if (eq (nth 7 state) 1) 'c++ 'c) - (nth 8 state))) - (t ; Neither string nor comment. - (point))))) - (if (nth 10 state) - (append (if (consp basic) - basic - (list basic)) - (list (nth 10 state))) - basic)) - - ;; Emacs <= 25, XEmacs. - (cond - ((nth 3 state) ; A string - (if (eq (char-before) ?\\) - (list (point) (nth 3 state) (nth 8 state) ?\\) - (list (point) (nth 3 state) (nth 8 state)))) - ((and (nth 4 state) ; comment - (not (eq (nth 7 state) 'syntax-table))) - (if (and (eq (char-before) ?*) - (> (- (point) (nth 8 state)) 2)) ; not "/*/". - (list (point) - (if (eq (nth 7 state) 1) 'c++ 'c) - (nth 8 state) - ?*) - (list (point) - (if (eq (nth 7 state) 1) 'c++ 'c) - (nth 8 state)))) - (t (if (memq (char-before) '(?/ ?\\)) - (list (point) (char-before)) - (point)))))) - -(defsubst c-ps-state-cache-pos (elt) - ;; Get the buffer position from ELT, an element from the cache - ;; `c-lit-pos-cache'. - (if (atom elt) - elt - (car elt))) - -(defun c-trim-lit-pos-cache () - ;; Trim the `c-lit-pos-cache' to take account of buffer - ;; changes, indicated by `c-lit-pos-cache-limit'. - (while (and c-lit-pos-cache - (> (c-ps-state-cache-pos (car c-lit-pos-cache)) - c-lit-pos-cache-limit)) - (setq c-lit-pos-cache (cdr c-lit-pos-cache)))) - -(defun c-parse-ps-state-below (here) - ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where - ;; CACHE-POS is a position not very far before HERE for which the - ;; parse-partial-sexp STATE is valid. Note that the only valid elements of - ;; STATE are those concerning comments and strings; STATE is the state of a - ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or - ;; string. - (save-excursion - (save-restriction - (widen) - (c-trim-lit-pos-cache) - (let ((c c-lit-pos-cache) - elt state npos high-elt) - (while (and c (> (c-ps-state-cache-pos (car c)) here)) - (setq high-elt (car c)) - (setq c (cdr c))) - (goto-char (or (and c (c-ps-state-cache-pos (car c))) - (point-min))) - (setq state - (if c - (c-cache-to-parse-ps-state (car c)) - (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil)))) - - (when (not high-elt) - ;; We need to extend the cache. Add an element to - ;; `c-lit-pos-cache' each iteration of the following. - (while - (<= (setq npos (+ (point) c-state-nonlit-pos-interval)) here) - (setq state (parse-partial-sexp (point) npos nil nil state)) - ;; If we're after a \ or a / or * which might be a comment - ;; delimiter half, move back a character. - (when (or (nth 5 state) ; After a quote character - (and (memq 'pps-extended-state c-emacs-features) - (nth 10 state))) ; in the middle of a 2-char seq. - (setq npos (1- npos)) - (backward-char) - (when (nth 10 state) - (setcar (nthcdr 10 state) nil)) - (when (nth 5 state) - (setcar (nthcdr 5 state) nil))) - - (setq elt (c-parse-ps-state-to-cache state)) - (setq c-lit-pos-cache - (cons elt c-lit-pos-cache)))) - - (if (> (point) c-lit-pos-cache-limit) - (setq c-lit-pos-cache-limit (point))) - - (cons (point) state))))) - (defun c-state-safe-place (here) ;; Return a buffer position before HERE which is "safe", i.e. outside any ;; string, comment, or macro. -- 2.39.5