From fc475445eea67393f6afbd748bf0fe8cc5738cd3 Mon Sep 17 00:00:00 2001 From: Alex Reed Date: Fri, 8 Sep 2023 22:42:23 -0400 Subject: [PATCH] Teach AUTOs to process escaped backslashes at the end of quoted strings (#1831) "...\\..." is a string containing a backslash: \ "...\"..." is a string containing a double-quote: " When parsing double-quoted strings, we must detect embedded escaped backslashes and double-quotes. Detecting when a string terminates with one or more of these characters is tricky. Strings terminating in "...\"" are not uncommon, and have reasonably robust support, but strings terminating in "...\\" are quite rare, and were quite broken. This patch aims to improve the detection of "...\\" (or "...\\\\", or any even number of backslashes in a row immediately preceding a double-quote string terminator. --- verilog-mode.el | 72 +++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/verilog-mode.el b/verilog-mode.el index 0e7070cc..e67985ed 100644 --- a/verilog-mode.el +++ b/verilog-mode.el @@ -3608,38 +3608,46 @@ This creates v-cmts properties where comments are in force." (save-match-data (verilog-save-buffer-state (let (pt) - (goto-char beg) - (while (< (point) end) - (cond ((looking-at "//") - (setq pt (point)) - (or (search-forward "\n" end t) - (goto-char end)) - ;; "1+": The leading // or /* itself isn't considered as - ;; being "inside" the comment, so that a (search-backward) - ;; that lands at the start of the // won't mis-indicate - ;; it's inside a comment. Also otherwise it would be - ;; hard to find a commented out /*AS*/ vs one that isn't - (put-text-property (1+ pt) (point) 'v-cmts t)) - ((looking-at "/\\*") - (setq pt (point)) - (or (search-forward "*/" end t) - ;; No error - let later code indicate it so we can - ;; use inside functions on-the-fly - ;;(error "%s: Unmatched /* */, at char %d" - ;; (verilog-point-text) (point)) - (goto-char end)) - (put-text-property (1+ pt) (point) 'v-cmts t)) - ((looking-at "\"") - (setq pt (point)) - (or (re-search-forward "[^\\]\"" end t) ; don't forward-char first, since we look for a non backslash first - ;; No error - let later code indicate it so we can - (goto-char end)) - (put-text-property (1+ pt) (point) 'v-cmts t)) - (t - (forward-char 1) - (if (re-search-forward "[/\"]" end t) - (backward-char 1) - (goto-char end)))))))))) + (goto-char beg) + (while (< (point) end) + (cond ((looking-at "//") + (setq pt (point)) + (or (search-forward "\n" end t) + (goto-char end)) + ;; "1+": The leading // or /* itself isn't considered as + ;; being "inside" the comment, so that a (search-backward) + ;; that lands at the start of the // won't mis-indicate + ;; it's inside a comment. Also otherwise it would be + ;; hard to find a commented out /*AS*/ vs one that isn't + (put-text-property (1+ pt) (point) 'v-cmts t)) + ((looking-at "/\\*") + (setq pt (point)) + (or (search-forward "*/" end t) + ;; No error - let later code indicate it so we can + ;; use inside functions on-the-fly + ;;(error "%s: Unmatched /* */, at char %d" + ;; (verilog-point-text) (point)) + (goto-char end)) + (put-text-property (1+ pt) (point) 'v-cmts t)) + ((looking-at "\"") + (setq pt (point)) + (setq pt2 nil) + ;; Move forward to the first non-escaped (backslashed) double-quote ("). That closes this string. + ;; skip: \" (an escaped double-quote) + ;; match: \\" (a backslash as the last character of a string) + (while (not pt2) + (or (re-search-forward "\\\\" end t) + (re-search-forward "[^\\]\"" end t) + (goto-char end)) + (if (looking-at "\\\\") + (forward-char 2) + (setq pt2 (point)))) + (put-text-property (1+ pt) (point) 'v-cmts t)) + (t + (forward-char 1) + (if (re-search-forward "[/\"]" end t) + (backward-char 1) + (goto-char end)))))))))) (defun verilog-scan () "Parse the buffer, marking all comments with properties.