-
Notifications
You must be signed in to change notification settings - Fork 0
/
flymake-verilator.el
118 lines (109 loc) · 4.88 KB
/
flymake-verilator.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
;;; flymake-verilator --- Flymake for Verilog -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'flymake)
(defvar verilog--flymake-proc nil
"A flymake verilog process.")
(defvar verilog-flymake-command '("verilator" "--lint-only" "-Wall")
"Command for verilog's flymake.")
(defvar verilog--flymake-output-buffer " *stderr of verilog-flymake*"
"Buffer for verilog's flymake output.")
(defun verilog-flymake-done (report-fn
source-buffer
output-buffer)
(with-current-buffer source-buffer
(save-excursion
(save-restriction
(with-current-buffer output-buffer
(goto-char (point-min))
(let ((diags))
(while (search-forward-regexp
"^\\(%.*\\): .*:\\([0-9]+\\):\\([0-9]+\\): \\(.*\\)$"
nil t)
(let* ((msg (match-string 4))
(level-msg (match-string 1))
(line (string-to-number (match-string 2)))
(locate-string)
(cal)
(beg)
(end)
(level))
(setq level (cond
((string-match-p "%Error" level-msg) ':error)
((string-match-p "%Warning" level-msg) ':warning)
(t :note)))
(search-forward-regexp "\\(\\^~*\\)" nil t)
(setq cal (length (match-string 1)))
(let ((current (point))
(line-beginning (line-beginning-position)))
(forward-line -1)
(forward-char (- current line-beginning))
(setq locate-string (buffer-substring-no-properties (- (point) cal) (point))))
(setq beg (with-current-buffer source-buffer
(save-excursion
(save-restriction
(goto-char (point-min))
(or (equal line 1)
(forward-line (- line 1)))
(search-forward locate-string nil t)
(- (point) cal)
))))
(setq end (+ beg cal))
(setq diags
(cons (flymake-make-diagnostic
source-buffer beg end level msg)
diags))
))
(funcall report-fn diags)
)))))
)
(defun verilog-flymake-detect (report-fn &rest _args)
"A Flymake backend for verilog.
Spawn an verilator process that byte-compiles a file representing the
current buffer state and calls REPORT-FN when done."
(when verilog--flymake-proc
(when (process-live-p verilog--flymake-proc)
(kill-process verilog--flymake-proc)))
(let ((source-buffer (current-buffer))
(coding-system-for-write 'utf-8-unix)
(coding-system-for-read 'utf-8))
(save-restriction
(widen)
(let* ((output-buffer (generate-new-buffer " *verilog-flymake*")))
(setq verilog--flymake-proc
(make-process
:name "verilog-flymake-process"
:buffer output-buffer
:command (append verilog-flymake-command
(list (buffer-file-name source-buffer)))
:connection-type 'pipe
:sentinel
(lambda (proc _event)
(unless (process-live-p proc)
(unwind-protect
(cond
((not (and (buffer-live-p source-buffer)
(eq proc (with-current-buffer source-buffer
verilog--flymake-proc))))
(flymake-log :warning
"verilog-flymake process %s obsolete" proc))
((memq (process-status proc) '(exit signal))
(verilog-flymake-done report-fn
source-buffer
verilog--flymake-output-buffer
))
(t
(funcall report-fn
:panic
:explanation
(format "process %s died" proc))))
(kill-buffer verilog--flymake-output-buffer)
)))
:stderr verilog--flymake-output-buffer
:noquery t))))))
(defun verilog-setup-flymake-backend ()
"Setup `flymake-verilator' for verilog buffer."
(add-hook 'flymake-diagnostic-functions 'verilog-flymake-detect nil t))
(add-hook 'verilog-mode-hook 'verilog-setup-flymake-backend)
(provide 'flymake-verilator)
;;; flymake-verilator.el ends here.