# HG changeset patch # User Katsumi Yamaoka # Date 1271198964 0 # Node ID eb72bd4ec8f0bd70a02b9f64744ef15f5840c0b2 # Parent 744ecddd96434ae1b0d64ba1f5c9f6c8134863c8# Parent 3022f1f90ee233518231221c8f70881611feedfa Merge from mainline. diff -r 744ecddd9643 -r eb72bd4ec8f0 .bzrignore --- a/.bzrignore Mon Apr 12 00:59:45 2010 +0000 +++ b/.bzrignore Tue Apr 13 22:49:24 2010 +0000 @@ -10,6 +10,7 @@ oo oo-spd autom4te.cache +*.dSYM *.elc *.exe DOC @@ -48,6 +49,7 @@ lisp/cus-load.el lisp/eshell/esh-groups.el lisp/finder-inf.el +nextstep/Emacs.app nt/config.log src/buildobj.h src/config.h diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/ChangeLog --- a/lisp/ChangeLog Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/ChangeLog Tue Apr 13 22:49:24 2010 +0000 @@ -134,11 +134,6 @@ * indent.el (indent-for-tab-command): Doc fix. -2010-03-22 Alan Mackenzie - - * progmodes/cc-engine.el (c-remove-stale-state-cache): - Fix off-by-one error. Fixes bug #5747. - 2010-03-22 Juanma Barranquero * image-dired.el (image-dired-display-thumbs): Fix typo in docstring. @@ -287,11 +282,6 @@ * calendar/cal-hebrew.el (holiday-hebrew-passover): Fix date of Yom HaAtzma'ut when it falls on a Monday (rule changed in 2004). -2010-03-01 Alan Mackenzie - - * progmodes/cc-engine.el (c-remove-stale-state-cache): - Correct previous patch. - 2010-03-01 Kenichi Handa * language/burmese.el (burmese-composable-pattern): Rename from @@ -303,11 +293,6 @@ (otf-script-alist): Likewise. (setup-default-fontset): Likewise. Re-fix :otf spec. -2010-03-01 Alan Mackenzie - - * cc-engine.el (c-remove-stale-state-cache): Take account of when - `good-pos' is in the same macro as `here'. Fixes bug#5649. - 2010-02-28 Katsumi Yamaoka * menu-bar.el (menu-bar-manuals-menu): Fix typo. @@ -373,16 +358,6 @@ * mail/sendmail.el (send-mail-function): Autoload the call to custom-initialize-delay, not otherwise preserved in loaddefs.el. -2010-02-25 Alan Mackenzie - - * progmodes/cc-engine.el (c-clear-<-pair-props) - (c-clear->-pair-props): Correct to wipe category text props, not - syntax-table ones. - - * progmodes/cc-mode.el (c-after-change): Remove any hard - syntax-table properties for <, > which, e.g., C-y has - inopportunely converted from category properties. - 2010-02-24 Chong Yidong * files.el (hack-local-variables-filter): For eval forms, also @@ -720,33 +695,6 @@ (doc-view-pdf->png): Don't rely on doc-view-pdf/ps->png for the few windows that are not yet showing images. -2010-02-04 Alan Mackenzie - - Change strategy for marking < and > as template delimiters: mark - them strictly in matching pairs. - - * cc-mode.el (c-before-change): - Use c-get-state-before-change-functions. - (c-common-init): Adapt to use - c-get-state-before-change-functions (note plural). - - * cc-langs.el (c-no-parens-syntax-table): New syntax table, used - for searching syntactically for matching s. - (c-get-state-before-change-functions): New language variable (note - the plural) which supersedes c-get-state-before-change-function. - - * cc-engine.el (c-clear-<-pair-props, c-clear->-pair-props) - (c-clear-<>-pair-props, c-clear-<-pair-props-if-match-after) - (c-clear->-pair-props-if-match-before) - (c-before-change-check-<>-operators): New functions. - (c-after-change-check-<>-operators): Use macro - c-unmark-<->-as-paren. - - * cc-defs.el (c-search-backward-char-property): New macro. - - * cc-cmds.el (c-electric-lt-gt): Do not set text properties on < - and > any more. (These will be handled by font locking.) - 2010-02-04 Michael Albinus * dired.el (dired-revert): If DIRED-DIRECTORY is a cons cell, call diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-cmds.el --- a/lisp/progmodes/cc-cmds.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-cmds.el Tue Apr 13 22:49:24 2010 +0000 @@ -1086,76 +1086,104 @@ (interactive "*P") (let ((c-echo-syntactic-information-p nil) - final-pos close-paren-inserted found-delim) + final-pos close-paren-inserted) (self-insert-command (prefix-numeric-value arg)) (setq final-pos (point)) -;;;; 2010-01-31: There used to be code here to put a syntax-table text -;;;; property on the new < or > and its mate (if any) when they are template -;;;; parens. This is now done in an after-change function. + (c-save-buffer-state (c-parse-and-markup-<>-arglists + c-restricted-<>-arglists + <-pos) + + (when c-recognize-<>-arglists + (if (eq last-command-event ?<) + (when (and (progn + (backward-char) + (= (point) + (progn + (c-beginning-of-current-token) + (point)))) + (progn + (c-backward-token-2) + (looking-at c-opt-<>-sexp-key))) + (c-mark-<-as-paren (1- final-pos))) + + ;; It's a ">". Check if there's an earlier "<" which either has + ;; open paren syntax already or that can be recognized as an arglist + ;; together with this ">". Note that this won't work in cases like + ;; "template " but they ought to be rare. + + (save-restriction + ;; Narrow to avoid that `c-forward-<>-arglist' below searches past + ;; our position. + (narrow-to-region (point-min) final-pos) + + (while (and + (progn + (goto-char final-pos) + (c-syntactic-skip-backward "^<;}" nil t) + (eq (char-before) ?<)) + (progn + (backward-char) + ;; If the "<" already got open paren syntax we know we + ;; have the matching closer. Handle it and exit the + ;; loop. + (if (looking-at "\\s\(") + (progn + (c-mark->-as-paren (1- final-pos)) + (setq close-paren-inserted t) + nil) + t)) + + (progn + (setq <-pos (point)) + (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (or (looking-at c-opt-<>-sexp-key) + (not (looking-at c-keywords-regexp))) + + (let ((c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists + (containing-sexp + (c-most-enclosing-brace (c-parse-state)))) + (when (and containing-sexp + (progn (goto-char containing-sexp) + (eq (char-after) ?\()) + (not (eq (get-text-property (point) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + (goto-char <-pos) + (c-forward-<>-arglist nil)) + + ;; Loop here if the "<" we found above belongs to a nested + ;; angle bracket sexp. When we start over we'll find the + ;; previous or surrounding sexp. + (if (< (point) final-pos) + t + (setq close-paren-inserted t) + nil))))))) + (goto-char final-pos) ;; Indent the line if appropriate. - (when (and c-electric-flag c-syntactic-indentation c-recognize-<>-arglists) - (setq found-delim - (if (eq last-command-event ?<) - ;; If a <, basically see if it's got "template" before it ..... - (or (and (progn - (backward-char) - (= (point) - (progn (c-beginning-of-current-token) (point)))) - (progn - (c-backward-token-2) - (looking-at c-opt-<>-sexp-key))) - ;; ..... or is a C++ << operator. - (and (c-major-mode-is 'c++-mode) - (progn - (goto-char (1- final-pos)) - (c-beginning-of-current-token) - (looking-at "<<")) - (>= (match-end 0) final-pos))) - - ;; It's a >. Either a C++ >> operator. ...... - (or (and (c-major-mode-is 'c++-mode) - (progn - (goto-char (1- final-pos)) - (c-beginning-of-current-token) - (looking-at ">>")) - (>= (match-end 0) final-pos)) - ;; ...., or search back for a < which isn't already marked as an - ;; opening template delimiter. - (save-restriction - (widen) - ;; Narrow to avoid `c-forward-<>-arglist' below searching past - ;; our position. - (narrow-to-region (point-min) final-pos) - (goto-char final-pos) - (while - (and - (progn - (c-syntactic-skip-backward "^<;}" nil t) - (eq (char-before) ?<)) - (progn - (backward-char) - (looking-at "\\s\(")))) - (and (eq (char-after) ?<) - (not (looking-at "\\s\(")) - (progn (c-backward-syntactic-ws) - (c-simple-skip-symbol-backward)) - (or (looking-at c-opt-<>-sexp-key) - (not (looking-at c-keywords-regexp))))))))) - - (goto-char final-pos) - (when found-delim - (indent-according-to-mode) - (when (and (eq (char-before) ?>) - (not executing-kbd-macro) - blink-paren-function) - ;; Note: Most paren blink functions, such as the standard - ;; `blink-matching-open', currently doesn't handle paren chars - ;; marked with text properties very well. Maybe we should avoid - ;; this call for the time being? - (funcall blink-paren-function))))) + (when (and c-electric-flag c-syntactic-indentation) + (backward-char) + (when (prog1 (or (looking-at "\\s\(\\|\\s\)") + (and (c-major-mode-is 'c++-mode) + (progn + (c-beginning-of-current-token) + (looking-at "<<\\|>>")) + (= (match-end 0) final-pos))) + (goto-char final-pos)) + (indent-according-to-mode))) + + (when (and close-paren-inserted + (not executing-kbd-macro) + blink-paren-function) + ;; Note: Most paren blink functions, such as the standard + ;; `blink-matching-open', currently doesn't handle paren chars + ;; marked with text properties very well. Maybe we should avoid + ;; this call for the time being? + (funcall blink-paren-function)))) (defun c-electric-paren (arg) "Insert a parenthesis. diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-defs.el --- a/lisp/progmodes/cc-defs.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-defs.el Tue Apr 13 22:49:24 2010 +0000 @@ -1029,44 +1029,6 @@ ;; Emacs. `(remove-text-properties ,from ,to '(,property nil)))) -(defmacro c-search-forward-char-property (property value &optional limit) - "Search forward for a text-property PROPERTY having value VALUE. -LIMIT bounds the search. The comparison is done with `equal'. - -Leave point just after the character, and set the match data on -this character, and return point. If VALUE isn't found, Return -nil; point is then left undefined." - `(let ((place (point))) - (while - (and - (< place ,(or limit '(point-max))) - (not (equal (get-text-property place ,property) ,value))) - (setq place (next-single-property-change - place ,property nil ,(or limit '(point-max))))) - (when (< place ,(or limit '(point-max))) - (goto-char place) - (search-forward-regexp ".") ; to set the match-data. - (point)))) - -(defmacro c-search-backward-char-property (property value &optional limit) - "Search backward for a text-property PROPERTY having value VALUE. -LIMIT bounds the search. The comparison is done with `equal'. - -Leave point just before the character, set the match data on this -character, and return point. If VALUE isn't found, Return nil; -point is then left undefined." - `(let ((place (point))) - (while - (and - (> place ,(or limit '(point-min))) - (not (equal (get-text-property (1- place) ,property) ,value))) - (setq place (previous-single-property-change - place ,property nil ,(or limit '(point-min))))) - (when (> place ,(or limit '(point-max))) - (goto-char place) - (search-backward-regexp ".") ; to set the match-data. - (point)))) - (defun c-clear-char-property-with-value-function (from to property value) "Remove all text-properties PROPERTY from the region (FROM, TO) which have the value VALUE, as tested by `equal'. These @@ -1183,117 +1145,23 @@ (goto-char (point-max))))) (defconst c-<-as-paren-syntax '(4 . ?>)) -(put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) (defsubst c-mark-<-as-paren (pos) - ;; Mark the "<" character at POS as a template opener using the - ;; `syntax-table' property via the `category' property. + ;; Mark the "<" character at POS as an sexp list opener using the + ;; syntax-table property. ;; - ;; This function does a hidden buffer change. Note that we use - ;; indirection through the `category' text property. This allows us to - ;; toggle the property in all template brackets simultaneously and - ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-put-char-property pos 'category 'c-<-as-paren-syntax)) + ;; This function does a hidden buffer change. + (c-put-char-property pos 'syntax-table c-<-as-paren-syntax)) (defconst c->-as-paren-syntax '(5 . ?<)) -(put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax) (defsubst c-mark->-as-paren (pos) ;; Mark the ">" character at POS as an sexp list closer using the ;; syntax-table property. ;; - ;; This function does a hidden buffer change. Note that we use - ;; indirection through the `category' text property. This allows us to - ;; toggle the property in all template brackets simultaneously and - ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-put-char-property pos 'category 'c->-as-paren-syntax)) - -(defsubst c-unmark-<->-as-paren (pos) - ;; Unmark the "<" or "<" character at POS as an sexp list opener using - ;; the syntax-table property indirectly through the `category' text - ;; property. - ;; - ;; This function does a hidden buffer change. Note that we use - ;; indirection through the `category' text property. This allows us to - ;; toggle the property in all template brackets simultaneously and - ;; cheaply. We use this, for instance, in `c-parse-state'. - (c-clear-char-property pos 'category)) - -(defsubst c-suppress-<->-as-parens () - ;; Suppress the syntactic effect of all marked < and > as parens. Note - ;; that this effect is NOT buffer local. You should probably not use - ;; this directly, but only through the macro - ;; `c-with-<->-as-parens-suppressed' - (put 'c-<-as-paren-syntax 'syntax-table nil) - (put 'c->-as-paren-syntax 'syntax-table nil)) - -(defsubst c-restore-<->-as-parens () - ;; Restore the syntactic effect of all marked s as parens. This - ;; has no effect on unmarked s - (put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) - (put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax)) - -(defmacro c-with-<->-as-parens-suppressed (&rest forms) - ;; Like progn, except that the paren property is suppressed on all - ;; template brackets whilst they are running. This macro does a hidden - ;; buffer change. - `(unwind-protect - (progn - (c-suppress-<->-as-parens) - ,@forms) - (c-restore-<->-as-parens))) - -;;;;;;;;;;;;;;; + ;; This function does a hidden buffer change. + (c-put-char-property pos 'syntax-table c->-as-paren-syntax)) -(defconst c-cpp-delimiter '(14)) ; generic comment syntax -;; This is the value of the `category' text property placed on every # -;; which introduces a CPP construct and every EOL (or EOB, or character -;; preceding //, etc.) which terminates it. We can instantly "comment -;; out" all CPP constructs by giving `c-cpp-delimiter' a syntax-table -;; propery '(14) (generic comment delimiter). -(defmacro c-set-cpp-delimiters (beg end) - ;; This macro does a hidden buffer change. - `(progn - (c-put-char-property ,beg 'category 'c-cpp-delimiter) - (if (< ,end (point-max)) - (c-put-char-property ,end 'category 'c-cpp-delimiter)))) -(defmacro c-clear-cpp-delimiters (beg end) - ;; This macro does a hidden buffer change. - `(progn - (c-clear-char-property ,beg 'category) - (if (< ,end (point-max)) - (c-clear-char-property ,end 'category)))) - -(defsubst c-comment-out-cpps () - ;; Render all preprocessor constructs syntactically commented out. - (put 'c-cpp-delimiter 'syntax-table c-cpp-delimiter)) -(defsubst c-uncomment-out-cpps () - ;; Restore the syntactic visibility of preprocessor constructs. - (put 'c-cpp-delimiter 'syntax-table nil)) - -(defmacro c-with-cpps-commented-out (&rest forms) - ;; Execute FORMS... whilst the syntactic effect of all characters in - ;; all CPP regions is suppressed. In particular, this is to suppress - ;; the syntactic significance of parens/braces/brackets to functions - ;; such as `scan-lists' and `parse-partial-sexp'. - `(unwind-protect - (c-save-buffer-state () - (c-comment-out-cpps) - ,@forms) - (c-save-buffer-state () - (c-uncomment-out-cpps)))) - -(defmacro c-with-all-but-one-cpps-commented-out (beg end &rest forms) - ;; Execute FORMS... whilst the syntactic effect of all characters in - ;; every CPP region APART FROM THE ONE BETWEEN BEG and END is - ;; suppressed. - `(unwind-protect - (c-save-buffer-state () - (c-clear-cpp-delimiters ,beg ,end) - ,`(c-with-cpps-commented-out ,@forms)) - (c-save-buffer-state () - (c-set-cpp-delimiters ,beg ,end)))) - (defsubst c-intersect-lists (list alist) ;; return the element of ALIST that matches the first element found ;; in LIST. Uses assq. diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-engine.el --- a/lisp/progmodes/cc-engine.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-engine.el Tue Apr 13 22:49:24 2010 +0000 @@ -79,10 +79,6 @@ ;; Note: This doc is for internal use only. Other packages should not ;; assume that these text properties are used as described here. ;; -;; 'category -;; Used for "indirection". With its help, some other property can -;; be cheaply and easily switched on or off everywhere it occurs. -;; ;; 'syntax-table ;; Used to modify the syntax of some characters. It is used to ;; mark the "<" and ">" of angle bracket parens with paren syntax, and @@ -260,27 +256,6 @@ (forward-char) t)))) -(defun c-syntactic-end-of-macro () - ;; Go to the end of a CPP directive, or a "safe" pos just before. - ;; - ;; This is normally the end of the next non-escaped line. A "safe" - ;; position is one not within a string or comment. (The EOL on a line - ;; comment is NOT "safe"). - ;; - ;; This function must only be called from the beginning of a CPP construct. - ;; - ;; Note that this function might do hidden buffer changes. See the comment - ;; at the start of cc-engine.el for more info. - (let* ((here (point)) - (there (progn (c-end-of-macro) (point))) - (s (parse-partial-sexp here there))) - (while (and (or (nth 3 s) ; in a string - (nth 4 s)) ; in a comment (maybe at end of line comment) - (> there here)) ; No infinite loops, please. - (setq there (1- (nth 8 s))) - (setq s (parse-partial-sexp here there))) - (point))) - (defun c-forward-over-cpp-define-id () ;; Assuming point is at the "#" that introduces a preprocessor ;; directive, it's moved forward to the end of the identifier which is @@ -1972,18 +1947,10 @@ ;; A system for finding noteworthy parens before the point. -(defconst c-state-cache-too-far 5000) -;; A maximum comfortable scanning distance, e.g. between -;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When -;; this distance is exceeded, we take "emergency meausures", e.g. by clearing -;; the cache and starting again from point-min or a beginning of defun. This -;; value can be tuned for efficiency or set to a lower value for testing. - (defvar c-state-cache nil) (make-variable-buffer-local 'c-state-cache) ;; The state cache used by `c-parse-state' to cut down the amount of -;; searching. It's the result from some earlier `c-parse-state' call. See -;; `c-parse-state''s doc string for details of its structure. +;; searching. It's the result from some earlier `c-parse-state' call. ;; ;; The use of the cached info is more effective if the next ;; `c-parse-state' call is on a line close by the one the cached state @@ -1992,12 +1959,18 @@ ;; most effective if `c-parse-state' is used on each line while moving ;; forward. +(defvar c-state-cache-start 1) +(make-variable-buffer-local 'c-state-cache-start) +;; This is (point-min) when `c-state-cache' was calculated, since a +;; change of narrowing is likely to affect the parens that are visible +;; before the point. + (defvar c-state-cache-good-pos 1) (make-variable-buffer-local 'c-state-cache-good-pos) -;; This is a position where `c-state-cache' is known to be correct, or -;; nil (see below). It's a position inside one of the recorded unclosed -;; parens or the top level, but not further nested inside any literal or -;; subparen that is closed before the last recorded position. +;; This is a position where `c-state-cache' is known to be correct. +;; It's a position inside one of the recorded unclosed parens or the +;; top level, but not further nested inside any literal or subparen +;; that is closed before the last recorded position. ;; ;; The exact position is chosen to try to be close to yet earlier than ;; the position where `c-state-cache' will be called next. Right now @@ -2005,1057 +1978,313 @@ ;; closing paren (of any type) before the line on which ;; `c-parse-state' was called. That is chosen primarily to work well ;; with refontification of the current line. -;; -;; 2009-07-28: When `c-state-point-min' and the last position where -;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are -;; both in the same literal, there is no such "good position", and -;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which -;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil. -;; -;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in -;; the middle of the desert, as long as it is not within a brace pair -;; recorded in `c-state-cache' or a paren/bracket pair. - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; We maintain a simple cache of positions which aren't in a literal, so as to -;; speed up testing for non-literality. -(defconst c-state-nonlit-pos-interval 10000) -;; The approximate interval between entries in `c-state-nonlit-pos-cache'. - -(defvar c-state-nonlit-pos-cache nil) -(make-variable-buffer-local 'c-state-nonlit-pos-cache) -;; A list of buffer positions which are known not to be in a literal. This is -;; ordered with higher positions at the front of the list. Only those which -;; are less than `c-state-nonlit-pos-cache-limit' are valid. - -(defvar c-state-nonlit-pos-cache-limit 1) -(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit) -;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is -;; reduced by buffer changes, and increased by invocations of -;; `c-state-literal-at'. - -(defsubst c-state-pp-to-literal (from to) - ;; Do a parse-partial-sexp from FROM to TO, returning the bounds of any - ;; literal at TO as a cons, otherwise NIL. - ;; FROM must not be in a literal, and the buffer should already be wide - ;; enough. - (save-excursion - (let ((s (parse-partial-sexp from to))) - (when (or (nth 3 s) (nth 4 s)) ; in a string or comment - (parse-partial-sexp (point) (point-max) - nil ; TARGETDEPTH - nil ; STOPBEFORE - s ; OLDSTATE - 'syntax-table) ; stop at end of literal - (cons (nth 8 s) (point)))))) - -(defun c-state-literal-at (here) - ;; If position HERE is inside a literal, return (START . END), the - ;; boundaries of the literal (which may be outside the accessible bit of the - ;; buffer). Otherwise, return nil. - ;; - ;; This function is almost the same as `c-literal-limits'. It differs in - ;; that it is a lower level function, and that it rigourously follows the - ;; syntax from BOB, whereas `c-literal-limits' uses a "local" safe position. - (save-restriction - (widen) - (save-excursion - (let ((c c-state-nonlit-pos-cache) - pos npos lit) - ;; Trim the cache to take account of buffer changes. - (while (and c (> (car c) c-state-nonlit-pos-cache-limit)) - (setq c (cdr c))) - (setq c-state-nonlit-pos-cache c) - - (while (and c (> (car c) here)) - (setq c (cdr c))) - (setq pos (or (car c) (point-min))) - - (while (<= (setq npos (+ pos c-state-nonlit-pos-interval)) - here) - (setq lit (c-state-pp-to-literal pos npos)) - (setq pos (or (cdr lit) npos)) ; end of literal containing npos. - (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache))) - - (if (> pos c-state-nonlit-pos-cache-limit) - (setq c-state-nonlit-pos-cache-limit pos)) - (if (< pos here) - (setq lit (c-state-pp-to-literal pos here))) - lit)))) - -(defsubst c-state-lit-beg (pos) - ;; Return the start of the literal containing POS, or POS itself. - (or (car (c-state-literal-at pos)) - pos)) - -(defsubst c-state-cache-non-literal-place (pos state) - ;; Return a position outside of a string/comment at or before POS. - ;; STATE is the parse-partial-sexp state at POS. - (if (or (nth 3 state) ; in a string? - (nth 4 state)) ; in a comment? - (nth 8 state) - pos)) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Stuff to do with point-min, and coping with any literal there. -(defvar c-state-point-min 1) -(make-variable-buffer-local 'c-state-point-min) -;; This is (point-min) when `c-state-cache' was last calculated. A change of -;; narrowing is likely to affect the parens that are visible before the point. - -(defvar c-state-point-min-lit-type nil) -(make-variable-buffer-local 'c-state-point-min-lit-type) -(defvar c-state-point-min-lit-start nil) -(make-variable-buffer-local 'c-state-point-min-lit-start) -;; These two variables define the literal, if any, containing point-min. -;; Their values are, respectively, 'string, c, or c++, and the start of the -;; literal. If there's no literal there, they're both nil. - -(defvar c-state-min-scan-pos 1) -(make-variable-buffer-local 'c-state-min-scan-pos) -;; This is the earliest buffer-pos from which scanning can be done. It is -;; either the end of the literal containing point-min, or point-min itself. -;; It becomes nil if the buffer is changed earlier than this point. -(defun c-state-get-min-scan-pos () - ;; Return the lowest valid scanning pos. This will be the end of the - ;; literal enclosing point-min, or point-min itself. - (or c-state-min-scan-pos - (save-restriction - (save-excursion - (widen) - (goto-char c-state-point-min-lit-start) - (if (eq c-state-point-min-lit-type 'string) - (forward-sexp) - (forward-comment 1)) - (setq c-state-min-scan-pos (point)))))) - -(defun c-state-mark-point-min-literal () - ;; Determine the properties of any literal containing POINT-MIN, setting the - ;; variables `c-state-point-min-lit-type', `c-state-point-min-lit-start', - ;; and `c-state-min-scan-pos' accordingly. The return value is meaningless. - (let ((p-min (point-min)) - lit) - (save-restriction - (widen) - (setq lit (c-state-literal-at p-min)) - (if lit - (setq c-state-point-min-lit-type - (save-excursion - (goto-char (car lit)) - (cond - ((looking-at c-block-comment-start-regexp) 'c) - ((looking-at c-line-comment-starter) 'c++) - (t 'string))) - c-state-point-min-lit-start (car lit) - c-state-min-scan-pos (cdr lit)) - (setq c-state-point-min-lit-type nil - c-state-point-min-lit-start nil - c-state-min-scan-pos p-min))))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; A variable which signals a brace dessert - helpful for reducing the number -;; of fruitless backward scans. -(defvar c-state-brace-pair-desert nil) -(make-variable-buffer-local 'c-state-brace-pair-desert) -;; Used only in `c-append-lower-brace-pair-to-state-cache'. It is set when an -;; that defun has searched backwards for a brace pair and not found one. Its -;; value is either nil or a cons (PA . FROM), where PA is the position of the -;; enclosing opening paren/brace/bracket which bounds the backwards search (or -;; nil when at top level) and FROM is where the backward search started. It -;; is reset to nil in `c-invalidate-state-cache'. - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Lowish level functions/macros which work directly on `c-state-cache', or a -;; list of like structure. -(defmacro c-state-cache-top-lparen (&optional cache) - ;; Return the address of the top left brace/bracket/paren recorded in CACHE - ;; (default `c-state-cache') (or nil). - (let ((cash (or cache 'c-state-cache))) - `(if (consp (car ,cash)) - (caar ,cash) - (car ,cash)))) - -(defmacro c-state-cache-top-paren (&optional cache) - ;; Return the address of the latest brace/bracket/paren (whether left or - ;; right) recorded in CACHE (default `c-state-cache') or nil. - (let ((cash (or cache 'c-state-cache))) - `(if (consp (car ,cash)) - (cdar ,cash) - (car ,cash)))) - -(defmacro c-state-cache-after-top-paren (&optional cache) - ;; Return the position just after the latest brace/bracket/paren (whether - ;; left or right) recorded in CACHE (default `c-state-cache') or nil. - (let ((cash (or cache 'c-state-cache))) - `(if (consp (car ,cash)) - (cdar ,cash) - (and (car ,cash) - (1+ (car ,cash)))))) - -(defun c-get-cache-scan-pos (here) - ;; From the state-cache, determine the buffer position from which we might - ;; scan forward to HERE to update this cache. This position will be just - ;; after a paren/brace/bracket recorded in the cache, if possible, otherwise - ;; return the earliest position in the accessible region which isn't within - ;; a literal. If the visible portion of the buffer is entirely within a - ;; literal, return NIL. - (let ((c c-state-cache) elt) - ;(while (>= (or (c-state-cache-top-lparen c) 1) here) - (while (and c - (>= (c-state-cache-top-lparen c) here)) - (setq c (cdr c))) - - (setq elt (car c)) - (cond - ((consp elt) - (if (> (cdr elt) here) - (1+ (car elt)) - (cdr elt))) - (elt (1+ elt)) - ((<= (c-state-get-min-scan-pos) here) - (c-state-get-min-scan-pos)) - (t nil)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Variables which keep track of preprocessor constructs. -(defvar c-state-old-cpp-beg nil) -(make-variable-buffer-local 'c-state-old-cpp-beg) -(defvar c-state-old-cpp-end nil) -(make-variable-buffer-local 'c-state-old-cpp-end) -;; These are the limits of the macro containing point at the previous call of -;; `c-parse-state', or nil. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Defuns which analyse the buffer, yet don't change `c-state-cache'. -(defun c-get-fallback-scan-pos (here) - ;; Return a start position for building `c-state-cache' from - ;; scratch. This will be at the top level, 2 defuns back. + +(defsubst c-invalidate-state-cache (pos) + ;; Invalidate all info on `c-state-cache' that applies to the buffer + ;; at POS or higher. This is much like `c-whack-state-after', but + ;; it never changes a paren pair element into an open paren element. + ;; Doing that would mean that the new open paren wouldn't have the + ;; required preceding paren pair element. + (while (and (or c-state-cache + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos 1) + nil)) + (let ((elem (car c-state-cache))) + (if (consp elem) + (or (< pos (cdr elem)) + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos (cdr elem)) + nil)) + (or (<= pos elem) + (when (< pos c-state-cache-good-pos) + (setq c-state-cache-good-pos (1+ elem)) + nil))))) + (setq c-state-cache (cdr c-state-cache)))) + +(defun c-get-fallback-start-pos (here) + ;; Return the start position for building `c-state-cache' from + ;; scratch. (save-excursion ;; Go back 2 bods, but ignore any bogus positions returned by ;; beginning-of-defun (i.e. open paren in column zero). (goto-char here) (let ((cnt 2)) (while (not (or (bobp) (zerop cnt))) - (c-beginning-of-defun-1) ; Pure elisp BOD. + (c-beginning-of-defun-1) (if (eq (char-after) ?\{) (setq cnt (1- cnt))))) (point))) -(defun c-state-balance-parens-backwards (here top) - ;; Return the position of the opening paren/brace/bracket before HERE which - ;; matches the outermost close p/b/b between HERE and TOP, like this: - ;; - ;; ...................................... - ;; | | - ;; ( [ ( ........... ) ( ) ] ) - ;; ^ ^ ^ - ;; | | | - ;; return HERE TOP - ;; - ;; If there aren't enough opening paren/brace/brackets, return the position - ;; of the outermost one found, or HERE it there are none. If there are no - ;; closeing p/b/bs between HERE and TOP, return HERE. HERE and TOP must not - ;; be inside literals. Only the accessible portion of the buffer will be - ;; scanned. - - ;; PART 1: scan from `here' up to `top', accumulating ")"s which enclose - ;; `here'. Go round the next loop each time we pass over such a ")". These - ;; probably match "("s before `here'. - (let (pos pa ren+1 lonely-rens) - (save-excursion - (save-restriction - (narrow-to-region (point-min) top) ; This can move point, sometimes. - (setq pos here) - (c-safe - (while - (setq ren+1 (scan-lists pos 1 1)) ; might signal - (setq lonely-rens (cons ren+1 lonely-rens) - pos ren+1))))) - - ;; PART 2: Scan back before `here' searching for the "("s - ;; matching/mismatching the ")"s found above. We only need to direct the - ;; caller to scan when we've encountered unmatched right parens. - (when lonely-rens - (setq pos here) - (c-safe - (while - (and lonely-rens ; actual values aren't used. - (setq pa (scan-lists pos -1 1))) - (setq pos pa) - (setq lonely-rens (cdr lonely-rens)))) ;) - ) - pos)) - -(defun c-parse-state-get-strategy (here good-pos) - ;; Determine the scanning strategy for adjusting `c-parse-state', attempting - ;; to minimise the amount of scanning. HERE is the pertinent position in - ;; the buffer, GOOD-POS is a position where `c-state-cache' (possibly with - ;; its head trimmed) is known to be good, or nil if there is no such - ;; position. - ;; - ;; The return value is a list, one of the following: - ;; - ;; o - ('forward CACHE-POS START-POINT) - scan forward from START-POINT, - ;; which is not less than CACHE-POS. - ;; o - ('backward CACHE-POS nil) - scan backwards (from HERE). - ;; o - ('BOD nil START-POINT) - scan forwards from START-POINT, which is at the - ;; top level. - ;; o - ('IN-LIT nil nil) - point is inside the literal containing point-min. - ;; , where CACHE-POS is the highest position recorded in `c-state-cache' at - ;; or below HERE. - (let ((cache-pos (c-get-cache-scan-pos here)) ; highest position below HERE in cache (or 1) - BOD-pos ; position of 2nd BOD before HERE. - strategy ; 'forward, 'backward, 'BOD, or 'IN-LIT. - start-point - how-far) ; putative scanning distance. - (setq good-pos (or good-pos (c-state-get-min-scan-pos))) - (cond - ((< here (c-state-get-min-scan-pos)) - (setq strategy 'IN-LIT - start-point nil - cache-pos nil - how-far 0)) - ((<= good-pos here) - (setq strategy 'forward - start-point (max good-pos cache-pos) - how-far (- here start-point))) - ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting. - (setq strategy 'backward - how-far (- good-pos here))) - (t - (setq strategy 'forward - how-far (- here cache-pos) - start-point cache-pos))) - - ;; Might we be better off starting from the top level, two defuns back, - ;; instead? - (when (> how-far c-state-cache-too-far) - (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! - (if (< (- here BOD-pos) how-far) - (setq strategy 'BOD - start-point BOD-pos))) - - (list - strategy - (and (memq strategy '(forward backward)) cache-pos) - (and (memq strategy '(forward BOD)) start-point)))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Routines which change `c-state-cache' and associated values. -(defun c-renarrow-state-cache () - ;; The region (more precisely, point-min) has changed since we - ;; calculated `c-state-cache'. Amend `c-state-cache' accordingly. - (if (< (point-min) c-state-point-min) - ;; If point-min has MOVED BACKWARDS then we drop the state completely. - ;; It would be possible to do a better job here and recalculate the top - ;; only. - (progn - (c-state-mark-point-min-literal) - (setq c-state-cache nil - c-state-cache-good-pos c-state-min-scan-pos - c-state-brace-pair-desert nil)) - - ;; point-min has MOVED FORWARD. - - ;; Is the new point-min inside a (different) literal? - (unless (and c-state-point-min-lit-start ; at prev. point-min - (< (point-min) (c-state-get-min-scan-pos))) - (c-state-mark-point-min-literal)) - - ;; Cut off a bit of the tail from `c-state-cache'. - (let ((ptr (cons nil c-state-cache)) - pa) - (while (and (setq pa (c-state-cache-top-lparen (cdr ptr))) - (>= pa (point-min))) - (setq ptr (cdr ptr))) - - (when (consp ptr) - (if (eq (cdr ptr) c-state-cache) - (setq c-state-cache nil - c-state-cache-good-pos c-state-min-scan-pos) - (setcdr ptr nil) - (setq c-state-cache-good-pos (1+ (c-state-cache-top-lparen)))) - ))) - - (setq c-state-point-min (point-min))) - -(defun c-append-lower-brace-pair-to-state-cache (from &optional upper-lim) - ;; If there is a brace pair preceding FROM in the buffer (not necessarily - ;; immediately preceding), push a cons onto `c-state-cache' to represent it. - ;; FROM must not be inside a literal. If UPPER-LIM is non-nil, we append - ;; the highest brace pair whose "}" is below UPPER-LIM. - ;; - ;; Return non-nil when this has been done. - ;; - ;; This routine should be fast. Since it can get called a LOT, we maintain - ;; `c-state-brace-pair-desert', a small cache of "failures", such that we - ;; reduce the time wasted in repeated fruitless searches in brace deserts. - (save-excursion - (save-restriction - (let ((bra from) ce ; Positions of "{" and "}". - new-cons - (cache-pos (c-state-cache-top-lparen)) ; might be nil. - (macro-start-or-from - (progn (goto-char from) - (c-beginning-of-macro) - (point)))) - (or upper-lim (setq upper-lim from)) - - ;; If we're essentially repeating a fruitless search, just give up. - (unless (and c-state-brace-pair-desert - (eq cache-pos (car c-state-brace-pair-desert)) - (<= from (cdr c-state-brace-pair-desert))) - ;; Only search what we absolutely need to: - (if (and c-state-brace-pair-desert - (> from (cdr c-state-brace-pair-desert))) - (narrow-to-region (cdr c-state-brace-pair-desert) (point-max))) - - ;; In the next pair of nested loops, the inner one moves back past a - ;; pair of (mis-)matching parens or brackets; the outer one moves - ;; back over a sequence of unmatched close brace/paren/bracket each - ;; time round. - (while - (progn - (c-safe - (while - (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal - (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal - (or (> ce upper-lim) - (not (eq (char-after bra) ?\{)) - (and (goto-char bra) - (c-beginning-of-macro) - (< (point) macro-start-or-from)))))) - (and ce (< ce bra))) - (setq bra ce)) ; If we just backed over an unbalanced closing - ; brace, ignore it. - - (if (and ce (< bra ce) (eq (char-after bra) ?\{)) - ;; We've found the desired brace-pair. - (progn - (setq new-cons (cons bra (1+ ce))) - (cond - ((consp (car c-state-cache)) - (setcar c-state-cache new-cons)) - ((and (numberp (car c-state-cache)) ; probably never happens - (< ce (car c-state-cache))) - (setcdr c-state-cache - (cons new-cons (cdr c-state-cache)))) - (t (setq c-state-cache (cons new-cons c-state-cache))))) - - ;; We haven't found a brace pair. Record this. - (setq c-state-brace-pair-desert (cons cache-pos from)))))))) - -(defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here) - ;; If BRA+1 is nil, do nothing. Otherwise, BRA+1 is the buffer position - ;; following a {, and that brace has a (mis-)matching } (or ]), and we - ;; "push" "a" brace pair onto `c-state-cache'. - ;; - ;; Here "push" means overwrite the top element if it's itself a brace-pair, - ;; otherwise push it normally. - ;; - ;; The brace pair we push is normally the one surrounding BRA+1, but if the - ;; latter is inside a macro, not being a macro containing - ;; MACRO-START-OR-HERE, we scan backwards through the buffer for a non-macro - ;; base pair. This latter case is assumed to be rare. - ;; - ;; Note: POINT is not preserved in this routine. - (if bra+1 - (if (or (> bra+1 macro-start-or-here) - (progn (goto-char bra+1) - (not (c-beginning-of-macro)))) - (setq c-state-cache - (cons (cons (1- bra+1) - (scan-lists bra+1 1 1)) - (if (consp (car c-state-cache)) - (cdr c-state-cache) - c-state-cache))) - ;; N.B. This defsubst codes one method for the simple, normal case, - ;; and a more sophisticated, slower way for the general case. Don't - ;; eliminate this defsubst - it's a speed optimisation. - (c-append-lower-brace-pair-to-state-cache (1- bra+1))))) - -(defun c-append-to-state-cache (from) - ;; Scan the buffer from FROM to (point-max), adding elements into - ;; `c-state-cache' for braces etc. Return a candidate for - ;; `c-state-cache-good-pos'. - ;; - ;; FROM must be after the latest brace/paren/bracket in `c-state-cache', if - ;; any. Typically, it is immediately after it. It must not be inside a - ;; literal. - (let ((here-bol (c-point 'bol (point-max))) - (macro-start-or-here - (save-excursion (goto-char (point-max)) - (if (c-beginning-of-macro) - (point) - (point-max)))) - pa+1 ; pos just after an opening PAren (or brace). - (ren+1 from) ; usually a pos just after an closing paREN etc. - ; Is actually the pos. to scan for a (/{/[ from, - ; which sometimes is after a silly )/}/]. - paren+1 ; Pos after some opening or closing paren. - paren+1s ; A list of `paren+1's; used to determine a - ; good-pos. - bra+1 ce+1 ; just after L/R bra-ces. - bra+1s ; list of OLD values of bra+1. - mstart) ; start of a macro. - - (save-excursion - ;; Each time round the following loop, we enter a succesively deeper - ;; level of brace/paren nesting. (Except sometimes we "continue at - ;; the existing level".) `pa+1' is a pos inside an opening - ;; brace/paren/bracket, usually just after it. - (while - (progn - ;; Each time round the next loop moves forward over an opening then - ;; a closing brace/bracket/paren. This loop is white hot, so it - ;; plays ugly tricks to go fast. DON'T PUT ANYTHING INTO THIS - ;; LOOP WHICH ISN'T ABSOLUTELY NECESSARY!!! It terminates when a - ;; call of `scan-lists' signals an error, which happens when there - ;; are no more b/b/p's to scan. - (c-safe - (while t - (setq pa+1 (scan-lists ren+1 1 -1) ; Into (/{/[; might signal - paren+1s (cons pa+1 paren+1s)) - (setq ren+1 (scan-lists pa+1 1 1)) ; Out of )/}/]; might signal - (if (and (eq (char-before pa+1) ?{)) ; Check for a macro later. - (setq bra+1 pa+1)) - (setcar paren+1s ren+1))) - - (if (and pa+1 (> pa+1 ren+1)) - ;; We've just entered a deeper nesting level. - (progn - ;; Insert the brace pair (if present) and the single open - ;; paren/brace/bracket into `c-state-cache' It cannot be - ;; inside a macro, except one around point, because of what - ;; `c-neutralize-syntax-in-CPP' has done. - (c-state-push-any-brace-pair bra+1 macro-start-or-here) - ;; Insert the opening brace/bracket/paren position. - (setq c-state-cache (cons (1- pa+1) c-state-cache)) - ;; Clear admin stuff for the next more nested part of the scan. - (setq ren+1 pa+1 pa+1 nil bra+1 nil bra+1s nil) - t) ; Carry on the loop - - ;; All open p/b/b's at this nesting level, if any, have probably - ;; been closed by matching/mismatching ones. We're probably - ;; finished - we just need to check for having found an - ;; unmatched )/}/], which we ignore. Such a )/}/] can't be in a - ;; macro, due the action of `c-neutralize-syntax-in-CPP'. - (c-safe (setq ren+1 (scan-lists ren+1 1 1)))))) ; acts as loop control. - - ;; Record the final, innermost, brace-pair if there is one. - (c-state-push-any-brace-pair bra+1 macro-start-or-here) - - ;; Determine a good pos - (while (and (setq paren+1 (car paren+1s)) - (> (if (> paren+1 macro-start-or-here) - paren+1 - (goto-char paren+1) - (setq mstart (and (c-beginning-of-macro) - (point))) - (or mstart paren+1)) - here-bol)) - (setq paren+1s (cdr paren+1s))) - (cond - ((and paren+1 mstart) - (min paren+1 mstart)) - (paren+1) - (t from))))) - -(defun c-remove-stale-state-cache (good-pos pps-point) - ;; Remove stale entries from the `c-cache-state', i.e. those which will - ;; not be in it when it is amended for position (point-max). - ;; Additionally, the "outermost" open-brace entry before (point-max) - ;; will be converted to a cons if the matching close-brace is scanned. - ;; - ;; GOOD-POS is a "maximal" "safe position" - there must be no open - ;; parens/braces/brackets between GOOD-POS and (point-max). - ;; - ;; As a second thing, calculate the result of parse-partial-sexp at - ;; PPS-POINT, w.r.t. GOOD-POS. The motivation here is that - ;; `c-state-cache-good-pos' may become PPS-POINT, but the caller may need to - ;; adjust it to get outside a string/comment. (Sorry about this! The code - ;; needs to be FAST). - ;; - ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where - ;; o - GOOD-POS is a position where the new value `c-state-cache' is known - ;; to be good (we aim for this to be as high as possible); - ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair - ;; preceding POS which needs to be recorded in `c-state-cache'. It is a - ;; position to scan backwards from. - ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT. - (save-restriction - (narrow-to-region 1 (point-max)) - (save-excursion - (let* ((in-macro-start ; start of macro containing (point-max) or nil. - (save-excursion - (goto-char (point-max)) - (and (c-beginning-of-macro) - (point)))) - (good-pos-actual-macro-start ; Start of macro containing good-pos - ; or nil - (and (< good-pos (point-max)) - (save-excursion - (goto-char good-pos) - (and (c-beginning-of-macro) - (point))))) - (good-pos-actual-macro-end ; End of this macro, (maybe - ; (point-max)), or nil. - (and good-pos-actual-macro-start - (save-excursion - (goto-char good-pos-actual-macro-start) - (c-end-of-macro) - (point)))) - pps-state ; Will be 9 or 10 elements long. - pos - upper-lim ; ,beyond which `c-state-cache' entries are removed - scan-back-pos - pair-beg pps-point-state target-depth) - - ;; Remove entries beyond (point-max). Also remove any entries inside - ;; a macro, unless (point-max) is in the same macro. - (setq upper-lim - (if (or (null c-state-old-cpp-beg) - (and (> (point-max) c-state-old-cpp-beg) - (< (point-max) c-state-old-cpp-end))) - (point-max) - (min (point-max) c-state-old-cpp-beg))) - (while (and c-state-cache (>= (c-state-cache-top-lparen) upper-lim)) - (setq c-state-cache (cdr c-state-cache))) - ;; If `upper-lim' is inside the last recorded brace pair, remove its - ;; RBrace and indicate we'll need to search backwards for a previous - ;; brace pair. - (when (and c-state-cache - (consp (car c-state-cache)) - (> (cdar c-state-cache) upper-lim)) - (setcar c-state-cache (caar c-state-cache)) - (setq scan-back-pos (car c-state-cache))) - - ;; The next loop jumps forward out of a nested level of parens each - ;; time round; the corresponding elements in `c-state-cache' are - ;; removed. `pos' is just after the brace-pair or the open paren at - ;; (car c-state-cache). There can be no open parens/braces/brackets - ;; between `good-pos'/`good-pos-actual-macro-start' and (point-max), - ;; due to the interface spec to this function. - (setq pos (if (and good-pos-actual-macro-end - (not (eq good-pos-actual-macro-start - in-macro-start))) - (1+ good-pos-actual-macro-end) ; get outside the macro as - ; marked by a `category' text property. - good-pos)) - (goto-char pos) - (while (and c-state-cache - (< (point) (point-max))) - (cond - ((null pps-state) ; first time through - (setq target-depth -1)) - ((eq (car pps-state) target-depth) ; found closing ),},] - (setq target-depth (1- (car pps-state)))) - ;; Do nothing when we've merely reached pps-point. - ) - - ;; Scan! - (setq pps-state - (parse-partial-sexp - (point) (if (< (point) pps-point) pps-point (point-max)) - target-depth - nil pps-state)) - - (if (= (point) pps-point) - (setq pps-point-state pps-state)) - - (when (eq (car pps-state) target-depth) - (setq pos (point)) ; POS is now just after an R-paren/brace. - (cond - ((and (consp (car c-state-cache)) - (eq (point) (cdar c-state-cache))) - ;; We've just moved out of the paren pair containing the brace-pair - ;; at (car c-state-cache). `pair-beg' is where the open paren is, - ;; and is potentially where the open brace of a cons in - ;; c-state-cache will be. - (setq pair-beg (car-safe (cdr c-state-cache)) - c-state-cache (cdr-safe (cdr c-state-cache)))) ; remove {}pair + containing Lparen. - ((numberp (car c-state-cache)) - (setq pair-beg (car c-state-cache) - c-state-cache (cdr c-state-cache))) ; remove this - ; containing Lparen - ((numberp (cadr c-state-cache)) - (setq pair-beg (cadr c-state-cache) - c-state-cache (cddr c-state-cache))) ; Remove a paren pair - ; together with enclosed brace pair. - ;; (t nil) ; Ignore an unmated Rparen. - ))) - - (if (< (point) pps-point) - (setq pps-state (parse-partial-sexp (point) pps-point - nil nil ; TARGETDEPTH, STOPBEFORE - pps-state))) - - ;; If the last paren pair we moved out of was actually a brace pair, - ;; insert it into `c-state-cache'. - (when (and pair-beg (eq (char-after pair-beg) ?{)) - (if (consp (car-safe c-state-cache)) - (setq c-state-cache (cdr c-state-cache))) - (setq c-state-cache (cons (cons pair-beg pos) - c-state-cache))) - - (list pos scan-back-pos pps-state))))) - -(defun c-remove-stale-state-cache-backwards (here cache-pos) - ;; Strip stale elements of `c-state-cache' by moving backwards through the - ;; buffer, and inform the caller of the scenario detected. - ;; - ;; HERE is the position we're setting `c-state-cache' for. - ;; CACHE-POS is just after the latest recorded position in `c-state-cache' - ;; before HERE, or a position at or near point-min which isn't in a - ;; literal. - ;; - ;; This function must only be called only when (> `c-state-cache-good-pos' - ;; HERE). Usually the gap between CACHE-POS and HERE is large. It is thus - ;; optimised to eliminate (or minimise) scanning between these two - ;; positions. - ;; - ;; Return a three element list (GOOD-POS SCAN-BACK-POS FWD-FLAG), where: - ;; o - GOOD-POS is a "good position", where `c-state-cache' is valid, or - ;; could become so after missing elements are inserted into - ;; `c-state-cache'. This is JUST AFTER an opening or closing - ;; brace/paren/bracket which is already in `c-state-cache' or just before - ;; one otherwise. exceptionally (when there's no such b/p/b handy) the BOL - ;; before `here''s line, or the start of the literal containing it. - ;; o - SCAN-BACK-POS, if non-nil, indicates there may be a brace pair - ;; preceding POS which isn't recorded in `c-state-cache'. It is a position - ;; to scan backwards from. - ;; o - FWD-FLAG, if non-nil, indicates there may be parens/braces between - ;; POS and HERE which aren't recorded in `c-state-cache'. - ;; - ;; The comments in this defun use "paren" to mean parenthesis or square - ;; bracket (as contrasted with a brace), and "(" and ")" likewise. - ;; - ;; . {..} (..) (..) ( .. { } ) (...) ( .... . ..) - ;; | | | | | | - ;; CP E here D C good - (let ((pos c-state-cache-good-pos) - pa ren ; positions of "(" and ")" - dropped-cons ; whether the last element dropped from `c-state-cache' - ; was a cons (representing a brace-pair) - good-pos ; see above. - lit ; (START . END) of a literal containing some point. - here-lit-start here-lit-end ; bounds of literal containing `here' - ; or `here' itself. - (here-bol (c-point 'bol here)) - (too-far-back (max (- here c-state-cache-too-far) 1))) - - ;; Remove completely irrelevant entries from `c-state-cache'. - (while (and c-state-cache - (>= (setq pa (c-state-cache-top-lparen)) here)) - (setq dropped-cons (consp (car c-state-cache))) - (setq c-state-cache (cdr c-state-cache)) - (setq pos pa)) - ;; At this stage, (> pos here); - ;; (< (c-state-cache-top-lparen) here) (or is nil). - - ;; CASE 1: The top of the cache is a brace pair which now encloses `here'. - ;; As good-pos, return the address. of the "{". - (if (and (consp (car c-state-cache)) - (> (cdar c-state-cache) here)) - ;; Since we've no knowledge of what's inside these braces, we have no - ;; alternative but to direct the caller to scan the buffer from the - ;; opening brace. - (progn - (setq pos (caar c-state-cache)) - (setcar c-state-cache pos) - (list (1+ pos) pos t)) ; return value. We've just converted a brace - ; pair entry into a { entry, so the caller - ; needs to search for a brace pair before the - ; {. - - ;; ;; `here' might be inside a literal. Check for this. - (setq lit (c-state-literal-at here) - here-lit-start (or (car lit) here) - here-lit-end (or (cdr lit) here)) - - ;; `here' might be nested inside any depth of parens (or brackets but - ;; not braces). Scan backwards to find the outermost such opening - ;; paren, if there is one. This will be the scan position to return. - (save-restriction - (narrow-to-region cache-pos (point-max)) - (setq pos (c-state-balance-parens-backwards here-lit-end pos))) - - (if (< pos here-lit-start) - ;; CASE 2: Address of outermost ( or [ which now encloses `here', - ;; but didn't enclose the (previous) `c-state-cache-good-pos'. If - ;; there is a brace pair preceding this, it will already be in - ;; `c-state-cache', unless there was a brace pair after it, - ;; i.e. there'll only be one to scan for if we've just deleted one. - (list pos (and dropped-cons pos) t) ; Return value. - - ;; `here' isn't enclosed in a (previously unrecorded) bracket/paren. - ;; Further forward scanning isn't needed, but we still need to find a - ;; GOOD-POS. Step out of all enclosing "("s on HERE's line. - (save-restriction - (narrow-to-region here-bol (point-max)) - (setq pos here-lit-start) - (c-safe (while (setq pa (scan-lists pos -1 1)) - (setq pos pa)))) ; might signal - (if (setq ren (c-safe-scan-lists pos -1 -1 too-far-back)) - ;; CASE 3: After a }/)/] before `here''s BOL. - (list (1+ ren) (and dropped-cons pos) nil) ; Return value - - ;; CASE 4; Best of a bad job: BOL before `here-bol', or beginning of - ;; literal containing it. - (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol))) - (list good-pos (and dropped-cons good-pos) nil)))))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Externally visible routines. - -(defun c-state-cache-init () - (setq c-state-cache nil - c-state-cache-good-pos 1 - c-state-nonlit-pos-cache nil - c-state-nonlit-pos-cache-limit 1 - c-state-brace-pair-desert nil - c-state-point-min 1 - c-state-point-min-lit-type nil - c-state-point-min-lit-start nil - c-state-min-scan-pos 1 - c-state-old-cpp-beg nil - c-state-old-cpp-end nil) - (c-state-mark-point-min-literal)) - -(defun c-invalidate-state-cache-1 (here) - ;; Invalidate all info on `c-state-cache' that applies to the buffer at HERE - ;; or higher and set `c-state-cache-good-pos' accordingly. The cache is - ;; left in a consistent state. - ;; - ;; This is much like `c-whack-state-after', but it never changes a paren - ;; pair element into an open paren element. Doing that would mean that the - ;; new open paren wouldn't have the required preceding paren pair element. - ;; - ;; This function is called from c-after-change. - - ;; The cache of non-literals: - (if (< here c-state-nonlit-pos-cache-limit) - (setq c-state-nonlit-pos-cache-limit here)) - - ;; `c-state-cache': - ;; Case 1: if `here' is in a literal containing point-min, everything - ;; becomes (or is already) nil. - (if (or (null c-state-cache-good-pos) - (< here (c-state-get-min-scan-pos))) - (setq c-state-cache nil - c-state-cache-good-pos nil - c-state-min-scan-pos nil) - -;;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value below -;;; `here'. To maintain its consistency, we may need to insert a new brace -;;; pair. - (let ((here-bol (c-point 'bol here)) - too-high-pa ; recorded {/(/[ next above here, or nil. - dropped-cons ; was the last removed element a brace pair? - pa) - ;; The easy bit - knock over-the-top bits off `c-state-cache'. - (while (and c-state-cache - (>= (setq pa (c-state-cache-top-paren)) here)) - (setq dropped-cons (consp (car c-state-cache)) - too-high-pa (c-state-cache-top-lparen) - c-state-cache (cdr c-state-cache))) - - ;; Do we need to add in an earlier brace pair, having lopped one off? - (if (and dropped-cons - (< too-high-pa (+ here c-state-cache-too-far))) - (c-append-lower-brace-pair-to-state-cache too-high-pa here-bol)) - (setq c-state-cache-good-pos (or (c-state-cache-after-top-paren) - (c-state-get-min-scan-pos))))) - - ;; The brace-pair desert marker: - (when (car c-state-brace-pair-desert) - (if (< here (car c-state-brace-pair-desert)) - (setq c-state-brace-pair-desert nil) - (if (< here (cdr c-state-brace-pair-desert)) - (setcdr c-state-brace-pair-desert here))))) - -(defun c-parse-state-1 () - ;; Find and record all noteworthy parens between some good point earlier in - ;; the file and point. That good point is at least the beginning of the - ;; top-level construct we are in, or the beginning of the preceding - ;; top-level construct if we aren't in one. - ;; - ;; The returned value is a list of the noteworthy parens with the last one - ;; first. If an element in the list is an integer, it's the position of an - ;; open paren (of any type) which has not been closed before the point. If - ;; an element is a cons, it gives the position of a closed BRACE paren - ;; pair[*]; the car is the start brace position and the cdr is the position - ;; following the closing brace. Only the last closed brace paren pair - ;; before each open paren and before the point is recorded, and thus the - ;; state never contains two cons elements in succession. When a close brace - ;; has no matching open brace (e.g., the matching brace is outside the - ;; visible region), it is not represented in the returned value. - ;; - ;; [*] N.B. The close "brace" might be a mismatching close bracket or paren. - ;; This defun explicitly treats mismatching parens/braces/brackets as - ;; matching. It is the open brace which makes it a "brace" pair. - ;; - ;; If POINT is within a macro, open parens and brace pairs within - ;; THIS macro MIGHT be recorded. This depends on whether their - ;; syntactic properties have been suppressed by - ;; `c-neutralize-syntax-in-CPP'. This might need fixing (2008-12-11). +(defun c-parse-state () + ;; Find and record all noteworthy parens between some good point + ;; earlier in the file and point. That good point is at least the + ;; beginning of the top-level construct we are in, or the beginning + ;; of the preceding top-level construct if we aren't in one. + ;; + ;; The returned value is a list of the noteworthy parens with the + ;; last one first. If an element in the list is an integer, it's + ;; the position of an open paren which has not been closed before + ;; the point. If an element is a cons, it gives the position of a + ;; closed brace paren pair; the car is the start paren position and + ;; the cdr is the position following the closing paren. Only the + ;; last closed brace paren pair before each open paren and before + ;; the point is recorded, and thus the state never contains two cons + ;; elements in succession. ;; ;; Currently no characters which are given paren syntax with the ;; syntax-table property are recorded, i.e. angle bracket arglist ;; parens are never present here. Note that this might change. ;; ;; BUG: This function doesn't cope entirely well with unbalanced - ;; parens in macros. (2008-12-11: this has probably been resolved - ;; by the function `c-neutralize-syntax-in-CPP'.) E.g. in the - ;; following case the brace before the macro isn't balanced with the - ;; one after it: + ;; parens in macros. E.g. in the following case the brace before + ;; the macro isn't balanced with the one after it: ;; ;; { ;; #define X { ;; } ;; - ;; Note to maintainers: this function DOES get called with point - ;; within comments and strings, so don't assume it doesn't! - ;; ;; This function might do hidden buffer changes. - (let* ((here (point)) - (here-bopl (c-point 'bopl)) - strategy ; 'forward, 'backward etc.. - ;; Candidate positions to start scanning from: - cache-pos ; highest position below HERE already existing in - ; cache (or 1). - good-pos - start-point - bopl-state - res - scan-backward-pos scan-forward-p) ; used for 'backward. - ;; If POINT-MIN has changed, adjust the cache - (unless (= (point-min) c-state-point-min) - (c-renarrow-state-cache)) - - ;; Strategy? - (setq res (c-parse-state-get-strategy here c-state-cache-good-pos) - strategy (car res) - cache-pos (cadr res) - start-point (nth 2 res)) - - (when (eq strategy 'BOD) - (setq c-state-cache nil - c-state-cache-good-pos start-point)) - - ;; SCAN! - (save-restriction - (cond - ((memq strategy '(forward BOD)) + + (save-restriction + (let* ((here (point)) + (here-bol (c-point 'bol)) + (c-macro-start (c-query-macro-start)) + (in-macro-start (or c-macro-start (point))) + old-state last-pos brace-pair-open brace-pair-close + pos save-pos) + (c-invalidate-state-cache here) + + ;; If the minimum position has changed due to narrowing then we + ;; have to fix the tail of `c-state-cache' accordingly. + (unless (= c-state-cache-start (point-min)) + (if (> (point-min) c-state-cache-start) + ;; If point-min has moved forward then we just need to cut + ;; off a bit of the tail. + (let ((ptr (cons nil c-state-cache)) elem) + (while (and (setq elem (car-safe (cdr ptr))) + (>= (if (consp elem) (car elem) elem) + (point-min))) + (setq ptr (cdr ptr))) + (when (consp ptr) + (if (eq (cdr ptr) c-state-cache) + (setq c-state-cache nil + c-state-cache-good-pos 1) + (setcdr ptr nil)))) + ;; If point-min has moved backward then we drop the state + ;; completely. It's possible to do a better job here and + ;; recalculate the top only. + (setq c-state-cache nil + c-state-cache-good-pos 1)) + (setq c-state-cache-start (point-min))) + + ;; Get the latest position we know are directly inside the + ;; closest containing paren of the cached state. + (setq last-pos (and c-state-cache + (if (consp (car c-state-cache)) + (cdr (car c-state-cache)) + (1+ (car c-state-cache))))) + (if (or (not last-pos) + (< last-pos c-state-cache-good-pos)) + (setq last-pos c-state-cache-good-pos) + ;; Take the opportunity to move the cached good position + ;; further down. + (if (< last-pos here-bol) + (setq c-state-cache-good-pos last-pos))) + + ;; Check if `last-pos' is in a macro. If it is, and we're not + ;; in the same macro, we must discard everything on + ;; `c-state-cache' that is inside the macro before using it. + (save-excursion + (goto-char last-pos) + (when (and (c-beginning-of-macro) + (/= (point) in-macro-start)) + (c-invalidate-state-cache (point)) + ;; Set `last-pos' again just like above except that there's + ;; no use looking at `c-state-cache-good-pos' here. + (setq last-pos (if c-state-cache + (if (consp (car c-state-cache)) + (cdr (car c-state-cache)) + (1+ (car c-state-cache))) + 1)))) + + ;; If we've moved very far from the last cached position then + ;; it's probably better to redo it from scratch, otherwise we + ;; might spend a lot of time searching from `last-pos' down to + ;; here. + (when (< last-pos (- here 20000)) + ;; First get the fallback start position. If it turns out + ;; that it's so far back that the cached state is closer then + ;; we'll keep it afterall. + (setq pos (c-get-fallback-start-pos here)) + (if (<= pos last-pos) + (setq pos nil) + (setq last-pos nil + c-state-cache nil + c-state-cache-good-pos 1))) + + ;; Find the start position for the forward search. (Can't + ;; search in the backward direction since the point might be in + ;; some kind of literal.) + + (unless pos + (setq old-state c-state-cache) + + ;; There's a cached state with a containing paren. Pop off + ;; the stale containing sexps from it by going forward out of + ;; parens as far as possible. (narrow-to-region (point-min) here) - (setq res (c-remove-stale-state-cache start-point here-bopl)) - (setq cache-pos (car res) - scan-backward-pos (cadr res) - bopl-state (car (cddr res))) ; will be nil if (< here-bopl - ; start-point) - (if scan-backward-pos - (c-append-lower-brace-pair-to-state-cache scan-backward-pos)) - (setq good-pos - (c-append-to-state-cache cache-pos)) - (setq c-state-cache-good-pos - (if (and bopl-state - (< good-pos (- here c-state-cache-too-far))) - (c-state-cache-non-literal-place here-bopl bopl-state) - good-pos))) - - ((eq strategy 'backward) - (setq res (c-remove-stale-state-cache-backwards here cache-pos) - good-pos (car res) - scan-backward-pos (cadr res) - scan-forward-p (car (cddr res))) - (if scan-backward-pos - (c-append-lower-brace-pair-to-state-cache - scan-backward-pos)) - (setq c-state-cache-good-pos - (if scan-forward-p - (progn (narrow-to-region (point-min) here) - (c-append-to-state-cache good-pos)) - - (c-get-cache-scan-pos good-pos)))) - - (t ; (eq strategy 'IN-LIT) - (setq c-state-cache nil - c-state-cache-good-pos nil))))) - - c-state-cache) - -(defun c-invalidate-state-cache (here) - ;; This is a wrapper over `c-invalidate-state-cache-1'. - ;; - ;; It suppresses the syntactic effect of the < and > (template) brackets and - ;; of all parens in preprocessor constructs, except for any such construct - ;; containing point. We can then call `c-invalidate-state-cache-1' without - ;; worrying further about macros and template delimiters. - (c-with-<->-as-parens-suppressed - (if (and c-state-old-cpp-beg - (< c-state-old-cpp-beg here)) - (c-with-all-but-one-cpps-commented-out - c-state-old-cpp-beg - (min c-state-old-cpp-end here) - (c-invalidate-state-cache-1 here)) - (c-with-cpps-commented-out - (c-invalidate-state-cache-1 here))))) - -(defun c-parse-state () - ;; This is a wrapper over `c-parse-state-1'. See that function for a - ;; description of the functionality and return value. - ;; - ;; It suppresses the syntactic effect of the < and > (template) brackets and - ;; of all parens in preprocessor constructs, except for any such construct - ;; containing point. We can then call `c-parse-state-1' without worrying - ;; further about macros and template delimiters. - (let (here-cpp-beg here-cpp-end) - (save-excursion - (when (c-beginning-of-macro) - (setq here-cpp-beg (point)) - (unless - (> (setq here-cpp-end (c-syntactic-end-of-macro)) - here-cpp-beg) - (setq here-cpp-beg nil here-cpp-end nil)))) - ;; FIXME!!! Put in a `condition-case' here to protect the integrity of the - ;; subsystem. - (prog1 - (c-with-<->-as-parens-suppressed - (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) - (c-with-all-but-one-cpps-commented-out - here-cpp-beg here-cpp-end - (c-parse-state-1)) - (c-with-cpps-commented-out - (c-parse-state-1)))) - (setq c-state-old-cpp-beg (and here-cpp-beg (copy-marker here-cpp-beg t)) - c-state-old-cpp-end (and here-cpp-end (copy-marker here-cpp-end t))) - ))) - -;; Debug tool to catch cache inconsistencies. This is called from -;; 000tests.el. + (let (placeholder pair-beg) + (while (and c-state-cache + (setq placeholder + (c-up-list-forward last-pos))) + (setq last-pos placeholder) + (if (consp (car c-state-cache)) + (setq pair-beg (car-safe (cdr c-state-cache)) + c-state-cache (cdr-safe (cdr c-state-cache))) + (setq pair-beg (car c-state-cache) + c-state-cache (cdr c-state-cache)))) + + (when (and pair-beg (eq (char-after pair-beg) ?{)) + ;; The last paren pair we moved out from was a brace + ;; pair. Modify the state to record this as a closed + ;; pair now. + (if (consp (car-safe c-state-cache)) + (setq c-state-cache (cdr c-state-cache))) + (setq c-state-cache (cons (cons pair-beg last-pos) + c-state-cache)))) + + ;; Check if the preceding balanced paren is within a + ;; macro; it should be ignored if we're outside the + ;; macro. There's no need to check any further upwards; + ;; if the macro contains an unbalanced opening paren then + ;; we're smoked anyway. + (when (and (<= (point) in-macro-start) + (consp (car c-state-cache))) + (save-excursion + (goto-char (car (car c-state-cache))) + (when (c-beginning-of-macro) + (setq here (point) + c-state-cache (cdr c-state-cache))))) + + (unless (eq c-state-cache old-state) + ;; Have to adjust the cached good position if state has been + ;; popped off. + (setq c-state-cache-good-pos + (if c-state-cache + (if (consp (car c-state-cache)) + (cdr (car c-state-cache)) + (1+ (car c-state-cache))) + 1) + old-state c-state-cache)) + + (when c-state-cache + (setq pos last-pos))) + + ;; Get the fallback start position. + (unless pos + (setq pos (c-get-fallback-start-pos here) + c-state-cache nil + c-state-cache-good-pos 1)) + + (narrow-to-region (point-min) here) + + (while pos + (setq save-pos pos + brace-pair-open nil) + + ;; Find the balanced brace pairs. This loop is hot, so it + ;; does ugly tricks to go faster. + (c-safe + (let (set-good-pos set-brace-pair) + (while t + (setq last-pos nil + last-pos (scan-lists pos 1 -1)) ; Might signal. + (setq pos (scan-lists last-pos 1 1) ; Might signal. + set-good-pos (< pos here-bol) + set-brace-pair (eq (char-before last-pos) ?{)) + + ;; Update the cached good position and record the brace + ;; pair, whichever is applicable for the paren we've + ;; just jumped over. But first check that it isn't + ;; inside a macro and the point isn't inside the same + ;; one. + (when (and (or set-good-pos set-brace-pair) + (or (>= pos in-macro-start) + (save-excursion + (goto-char pos) + (not (c-beginning-of-macro))))) + (if set-good-pos + (setq c-state-cache-good-pos pos)) + (if set-brace-pair + (setq brace-pair-open last-pos + brace-pair-close pos)))))) + + ;; Record the last brace pair. + (when brace-pair-open + (let ((head (car-safe c-state-cache))) + (if (consp head) + (progn + (setcar head (1- brace-pair-open)) + (setcdr head brace-pair-close)) + (setq c-state-cache (cons (cons (1- brace-pair-open) + brace-pair-close) + c-state-cache))))) + + (if last-pos + ;; Prepare to loop, but record the open paren only if it's + ;; outside a macro or within the same macro as point, and + ;; if it is a legitimate open paren and not some character + ;; that got an open paren syntax-table property. + (progn + (setq pos last-pos) + (when (and (or (>= last-pos in-macro-start) + (save-excursion + (goto-char last-pos) + (not (c-beginning-of-macro)))) + ;; Check for known types of parens that we + ;; want to record. The syntax table is not to + ;; be trusted here since the caller might be + ;; using e.g. `c++-template-syntax-table'. + (memq (char-before last-pos) '(?{ ?\( ?\[))) + (if (< last-pos here-bol) + (setq c-state-cache-good-pos last-pos)) + (setq c-state-cache (cons (1- last-pos) c-state-cache)))) + + (if (setq last-pos (c-up-list-forward pos)) + ;; Found a close paren without a corresponding opening + ;; one. Maybe we didn't go back far enough, so try to + ;; scan backward for the start paren and then start over. + (progn + (setq pos (c-up-list-backward pos) + c-state-cache nil + c-state-cache-good-pos c-state-cache-start) + (when (or (not pos) + ;; Emacs (up to at least 21.2) can get confused by + ;; open parens in column zero inside comments: The + ;; sexp functions can then misbehave and bring us + ;; back to the same point again. Check this so that + ;; we don't get an infinite loop. + (>= pos save-pos)) + (setq pos last-pos + c-parsing-error + (format "Unbalanced close paren at line %d" + (1+ (count-lines (point-min) + (c-point 'bol last-pos))))))) + (setq pos nil)))) + + ;;(message "c-parse-state: %S end: %S" c-state-cache c-state-cache-good-pos) + c-state-cache))) + +;; Debug tool to catch cache inconsistencies. (defvar c-debug-parse-state nil) (unless (fboundp 'c-real-parse-state) (fset 'c-real-parse-state (symbol-function 'c-parse-state))) (cc-bytecomp-defun c-real-parse-state) (defun c-debug-parse-state () - (let ((here (point)) (res1 (c-real-parse-state)) res2) + (let ((res1 (c-real-parse-state)) res2) (let ((c-state-cache nil) - (c-state-cache-good-pos 1) - (c-state-nonlit-pos-cache nil) - (c-state-nonlit-pos-cache-limit 1) - (c-state-brace-pair-desert nil) - (c-state-point-min 1) - (c-state-point-min-lit-type nil) - (c-state-point-min-lit-start nil) - (c-state-min-scan-pos 1) - (c-state-old-cpp-beg nil) - (c-state-old-cpp-end nil)) + (c-state-cache-start 1) + (c-state-cache-good-pos 1)) (setq res2 (c-real-parse-state))) (unless (equal res1 res2) ;; The cache can actually go further back due to the ad-hoc way @@ -3067,11 +2296,10 @@ (while (not (or (bobp) (eq (char-after) ?{))) (c-beginning-of-defun-1)) (unless (equal (c-whack-state-before (point) res1) res2) - (message (concat "c-parse-state inconsistency at %s: " + (message (concat "c-parse-state inconsistency: " "using cache: %s, from scratch: %s") - here res1 res2)))) + res1 res2)))) res1)) - (defun c-toggle-parse-state-debug (&optional arg) (interactive "P") (setq c-debug-parse-state (c-calculate-state arg c-debug-parse-state)) @@ -3082,7 +2310,6 @@ (when c-debug-parse-state (c-toggle-parse-state-debug 1)) - (defun c-whack-state-before (bufpos paren-state) ;; Whack off any state information from PAREN-STATE which lies ;; before BUFPOS. Not destructive on PAREN-STATE. @@ -4882,168 +4109,7 @@ ))) -;; Setting and removing syntax properties on < and > in languages (C++ -;; and Java) where they can be template/generic delimiters as well as -;; their normal meaning of "less/greater than". - -;; Normally, < and > have syntax 'punctuation'. When they are found to -;; be delimiters, they are marked as such with the category properties -;; c-<-as-paren-syntax, c->-as-paren-syntax respectively. - -;; STRATEGY: -;; -;; It is impossible to determine with certainty whether a <..> pair in -;; C++ is two comparison operators or is template delimiters, unless -;; one duplicates a lot of a C++ compiler. For example, the following -;; code fragment: -;; -;; foo (a < b, c > d) ; -;; -;; could be a function call with two integer parameters (each a -;; relational expression), or it could be a constructor for class foo -;; taking one parameter d of templated type "a < b, c >". They are -;; somewhat easier to distinguish in Java. -;; -;; The strategy now (2010-01) adopted is to mark and unmark < and -;; > IN MATCHING PAIRS ONLY. [Previously, they were marked -;; individually when their context so indicated. This gave rise to -;; intractible problems when one of a matching pair was deleted, or -;; pulled into a literal.] -;; -;; At each buffer change, the syntax-table properties are removed in a -;; before-change function and reapplied, when needed, in an -;; after-change function. It is far more important that the -;; properties get removed when they they are spurious than that they -;; be present when wanted. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defun c-clear-<-pair-props (&optional pos) - ;; POS (default point) is at a < character. If it is marked with - ;; open paren syntax-table text property, remove the property, - ;; together with the close paren property on the matching > (if - ;; any). - (save-excursion - (if pos - (goto-char pos) - (setq pos (point))) - (when (equal (c-get-char-property (point) 'syntax-table) - c-<-as-paren-syntax) - (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. - (c-go-list-forward)) - (when (equal (c-get-char-property (1- (point)) 'syntax-table) - c->-as-paren-syntax) ; should always be true. - (c-clear-char-property (1- (point)) 'category)) - (c-clear-char-property pos 'category)))) - -(defun c-clear->-pair-props (&optional pos) - ;; POS (default point) is at a > character. If it is marked with - ;; close paren syntax-table property, remove the property, together - ;; with the open paren property on the matching < (if any). - (save-excursion - (if pos - (goto-char pos) - (setq pos (point))) - (when (equal (c-get-char-property (point) 'syntax-table) - c->-as-paren-syntax) - (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. - (c-go-up-list-backward)) - (when (equal (c-get-char-property (point) 'syntax-table) - c-<-as-paren-syntax) ; should always be true. - (c-clear-char-property (point) 'category)) - (c-clear-char-property pos 'category)))) - -(defun c-clear-<>-pair-props (&optional pos) - ;; POS (default point) is at a < or > character. If it has an - ;; open/close paren syntax-table property, remove this property both - ;; from the current character and its partner (which will also be - ;; thusly marked). - (cond - ((eq (char-after) ?\<) - (c-clear-<-pair-props pos)) - ((eq (char-after) ?\>) - (c-clear->-pair-props pos)) - (t (c-benign-error - "c-clear-<>-pair-props called from wrong position")))) - -(defun c-clear-<-pair-props-if-match-after (lim &optional pos) - ;; POS (default point) is at a < character. If it is both marked - ;; with open/close paren syntax-table property, and has a matching > - ;; (also marked) which is after LIM, remove the property both from - ;; the current > and its partner. - (save-excursion - (if pos - (goto-char pos) - (setq pos (point))) - (when (equal (c-get-char-property (point) 'syntax-table) - c-<-as-paren-syntax) - (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. - (c-go-list-forward)) - (when (and (>= (point) lim) - (equal (c-get-char-property (1- (point)) 'syntax-table) - c->-as-paren-syntax)) ; should always be true. - (c-unmark-<->-as-paren (1- (point))) - (c-unmark-<->-as-paren pos))))) - -(defun c-clear->-pair-props-if-match-before (lim &optional pos) - ;; POS (default point) is at a > character. If it is both marked - ;; with open/close paren syntax-table property, and has a matching < - ;; (also marked) which is before LIM, remove the property both from - ;; the current < and its partner. - (save-excursion - (if pos - (goto-char pos) - (setq pos (point))) - (when (equal (c-get-char-property (point) 'syntax-table) - c->-as-paren-syntax) - (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. - (c-go-up-list-backward)) - (when (and (<= (point) lim) - (equal (c-get-char-property (point) 'syntax-table) - c-<-as-paren-syntax)) ; should always be true. - (c-unmark-<->-as-paren (point)) - (c-unmark-<->-as-paren pos))))) - -(defun c-before-change-check-<>-operators (beg end) - ;; Unmark certain pairs of "< .... >" which are currently marked as - ;; template/generic delimiters. (This marking is via syntax-table - ;; text properties). - ;; - ;; These pairs are those which are in the current "statement" (i.e., - ;; the region between the {, }, or ; before BEG and the one after - ;; END), and which enclose any part of the interval (BEG END). - ;; - ;; Note that in C++ (?and Java), template/generic parens cannot - ;; enclose a brace or semicolon, so we use these as bounds on the - ;; region we must work on. - ;; - ;; This function is called from before-change-functions (via - ;; c-get-state-before-change-functions). Thus the buffer is widened, - ;; and point is undefined, both at entry and exit. - ;; - ;; FIXME!!! This routine ignores the possibility of macros entirely. - ;; 2010-01-29. - (save-excursion - (let ((beg-lit-limits (progn (goto-char beg) (c-literal-limits))) - (end-lit-limits (progn (goto-char end) (c-literal-limits)))) - ;; Locate the barrier before the changed region - (goto-char (if beg-lit-limits (car beg-lit-limits) beg)) - (c-syntactic-skip-backward "^;{}" (max (- beg 2048) (point-min))) - - ;; Remove the syntax-table properties from each pertinent <...> pair. - ;; Firsly, the ones with the < before beg and > after beg. - (while (c-search-forward-char-property 'category 'c-<-as-paren-syntax beg) - (c-clear-<-pair-props-if-match-after beg (1- (point)))) - - ;; Locate the barrier after END. - (goto-char (if end-lit-limits (cdr end-lit-limits) end)) - (c-syntactic-re-search-forward "[;{}]" - (min (+ end 2048) (point-max)) 'end) - - ;; Remove syntax-table properties from the remaining pertinent <...> - ;; pairs, those with a > after end and < before end. - (while (c-search-backward-char-property 'category 'c->-as-paren-syntax end) - (c-clear->-pair-props-if-match-before end))))) - - +;; Handling of small scale constructs like types and names. (defun c-after-change-check-<>-operators (beg end) ;; This is called from `after-change-functions' when @@ -5065,7 +4131,7 @@ (< beg (setq beg (match-end 0)))) (while (progn (skip-chars-forward "^<>" beg) (< (point) beg)) - (c-clear-<>-pair-props) + (c-clear-char-property (point) 'syntax-table) (forward-char)))) (when (< beg end) @@ -5080,13 +4146,9 @@ (< end (setq end (match-end 0)))) (while (progn (skip-chars-forward "^<>" end) (< (point) end)) - (c-clear-<>-pair-props) + (c-clear-char-property (point) 'syntax-table) (forward-char))))))) - - -;; Handling of small scale constructs like types and names. - ;; Dynamically bound variable that instructs `c-forward-type' to also ;; treat possible types (i.e. those that it normally returns 'maybe or ;; 'found for) as actual types (and always return 'found for them). diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-fonts.el --- a/lisp/progmodes/cc-fonts.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-fonts.el Tue Apr 13 22:49:24 2010 +0000 @@ -426,8 +426,7 @@ (progn (c-mark-<-as-paren beg) (c-mark->-as-paren end)) - ;; (c-clear-char-property beg 'syntax-table) - (c-clear-char-property beg 'category))) + (c-clear-char-property beg 'syntax-table))) nil))))))) ;; #define. diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-langs.el --- a/lisp/progmodes/cc-langs.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-langs.el Tue Apr 13 22:49:24 2010 +0000 @@ -391,27 +391,6 @@ (and (c-lang-const c++-make-template-syntax-table) (funcall (c-lang-const c++-make-template-syntax-table)))) -(c-lang-defconst c-no-parens-syntax-table - ;; A variant of the standard syntax table which is used to find matching - ;; "<"s and ">"s which have been marked as parens using syntax table - ;; properties. The other paren characters (e.g. "{", ")" "]") are given a - ;; non-paren syntax here. so that the list commands will work on "< ... >" - ;; even when there's unbalanced other parens inside them. - ;; - ;; This variable is nil for languages which don't have template stuff. - t `(lambda () - (if (c-lang-const c-recognize-<>-arglists) - (let ((table (funcall ,(c-lang-const c-make-mode-syntax-table)))) - (modify-syntax-entry ?\( "." table) - (modify-syntax-entry ?\) "." table) - (modify-syntax-entry ?\[ "." table) - (modify-syntax-entry ?\] "." table) - (modify-syntax-entry ?\{ "." table) - (modify-syntax-entry ?\} "." table) - table)))) -(c-lang-defvar c-no-parens-syntax-table - (funcall (c-lang-const c-no-parens-syntax-table))) - (c-lang-defconst c-identifier-syntax-modifications "A list that describes the modifications that should be done to the mode syntax table to get a syntax table that matches all identifiers @@ -444,36 +423,26 @@ classifies symbol constituents like '_' and '$' as word constituents, so that all identifiers are recognized as words.") -(c-lang-defconst c-get-state-before-change-functions - ;; For documentation see the following c-lang-defvar of the same name. - ;; The value here may be a list of functions or a single function. - t nil - c++ '(c-extend-region-for-CPP c-before-change-check-<>-operators) - (c objc) 'c-extend-region-for-CPP - ;; java 'c-before-change-check-<>-operators - awk 'c-awk-record-region-clear-NL) -(c-lang-defvar c-get-state-before-change-functions - (let ((fs (c-lang-const c-get-state-before-change-functions))) - (if (listp fs) - fs - (list fs))) - "If non-nil, a list of functions called from c-before-change-hook. -Typically these will record enough state to allow +(c-lang-defconst c-get-state-before-change-function + "If non-nil, a function called from c-before-change-hook. +Typically it will record enough state to allow `c-before-font-lock-function' to extend the region to fontify, and may do such things as removing text-properties which must be recalculated. -These functions will be run in the order given. Each of them -takes 2 parameters, the BEG and END supplied to every +It takes 2 parameters, the BEG and END supplied to every before-change function; on entry, the buffer will have been widened and match-data will have been saved; point is undefined on both entry and exit; the return value is ignored. -The functions are called even when font locking isn't enabled. - -When the mode is initialized, the functions are called with -parameters \(point-min) and \(point-max).") - +When the mode is initialized, this function is called with +parameters \(point-min) and \(point-max)." + t nil + (c c++ objc) 'c-extend-region-for-CPP + awk 'c-awk-record-region-clear-NL) +(c-lang-defvar c-get-state-before-change-function + (c-lang-const c-get-state-before-change-function)) + (c-lang-defconst c-before-font-lock-function "If non-nil, a function called just before font locking. Typically it will extend the region about to be fontified \(see @@ -492,7 +461,7 @@ When the mode is initialized, this function is called with parameters \(point-min), \(point-max) and ." t nil - (c c++ objc) 'c-neutralize-syntax-in-and-mark-CPP + (c c++ objc) 'c-extend-and-neutralize-syntax-in-CPP awk 'c-awk-extend-and-syntax-tablify-region) (c-lang-defvar c-before-font-lock-function (c-lang-const c-before-font-lock-function)) diff -r 744ecddd9643 -r eb72bd4ec8f0 lisp/progmodes/cc-mode.el --- a/lisp/progmodes/cc-mode.el Mon Apr 12 00:59:45 2010 +0000 +++ b/lisp/progmodes/cc-mode.el Tue Apr 13 22:49:24 2010 +0000 @@ -410,7 +410,7 @@ ;; temporary changes in some font lock support modes, causing extra ;; unnecessary work and font lock glitches due to interactions between ;; various text properties. -;; +;; ;; (2007-02-12): The macro `combine-after-change-calls' ISN'T used any ;; more. @@ -451,18 +451,18 @@ end (point)))))))) ;; c-maybe-stale-found-type records a place near the region being -;; changed where an element of `found-types' might become stale. It +;; changed where an element of `found-types' might become stale. It ;; is set in c-before-change and is either nil, or has the form: ;; ;; (c-decl-id-start "foo" 97 107 " (* ooka) " "o"), where -;; +;; ;; o - `c-decl-id-start' is the c-type text property value at buffer ;; pos 96. -;; +;; ;; o - 97 107 is the region potentially containing the stale type - ;; this is delimited by a non-nil c-type text property at 96 and ;; either another one or a ";", "{", or "}" at 107. -;; +;; ;; o - " (* ooka) " is the (before change) buffer portion containing ;; the suspect type (here "ooka"). ;; @@ -517,9 +517,6 @@ (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'c-fill-paragraph) - ;; Initialise the cache of brace pairs, and opening braces/brackets/parens. - (c-state-cache-init) - (when (or c-recognize-<>-arglists (c-major-mode-is 'awk-mode) (c-major-mode-is '(c-mode c++-mode objc-mode))) @@ -641,10 +638,8 @@ (save-restriction (widen) (save-excursion - (if c-get-state-before-change-functions - (mapc (lambda (fn) - (funcall fn (point-min) (point-max))) - c-get-state-before-change-functions)) + (if c-get-state-before-change-function + (funcall c-get-state-before-change-function (point-min) (point-max))) (if c-before-font-lock-function (funcall c-before-font-lock-function (point-min) (point-max) (- (point-max) (point-min)))))) @@ -777,7 +772,7 @@ (defmacro c-run-mode-hooks (&rest hooks) ;; Emacs 21.1 has introduced a system with delayed mode hooks that - ;; requires the use of the new function `run-mode-hooks'. + ;; require the use of the new function `run-mode-hooks'. (if (cc-bytecomp-fboundp 'run-mode-hooks) `(run-mode-hooks ,@hooks) `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks)))) @@ -810,8 +805,8 @@ ;; has already been widened, and match-data saved. The return value is ;; meaningless. ;; - ;; This function is in the C/C++/ObjC values of - ;; `c-get-state-before-change-functions' and is called exclusively as a + ;; This function is the C/C++/ObjC value of + ;; `c-get-state-before-change-function' and is called exclusively as a ;; before change function. (goto-char beg) (c-beginning-of-macro) @@ -848,7 +843,7 @@ t) (t nil))))))) -(defun c-neutralize-syntax-in-and-mark-CPP (begg endd old-len) +(defun c-extend-and-neutralize-syntax-in-CPP (begg endd old-len) ;; (i) Extend the font lock region to cover all changed preprocessor ;; regions; it does this by setting the variables `c-new-BEG' and ;; `c-new-END' to the new boundaries. @@ -857,15 +852,10 @@ ;; extended changed region. "Restore" lines which were CPP lines before the ;; change and are no longer so; these can be located from the Buffer local ;; variables `c-old-BOM' and `c-old-EOM'. - ;; - ;; (iii) Mark every CPP construct by placing a `category' property value - ;; `c-cpp-delimiter' at its start and end. The marked characters are the - ;; opening # and usually the terminating EOL, but sometimes the character - ;; before a comment/string delimiter. - ;; + ;; ;; That is, set syntax-table properties on characters that would otherwise ;; interact syntactically with those outside the CPP line(s). - ;; + ;; ;; This function is called from an after-change function, BEGG ENDD and ;; OLD-LEN being the standard parameters. It prepares the buffer for font ;; locking, hence must get called before `font-lock-after-change-function'. @@ -876,34 +866,32 @@ ;; This function is the C/C++/ObjC value of `c-before-font-lock-function'. ;; ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! - ;; + ;; ;; This function might make hidden buffer changes. - (c-save-buffer-state (limits) + (c-save-buffer-state (limits mbeg+1) ;; First determine the region, (c-new-BEG c-new-END), which will get font ;; locked. It might need "neutralizing". This region may not start ;; inside a string, comment, or macro. (goto-char c-old-BOM) ; already set to old start of macro or begg. (setq c-new-BEG - (if (setq limits (c-state-literal-at (point))) + (if (setq limits (c-literal-limits)) (cdr limits) ; go forward out of any string or comment. (point))) (goto-char endd) - (if (setq limits (c-state-literal-at (point))) + (if (setq limits (c-literal-limits)) (goto-char (car limits))) ; go backward out of any string or comment. (if (c-beginning-of-macro) (c-end-of-macro)) (setq c-new-END (max (+ (- c-old-EOM old-len) (- endd begg)) (point))) - ;; Clear all old relevant properties. + ;; Clear any existing punctuation properties. (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) - (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter) - ;; FIXME!!! What about the "<" and ">" category properties? 2009-11-16 ;; Add needed properties to each CPP construct in the region. (goto-char c-new-BEG) - (let ((pps-position c-new-BEG) pps-state mbeg) + (let ((pps-position c-new-BEG) pps-state) (while (and (< (point) c-new-END) (search-forward-regexp c-anchored-cpp-prefix c-new-END t)) ;; If we've found a "#" inside a string/comment, ignore it. @@ -912,24 +900,18 @@ pps-position (point)) (unless (or (nth 3 pps-state) ; in a string? (nth 4 pps-state)) ; in a comment? - (goto-char (match-beginning 0)) - (setq mbeg (point)) - (if (> (c-syntactic-end-of-macro) mbeg) - (progn - (c-neutralize-CPP-line mbeg (point)) - (c-set-cpp-delimiters mbeg (point)) - ;(setq pps-position (point)) - ) - (forward-line)) ; no infinite loop with, e.g., "#//" - ))))) + (setq mbeg+1 (point)) + (c-end-of-macro) ; Do we need to go forward 1 char here? No! + (c-neutralize-CPP-line mbeg+1 (point)) + (setq pps-position (point))))))) ; no need to update pps-state. (defun c-before-change (beg end) - ;; Function to be put on `before-change-functions'. Primarily, this calls - ;; the language dependent `c-get-state-before-change-functions'. It is + ;; Function to be put on `before-change-function'. Primarily, this calls + ;; the language dependent `c-get-state-before-change-function'. It is ;; otherwise used only to remove stale entries from the `c-found-types' ;; cache, and to record entries which a `c-after-change' function might ;; confirm as stale. - ;; + ;; ;; Note that this function must be FAST rather than accurate. Note ;; also that it only has any effect when font locking is enabled. ;; We exploit this by checking for font-lock-*-face instead of doing @@ -1003,10 +985,8 @@ ;; larger than (beg end). (setq c-new-BEG beg c-new-END end) - (if c-get-state-before-change-functions - (mapc (lambda (fn) - (funcall fn beg end)) - c-get-state-before-change-functions)) + (if c-get-state-before-change-function + (funcall c-get-state-before-change-function beg end)) )))) (defun c-after-change (beg end old-len) @@ -1040,14 +1020,6 @@ (when (> beg end) (setq beg end))) - ;; C-y is capable of spuriously converting category properties - ;; c--as-paren-syntax into hard syntax-table properties. Remove - ;; these when it happens. - (c-clear-char-property-with-value beg end 'syntax-table - c-<-as-paren-syntax) - (c-clear-char-property-with-value beg end 'syntax-table - c->-as-paren-syntax) - (c-trim-found-types beg end old-len) ; maybe we don't need all of these. (c-invalidate-sws-region-after beg end) (c-invalidate-state-cache beg) diff -r 744ecddd9643 -r eb72bd4ec8f0 src/ChangeLog --- a/src/ChangeLog Mon Apr 12 00:59:45 2010 +0000 +++ b/src/ChangeLog Tue Apr 13 22:49:24 2010 +0000 @@ -1,3 +1,8 @@ +2010-04-13 Adrian Robert + + * nsmenu.m (EmacsDialog-runDialogAt:): Declare ret as + NSInteger (Bug#5811). + 2010-04-10 YAMAMOTO Mitsuharu * s/darwin.h (PTY_ITERATION, PTY_NAME_SPRINTF, PTY_TTY_NAME_SPRINTF) diff -r 744ecddd9643 -r eb72bd4ec8f0 src/nsmenu.m --- a/src/nsmenu.m Mon Apr 12 00:59:45 2010 +0000 +++ b/src/nsmenu.m Tue Apr 13 22:49:24 2010 +0000 @@ -1709,7 +1709,7 @@ - (Lisp_Object)runDialogAt: (NSPoint)p { - int ret; + NSInteger ret; extern EMACS_TIME timer_check (int do_it_now); /* TODO: add to a header */ /* initiate a session that will be ended by pop_down_menu */