diff options
| author | Alan Mackenzie | 2019-06-01 20:08:27 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2019-06-01 20:08:27 +0000 |
| commit | 99bc4af9c883d0faa5a1387cb26c1cbf09feb958 (patch) | |
| tree | 336dc64dab208879de2bea2efd9313e170c2557a | |
| parent | 9dee49ed6439bfdf7f1c98fee767d170d144f581 (diff) | |
| download | emacs-99bc4af9c883d0faa5a1387cb26c1cbf09feb958.tar.gz emacs-99bc4af9c883d0faa5a1387cb26c1cbf09feb958.zip | |
* lisp/progmodes/cc-engine.el: Permute certain literal cacheing functions
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 547 |
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. |