diff options
| author | Alan Mackenzie | 2018-05-20 13:28:14 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2018-05-20 13:28:14 +0000 |
| commit | bb591f139f0602af292c772f974dcc14dabb1deb (patch) | |
| tree | f0c0c0a8d534a30cc841ea82d72a17a211f1f88d | |
| parent | e2f68c144f83b4634096b8180ee9d5d56329a01d (diff) | |
| download | emacs-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.el | 18 | ||||
| -rw-r--r-- | lisp/progmodes/cc-fonts.el | 35 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 48 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 225 |
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)) |