aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2019-06-01 20:08:27 +0000
committerAlan Mackenzie2019-06-01 20:08:27 +0000
commit99bc4af9c883d0faa5a1387cb26c1cbf09feb958 (patch)
tree336dc64dab208879de2bea2efd9313e170c2557a
parent9dee49ed6439bfdf7f1c98fee767d170d144f581 (diff)
downloademacs-99bc4af9c883d0faa5a1387cb26c1cbf09feb958.tar.gz
emacs-99bc4af9c883d0faa5a1387cb26c1cbf09feb958.zip
* lisp/progmodes/cc-engine.el: Permute certain literal cacheing functions
-rw-r--r--lisp/progmodes/cc-engine.el547
1 files 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."
2470 (c-skip-ws-forward end+1) 2470 (c-skip-ws-forward end+1)
2471 (eq (point) end+1)))))) 2471 (eq (point) end+1))))))
2472 2472
2473;; A system for finding noteworthy parens before the point. 2473;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2474 2474;; We maintain a sopisticated cache of positions which are in a literal,
2475(defconst c-state-cache-too-far 5000) 2475;; disregarding macros (i.e. we don't distinguish between "in a macro" and
2476;; A maximum comfortable scanning distance, e.g. between 2476;; not).
2477;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When
2478;; this distance is exceeded, we take "emergency measures", e.g. by clearing
2479;; the cache and starting again from point-min or a beginning of defun. This
2480;; value can be tuned for efficiency or set to a lower value for testing.
2481
2482(defvar c-state-cache nil)
2483(make-variable-buffer-local 'c-state-cache)
2484;; The state cache used by `c-parse-state' to cut down the amount of
2485;; searching. It's the result from some earlier `c-parse-state' call. See
2486;; `c-parse-state''s doc string for details of its structure.
2487;; 2477;;
2488;; The use of the cached info is more effective if the next 2478;; This cache is in three parts: two "near" caches, which are association
2489;; `c-parse-state' call is on a line close by the one the cached state 2479;; lists of a small number (currently six) of positions and the parser states
2490;; was made at; the cache can actually slow down a little if the 2480;; there; the "far" cache (also known as "the cache"), a list of compressed
2491;; cached state was made very far back in the buffer. The cache is 2481;; parser states going back to the beginning of the buffer, one entry every
2492;; most effective if `c-parse-state' is used on each line while moving 2482;; 3000 characters.
2493;; forward.
2494
2495(defvar c-state-cache-good-pos 1)
2496(make-variable-buffer-local 'c-state-cache-good-pos)
2497;; This is a position where `c-state-cache' is known to be correct, or
2498;; nil (see below). It's a position inside one of the recorded unclosed
2499;; parens or the top level, but not further nested inside any literal or
2500;; subparen that is closed before the last recorded position.
2501;; 2483;;
2502;; The exact position is chosen to try to be close to yet earlier than 2484;; The two main callable functions embodying this cache are
2503;; the position where `c-state-cache' will be called next. Right now 2485;; `c-semi-pp-to-literal', which returns a `parse-partial-sexp' state at a
2504;; the heuristic is to set it to the position after the last found 2486;; given position, together with the start of any literal enclosing it, and
2505;; closing paren (of any type) before the line on which 2487;; `c-full-pp-to-literal', which additionally returns the end of such literal.
2506;; `c-parse-state' was called. That is chosen primarily to work well 2488;; One of the above "near" caches is associated with each of these functions.
2507;; with refontification of the current line.
2508;; 2489;;
2509;; 2009-07-28: When `c-state-point-min' and the last position where 2490;; When searching this cache, these functions first seek an exact match, then
2510;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are 2491;; a "close" match from the assiciated near cache. If neither of these
2511;; both in the same literal, there is no such "good position", and 2492;; succeed, the nearest preceding entry in the far cache is used.
2512;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which
2513;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil.
2514;; 2493;;
2515;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in
2516;; the middle of the desert, as long as it is not within a brace pair
2517;; recorded in `c-state-cache' or a paren/bracket pair.
2518
2519;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2494;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2520;; We maintain a simple cache of positions which aren't in a literal, so as to
2521;; speed up testing for non-literality.
2522(defconst c-state-nonlit-pos-interval 3000)
2523;; The approximate interval between entries in `c-state-nonlit-pos-cache'.
2524 2495
2525(defvar c-state-nonlit-pos-cache nil) 2496(defvar c-semi-lit-near-cache nil)
2526(make-variable-buffer-local 'c-state-nonlit-pos-cache) 2497(make-variable-buffer-local 'c-semi-lit-near-cache)
2527;; A list of buffer positions which are known not to be in a literal or a cpp 2498;; A list of up to six recent results from `c-semi-pp-to-literal'. Each
2528;; construct. This is ordered with higher positions at the front of the list. 2499;; element is a cons of the buffer position and the `parse-partial-sexp' state
2529;; Only those which are less than `c-state-nonlit-pos-cache-limit' are valid. 2500;; at that position.
2530 2501
2531(defvar c-state-nonlit-pos-cache-limit 1) 2502(defvar c-semi-near-cache-limit 1)
2532(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit) 2503(make-variable-buffer-local 'c-semi-near-cache-limit)
2533;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is 2504;; An upper limit on valid entries in `c-semi-lit-near-cache'. This is
2534;; reduced by buffer changes, and increased by invocations of 2505;; reduced by buffer changes, and increased by invocations of
2535;; `c-state-literal-at'. 2506;; `c-semi-pp-to-literal'.
2536
2537;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2538;; We also maintain a less simple cache of positions which aren't in a
2539;; literal, disregarding macros.
2540;;
2541;; This cache is in two parts: the "near" cache, which is an association list
2542;; of a small number (currently six) of positions and the parser states there;
2543;; the "far" cache (also known as "the cache"), a list of compressed parser
2544;; states going back to the beginning of the buffer, one entry every 3000
2545;; characters.
2546;;
2547;; When searching this cache, `c-semi-pp-to-literal' first seeks an
2548;; exact match, then a "close" match from the near cache. If neither of these
2549;; succeed, the nearest entry in the far cache is used.
2550;;
2551;; Because either sub-cache can raise `c-lit-pos-cache-limit',
2552;; both of them are "trimmed" together after a buffer change to ensure
2553;; consistency.
2554;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2555 2507
2556(defvar c-lit-pos-cache nil) 2508(defvar c-lit-pos-cache nil)
2557(make-variable-buffer-local 'c-lit-pos-cache) 2509(make-variable-buffer-local 'c-lit-pos-cache)
@@ -2575,27 +2527,186 @@ comment at the start of cc-engine.el for more info."
2575;; is reduced by buffer changes, and increased by invocations of 2527;; is reduced by buffer changes, and increased by invocations of
2576;; `c-parse-ps-state-below'. 2528;; `c-parse-ps-state-below'.
2577 2529
2578(defvar c-semi-lit-near-cache nil) 2530;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used.
2579(make-variable-buffer-local 'c-semi-lit-near-cache) 2531(defun c-cache-to-parse-ps-state (elt)
2580;; A list of up to six recent results from `c-semi-pp-to-literal'. Each 2532 ;; Create a list suitable to use as the old-state parameter to
2581;; element is a cons of the buffer position and the `parse-partial-sexp' state 2533 ;; `parse-partial-sexp', out of ELT, a member of
2582;; at that position. 2534 ;; `c-lit-pos-cache'. ELT is either just a number, or a list
2535 ;; with 2, 3, or 4 members (See `c-parse-ps-state-to-cache'). That number
2536 ;; or the car of the list is the "position element" of ELT, the position
2537 ;; where ELT is valid.
2538 ;;
2539 ;; POINT is left at the postition for which the returned state is valid. It
2540 ;; will be either the position element of ELT, or one character before
2541 ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates
2542 ;; its position element directly follows a potential first character of a
2543 ;; two char construct (such as a comment opener or an escaped character).)
2544 (if (and (consp elt) (>= (length elt) 3))
2545 ;; Inside a string or comment
2546 (let ((depth 0) (containing nil) (last nil)
2547 in-string in-comment (after-quote nil)
2548 (min-depth 0) com-style com-str-start (intermediate nil)
2549 (char-1 (nth 3 elt)) ; first char of poss. 2-char construct
2550 (pos (car elt))
2551 (type (cadr elt)))
2552 (setq com-str-start (car (cddr elt)))
2553 (cond
2554 ((or (numberp type) (eq type t)) ; A string
2555 (setq in-string type))
2556 ((memq type '(c c++)) ; A comment
2557 (setq in-comment t
2558 com-style (if (eq type 'c++) 1 nil)))
2559 (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state"
2560 elt)))
2561 (goto-char (if char-1
2562 (1- pos)
2563 pos))
2564 (if (memq 'pps-extended-state c-emacs-features)
2565 (list depth containing last
2566 in-string in-comment nil
2567 min-depth com-style com-str-start
2568 intermediate nil)
2569 (list depth containing last
2570 in-string in-comment nil
2571 min-depth com-style com-str-start
2572 intermediate)))
2583 2573
2584(defvar c-semi-near-cache-limit 1) 2574 ;; Not in a string or comment.
2585(make-variable-buffer-local 'c-semi-near-cache-limit) 2575 (if (memq 'pps-extended-state c-emacs-features)
2586;; An upper limit on valid entries in `c-semi-lit-near-cache'. This is 2576 (progn
2587;; reduced by buffer changes, and increased by invocations of 2577 (goto-char (if (consp elt) (car elt) elt))
2588;; `c-semi-pp-to-literal'. 2578 (list 0 nil nil nil nil
2579 (and (consp elt) (eq (nth 1 elt) 9)) ; 9 is syntax code for "escape".
2580 0 nil nil nil
2581 (and (consp elt) (nth 1 elt))))
2582 (goto-char (if (consp elt) (car elt) elt))
2583 (if (and (consp elt) (cdr elt)) (backward-char))
2584 (copy-tree '(0 nil nil nil nil
2585 nil
2586 0 nil nil nil)))))
2589 2587
2590(defsubst c-truncate-lit-pos-cache (pos) 2588;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used.
2591 ;; Truncate the upper bound of each of the three caches to POS, if it is 2589(defun c-parse-ps-state-to-cache (state)
2592 ;; higher than that position. 2590 ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element
2593 (setq c-lit-pos-cache-limit 2591 ;; for the `c-lit-pos-cache' cache. This is one of
2594 (min c-lit-pos-cache-limit pos) 2592 ;; o - POINT (when point is not in a literal);
2595 c-semi-near-cache-limit 2593 ;; o - (POINT CHAR-1) (when the last character before point is potentially
2596 (min c-semi-near-cache-limit pos) 2594 ;; the first of a two-character construct
2597 c-full-near-cache-limit 2595 ;; o - (POINT TYPE STARTING-POS) (when in a literal);
2598 (min c-full-near-cache-limit pos))) 2596 ;; o - (POINT TYPE STARTING-POS CHAR-1) (Combination of the previous two),
2597 ;; where TYPE is the type of the literal (either 'c, or 'c++, or the
2598 ;; character which closes the string), STARTING-POS is the starting
2599 ;; position of the comment or string. CHAR-1 is either the character
2600 ;; potentially forming the first half of a two-char construct (in Emacs <=
2601 ;; 25 and XEmacs) or the syntax of the character (in Emacs >= 26).
2602 (if (memq 'pps-extended-state c-emacs-features)
2603 ;; Emacs >= 26.
2604 (let ((basic
2605 (cond
2606 ((nth 3 state) ; A string
2607 (list (point) (nth 3 state) (nth 8 state)))
2608 ((and (nth 4 state) ; A comment
2609 (not (eq (nth 7 state) 'syntax-table))) ; but not a psuedo comment.
2610 (list (point)
2611 (if (eq (nth 7 state) 1) 'c++ 'c)
2612 (nth 8 state)))
2613 (t ; Neither string nor comment.
2614 (point)))))
2615 (if (nth 10 state)
2616 (append (if (consp basic)
2617 basic
2618 (list basic))
2619 (list (nth 10 state)))
2620 basic))
2621
2622 ;; Emacs <= 25, XEmacs.
2623 (cond
2624 ((nth 3 state) ; A string
2625 (if (eq (char-before) ?\\)
2626 (list (point) (nth 3 state) (nth 8 state) ?\\)
2627 (list (point) (nth 3 state) (nth 8 state))))
2628 ((and (nth 4 state) ; comment
2629 (not (eq (nth 7 state) 'syntax-table)))
2630 (if (and (eq (char-before) ?*)
2631 (> (- (point) (nth 8 state)) 2)) ; not "/*/".
2632 (list (point)
2633 (if (eq (nth 7 state) 1) 'c++ 'c)
2634 (nth 8 state)
2635 ?*)
2636 (list (point)
2637 (if (eq (nth 7 state) 1) 'c++ 'c)
2638 (nth 8 state))))
2639 (t (if (memq (char-before) '(?/ ?\\))
2640 (list (point) (char-before))
2641 (point))))))
2642
2643(defsubst c-ps-state-cache-pos (elt)
2644 ;; Get the buffer position from ELT, an element from the cache
2645 ;; `c-lit-pos-cache'.
2646 (if (atom elt)
2647 elt
2648 (car elt)))
2649
2650(defun c-trim-lit-pos-cache ()
2651 ;; Trim the `c-lit-pos-cache' to take account of buffer
2652 ;; changes, indicated by `c-lit-pos-cache-limit'.
2653 (while (and c-lit-pos-cache
2654 (> (c-ps-state-cache-pos (car c-lit-pos-cache))
2655 c-lit-pos-cache-limit))
2656 (setq c-lit-pos-cache (cdr c-lit-pos-cache))))
2657
2658(defconst c-state-nonlit-pos-interval 3000)
2659;; The approximate interval between entries in `c-state-nonlit-pos-cache'.
2660
2661(defun c-parse-ps-state-below (here)
2662 ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where
2663 ;; CACHE-POS is a position not very far before HERE for which the
2664 ;; parse-partial-sexp STATE is valid. Note that the only valid elements of
2665 ;; STATE are those concerning comments and strings; STATE is the state of a
2666 ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or
2667 ;; string.
2668 (save-excursion
2669 (save-restriction
2670 (widen)
2671 (c-trim-lit-pos-cache)
2672 (let ((c c-lit-pos-cache)
2673 elt state npos high-elt)
2674 (while (and c (> (c-ps-state-cache-pos (car c)) here))
2675 (setq high-elt (car c))
2676 (setq c (cdr c)))
2677 (goto-char (or (and c (c-ps-state-cache-pos (car c)))
2678 (point-min)))
2679 (setq state
2680 (if c
2681 (c-cache-to-parse-ps-state (car c))
2682 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
2683
2684 (when (not high-elt)
2685 ;; We need to extend the cache. Add an element to
2686 ;; `c-lit-pos-cache' each iteration of the following.
2687 (while
2688 (<= (setq npos (+ (point) c-state-nonlit-pos-interval)) here)
2689 (setq state (parse-partial-sexp (point) npos nil nil state))
2690 ;; If we're after a \ or a / or * which might be a comment
2691 ;; delimiter half, move back a character.
2692 (when (or (nth 5 state) ; After a quote character
2693 (and (memq 'pps-extended-state c-emacs-features)
2694 (nth 10 state))) ; in the middle of a 2-char seq.
2695 (setq npos (1- npos))
2696 (backward-char)
2697 (when (nth 10 state)
2698 (setcar (nthcdr 10 state) nil))
2699 (when (nth 5 state)
2700 (setcar (nthcdr 5 state) nil)))
2701
2702 (setq elt (c-parse-ps-state-to-cache state))
2703 (setq c-lit-pos-cache
2704 (cons elt c-lit-pos-cache))))
2705
2706 (if (> (point) c-lit-pos-cache-limit)
2707 (setq c-lit-pos-cache-limit (point)))
2708
2709 (cons (point) state)))))
2599 2710
2600(defun c-semi-trim-near-cache () 2711(defun c-semi-trim-near-cache ()
2601 ;; Remove stale entries in `c-semi-lit-near-cache', i.e. those 2712 ;; 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."
2891 (c-full-put-near-cache-entry here s nil) 3002 (c-full-put-near-cache-entry here s nil)
2892 (list s)))))))) 3003 (list s))))))))
2893 3004
3005(defsubst c-truncate-lit-pos-cache (pos)
3006 ;; Truncate the upper bound of each of the three caches to POS, if it is
3007 ;; higher than that position.
3008 (setq c-lit-pos-cache-limit
3009 (min c-lit-pos-cache-limit pos)
3010 c-semi-near-cache-limit
3011 (min c-semi-near-cache-limit pos)
3012 c-full-near-cache-limit
3013 (min c-full-near-cache-limit pos)))
3014
3015
3016;; A system for finding noteworthy parens before the point.
3017
3018(defconst c-state-cache-too-far 5000)
3019;; A maximum comfortable scanning distance, e.g. between
3020;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When
3021;; this distance is exceeded, we take "emergency measures", e.g. by clearing
3022;; the cache and starting again from point-min or a beginning of defun. This
3023;; value can be tuned for efficiency or set to a lower value for testing.
3024
3025(defvar c-state-cache nil)
3026(make-variable-buffer-local 'c-state-cache)
3027;; The state cache used by `c-parse-state' to cut down the amount of
3028;; searching. It's the result from some earlier `c-parse-state' call. See
3029;; `c-parse-state''s doc string for details of its structure.
3030;;
3031;; The use of the cached info is more effective if the next
3032;; `c-parse-state' call is on a line close by the one the cached state
3033;; was made at; the cache can actually slow down a little if the
3034;; cached state was made very far back in the buffer. The cache is
3035;; most effective if `c-parse-state' is used on each line while moving
3036;; forward.
3037
3038(defvar c-state-cache-good-pos 1)
3039(make-variable-buffer-local 'c-state-cache-good-pos)
3040;; This is a position where `c-state-cache' is known to be correct, or
3041;; nil (see below). It's a position inside one of the recorded unclosed
3042;; parens or the top level, but not further nested inside any literal or
3043;; subparen that is closed before the last recorded position.
3044;;
3045;; The exact position is chosen to try to be close to yet earlier than
3046;; the position where `c-state-cache' will be called next. Right now
3047;; the heuristic is to set it to the position after the last found
3048;; closing paren (of any type) before the line on which
3049;; `c-parse-state' was called. That is chosen primarily to work well
3050;; with refontification of the current line.
3051;;
3052;; 2009-07-28: When `c-state-point-min' and the last position where
3053;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are
3054;; both in the same literal, there is no such "good position", and
3055;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which
3056;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil.
3057;;
3058;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in
3059;; the middle of the desert, as long as it is not within a brace pair
3060;; recorded in `c-state-cache' or a paren/bracket pair.
3061
3062;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3063;; We maintain a simple cache of positions which aren't in a literal, so as to
3064;; speed up testing for non-literality.
3065(defvar c-state-nonlit-pos-cache nil)
3066(make-variable-buffer-local 'c-state-nonlit-pos-cache)
3067;; A list of buffer positions which are known not to be in a literal or a cpp
3068;; construct. This is ordered with higher positions at the front of the list.
3069;; Only those which are less than `c-state-nonlit-pos-cache-limit' are valid.
3070
3071(defvar c-state-nonlit-pos-cache-limit 1)
3072(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit)
3073;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is
3074;; reduced by buffer changes, and increased by invocations of
3075;; `c-state-literal-at'.
3076
2894(defun c-state-pp-to-literal (from to &optional not-in-delimiter) 3077(defun c-state-pp-to-literal (from to &optional not-in-delimiter)
2895 ;; Do a parse-partial-sexp from FROM to TO, returning either 3078 ;; Do a parse-partial-sexp from FROM to TO, returning either
2896 ;; (STATE TYPE (BEG . END)) if TO is in a literal; or 3079 ;; (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."
2936 3119
2937 (t `(,s))))))) 3120 (t `(,s)))))))
2938 3121
2939;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used.
2940(defun c-cache-to-parse-ps-state (elt)
2941 ;; Create a list suitable to use as the old-state parameter to
2942 ;; `parse-partial-sexp', out of ELT, a member of
2943 ;; `c-lit-pos-cache'. ELT is either just a number, or a list
2944 ;; with 2, 3, or 4 members (See `c-parse-ps-state-to-cache'). That number
2945 ;; or the car of the list is the "position element" of ELT, the position
2946 ;; where ELT is valid.
2947 ;;
2948 ;; POINT is left at the position for which the returned state is valid. It
2949 ;; will be either the position element of ELT, or one character before
2950 ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates
2951 ;; its position element directly follows a potential first character of a
2952 ;; two char construct (such as a comment opener or an escaped character).)
2953 (if (and (consp elt) (>= (length elt) 3))
2954 ;; Inside a string or comment
2955 (let ((depth 0) (containing nil) (last nil)
2956 in-string in-comment (after-quote nil)
2957 (min-depth 0) com-style com-str-start (intermediate nil)
2958 (char-1 (nth 3 elt)) ; first char of poss. 2-char construct
2959 (pos (car elt))
2960 (type (cadr elt)))
2961 (setq com-str-start (car (cddr elt)))
2962 (cond
2963 ((or (numberp type) (eq type t)) ; A string
2964 (setq in-string type))
2965 ((memq type '(c c++)) ; A comment
2966 (setq in-comment t
2967 com-style (if (eq type 'c++) 1 nil)))
2968 (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state"
2969 elt)))
2970 (goto-char (if char-1
2971 (1- pos)
2972 pos))
2973 (if (memq 'pps-extended-state c-emacs-features)
2974 (list depth containing last
2975 in-string in-comment nil
2976 min-depth com-style com-str-start
2977 intermediate nil)
2978 (list depth containing last
2979 in-string in-comment nil
2980 min-depth com-style com-str-start
2981 intermediate)))
2982
2983 ;; Not in a string or comment.
2984 (if (memq 'pps-extended-state c-emacs-features)
2985 (progn
2986 (goto-char (if (consp elt) (car elt) elt))
2987 (list 0 nil nil nil nil
2988 (and (consp elt) (eq (nth 1 elt) 9)) ; 9 is syntax code for "escape".
2989 0 nil nil nil
2990 (and (consp elt) (nth 1 elt))))
2991 (goto-char (if (consp elt) (car elt) elt))
2992 (if (and (consp elt) (cdr elt)) (backward-char))
2993 (copy-tree '(0 nil nil nil nil
2994 nil
2995 0 nil nil nil)))))
2996
2997;; Note that as of 2019-05-27, the forms involving CHAR-1 are no longer used.
2998(defun c-parse-ps-state-to-cache (state)
2999 ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element
3000 ;; for the `c-lit-pos-cache' cache. This is one of
3001 ;; o - POINT (when point is not in a literal);
3002 ;; o - (POINT CHAR-1) (when the last character before point is potentially
3003 ;; the first of a two-character construct
3004 ;; o - (POINT TYPE STARTING-POS) (when in a literal);
3005 ;; o - (POINT TYPE STARTING-POS CHAR-1) (Combination of the previous two),
3006 ;; where TYPE is the type of the literal (either 'c, or 'c++, or the
3007 ;; character which closes the string), STARTING-POS is the starting
3008 ;; position of the comment or string. CHAR-1 is either the character
3009 ;; potentially forming the first half of a two-char construct (in Emacs <=
3010 ;; 25 and XEmacs) or the syntax of the character (in Emacs >= 26).
3011 (if (memq 'pps-extended-state c-emacs-features)
3012 ;; Emacs >= 26.
3013 (let ((basic
3014 (cond
3015 ((nth 3 state) ; A string
3016 (list (point) (nth 3 state) (nth 8 state)))
3017 ((and (nth 4 state) ; A comment
3018 (not (eq (nth 7 state) 'syntax-table))) ; but not a pseudo comment.
3019 (list (point)
3020 (if (eq (nth 7 state) 1) 'c++ 'c)
3021 (nth 8 state)))
3022 (t ; Neither string nor comment.
3023 (point)))))
3024 (if (nth 10 state)
3025 (append (if (consp basic)
3026 basic
3027 (list basic))
3028 (list (nth 10 state)))
3029 basic))
3030
3031 ;; Emacs <= 25, XEmacs.
3032 (cond
3033 ((nth 3 state) ; A string
3034 (if (eq (char-before) ?\\)
3035 (list (point) (nth 3 state) (nth 8 state) ?\\)
3036 (list (point) (nth 3 state) (nth 8 state))))
3037 ((and (nth 4 state) ; comment
3038 (not (eq (nth 7 state) 'syntax-table)))
3039 (if (and (eq (char-before) ?*)
3040 (> (- (point) (nth 8 state)) 2)) ; not "/*/".
3041 (list (point)
3042 (if (eq (nth 7 state) 1) 'c++ 'c)
3043 (nth 8 state)
3044 ?*)
3045 (list (point)
3046 (if (eq (nth 7 state) 1) 'c++ 'c)
3047 (nth 8 state))))
3048 (t (if (memq (char-before) '(?/ ?\\))
3049 (list (point) (char-before))
3050 (point))))))
3051
3052(defsubst c-ps-state-cache-pos (elt)
3053 ;; Get the buffer position from ELT, an element from the cache
3054 ;; `c-lit-pos-cache'.
3055 (if (atom elt)
3056 elt
3057 (car elt)))
3058
3059(defun c-trim-lit-pos-cache ()
3060 ;; Trim the `c-lit-pos-cache' to take account of buffer
3061 ;; changes, indicated by `c-lit-pos-cache-limit'.
3062 (while (and c-lit-pos-cache
3063 (> (c-ps-state-cache-pos (car c-lit-pos-cache))
3064 c-lit-pos-cache-limit))
3065 (setq c-lit-pos-cache (cdr c-lit-pos-cache))))
3066
3067(defun c-parse-ps-state-below (here)
3068 ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where
3069 ;; CACHE-POS is a position not very far before HERE for which the
3070 ;; parse-partial-sexp STATE is valid. Note that the only valid elements of
3071 ;; STATE are those concerning comments and strings; STATE is the state of a
3072 ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or
3073 ;; string.
3074 (save-excursion
3075 (save-restriction
3076 (widen)
3077 (c-trim-lit-pos-cache)
3078 (let ((c c-lit-pos-cache)
3079 elt state npos high-elt)
3080 (while (and c (> (c-ps-state-cache-pos (car c)) here))
3081 (setq high-elt (car c))
3082 (setq c (cdr c)))
3083 (goto-char (or (and c (c-ps-state-cache-pos (car c)))
3084 (point-min)))
3085 (setq state
3086 (if c
3087 (c-cache-to-parse-ps-state (car c))
3088 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
3089
3090 (when (not high-elt)
3091 ;; We need to extend the cache. Add an element to
3092 ;; `c-lit-pos-cache' each iteration of the following.
3093 (while
3094 (<= (setq npos (+ (point) c-state-nonlit-pos-interval)) here)
3095 (setq state (parse-partial-sexp (point) npos nil nil state))
3096 ;; If we're after a \ or a / or * which might be a comment
3097 ;; delimiter half, move back a character.
3098 (when (or (nth 5 state) ; After a quote character
3099 (and (memq 'pps-extended-state c-emacs-features)
3100 (nth 10 state))) ; in the middle of a 2-char seq.
3101 (setq npos (1- npos))
3102 (backward-char)
3103 (when (nth 10 state)
3104 (setcar (nthcdr 10 state) nil))
3105 (when (nth 5 state)
3106 (setcar (nthcdr 5 state) nil)))
3107
3108 (setq elt (c-parse-ps-state-to-cache state))
3109 (setq c-lit-pos-cache
3110 (cons elt c-lit-pos-cache))))
3111
3112 (if (> (point) c-lit-pos-cache-limit)
3113 (setq c-lit-pos-cache-limit (point)))
3114
3115 (cons (point) state)))))
3116
3117(defun c-state-safe-place (here) 3122(defun c-state-safe-place (here)
3118 ;; Return a buffer position before HERE which is "safe", i.e. outside any 3123 ;; Return a buffer position before HERE which is "safe", i.e. outside any
3119 ;; string, comment, or macro. 3124 ;; string, comment, or macro.