aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2018-05-20 13:28:14 +0000
committerAlan Mackenzie2018-05-20 13:28:14 +0000
commitbb591f139f0602af292c772f974dcc14dabb1deb (patch)
treef0c0c0a8d534a30cc841ea82d72a17a211f1f88d
parente2f68c144f83b4634096b8180ee9d5d56329a01d (diff)
downloademacs-bb591f139f0602af292c772f974dcc14dabb1deb.tar.gz
emacs-bb591f139f0602af292c772f974dcc14dabb1deb.zip
Enhance CC Mode's fontification, etc., of unterminated strings.
String delimiters, including escaped new lines, of correctly terminated strings are left in font-lock-string-face. All others get font-lock-warning-face. The latter get syntax-table text properties on the opening string delim and the "terminating EOL". Correct two miscellaneous bugs: the handling of text properties on Java Mode's generic delimiters; the handling of c-just-done-before-change. * lisp/progmodes/cc-defs.el (c-point): New position 'eoll "end of logical line". (c-characterp): New macro. * lisp/progmodes/cc-fonts.el (c-font-lock-invalid-string): Removed. (c-basic-matchers-before): Use a simple matcher in place of the form around c-font-lock-invalid-string. * lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Add c-before-change-check-unbalanced-strings to the value for all modes except AWK Mode. Also add c-before-change-check-<>-operators to Java Mode, correcting an error in that mode's handling of generic delimiters. (c-before-font-lock-functions): Add c-after-change-re-mark-unbalanced-strings to the value for all modes except AWK Mode. (c-single-quotes-quote-strings, c-string-delims): New lang variables for future enhancements. (c-string-innards-re-alist): New lang variable. * lisp/progmodes/cc-mode.el (c-just-done-before-change): Do not set this variable when a change is the alteration of text properties. (c-basic-common-init): Set parse-sexp-lookup-properties (and the XEmacs equivalent) also for Pike Mode. (c-neutralize-CPP-line): No longer neutralize unbalanced quotes here. (c-unescaped-nls-in-string-p, c-multiline-string-start-is-being-detached) (c-pps-to-string-delim, c-before-change-check-unbalanced-strings) (c-after-change-re-mark-unbalanced-strings): New functions. (c-after-change): Fix a bug with the handling of c-just-done-before-change.
-rw-r--r--lisp/progmodes/cc-defs.el18
-rw-r--r--lisp/progmodes/cc-fonts.el35
-rw-r--r--lisp/progmodes/cc-langs.el48
-rw-r--r--lisp/progmodes/cc-mode.el225
4 files changed, 279 insertions, 47 deletions
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 7ec57e03b38..53d665477c1 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -219,6 +219,7 @@ one of the following symbols:
219 219
220`bol' -- beginning of line 220`bol' -- beginning of line
221`eol' -- end of line 221`eol' -- end of line
222`eoll' -- end of logical line (i.e. without escaped NL)
222`bod' -- beginning of defun 223`bod' -- beginning of defun
223`eod' -- end of defun 224`eod' -- end of defun
224`boi' -- beginning of indentation 225`boi' -- beginning of indentation
@@ -254,6 +255,16 @@ to it is returned. This function does not modify the point or the mark."
254 (end-of-line) 255 (end-of-line)
255 (point)))) 256 (point))))
256 257
258 ((eq position 'eoll)
259 `(save-excursion
260 ,@(if point `((goto-char ,point)))
261 (while (progn
262 (end-of-line)
263 (prog1 (eq (logand 1 (skip-chars-backward "\\\\")) 1)))
264 (beginning-of-line 2))
265 (end-of-line)
266 (point)))
267
257 ((eq position 'boi) 268 ((eq position 'boi)
258 `(save-excursion 269 `(save-excursion
259 ,@(if point `((goto-char ,point))) 270 ,@(if point `((goto-char ,point)))
@@ -453,6 +464,13 @@ to it is returned. This function does not modify the point or the mark."
453 `(int-to-char ,integer) 464 `(int-to-char ,integer)
454 integer)) 465 integer))
455 466
467(defmacro c-characterp (arg)
468 ;; Return t when ARG is a character (XEmacs) or integer (Emacs), otherwise
469 ;; return nil.
470 (if (integerp ?c)
471 `(integerp ,arg)
472 `(characterp ,arg)))
473
456(defmacro c-last-command-char () 474(defmacro c-last-command-char ()
457 ;; The last character just typed. Note that `last-command-event' exists in 475 ;; The last character just typed. Note that `last-command-event' exists in
458 ;; both Emacs and XEmacs, but with confusingly different meanings. 476 ;; both Emacs and XEmacs, but with confusingly different meanings.
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 7cac55e057f..9d2517f2524 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -682,33 +682,6 @@ stuff. Used on level 1 and higher."
682 ''c-nonbreakable-space-face))) 682 ''c-nonbreakable-space-face)))
683 )) 683 ))
684 684
685(defun c-font-lock-invalid-string ()
686 ;; Assuming the point is after the opening character of a string,
687 ;; fontify that char with `font-lock-warning-face' if the string
688 ;; decidedly isn't terminated properly.
689 ;;
690 ;; This function does hidden buffer changes.
691 (let ((start (1- (point))))
692 (save-excursion
693 (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start)
694 (if (if (eval-when-compile (integerp ?c))
695 ;; Emacs
696 (integerp c-multiline-string-start-char)
697 ;; XEmacs
698 (characterp c-multiline-string-start-char))
699 ;; There's no multiline string start char before the
700 ;; string, so newlines aren't allowed.
701 (not (eq (char-before start) c-multiline-string-start-char))
702 ;; Multiline strings are allowed anywhere if
703 ;; c-multiline-string-start-char is t.
704 (not c-multiline-string-start-char))
705 (if c-string-escaped-newlines
706 ;; There's no \ before the newline.
707 (not (eq (char-before (point)) ?\\))
708 ;; Escaped newlines aren't supported.
709 t)
710 (c-put-font-lock-face start (1+ start) 'font-lock-warning-face)))))
711
712(defun c-font-lock-invalid-single-quotes (limit) 685(defun c-font-lock-invalid-single-quotes (limit)
713 ;; This function will be called from font-lock for a region bounded by POINT 686 ;; This function will be called from font-lock for a region bounded by POINT
714 ;; and LIMIT, as though it were to identify a keyword for 687 ;; and LIMIT, as though it were to identify a keyword for
@@ -749,16 +722,12 @@ casts and declarations are fontified. Used on level 2 and higher."
749 ;; `c-recognize-<>-arglists' is set. 722 ;; `c-recognize-<>-arglists' is set.
750 723
751 t `(;; Put a warning face on the opener of unclosed strings that 724 t `(;; Put a warning face on the opener of unclosed strings that
752 ;; can't span lines. Later font 725 ;; can't span lines and on the "terminating" newlines. Later font
753 ;; lock packages have a `font-lock-syntactic-face-function' for 726 ;; lock packages have a `font-lock-syntactic-face-function' for
754 ;; this, but it doesn't give the control we want since any 727 ;; this, but it doesn't give the control we want since any
755 ;; fontification done inside the function will be 728 ;; fontification done inside the function will be
756 ;; unconditionally overridden. 729 ;; unconditionally overridden.
757 ,(c-make-font-lock-search-function 730 ("\\s|" 0 font-lock-warning-face t nil)
758 ;; Match a char before the string starter to make
759 ;; `c-skip-comments-and-strings' work correctly.
760 (concat ".\\(" c-string-limit-regexp "\\)")
761 '((c-font-lock-invalid-string)))
762 731
763 ;; Invalid single quotes. 732 ;; Invalid single quotes.
764 c-font-lock-invalid-single-quotes 733 c-font-lock-invalid-single-quotes
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 4a7c79a6dfa..53cb7f7f725 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -472,21 +472,24 @@ so that all identifiers are recognized as words.")
472(c-lang-defconst c-get-state-before-change-functions 472(c-lang-defconst c-get-state-before-change-functions
473 ;; For documentation see the following c-lang-defvar of the same name. 473 ;; For documentation see the following c-lang-defvar of the same name.
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 'c-before-change-check-unbalanced-strings
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-raw-strings
478 c-before-change-check-<>-operators 478 c-before-change-check-<>-operators
479 c-depropertize-CPP 479 c-depropertize-CPP
480 c-invalidate-macro-cache 480 c-invalidate-macro-cache
481 c-truncate-bs-cache 481 c-truncate-bs-cache
482 c-before-change-check-unbalanced-strings
482 c-parse-quotes-before-change) 483 c-parse-quotes-before-change)
483 (c objc) '(c-extend-region-for-CPP 484 (c objc) '(c-extend-region-for-CPP
484 c-depropertize-CPP 485 c-depropertize-CPP
485 c-invalidate-macro-cache 486 c-invalidate-macro-cache
486 c-truncate-bs-cache 487 c-truncate-bs-cache
488 c-before-change-check-unbalanced-strings
487 c-parse-quotes-before-change) 489 c-parse-quotes-before-change)
488 java 'c-parse-quotes-before-change 490 java '(c-parse-quotes-before-change
489 ;; 'c-before-change-check-<>-operators 491 c-before-change-check-unbalanced-strings
492 c-before-change-check-<>-operators)
490 awk 'c-awk-record-region-clear-NL) 493 awk 'c-awk-record-region-clear-NL)
491(c-lang-defvar c-get-state-before-change-functions 494(c-lang-defvar c-get-state-before-change-functions
492 (let ((fs (c-lang-const c-get-state-before-change-functions))) 495 (let ((fs (c-lang-const c-get-state-before-change-functions)))
@@ -514,14 +517,17 @@ parameters \(point-min) and \(point-max).")
514 ;; For documentation see the following c-lang-defvar of the same name. 517 ;; For documentation see the following c-lang-defvar of the same name.
515 ;; The value here may be a list of functions or a single function. 518 ;; The value here may be a list of functions or a single function.
516 t '(c-depropertize-new-text 519 t '(c-depropertize-new-text
520 c-after-change-re-mark-unbalanced-strings
517 c-change-expand-fl-region) 521 c-change-expand-fl-region)
518 (c objc) '(c-depropertize-new-text 522 (c objc) '(c-depropertize-new-text
519 c-parse-quotes-after-change 523 c-parse-quotes-after-change
524 c-after-change-re-mark-unbalanced-strings
520 c-extend-font-lock-region-for-macros 525 c-extend-font-lock-region-for-macros
521 c-neutralize-syntax-in-CPP 526 c-neutralize-syntax-in-CPP
522 c-change-expand-fl-region) 527 c-change-expand-fl-region)
523 c++ '(c-depropertize-new-text 528 c++ '(c-depropertize-new-text
524 c-parse-quotes-after-change 529 c-parse-quotes-after-change
530 c-after-change-re-mark-unbalanced-strings
525 c-extend-font-lock-region-for-macros 531 c-extend-font-lock-region-for-macros
526 c-after-change-re-mark-raw-strings 532 c-after-change-re-mark-raw-strings
527 c-neutralize-syntax-in-CPP 533 c-neutralize-syntax-in-CPP
@@ -529,6 +535,7 @@ parameters \(point-min) and \(point-max).")
529 c-change-expand-fl-region) 535 c-change-expand-fl-region)
530 java '(c-depropertize-new-text 536 java '(c-depropertize-new-text
531 c-parse-quotes-after-change 537 c-parse-quotes-after-change
538 c-after-change-re-mark-unbalanced-strings
532 c-restore-<>-properties 539 c-restore-<>-properties
533 c-change-expand-fl-region) 540 c-change-expand-fl-region)
534 awk '(c-depropertize-new-text 541 awk '(c-depropertize-new-text
@@ -611,6 +618,19 @@ EOL terminated statements."
611 (c c++ objc) t) 618 (c c++ objc) t)
612(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) 619(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields))
613 620
621(c-lang-defconst c-single-quotes-quote-strings
622 "Whether the language uses single quotes for multi-char strings."
623 t nil)
624(c-lang-defvar c-single-quotes-quote-strings
625 (c-lang-const c-single-quotes-quote-strings))
626
627(c-lang-defconst c-string-delims
628 "A list of characters which can delimit arbitrary length strings"
629 t (if (c-lang-const c-single-quotes-quote-strings)
630 '(?\" ?\')
631 '(?\")))
632(c-lang-defvar c-string-delims (c-lang-const c-string-delims))
633
614(c-lang-defconst c-has-quoted-numbers 634(c-lang-defconst c-has-quoted-numbers
615 "Whether the language has numbers quoted like 4'294'967'295." 635 "Whether the language has numbers quoted like 4'294'967'295."
616 t nil 636 t nil
@@ -856,6 +876,28 @@ literal are multiline."
856(c-lang-defvar c-multiline-string-start-char 876(c-lang-defvar c-multiline-string-start-char
857 (c-lang-const c-multiline-string-start-char)) 877 (c-lang-const c-multiline-string-start-char))
858 878
879(c-lang-defconst c-string-innards-re-alist
880 ;; An alist of regexps matching the innards of a string, the key being the
881 ;; string's delimiter.
882 ;;
883 ;; The regexps' matches extend up to, but not including, the closing string
884 ;; delimiter or an unescaped NL. An EOL is part of the string only if it is
885 ;; escaped.
886 t (mapcar (lambda (delim)
887 (cons
888 delim
889 (concat "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r"
890 (string delim)
891 "]\\)*")))
892 (and
893 (or (null (c-lang-const c-multiline-string-start-char))
894 (c-characterp (c-lang-const c-multiline-string-start-char)))
895 (if (c-lang-const c-single-quotes-quote-strings)
896 '(?\" ?\')
897 '(?\")))))
898(c-lang-defvar c-string-innards-re-alist
899 (c-lang-const c-string-innards-re-alist))
900
859(c-lang-defconst c-opt-cpp-symbol 901(c-lang-defconst c-opt-cpp-symbol
860 "The symbol which starts preprocessor constructs when in the margin." 902 "The symbol which starts preprocessor constructs when in the margin."
861 t "#" 903 t "#"
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index f42510932e5..2427191eae0 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -499,9 +499,10 @@ preferably use the `c-mode-menu' language constant directly."
499;; `basic-save-buffer' does (insert ?\n) when `require-final-newline' is 499;; `basic-save-buffer' does (insert ?\n) when `require-final-newline' is
500;; non-nil; (ii) to detect when Emacs fails to invoke 500;; non-nil; (ii) to detect when Emacs fails to invoke
501;; `before-change-functions'. This can happen when reverting a buffer - see 501;; `before-change-functions'. This can happen when reverting a buffer - see
502;; bug #24094. It seems these failures happen only in GNU Emacs; XEmacs 502;; bug #24094. It seems these failures happen only in GNU Emacs; XEmacs seems
503;; seems to maintain the strict alternation of calls to 503;; to maintain the strict alternation of calls to `before-change-functions'
504;; `before-change-functions' and `after-change-functions'. 504;; and `after-change-functions'. Note that this variable is not set when
505;; `c-before-change' is invoked by a change to text properties.
505 506
506(defun c-basic-common-init (mode default-style) 507(defun c-basic-common-init (mode default-style)
507 "Do the necessary initialization for the syntax handling routines 508 "Do the necessary initialization for the syntax handling routines
@@ -563,7 +564,7 @@ that requires a literal mode spec at compile time."
563 564
564 (when (or c-recognize-<>-arglists 565 (when (or c-recognize-<>-arglists
565 (c-major-mode-is 'awk-mode) 566 (c-major-mode-is 'awk-mode)
566 (c-major-mode-is '(java-mode c-mode c++-mode objc-mode))) 567 (c-major-mode-is '(java-mode c-mode c++-mode objc-mode pike-mode)))
567 ;; We'll use the syntax-table text property to change the syntax 568 ;; We'll use the syntax-table text property to change the syntax
568 ;; of some chars for this language, so do the necessary setup for 569 ;; of some chars for this language, so do the necessary setup for
569 ;; that. 570 ;; that.
@@ -996,9 +997,9 @@ Note that the style variables are always made local to the buffer."
996 ;; characters, ones which would interact syntactically with stuff outside 997 ;; characters, ones which would interact syntactically with stuff outside
997 ;; this region. 998 ;; this region.
998 ;; 999 ;;
999 ;; These are unmatched string delimiters, or unmatched 1000 ;; These are unmatched parens/brackets/braces. An unclosed comment is
1000 ;; parens/brackets/braces. An unclosed comment is regarded as valid, NOT 1001 ;; regarded as valid, NOT obtrusive. Unbalanced strings are handled
1001 ;; obtrusive. 1002 ;; elsewhere.
1002 (save-excursion 1003 (save-excursion
1003 (let (s) 1004 (let (s)
1004 (while 1005 (while
@@ -1008,9 +1009,11 @@ Note that the style variables are always made local to the buffer."
1008 ((< (nth 0 s) 0) ; found an unmated ),},] 1009 ((< (nth 0 s) 0) ; found an unmated ),},]
1009 (c-put-char-property (1- (point)) 'syntax-table '(1)) 1010 (c-put-char-property (1- (point)) 'syntax-table '(1))
1010 t) 1011 t)
1011 ((nth 3 s) ; In a string 1012 ;; Unbalanced strings are now handled by
1012 (c-put-char-property (nth 8 s) 'syntax-table '(1)) 1013 ;; `c-before-change-check-unbalanced-strings', etc.
1013 t) 1014 ;; ((nth 3 s) ; In a string
1015 ;; (c-put-char-property (nth 8 s) 'syntax-table '(1))
1016 ;; t)
1014 ((> (nth 0 s) 0) ; In a (,{,[ 1017 ((> (nth 0 s) 0) ; In a (,{,[
1015 (c-put-char-property (nth 1 s) 'syntax-table '(1)) 1018 (c-put-char-property (nth 1 s) 'syntax-table '(1))
1016 t) 1019 t)
@@ -1070,6 +1073,205 @@ Note that the style variables are always made local to the buffer."
1070 (forward-line)) ; no infinite loop with, e.g., "#//" 1073 (forward-line)) ; no infinite loop with, e.g., "#//"
1071 ))))) 1074 )))))
1072 1075
1076(defun c-unescaped-nls-in-string-p (&optional quote-pos)
1077 ;; Return whether unescaped newlines can be inside strings.
1078 ;;
1079 ;; QUOTE-POS, if present, is the position of the opening quote of a string.
1080 ;; Depending on the language, there might be a special character before it
1081 ;; signifying the validity of such NLs.
1082 (cond
1083 ((null c-multiline-string-start-char) nil)
1084 ((c-characterp c-multiline-string-start-char)
1085 (and quote-pos
1086 (eq (char-before quote-pos) c-multiline-string-start-char)))
1087 (t t)))
1088
1089(defun c-multiline-string-start-is-being-detached (end)
1090 ;; If (e.g.), the # character in Pike is being detached from the string
1091 ;; opener it applies to, return t. Else return nil. END is the argument
1092 ;; supplied to every before-change function.
1093 (and (memq (char-after end) c-string-delims)
1094 (c-characterp c-multiline-string-start-char)
1095 (eq (char-before end) c-multiline-string-start-char)))
1096
1097(defun c-pps-to-string-delim (end)
1098 ;; parse-partial-sexp forward to the next string quote, which is deemed to
1099 ;; be a closing quote. Return nil.
1100 ;;
1101 ;; We remove string-fence syntax-table text properties from characters we
1102 ;; pass over.
1103 (let* ((start (point))
1104 (no-st-s `(0 nil nil ?\" nil nil 0 nil ,start nil nil))
1105 (st-s `(0 nil nil t nil nil 0 nil ,start nil nil))
1106 no-st-pos st-pos
1107 )
1108 (parse-partial-sexp start end nil nil no-st-s 'syntax-table)
1109 (setq no-st-pos (point))
1110 (goto-char start)
1111 (while (progn
1112 (parse-partial-sexp (point) end nil nil st-s 'syntax-table)
1113 (c-clear-char-property (1- (point)) 'syntax-table)
1114 (setq st-pos (point))
1115 (and (< (point) end)
1116 (not (eq (char-before) ?\")))))
1117 (goto-char (min no-st-pos st-pos))
1118 nil))
1119
1120(defun c-before-change-check-unbalanced-strings (beg end)
1121 ;; If BEG or END is inside an unbalanced string, remove the syntax-table
1122 ;; text property from respectively the start or end of the string. Also
1123 ;; extend the region (c-new-BEG c-new-END) as necessary to cope with the
1124 ;; change being the insertion of an odd number of quotes.
1125 ;;
1126 ;; POINT is undefined both at entry to and exit from this function, the
1127 ;; buffer will have been widened, and match data will have been saved.
1128 ;;
1129 ;; This function is called exclusively as a before-change function via
1130 ;; `c-get-state-before-change-functions'.
1131 (c-save-buffer-state
1132 ((end-limits
1133 (progn
1134 (goto-char (if (c-multiline-string-start-is-being-detached end)
1135 (1+ end)
1136 end))
1137 (c-literal-limits)))
1138 (end-literal-type (and end-limits
1139 (c-literal-type end-limits)))
1140 (beg-limits
1141 (progn
1142 (goto-char beg)
1143 (c-literal-limits)))
1144 (beg-literal-type (and beg-limits
1145 (c-literal-type beg-limits))))
1146
1147 (when (eq end-literal-type 'string)
1148 (setq c-new-END (max c-new-END (cdr end-limits))))
1149 ;; It is possible the buffer change will include inserting a string quote.
1150 ;; This could have the effect of flipping the meaning of any following
1151 ;; quotes up until the next unescaped EOL. Also guard against the change
1152 ;; being the insertion of \ before an EOL, escaping it.
1153 (cond
1154 ((c-characterp c-multiline-string-start-char)
1155 ;; The text about to be inserted might contain a multiline string
1156 ;; opener. Set c-new-END after anything which might be affected.
1157 ;; Go to the end of the putative multiline string.
1158 (goto-char end)
1159 (c-pps-to-string-delim (point-max))
1160 (when (< (point) (point-max))
1161 (while
1162 (and
1163 (progn
1164 (while
1165 (and
1166 (c-syntactic-re-search-forward
1167 "\"\\|\\s|" (point-max) t t)
1168 (progn
1169 (c-clear-char-property (1- (point)) 'syntax-table)
1170 (not (eq (char-before) ?\")))))
1171 (eq (char-before) ?\"))
1172 (if (eq (char-before (1- (point)))
1173 c-multiline-string-start-char)
1174 (progn
1175 (c-pps-to-string-delim (point-max))
1176 (< (point) (point-max)))
1177 (c-pps-to-string-delim (c-point 'eoll))
1178 (< (point) (c-point 'eoll))))))
1179 (setq c-new-END (max (point) c-new-END)))
1180
1181 ((< c-new-END (point-max))
1182 (goto-char (1+ c-new-END)) ; might be a newline.
1183 ;; In the following regexp, the initial \n caters for a newline getting
1184 ;; joined to a preceding \ by the removal of what comes between.
1185 (re-search-forward "\n?\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r]\\)*" nil t)
1186 ;; We're at an EOLL or point-max.
1187 (setq c-new-END (min (1+ (point)) (point-max)))
1188 ;; FIXME!!! Write a clever comment here.
1189 (goto-char c-new-END)
1190 (when (equal (c-get-char-property (1- (point)) 'syntax-table) '(15))
1191 (backward-sexp)
1192 (c-clear-char-property (1- c-new-END) 'syntax-table)
1193 (c-clear-char-property (point) 'syntax-table)))
1194
1195 (t (if (memq (char-before c-new-END) c-string-delims)
1196 (c-clear-char-property (1- c-new-END) 'syntax-table))))
1197
1198 (when (eq end-literal-type 'string)
1199 (c-clear-char-property (1- (cdr end-limits)) 'syntax-table))
1200
1201 (when (eq beg-literal-type 'string)
1202 (setq c-new-BEG (min c-new-BEG (car beg-limits)))
1203 (c-clear-char-property (car beg-limits) 'syntax-table))))
1204
1205(defun c-after-change-re-mark-unbalanced-strings (beg _end _old-len)
1206 ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with
1207 ;; string fence syntax-table text properties.
1208 ;;
1209 ;; POINT is undefined both at entry to and exit from this function, the
1210 ;; buffer will have been widened, and match data will have been saved.
1211 ;;
1212 ;; This function is called exclusively as an after-change function via
1213 ;; `c-before-font-lock-functions'.
1214 (c-save-buffer-state
1215 ((cll (progn (goto-char c-new-BEG)
1216 (c-literal-limits)))
1217 (beg-literal-type (and cll (c-literal-type cll)))
1218 (beg-limits
1219 (cond
1220 ((and (eq beg-literal-type 'string)
1221 (c-unescaped-nls-in-string-p (car cll)))
1222 (cons
1223 (car cll)
1224 (progn
1225 (goto-char (1+ (car cll)))
1226 (search-forward-regexp
1227 (cdr (assq (char-after (car cll)) c-string-innards-re-alist))
1228 nil t)
1229 (min (1+ (point)) (point-max)))))
1230 ((and (null beg-literal-type)
1231 (goto-char beg)
1232 (eq (char-before) c-multiline-string-start-char)
1233 (memq (char-after) c-string-delims))
1234 (cons (point)
1235 (progn
1236 (forward-char)
1237 (search-forward-regexp
1238 (cdr (assq (char-before) c-string-innards-re-alist)) nil t)
1239 (1+ (point)))))
1240 (cll)))
1241 s)
1242 (goto-char
1243 (cond ((null beg-literal-type)
1244 c-new-BEG)
1245 ((eq beg-literal-type 'string)
1246 (car beg-limits))
1247 (t ; comment
1248 (cdr beg-limits))))
1249 (while
1250 (and
1251 (< (point) c-new-END)
1252 (progn
1253 ;; Skip over any comments before the next string.
1254 (while (progn
1255 (setq s (parse-partial-sexp (point) c-new-END nil
1256 nil s 'syntax-table))
1257 (and (not (nth 3 s))
1258 (< (point) c-new-END)
1259 (not (memq (char-before) c-string-delims)))))
1260 ;; We're at the start of a string.
1261 (memq (char-before) c-string-delims)))
1262 (if (c-unescaped-nls-in-string-p (1- (point)))
1263 (looking-at "[^\"]*")
1264 (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
1265 (cond
1266 ((memq (char-after (match-end 0)) '(?\n ?\r))
1267 (c-put-char-property (1- (point)) 'syntax-table '(15))
1268 (c-put-char-property (match-end 0) 'syntax-table '(15)))
1269 ((or (eq (match-end 0) (point-max))
1270 (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
1271 (c-put-char-property (1- (point)) 'syntax-table '(15))))
1272 (goto-char (min (1+ (match-end 0)) (point-max)))
1273 (setq s nil))))
1274
1073;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1275;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1074;; Parsing of quotes. 1276;; Parsing of quotes.
1075;; 1277;;
@@ -1418,7 +1620,8 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
1418 ;; without an intervening call to `before-change-functions' when reverting 1620 ;; without an intervening call to `before-change-functions' when reverting
1419 ;; the buffer (see bug #24094). Whatever the cause, assume that the entire 1621 ;; the buffer (see bug #24094). Whatever the cause, assume that the entire
1420 ;; buffer has changed. 1622 ;; buffer has changed.
1421 (when (not c-just-done-before-change) 1623 (when (and (not c-just-done-before-change)
1624 (not (c-called-from-text-property-change-p)))
1422 (save-restriction 1625 (save-restriction
1423 (widen) 1626 (widen)
1424 (c-before-change (point-min) (point-max)) 1627 (c-before-change (point-min) (point-max))