diff options
| author | Alan Mackenzie | 2016-06-09 12:24:27 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2016-06-09 12:24:27 +0000 |
| commit | fabb558250fca14a2684357a95225241253cdfda (patch) | |
| tree | 6d54ec0d8cdbd162404652a3c33ba58497ddcd82 | |
| parent | 47b710a976d6e343d48b5170757a7971b0ac2966 (diff) | |
| download | emacs-fabb558250fca14a2684357a95225241253cdfda.tar.gz emacs-fabb558250fca14a2684357a95225241253cdfda.zip | |
Handle C++ raw strings.
* lisp/progmodes/cc-engine.el (c-raw-string-pos, c-depropertize-raw-string)
(c-depropertize-raw-strings-in-region,
c-before-change-check-raw-strings)
(c-propertize-raw-string-opener, c-after-change-re-mark-raw-strings): New
functions.
* lisp/progmodes/cc-fonts.el (c-basic-matchers-before): Insert a clause for
c-font-lock-raw-strings.
(c-font-lock-raw-strings): New function.
* lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Insert
c-before-change-check-raw-strings into the C++ value, and c-depropertize-CPP
into the values for C, C++, and Objective C.
(c-before-font-lock-functions): Insert c-after-change-re-mark-raw-strings into
the C++ value.
* lisp/progmodes/cc-mode.el (c-old-BEG, c-old-END): New variables.
(c-depropertize-CPP): New function, extracted from
c-neutralize-syntax-in-and-mark-CPP.
(c-neutralize-syntax-in-and-mark-CPP): Remove the call to
c-clear-char-property-with-value for 'syntax-table value '(1) at the beginning
of the function.
(c-after-change): Set c-old-BEG and c-old-END to the current values of
c-new-BEG and c-new-END.
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 338 | ||||
| -rw-r--r-- | lisp/progmodes/cc-fonts.el | 41 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 4 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 39 |
4 files changed, 416 insertions, 6 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 4d6a1203c25..7c77b70de5c 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -83,8 +83,9 @@ | |||
| 83 | ;; | 83 | ;; |
| 84 | ;; 'syntax-table | 84 | ;; 'syntax-table |
| 85 | ;; Used to modify the syntax of some characters. It is used to | 85 | ;; Used to modify the syntax of some characters. It is used to |
| 86 | ;; mark the "<" and ">" of angle bracket parens with paren syntax, and | 86 | ;; mark the "<" and ">" of angle bracket parens with paren syntax, to |
| 87 | ;; to "hide" obtrusive characters in preprocessor lines. | 87 | ;; "hide" obtrusive characters in preprocessor lines, and to mark C++ |
| 88 | ;; raw strings to enable their fontification. | ||
| 88 | ;; | 89 | ;; |
| 89 | ;; This property is used on single characters and is therefore | 90 | ;; This property is used on single characters and is therefore |
| 90 | ;; always treated as front and rear nonsticky (or start and end open | 91 | ;; always treated as front and rear nonsticky (or start and end open |
| @@ -2293,7 +2294,8 @@ comment at the start of cc-engine.el for more info." | |||
| 2293 | ;; (STATE TYPE (BEG . END)) if TO is in a literal; or | 2294 | ;; (STATE TYPE (BEG . END)) if TO is in a literal; or |
| 2294 | ;; (STATE) otherwise, | 2295 | ;; (STATE) otherwise, |
| 2295 | ;; where STATE is the parsing state at TO, TYPE is the type of the literal | 2296 | ;; where STATE is the parsing state at TO, TYPE is the type of the literal |
| 2296 | ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal. | 2297 | ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal, |
| 2298 | ;; including the delimiters. | ||
| 2297 | ;; | 2299 | ;; |
| 2298 | ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character | 2300 | ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character |
| 2299 | ;; comment opener, this is recognized as being in a comment literal. | 2301 | ;; comment opener, this is recognized as being in a comment literal. |
| @@ -5657,6 +5659,9 @@ comment at the start of cc-engine.el for more info." | |||
| 5657 | ;; Set by c-common-init in cc-mode.el. | 5659 | ;; Set by c-common-init in cc-mode.el. |
| 5658 | (defvar c-new-BEG) | 5660 | (defvar c-new-BEG) |
| 5659 | (defvar c-new-END) | 5661 | (defvar c-new-END) |
| 5662 | ;; Set by c-after-change in cc-mode.el. | ||
| 5663 | (defvar c-old-BEG) | ||
| 5664 | (defvar c-old-END) | ||
| 5660 | 5665 | ||
| 5661 | (defun c-before-change-check-<>-operators (beg end) | 5666 | (defun c-before-change-check-<>-operators (beg end) |
| 5662 | ;; Unmark certain pairs of "< .... >" which are currently marked as | 5667 | ;; Unmark certain pairs of "< .... >" which are currently marked as |
| @@ -5777,6 +5782,333 @@ comment at the start of cc-engine.el for more info." | |||
| 5777 | 'c-decl-arg-start))))))) | 5782 | 'c-decl-arg-start))))))) |
| 5778 | (or (c-forward-<>-arglist nil) | 5783 | (or (c-forward-<>-arglist nil) |
| 5779 | (forward-char))))) | 5784 | (forward-char))))) |
| 5785 | |||
| 5786 | |||
| 5787 | ;; Functions to handle C++ raw strings. | ||
| 5788 | ;; | ||
| 5789 | ;; A valid C++ raw string looks like | ||
| 5790 | ;; R"<id>(<contents>)<id>" | ||
| 5791 | ;; , where <id> is an identifier from 0 to 16 characters long, not containing | ||
| 5792 | ;; spaces, control characters, double quote or left/right paren. <contents> | ||
| 5793 | ;; can include anything which isn't the terminating )<id>", including new | ||
| 5794 | ;; lines, "s, parentheses, etc. | ||
| 5795 | ;; | ||
| 5796 | ;; CC Mode handles C++ raw strings by the use of `syntax-table' text | ||
| 5797 | ;; properties as follows: | ||
| 5798 | ;; | ||
| 5799 | ;; (i) On a validly terminated raw string, no `syntax-table' text properties | ||
| 5800 | ;; are applied to the opening and closing delimiters, but any " in the | ||
| 5801 | ;; contents is given the property value "punctuation" (`(1)') to prevent it | ||
| 5802 | ;; interacting with the "s in the delimiters. | ||
| 5803 | ;; | ||
| 5804 | ;; The font locking routine `c-font-lock-c++-raw-strings' (in cc-fonts.el) | ||
| 5805 | ;; recognizes valid raw strings, and fontifies the delimiters (apart from | ||
| 5806 | ;; the parentheses) with the default face and the parentheses and the | ||
| 5807 | ;; <contents> with font-lock-string-face. | ||
| 5808 | ;; | ||
| 5809 | ;; (ii) A valid, but unterminated, raw string opening delimiter gets the | ||
| 5810 | ;; "punctuation" value (`(1)') of the `syntax-table' text property, and the | ||
| 5811 | ;; open parenthesis gets the "string fence" value (`(15)'). | ||
| 5812 | ;; | ||
| 5813 | ;; `c-font-lock-c++-raw-strings' puts c-font-lock-warning-face on the entire | ||
| 5814 | ;; unmatched opening delimiter (from the R up to the open paren), and allows | ||
| 5815 | ;; the rest of the buffer to get font-lock-string-face, caused by the | ||
| 5816 | ;; unmatched "string fence" `syntax-table' text property value. | ||
| 5817 | ;; | ||
| 5818 | ;; (iii) Inside a macro, a valid raw string is handled as in (i). An | ||
| 5819 | ;; unmatched opening delimiter is handled slightly differently. In addition | ||
| 5820 | ;; to the "punctuation" and "string fence" properties on the delimiter, | ||
| 5821 | ;; another "string fence" `syntax-table' property is applied to the last | ||
| 5822 | ;; possible character of the macro before the terminating linefeed (if there | ||
| 5823 | ;; is such a character after the "("). This "last possible" character is | ||
| 5824 | ;; never a backslash escaping the end of line. If the character preceding | ||
| 5825 | ;; this "last possible" character is itself a backslash, this preceding | ||
| 5826 | ;; character gets a "punctuation" `syntax-table' value. If the "(" is | ||
| 5827 | ;; already at the end of the macro, it gets the "punctuaion" value, and no | ||
| 5828 | ;; "string fence"s are used. | ||
| 5829 | ;; | ||
| 5830 | ;; The effect on the fontification of either of these tactics is that rest of | ||
| 5831 | ;; the macro (if any) after the "(" gets font-lock-string-face, but the rest | ||
| 5832 | ;; of the file is fontified normally. | ||
| 5833 | |||
| 5834 | |||
| 5835 | (defun c-raw-string-pos () | ||
| 5836 | ;; Get POINT's relationship to any containing raw string. | ||
| 5837 | ;; If point isn't in a raw string, return nil. | ||
| 5838 | ;; Otherwise, return the following list: | ||
| 5839 | ;; | ||
| 5840 | ;; (POS B\" B\( E\) E\") | ||
| 5841 | ;; | ||
| 5842 | ;; , where POS is the symbol `open-delim' if point is in the opening | ||
| 5843 | ;; delimiter, the symbol `close-delim' if it's in the closing delimiter, and | ||
| 5844 | ;; nil if it's in the string body. B\", B\(, E\), E\" are the positions of | ||
| 5845 | ;; the opening and closing quotes and parentheses of a correctly terminated | ||
| 5846 | ;; raw string. (N.B.: E\) and E\" are NOT on the "outside" of these | ||
| 5847 | ;; characters.) If the raw string is not terminated, E\) and E\" are set to | ||
| 5848 | ;; nil. | ||
| 5849 | ;; | ||
| 5850 | ;; Note: this routine is dependant upon the correct syntax-table text | ||
| 5851 | ;; properties being set. | ||
| 5852 | (let* ((safe (c-state-semi-safe-place (point))) | ||
| 5853 | (state (c-state-pp-to-literal safe (point))) | ||
| 5854 | open-quote-pos open-paren-pos close-paren-pos close-quote-pos id) | ||
| 5855 | (save-excursion | ||
| 5856 | (when | ||
| 5857 | (and | ||
| 5858 | (cond | ||
| 5859 | ((null (cadr state)) | ||
| 5860 | (or (eq (char-after) ?\") | ||
| 5861 | (search-backward "\"" (max (- (point) 17) (point-min)) t))) | ||
| 5862 | ((and (eq (cadr state) 'string) | ||
| 5863 | (goto-char (car (nth 2 state))) | ||
| 5864 | (or (eq (char-after) ?\") | ||
| 5865 | (search-backward "\"" (max (- (point) 17) (point-min)) t)) | ||
| 5866 | (not (bobp))))) | ||
| 5867 | (eq (char-before) ?R) | ||
| 5868 | (looking-at "\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(")) | ||
| 5869 | (setq open-quote-pos (point) | ||
| 5870 | open-paren-pos (match-end 1) | ||
| 5871 | id (match-string-no-properties 1)) | ||
| 5872 | (goto-char (1+ open-paren-pos)) | ||
| 5873 | (when (and (not (c-get-char-property open-paren-pos 'syntax-table)) | ||
| 5874 | (search-forward (concat ")" id "\"") nil t)) | ||
| 5875 | (setq close-paren-pos (match-beginning 0) | ||
| 5876 | close-quote-pos (1- (point)))))) | ||
| 5877 | (and open-quote-pos | ||
| 5878 | (list | ||
| 5879 | (cond | ||
| 5880 | ((<= (point) open-paren-pos) | ||
| 5881 | 'open-delim) | ||
| 5882 | ((and close-paren-pos | ||
| 5883 | (> (point) close-paren-pos)) | ||
| 5884 | 'close-delim) | ||
| 5885 | (t nil)) | ||
| 5886 | open-quote-pos open-paren-pos close-paren-pos close-quote-pos)))) | ||
| 5887 | |||
| 5888 | (defun c-depropertize-raw-string (id open-quote open-paren bound) | ||
| 5889 | ;; Point is immediately after a raw string opening delimiter. Remove any | ||
| 5890 | ;; `syntax-table' text properties associated with the delimiter (if it's | ||
| 5891 | ;; unmatched) or the raw string. | ||
| 5892 | ;; | ||
| 5893 | ;; ID, a string, is the delimiter's identifier. OPEN-QUOTE and OPEN-PAREN | ||
| 5894 | ;; are the buffer positions of the delimiter's components. BOUND is the | ||
| 5895 | ;; bound for searching for a matching closing delimiter; it is usually nil, | ||
| 5896 | ;; but if we're inside a macro, it's the end of the macro. | ||
| 5897 | ;; | ||
| 5898 | ;; Point is moved to after the (terminated) raw string, or left after the | ||
| 5899 | ;; unmatched opening delimiter, as the case may be. The return value is of | ||
| 5900 | ;; no significance. | ||
| 5901 | (let ((open-paren-prop (c-get-char-property open-paren 'syntax-table))) | ||
| 5902 | (cond | ||
| 5903 | ((null open-paren-prop) | ||
| 5904 | ;; A terminated raw string | ||
| 5905 | (if (search-forward (concat ")" id "\"") nil t) | ||
| 5906 | (c-clear-char-property-with-value | ||
| 5907 | (1+ open-paren) (match-beginning 0) 'syntax-table '(1)))) | ||
| 5908 | ((or (and (equal open-paren-prop '(15)) (null bound)) | ||
| 5909 | (equal open-paren-prop '(1))) | ||
| 5910 | ;; An unterminated raw string either not in a macro, or in a macro with | ||
| 5911 | ;; the open parenthesis right up against the end of macro | ||
| 5912 | (c-clear-char-property open-quote 'syntax-table) | ||
| 5913 | (c-clear-char-property open-paren 'syntax-table)) | ||
| 5914 | (t | ||
| 5915 | ;; An unterminated string in a macro, with at least one char after the | ||
| 5916 | ;; open paren | ||
| 5917 | (c-clear-char-property open-quote 'syntax-table) | ||
| 5918 | (c-clear-char-property open-paren 'syntax-table) | ||
| 5919 | (let ((after-string-fence-pos | ||
| 5920 | (save-excursion | ||
| 5921 | (goto-char (1+ open-paren)) | ||
| 5922 | (c-search-forward-char-property 'syntax-table '(15) bound)))) | ||
| 5923 | (when after-string-fence-pos | ||
| 5924 | (c-clear-char-property (1- after-string-fence-pos) 'syntax-table))) | ||
| 5925 | )))) | ||
| 5926 | |||
| 5927 | (defun c-depropertize-raw-strings-in-region (start finish) | ||
| 5928 | ;; Remove any `syntax-table' text properties associated with C++ raw strings | ||
| 5929 | ;; contained in the region (START FINISH). Point is undefined at entry and | ||
| 5930 | ;; exit, and the return value has no significance. | ||
| 5931 | (goto-char start) | ||
| 5932 | (while (and (< (point) finish) | ||
| 5933 | (re-search-forward | ||
| 5934 | (concat "\\(" ; 1 | ||
| 5935 | c-anchored-cpp-prefix ; 2 | ||
| 5936 | "\\)\\|\\(" ; 3 | ||
| 5937 | "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" ; 4 | ||
| 5938 | "\\)") | ||
| 5939 | finish t)) | ||
| 5940 | (when (save-excursion | ||
| 5941 | (goto-char (match-beginning 0)) (not (c-in-literal))) | ||
| 5942 | (if (match-beginning 4) ; the id | ||
| 5943 | ;; We've found a raw string | ||
| 5944 | (c-depropertize-raw-string | ||
| 5945 | (match-string-no-properties 4) ; id | ||
| 5946 | (1+ (match-beginning 3)) ; open quote | ||
| 5947 | (match-end 4) ; open paren | ||
| 5948 | nil) ; bound | ||
| 5949 | ;; We've found a CPP construct. Search for raw strings within it. | ||
| 5950 | (goto-char (match-beginning 2)) ; the "#" | ||
| 5951 | (c-end-of-macro) | ||
| 5952 | (let ((eom (point))) | ||
| 5953 | (goto-char (match-end 2)) ; after the "#". | ||
| 5954 | (while (and (< (point) eom) | ||
| 5955 | (c-syntactic-re-search-forward | ||
| 5956 | "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t)) | ||
| 5957 | (c-depropertize-raw-string | ||
| 5958 | (match-string-no-properties 1) ; id | ||
| 5959 | (1+ (match-beginning 0)) ; open quote | ||
| 5960 | (match-end 1) ; open paren | ||
| 5961 | eom))))))) ; bound. | ||
| 5962 | |||
| 5963 | (defun c-before-change-check-raw-strings (beg end) | ||
| 5964 | ;; This function clears `syntax-table' text properties from C++ raw strings | ||
| 5965 | ;; in the region (c-new-BEG c-new-END). BEG and END are the standard | ||
| 5966 | ;; arguments supplied to any before-change function. | ||
| 5967 | ;; | ||
| 5968 | ;; Point is undefined on both entry and exit, and the return value has no | ||
| 5969 | ;; significance. | ||
| 5970 | ;; | ||
| 5971 | ;; This function is called as a before-change function solely due to its | ||
| 5972 | ;; membership of the C++ value of `c-get-state-before-change-functions'. | ||
| 5973 | (c-save-buffer-state | ||
| 5974 | ((beg-rs (progn (goto-char beg) (c-raw-string-pos))) | ||
| 5975 | (beg-plus (if (null beg-rs) | ||
| 5976 | beg | ||
| 5977 | (max beg | ||
| 5978 | (1+ (or (nth 4 beg-rs) (nth 2 beg-rs)))))) | ||
| 5979 | (end-rs (progn (goto-char end) (c-raw-string-pos))) ; FIXME!!! | ||
| 5980 | ; Optimize this so that we don't call | ||
| 5981 | ; `c-raw-string-pos' twice when once | ||
| 5982 | ; will do. (2016-06-02). | ||
| 5983 | (end-minus (if (null end-rs) | ||
| 5984 | end | ||
| 5985 | (min end (cadr end-rs)))) | ||
| 5986 | ) | ||
| 5987 | (when beg-rs | ||
| 5988 | (setq c-new-BEG (min c-new-BEG (1- (cadr beg-rs))))) | ||
| 5989 | (c-depropertize-raw-strings-in-region c-new-BEG beg-plus) | ||
| 5990 | |||
| 5991 | (when end-rs | ||
| 5992 | (setq c-new-END (max c-new-END | ||
| 5993 | (1+ (or (nth 4 end-rs) | ||
| 5994 | (nth 2 end-rs)))))) | ||
| 5995 | (c-depropertize-raw-strings-in-region end-minus c-new-END))) | ||
| 5996 | |||
| 5997 | (defun c-propertize-raw-string-opener (id open-quote open-paren bound) | ||
| 5998 | ;; Point is immediately after a raw string opening delimiter. Apply any | ||
| 5999 | ;; pertinent `syntax-table' text properties to the delimiter and also the | ||
| 6000 | ;; raw string, should there be a valid matching closing delimiter. | ||
| 6001 | ;; | ||
| 6002 | ;; ID, a string, is the delimiter's identifier. OPEN-QUOTE and OPEN-PAREN | ||
| 6003 | ;; are the buffer positions of the delimiter's components. BOUND is the | ||
| 6004 | ;; bound for searching for a matching closing delimiter; it is usually nil, | ||
| 6005 | ;; but if we're inside a macro, it's the end of the macro. | ||
| 6006 | ;; | ||
| 6007 | ;; Point is moved to after the (terminated) raw string, or left after the | ||
| 6008 | ;; unmatched opening delimiter, as the case may be. The return value is of | ||
| 6009 | ;; no significance. | ||
| 6010 | (if (search-forward (concat ")" id "\"") bound t) | ||
| 6011 | (let ((end-string (match-beginning 0)) | ||
| 6012 | (after-quote (match-end 0))) | ||
| 6013 | (goto-char open-paren) | ||
| 6014 | (while (progn (skip-syntax-forward "^\"" end-string) | ||
| 6015 | (< (point) end-string)) | ||
| 6016 | (c-put-char-property (point) 'syntax-table '(1)) ; punctuation | ||
| 6017 | (forward-char)) | ||
| 6018 | (goto-char after-quote)) | ||
| 6019 | (c-put-char-property open-quote 'syntax-table '(1)) ; punctuation | ||
| 6020 | (c-put-char-property open-paren 'syntax-table '(15)) ; generic string | ||
| 6021 | (when bound | ||
| 6022 | ;; In a CPP construct, we try to apply a generic-string `syntax-table' | ||
| 6023 | ;; text property to the last possible character in the string, so that | ||
| 6024 | ;; only characters within the macro get "stringed out". | ||
| 6025 | (goto-char bound) | ||
| 6026 | (if (save-restriction | ||
| 6027 | (narrow-to-region (1+ open-paren) (point-max)) | ||
| 6028 | (re-search-backward | ||
| 6029 | (eval-when-compile | ||
| 6030 | ;; This regular expression matches either an escape pair (which | ||
| 6031 | ;; isn't an escaped NL) (submatch 5) or a non-escaped character | ||
| 6032 | ;; (which isn't itself a backslash) (submatch 10). The long | ||
| 6033 | ;; preambles to these (respectively submatches 2-4 and 6-9) | ||
| 6034 | ;; ensure that we have the correct parity for sequences of | ||
| 6035 | ;; backslashes, etc.. | ||
| 6036 | (concat "\\(" ; 1 | ||
| 6037 | "\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)*" ; 2-4 | ||
| 6038 | "\\(\\\\.\\)" ; 5 | ||
| 6039 | "\\|" | ||
| 6040 | "\\(\\`\\|[^\\]\\|\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)+\\)" ; 6-9 | ||
| 6041 | "\\([^\\]\\)" ; 10 | ||
| 6042 | "\\)" | ||
| 6043 | "\\(\\\\\n\\)*\\=")) ; 11 | ||
| 6044 | (1+ open-paren) t)) | ||
| 6045 | (if (match-beginning 10) | ||
| 6046 | (c-put-char-property (match-beginning 10) 'syntax-table '(15)) | ||
| 6047 | (c-put-char-property (match-beginning 5) 'syntax-table '(1)) | ||
| 6048 | (c-put-char-property (1+ (match-beginning 5)) 'syntax-table '(15))) | ||
| 6049 | (c-put-char-property open-paren 'syntax-table '(1))) | ||
| 6050 | (goto-char bound)))) | ||
| 6051 | |||
| 6052 | (defun c-after-change-re-mark-raw-strings (beg end old-len) | ||
| 6053 | ;; This function applies `syntax-table' text properties to C++ raw strings | ||
| 6054 | ;; beginning in the region (c-new-BEG c-new-END). BEG, END, and OLD-LEN are | ||
| 6055 | ;; the standard arguments supplied to any after-change function. | ||
| 6056 | ;; | ||
| 6057 | ;; Point is undefined on both entry and exit, and the return value has no | ||
| 6058 | ;; significance. | ||
| 6059 | ;; | ||
| 6060 | ;; This function is called as an after-change function solely due to its | ||
| 6061 | ;; membership of the C++ value of `c-before-font-lock-functions'. | ||
| 6062 | (c-save-buffer-state () | ||
| 6063 | ;; If the region (c-new-BEG c-new-END) has expanded, remove | ||
| 6064 | ;; `syntax-table' text-properties from the new piece(s). | ||
| 6065 | (when (< c-new-BEG c-old-BEG) | ||
| 6066 | (let ((beg-rs (progn (goto-char c-old-BEG) (c-raw-string-pos)))) | ||
| 6067 | (c-depropertize-raw-strings-in-region | ||
| 6068 | c-new-BEG | ||
| 6069 | (if beg-rs | ||
| 6070 | (1+ (or (nth 4 beg-rs) (nth 2 beg-rs))) | ||
| 6071 | c-old-BEG)))) | ||
| 6072 | (when (> c-new-END c-old-END) | ||
| 6073 | (let ((end-rs (progn (goto-char c-old-END) (c-raw-string-pos)))) | ||
| 6074 | (c-depropertize-raw-strings-in-region | ||
| 6075 | (if end-rs | ||
| 6076 | (cadr end-rs) | ||
| 6077 | c-old-END) | ||
| 6078 | c-new-END))) | ||
| 6079 | |||
| 6080 | (goto-char c-new-BEG) | ||
| 6081 | (while (and (< (point) c-new-END) | ||
| 6082 | (re-search-forward | ||
| 6083 | (concat "\\(" ; 1 | ||
| 6084 | c-anchored-cpp-prefix ; 2 | ||
| 6085 | "\\)\\|\\(" ; 3 | ||
| 6086 | "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" ; 4 | ||
| 6087 | "\\)") | ||
| 6088 | c-new-END t)) | ||
| 6089 | (when (save-excursion | ||
| 6090 | (goto-char (match-beginning 0)) (not (c-in-literal))) | ||
| 6091 | (if (match-beginning 4) ; the id | ||
| 6092 | ;; We've found a raw string. | ||
| 6093 | (c-propertize-raw-string-opener | ||
| 6094 | (match-string-no-properties 4) ; id | ||
| 6095 | (1+ (match-beginning 3)) ; open quote | ||
| 6096 | (match-end 4) ; open paren | ||
| 6097 | nil) ; bound | ||
| 6098 | ;; We've found a CPP construct. Search for raw strings within it. | ||
| 6099 | (goto-char (match-beginning 2)) ; the "#" | ||
| 6100 | (c-end-of-macro) | ||
| 6101 | (let ((eom (point))) | ||
| 6102 | (goto-char (match-end 2)) ; after the "#". | ||
| 6103 | (while (and (< (point) eom) | ||
| 6104 | (c-syntactic-re-search-forward | ||
| 6105 | "R\"\\([^ ()\\\n\r\t]\\{,16\\}\\)(" eom t)) | ||
| 6106 | (c-propertize-raw-string-opener | ||
| 6107 | (match-string-no-properties 1) ; id | ||
| 6108 | (1+ (match-beginning 0)) ; open quote | ||
| 6109 | (match-end 1) ; open paren | ||
| 6110 | eom)))))))) ; bound | ||
| 6111 | |||
| 5780 | 6112 | ||
| 5781 | ;; Handling of small scale constructs like types and names. | 6113 | ;; Handling of small scale constructs like types and names. |
| 5782 | 6114 | ||
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 4e83d6df620..f3f369f5f8c 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el | |||
| @@ -723,6 +723,10 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 723 | (concat ".\\(" c-string-limit-regexp "\\)") | 723 | (concat ".\\(" c-string-limit-regexp "\\)") |
| 724 | '((c-font-lock-invalid-string))) | 724 | '((c-font-lock-invalid-string))) |
| 725 | 725 | ||
| 726 | ;; Fontify C++ raw strings. | ||
| 727 | ,@(when (c-major-mode-is 'c++-mode) | ||
| 728 | '(c-font-lock-raw-strings)) | ||
| 729 | |||
| 726 | ;; Fontify keyword constants. | 730 | ;; Fontify keyword constants. |
| 727 | ,@(when (c-lang-const c-constant-kwds) | 731 | ,@(when (c-lang-const c-constant-kwds) |
| 728 | (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) | 732 | (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) |
| @@ -1571,6 +1575,43 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1571 | (c-forward-syntactic-ws) | 1575 | (c-forward-syntactic-ws) |
| 1572 | (c-font-lock-declarators limit t in-typedef))))))) | 1576 | (c-font-lock-declarators limit t in-typedef))))))) |
| 1573 | 1577 | ||
| 1578 | (defun c-font-lock-raw-strings (limit) | ||
| 1579 | ;; Fontify C++ raw strings. | ||
| 1580 | ;; | ||
| 1581 | ;; This function will be called from font-lock for a region bounded by POINT | ||
| 1582 | ;; and LIMIT, as though it were to identify a keyword for | ||
| 1583 | ;; font-lock-keyword-face. It always returns NIL to inhibit this and | ||
| 1584 | ;; prevent a repeat invocation. See elisp/lispref page "Search-based | ||
| 1585 | ;; Fontification". | ||
| 1586 | (while (search-forward-regexp | ||
| 1587 | "R\\(\"\\)\\([^ ()\\\n\r\t]\\{,16\\}\\)(" limit t) | ||
| 1588 | (when | ||
| 1589 | (or (and (eobp) | ||
| 1590 | (eq (c-get-char-property (1- (point)) 'face) | ||
| 1591 | 'font-lock-warning-face)) | ||
| 1592 | (eq (c-get-char-property (point) 'face) 'font-lock-string-face) | ||
| 1593 | (and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1)) | ||
| 1594 | (equal (c-get-char-property (match-beginning 1) 'syntax-table) | ||
| 1595 | '(1)))) | ||
| 1596 | (let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table))) | ||
| 1597 | (if paren-prop | ||
| 1598 | (progn | ||
| 1599 | (c-put-font-lock-face (match-beginning 0) (match-end 0) | ||
| 1600 | 'font-lock-warning-face) | ||
| 1601 | (when | ||
| 1602 | (and | ||
| 1603 | (equal paren-prop '(15)) | ||
| 1604 | (not (c-search-forward-char-property 'syntax-table '(15) limit))) | ||
| 1605 | (goto-char limit))) | ||
| 1606 | (c-put-font-lock-face (match-beginning 1) (match-end 2) 'default) | ||
| 1607 | (when (search-forward-regexp | ||
| 1608 | (concat ")\\(" (regexp-quote (match-string-no-properties 2)) | ||
| 1609 | "\\)\"") | ||
| 1610 | limit t) | ||
| 1611 | (c-put-font-lock-face (match-beginning 1) (point) | ||
| 1612 | 'default)))))) | ||
| 1613 | nil) | ||
| 1614 | |||
| 1574 | (c-lang-defconst c-simple-decl-matchers | 1615 | (c-lang-defconst c-simple-decl-matchers |
| 1575 | "Simple font lock matchers for types and declarations. These are used | 1616 | "Simple font lock matchers for types and declarations. These are used |
| 1576 | on level 2 only and so aren't combined with `c-complex-decl-matchers'." | 1617 | on level 2 only and so aren't combined with `c-complex-decl-matchers'." |
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 18f1cc4374a..ba05e81aba3 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -474,9 +474,12 @@ so that all identifiers are recognized as words.") | |||
| 474 | ;; The value here may be a list of functions or a single function. | 474 | ;; The value here may be a list of functions or a single function. |
| 475 | t nil | 475 | t nil |
| 476 | c++ '(c-extend-region-for-CPP | 476 | c++ '(c-extend-region-for-CPP |
| 477 | c-before-change-check-raw-strings | ||
| 477 | c-before-change-check-<>-operators | 478 | c-before-change-check-<>-operators |
| 479 | c-depropertize-CPP | ||
| 478 | c-invalidate-macro-cache) | 480 | c-invalidate-macro-cache) |
| 479 | (c objc) '(c-extend-region-for-CPP | 481 | (c objc) '(c-extend-region-for-CPP |
| 482 | c-depropertize-CPP | ||
| 480 | c-invalidate-macro-cache) | 483 | c-invalidate-macro-cache) |
| 481 | ;; java 'c-before-change-check-<>-operators | 484 | ;; java 'c-before-change-check-<>-operators |
| 482 | awk 'c-awk-record-region-clear-NL) | 485 | awk 'c-awk-record-region-clear-NL) |
| @@ -510,6 +513,7 @@ parameters \(point-min) and \(point-max).") | |||
| 510 | c-neutralize-syntax-in-and-mark-CPP | 513 | c-neutralize-syntax-in-and-mark-CPP |
| 511 | c-change-expand-fl-region) | 514 | c-change-expand-fl-region) |
| 512 | c++ '(c-extend-font-lock-region-for-macros | 515 | c++ '(c-extend-font-lock-region-for-macros |
| 516 | c-after-change-re-mark-raw-strings | ||
| 513 | c-neutralize-syntax-in-and-mark-CPP | 517 | c-neutralize-syntax-in-and-mark-CPP |
| 514 | c-restore-<>-properties | 518 | c-restore-<>-properties |
| 515 | c-change-expand-fl-region) | 519 | c-change-expand-fl-region) |
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 9ab04808af6..6f326133671 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -665,6 +665,14 @@ that requires a literal mode spec at compile time." | |||
| 665 | (make-variable-buffer-local 'c-new-BEG) | 665 | (make-variable-buffer-local 'c-new-BEG) |
| 666 | (defvar c-new-END 0) | 666 | (defvar c-new-END 0) |
| 667 | (make-variable-buffer-local 'c-new-END) | 667 | (make-variable-buffer-local 'c-new-END) |
| 668 | ;; The following two variables record the values of `c-new-BEG' and | ||
| 669 | ;; `c-new-END' just after `c-new-END' has been adjusted for the length of text | ||
| 670 | ;; inserted or removed. They may be read by any after-change function (but | ||
| 671 | ;; should not be altered by one). | ||
| 672 | (defvar c-old-BEG 0) | ||
| 673 | (make-variable-buffer-local 'c-old-BEG) | ||
| 674 | (defvar c-old-END 0) | ||
| 675 | (make-variable-buffer-local 'c-old-END) | ||
| 668 | 676 | ||
| 669 | (defun c-common-init (&optional mode) | 677 | (defun c-common-init (&optional mode) |
| 670 | "Common initialization for all CC Mode modes. | 678 | "Common initialization for all CC Mode modes. |
| @@ -877,6 +885,31 @@ Note that the style variables are always made local to the buffer." | |||
| 877 | (memq (cadr (backtrace-frame 3)) | 885 | (memq (cadr (backtrace-frame 3)) |
| 878 | '(put-text-property remove-list-of-text-properties))) | 886 | '(put-text-property remove-list-of-text-properties))) |
| 879 | 887 | ||
| 888 | (defun c-depropertize-CPP (beg end) | ||
| 889 | ;; Remove the punctuation syntax-table text property from the CPP parts of | ||
| 890 | ;; (c-new-BEG c-new-END). | ||
| 891 | ;; | ||
| 892 | ;; This function is in the C/C++/ObjC values of | ||
| 893 | ;; `c-get-state-before-change-functions' and is called exclusively as a | ||
| 894 | ;; before change function. | ||
| 895 | (goto-char c-new-BEG) | ||
| 896 | (while (and (< (point) beg) | ||
| 897 | (search-forward-regexp c-anchored-cpp-prefix beg t)) | ||
| 898 | (goto-char (match-beginning 1)) | ||
| 899 | (let ((m-beg (point))) | ||
| 900 | (c-end-of-macro) | ||
| 901 | (c-clear-char-property-with-value | ||
| 902 | m-beg (min (point) beg) 'syntax-table '(1)))) | ||
| 903 | |||
| 904 | (goto-char end) | ||
| 905 | (while (and (< (point) c-new-END) | ||
| 906 | (search-forward-regexp c-anchored-cpp-prefix c-new-END t)) | ||
| 907 | (goto-char (match-beginning 1)) | ||
| 908 | (let ((m-beg (point))) | ||
| 909 | (c-end-of-macro) | ||
| 910 | (c-clear-char-property-with-value | ||
| 911 | m-beg (min (point) c-new-END) 'syntax-table '(1))))) | ||
| 912 | |||
| 880 | (defun c-extend-region-for-CPP (beg end) | 913 | (defun c-extend-region-for-CPP (beg end) |
| 881 | ;; Adjust `c-new-BEG', `c-new-END' respectively to the beginning and end of | 914 | ;; Adjust `c-new-BEG', `c-new-END' respectively to the beginning and end of |
| 882 | ;; any preprocessor construct they may be in. | 915 | ;; any preprocessor construct they may be in. |
| @@ -967,9 +1000,9 @@ Note that the style variables are always made local to the buffer." | |||
| 967 | ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! | 1000 | ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! |
| 968 | ;; | 1001 | ;; |
| 969 | ;; This function might make hidden buffer changes. | 1002 | ;; This function might make hidden buffer changes. |
| 970 | (c-save-buffer-state (limits ) | 1003 | (c-save-buffer-state (limits) |
| 971 | ;; Clear 'syntax-table properties "punctuation": | 1004 | ;; Clear 'syntax-table properties "punctuation": |
| 972 | (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) | 1005 | ;; (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) |
| 973 | 1006 | ||
| 974 | ;; CPP "comment" markers: | 1007 | ;; CPP "comment" markers: |
| 975 | (if (eval-when-compile (memq 'category-properties c-emacs-features));Emacs. | 1008 | (if (eval-when-compile (memq 'category-properties c-emacs-features));Emacs. |
| @@ -1125,8 +1158,8 @@ Note that the style variables are always made local to the buffer." | |||
| 1125 | 1158 | ||
| 1126 | ;; (c-new-BEG c-new-END) will be the region to fontify. It may become | 1159 | ;; (c-new-BEG c-new-END) will be the region to fontify. It may become |
| 1127 | ;; larger than (beg end). | 1160 | ;; larger than (beg end). |
| 1128 | ;; (setq c-new-BEG beg c-new-END end) | ||
| 1129 | (setq c-new-END (- (+ c-new-END (- end beg)) old-len)) | 1161 | (setq c-new-END (- (+ c-new-END (- end beg)) old-len)) |
| 1162 | (setq c-old-BEG c-new-BEG c-old-END c-new-END) | ||
| 1130 | 1163 | ||
| 1131 | (unless (c-called-from-text-property-change-p) | 1164 | (unless (c-called-from-text-property-change-p) |
| 1132 | (setq c-just-done-before-change nil) | 1165 | (setq c-just-done-before-change nil) |