aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2016-06-27 11:34:02 +0000
committerAlan Mackenzie2016-06-27 11:34:02 +0000
commit8040d99b6294ad798d4ab677ba20082b45fd2e7d (patch)
tree9c53c471d718eb1a2028168705324ffa9501cac4
parent15c307417f7bc13b27f06994dd931cb04873a26f (diff)
downloademacs-8040d99b6294ad798d4ab677ba20082b45fd2e7d.tar.gz
emacs-8040d99b6294ad798d4ab677ba20082b45fd2e7d.zip
Amend a cache so that typing into C++ raw strings has no undue delay.
Also amend the code so that low-level searches to the end of literals are done only when these positions get used. * lisp/progmodes/cc-engine.el (c-crosses-statement-barrier-p): Use the new c-literal-start instead of c-literal-limit. (c-state-semi-nonlit-pos-cache): Change the structure of this cache, such that it stores details of the literal at a point, rather than merely points outside of literals. (c-state-semi-pp-to-literal, c-state-full-pp-to-literal) (c-cache-to-parse-ps-state, c-parse-ps-state-to-cache, c-ps-state-cache-pos) (c-parse-ps-state-below, c-literal-start): New functions. (c-state-semi-safe-place): Removed. (c-in-literal): Use c-state-semi-pp-to-literal, so as not to scan to its end. (c-literal-limits, c-determine-limit-get-base): consequential amendments. (c-find-decl-spots, c-before-change-check-<>-operators, c-raw-string-pos) (c-guess-basic-syntax (CASE 2)): Avoid needless scans to end of literals. * lisp/progmodes/cc-fonts.el (c-font-lock-doc-comments): Avoid needless scans to end of literals. * lisp/progmodes/cc-mode.el (c-fl-decl-start): Avoid needless scans to end of literals. * lisp/progmodes/cc-cmds.el (c-beginning-of-defun, c-end-of-defun) (c-defun-name, c-declaration-limits): Avoid needless scans to end of literals.
-rw-r--r--lisp/progmodes/cc-cmds.el188
-rw-r--r--lisp/progmodes/cc-engine.el312
-rw-r--r--lisp/progmodes/cc-fonts.el6
-rw-r--r--lisp/progmodes/cc-mode.el6
4 files changed, 338 insertions, 174 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 59f2729c43d..f0ad2942457 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1610,8 +1610,8 @@ defun."
1610 1610
1611 ;; Move back out of any macro/comment/string we happen to be in. 1611 ;; Move back out of any macro/comment/string we happen to be in.
1612 (c-beginning-of-macro) 1612 (c-beginning-of-macro)
1613 (setq pos (c-literal-limits)) 1613 (setq pos (c-literal-start))
1614 (if pos (goto-char (car pos))) 1614 (if pos (goto-char pos))
1615 1615
1616 (setq where (c-where-wrt-brace-construct)) 1616 (setq where (c-where-wrt-brace-construct))
1617 1617
@@ -1734,8 +1734,8 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
1734 1734
1735 ;; Move back out of any macro/comment/string we happen to be in. 1735 ;; Move back out of any macro/comment/string we happen to be in.
1736 (c-beginning-of-macro) 1736 (c-beginning-of-macro)
1737 (setq pos (c-literal-limits)) 1737 (setq pos (c-literal-start))
1738 (if pos (goto-char (car pos))) 1738 (if pos (goto-char pos))
1739 1739
1740 (setq where (c-where-wrt-brace-construct)) 1740 (setq where (c-where-wrt-brace-construct))
1741 1741
@@ -1793,8 +1793,8 @@ with a brace block."
1793 (save-excursion 1793 (save-excursion
1794 ;; Move back out of any macro/comment/string we happen to be in. 1794 ;; Move back out of any macro/comment/string we happen to be in.
1795 (c-beginning-of-macro) 1795 (c-beginning-of-macro)
1796 (setq pos (c-literal-limits)) 1796 (setq pos (c-literal-start))
1797 (if pos (goto-char (car pos))) 1797 (if pos (goto-char pos))
1798 1798
1799 (setq where (c-where-wrt-brace-construct)) 1799 (setq where (c-where-wrt-brace-construct))
1800 1800
@@ -1880,103 +1880,103 @@ with a brace block."
1880 (or (save-restriction 1880 (or (save-restriction
1881 (c-narrow-to-most-enclosing-decl-block nil) 1881 (c-narrow-to-most-enclosing-decl-block nil)
1882 1882
1883 ;; Note: Some code duplication in `c-beginning-of-defun' and 1883 ;; Note: Some code duplication in `c-beginning-of-defun' and
1884 ;; `c-end-of-defun'. 1884 ;; `c-end-of-defun'.
1885 (catch 'exit 1885 (catch 'exit
1886 (let ((start (point)) 1886 (let ((start (point))
1887 (paren-state (c-parse-state)) 1887 (paren-state (c-parse-state))
1888 lim pos end-pos) 1888 lim pos end-pos)
1889 (unless (c-safe 1889 (unless (c-safe
1890 (goto-char (c-least-enclosing-brace paren-state)) 1890 (goto-char (c-least-enclosing-brace paren-state))
1891 ;; If we moved to the outermost enclosing paren 1891 ;; If we moved to the outermost enclosing paren
1892 ;; then we can use c-safe-position to set the 1892 ;; then we can use c-safe-position to set the
1893 ;; limit. Can't do that otherwise since the 1893 ;; limit. Can't do that otherwise since the
1894 ;; earlier paren pair on paren-state might very 1894 ;; earlier paren pair on paren-state might very
1895 ;; well be part of the declaration we should go 1895 ;; well be part of the declaration we should go
1896 ;; to. 1896 ;; to.
1897 (setq lim (c-safe-position (point) paren-state)) 1897 (setq lim (c-safe-position (point) paren-state))
1898 t) 1898 t)
1899 ;; At top level. Make sure we aren't inside a literal. 1899 ;; At top level. Make sure we aren't inside a literal.
1900 (setq pos (c-literal-limits 1900 (setq pos (c-literal-start
1901 (c-safe-position (point) paren-state))) 1901 (c-safe-position (point) paren-state)))
1902 (if pos (goto-char (car pos)))) 1902 (if pos (goto-char pos)))
1903 1903
1904 (when (c-beginning-of-macro) 1904 (when (c-beginning-of-macro)
1905 (throw 'exit 1905 (throw 'exit
1906 (cons (point) 1906 (cons (point)
1907 (save-excursion 1907 (save-excursion
1908 (c-end-of-macro) 1908 (c-end-of-macro)
1909 (forward-line 1) 1909 (forward-line 1)
1910 (point))))) 1910 (point)))))
1911 1911
1912 (setq pos (point))
1913 (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous)
1914 (= pos (point)))
1915 ;; We moved back over the previous defun. Skip to the next
1916 ;; one. Not using c-forward-syntactic-ws here since we
1917 ;; should not skip a macro. We can also be directly after
1918 ;; the block in a `c-opt-block-decls-with-vars-key'
1919 ;; declaration, but then we won't move significantly far
1920 ;; here.
1921 (goto-char pos)
1922 (c-forward-comments)
1923
1924 (when (and near (c-beginning-of-macro))
1925 (throw 'exit
1926 (cons (point)
1927 (save-excursion
1928 (c-end-of-macro)
1929 (forward-line 1)
1930 (point))))))
1931
1932 (if (eobp) (throw 'exit nil))
1933
1934 ;; Check if `c-beginning-of-decl-1' put us after the block in a
1935 ;; declaration that doesn't end there. We're searching back and
1936 ;; forth over the block here, which can be expensive.
1937 (setq pos (point))
1938 (if (and c-opt-block-decls-with-vars-key
1939 (progn
1940 (c-backward-syntactic-ws)
1941 (eq (char-before) ?}))
1942 (eq (car (c-beginning-of-decl-1))
1943 'previous)
1944 (save-excursion
1945 (c-end-of-decl-1)
1946 (and (> (point) pos)
1947 (setq end-pos (point)))))
1948 nil
1949 (goto-char pos))
1950
1951 (if (and (not near) (> (point) start))
1952 nil
1953
1954 ;; Try to be line oriented; position the limits at the
1955 ;; closest preceding boi, and after the next newline, that
1956 ;; isn't inside a comment, but if we hit a neighboring
1957 ;; declaration then we instead use the exact declaration
1958 ;; limit in that direction.
1959 (cons (progn
1960 (setq pos (point)) 1912 (setq pos (point))
1961 (while (and (/= (point) (c-point 'boi)) 1913 (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous)
1962 (c-backward-single-comment))) 1914 (= pos (point)))
1963 (if (/= (point) (c-point 'boi)) 1915 ;; We moved back over the previous defun. Skip to the next
1964 pos 1916 ;; one. Not using c-forward-syntactic-ws here since we
1965 (point))) 1917 ;; should not skip a macro. We can also be directly after
1966 (progn 1918 ;; the block in a `c-opt-block-decls-with-vars-key'
1967 (if end-pos 1919 ;; declaration, but then we won't move significantly far
1968 (goto-char end-pos) 1920 ;; here.
1969 (c-end-of-decl-1)) 1921 (goto-char pos)
1922 (c-forward-comments)
1923
1924 (when (and near (c-beginning-of-macro))
1925 (throw 'exit
1926 (cons (point)
1927 (save-excursion
1928 (c-end-of-macro)
1929 (forward-line 1)
1930 (point))))))
1931
1932 (if (eobp) (throw 'exit nil))
1933
1934 ;; Check if `c-beginning-of-decl-1' put us after the block in a
1935 ;; declaration that doesn't end there. We're searching back and
1936 ;; forth over the block here, which can be expensive.
1970 (setq pos (point)) 1937 (setq pos (point))
1971 (while (and (not (bolp)) 1938 (if (and c-opt-block-decls-with-vars-key
1972 (not (looking-at "\\s *$")) 1939 (progn
1973 (c-forward-single-comment))) 1940 (c-backward-syntactic-ws)
1974 (cond ((bolp) 1941 (eq (char-before) ?}))
1975 (point)) 1942 (eq (car (c-beginning-of-decl-1))
1976 ((looking-at "\\s *$") 1943 'previous)
1977 (forward-line 1) 1944 (save-excursion
1978 (point)) 1945 (c-end-of-decl-1)
1979 (t 1946 (and (> (point) pos)
1947 (setq end-pos (point)))))
1948 nil
1949 (goto-char pos))
1950
1951 (if (and (not near) (> (point) start))
1952 nil
1953
1954 ;; Try to be line oriented; position the limits at the
1955 ;; closest preceding boi, and after the next newline, that
1956 ;; isn't inside a comment, but if we hit a neighboring
1957 ;; declaration then we instead use the exact declaration
1958 ;; limit in that direction.
1959 (cons (progn
1960 (setq pos (point))
1961 (while (and (/= (point) (c-point 'boi))
1962 (c-backward-single-comment)))
1963 (if (/= (point) (c-point 'boi))
1964 pos
1965 (point)))
1966 (progn
1967 (if end-pos
1968 (goto-char end-pos)
1969 (c-end-of-decl-1))
1970 (setq pos (point))
1971 (while (and (not (bolp))
1972 (not (looking-at "\\s *$"))
1973 (c-forward-single-comment)))
1974 (cond ((bolp)
1975 (point))
1976 ((looking-at "\\s *$")
1977 (forward-line 1)
1978 (point))
1979 (t
1980 pos)))))))) 1980 pos))))))))
1981 (and (not near) 1981 (and (not near)
1982 (goto-char (point-min)) 1982 (goto-char (point-min))
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 17415a259b6..4bc4056081b 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1300,7 +1300,7 @@ comment at the start of cc-engine.el for more info."
1300 c-stmt-delim-chars)) 1300 c-stmt-delim-chars))
1301 (non-skip-list 1301 (non-skip-list
1302 (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:) 1302 (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
1303 lit-range vsemi-pos) 1303 lit-range lit-start vsemi-pos)
1304 (save-restriction 1304 (save-restriction
1305 (widen) 1305 (widen)
1306 (save-excursion 1306 (save-excursion
@@ -1315,8 +1315,8 @@ comment at the start of cc-engine.el for more info."
1315 ((and (bolp) 1315 ((and (bolp)
1316 (save-excursion 1316 (save-excursion
1317 (progn 1317 (progn
1318 (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment? 1318 (if (setq lit-start (c-literal-start from)) ; Have we landed in a string/comment?
1319 (goto-char (car lit-range))) 1319 (goto-char lit-start))
1320 (c-backward-syntactic-ws) ; ? put a limit here, maybe? 1320 (c-backward-syntactic-ws) ; ? put a limit here, maybe?
1321 (setq vsemi-pos (point)) 1321 (setq vsemi-pos (point))
1322 (c-at-vsemi-p)))) 1322 (c-at-vsemi-p))))
@@ -2279,15 +2279,110 @@ comment at the start of cc-engine.el for more info."
2279 2279
2280(defvar c-state-semi-nonlit-pos-cache nil) 2280(defvar c-state-semi-nonlit-pos-cache nil)
2281(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache) 2281(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache)
2282;; A list of buffer positions which are known not to be in a literal. This is 2282;; A list of elements which are either buffer positions (when such positions
2283;; ordered with higher positions at the front of the list. Only those which 2283;; are not in literals) or lists of the form (POS TYPE START), where POS is
2284;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid. 2284;; a buffer position inside a literal, TYPE is the type of the literal
2285;; ('string, 'c, or 'c++) and START is the start of the literal.
2285 2286
2286(defvar c-state-semi-nonlit-pos-cache-limit 1) 2287(defvar c-state-semi-nonlit-pos-cache-limit 1)
2287(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit) 2288(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit)
2288;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This is 2289;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This
2289;; reduced by buffer changes, and increased by invocations of 2290;; is reduced by buffer changes, and increased by invocations of
2290;; `c-state-literal-at'. FIXME!!! 2291;; `c-parse-ps-state-below'.
2292
2293(defun c-state-semi-pp-to-literal (here &optional not-in-delimiter)
2294 ;; Do a parse-partial-sexp from a position in the buffer before HERE which
2295 ;; isn't in a literal, and return information about HERE, either:
2296 ;; (STATE TYPE BEG) if HERE is in a literal; or
2297 ;; (STATE) otherwise,
2298 ;; where STATE is the parsing state at HERE, TYPE is the type of the literal
2299 ;; enclosing HERE, (one of 'string, 'c, 'c++) and BEG is the starting
2300 ;; position of that literal (including the delimiter).
2301 ;;
2302 ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
2303 ;; comment opener, this is recognized as being in a comment literal.
2304 ;;
2305 ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), 7
2306 ;; (comment type), and 8 (start of comment/string), and possibly 10 (in
2307 ;; newer Emacsen only, the syntax of a position after a potential first char
2308 ;; of a two char construct) of STATE are valid.
2309 (save-excursion
2310 (save-match-data
2311 (let* ((base-and-state (c-parse-ps-state-below here))
2312 (base (car base-and-state))
2313 (s (cdr base-and-state))
2314 (s (parse-partial-sexp base here nil nil s))
2315 ty)
2316 (cond
2317 ((or (nth 3 s) (nth 4 s)) ; in a string or comment
2318 (setq ty (cond
2319 ((nth 3 s) 'string)
2320 ((nth 7 s) 'c++)
2321 (t 'c)))
2322 (list s ty (nth 8 s)))
2323
2324 ((and (not not-in-delimiter) ; inside a comment starter
2325 (not (bobp))
2326 (progn (backward-char)
2327 (and (not (and (memq 'category-properties c-emacs-features)
2328 (looking-at "\\s!")))
2329 (looking-at c-comment-start-regexp))))
2330 (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++))
2331 (list s ty (point)))
2332
2333 (t (list s)))))))
2334
2335(defun c-state-full-pp-to-literal (here &optional not-in-delimiter)
2336 ;; This function will supersede c-state-pp-to-literal.
2337 ;;
2338 ;; Do a parse-partial-sexp from a position in the buffer before HERE which
2339 ;; isn't in a literal, and return information about HERE, either:
2340 ;; (STATE TYPE (BEG . END)) if HERE is in a literal; or
2341 ;; (STATE) otherwise,
2342 ;; where STATE is the parsing state at HERE, TYPE is the type of the literal
2343 ;; enclosing HERE, (one of 'string, 'c, 'c++) and (BEG . END) is the
2344 ;; boundaries of that literal (including the delimiters).
2345 ;;
2346 ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
2347 ;; comment opener, this is recognized as being in a comment literal.
2348 ;;
2349 ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), 7
2350 ;; (comment type), and 8 (start of comment/string), and possibly 10 (in
2351 ;; newer Emacsen only, the syntax of a position after a potential first char
2352 ;; of a two char construct) of STATE are valid.
2353 (save-excursion
2354 (save-match-data
2355 (let* ((base-and-state (c-parse-ps-state-below here))
2356 (base (car base-and-state))
2357 (s (cdr base-and-state))
2358 (s (parse-partial-sexp base here nil nil s))
2359 ty start)
2360 (cond
2361 ((or (nth 3 s) (nth 4 s)) ; in a string or comment
2362 (setq ty (cond
2363 ((nth 3 s) 'string)
2364 ((nth 7 s) 'c++)
2365 (t 'c)))
2366 (setq start (nth 8 s))
2367 (parse-partial-sexp here (point-max)
2368 nil ; TARGETDEPTH
2369 nil ; STOPBEFORE
2370 s ; OLDSTATE
2371 'syntax-table) ; stop at end of literal
2372 (list s ty (cons start (point))))
2373
2374 ((and (not not-in-delimiter) ; inside a comment starter
2375 (not (bobp))
2376 (progn (backward-char)
2377 (and (not (and (memq 'category-properties c-emacs-features)
2378 (looking-at "\\s!")))
2379 (looking-at c-comment-start-regexp))))
2380 (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
2381 start (point))
2382 (forward-comment 1)
2383 (list s ty (cons start (point))))
2384
2385 (t (list s)))))))
2291 2386
2292(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter) 2387(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter)
2293 ;; Do a parse-partial-sexp from FROM to TO, returning either 2388 ;; Do a parse-partial-sexp from FROM to TO, returning either
@@ -2332,6 +2427,103 @@ comment at the start of cc-engine.el for more info."
2332 2427
2333 (t `(,s))))))) 2428 (t `(,s)))))))
2334 2429
2430(defun c-cache-to-parse-ps-state (elt)
2431 ;; Create a list suitable to use as the old-state parameter to
2432 ;; `parse-partial-sexp', out of ELT. ELT is either just a number, a buffer
2433 ;; position, or it is a list (POS TYPE STARTING-POS). Here POS is the
2434 ;; buffer position the other elements are pertinent for, TYPE is either 'c
2435 ;; or 'c++ (for a comment) or a character (for a string delimiter) or t
2436 ;; (meaning a string fence opened the string), STARTING-POS is the starting
2437 ;; position of the comment or string.
2438 (if (consp elt)
2439 (let ((depth 0) (containing nil) (last nil)
2440 in-string in-comment (after-quote nil)
2441 (min-depth 0) com-style com-str-start (intermediate nil)
2442 (between-syntax nil)
2443 (type (cadr elt)))
2444 (setq com-str-start (car (cddr elt)))
2445 (cond
2446 ((or (numberp type) (eq type t)) ; A string
2447 (setq in-string type))
2448 ((memq type '(c c++)) ; A comment
2449 (setq in-comment t
2450 com-style (if (eq type 'c++) 1 nil)))
2451 (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state"
2452 elt)))
2453 (list depth containing last
2454 in-string in-comment after-quote
2455 min-depth com-style com-str-start
2456 intermediate nil))
2457 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
2458
2459(defun c-parse-ps-state-to-cache (state)
2460 ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element
2461 ;; for the `c-state-semi-nonlit-pos-cache' cache. This is either POINT
2462 ;; (when point is not in a literal) or a list (POINT TYPE STARTING-POS),
2463 ;; where TYPE is the type of the literal, either 'string, 'c, or 'c++, and
2464 ;; STARTING-POS is the starting position of the comment or string.
2465 (cond
2466 ((nth 3 state) ; A string
2467 (list (point) (nth 3 state) (nth 8 state)))
2468 ((nth 4 state) ; A comment
2469 (list (point)
2470 (if (eq (nth 7 state) 1) 'c++ 'c)
2471 (nth 8 state)))
2472 (t ; Neither string nor comment.
2473 (point))))
2474
2475(defsubst c-ps-state-cache-pos (elt)
2476 ;; Get the buffer position from ELT, an element from the cache
2477 ;; `c-state-semi-nonlit-pos-cache'.
2478 (if (atom elt)
2479 elt
2480 (car elt)))
2481
2482(defun c-parse-ps-state-below (here)
2483 ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where
2484 ;; CACHE-POS is a position not very far before HERE for which the
2485 ;; parse-partial-sexp STATE is valid. Note that the only valid elements of
2486 ;; STATE are those concerning comments and strings; STATE is the state of a
2487 ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or
2488 ;; string.
2489 (save-restriction
2490 (widen)
2491 (save-excursion
2492 (let ((c c-state-semi-nonlit-pos-cache)
2493 elt state pos npos high-elt)
2494 ;; Trim the cache to take account of buffer changes.
2495 (while (and c (> (c-ps-state-cache-pos (c-ps-state-cache-pos (car c)))
2496 c-state-semi-nonlit-pos-cache-limit))
2497 (setq c (cdr c)))
2498 (setq c-state-semi-nonlit-pos-cache c)
2499
2500 (while (and c (> (c-ps-state-cache-pos (car c)) here))
2501 (setq high-elt (car c))
2502 (setq c (cdr c)))
2503 (setq pos (or (and c (c-ps-state-cache-pos (car c)))
2504 (point-min)))
2505
2506 (if high-elt
2507 (setq state (c-cache-to-parse-ps-state (car c)))
2508 (setq elt (if c (car c) (point-min)))
2509 (setq state
2510 (if c
2511 (c-cache-to-parse-ps-state (car c))
2512 (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
2513 (while
2514 ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
2515 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
2516 (setq state (parse-partial-sexp pos npos nil nil state))
2517 (setq elt (c-parse-ps-state-to-cache state))
2518 (setq c-state-semi-nonlit-pos-cache
2519 (cons elt c-state-semi-nonlit-pos-cache))
2520 (setq pos npos)))
2521
2522 (if (> pos c-state-semi-nonlit-pos-cache-limit)
2523 (setq c-state-semi-nonlit-pos-cache-limit pos))
2524
2525 (cons pos state)))))
2526
2335(defun c-state-safe-place (here) 2527(defun c-state-safe-place (here)
2336 ;; Return a buffer position before HERE which is "safe", i.e. outside any 2528 ;; Return a buffer position before HERE which is "safe", i.e. outside any
2337 ;; string, comment, or macro. 2529 ;; string, comment, or macro.
@@ -2397,45 +2589,6 @@ comment at the start of cc-engine.el for more info."
2397 (setq c-state-nonlit-pos-cache-limit pos)) 2589 (setq c-state-nonlit-pos-cache-limit pos))
2398 pos)))) 2590 pos))))
2399 2591
2400(defun c-state-semi-safe-place (here)
2401 ;; Return a buffer position before HERE which is "safe", i.e. outside any
2402 ;; string or comment. It may be in a macro.
2403 (save-restriction
2404 (widen)
2405 (save-excursion
2406 (let ((c c-state-semi-nonlit-pos-cache)
2407 pos npos high-pos lit macro-beg macro-end)
2408 ;; Trim the cache to take account of buffer changes.
2409 (while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
2410 (setq c (cdr c)))
2411 (setq c-state-semi-nonlit-pos-cache c)
2412
2413 (while (and c (> (car c) here))
2414 (setq high-pos (car c))
2415 (setq c (cdr c)))
2416 (setq pos (or (car c) (point-min)))
2417
2418 (unless high-pos
2419 (while
2420 ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
2421 (and
2422 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
2423
2424 ;; Test for being in a literal. If so, go to after it.
2425 (progn
2426 (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
2427 (or (null lit)
2428 (prog1 (<= (cdr lit) here)
2429 (setq npos (cdr lit))))))
2430
2431 (setq pos npos)
2432 (setq c-state-semi-nonlit-pos-cache
2433 (cons pos c-state-semi-nonlit-pos-cache))))
2434
2435 (if (> pos c-state-semi-nonlit-pos-cache-limit)
2436 (setq c-state-semi-nonlit-pos-cache-limit pos))
2437 pos))))
2438
2439(defun c-state-literal-at (here) 2592(defun c-state-literal-at (here)
2440 ;; If position HERE is inside a literal, return (START . END), the 2593 ;; If position HERE is inside a literal, return (START . END), the
2441 ;; boundaries of the literal (which may be outside the accessible bit of the 2594 ;; boundaries of the literal (which may be outside the accessible bit of the
@@ -4633,8 +4786,7 @@ Note that this function might do hidden buffer changes. See the
4633comment at the start of cc-engine.el for more info." 4786comment at the start of cc-engine.el for more info."
4634 (save-restriction 4787 (save-restriction
4635 (widen) 4788 (widen)
4636 (let* ((safe-place (c-state-semi-safe-place (point))) 4789 (let ((lit (c-state-semi-pp-to-literal (point))))
4637 (lit (c-state-pp-to-literal safe-place (point))))
4638 (or (cadr lit) 4790 (or (cadr lit)
4639 (and detect-cpp 4791 (and detect-cpp
4640 (save-excursion (c-beginning-of-macro)) 4792 (save-excursion (c-beginning-of-macro))
@@ -4656,14 +4808,19 @@ Note that this function might do hidden buffer changes. See the
4656comment at the start of cc-engine.el for more info." 4808comment at the start of cc-engine.el for more info."
4657 4809
4658 (save-excursion 4810 (save-excursion
4659 (let* ((pos (point)) 4811 (let*
4660 (lim (or lim (c-state-semi-safe-place pos))) 4812 ((pos (point))
4661 (pp-to-lit (save-restriction 4813 (lit-limits
4662 (widen) 4814 (if lim
4663 (c-state-pp-to-literal lim pos not-in-delimiter))) 4815 (let ((s (parse-partial-sexp lim (point))))
4664 (state (car pp-to-lit)) 4816 (when (or (nth 3 s) (nth 4 s))
4665 (lit-limits (car (cddr pp-to-lit)))) 4817 (cons (nth 8 s)
4666 4818 (progn (parse-partial-sexp (point) (point-max)
4819 nil 'syntax-table
4820 s)
4821 (point)))))
4822 (let ((pp-to-lit (c-state-full-pp-to-literal pos not-in-delimiter)))
4823 (car (cddr pp-to-lit))))))
4667 (cond 4824 (cond
4668 (lit-limits) 4825 (lit-limits)
4669 4826
@@ -4702,6 +4859,16 @@ comment at the start of cc-engine.el for more info."
4702 (if beg (cons beg end)))))) 4859 (if beg (cons beg end))))))
4703 )))) 4860 ))))
4704 4861
4862(defun c-literal-start (&optional safe-pos)
4863 "Return the start of the string or comment surrounding point, or nil if
4864point isn't in one. SAFE-POS, if non-nil, is a position before point which is
4865a known \"safe position\", i.e. outside of any string or comment."
4866 (if safe-pos
4867 (let ((s (parse-partial-sexp safe-pos (point))))
4868 (and (or (nth 3 s) (nth 4 s))
4869 (nth 8 s)))
4870 (car (cddr (c-state-semi-pp-to-literal (point))))))
4871
4705;; In case external callers use this; it did have a docstring. 4872;; In case external callers use this; it did have a docstring.
4706(defalias 'c-literal-limits-fast 'c-literal-limits) 4873(defalias 'c-literal-limits-fast 'c-literal-limits)
4707 4874
@@ -4766,13 +4933,10 @@ comment at the start of cc-engine.el for more info."
4766 4933
4767(defsubst c-determine-limit-get-base (start try-size) 4934(defsubst c-determine-limit-get-base (start try-size)
4768 ;; Get a "safe place" approximately TRY-SIZE characters before START. 4935 ;; Get a "safe place" approximately TRY-SIZE characters before START.
4769 ;; This doesn't preserve point. 4936 ;; This defsubst doesn't preserve point.
4770 (let* ((pos (max (- start try-size) (point-min))) 4937 (let* ((pos (max (- start try-size) (point-min)))
4771 (base (c-state-semi-safe-place pos)) 4938 (s (c-state-semi-pp-to-literal pos)))
4772 (s (parse-partial-sexp base pos))) 4939 (or (car (cddr s)) pos)))
4773 (if (or (nth 4 s) (nth 3 s)) ; comment or string
4774 (nth 8 s)
4775 (point))))
4776 4940
4777(defun c-determine-limit (how-far-back &optional start try-size) 4941(defun c-determine-limit (how-far-back &optional start try-size)
4778 ;; Return a buffer position HOW-FAR-BACK non-literal characters from START 4942 ;; Return a buffer position HOW-FAR-BACK non-literal characters from START
@@ -5152,8 +5316,9 @@ comment at the start of cc-engine.el for more info."
5152 ;; arrived at something that looks like a start or else 5316 ;; arrived at something that looks like a start or else
5153 ;; resort to `c-literal-limits'. 5317 ;; resort to `c-literal-limits'.
5154 (unless (looking-at c-literal-start-regexp) 5318 (unless (looking-at c-literal-start-regexp)
5155 (let ((range (c-literal-limits))) 5319 (let ((lit-start (c-literal-start)))
5156 (if range (goto-char (car range))))) 5320 (if lit-start (goto-char lit-start)))
5321 )
5157 5322
5158 (setq start-in-literal (point))) ; end of `and' arm. 5323 (setq start-in-literal (point))) ; end of `and' arm.
5159 5324
@@ -5690,12 +5855,12 @@ comment at the start of cc-engine.el for more info."
5690 ;; 2010-01-29. 5855 ;; 2010-01-29.
5691 (save-excursion 5856 (save-excursion
5692 (c-save-buffer-state 5857 (c-save-buffer-state
5693 ((beg-lit-limits (progn (goto-char beg) (c-literal-limits))) 5858 ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
5694 (end-lit-limits (progn (goto-char end) (c-literal-limits))) 5859 (end-lit-limits (progn (goto-char end) (c-literal-limits)))
5695 new-beg new-end beg-limit end-limit) 5860 new-beg new-end beg-limit end-limit)
5696 ;; Locate the earliest < after the barrier before the changed region, 5861 ;; Locate the earliest < after the barrier before the changed region,
5697 ;; which isn't already marked as a paren. 5862 ;; which isn't already marked as a paren.
5698 (goto-char (if beg-lit-limits (car beg-lit-limits) beg)) 5863 (goto-char (or beg-lit-start beg))
5699 (setq beg-limit (c-determine-limit 512)) 5864 (setq beg-limit (c-determine-limit 512))
5700 5865
5701 ;; Remove the syntax-table/category properties from each pertinent <...> 5866 ;; Remove the syntax-table/category properties from each pertinent <...>
@@ -5854,9 +6019,8 @@ comment at the start of cc-engine.el for more info."
5854 ;; 6019 ;;
5855 ;; Note: this routine is dependant upon the correct syntax-table text 6020 ;; Note: this routine is dependant upon the correct syntax-table text
5856 ;; properties being set. 6021 ;; properties being set.
5857 (let* ((safe (c-state-semi-safe-place (point))) 6022 (let ((state (c-state-semi-pp-to-literal (point)))
5858 (state (c-state-pp-to-literal safe (point))) 6023 open-quote-pos open-paren-pos close-paren-pos close-quote-pos id)
5859 open-quote-pos open-paren-pos close-paren-pos close-quote-pos id)
5860 (save-excursion 6024 (save-excursion
5861 (when 6025 (when
5862 (and 6026 (and
@@ -5865,7 +6029,7 @@ comment at the start of cc-engine.el for more info."
5865 (or (eq (char-after) ?\") 6029 (or (eq (char-after) ?\")
5866 (search-backward "\"" (max (- (point) 17) (point-min)) t))) 6030 (search-backward "\"" (max (- (point) 17) (point-min)) t)))
5867 ((and (eq (cadr state) 'string) 6031 ((and (eq (cadr state) 'string)
5868 (goto-char (car (nth 2 state))) 6032 (goto-char (nth 2 state))
5869 (or (eq (char-after) ?\") 6033 (or (eq (char-after) ?\")
5870 (search-backward "\"" (max (- (point) 17) (point-min)) t)) 6034 (search-backward "\"" (max (- (point) 17) (point-min)) t))
5871 (not (bobp))))) 6035 (not (bobp)))))
@@ -10551,8 +10715,8 @@ comment at the start of cc-engine.el for more info."
10551 ;; versions, which results in that we get nil from 10715 ;; versions, which results in that we get nil from
10552 ;; `c-literal-limits' even when `c-in-literal' claims 10716 ;; `c-literal-limits' even when `c-in-literal' claims
10553 ;; we're inside a comment. 10717 ;; we're inside a comment.
10554 (setq placeholder (c-literal-limits lim))) 10718 (setq placeholder (c-literal-start lim)))
10555 (c-add-syntax literal (car placeholder))) 10719 (c-add-syntax literal placeholder))
10556 10720
10557 ;; CASE 3: in a cpp preprocessor macro continuation. 10721 ;; CASE 3: in a cpp preprocessor macro continuation.
10558 ((and (save-excursion 10722 ((and (save-excursion
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 3a8c9ec0ec4..52f0b0d8696 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -2480,10 +2480,10 @@ need for `pike-font-lock-extra-types'.")
2480 'font-lock-comment-face) 2480 'font-lock-comment-face)
2481 ;; Handle the case when the fontified region starts inside a 2481 ;; Handle the case when the fontified region starts inside a
2482 ;; comment. 2482 ;; comment.
2483 (let ((range (c-literal-limits))) 2483 (let ((start (c-literal-start)))
2484 (setq region-beg (point)) 2484 (setq region-beg (point))
2485 (when range 2485 (when start
2486 (goto-char (car range))) 2486 (goto-char start))
2487 (when (looking-at prefix) 2487 (when (looking-at prefix)
2488 (setq comment-beg (point))))) 2488 (setq comment-beg (point)))))
2489 2489
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 80ac08fb9e0..5ad7a010641 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1299,12 +1299,12 @@ Note that the style variables are always made local to the buffer."
1299 ;; This function is called indirectly from font locking stuff - either from 1299 ;; This function is called indirectly from font locking stuff - either from
1300 ;; c-after-change (to prepare for after-change font-locking) or from font 1300 ;; c-after-change (to prepare for after-change font-locking) or from font
1301 ;; lock context (etc.) fontification. 1301 ;; lock context (etc.) fontification.
1302 (let ((lit-limits (c-literal-limits)) 1302 (let ((lit-start (c-literal-start))
1303 (new-pos pos) 1303 (new-pos pos)
1304 bod-lim bo-decl) 1304 bod-lim bo-decl)
1305 (goto-char (c-point 'bol new-pos)) 1305 (goto-char (c-point 'bol new-pos))
1306 (when lit-limits ; Comment or string. 1306 (when lit-start ; Comment or string.
1307 (goto-char (car lit-limits))) 1307 (goto-char lit-start))
1308 (setq bod-lim (c-determine-limit 500)) 1308 (setq bod-lim (c-determine-limit 500))
1309 1309
1310 (while 1310 (while