diff options
| author | Alan Mackenzie | 2016-03-14 21:44:11 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2016-03-14 21:48:45 +0000 |
| commit | 5cc691930808ccf7afdbc53ed49ca24badd97013 (patch) | |
| tree | f986652c247488eb6c2d09d2db388599e206256e | |
| parent | 0ce37eac45f8b1279e89e854f71bb3f35fd43d29 (diff) | |
| download | emacs-5cc691930808ccf7afdbc53ed49ca24badd97013.tar.gz emacs-5cc691930808ccf7afdbc53ed49ca24badd97013.zip | |
Fix a cacheing bug, which led to inordinately slow c-beginning-of-defun.
* lisp/progmodes/cc-defs.el (c-self-bind-state-cache): New macro.
* lisp/progmodes/cc-engine.el (c-ssb-lit-begin): Always call c-parse-state
rather than just using the cache variable c-state-cache.
(c-syntactic-skip-backward): Invoke c-self-bind-state-cache to isolate calls
to c-parse-state from other uses of the parse state cache.
* lisp/progmodes/cc-cmds.el (c-beginning-of-defun, c-end-of-defun): Invoke
c-self-bind-state-cache around the processing, replacing flawed bindings of
c-state-cache.
| -rw-r--r-- | lisp/progmodes/cc-cmds.el | 245 | ||||
| -rw-r--r-- | lisp/progmodes/cc-defs.el | 23 | ||||
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 200 |
3 files changed, 246 insertions, 222 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index 6761de11700..764f44a8dd8 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el | |||
| @@ -1594,69 +1594,70 @@ defun." | |||
| 1594 | (c-region-is-active-p) | 1594 | (c-region-is-active-p) |
| 1595 | (push-mark)) | 1595 | (push-mark)) |
| 1596 | 1596 | ||
| 1597 | (c-save-buffer-state | 1597 | (c-self-bind-state-cache ; We must not share with other users of c-state-cache. |
| 1598 | (beginning-of-defun-function end-of-defun-function | 1598 | (c-save-buffer-state |
| 1599 | (start (point)) | 1599 | (beginning-of-defun-function |
| 1600 | (paren-state (copy-tree (c-parse-state))) ; This must not share list | 1600 | end-of-defun-function |
| 1601 | ; structure with other users of c-state-cache. | 1601 | (start (point)) |
| 1602 | (orig-point-min (point-min)) (orig-point-max (point-max)) | 1602 | (paren-state (c-parse-state)) |
| 1603 | lim ; Position of { which has been widened to. | 1603 | (orig-point-min (point-min)) (orig-point-max (point-max)) |
| 1604 | where pos case-fold-search) | 1604 | lim ; Position of { which has been widened to. |
| 1605 | 1605 | where pos case-fold-search) | |
| 1606 | (save-restriction | 1606 | |
| 1607 | (if (eq c-defun-tactic 'go-outward) | 1607 | (save-restriction |
| 1608 | (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace. | 1608 | (if (eq c-defun-tactic 'go-outward) |
| 1609 | paren-state orig-point-min orig-point-max))) | 1609 | (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace. |
| 1610 | 1610 | paren-state orig-point-min orig-point-max))) | |
| 1611 | ;; Move back out of any macro/comment/string we happen to be in. | 1611 | |
| 1612 | (c-beginning-of-macro) | 1612 | ;; Move back out of any macro/comment/string we happen to be in. |
| 1613 | (setq pos (c-literal-limits)) | 1613 | (c-beginning-of-macro) |
| 1614 | (if pos (goto-char (car pos))) | 1614 | (setq pos (c-literal-limits)) |
| 1615 | 1615 | (if pos (goto-char (car pos))) | |
| 1616 | (setq where (c-where-wrt-brace-construct)) | 1616 | |
| 1617 | 1617 | (setq where (c-where-wrt-brace-construct)) | |
| 1618 | (if (< arg 0) | 1618 | |
| 1619 | ;; Move forward to the closing brace of a function. | 1619 | (if (< arg 0) |
| 1620 | (progn | 1620 | ;; Move forward to the closing brace of a function. |
| 1621 | (if (memq where '(at-function-end outwith-function)) | 1621 | (progn |
| 1622 | (setq arg (1+ arg))) | 1622 | (if (memq where '(at-function-end outwith-function)) |
| 1623 | (if (< arg 0) | 1623 | (setq arg (1+ arg))) |
| 1624 | (c-while-widening-to-decl-block | 1624 | (if (< arg 0) |
| 1625 | (< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0))) | 1625 | (c-while-widening-to-decl-block |
| 1626 | ;; Move forward to the next opening brace.... | 1626 | (< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0))) |
| 1627 | (when (and (= arg 0) | 1627 | ;; Move forward to the next opening brace.... |
| 1628 | (progn | 1628 | (when (and (= arg 0) |
| 1629 | (c-while-widening-to-decl-block | 1629 | (progn |
| 1630 | (not (c-syntactic-re-search-forward "{" nil 'eob))) | 1630 | (c-while-widening-to-decl-block |
| 1631 | (eq (char-before) ?{))) | 1631 | (not (c-syntactic-re-search-forward "{" nil 'eob))) |
| 1632 | (backward-char) | 1632 | (eq (char-before) ?{))) |
| 1633 | ;; ... and backward to the function header. | 1633 | (backward-char) |
| 1634 | (c-beginning-of-decl-1) | 1634 | ;; ... and backward to the function header. |
| 1635 | t)) | 1635 | (c-beginning-of-decl-1) |
| 1636 | 1636 | t)) | |
| 1637 | ;; Move backward to the opening brace of a function, making successively | 1637 | |
| 1638 | ;; larger portions of the buffer visible as necessary. | 1638 | ;; Move backward to the opening brace of a function, making successively |
| 1639 | (when (> arg 0) | 1639 | ;; larger portions of the buffer visible as necessary. |
| 1640 | (c-while-widening-to-decl-block | 1640 | (when (> arg 0) |
| 1641 | (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))) | 1641 | (c-while-widening-to-decl-block |
| 1642 | 1642 | (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))) | |
| 1643 | (when (eq arg 0) | 1643 | |
| 1644 | ;; Go backward to this function's header. | 1644 | (when (eq arg 0) |
| 1645 | (c-beginning-of-decl-1) | 1645 | ;; Go backward to this function's header. |
| 1646 | 1646 | (c-beginning-of-decl-1) | |
| 1647 | (setq pos (point)) | 1647 | |
| 1648 | ;; We're now there, modulo comments and whitespace. | 1648 | (setq pos (point)) |
| 1649 | ;; Try to be line oriented; position point at the closest | 1649 | ;; We're now there, modulo comments and whitespace. |
| 1650 | ;; preceding boi that isn't inside a comment, but if we hit | 1650 | ;; Try to be line oriented; position point at the closest |
| 1651 | ;; the previous declaration then we use the current point | 1651 | ;; preceding boi that isn't inside a comment, but if we hit |
| 1652 | ;; instead. | 1652 | ;; the previous declaration then we use the current point |
| 1653 | (while (and (/= (point) (c-point 'boi)) | 1653 | ;; instead. |
| 1654 | (c-backward-single-comment))) | 1654 | (while (and (/= (point) (c-point 'boi)) |
| 1655 | (if (/= (point) (c-point 'boi)) | 1655 | (c-backward-single-comment))) |
| 1656 | (goto-char pos))) | 1656 | (if (/= (point) (c-point 'boi)) |
| 1657 | 1657 | (goto-char pos))) | |
| 1658 | (c-keep-region-active) | 1658 | |
| 1659 | (= arg 0))))) | 1659 | (c-keep-region-active) |
| 1660 | (= arg 0)))))) | ||
| 1660 | 1661 | ||
| 1661 | (defun c-forward-to-nth-EOF-} (n where) | 1662 | (defun c-forward-to-nth-EOF-} (n where) |
| 1662 | ;; Skip to the closing brace of the Nth function after point. If | 1663 | ;; Skip to the closing brace of the Nth function after point. If |
| @@ -1718,66 +1719,68 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'." | |||
| 1718 | (c-region-is-active-p) | 1719 | (c-region-is-active-p) |
| 1719 | (push-mark)) | 1720 | (push-mark)) |
| 1720 | 1721 | ||
| 1721 | (c-save-buffer-state | 1722 | (c-self-bind-state-cache ; c-state-cache's list structure must not be shared |
| 1722 | (beginning-of-defun-function end-of-defun-function | 1723 | ; with other users. |
| 1723 | (start (point)) | 1724 | (c-save-buffer-state |
| 1724 | (paren-state (copy-tree (c-parse-state))) ; This must not share list | 1725 | (beginning-of-defun-function |
| 1725 | ; structure with other users of c-state-cache. | 1726 | end-of-defun-function |
| 1726 | (orig-point-min (point-min)) (orig-point-max (point-max)) | 1727 | (start (point)) |
| 1727 | lim | 1728 | (paren-state (c-parse-state)) |
| 1728 | where pos case-fold-search) | 1729 | (orig-point-min (point-min)) (orig-point-max (point-max)) |
| 1729 | 1730 | lim | |
| 1730 | (save-restriction | 1731 | where pos case-fold-search) |
| 1731 | (if (eq c-defun-tactic 'go-outward) | 1732 | |
| 1732 | (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace | 1733 | (save-restriction |
| 1733 | paren-state orig-point-min orig-point-max))) | 1734 | (if (eq c-defun-tactic 'go-outward) |
| 1734 | 1735 | (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace | |
| 1735 | ;; Move back out of any macro/comment/string we happen to be in. | 1736 | paren-state orig-point-min orig-point-max))) |
| 1736 | (c-beginning-of-macro) | 1737 | |
| 1737 | (setq pos (c-literal-limits)) | 1738 | ;; Move back out of any macro/comment/string we happen to be in. |
| 1738 | (if pos (goto-char (car pos))) | 1739 | (c-beginning-of-macro) |
| 1739 | 1740 | (setq pos (c-literal-limits)) | |
| 1740 | (setq where (c-where-wrt-brace-construct)) | 1741 | (if pos (goto-char (car pos))) |
| 1742 | |||
| 1743 | (setq where (c-where-wrt-brace-construct)) | ||
| 1744 | |||
| 1745 | (if (< arg 0) | ||
| 1746 | ;; Move backwards to the } of a function | ||
| 1747 | (progn | ||
| 1748 | (if (memq where '(at-header outwith-function)) | ||
| 1749 | (setq arg (1+ arg))) | ||
| 1750 | (if (< arg 0) | ||
| 1751 | (c-while-widening-to-decl-block | ||
| 1752 | (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0))) | ||
| 1753 | (if (= arg 0) | ||
| 1754 | (c-while-widening-to-decl-block | ||
| 1755 | (progn (c-syntactic-skip-backward "^}") | ||
| 1756 | (not (eq (char-before) ?})))))) | ||
| 1757 | |||
| 1758 | ;; Move forward to the } of a function | ||
| 1759 | (if (> arg 0) | ||
| 1760 | (c-while-widening-to-decl-block | ||
| 1761 | (> (setq arg (c-forward-to-nth-EOF-} arg where)) 0)))) | ||
| 1762 | |||
| 1763 | ;; Do we need to move forward from the brace to the semicolon? | ||
| 1764 | (when (eq arg 0) | ||
| 1765 | (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc. | ||
| 1766 | (c-syntactic-re-search-forward ";")) | ||
| 1741 | 1767 | ||
| 1742 | (if (< arg 0) | 1768 | (setq pos (point)) |
| 1743 | ;; Move backwards to the } of a function | 1769 | ;; We're there now, modulo comments and whitespace. |
| 1744 | (progn | 1770 | ;; Try to be line oriented; position point after the next |
| 1745 | (if (memq where '(at-header outwith-function)) | 1771 | ;; newline that isn't inside a comment, but if we hit the |
| 1746 | (setq arg (1+ arg))) | 1772 | ;; next declaration then we use the current point instead. |
| 1747 | (if (< arg 0) | 1773 | (while (and (not (bolp)) |
| 1748 | (c-while-widening-to-decl-block | 1774 | (not (looking-at "\\s *$")) |
| 1749 | (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0))) | 1775 | (c-forward-single-comment))) |
| 1750 | (if (= arg 0) | 1776 | (cond ((bolp)) |
| 1751 | (c-while-widening-to-decl-block | 1777 | ((looking-at "\\s *$") |
| 1752 | (progn (c-syntactic-skip-backward "^}") | 1778 | (forward-line 1)) |
| 1753 | (not (eq (char-before) ?})))))) | 1779 | (t |
| 1754 | 1780 | (goto-char pos)))) | |
| 1755 | ;; Move forward to the } of a function | ||
| 1756 | (if (> arg 0) | ||
| 1757 | (c-while-widening-to-decl-block | ||
| 1758 | (> (setq arg (c-forward-to-nth-EOF-} arg where)) 0)))) | ||
| 1759 | |||
| 1760 | ;; Do we need to move forward from the brace to the semicolon? | ||
| 1761 | (when (eq arg 0) | ||
| 1762 | (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc. | ||
| 1763 | (c-syntactic-re-search-forward ";")) | ||
| 1764 | 1781 | ||
| 1765 | (setq pos (point)) | 1782 | (c-keep-region-active) |
| 1766 | ;; We're there now, modulo comments and whitespace. | 1783 | (= arg 0))))) |
| 1767 | ;; Try to be line oriented; position point after the next | ||
| 1768 | ;; newline that isn't inside a comment, but if we hit the | ||
| 1769 | ;; next declaration then we use the current point instead. | ||
| 1770 | (while (and (not (bolp)) | ||
| 1771 | (not (looking-at "\\s *$")) | ||
| 1772 | (c-forward-single-comment))) | ||
| 1773 | (cond ((bolp)) | ||
| 1774 | ((looking-at "\\s *$") | ||
| 1775 | (forward-line 1)) | ||
| 1776 | (t | ||
| 1777 | (goto-char pos)))) | ||
| 1778 | |||
| 1779 | (c-keep-region-active) | ||
| 1780 | (= arg 0)))) | ||
| 1781 | 1784 | ||
| 1782 | (defun c-defun-name () | 1785 | (defun c-defun-name () |
| 1783 | "Return the name of the current defun, or NIL if there isn't one. | 1786 | "Return the name of the current defun, or NIL if there isn't one. |
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 000995c5b53..3b9f44e55a0 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el | |||
| @@ -1258,7 +1258,8 @@ been put there by c-put-char-property. POINT remains unchanged." | |||
| 1258 | (def-edebug-spec c-clear-char-property t) | 1258 | (def-edebug-spec c-clear-char-property t) |
| 1259 | (def-edebug-spec c-clear-char-properties t) | 1259 | (def-edebug-spec c-clear-char-properties t) |
| 1260 | (def-edebug-spec c-put-overlay t) | 1260 | (def-edebug-spec c-put-overlay t) |
| 1261 | (def-edebug-spec c-delete-overlay t) ;)) | 1261 | (def-edebug-spec c-delete-overlay t) |
| 1262 | (def-edebug-spec c-self-bind-state-cache t);)) | ||
| 1262 | 1263 | ||
| 1263 | 1264 | ||
| 1264 | ;;; Functions. | 1265 | ;;; Functions. |
| @@ -1397,6 +1398,26 @@ been put there by c-put-char-property. POINT remains unchanged." | |||
| 1397 | (save-restriction | 1398 | (save-restriction |
| 1398 | (widen) | 1399 | (widen) |
| 1399 | (c-set-cpp-delimiters ,beg ,end))))) | 1400 | (c-set-cpp-delimiters ,beg ,end))))) |
| 1401 | |||
| 1402 | (defmacro c-self-bind-state-cache (&rest forms) | ||
| 1403 | ;; Bind the state cache to itself and execute the FORMS. It is assumed that no | ||
| 1404 | ;; buffer changes will happen in FORMS, and no hidden buffer changes which could | ||
| 1405 | ;; affect the parsing will be made by FORMS. | ||
| 1406 | `(let ((c-state-cache (copy-tree c-state-cache)) | ||
| 1407 | (c-state-cache-good-pos c-state-cache-good-pos) | ||
| 1408 | ;(c-state-nonlit-pos-cache (copy-tree c-state-nonlit-pos-cache)) | ||
| 1409 | ;(c-state-nonlit-pos-cache-limit c-state-nonlit-pos-cache-limit) | ||
| 1410 | ;(c-state-semi-nonlit-pos-cache (copy-treec c-state-semi-nonlit-pos-cache)) | ||
| 1411 | ;(c-state-semi-nonlit-pos-cache-limit c-state-semi-nonlit-pos-cache) | ||
| 1412 | (c-state-brace-pair-desert (copy-tree c-state-brace-pair-desert)) | ||
| 1413 | (c-state-point-min c-state-point-min) | ||
| 1414 | (c-state-point-min-lit-type c-state-point-min-lit-type) | ||
| 1415 | (c-state-point-min-lit-start c-state-point-min-lit-start) | ||
| 1416 | (c-state-min-scan-pos c-state-min-scan-pos) | ||
| 1417 | (c-state-old-cpp-beg c-state-old-cpp-beg) | ||
| 1418 | (c-state-old-cpp-end c-state-old-cpp-end)) | ||
| 1419 | ,@forms)) | ||
| 1420 | |||
| 1400 | 1421 | ||
| 1401 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 1422 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 1402 | ;; The following macros are to be used only in `c-parse-state' and its | 1423 | ;; The following macros are to be used only in `c-parse-state' and its |
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 69a2a53d5c9..afe87c5ee6a 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -4259,8 +4259,7 @@ comment at the start of cc-engine.el for more info." | |||
| 4259 | (setq safe-pos-list (cdr safe-pos-list))) | 4259 | (setq safe-pos-list (cdr safe-pos-list))) |
| 4260 | (unless (setq safe-pos (car-safe safe-pos-list)) | 4260 | (unless (setq safe-pos (car-safe safe-pos-list)) |
| 4261 | (setq safe-pos (max (or (c-safe-position | 4261 | (setq safe-pos (max (or (c-safe-position |
| 4262 | (point) (or c-state-cache | 4262 | (point) (c-parse-state)) |
| 4263 | (c-parse-state))) | ||
| 4264 | 0) | 4263 | 0) |
| 4265 | (point-min)) | 4264 | (point-min)) |
| 4266 | safe-pos-list (list safe-pos))) | 4265 | safe-pos-list (list safe-pos))) |
| @@ -4308,107 +4307,108 @@ Non-nil is returned if the point moved, nil otherwise. | |||
| 4308 | Note that this function might do hidden buffer changes. See the | 4307 | Note that this function might do hidden buffer changes. See the |
| 4309 | comment at the start of cc-engine.el for more info." | 4308 | comment at the start of cc-engine.el for more info." |
| 4310 | 4309 | ||
| 4311 | (let ((start (point)) | 4310 | (c-self-bind-state-cache |
| 4312 | state-2 | 4311 | (let ((start (point)) |
| 4313 | ;; A list of syntactically relevant positions in descending | 4312 | state-2 |
| 4314 | ;; order. It's used to avoid scanning repeatedly over | 4313 | ;; A list of syntactically relevant positions in descending |
| 4315 | ;; potentially large regions with `parse-partial-sexp' to verify | 4314 | ;; order. It's used to avoid scanning repeatedly over |
| 4316 | ;; each position. Used in `c-ssb-lit-begin' | 4315 | ;; potentially large regions with `parse-partial-sexp' to verify |
| 4317 | safe-pos-list | 4316 | ;; each position. Used in `c-ssb-lit-begin' |
| 4318 | ;; The result from `c-beginning-of-macro' at the start position or the | 4317 | safe-pos-list |
| 4319 | ;; start position itself if it isn't within a macro. Evaluated on | 4318 | ;; The result from `c-beginning-of-macro' at the start position or the |
| 4320 | ;; demand. | 4319 | ;; start position itself if it isn't within a macro. Evaluated on |
| 4321 | start-macro-beg | 4320 | ;; demand. |
| 4322 | ;; The earliest position after the current one with the same paren | 4321 | start-macro-beg |
| 4323 | ;; level. Used only when `paren-level' is set. | 4322 | ;; The earliest position after the current one with the same paren |
| 4324 | lit-beg | 4323 | ;; level. Used only when `paren-level' is set. |
| 4325 | (paren-level-pos (point))) | 4324 | lit-beg |
| 4326 | 4325 | (paren-level-pos (point))) | |
| 4327 | (while | 4326 | |
| 4328 | (progn | 4327 | (while |
| 4329 | ;; The next loop "tries" to find the end point each time round, | 4328 | (progn |
| 4330 | ;; loops when it hasn't succeeded. | 4329 | ;; The next loop "tries" to find the end point each time round, |
| 4331 | (while | 4330 | ;; loops when it hasn't succeeded. |
| 4332 | (and | 4331 | (while |
| 4333 | (let ((pos (point))) | 4332 | (and |
| 4334 | (while (and | 4333 | (let ((pos (point))) |
| 4335 | (< (skip-chars-backward skip-chars limit) 0) | 4334 | (while (and |
| 4336 | ;; Don't stop inside a literal. | 4335 | (< (skip-chars-backward skip-chars limit) 0) |
| 4337 | (when (setq lit-beg (c-ssb-lit-begin)) | 4336 | ;; Don't stop inside a literal. |
| 4338 | (goto-char lit-beg) | 4337 | (when (setq lit-beg (c-ssb-lit-begin)) |
| 4339 | t))) | 4338 | (goto-char lit-beg) |
| 4340 | (< (point) pos)) | 4339 | t))) |
| 4340 | (< (point) pos)) | ||
| 4341 | |||
| 4342 | (let ((pos (point)) state-2 pps-end-pos) | ||
| 4341 | 4343 | ||
| 4342 | (let ((pos (point)) state-2 pps-end-pos) | 4344 | (cond |
| 4345 | ((and paren-level | ||
| 4346 | (save-excursion | ||
| 4347 | (setq state-2 (parse-partial-sexp | ||
| 4348 | pos paren-level-pos -1) | ||
| 4349 | pps-end-pos (point)) | ||
| 4350 | (/= (car state-2) 0))) | ||
| 4351 | ;; Not at the right level. | ||
| 4352 | |||
| 4353 | (if (and (< (car state-2) 0) | ||
| 4354 | ;; We stop above if we go out of a paren. | ||
| 4355 | ;; Now check whether it precedes or is | ||
| 4356 | ;; nested in the starting sexp. | ||
| 4357 | (save-excursion | ||
| 4358 | (setq state-2 | ||
| 4359 | (parse-partial-sexp | ||
| 4360 | pps-end-pos paren-level-pos | ||
| 4361 | nil nil state-2)) | ||
| 4362 | (< (car state-2) 0))) | ||
| 4363 | |||
| 4364 | ;; We've stopped short of the starting position | ||
| 4365 | ;; so the hit was inside a nested list. Go up | ||
| 4366 | ;; until we are at the right level. | ||
| 4367 | (condition-case nil | ||
| 4368 | (progn | ||
| 4369 | (goto-char (scan-lists pos -1 | ||
| 4370 | (- (car state-2)))) | ||
| 4371 | (setq paren-level-pos (point)) | ||
| 4372 | (if (and limit (>= limit paren-level-pos)) | ||
| 4373 | (progn | ||
| 4374 | (goto-char limit) | ||
| 4375 | nil) | ||
| 4376 | t)) | ||
| 4377 | (error | ||
| 4378 | (goto-char (or limit (point-min))) | ||
| 4379 | nil)) | ||
| 4380 | |||
| 4381 | ;; The hit was outside the list at the start | ||
| 4382 | ;; position. Go to the start of the list and exit. | ||
| 4383 | (goto-char (1+ (elt state-2 1))) | ||
| 4384 | nil)) | ||
| 4385 | |||
| 4386 | ((c-beginning-of-macro limit) | ||
| 4387 | ;; Inside a macro. | ||
| 4388 | (if (< (point) | ||
| 4389 | (or start-macro-beg | ||
| 4390 | (setq start-macro-beg | ||
| 4391 | (save-excursion | ||
| 4392 | (goto-char start) | ||
| 4393 | (c-beginning-of-macro limit) | ||
| 4394 | (point))))) | ||
| 4395 | t | ||
| 4396 | |||
| 4397 | ;; It's inside the same macro we started in so it's | ||
| 4398 | ;; a relevant match. | ||
| 4399 | (goto-char pos) | ||
| 4400 | nil)))))) | ||
| 4343 | 4401 | ||
| 4344 | (cond | 4402 | (> (point) |
| 4345 | ((and paren-level | 4403 | (progn |
| 4346 | (save-excursion | 4404 | ;; Skip syntactic ws afterwards so that we don't stop at the |
| 4347 | (setq state-2 (parse-partial-sexp | 4405 | ;; end of a comment if `skip-chars' is something like "^/". |
| 4348 | pos paren-level-pos -1) | 4406 | (c-backward-syntactic-ws) |
| 4349 | pps-end-pos (point)) | 4407 | (point))))) |
| 4350 | (/= (car state-2) 0))) | ||
| 4351 | ;; Not at the right level. | ||
| 4352 | |||
| 4353 | (if (and (< (car state-2) 0) | ||
| 4354 | ;; We stop above if we go out of a paren. | ||
| 4355 | ;; Now check whether it precedes or is | ||
| 4356 | ;; nested in the starting sexp. | ||
| 4357 | (save-excursion | ||
| 4358 | (setq state-2 | ||
| 4359 | (parse-partial-sexp | ||
| 4360 | pps-end-pos paren-level-pos | ||
| 4361 | nil nil state-2)) | ||
| 4362 | (< (car state-2) 0))) | ||
| 4363 | |||
| 4364 | ;; We've stopped short of the starting position | ||
| 4365 | ;; so the hit was inside a nested list. Go up | ||
| 4366 | ;; until we are at the right level. | ||
| 4367 | (condition-case nil | ||
| 4368 | (progn | ||
| 4369 | (goto-char (scan-lists pos -1 | ||
| 4370 | (- (car state-2)))) | ||
| 4371 | (setq paren-level-pos (point)) | ||
| 4372 | (if (and limit (>= limit paren-level-pos)) | ||
| 4373 | (progn | ||
| 4374 | (goto-char limit) | ||
| 4375 | nil) | ||
| 4376 | t)) | ||
| 4377 | (error | ||
| 4378 | (goto-char (or limit (point-min))) | ||
| 4379 | nil)) | ||
| 4380 | |||
| 4381 | ;; The hit was outside the list at the start | ||
| 4382 | ;; position. Go to the start of the list and exit. | ||
| 4383 | (goto-char (1+ (elt state-2 1))) | ||
| 4384 | nil)) | ||
| 4385 | |||
| 4386 | ((c-beginning-of-macro limit) | ||
| 4387 | ;; Inside a macro. | ||
| 4388 | (if (< (point) | ||
| 4389 | (or start-macro-beg | ||
| 4390 | (setq start-macro-beg | ||
| 4391 | (save-excursion | ||
| 4392 | (goto-char start) | ||
| 4393 | (c-beginning-of-macro limit) | ||
| 4394 | (point))))) | ||
| 4395 | t | ||
| 4396 | |||
| 4397 | ;; It's inside the same macro we started in so it's | ||
| 4398 | ;; a relevant match. | ||
| 4399 | (goto-char pos) | ||
| 4400 | nil)))))) | ||
| 4401 | |||
| 4402 | (> (point) | ||
| 4403 | (progn | ||
| 4404 | ;; Skip syntactic ws afterwards so that we don't stop at the | ||
| 4405 | ;; end of a comment if `skip-chars' is something like "^/". | ||
| 4406 | (c-backward-syntactic-ws) | ||
| 4407 | (point))))) | ||
| 4408 | 4408 | ||
| 4409 | ;; We might want to extend this with more useful return values in | 4409 | ;; We might want to extend this with more useful return values in |
| 4410 | ;; the future. | 4410 | ;; the future. |
| 4411 | (/= (point) start))) | 4411 | (/= (point) start)))) |
| 4412 | 4412 | ||
| 4413 | ;; The following is an alternative implementation of | 4413 | ;; The following is an alternative implementation of |
| 4414 | ;; `c-syntactic-skip-backward' that uses backward movement to keep | 4414 | ;; `c-syntactic-skip-backward' that uses backward movement to keep |