From 442fe111436264e1a610fbf5686ccf1314407d4a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 7 Sep 2017 23:24:28 -0400 Subject: [PATCH] Fix various verilog-mode.el issues. * lisp/progmodes/verilog-mode.el (verilog-expand-dirnames): Fix expanding "*/*", msg2284. Reported by Jonathan Ferguson. (ignore-errors): Fix ignore-errors error on Emacs 22.3, bug1177. Reported by Victor Lau. (verilog-getopt, verilog-getopt-file) (verilog-library-flags, verilog-substitute-file-name-path): Support -F in verilog getopt files, bug1171. Reported by George Cuan. (verilog-do-indent): Fix misindenting symbols starting with t, bug1169. Reported by Hoai Tran. (verilog-read-auto-template-middle): Fix slow template matching on AUTOINST. Reported by Jeffrey Huynh. (verilog-pretty-expr): The extra whitespace addition before "=" operators is now done only if the whole assignment block contains the 2-character "<=" operator. Remove the unused argument _myre. Use `unless', `save-excursion' and `when' functions where possible. Internal variables refactored for clarity. Follow elisp convention for closing parentheses. By Kaushal Modi. (verilog-get-lineup-indent-2): Update docstring. Internal variables refactored for clarity. Earlier EDPOS argument was expected to be a marker; it is now renamed to END and is now expected to be a position. Use `when' instead of `if'. By Kaushal Modi. (electric-verilog-terminate-line): Remove the unused second argument from `verilog-pretty-expr' call. By Kaushal Modi. (verilog-calc-1): Fix indentation of a virtual class definition after a typedef class, bug1080. By Kaushal Modi. --- lisp/progmodes/verilog-mode.el | 364 +++++++++++++++++---------------- 1 file changed, 191 insertions(+), 173 deletions(-) diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el index 2760c4d276e..6e79b1a63df 100644 --- a/lisp/progmodes/verilog-mode.el +++ b/lisp/progmodes/verilog-mode.el @@ -4,7 +4,6 @@ ;; Author: Michael McNamara ;; Wilson Snyder -;; X-URL: http://www.verilog.com ;; X-URL: http://www.veripool.org ;; Created: 3 Jan 1996 ;; Keywords: languages @@ -70,7 +69,7 @@ ;; default. ;; You can get step by step help in installing this file by going to -;; +;; ;; The short list of installation instructions are: To set up ;; automatic Verilog mode, put this file in your load path, and put @@ -123,7 +122,7 @@ ;; ;; This variable will always hold the version number of the mode -(defconst verilog-mode-version "2017-05-08-b240c8f-vpo-GNU" +(defconst verilog-mode-version "2017-08-07-c085e50-vpo-GNU" "Version of this Verilog mode.") (defconst verilog-mode-release-emacs t "If non-nil, this version of Verilog mode was released with Emacs itself.") @@ -345,6 +344,12 @@ wherever possible, since it is slow." (unless (fboundp 'buffer-chars-modified-tick) ; Emacs 22 added (defmacro buffer-chars-modified-tick () (buffer-modified-tick))) (error nil)) + ;; Added in Emacs 23.1 + (condition-case nil + (unless (fboundp 'ignore-errors) + (defmacro ignore-errors (&rest body) + (declare (debug t) (indent 0)) + `(condition-case nil (progn ,@body) (error nil))))) ;; Added in Emacs 24.1 (condition-case nil (unless (fboundp 'prog-mode) @@ -961,7 +966,8 @@ Only used in XEmacs; GNU Emacs uses `verilog-error-regexp-emacs-alist'.") These arguments are used to find files for `verilog-auto', and match the flags accepted by a standard Verilog-XL simulator. - -f filename Reads more `verilog-library-flags' from the filename. + -f filename Reads absolute `verilog-library-flags' from the filename. + -F filename Reads relative `verilog-library-flags' from the filename. +incdir+dir Adds the directory to `verilog-library-directories'. -Idir Adds the directory to `verilog-library-directories'. -y dir Adds the directory to `verilog-library-directories'. @@ -4034,7 +4040,7 @@ With optional ARG, remove existing end of line comments." (progn (if (or (eq 'all verilog-auto-lineup) (eq 'assignments verilog-auto-lineup)) - (verilog-pretty-expr t "\\(<\\|:\\)?=" )) + (verilog-pretty-expr :quiet)) (newline)) (forward-line 1)) ;; Indent next line @@ -5790,11 +5796,9 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." (goto-char here) ; or is clocking, starts a new block (throw 'nesting 'block))))) - ;; need to consider typedef struct here... ((looking-at "\\") ;; *sigh* These words have an optional prefix: ;; extern {virtual|protected}? function a(); - ;; typedef class foo; ;; and we don't want to confuse this with ;; function a(); ;; property @@ -5804,7 +5808,11 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)." (cond ((looking-at verilog-dpi-import-export-re) (throw 'continue 'foo)) - ((looking-at "\\\\s-+\\\\s-+\\(?:\\<\\(local\\|protected\\|static\\)\\>\\s-+\\)?\\<\\(function\\|task\\)\\>\\s-+") + ((or + (looking-at "\\\\s-+\\\\s-+\\(?:\\<\\(local\\|protected\\|static\\)\\>\\s-+\\)?\\<\\(function\\|task\\)\\>\\s-+") + ;; Do not throw 'defun for class typedefs like + ;; typedef class foo; + (looking-at "\\\\s-+\\(?:\\\\s-+\\)?\\\\s-+")) (throw 'nesting 'statement)) ((looking-at verilog-beg-block-re-ordered) (throw 'nesting 'block)) @@ -6660,7 +6668,7 @@ Only look at a few lines to determine indent level." (let ((val)) (verilog-beg-of-statement-1) (if (and (< (point) here) - (verilog-re-search-forward "=[ \\t]*" here 'move) + (verilog-re-search-forward "=[ \t]*" here 'move) ;; not at a |=>, #=#, or [=n] operator (not (string-match "\\[=.\\|#=#\\||=>" (or (buffer-substring (- (point) 2) (1+ (point))) @@ -6974,106 +6982,97 @@ Be verbose about progress unless optional QUIET set." (forward-line 1)) (unless quiet (message ""))))))) -(defun verilog-pretty-expr (&optional quiet _myre) - "Line up expressions around point, optionally QUIET with regexp _MYRE ignored." +(defun verilog-pretty-expr (&optional quiet) + "Line up expressions around point. +If QUIET is non-nil, do not print messages showing the progress of line-up." (interactive) - (if (not (verilog-in-comment-or-string-p)) - (save-excursion - (let ( (rexp (concat "^\\s-*" verilog-complete-reg)) - (rexp1 (concat "^\\s-*" verilog-basic-complete-re))) - (beginning-of-line) - (if (and (not (looking-at rexp )) + (unless (verilog-in-comment-or-string-p) + (save-excursion + (let ((regexp (concat "^\\s-*" verilog-complete-reg)) + (regexp1 (concat "^\\s-*" verilog-basic-complete-re))) + (beginning-of-line) + (when (and (not (looking-at regexp)) (looking-at verilog-assignment-operation-re) (save-excursion (goto-char (match-end 2)) (and (not (verilog-in-attribute-p)) (not (verilog-in-parameter-p)) (not (verilog-in-comment-or-string-p))))) - (let* ((here (point)) - (e) (r) - (start - (progn - (beginning-of-line) - (setq e (point)) - (verilog-backward-syntactic-ws) - (beginning-of-line) - (while (and (not (looking-at rexp1)) - (looking-at verilog-assignment-operation-re) - (not (bobp)) - ) - (setq e (point)) - (verilog-backward-syntactic-ws) + (let* ((start (save-excursion ; BOL of the first line of the assignment block (beginning-of-line) - ) ;Ack, need to grok `define - e)) - (end - (progn - (goto-char here) + (let ((pt (point))) + (verilog-backward-syntactic-ws) + (beginning-of-line) + (while (and (not (looking-at regexp1)) + (looking-at verilog-assignment-operation-re) + (not (bobp))) + (setq pt (point)) + (verilog-backward-syntactic-ws) + (beginning-of-line)) ; Ack, need to grok `define + pt))) + (end (save-excursion ; EOL of the last line of the assignment block (end-of-line) - (setq e (point)) ;Might be on last line - (verilog-forward-syntactic-ws) - (beginning-of-line) - (while (and - (not (looking-at rexp1 )) - (looking-at verilog-assignment-operation-re) - (progn - (end-of-line) - (not (eq e (point))))) - (setq e (point)) + (let ((pt (point))) ; Might be on last line (verilog-forward-syntactic-ws) (beginning-of-line) - ) - e)) - (endpos (set-marker (make-marker) end)) - (ind) - ) - (goto-char start) - (verilog-do-indent (verilog-calculate-indent)) - (if (and (not quiet) - (> (- end start) 100)) - (message "Lining up expressions..(please stand by)")) - - ;; Set indent to minimum throughout region - (while (< (point) (marker-position endpos)) - (beginning-of-line) - (verilog-just-one-space verilog-assignment-operation-re) - (beginning-of-line) - (verilog-do-indent (verilog-calculate-indent)) - (end-of-line) - (verilog-forward-syntactic-ws) - ) - - ;; Now find biggest prefix - (setq ind (verilog-get-lineup-indent-2 verilog-assignment-operation-re start endpos)) - - ;; Now indent each line. - (goto-char start) - (while (progn (setq e (marker-position endpos)) - (setq r (- e (point))) - (> r 0)) - (setq e (point)) - (if (not quiet) (message "%d" r)) - (cond - ((looking-at verilog-assignment-operation-re) - (goto-char (match-beginning 2)) - (if (not (or (verilog-in-parenthesis-p) ; leave attributes and comparisons alone - (verilog-in-coverage-p))) - (if (eq (char-after) ?=) - (indent-to (1+ ind)) ; line up the = of the <= with surrounding = - (indent-to ind) - )) - ) - ((verilog-continued-line-1 start) - (goto-char e) - (indent-line-to ind)) - (t ; Must be comment or white space - (goto-char e) - (verilog-forward-ws&directives) - (forward-line -1)) - ) - (forward-line 1)) - (unless quiet (message "")) - )))))) + (while (and + (not (looking-at regexp1)) + (looking-at verilog-assignment-operation-re) + (progn + (end-of-line) + (not (eq pt (point))))) + (setq pt (point)) + (verilog-forward-syntactic-ws) + (beginning-of-line)) + pt))) + (contains-2-char-operator (string-match "<=" (buffer-substring-no-properties start end))) + (endmark (set-marker (make-marker) end))) + (goto-char start) + (verilog-do-indent (verilog-calculate-indent)) + (when (and (not quiet) + (> (- end start) 100)) + (message "Lining up expressions.. (please stand by)")) + + ;; Set indent to minimum throughout region + ;; Rely on mark rather than on point as the indentation changes can + ;; make the older point reference obsolete + (while (< (point) (marker-position endmark)) + (beginning-of-line) + (save-excursion + (verilog-just-one-space verilog-assignment-operation-re)) + (verilog-do-indent (verilog-calculate-indent)) + (end-of-line) + (verilog-forward-syntactic-ws)) + + (let ((ind (verilog-get-lineup-indent-2 verilog-assignment-operation-re start (marker-position endmark))) ; Find the biggest prefix + e) + ;; Now indent each line. + (goto-char start) + (while (progn + (setq e (marker-position endmark)) + (> e (point))) + (unless quiet + (message " verilog-pretty-expr: %d" (- e (point)))) + (setq e (point)) + (cond + ((looking-at verilog-assignment-operation-re) + (goto-char (match-beginning 2)) + (unless (or (verilog-in-parenthesis-p) ; Leave attributes and comparisons alone + (verilog-in-coverage-p)) + (if (and contains-2-char-operator + (eq (char-after) ?=)) + (indent-to (1+ ind)) ; Line up the = of the <= with surrounding = + (indent-to ind)))) + ((verilog-continued-line-1 start) + (goto-char e) + (indent-line-to ind)) + (t ; Must be comment or white space + (goto-char e) + (verilog-forward-ws&directives) + (forward-line -1))) + (forward-line 1)) + (unless quiet + (message ""))))))))) (defun verilog-just-one-space (myre) "Remove extra spaces around regular expression MYRE." @@ -7180,30 +7179,30 @@ Region is defined by B and EDPOS." ;;(skip-chars-backward " \t") (1+ (current-column)))))) -(defun verilog-get-lineup-indent-2 (myre b edpos) - "Return the indent level that will line up several lines within the region." +(defun verilog-get-lineup-indent-2 (regexp beg end) + "Return the indent level that will line up several lines. +The lineup string is searched using REGEXP within the region between points +BEG and END." (save-excursion - (let ((ind 0) e) - (goto-char b) + (let ((ind 0)) + (goto-char beg) ;; Get rightmost position - (while (progn (setq e (marker-position edpos)) - (< (point) e)) - (if (and (verilog-re-search-forward myre e 'move) - (not (verilog-in-attribute-p))) ; skip attribute exprs - (progn - (goto-char (match-beginning 2)) - (verilog-backward-syntactic-ws) - (if (> (current-column) ind) - (setq ind (current-column))) - (goto-char (match-end 0))) - )) - (if (> ind 0) - (1+ ind) - ;; No lineup-string found - (goto-char b) - (end-of-line) - (skip-chars-backward " \t") - (1+ (current-column)))))) + (while (< (point) end) + (when (and (verilog-re-search-forward regexp end 'move) + (not (verilog-in-attribute-p))) ; skip attribute exprs + (goto-char (match-beginning 2)) + (verilog-backward-syntactic-ws) + (if (> (current-column) ind) + (setq ind (current-column))) + (goto-char (match-end 0)))) + (setq ind (if (> ind 0) + (1+ ind) + ;; No lineup-string found + (goto-char beg) + (end-of-line) + (skip-chars-backward " \t") + (1+ (current-column)))) + ind))) (defun verilog-comment-depth (type val) "A useful mode debugging aide. TYPE and VAL are comments for insertion." @@ -9344,7 +9343,7 @@ Returns REGEXP and list of ( (signal_name connection_name)... )." ;; Regexp form?? ((looking-at ;; Regexp bug in XEmacs disallows ][ inside [], and wants + last - "\\s-*\\.\\(\\([a-zA-Z0-9`_$+@^.*?|---]+\\|[][]\\|\\\\[()|]\\)+\\)\\s-*(\\(.*\\))\\s-*\\(,\\|)\\s-*;\\)") + "\\s-*\\.\\(\\([a-zA-Z0-9`_$+@^.*?|---]\\|[][]\\|\\\\[()|]\\)+\\)\\s-*(\\(.*\\))\\s-*\\(,\\|)\\s-*;\\)") (setq rep (match-string-no-properties 3)) (goto-char (match-end 0)) (setq tpl-wild-list @@ -9619,8 +9618,9 @@ Some macros and such are also found and included. For dinotrace.el." ;; Argument file parsing ;; -(defun verilog-getopt (arglist) - "Parse -f, -v etc arguments in ARGLIST list or string." +(defun verilog-getopt (arglist &optional default-dir) + "Parse -f, -v etc arguments in ARGLIST list or string. +Use DEFAULT-DIR to anchor paths if non-nil." (unless (listp arglist) (setq arglist (list arglist))) (let ((space-args '()) arg next-param) @@ -9638,6 +9638,8 @@ Some macros and such are also found and included. For dinotrace.el." space-args (cdr space-args)) (cond ;; Need another arg + ((equal arg "-F") + (setq next-param arg)) ((equal arg "-f") (setq next-param arg)) ((equal arg "-v") @@ -9661,32 +9663,37 @@ Some macros and such are also found and included. For dinotrace.el." ((or (string-match "^\\+incdir\\+\\(.*\\)" arg) ; +incdir+dir (string-match "^-I\\(.*\\)" arg)) ; -Idir (verilog-add-list-unique `verilog-library-directories - (match-string 1 (substitute-in-file-name arg)))) + (substitute-in-file-name (match-string 1 arg)))) ;; Ignore ((equal "+librescan" arg)) ((string-match "^-U\\(.*\\)" arg)) ; -Udefine ;; Second parameters + ((equal next-param "-F") + (setq next-param nil) + (verilog-getopt-file (verilog-substitute-file-name-path arg default-dir) + (file-name-directory (verilog-substitute-file-name-path arg default-dir)))) ((equal next-param "-f") (setq next-param nil) - (verilog-getopt-file (substitute-in-file-name arg))) + (verilog-getopt-file (verilog-substitute-file-name-path arg default-dir) nil)) ((equal next-param "-v") (setq next-param nil) (verilog-add-list-unique `verilog-library-files - (substitute-in-file-name arg))) + (verilog-substitute-file-name-path arg default-dir))) ((equal next-param "-y") (setq next-param nil) (verilog-add-list-unique `verilog-library-directories - (substitute-in-file-name arg))) + (verilog-substitute-file-name-path arg default-dir))) ;; Filename ((string-match "^[^-+]" arg) (verilog-add-list-unique `verilog-library-files - (substitute-in-file-name arg))) + (verilog-substitute-file-name-path arg default-dir))) ;; Default - ignore; no warning )))) ;;(verilog-getopt (list "+libext+.a+.b" "+incdir+foodir" "+define+a+aval" "-f" "otherf" "-v" "library" "-y" "dir")) -(defun verilog-getopt-file (filename) - "Read Verilog options from the specified FILENAME." +(defun verilog-getopt-file (filename &optional default-dir) + "Read Verilog options from the specified FILENAME. +Use DEFAULT-DIR to anchor paths if non-nil." (save-excursion (let ((fns (verilog-library-filenames filename (buffer-file-name))) (orig-buffer (current-buffer)) @@ -9702,7 +9709,7 @@ Some macros and such are also found and included. For dinotrace.el." (when (string-match "//" line) (setq line (substring line 0 (match-beginning 0)))) (with-current-buffer orig-buffer ; Variables are buffer-local, so need right context. - (verilog-getopt line)))))) + (verilog-getopt line default-dir)))))) (defun verilog-getopt-flags () "Convert `verilog-library-flags' into standard library variables." @@ -9719,6 +9726,13 @@ Some macros and such are also found and included. For dinotrace.el." ;; Allow user to customize (verilog-run-hooks 'verilog-getopt-flags-hook)) +(defun verilog-substitute-file-name-path (filename default-dir) + "Return FILENAME with environment variables substituted. +Use DEFAULT-DIR to anchor paths if non-nil." + (if default-dir + (expand-file-name (substitute-in-file-name filename) default-dir) + (substitute-in-file-name filename))) + (defun verilog-add-list-unique (varref object) "Append to VARREF list the given OBJECT, unless it is already a member of the variable's list." @@ -9898,42 +9912,44 @@ Or, just the existing dirnames themselves if there are no wildcards." (interactive) (unless dirnames (error "`verilog-library-directories' should include at least `.'")) - (setq dirnames (reverse dirnames)) ; not nreverse - (let ((dirlist nil) - pattern dirfile dirfiles dirname root filename rest basefile) - (while dirnames - (setq dirname (substitute-in-file-name (car dirnames)) - dirnames (cdr dirnames)) - (cond ((string-match (concat "^\\(\\|[/\\]*[^*?]*[/\\]\\)" ; root - "\\([^/\\]*[*?][^/\\]*\\)" ; filename with *? - "\\(.*\\)") ; rest - dirname) - (setq root (match-string 1 dirname) - filename (match-string 2 dirname) - rest (match-string 3 dirname) - pattern filename) - ;; now replace those * and ? with .+ and . - ;; use ^ and /> to get only whole file names - (setq pattern (verilog-string-replace-matches "[*]" ".+" nil nil pattern) - pattern (verilog-string-replace-matches "[?]" "." nil nil pattern) - pattern (concat "^" pattern "$") - dirfiles (verilog-dir-files root)) - (while dirfiles - (setq basefile (car dirfiles) - dirfile (expand-file-name (concat root basefile rest)) - dirfiles (cdr dirfiles)) - (if (and (string-match pattern basefile) - ;; Don't allow abc/*/rtl to match abc/rtl via .. - (not (equal basefile ".")) - (not (equal basefile "..")) - (file-directory-p dirfile)) - (setq dirlist (cons dirfile dirlist))))) - ;; Defaults - (t - (if (file-directory-p dirname) - (setq dirlist (cons dirname dirlist)))))) - dirlist)) -;;(verilog-expand-dirnames (list "." ".." "nonexist" "../*" "/home/wsnyder/*/v")) + (save-match-data + (setq dirnames (reverse dirnames)) ; not nreverse + (let ((dirlist nil) + pattern dirfile dirfiles dirname root filename rest basefile) + (setq dirnames (mapcar 'substitute-in-file-name dirnames)) + (while dirnames + (setq dirname (car dirnames) + dirnames (cdr dirnames)) + (cond ((string-match (concat "^\\(\\|[/\\]*[^*?]*[/\\]\\)" ; root + "\\([^/\\]*[*?][^/\\]*\\)" ; filename with *? + "\\(.*\\)") ; rest + dirname) + (setq root (match-string 1 dirname) + filename (match-string 2 dirname) + rest (match-string 3 dirname) + pattern filename) + ;; now replace those * and ? with .+ and . + ;; use ^ and /> to get only whole file names + (setq pattern (verilog-string-replace-matches "[*]" ".+" nil nil pattern) + pattern (verilog-string-replace-matches "[?]" "." nil nil pattern) + pattern (concat "^" pattern "$") + dirfiles (verilog-dir-files root)) + (while dirfiles + (setq basefile (car dirfiles) + dirfile (expand-file-name (concat root basefile rest)) + dirfiles (cdr dirfiles)) + (when (and (string-match pattern basefile) + ;; Don't allow abc/*/rtl to match abc/rtl via .. + (not (equal basefile ".")) + (not (equal basefile ".."))) + ;; Might have more wildcards, so process again + (setq dirnames (cons dirfile dirnames))))) + ;; Defaults + (t + (if (file-directory-p dirname) + (setq dirlist (cons dirname dirlist)))))) + dirlist))) +;;(verilog-expand-dirnames (list "." ".." "nonexist" "../*" "/home/wsnyder/*/v" "../*/*")) (defun verilog-library-filenames (filename &optional current check-ext) "Return a search path to find the given FILENAME or module name. @@ -12074,7 +12090,7 @@ This is currently equivalent to: with the below at the bottom of the file // Local Variables: - // verilog-auto-logic-type:\"logic\" + // verilog-auto-wire-type:\"logic\" // End: In the future AUTOLOGIC may declare additional identifiers, @@ -13223,10 +13239,12 @@ Typing \\[verilog-auto] will make this into: Replace the /*AUTOTIEOFF*/ comment with code to wire-tie all unused output signals to deasserted. -/*AUTOTIEOFF*/ is used to make stub modules; modules that have the same -input/output list as another module, but no internals. Specifically, it -finds all outputs in the module, and if that input is not otherwise declared -as a register or wire, creates a tieoff. +/*AUTOTIEOFF*/ is used to make stub modules; modules that have +the same input/output list as another module, but no internals. +Specifically, it finds all outputs in the module, and if that +input is not otherwise declared as a register or wire, nor comes +from a AUTOINST submodule's output, creates a tieoff. AUTOTIEOFF +does not examine assignments to determine what is already driven. AUTORESET ties signals to deasserted, which is presumed to be zero. Signals that match `verilog-active-low-regexp' will be deasserted by tying @@ -14420,7 +14438,7 @@ Files are checked based on `verilog-library-flags'." (with-output-to-temp-buffer "*verilog-mode help*" (princ (format "You are using verilog-mode %s\n" verilog-mode-version)) (princ "\n") - (princ "For new releases, see http://www.verilog.com\n") + (princ "For new releases, see http://www.veripool.com/verilog-mode\n") (princ "\n") (princ "For frequently asked questions, see http://www.veripool.org/verilog-mode-faq.html\n") (princ "\n") -- 2.39.2