+;; Auto diff
+;;
+
+(defun verilog-diff-buffers-p (b1 b2 &optional whitespace)
+ "Return nil if buffers B1 and B2 have same contents.
+Else, return point in B1 that first mismatches.
+If optional WHITESPACE true, ignore whitespace."
+ (save-excursion
+ (let* ((case-fold-search nil) ;; compare-buffer-substrings cares
+ (p1 (with-current-buffer b1 (goto-char (point-min))))
+ (p2 (with-current-buffer b2 (goto-char (point-min))))
+ (maxp1 (with-current-buffer b1 (point-max)))
+ (maxp2 (with-current-buffer b2 (point-max)))
+ (op1 -1) (op2 -1)
+ progress size)
+ (while (not (and (eq p1 op1) (eq p2 op2)))
+ ;; If both windows have whitespace optionally skip over it.
+ (when whitespace
+ ;; skip-syntax-* doesn't count \n
+ (with-current-buffer b1
+ (goto-char p1)
+ (skip-chars-forward " \t\n\r\f\v")
+ (setq p1 (point)))
+ (with-current-buffer b2
+ (goto-char p2)
+ (skip-chars-forward " \t\n\r\f\v")
+ (setq p2 (point))))
+ (setq size (min (- maxp1 p1) (- maxp2 p2)))
+ (setq progress (compare-buffer-substrings b2 p2 (+ size p2)
+ b1 p1 (+ size p1)))
+ (setq progress (if (zerop progress) size (1- (abs progress))))
+ (setq op1 p1 op2 p2
+ p1 (+ p1 progress)
+ p2 (+ p2 progress)))
+ ;; Return value
+ (if (and (eq p1 maxp1) (eq p2 maxp2))
+ nil p1))))
+
+(defun verilog-diff-file-with-buffer (f1 b2 &optional whitespace show)
+ "View the differences between file F1 and buffer B2.
+This requires the external program `diff-command' to be in your `exec-path',
+and uses `diff-switches' in which you may want to have \"-u\" flag.
+Ignores WHITESPACE if t, and writes output to stdout if SHOW."
+ ;; Similar to `diff-buffer-with-file' but works on XEmacs, and doesn't
+ ;; call `diff' as `diff' has different calling semantics on different
+ ;; versions of Emacs.
+ (if (not (file-exists-p f1))
+ (message "Buffer %s has no associated file on disc" (buffer-name b2))
+ (with-temp-buffer "*Verilog-Diff*"
+ (let ((outbuf (current-buffer))
+ (f2 (make-temp-file "vm-diff-auto-")))
+ (unwind-protect
+ (progn
+ (with-current-buffer b2
+ (save-restriction
+ (widen)
+ (write-region (point-min) (point-max) f2 nil 'nomessage)))
+ (call-process diff-command nil outbuf t
+ diff-switches ;; User may want -u in diff-switches
+ (if whitespace "-b" "")
+ f1 f2)
+ ;; Print out results. Alternatively we could have call-processed
+ ;; ourself, but this way we can reuse diff switches
+ (when show
+ (with-current-buffer outbuf (message "%s" (buffer-string))))))
+ (sit-for 0)
+ (when (file-exists-p f2)
+ (delete-file f2))))))
+
+(defun verilog-diff-report (b1 b2 diffpt)
+ "Report differences detected with `verilog-diff-auto'.
+Differences are between buffers B1 and B2, starting at point
+DIFFPT. This function is called via `verilog-diff-function'."
+ (let ((name1 (with-current-buffer b1 (buffer-file-name))))
+ (message "%%Warning: %s:%d: Difference in AUTO expansion found"
+ name1 (with-current-buffer b1 (1+ (count-lines (point-min) (point)))))
+ (cond (noninteractive
+ (verilog-diff-file-with-buffer name1 b2 t t))
+ (t
+ (ediff-buffers b1 b2)))))
+
+(defun verilog-diff-auto ()
+ "Expand AUTOs in a temporary buffer and indicate any changes.
+Whitespace differences are ignored to determine identicalness, but
+once a difference is detected, whitespace differences may be shown.
+
+To call this from the command line, see \\[verilog-batch-diff-auto].
+
+The action on differences is selected with
+`verilog-diff-function'. The default is `verilog-diff-report'
+which will report an error and run `ediff' in interactive mode,
+or `diff' in batch mode."
+ (interactive)
+ (let ((b1 (current-buffer)) b2 diffpt
+ (name1 (buffer-file-name))
+ (newname "*Verilog-Diff*"))
+ (save-excursion
+ (when (get-buffer newname)
+ (kill-buffer newname))
+ (setq b2 (let (buffer-file-name) ;; Else clone is upset
+ (clone-buffer newname)))
+ (with-current-buffer b2
+ ;; auto requires the filename, but can't have same filename in two
+ ;; buffers; so override both b1 and b2's names
+ (let ((buffer-file-name name1))
+ (unwind-protect
+ (progn
+ (with-current-buffer b1 (setq buffer-file-name nil))
+ (verilog-auto)
+ (when (not verilog-auto-star-save)
+ (verilog-delete-auto-star-implicit)))
+ ;; Restore name if unwind
+ (with-current-buffer b1 (setq buffer-file-name name1)))))
+ ;;
+ (setq diffpt (verilog-diff-buffers-p b1 b2 t))
+ (cond ((not diffpt)
+ (unless noninteractive (message "AUTO expansion identical"))
+ (kill-buffer newname)) ;; Nice to cleanup after oneself
+ (t
+ (funcall verilog-diff-function b1 b2 diffpt)))
+ ;; Return result of compare
+ diffpt)))
+
+\f
+;;