aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorAlan Mackenzie2017-05-07 09:27:00 +0000
committerAlan Mackenzie2017-05-07 09:27:00 +0000
commitbcbd8f7e4e929604bb3dfef9937432cb05b5f648 (patch)
treee60abdb591038992dea3225300a00982c0d167e3 /lisp
parent55b07d33796a4697b37215c18b4630eeaaa4fb76 (diff)
downloademacs-bcbd8f7e4e929604bb3dfef9937432cb05b5f648.tar.gz
emacs-bcbd8f7e4e929604bb3dfef9937432cb05b5f648.zip
CC Mode internal cache: Handle a cache pos being inside a two-char construct.
Cache c-state-semi-nonlit-pos-cache was failing when a cache position was, e.g., between the two characters of an opening comment "/*", and additionally there were an odd number of quote marks (apostrophes) in the comment. This happened in .../src/xdisp.c in the Emacs master branch around 2017-05-02 at buffer position 615001. * lisp/progmodes/cc-defs.el (c-emacs-features): Repurpose symbol pps-extended-state to mean that there are at least 11 elements in the parser state. * lisp/progmodes/cc-engine.el (c-cache-to-parse-ps-state) (c-parse-ps-state-to-cache): Rewrite these to use enhanced cache element list types which indicate potentially being inside two-char constructs. (c-parse-ps-state-below): Rewrite to use the new versions of the above two functions.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/progmodes/cc-defs.el27
-rw-r--r--lisp/progmodes/cc-engine.el155
2 files changed, 125 insertions, 57 deletions
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 8dd56106af4..dd8f8afc6a3 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1914,14 +1914,18 @@ non-nil, a caret is prepended to invert the set."
1914 (set-buffer-modified-p nil)) 1914 (set-buffer-modified-p nil))
1915 (kill-buffer buf)) 1915 (kill-buffer buf))
1916 1916
1917 ;; See if `parse-partial-sexp' returns the eighth element. 1917 ;; Check how many elements `parse-partial-sexp' returns.
1918 (if (c-safe (>= (length (save-excursion 1918 (let ((ppss-size (or (c-safe (length
1919 (parse-partial-sexp (point) (point)))) 1919 (save-excursion
1920 10)) 1920 (parse-partial-sexp (point) (point)))))
1921 (setq list (cons 'pps-extended-state list)) 1921 0)))
1922 (error (concat 1922 (cond
1923 "CC Mode is incompatible with this version of Emacs - " 1923 ((>= ppss-size 11) (setq list (cons 'pps-extended-state list)))
1924 "`parse-partial-sexp' has to return at least 10 elements."))) 1924 ((>= ppss-size 10))
1925 (t (error
1926 (concat
1927 "CC Mode is incompatible with this version of Emacs - "
1928 "`parse-partial-sexp' has to return at least 10 elements.")))))
1925 1929
1926 ;;(message "c-emacs-features: %S" list) 1930 ;;(message "c-emacs-features: %S" list)
1927 list) 1931 list)
@@ -1944,10 +1948,9 @@ might be present:
1944 (i.e. the syntax class `!'). 1948 (i.e. the syntax class `!').
1945`gen-string-delim' Generic string delimiters work 1949`gen-string-delim' Generic string delimiters work
1946 (i.e. the syntax class `|'). 1950 (i.e. the syntax class `|').
1947`pps-extended-state' `parse-partial-sexp' returns a list with at least 10 1951`pps-extended-state' `parse-partial-sexp' returns a list with at least 11
1948 elements, i.e. it contains the position of the start of 1952 elements, i.e. it indicates having stopped after the
1949 the last comment or string. It's always set - CC Mode 1953 first character of a potential two-char construct.
1950 no longer works in emacsen without this feature.
1951`posix-char-classes' The regexp engine understands POSIX character classes. 1954`posix-char-classes' The regexp engine understands POSIX character classes.
1952`col-0-paren' It's possible to turn off the ad-hoc rule that a paren 1955`col-0-paren' It's possible to turn off the ad-hoc rule that a paren
1953 in column zero is the start of a defun. 1956 in column zero is the start of a defun.
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 4af7c359747..6d7bab7a65c 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -2575,17 +2575,24 @@ comment at the start of cc-engine.el for more info."
2575 2575
2576(defun c-cache-to-parse-ps-state (elt) 2576(defun c-cache-to-parse-ps-state (elt)
2577 ;; Create a list suitable to use as the old-state parameter to 2577 ;; Create a list suitable to use as the old-state parameter to
2578 ;; `parse-partial-sexp', out of ELT. ELT is either just a number, a buffer 2578 ;; `parse-partial-sexp', out of ELT, a member of
2579 ;; position, or it is a list (POS TYPE STARTING-POS). Here POS is the 2579 ;; `c-state-semi-nonlit-pos-cache'. ELT is either just a number, or a list
2580 ;; buffer position the other elements are pertinent for, TYPE is either 'c 2580 ;; with 2, 3, or 4 members (See `c-parse-ps-state-to-cache'). That number
2581 ;; or 'c++ (for a comment) or a character (for a string delimiter) or t 2581 ;; or the car of the list is the "position element" of ELT, the position
2582 ;; (meaning a string fence opened the string), STARTING-POS is the starting 2582 ;; where ELT is valid.
2583 ;; position of the comment or string. 2583 ;;
2584 (if (consp elt) 2584 ;; POINT is left at the postition for which the returned state is valid. It
2585 ;; will be either the position element of ELT, or one character before
2586 ;; that. (The latter happens in Emacs <= 25 and XEmacs, when ELT indicates
2587 ;; its position element directly follows a potential first character of a
2588 ;; two char construct (such as a comment opener or an escaped character).)
2589 (if (and (consp elt) (>= (length elt) 3))
2590 ;; Inside a string or comment
2585 (let ((depth 0) (containing nil) (last nil) 2591 (let ((depth 0) (containing nil) (last nil)
2586 in-string in-comment (after-quote nil) 2592 in-string in-comment (after-quote nil)
2587 (min-depth 0) com-style com-str-start (intermediate nil) 2593 (min-depth 0) com-style com-str-start (intermediate nil)
2588 (between-syntax nil) 2594 (char-1 (nth 3 elt)) ; first char of poss. 2-char construct
2595 (pos (car elt))
2589 (type (cadr elt))) 2596 (type (cadr elt)))
2590 (setq com-str-start (car (cddr elt))) 2597 (setq com-str-start (car (cddr elt)))
2591 (cond 2598 (cond
@@ -2596,28 +2603,88 @@ comment at the start of cc-engine.el for more info."
2596 com-style (if (eq type 'c++) 1 nil))) 2603 com-style (if (eq type 'c++) 1 nil)))
2597 (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state" 2604 (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state"
2598 elt))) 2605 elt)))
2599 (list depth containing last 2606 (if (memq 'pps-extended-state c-emacs-features)
2600 in-string in-comment after-quote 2607 (progn
2601 min-depth com-style com-str-start 2608 (goto-char pos)
2602 intermediate nil)) 2609 (list depth containing last
2603 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil)))) 2610 in-string in-comment after-quote
2611 min-depth com-style com-str-start
2612 intermediate char-1))
2613 (goto-char (if char-1
2614 (1- pos)
2615 pos))
2616 (list depth containing last
2617 in-string in-comment nil
2618 min-depth com-style com-str-start
2619 intermediate)))
2620
2621 ;; Not in a string or comment.
2622 (if (memq 'pps-extended-state c-emacs-features)
2623 (progn
2624 (goto-char (if (consp elt) (car elt) elt))
2625 (list 0 nil nil nil nil
2626 (and (consp elt) (eq (nth 1 elt) 9)) ; 9 is syntax code for "escape".
2627 0 nil nil nil
2628 (and (consp elt) (nth 1 elt))))
2629 (goto-char (if (consp elt) (car elt) elt))
2630 (if (and (consp elt) (cdr elt)) (backward-char))
2631 (copy-tree '(0 nil nil nil nil
2632 nil
2633 0 nil nil nil)))))
2604 2634
2605(defun c-parse-ps-state-to-cache (state) 2635(defun c-parse-ps-state-to-cache (state)
2606 ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element 2636 ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element
2607 ;; for the `c-state-semi-nonlit-pos-cache' cache. This is either POINT 2637 ;; for the `c-state-semi-nonlit-pos-cache' cache. This is one of
2608 ;; (when point is not in a literal) or a list (POINT TYPE STARTING-POS), 2638 ;; o - POINT (when point is not in a literal);
2609 ;; where TYPE is the type of the literal, either 'string, 'c, or 'c++, and 2639 ;; o - (POINT CHAR-1) (when the last character before point is potentially
2610 ;; STARTING-POS is the starting position of the comment or string. 2640 ;; the first of a two-character construct
2611 (cond 2641 ;; o - (POINT TYPE STARTING-POS) (when in a literal);
2612 ((nth 3 state) ; A string 2642 ;; o - (POINT TYPE STARTING-POS CHAR-1) (Combination of the previous two),
2613 (list (point) (nth 3 state) (nth 8 state))) 2643 ;; where TYPE is the type of the literal (either 'c, or 'c++, or the
2614 ((and (nth 4 state) ; A comment 2644 ;; character which closes the string), STARTING-POS is the starting
2615 (not (eq (nth 7 state) 'syntax-table))) ; but not a psuedo comment. 2645 ;; position of the comment or string. CHAR-1 is either the character
2616 (list (point) 2646 ;; potentially forming the first half of a two-char construct (in Emacs <=
2617 (if (eq (nth 7 state) 1) 'c++ 'c) 2647 ;; 25 and XEmacs) or the syntax of the character (in Emacs >= 26).
2618 (nth 8 state))) 2648 (if (memq 'pps-extended-state c-emacs-features)
2619 (t ; Neither string nor comment. 2649 ;; Emacs >= 26.
2620 (point)))) 2650 (let ((basic
2651 (cond
2652 ((nth 3 state) ; A string
2653 (list (point) (nth 3 state) (nth 8 state)))
2654 ((and (nth 4 state) ; A comment
2655 (not (eq (nth 7 state) 'syntax-table))) ; but not a psuedo comment.
2656 (list (point)
2657 (if (eq (nth 7 state) 1) 'c++ 'c)
2658 (nth 8 state)))
2659 (t ; Neither string nor comment.
2660 (point)))))
2661 (if (nth 10 state)
2662 (append (if (consp basic)
2663 basic
2664 (list basic))
2665 (list (nth 10 state)))
2666 basic))
2667
2668 ;; Emacs <= 25, XEmacs.
2669 (cond
2670 ((nth 3 state) ; A string
2671 (if (eq (char-before) ?\\)
2672 (list (point) (nth 3 state) (nth 8 state) ?\\)
2673 (list (point) (nth 3 state) (nth 8 state))))
2674 ((and (nth 4 state) ; comment
2675 (not (eq (nth 7 state) 'syntax-table)))
2676 (if (and (eq (char-before) ?*)
2677 (> (- (point) (nth 8 state)) 2)) ; not "/*/".
2678 (list (point)
2679 (if (eq (nth 7 state) 1) 'c++ 'c)
2680 (nth 8 state)
2681 ?*)
2682 (list (point)
2683 (if (eq (nth 7 state) 1) 'c++ 'c)
2684 (nth 8 state))))
2685 (t (if (memq (char-before) '(?/ ?\\))
2686 (list (point) (char-before))
2687 (point))))))
2621 2688
2622(defsubst c-ps-state-cache-pos (elt) 2689(defsubst c-ps-state-cache-pos (elt)
2623 ;; Get the buffer position from ELT, an element from the cache 2690 ;; Get the buffer position from ELT, an element from the cache
@@ -2637,7 +2704,7 @@ comment at the start of cc-engine.el for more info."
2637 (save-restriction 2704 (save-restriction
2638 (widen) 2705 (widen)
2639 (let ((c c-state-semi-nonlit-pos-cache) 2706 (let ((c c-state-semi-nonlit-pos-cache)
2640 elt state pos npos high-elt) 2707 elt state npos high-elt)
2641 ;; Trim the cache to take account of buffer changes. 2708 ;; Trim the cache to take account of buffer changes.
2642 (while (and c (> (c-ps-state-cache-pos (car c)) 2709 (while (and c (> (c-ps-state-cache-pos (car c))
2643 c-state-semi-nonlit-pos-cache-limit)) 2710 c-state-semi-nonlit-pos-cache-limit))
@@ -2647,29 +2714,27 @@ comment at the start of cc-engine.el for more info."
2647 (while (and c (> (c-ps-state-cache-pos (car c)) here)) 2714 (while (and c (> (c-ps-state-cache-pos (car c)) here))
2648 (setq high-elt (car c)) 2715 (setq high-elt (car c))
2649 (setq c (cdr c))) 2716 (setq c (cdr c)))
2650 (setq pos (or (and c (c-ps-state-cache-pos (car c))) 2717 (goto-char (or (and c (c-ps-state-cache-pos (car c)))
2651 (point-min))) 2718 (point-min)))
2719 (setq state
2720 (if c
2721 (c-cache-to-parse-ps-state (car c))
2722 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
2652 2723
2653 (if high-elt 2724 (when (not high-elt)
2654 (setq state (c-cache-to-parse-ps-state (car c))) 2725 ;; We need to extend the cache. Add an element to
2655 (setq elt (if c (car c) (point-min))) 2726 ;; `c-state-semi-nonlit-pos-cache' each iteration of the following.
2656 (setq state
2657 (if c
2658 (c-cache-to-parse-ps-state (car c))
2659 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
2660 (while 2727 (while
2661 ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration. 2728 (<= (setq npos (+ (point) c-state-nonlit-pos-interval)) here)
2662 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) 2729 (setq state (parse-partial-sexp (point) npos nil nil state))
2663 (setq state (parse-partial-sexp pos npos nil nil state))
2664 (setq elt (c-parse-ps-state-to-cache state)) 2730 (setq elt (c-parse-ps-state-to-cache state))
2665 (setq c-state-semi-nonlit-pos-cache 2731 (setq c-state-semi-nonlit-pos-cache
2666 (cons elt c-state-semi-nonlit-pos-cache)) 2732 (cons elt c-state-semi-nonlit-pos-cache))))
2667 (setq pos npos)))
2668 2733
2669 (if (> pos c-state-semi-nonlit-pos-cache-limit) 2734 (if (> (point) c-state-semi-nonlit-pos-cache-limit)
2670 (setq c-state-semi-nonlit-pos-cache-limit pos)) 2735 (setq c-state-semi-nonlit-pos-cache-limit (point)))
2671 2736
2672 (cons pos state))))) 2737 (cons (point) state)))))
2673 2738
2674(defun c-state-safe-place (here) 2739(defun c-state-safe-place (here)
2675 ;; Return a buffer position before HERE which is "safe", i.e. outside any 2740 ;; Return a buffer position before HERE which is "safe", i.e. outside any