Skip to content

Commit c601148

Browse files
author
Alan Mackenzie
committed
CC Mode (some languages): handle string lines ending in \\
In C, C++, Objective C, and Pike modes, regard \\ in a string at EOL as a backslash followed by an escaped newline. In the other languages, this remains regarded as an escaped backslash followed by an invalid string terminator. * lisp/progmodes/cc-defs.el (c-is-escaped, c-will-be-escaped): Amend to observe the changed notion of escaped newlines. * lisp/progmodes/cc-langs.el (c-string-escaped-newlines): Unused, removed. (c-escaped-newline-takes-precedence): New lang const and var. (c-string-innards-re-alist): Amend, using the above new lang var.
1 parent 5513f72 commit c601148

File tree

2 files changed

+39
-19
lines changed

2 files changed

+39
-19
lines changed

lisp/progmodes/cc-defs.el

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,25 +425,38 @@ to it is returned. This function does not modify the point or the mark."
425425
(defvar lookup-syntax-properties) ;XEmacs.
426426

427427
(defmacro c-is-escaped (pos)
428-
;; Are there an odd number of backslashes before POS?
428+
;; Is the character following POS escaped?
429429
(declare (debug t))
430430
`(save-excursion
431431
(goto-char ,pos)
432-
(not (zerop (logand (skip-chars-backward "\\\\") 1)))))
432+
(if (and c-escaped-newline-takes-precedence
433+
(memq (char-after) '(?\n ?\r)))
434+
(eq (char-before) ?\\)
435+
(not (zerop (logand (skip-chars-backward "\\\\") 1))))))
433436

434437
(defmacro c-will-be-escaped (pos beg end)
435438
;; Will the character after POS be escaped after the removal of (BEG END)?
436439
;; It is assumed that (>= POS END).
437440
(declare (debug t))
438441
`(save-excursion
439442
(let ((-end- ,end)
443+
(-pos- ,pos)
440444
count)
441-
(goto-char ,pos)
442-
(setq count (skip-chars-backward "\\\\" -end-))
443-
(when (eq (point) -end-)
444-
(goto-char ,beg)
445-
(setq count (+ count (skip-chars-backward "\\\\"))))
446-
(not (zerop (logand count 1))))))
445+
(if (and c-escaped-newline-takes-precedence
446+
(memq (char-after -pos-) '(?\n ?\r)))
447+
(eq (char-before (if (eq -pos- -end-)
448+
,beg
449+
-pos-))
450+
?\\)
451+
(goto-char -pos-)
452+
(setq count
453+
(if (> -pos- -end-)
454+
(skip-chars-backward "\\\\" -end-)
455+
0))
456+
(when (eq (point) -end-)
457+
(goto-char ,beg)
458+
(setq count (+ count (skip-chars-backward "\\\\"))))
459+
(not (zerop (logand count 1)))))))
447460

448461
(defmacro c-will-be-unescaped (beg)
449462
;; Would the character after BEG be unescaped?

lisp/progmodes/cc-langs.el

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,14 +1071,6 @@ Currently (2022-09) just C++ Mode uses this."
10711071
;; matched.
10721072
t nil)
10731073

1074-
(c-lang-defconst c-string-escaped-newlines
1075-
"Set if the language support backslash escaped newlines inside string
1076-
literals."
1077-
t nil
1078-
(c c++ objc pike) t)
1079-
(c-lang-defvar c-string-escaped-newlines
1080-
(c-lang-const c-string-escaped-newlines))
1081-
10821074
(c-lang-defconst c-multiline-string-start-char
10831075
"Set if the language supports multiline string literals without escaped
10841076
newlines. If t, all string literals are multiline. If a character,
@@ -1095,6 +1087,18 @@ further directions."
10951087
(c-lang-defvar c-multiline-string-start-char
10961088
(c-lang-const c-multiline-string-start-char))
10971089

1090+
(c-lang-defconst c-escaped-newline-takes-precedence
1091+
"Set if the language resolves escaped newlines first.
1092+
This makes a difference in a string like \"...\\\\\n\". When
1093+
this variable is nil, the first backslash escapes the second,
1094+
leaving an unterminated string. When it's non-nil, the string is
1095+
continued onto the next line, and the first backslash escapes
1096+
whatever begins that next line."
1097+
t nil
1098+
(c c++ objc pike) t)
1099+
(c-lang-defvar c-escaped-newline-takes-precedence
1100+
(c-lang-const c-escaped-newline-takes-precedence))
1101+
10981102
(c-lang-defconst c-string-innards-re-alist
10991103
;; An alist of regexps matching the innards of a string, the key being the
11001104
;; string's delimiter.
@@ -1105,9 +1109,12 @@ further directions."
11051109
t (mapcar (lambda (delim)
11061110
(cons
11071111
delim
1108-
(concat "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r"
1109-
(string delim)
1110-
"]\\)*")))
1112+
(concat
1113+
(if (c-lang-const c-escaped-newline-takes-precedence)
1114+
"\\(\\\\\\(\\\\?\n\\|.\\)\\|[^\\\n\r"
1115+
"\\(\\\\\\(\n\\|.\\)\\|[^\\\n\r")
1116+
(string delim)
1117+
"]\\)*")))
11111118
(and
11121119
(or (null (c-lang-const c-multiline-string-start-char))
11131120
(c-characterp (c-lang-const c-multiline-string-start-char)))

0 commit comments

Comments
 (0)