aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2008-02-19 22:14:40 +0000
committerAlan Mackenzie2008-02-19 22:14:40 +0000
commit1d1e48680da355a2272071309b4be9d2caf90e41 (patch)
treee8438e6e6ba6d6ea267345ab55585fcfed8894ea
parent5ee2e9881b707eed5b3f2f5a07b2e20fac001759 (diff)
downloademacs-1d1e48680da355a2272071309b4be9d2caf90e41.tar.gz
emacs-1d1e48680da355a2272071309b4be9d2caf90e41.zip
Set of changes so that "obtrusive" syntactic elements in a
C/C++/ObjC preprocessor line (e.g. an unbalanced string quote or unmatched paren) don't interact syntactically with stuff outside the CPP line. (c-basic-common-init): C and ObjC now use syntax-table text properties. (c-common-init): Call language specific before/after-change functions at mode initialisation. (c-new-BEG, c-new-END, c-old-BOM, c-old-EOM): new variables. (c-extend-region-for-CPP, c-neutralize-CPP-line, c-neutralize-syntax-in-CPP): new functions. (c-before-change, c-after-change): call the new language specific change functions defined in cc-langs.el. (c-advise-fl-for-region): new macro. (awk-mode): Remove AWK specific stuff which has been refactored into language independent stuff.
-rw-r--r--lisp/progmodes/cc-mode.el440
1 files changed, 286 insertions, 154 deletions
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 24e2023ba5d..6f184a399f9 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -464,117 +464,6 @@ preferably use the `c-mode-menu' language constant directly."
464(defvar c-maybe-stale-found-type nil) 464(defvar c-maybe-stale-found-type nil)
465(make-variable-buffer-local 'c-maybe-stale-found-type) 465(make-variable-buffer-local 'c-maybe-stale-found-type)
466 466
467(defun c-before-change (beg end)
468 ;; Function to be put on `before-change-function'. Currently
469 ;; (2007-02) it is used only to remove stale entries from the
470 ;; `c-found-types' cache, and to record entries which a
471 ;; `c-after-change' function might confirm as stale.
472 ;;
473 ;; Note that this function must be FAST rather than accurate. Note
474 ;; also that it only has any effect when font locking is enabled.
475 ;; We exploit this by checking for font-lock-*-face instead of doing
476 ;; rigourous syntactic analysis.
477
478 ;; If either change boundary is wholly inside an identifier, delete
479 ;; it/them from the cache. Don't worry about being inside a string
480 ;; or a comment - "wrongly" removing a symbol from `c-found-types'
481 ;; isn't critical.
482 (setq c-maybe-stale-found-type nil)
483 (save-restriction
484 (save-match-data
485 (widen)
486 (save-excursion
487 ;; Are we inserting/deleting stuff in the middle of an identifier?
488 (c-unfind-enclosing-token beg)
489 (c-unfind-enclosing-token end)
490 ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
491 (when (< beg end)
492 (c-unfind-coalesced-tokens beg end))
493 ;; Are we (potentially) disrupting the syntactic context which
494 ;; makes a type a type? E.g. by inserting stuff after "foo" in
495 ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
496 ;;
497 ;; We search for appropriate c-type properties "near" the change.
498 ;; First, find an appropriate boundary for this property search.
499 (let (lim
500 type type-pos
501 marked-id term-pos
502 (end1
503 (or (and (eq (get-text-property end 'face) 'font-lock-comment-face)
504 (previous-single-property-change end 'face))
505 end)))
506 (when (>= end1 beg) ; Don't hassle about changes entirely in comments.
507 ;; Find a limit for the search for a `c-type' property
508 (while
509 (and (/= (skip-chars-backward "^;{}") 0)
510 (> (point) (point-min))
511 (memq (c-get-char-property (1- (point)) 'face)
512 '(font-lock-comment-face font-lock-string-face))))
513 (setq lim (max (point-min) (1- (point))))
514
515 ;; Look for the latest `c-type' property before end1
516 (when (and (> end1 (point-min))
517 (setq type-pos
518 (if (get-text-property (1- end1) 'c-type)
519 end1
520 (previous-single-property-change end1 'c-type nil lim))))
521 (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
522
523 (when (memq type '(c-decl-id-start c-decl-type-start))
524 ;; Get the identifier, if any, that the property is on.
525 (goto-char (1- type-pos))
526 (setq marked-id
527 (when (looking-at "\\(\\sw\\|\\s_\\)")
528 (c-beginning-of-current-token)
529 (buffer-substring-no-properties (point) type-pos)))
530
531 (goto-char end1)
532 (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe
533 (setq lim (point))
534 (setq term-pos
535 (or (next-single-property-change end 'c-type nil lim) lim))
536 (setq c-maybe-stale-found-type
537 (list type marked-id
538 type-pos term-pos
539 (buffer-substring-no-properties type-pos term-pos)
540 (buffer-substring-no-properties beg end)))))))))))
541
542(defun c-after-change (beg end old-len)
543 ;; Function put on `after-change-functions' to adjust various caches
544 ;; etc. Prefer speed to finesse here, since there will be an order
545 ;; of magnitude more calls to this function than any of the
546 ;; functions that use the caches.
547 ;;
548 ;; Note that care must be taken so that this is called before any
549 ;; font-lock callbacks since we might get calls to functions using
550 ;; these caches from inside them, and we must thus be sure that this
551 ;; has already been executed.
552
553 (c-save-buffer-state ()
554 ;; When `combine-after-change-calls' is used we might get calls
555 ;; with regions outside the current narrowing. This has been
556 ;; observed in Emacs 20.7.
557 (save-restriction
558 (save-match-data ; c-recognize-<>-arglists changes match-data
559 (widen)
560
561 (when (> end (point-max))
562 ;; Some emacsen might return positions past the end. This has been
563 ;; observed in Emacs 20.7 when rereading a buffer changed on disk
564 ;; (haven't been able to minimize it, but Emacs 21.3 appears to
565 ;; work).
566 (setq end (point-max))
567 (when (> beg end)
568 (setq beg end)))
569
570 (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
571 (c-invalidate-sws-region-after beg end)
572 (c-invalidate-state-cache beg)
573 (c-invalidate-find-decl-cache beg)
574
575 (when c-recognize-<>-arglists
576 (c-after-change-check-<>-operators beg end))))))
577
578(defun c-basic-common-init (mode default-style) 467(defun c-basic-common-init (mode default-style)
579 "Do the necessary initialization for the syntax handling routines 468 "Do the necessary initialization for the syntax handling routines
580and the line breaking/filling code. Intended to be used by other 469and the line breaking/filling code. Intended to be used by other
@@ -622,7 +511,8 @@ that requires a literal mode spec at compile time."
622 (setq fill-paragraph-function 'c-fill-paragraph) 511 (setq fill-paragraph-function 'c-fill-paragraph)
623 512
624 (when (or c-recognize-<>-arglists 513 (when (or c-recognize-<>-arglists
625 (c-major-mode-is 'awk-mode)) 514 (c-major-mode-is 'awk-mode)
515 (c-major-mode-is '(c-mode c++-mode objc-mode)))
626 ;; We'll use the syntax-table text property to change the syntax 516 ;; We'll use the syntax-table text property to change the syntax
627 ;; of some chars for this language, so do the necessary setup for 517 ;; of some chars for this language, so do the necessary setup for
628 ;; that. 518 ;; that.
@@ -709,34 +599,6 @@ that requires a literal mode spec at compile time."
709 (make-local-hook 'after-change-functions) 599 (make-local-hook 'after-change-functions)
710 (add-hook 'after-change-functions 'c-after-change nil t)) 600 (add-hook 'after-change-functions 'c-after-change nil t))
711 601
712(defun c-after-font-lock-init ()
713 ;; Put on `font-lock-mode-hook'.
714 (remove-hook 'after-change-functions 'c-after-change t)
715 (add-hook 'after-change-functions 'c-after-change nil t))
716
717(defun c-font-lock-init ()
718 "Set up the font-lock variables for using the font-lock support in CC Mode.
719This does not load the font-lock package. Use after
720`c-basic-common-init' and after cc-fonts has been loaded."
721
722 (make-local-variable 'font-lock-defaults)
723 (setq font-lock-defaults
724 `(,(if (c-major-mode-is 'awk-mode)
725 ;; awk-mode currently has only one font lock level.
726 'awk-font-lock-keywords
727 (mapcar 'c-mode-symbol
728 '("font-lock-keywords" "font-lock-keywords-1"
729 "font-lock-keywords-2" "font-lock-keywords-3")))
730 nil nil
731 ,c-identifier-syntax-modifications
732 c-beginning-of-syntax
733 (font-lock-lines-before . 1)
734 (font-lock-mark-block-function
735 . c-mark-function)))
736
737 (make-local-hook 'font-lock-mode-hook)
738 (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
739
740(defun c-setup-doc-comment-style () 602(defun c-setup-doc-comment-style ()
741 "Initialize the variables that depend on the value of `c-doc-comment-style'." 603 "Initialize the variables that depend on the value of `c-doc-comment-style'."
742 (when (and (featurep 'font-lock) 604 (when (and (featurep 'font-lock)
@@ -766,6 +628,16 @@ compatible with old code; callers should always specify it."
766 ;; Only initialize font locking if we aren't called from an old package. 628 ;; Only initialize font locking if we aren't called from an old package.
767 (c-font-lock-init)) 629 (c-font-lock-init))
768 630
631 ;; Starting a mode is a sort of "change". So call the change functions...
632 (save-restriction
633 (widen)
634 (save-excursion
635 (if c-get-state-before-change-function
636 (funcall c-get-state-before-change-function (point-min) (point-max)))
637 (if c-before-font-lock-function
638 (funcall c-before-font-lock-function (point-min) (point-max)
639 (- (point-max) (point-min))))))
640
769 (make-local-variable 'outline-regexp) 641 (make-local-variable 'outline-regexp)
770 (make-local-variable 'outline-level) 642 (make-local-variable 'outline-level)
771 (setq outline-regexp "[^#\n\^M]" 643 (setq outline-regexp "[^#\n\^M]"
@@ -875,6 +747,280 @@ Note that the style variables are always made local to the buffer."
875 `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks)))) 747 `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks))))
876 748
877 749
750;;; Change hooks, linking with Font Lock.
751
752;; Buffer local variables defining the region to be fontified by a font lock
753;; after-change function. They are set in c-after-change to
754;; after-change-function's BEG and END, and may be modified by a
755;; `c-before-font-lock-function'.
756(defvar c-new-BEG 0)
757(make-variable-buffer-local 'c-new-BEG)
758(defvar c-new-END 0)
759(make-variable-buffer-local 'c-new-END)
760
761;; Buffer local variables recording Beginning/End-of-Macro position before a
762;; change, when a macro straddles, respectively, the BEG or END (or both) of
763;; the change region. Otherwise these have the values BEG/END.
764(defvar c-old-BOM 0)
765(make-variable-buffer-local 'c-old-BOM)
766(defvar c-old-EOM 0)
767(make-variable-buffer-local 'c-old-EOM)
768
769(defun c-extend-region-for-CPP (beg end)
770 ;; If either BEG or END is inside a preprocessor (logical) line, set
771 ;; c-old-BOM or c-ole-EOM respectively to the beginning/end of the line.
772 ;;
773 ;; Point is undefined both before and after this function call; the buffer
774 ;; has already been widened, and match-data saved. The return value is
775 ;; meaningless.
776 ;;
777 ;; This function is the C/C++/ObjC value of
778 ;; `c-get-state-before-change-function' and is called exclusively as a
779 ;; before change function.
780 (goto-char beg)
781 (c-beginning-of-macro)
782 (setq c-old-BOM (point))
783
784 (goto-char end)
785 (when (c-beginning-of-macro)
786 (c-end-of-macro)
787 (setq c-old-EOM (point))))
788
789(defun c-neutralize-CPP-line (beg end)
790 ;; BEG and END bound a preprocessor line. Put a "punctuation" syntax-table
791 ;; property on syntactically obtrusive characters, ones which would interact
792 ;; syntactically with stuff outside the CPP line.
793 ;;
794 ;; These are unmatched string delimiters, or unmatched
795 ;; parens/brackets/braces. An unclosed comment is regarded as valid, NOT
796 ;; obtrusive.
797 (let (s)
798 (while
799 (progn
800 (setq s (parse-partial-sexp beg end -1))
801 (cond
802 ((< (nth 0 s) 0) ; found an unmated ),},]
803 (c-put-char-property (1- (point)) 'syntax-table '(1))
804 t)
805 ((nth 3 s) ; In a string
806 (c-put-char-property (nth 8 s) 'syntax-table '(1))
807 t)
808 ((> (nth 0 s) 0) ; In a (,{,[
809 (c-put-char-property (nth 1 s) 'syntax-table '(1))
810 t)
811 (t nil))))))
812
813(defun c-neutralize-syntax-in-CPP (begg endd old-len)
814 ;; "Neutralize" every preprocessor line wholly or partially in the changed
815 ;; region. "Restore" lines which were CPP lines before the change and are
816 ;; no longer so; these can be located from the Buffer local variables
817 ;; c-old-[EB]OM.
818 ;;
819 ;; That is, set syntax-table properties on characters that would otherwise
820 ;; interact syntactically with those outside the CPP line(s).
821 ;;
822 ;; This function is called from an after-change function, BEGG ENDD and
823 ;; OLD-LEN being the standard parameters. It prepares the buffer for font
824 ;; locking, hence must get called before `font-lock-after-change-function'.
825 ;;
826 ;; Point is undefined both before and after this function call, the buffer
827 ;; has been widened, and match-data saved. The return value is ignored.
828 ;;
829 ;; This function is the C/C++/ObjC value of `c-before-font-lock-function'.
830 ;;
831 ;; This function might do invisible changes.
832 (c-save-buffer-state (limits mbeg beg end)
833 ;; First calculate the region, possibly to be extended.
834 (setq beg (min begg c-old-BOM))
835 (goto-char endd)
836 (when (c-beginning-of-macro)
837 (c-end-of-macro))
838 (setq end (max (+ (- c-old-EOM old-len) (- endd begg))
839 (point)))
840 ;; Clear all old punctuation properties
841 (c-clear-char-property-with-value beg end 'syntax-table '(1))
842
843 (goto-char beg)
844 ;; If we're inside a string/comment, go to its end.
845 (if (setq limits (c-literal-limits))
846 (goto-char (cdr limits)))
847
848 (while (and (< (point) end)
849 (search-forward-regexp c-anchored-cpp-prefix end t))
850 (when (c-beginning-of-macro) ; Guard against being in a string/comment.
851 (setq mbeg (point))
852 (c-end-of-macro) ; Do we need to go forward 1 char here? No!
853 (c-neutralize-CPP-line mbeg (point)))
854 (forward-char)))) ; We might still be in a comment - this is OK.
855
856(defun c-before-change (beg end)
857 ;; Function to be put on `before-change-function'. Primarily, this calls
858 ;; the language dependent `c-get-state-before-change-function'. It is
859 ;; otherwise used only to remove stale entries from the `c-found-types'
860 ;; cache, and to record entries which a `c-after-change' function might
861 ;; confirm as stale.
862 ;;
863 ;; Note that this function must be FAST rather than accurate. Note
864 ;; also that it only has any effect when font locking is enabled.
865 ;; We exploit this by checking for font-lock-*-face instead of doing
866 ;; rigourous syntactic analysis.
867
868 ;; If either change boundary is wholly inside an identifier, delete
869 ;; it/them from the cache. Don't worry about being inside a string
870 ;; or a comment - "wrongly" removing a symbol from `c-found-types'
871 ;; isn't critical.
872 (setq c-maybe-stale-found-type nil)
873 (save-restriction
874 (save-match-data
875 (widen)
876 (save-excursion
877 ;; Are we inserting/deleting stuff in the middle of an identifier?
878 (c-unfind-enclosing-token beg)
879 (c-unfind-enclosing-token end)
880 ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
881 (when (< beg end)
882 (c-unfind-coalesced-tokens beg end))
883 ;; Are we (potentially) disrupting the syntactic context which
884 ;; makes a type a type? E.g. by inserting stuff after "foo" in
885 ;; "foo bar;", or before "foo" in "typedef foo *bar;"?
886 ;;
887 ;; We search for appropriate c-type properties "near" the change.
888 ;; First, find an appropriate boundary for this property search.
889 (let (lim
890 type type-pos
891 marked-id term-pos
892 (end1
893 (or (and (eq (get-text-property end 'face) 'font-lock-comment-face)
894 (previous-single-property-change end 'face))
895 end)))
896 (when (>= end1 beg) ; Don't hassle about changes entirely in comments.
897 ;; Find a limit for the search for a `c-type' property
898 (while
899 (and (/= (skip-chars-backward "^;{}") 0)
900 (> (point) (point-min))
901 (memq (c-get-char-property (1- (point)) 'face)
902 '(font-lock-comment-face font-lock-string-face))))
903 (setq lim (max (point-min) (1- (point))))
904
905 ;; Look for the latest `c-type' property before end1
906 (when (and (> end1 (point-min))
907 (setq type-pos
908 (if (get-text-property (1- end1) 'c-type)
909 end1
910 (previous-single-property-change end1 'c-type nil lim))))
911 (setq type (get-text-property (max (1- type-pos) lim) 'c-type))
912
913 (when (memq type '(c-decl-id-start c-decl-type-start))
914 ;; Get the identifier, if any, that the property is on.
915 (goto-char (1- type-pos))
916 (setq marked-id
917 (when (looking-at "\\(\\sw\\|\\s_\\)")
918 (c-beginning-of-current-token)
919 (buffer-substring-no-properties (point) type-pos)))
920
921 (goto-char end1)
922 (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe
923 (setq lim (point))
924 (setq term-pos
925 (or (next-single-property-change end 'c-type nil lim) lim))
926 (setq c-maybe-stale-found-type
927 (list type marked-id
928 type-pos term-pos
929 (buffer-substring-no-properties type-pos term-pos)
930 (buffer-substring-no-properties beg end)))))))
931
932 (setq c-new-BEG beg
933 c-new-END end)
934 (if c-get-state-before-change-function
935 (funcall c-get-state-before-change-function beg end))
936 ))))
937
938(defun c-after-change (beg end old-len)
939 ;; Function put on `after-change-functions' to adjust various caches
940 ;; etc. Prefer speed to finesse here, since there will be an order
941 ;; of magnitude more calls to this function than any of the
942 ;; functions that use the caches.
943 ;;
944 ;; Note that care must be taken so that this is called before any
945 ;; font-lock callbacks since we might get calls to functions using
946 ;; these caches from inside them, and we must thus be sure that this
947 ;; has already been executed.
948 ;;
949 ;; This calls the language variable c-before-font-lock-function, if non nil.
950 ;; This typically sets `syntax-table' properties.
951
952 (c-save-buffer-state ()
953 ;; When `combine-after-change-calls' is used we might get calls
954 ;; with regions outside the current narrowing. This has been
955 ;; observed in Emacs 20.7.
956 (save-restriction
957 (save-match-data ; c-recognize-<>-arglists changes match-data
958 (widen)
959
960 (when (> end (point-max))
961 ;; Some emacsen might return positions past the end. This has been
962 ;; observed in Emacs 20.7 when rereading a buffer changed on disk
963 ;; (haven't been able to minimize it, but Emacs 21.3 appears to
964 ;; work).
965 (setq end (point-max))
966 (when (> beg end)
967 (setq beg end)))
968
969 (c-trim-found-types beg end old-len) ; maybe we don't need all of these.
970 (c-invalidate-sws-region-after beg end)
971 (c-invalidate-state-cache beg)
972 (c-invalidate-find-decl-cache beg)
973
974 (when c-recognize-<>-arglists
975 (c-after-change-check-<>-operators beg end))
976
977 (if c-before-font-lock-function
978 (save-excursion
979 (funcall c-before-font-lock-function beg end old-len)))))))
980
981(defun c-after-font-lock-init ()
982 ;; Put on `font-lock-mode-hook'.
983 (remove-hook 'after-change-functions 'c-after-change t)
984 (add-hook 'after-change-functions 'c-after-change nil t))
985
986(defun c-font-lock-init ()
987 "Set up the font-lock variables for using the font-lock support in CC Mode.
988This does not load the font-lock package. Use after
989`c-basic-common-init' and after cc-fonts has been loaded."
990
991 (make-local-variable 'font-lock-defaults)
992 (setq font-lock-defaults
993 `(,(if (c-major-mode-is 'awk-mode)
994 ;; awk-mode currently has only one font lock level.
995 'awk-font-lock-keywords
996 (mapcar 'c-mode-symbol
997 '("font-lock-keywords" "font-lock-keywords-1"
998 "font-lock-keywords-2" "font-lock-keywords-3")))
999 nil nil
1000 ,c-identifier-syntax-modifications
1001 c-beginning-of-syntax
1002 (font-lock-lines-before . 1)
1003 (font-lock-mark-block-function
1004 . c-mark-function)))
1005
1006 (make-local-hook 'font-lock-mode-hook)
1007 (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))
1008
1009(defmacro c-advise-fl-for-region (function)
1010 `(defadvice ,function (before get-awk-region activate)
1011;; When font-locking an AWK Mode buffer, make sure that any string/regexp is
1012;; completely font-locked.
1013 (when (eq major-mode 'awk-mode)
1014 (save-excursion
1015 (ad-set-arg 1 c-new-END) ; end
1016 (ad-set-arg 0 c-new-BEG))))) ; beg
1017
1018(c-advise-fl-for-region font-lock-after-change-function)
1019(c-advise-fl-for-region jit-lock-after-change)
1020(c-advise-fl-for-region lazy-lock-defer-rest-after-change)
1021(c-advise-fl-for-region lazy-lock-defer-line-after-change)
1022
1023
878;; Support for C 1024;; Support for C
879 1025
880;;;###autoload 1026;;;###autoload
@@ -1336,21 +1482,7 @@ Key bindings:
1336 (use-local-map awk-mode-map) 1482 (use-local-map awk-mode-map)
1337 (c-init-language-vars-for 'awk-mode) 1483 (c-init-language-vars-for 'awk-mode)
1338 (c-common-init 'awk-mode) 1484 (c-common-init 'awk-mode)
1339 ;; The rest of CC Mode does not (yet) use `font-lock-syntactic-keywords',
1340 ;; so it's not set by `c-font-lock-init'.
1341 (make-local-variable 'font-lock-syntactic-keywords)
1342 (setq font-lock-syntactic-keywords
1343 '((c-awk-set-syntax-table-properties
1344 0 (0) ; Everything on this line is a dummy.
1345 nil t)))
1346 (c-awk-unstick-NL-prop) 1485 (c-awk-unstick-NL-prop)
1347 (add-hook 'before-change-functions 'c-awk-before-change nil t)
1348 (add-hook 'after-change-functions 'c-awk-after-change nil t)
1349 (c-save-buffer-state nil
1350 (save-restriction
1351 (widen)
1352 (c-awk-clear-NL-props (point-min) (point-max))
1353 (c-awk-after-change (point-min) (point-max) 0))) ; Set syntax-table props.
1354 1486
1355 ;; Prevent Xemacs's buffer-syntactic-context being used. See the comment 1487 ;; Prevent Xemacs's buffer-syntactic-context being used. See the comment
1356 ;; in cc-engine.el, just before (defun c-fast-in-literal ... 1488 ;; in cc-engine.el, just before (defun c-fast-in-literal ...