aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2011-07-26 19:18:40 +0000
committerAlan Mackenzie2011-07-26 19:18:40 +0000
commitb248a85d103b7f34b9747e8d6884179bf3d4decb (patch)
tree333bf00f158a25e470684db5ef2dcfaa2e96663e
parent68575ab00b802b29b0bc74ebb3780a81a7550698 (diff)
downloademacs-b248a85d103b7f34b9747e8d6884179bf3d4decb.tar.gz
emacs-b248a85d103b7f34b9747e8d6884179bf3d4decb.zip
Fontify bitfield declarations properly.
cc-langs.el (c-has-bitfields): New lang variable. (c-symbol-chars): Now exported as a lang variable. (c-not-primitive-type-keywords): New lang variable. cc-fonts.el (c-font-lock-declarations): Jump over the QT keyword "more" to prevent "more slots: ...." being spuriously parsed as a bitfield declaraion. cc-engine.el (c-beginning-of-statement-1): Refactor and enhance to handle bitfield declarations. (c-punctuation-in): New function. (c-forward-decl-or-cast-1): Enhance CASE 3 to handle bitfield declarations properly.
-rw-r--r--lisp/ChangeLog18
-rw-r--r--lisp/progmodes/cc-engine.el229
-rw-r--r--lisp/progmodes/cc-fonts.el8
-rw-r--r--lisp/progmodes/cc-langs.el22
4 files changed, 181 insertions, 96 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index b2e2dd6d8aa..8a25116efcb 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,21 @@
12011-07-26 Alan Mackenzie <acm@muc.de>
2
3 Fontify bitfield declarations properly.
4
5 * progmodes/cc-langs.el (c-has-bitfields): New lang variable.
6 (c-symbol-chars): Now exported as a lang variable.
7 (c-not-primitive-type-keywords): New lang variable.
8
9 * progmodes/cc-fonts.el (c-font-lock-declarations): Jump over the
10 QT keyword "more" to prevent "more slots: ...." being spuriously
11 parsed as a bitfield declaraion.
12
13 * progmodes/cc-engine.el (c-beginning-of-statement-1): Refactor
14 and enhance to handle bitfield declarations.
15 (c-punctuation-in): New function.
16 (c-forward-decl-or-cast-1): Enhance CASE 3 to handle bitfield
17 declarations properly.
18
12011-07-26 Ulf Jasper <ulf.jasper@web.de> 192011-07-26 Ulf Jasper <ulf.jasper@web.de>
2 20
3 * calendar/icalendar.el (icalendar--all-events): Take care of 21 * calendar/icalendar.el (icalendar--all-events): Take care of
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index a6fd28be21d..0236a2be296 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -709,6 +709,9 @@ comment at the start of cc-engine.el for more info."
709 ;; content was found in the label. Note that we might still 709 ;; content was found in the label. Note that we might still
710 ;; regard it a label if it starts with `c-label-kwds'. 710 ;; regard it a label if it starts with `c-label-kwds'.
711 label-good-pos 711 label-good-pos
712 ;; Putative positions of the components of a bitfield declaration,
713 ;; e.g. "int foo : NUM_FOO_BITS ;"
714 bitfield-type-pos bitfield-id-pos bitfield-size-pos
712 ;; Symbol just scanned back over (e.g. 'while or 'boundary). 715 ;; Symbol just scanned back over (e.g. 'while or 'boundary).
713 ;; See above. 716 ;; See above.
714 sym 717 sym
@@ -765,13 +768,22 @@ comment at the start of cc-engine.el for more info."
765 ;; Record this as the first token if not starting inside it. 768 ;; Record this as the first token if not starting inside it.
766 (setq tok start)) 769 (setq tok start))
767 770
768 ;; The following while loop goes back one sexp (balanced parens, 771
769 ;; etc. with contents, or symbol or suchlike) each iteration. This 772 ;; The following while loop goes back one sexp (balanced parens,
770 ;; movement is accomplished with a call to scan-sexps approx 130 lines 773 ;; etc. with contents, or symbol or suchlike) each iteration. This
771 ;; below. 774 ;; movement is accomplished with a call to c-backward-sexp approx 170
775 ;; lines below.
776 ;;
777 ;; The loop is exited only by throwing nil to the (catch 'loop ...):
778 ;; 1. On reaching the start of a macro;
779 ;; 2. On having passed a stmt boundary with the PDA stack empty;
780 ;; 3. On reaching the start of an Objective C method def;
781 ;; 4. From macro `c-bos-pop-state'; when the stack is empty;
782 ;; 5. From macro `c-bos-pop-state-and-retry' when the stack is empty.
772 (while 783 (while
773 (catch 'loop ;; Throw nil to break, non-nil to continue. 784 (catch 'loop ;; Throw nil to break, non-nil to continue.
774 (cond 785 (cond
786 ;; Are we in a macro, just after the opening #?
775 ((save-excursion 787 ((save-excursion
776 (and macro-start ; Always NIL for AWK. 788 (and macro-start ; Always NIL for AWK.
777 (progn (skip-chars-backward " \t") 789 (progn (skip-chars-backward " \t")
@@ -792,7 +804,7 @@ comment at the start of cc-engine.el for more info."
792 (setq pos saved 804 (setq pos saved
793 ret 'macro 805 ret 'macro
794 ignore-labels t)) 806 ignore-labels t))
795 (throw 'loop nil)) 807 (throw 'loop nil)) ; 1. Start of macro.
796 808
797 ;; Do a round through the automaton if we've just passed a 809 ;; Do a round through the automaton if we've just passed a
798 ;; statement boundary or passed a "while"-like token. 810 ;; statement boundary or passed a "while"-like token.
@@ -801,7 +813,7 @@ comment at the start of cc-engine.el for more info."
801 (setq sym (intern (match-string 1))))) 813 (setq sym (intern (match-string 1)))))
802 814
803 (when (and (< pos start) (null stack)) 815 (when (and (< pos start) (null stack))
804 (throw 'loop nil)) 816 (throw 'loop nil)) ; 2. Statement boundary.
805 817
806 ;; The PDA state handling. 818 ;; The PDA state handling.
807 ;; 819 ;;
@@ -918,19 +930,14 @@ comment at the start of cc-engine.el for more info."
918 ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE 930 ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
919 ;; BACKWARDS THROUGH THE SOURCE. 931 ;; BACKWARDS THROUGH THE SOURCE.
920 932
921 ;; This is typically fast with the caching done by
922 ;; c-(backward|forward)-sws.
923 (c-backward-syntactic-ws) 933 (c-backward-syntactic-ws)
924
925 (let ((before-sws-pos (point)) 934 (let ((before-sws-pos (point))
926 ;; Set as long as we have to continue jumping by sexps.
927 ;; It's the position to use as end in the next round.
928 sexp-loop-continue-pos
929 ;; The end position of the area to search for statement 935 ;; The end position of the area to search for statement
930 ;; barriers in this round. 936 ;; barriers in this round.
931 (sexp-loop-end-pos pos)) 937 (maybe-after-boundary-pos pos))
932 938
933 ;; The following while goes back one sexp per iteration. 939 ;; Go back over exactly one logical sexp, taking proper
940 ;; account of macros and escaped EOLs.
934 (while 941 (while
935 (progn 942 (progn
936 (unless (c-safe (c-backward-sexp) t) 943 (unless (c-safe (c-backward-sexp) t)
@@ -938,81 +945,87 @@ comment at the start of cc-engine.el for more info."
938 ;; stack won't be empty the code below will report a 945 ;; stack won't be empty the code below will report a
939 ;; suitable error. 946 ;; suitable error.
940 (throw 'loop nil)) 947 (throw 'loop nil))
941 948 (cond
942 ;; Check if the sexp movement crossed a statement or 949 ;; Have we moved into a macro?
943 ;; declaration boundary. But first modify the point 950 ((and (not macro-start)
944 ;; so that `c-crosses-statement-barrier-p' only looks 951 (c-beginning-of-macro))
945 ;; at the non-sexp chars following the sexp. 952 ;; Have we crossed a statement boundary? If not,
946 (save-excursion 953 ;; keep going back until we find one or a "real" sexp.
947 (when (setq 954 (and
948 boundary-pos 955 (save-excursion
949 (cond 956 (c-end-of-macro)
950 ((if macro-start 957 (not (c-crosses-statement-barrier-p
951 nil 958 (point) maybe-after-boundary-pos)))
952 (save-excursion 959 (setq maybe-after-boundary-pos (point))))
953 (when (c-beginning-of-macro) 960 ;; Have we just gone back over an escaped NL? This
954 ;; Set continuation position in case 961 ;; doesn't count as a sexp.
955 ;; `c-crosses-statement-barrier-p' 962 ((looking-at "\\\\$")))))
956 ;; doesn't detect anything below. 963
957 (setq sexp-loop-continue-pos (point))))) 964 ;; Have we crossed a statement boundary?
958 ;; If the sexp movement took us into a 965 (setq boundary-pos
959 ;; macro then there were only some non-sexp 966 (cond
960 ;; chars after it. Skip out of the macro 967 ;; Are we at a macro beginning?
961 ;; to analyze them but not the non-sexp 968 ((and (not macro-start)
962 ;; chars that might be inside the macro. 969 c-opt-cpp-prefix
963 (c-end-of-macro) 970 (looking-at c-opt-cpp-prefix))
964 (c-crosses-statement-barrier-p 971 (save-excursion
965 (point) sexp-loop-end-pos)) 972 (c-end-of-macro)
966 973 (c-crosses-statement-barrier-p
967 ((and 974 (point) maybe-after-boundary-pos)))
968 (eq (char-after) ?{) 975 ;; Just gone back over a brace block?
969 (not (c-looking-at-inexpr-block lim nil t))) 976 ((and
970 ;; Passed a block sexp. That's a boundary 977 (eq (char-after) ?{)
971 ;; alright. 978 (not (c-looking-at-inexpr-block lim nil t)))
972 (point)) 979 (save-excursion
973 980 (c-forward-sexp) (point)))
974 ((looking-at "\\s\(") 981 ;; Just gone back over some paren block?
975 ;; Passed some other paren. Only analyze 982 ((looking-at "\\s\(")
976 ;; the non-sexp chars after it. 983 (save-excursion
977 (goto-char (1+ (c-down-list-backward 984 (goto-char (1+ (c-down-list-backward
978 before-sws-pos))) 985 before-sws-pos)))
979 ;; We're at a valid token start position 986 (c-crosses-statement-barrier-p
980 ;; (outside the `save-excursion') if 987 (point) maybe-after-boundary-pos)))
981 ;; `c-crosses-statement-barrier-p' failed. 988 ;; Just gone back over an ordinary symbol of some sort?
982 (c-crosses-statement-barrier-p 989 (t (c-crosses-statement-barrier-p
983 (point) sexp-loop-end-pos)) 990 (point) maybe-after-boundary-pos))))
984 991
985 (t 992 (when boundary-pos
986 ;; Passed a symbol sexp or line 993 (setq pptok ptok
987 ;; continuation. It doesn't matter that 994 ptok tok
988 ;; it's included in the analyzed region. 995 tok boundary-pos
989 (if (c-crosses-statement-barrier-p 996 sym 'boundary)
990 (point) sexp-loop-end-pos) 997 ;; Like a C "continue". Analyze the next sexp.
991 t 998 (throw 'loop t))))
992 ;; If it was a line continuation then we
993 ;; have to continue looping.
994 (if (looking-at "\\\\$")
995 (setq sexp-loop-continue-pos (point)))
996 nil))))
997
998 (setq pptok ptok
999 ptok tok
1000 tok boundary-pos
1001 sym 'boundary)
1002 ;; Like a C "continue". Analyze the next sexp.
1003 (throw 'loop t)))
1004
1005 sexp-loop-continue-pos) ; End of "go back a sexp" loop condition.
1006 (goto-char sexp-loop-continue-pos)
1007 (setq sexp-loop-end-pos sexp-loop-continue-pos
1008 sexp-loop-continue-pos nil))))
1009 999
1010 ;; ObjC method def? 1000 ;; ObjC method def?
1011 (when (and c-opt-method-key 1001 (when (and c-opt-method-key
1012 (setq saved (c-in-method-def-p))) 1002 (setq saved (c-in-method-def-p)))
1013 (setq pos saved 1003 (setq pos saved
1014 ignore-labels t) ; Avoid the label check on exit. 1004 ignore-labels t) ; Avoid the label check on exit.
1015 (throw 'loop nil)) 1005 (throw 'loop nil)) ; 3. ObjC method def.
1006
1007 ;; Might we have a bitfield declaration, "<type> <id> : <size>"?
1008 (if c-has-bitfields
1009 (cond
1010 ;; The : <size> and <id> fields?
1011 ((and (numberp c-maybe-labelp)
1012 (not bitfield-size-pos)
1013 (save-excursion
1014 (goto-char (or tok start))
1015 (not (looking-at c-keywords-regexp)))
1016 (not (looking-at c-keywords-regexp))
1017 (not (c-punctuation-in (point) c-maybe-labelp)))
1018 (setq bitfield-size-pos (or tok start)
1019 bitfield-id-pos (point)))
1020 ;; The <type> field?
1021 ((and bitfield-id-pos
1022 (not bitfield-type-pos))
1023 (if (and (looking-at c-symbol-key) ; Can only be an integer type. :-)
1024 (not (looking-at c-not-primitive-type-keywords-regexp))
1025 (not (c-punctuation-in (point) tok)))
1026 (setq bitfield-type-pos (point))
1027 (setq bitfield-size-pos nil
1028 bitfield-id-pos nil)))))
1016 1029
1017 ;; Handle labels. 1030 ;; Handle labels.
1018 (unless (eq ignore-labels t) 1031 (unless (eq ignore-labels t)
@@ -1044,8 +1057,10 @@ comment at the start of cc-engine.el for more info."
1044 pptok ptok 1057 pptok ptok
1045 ptok tok 1058 ptok tok
1046 tok (point) 1059 tok (point)
1047 pos tok))) ; Not nil (for the while loop). 1060 pos tok) ; always non-nil
1048 1061 ) ; end of (catch loop ....)
1062 ) ; end of sexp-at-a-time (while ....)
1063
1049 ;; If the stack isn't empty there might be errors to report. 1064 ;; If the stack isn't empty there might be errors to report.
1050 (while stack 1065 (while stack
1051 (if (and (vectorp saved-pos) (eq (length saved-pos) 3)) 1066 (if (and (vectorp saved-pos) (eq (length saved-pos) 3))
@@ -1067,6 +1082,7 @@ comment at the start of cc-engine.el for more info."
1067 (eq c-maybe-labelp t) 1082 (eq c-maybe-labelp t)
1068 (not (eq ret 'beginning)) 1083 (not (eq ret 'beginning))
1069 after-labels-pos 1084 after-labels-pos
1085 (not bitfield-type-pos) ; Bitfields take precedence over labels.
1070 (or (not label-good-pos) 1086 (or (not label-good-pos)
1071 (<= label-good-pos pos) 1087 (<= label-good-pos pos)
1072 (progn 1088 (progn
@@ -1104,6 +1120,19 @@ comment at the start of cc-engine.el for more info."
1104 (goto-char pos) 1120 (goto-char pos)
1105 ret))) 1121 ret)))
1106 1122
1123(defun c-punctuation-in (from to)
1124 "Return non-nil if there is a non-comment non-macro punctuation character
1125between FROM and TO. FROM must not be in a string or comment. The returned
1126value is the position of the first such character."
1127 (save-excursion
1128 (goto-char from)
1129 (let ((pos (point)))
1130 (while (progn (skip-chars-forward c-symbol-chars to)
1131 (c-forward-syntactic-ws to)
1132 (> (point) pos))
1133 (setq pos (point))))
1134 (and (< (point) to) (point))))
1135
1107(defun c-crosses-statement-barrier-p (from to) 1136(defun c-crosses-statement-barrier-p (from to)
1108 "Return non-nil if buffer positions FROM to TO cross one or more 1137 "Return non-nil if buffer positions FROM to TO cross one or more
1109statement or declaration boundaries. The returned value is actually 1138statement or declaration boundaries. The returned value is actually
@@ -6618,19 +6647,27 @@ comment at the start of cc-engine.el for more info."
6618 (if backup-at-type 6647 (if backup-at-type
6619 (progn 6648 (progn
6620 6649
6621 ;; CASE 3 6650
6622 (when (= (point) start) 6651 ;; CASE 3
6623 ;; Got a plain list of identifiers. If a colon follows it's 6652 (when (= (point) start)
6624 ;; a valid label. Otherwise the last one probably is the 6653 ;; Got a plain list of identifiers. If a colon follows it's
6625 ;; declared identifier and we should back up to the previous 6654 ;; a valid label, or maybe a bitfield. Otherwise the last
6626 ;; type, providing it isn't a cast. 6655 ;; one probably is the declared identifier and we should
6656 ;; back up to the previous type, providing it isn't a cast.
6627 (if (and (eq (char-after) ?:) 6657 (if (and (eq (char-after) ?:)
6628 (not (c-major-mode-is 'java-mode))) 6658 (not (c-major-mode-is 'java-mode)))
6629 ;; If we've found a specifier keyword then it's a 6659 (cond
6630 ;; declaration regardless. 6660 ;; If we've found a specifier keyword then it's a
6631 (throw 'at-decl-or-cast (eq at-decl-or-cast t)) 6661 ;; declaration regardless.
6632 (setq backup-if-not-cast t) 6662 ((eq at-decl-or-cast t)
6633 (throw 'at-decl-or-cast t))) 6663 (throw 'at-decl-or-cast t))
6664 ((and c-has-bitfields
6665 (eq at-decl-or-cast 'ids)) ; bitfield.
6666 (setq backup-if-not-cast t)
6667 (throw 'at-decl-or-cast t)))
6668
6669 (setq backup-if-not-cast t)
6670 (throw 'at-decl-or-cast t)))
6634 6671
6635 ;; CASE 4 6672 ;; CASE 4
6636 (when (and got-suffix 6673 (when (and got-suffix
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 0500d48ddbc..2277ba760ab 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1179,6 +1179,14 @@ casts and declarations are fontified. Used on level 2 and higher."
1179 (goto-char start-pos))) 1179 (goto-char start-pos)))
1180 1180
1181 ;; Now analyze the construct. 1181 ;; Now analyze the construct.
1182 ;; In QT, "more" is an irritating keyword that expands to nothing.
1183 ;; We skip over it to prevent recognition of "more slots: <symbol>"
1184 ;; as a bitfield declaration.
1185 (when (and (c-major-mode-is 'c++-mode)
1186 (looking-at
1187 (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
1188 (goto-char (match-end 1))
1189 (c-forward-syntactic-ws))
1182 (setq decl-or-cast (c-forward-decl-or-cast-1 1190 (setq decl-or-cast (c-forward-decl-or-cast-1
1183 match-pos context last-cast-end)) 1191 match-pos context last-cast-end))
1184 1192
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index d7ef278174a..35097242cb7 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -511,6 +511,12 @@ parameters \(point-min), \(point-max) and <buffer size>."
511 511
512;;; Lexer-level syntax (identifiers, tokens etc). 512;;; Lexer-level syntax (identifiers, tokens etc).
513 513
514(c-lang-defconst c-has-bitfields
515 "Whether the language has bitfield declarations."
516 t nil
517 (c c++ objc) t)
518(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields))
519
514(c-lang-defconst c-symbol-start 520(c-lang-defconst c-symbol-start
515 "Regexp that matches the start of a symbol, i.e. any identifier or 521 "Regexp that matches the start of a symbol, i.e. any identifier or
516keyword. It's unspecified how far it matches. Does not contain a \\| 522keyword. It's unspecified how far it matches. Does not contain a \\|
@@ -528,6 +534,7 @@ This is of the form that fits inside [ ] in a regexp."
528 ;; operator chars too, but they are handled with other means instead. 534 ;; operator chars too, but they are handled with other means instead.
529 t (concat c-alnum "_$") 535 t (concat c-alnum "_$")
530 objc (concat c-alnum "_$@")) 536 objc (concat c-alnum "_$@"))
537(c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars))
531 538
532(c-lang-defconst c-symbol-key 539(c-lang-defconst c-symbol-key
533 "Regexp matching identifiers and keywords (with submatch 0). Assumed 540 "Regexp matching identifiers and keywords (with submatch 0). Assumed
@@ -1927,6 +1934,21 @@ one of `c-type-list-kwds', `c-ref-list-kwds',
1927(c-lang-defvar c-not-decl-init-keywords 1934(c-lang-defvar c-not-decl-init-keywords
1928 (c-lang-const c-not-decl-init-keywords)) 1935 (c-lang-const c-not-decl-init-keywords))
1929 1936
1937(c-lang-defconst c-not-primitive-type-keywords
1938 "List of all keywords apart from primitive types (like \"int\")."
1939 t (set-difference (c-lang-const c-keywords)
1940 (c-lang-const c-primitive-type-kwds)
1941 :test 'string-equal)
1942 ;; The "more" for C++ is the QT keyword (as in "more slots:").
1943 ;; This variable is intended for use in c-beginning-of-statement-1.
1944 c++ (append (c-lang-const c-not-primitive-type-keywords) '("more")))
1945
1946(c-lang-defconst c-not-primitive-type-keywords-regexp
1947 t (c-make-keywords-re t
1948 (c-lang-const c-not-primitive-type-keywords)))
1949(c-lang-defvar c-not-primitive-type-keywords-regexp
1950 (c-lang-const c-not-primitive-type-keywords-regexp))
1951
1930(c-lang-defconst c-protection-kwds 1952(c-lang-defconst c-protection-kwds
1931 "Access protection label keywords in classes." 1953 "Access protection label keywords in classes."
1932 t nil 1954 t nil