Skip to content

Commit

Permalink
Teach AUTOs to process escaped backslashes at the end of quoted strin…
Browse files Browse the repository at this point in the history
…gs (veripool#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.
  • Loading branch information
acr4 committed Sep 9, 2023
1 parent 0823759 commit fc47544
Showing 1 changed file with 40 additions and 32 deletions.
72 changes: 40 additions & 32 deletions verilog-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit fc47544

Please sign in to comment.