From b619777dd67e271d639c6fb1d031650af8fd79e6 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sat, 30 Mar 2019 13:19:47 +0000 Subject: [PATCH] Allow a CC Mode derived mode to have strings delimited by single quotes. Also fix the bug where the delimiters of '\033', etc. got the error face. * lisp/progmodes/cc-langs.el (c-single-quotes-quote-strings): Enhance the docr string. (c-string-delims): Change doc string to doc comment. * listp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings): In searches and comparisons, take account of the string delimiters possibly being '. Fix argument in call of c-before-change-check-unbalanced-strings. (c-parse-quotes-before-change, c-parse-quotes-after-change): Bind case-fold-search to nil. Analyze escape constructs inside character constants more accurately, in particular accepting as valid more than one character after /[0-7], /x, /u, and /U. Amend calculations to account for this extra length. --- lisp/progmodes/cc-langs.el | 12 +++++++-- lisp/progmodes/cc-mode.el | 52 ++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 22b7b602f1e..2dff5cf83c8 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -599,13 +599,21 @@ EOL terminated statements." (c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) (c-lang-defconst c-single-quotes-quote-strings - "Whether the language uses single quotes for multi-char strings." + "Whether the language uses single quotes for multi-char strings. + +Note that to set up a language to use this, additionally: +\(i) the syntax of \"'\" must be \"string quote\" (7); +\(ii) the language's value of `c-has-quoted-numbers' must be nil; +\(iii) the language's value of `c-get-state-before-change-functions' may not + contain `c-parse-quotes-before-change'; +\(iv) the language's value of `c-before-font-lock-functions' may not contain + `c-parse-quotes-after-change'." t nil) (c-lang-defvar c-single-quotes-quote-strings (c-lang-const c-single-quotes-quote-strings)) (c-lang-defconst c-string-delims - "A list of characters which can delimit arbitrary length strings" +;; A list of characters which can delimit arbitrary length strings. t (if (c-lang-const c-single-quotes-quote-strings) '(?\" ?\') '(?\"))) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index b7812fa8f3d..49268c4482e 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1212,12 +1212,15 @@ Note that the style variables are always made local to the buffer." (while (and (c-syntactic-re-search-forward - "\"\\|\\s|" (point-max) t t) + (if c-single-quotes-quote-strings + "[\"']\\|\\s|" + "\"\\|\\s|") + (point-max) t t) (progn (c-clear-char-property (1- (point)) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (1- (point))) - (not (eq (char-before) ?\"))))) - (eq (char-before) ?\")) + (not (memq (char-before) c-string-delims))))) + (memq (char-before) c-string-delims)) (progn (c-pps-to-string-delim (point-max)) (< (point) (point-max)))))) @@ -1229,7 +1232,9 @@ Note that the style variables are always made local to the buffer." (eq beg-literal-type 'string)))) ;; Deal with deletion of backslashes before "s. (goto-char end) - (if (and (looking-at "\\\\*\"") + (if (and (looking-at (if c-single-quotes-quote-strings + "\\\\*[\"']" + "\\\\*\"")) (eq (logand (skip-chars-backward "\\\\" beg) 1) 1)) (setq c-bc-changed-stringiness (not c-bc-changed-stringiness))) (if (eq beg-literal-type 'string) @@ -1250,12 +1255,12 @@ Note that the style variables are always made local to the buffer." (forward-char) (backward-sexp) (c-clear-char-property eoll-1 'syntax-table) - (c-truncate-semi-nonlit-pos-cache eoll-1) - (c-clear-char-property (point) 'syntax-table)) + (c-clear-char-property (point) 'syntax-table) + (c-truncate-semi-nonlit-pos-cache (point))) ;; Opening " at EOB. (c-clear-char-property (1- (point)) 'syntax-table)) (when (and (c-search-backward-char-property 'syntax-table '(15) c-new-BEG) - (eq (char-after) ?\")) ; Ignore an unterminated raw string's (. + (memq (char-after) c-string-delims)) ; Ignore an unterminated raw string's (. ;; Opening " on last line of text (without EOL). (c-clear-char-property (point) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (point))))) @@ -1264,7 +1269,7 @@ Note that the style variables are always made local to the buffer." (when (and (c-search-backward-char-property 'syntax-table '(15) c-new-BEG) - (eq (char-after) ?\")) + (memq (char-after) c-string-delims)) (c-clear-char-property (point) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (point))))) @@ -1276,7 +1281,7 @@ Note that the style variables are always made local to the buffer." (c-truncate-semi-nonlit-pos-cache (1- (cdr end-limits)))) (when (and (eq beg-literal-type 'string) - (eq (char-after (car beg-limits)) ?\")) + (memq (char-after (car beg-limits)) c-string-delims)) (setq c-new-BEG (min c-new-BEG (car beg-limits))) (c-clear-char-property (car beg-limits) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (car beg-limits)))))) @@ -1492,7 +1497,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ;; ;; This function is called exclusively as a before-change function via the ;; variable `c-get-state-before-change-functions'. - (c-save-buffer-state () + (c-save-buffer-state (case-fold-search) (goto-char c-new-BEG) ;; We need to scan for 's from the BO (logical) line. (beginning-of-line) @@ -1508,13 +1513,13 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ((c-quoted-number-head-before-point) (if (>= (point) c-new-BEG) (setq c-new-BEG (match-beginning 0)))) - ((looking-at "\\([^'\\]\\|\\\\.\\)'") + ((looking-at + "\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][0-9a-fA-F]+\\|.\\)\\)'") (goto-char (match-end 0)) (if (> (match-end 0) c-new-BEG) (setq c-new-BEG (1- (match-beginning 0))))) - ((or (>= (point) (1- c-new-BEG)) - (and (eq (point) (- c-new-BEG 2)) - (eq (char-after) ?\\))) + ((save-excursion + (not (search-forward "'" c-new-BEG t))) (setq c-new-BEG (1- (point)))) (t nil))) @@ -1534,19 +1539,26 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (goto-char (match-end 0)) (if (> (match-end 0) c-new-END) (setq c-new-END (match-end 0)))) - ((looking-at "\\([^'\\]\\|\\\\.\\)'") + ((looking-at + "\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][0-9a-fA-F]+\\|.\\)\\)'") (goto-char (match-end 0)) (if (> (match-end 0) c-new-END) (setq c-new-END (match-end 0)))) + ((equal (c-get-char-property (1- (point)) 'syntax-table) '(1)) + (when (c-search-forward-char-property-with-value-on-char + 'syntax-table '(1) ?\' (c-point 'eoll)) + (setq c-new-END (max (point) c-new-END)))) (t nil))) ;; Having reached c-new-END, handle any 's after it whose context may be - ;; changed by the current buffer change. + ;; changed by the current buffer change. The idea is to catch + ;; monstrosities like ',',',',',' changing "polarity". (goto-char c-new-END) (cond ((c-quoted-number-tail-after-point) (setq c-new-END (match-end 0))) ((looking-at - "\\(\\\\.\\|.\\)?\\('\\([^'\\]\\|\\\\.\\)\\)*'") + "\\(\\\\\\([0-7]\\{1,3\\}\\|[xuU][0-9a-fA-F]+\\|.\\)\\|.\\)?\ +\\('\\([^'\\]\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][0-9a-fA-F]+\\|.\\)\\)\\)*'") (setq c-new-END (match-end 0)))) ;; Remove the '(1) syntax-table property from any "'"s within (c-new-BEG @@ -1575,7 +1587,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ;; ;; This function is called exclusively as an after-change function via the ;; variable `c-before-font-lock-functions'. - (c-save-buffer-state (num-beg num-end) + (c-save-buffer-state (num-beg num-end case-fold-search) ;; Apply the needed syntax-table and c-digit-separator text properties to ;; quotes. (save-restriction @@ -1597,7 +1609,9 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (c-put-char-properties-on-char num-beg num-end 'c-digit-separator t ?') (goto-char num-end)) - ((looking-at "\\([^\\']\\|\\\\.\\)'") ; balanced quoted expression. + ((looking-at + "\\([^\\']\\|\\\\\\([0-7]\\{1,3\\}\\|[xuU][0-9a-fA-F]+\\|.\\)\ +\\)'") ; balanced quoted expression. (goto-char (match-end 0))) (t (c-invalidate-state-cache (1- (point))) -- 2.39.5