From xemacs-m  Tue Feb  4 14:22:37 1997
Received: from steadfast.teradyne.com (steadfast.teradyne.com [131.101.1.200])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id OAA07875
	for <xemacs-beta@xemacs.org>; Tue, 4 Feb 1997 14:22:35 -0600 (CST)
Received: from engine.ecf.teradyne.com (engine.ecf.teradyne.com [131.101.192.6]) by steadfast.teradyne.com (8.7.1/8.7.1) with ESMTP id PAA25190; Tue, 4 Feb 1997 15:23:42 -0500 (EST)
Received: from midnight.eng.ecf.teradyne.com (midnight.ecf.teradyne.com [131.101.192.49]) by engine.ecf.teradyne.com (8.7.1/8.7.1) with SMTP id VAA18277; Tue, 4 Feb 1997 21:19:53 +0100 (MET)
Received: by midnight.eng.ecf.teradyne.com (SMI-8.6/SMI-SVR4)
	id VAA02923; Tue, 4 Feb 1997 21:19:52 +0100
To: Michael McNamara <mac@silicon-sorcery.com>
Cc: XEmacs Beta Mailing List <xemacs-beta@xemacs.org>,
        Jens Edelmann <edelmann@ecf.teradyne.com>
X-Face: 4[iHdXiTu\V3u[~\I)<f9HC);%~nG8`oUqv#uzvs6=\V{AjN6Sn
 c/qi;YLwRmEbt8Y*=j5n(urqY@chPh@J'D"QlqD!C8>*}#kYF[-tYl3VZga/HSOP|K,{L
 Rtu@f0y/=O&Cu}\:~d|P$JON?pn?j,&CnPb1z#/TL9bkAJwyol&a:SvYj-VYbM=Dtxhk9
 =w|R6U3_;SH&B<Mfy6Q%#
Subject: Update of verilog-mode.el<2.21> for XEmacs-20.0 (1/4)
Mime-Version: 1.0 (split by tm-edit 7.101)
Content-Type: message/partial; id="Tue_Feb__4_21:19:50_1997@midnight.ecf.teradyne.com"; number=1; total=4
From: Adrian Aichner <aichner@ecf.teradyne.com>
Date: 04 Feb 1997 21:19:50 +0100
Message-ID: <rxswwsocoih.fsf@midnight.ecf.teradyne.com>
Lines: 999
X-Mailer: Red Gnus v0.84/XEmacs 20.0

To: Michael McNamara <mac@silicon-sorcery.com>
Cc: XEmacs Beta Mailing List <xemacs-beta@xemacs.org>,
    Jens Edelmann <edelmann@ecf.teradyne.com>
Subject: Update of verilog-mode.el<2.21> for XEmacs-20.0
X-Face: 4[iHdXiTu\V3u[~\I)<f9HC);%~nG8`oUqv#uzvs6=\V{AjN6Sn
 c/qi;YLwRmEbt8Y*=j5n(urqY@chPh@J'D"QlqD!C8>*}#kYF[-tYl3VZga/HSOP|K,{L
 Rtu@f0y/=O&Cu}\:~d|P$JON?pn?j,&CnPb1z#/TL9bkAJwyol&a:SvYj-VYbM=Dtxhk9
 =w|R6U3_;SH&B<Mfy6Q%#
Mime-Version: 1.0 (generated by tm-edit 7.101)
Content-Type: multipart/mixed;
 boundary="Multipart_Tue_Feb__4_21:19:43_1997-1"
Content-Transfer-Encoding: 7bit

--Multipart_Tue_Feb__4_21:19:43_1997-1
Content-Type: text/plain; charset=US-ASCII


Hello Michael,

I just gave it a shot and updated your verilog-mode.el<2.21> according
to the cc-mode.el supplied with XEmacs-20.0 (Emacs Version major and
flavor logic).

So far it seems to work fine now under XEmacs-20.0.

See if you can use it in case you have XEmacs-20.0 available.

Regards,

Adrian


--Multipart_Tue_Feb__4_21:19:43_1997-1
Content-Type: text/plain; charset=US-ASCII

;;; For help figuring out what to do with this file, visit
;;;  <http://www.silicon-sorcery.com/emacs_install.html>

;;; verilog-mode.el --- major mode for editing verilog source in Emacs
;;
;; $Header: /usr/local/lib/el/RCS/verilog-mode.el,v 1.1 1997/02/03 17:38:02 aichner Exp aichner $

;; Copyright (C) 1996 Free Software Foundation, Inc.

;; Author: Michael McNamara (mac@silicon-sorcery.com) 
;; President, Silicon Sorcery
;; Keywords: languages

;; This file is part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;;; Commentary:

;;; This mode borrows heavily from the pascal-mode and the cc-mode of emacs

;;; USAGE
;;; =====

;;; A major mode for editing Verilog HDL source code. When you have
;;; entered Verilog mode, you may get more info by pressing C-h m. You
;;; may also get online help describing various functions by: C-h f
;;; <Name of function you want described>

;;; To set up automatic verilog mode, put this file in your load path,
;;; and include stuff like this in your .emacs:

; (autoload 'verilog-mode "verilog-mode" "Verilog mode" t )
; (setq auto-mode-alist (cons  '("\\.v\\'" . verilog-mode) auto-mode-alist))
; (setq auto-mode-alist (cons  '("\\.dv\\'" . verilog-mode) auto-mode-alist))

;;; If you want to customize Verilog mode to fit your needs better,
;;; you may add these lines (the values of the variables presented
;;; here are the defaults):
;;;
;;; ;; User customization for Verilog mode
;;; (setq verilog-indent-level             3
;;;       verilog-case-indent              2
;;;       verilog-auto-newline             t
;;;       verilog-auto-indent-on-newline   t
;;;       verilog-tab-always-indent        t
;;;       verilog-auto-endcomments         t
;;;       verilog-minimum-comment-distance 40
;;;       verilog-indent-begin-after-if    t
;;;       verilog-auto-lineup              '(all))

;;; I've put in the common support for colored displays for older
;;; emacs-19 behaviour, and newer emacs-19 behaviour, as well as
;;; support for xemacs.  After that, customizing according to your
;;; particular emacs version is up to you.  I've used the following
;;; for emacs 19.27 and emacs 19.30; also xemacs seems to work for me
;;; as well.  I must caution that since the font-lock package doesn't
;;; have a version number, I've had to key off the emacs version
;;; number, which might not corrolate with the font-lock package you
;;; happen to be using...

;;;; Cut the following (From ";;;; - HERE - " to ";;;; - THERE -") and
;;;; place the text in your .emacs file. The delete all the single ;
;;;; at the beginning of the lines.  

;;;; (If you set the mark at the word HERE, (get cursor of the word
;;;; and type C-@) and point at word THERE, and then type C-u M-x
;;;; comment-region it will magically delete all the ; for you)

;;;; As coded this should work for modern versions of emacs, and also
;;;; should be a basis where you could build from to get colors for
;;;; other modes.  It owes a fair bit to the excellent sample.emacs
;;;; from Xemacs.


; ;;; - HERE -
;(defvar background-mode 'light)
;(defvar display-type 'color)
;  ;; figure out background color.  We could ask the user, but that would be too easy
;(cond
; ((and
;   (fboundp 'device-type)
;   (string= "x" (device-type)))
;  (setq display-type (device-class)
;	background-mode 
;	(condition-case nil
;	    (let ((bg-resource (x-get-resource ".backgroundMode" "BackgroundMode" 'string))
;		  (params (frame-parameters)))
;	      (cond (bg-resource (intern (downcase bg-resource)))
;		    ((and (cdr (assq 'background-color params))
;			  (< (apply '+ (x-color-values
;					(cdr (assq 'background-color params))))
;			     (/ (apply '+ (x-color-values "white")) 3)))
;		     'dark)
;		    ((and (cdr (assq 'border-color params))
;			  (> (apply '+ (color-instance-rgb-components 
;					(make-color-instance (cdr (assq 'border-color params)))))
;			     (/ 255 3)))
;		     'dark)
;		    (t 'light)))
;	  (error 'light))
;	)
;  )
; ((and
;   (boundp 'window-system)
;   (string= window-system "x"))
;  (setq display-type 
;	(condition-case nil
;	    (let ((display-resource (x-get-resource ".displayType" "DisplayType")))
;	      (cond (display-resource (intern (downcase display-resource)))
;		    ((x-display-color-p) 'color)
;		    ((x-display-grayscale-p) 'grayscale)
;		    (t 'mono)))
;	  (error 'mono))
;	)
;  (setq background-mode 
;	(condition-case nil
;	    (let ((bg-resource (x-get-resource ".backgroundMode"
;					       "BackgroundMode" ))
;		  (params (frame-parameters)))
;	      (cond (bg-resource (intern (downcase bg-resource)))
;		    ((and (cdr (assq 'background-color params))
;			  (< (apply '+ (x-color-values
;					(cdr (assq 'background-color params))))
;			     (/ (apply '+ (x-color-values "white")) 3)))
;		     'dark)
;		    ((and (fboundp 'color-instance-rgb-components )
;			  (cdr (assq 'border-color params))
;			  (> (apply '+ (color-instance-rgb-components 
;					(make-color-instance (cdr (assq 'border-color params)))))
;			     (/ 255 3)))
;		     'dark)
;		    (t 'light)))
;	  (error 'light))
;	)
;  ))

;(message "It appears you have a %s background" background-mode)

; ; Now do emacs version specific color setup
;(cond
; ((and (string-match "XEmacs" emacs-version)
;       (boundp 'emacs-major-version)
;       (= emacs-major-version 19)
;       (>= emacs-minor-version 12))

;  ;; If you want the default colors, you could do this:
;  ;; (setq font-lock-use-default-fonts nil)
;  ;; (setq font-lock-use-default-colors t)
;  ;; but I want to specify my own colors, so I turn off all
;  ;; default values.
;  (setq font-lock-use-default-fonts nil)
;  (setq font-lock-use-default-colors nil)
;  (require 'font-lock)
  
;  ;; Mess around with the faces a bit.  Note that you have
;  ;; to change the font-lock-use-default-* variables *before*
;  ;; loading font-lock, and wait till *after* loading font-lock
;  ;; to customize the faces.
  
;  ;; (use copy-face instead of make-face-italic/make-face-bold because
;  ;; the startup code does intelligent things to the 'italic and 'bold
;  ;; faces to ensure that they are different from the default face.
;  ;; For example, if the default face is bold, then the 'bold face
;  ;; will be unbold.)
;  ;; Underling comments looks terrible on tty's
;  (set-face-underline-p 'font-lock-comment-face nil 'global 'tty)
;  (set-face-highlight-p 'font-lock-comment-face t 'global 'tty)

;  (make-face-unitalic 'font-lock-comment-face)
;  (make-face-unitalic 'font-lock-string-face)
;  (copy-face 'bold 'font-lock-function-name-face)
;  (cond 
;   ((eq background-mode 'light)
;    (set-face-foreground 'font-lock-comment-face "orchid")
;    (set-face-foreground 'font-lock-function-name-face "red")
;    (set-face-foreground 'font-lock-keyword-face "blue")
;    (set-face-foreground 'font-lock-string-face  "steelblue")
;    (set-face-foreground 'font-lock-type-face 	 "darkgreen")
;    )
;   ((eq background-mode 'dark)
;    (set-face-foreground 'font-lock-comment-face "#efc80c")
;    (set-face-foreground 'font-lock-function-name-face "red")
;    (set-face-foreground 'font-lock-keyword-face "tan")
;    (set-face-foreground 'font-lock-string-face  "lightskyblue")
;    (set-face-foreground 'font-lock-type-face 	 "Aquamarine")
;    )
;   )
;  ;; misc. faces
;  (and (find-face 'font-lock-preprocessor-face) ; 19.13 and above
;       (copy-face 'bold 'font-lock-preprocessor-face))
;  )
;   ((> emacs-minor-version 29)
;    (if (eq background-mode 'light)
;	(setq font-lock-face-attributes
;	      '(
;		(font-lock-comment-face "orchid"		nil nil t   nil) 
;		(font-lock-function-name-face "red"		nil t   nil nil) 
;		(font-lock-keyword-face "blue" 		nil nil nil nil) 
;		(font-lock-reference-face "indianred"         nil t nil nil  )
;		(font-lock-string-face  "steelblue"	nil nil nil nil) 
;		(font-lock-type-face 	  "darkgreen"          nil nil nil nil) 
;		(font-lock-variable-name-face "brown") 
;		)
;	      )
;      (setq font-lock-face-attributes
;	      '(
;		(font-lock-comment-face "#efc80c"		nil nil t   nil) 
;		(font-lock-function-name-face "red"		nil t   nil nil) 
;		(font-lock-keyword-face "tan" 		nil nil nil nil) 
;		(font-lock-reference-face "indianred"         nil t nil nil  )
;		(font-lock-string-face  "lightskyblue"	nil nil nil nil) 
;		(font-lock-type-face 	  "Aquamarine"          nil nil nil nil) 
;		(font-lock-variable-name-face "LightGoldenrod") 
;		)
;	      )
;      )
;    )
;   (t
;    (if (eq background-mode 'dark)
;	(progn
;	  (make-face 'my-font-lock-function-name-face)
;	  (set-face-foreground 'my-font-lock-function-name-face "red") 
;	  (setq  font-lock-function-name-face  'my-font-lock-function-name-face)
	  
;	  (make-face 'my-font-lock-keyword-face)
;	  (set-face-foreground 'my-font-lock-keyword-face "tan")
;	  (setq  font-lock-keyword-face  'my-font-lock-keyword-face)
	  
;	  (make-face 'my-font-lock-string-face)
;	  (set-face-foreground 'my-font-lock-string-face      "lightskyblue")
;	  (setq  font-lock-string-face  'my-font-lock-string-face)
	  
;	  (make-face 'my-font-lock-type-face)
;	  (set-face-foreground 'my-font-lock-type-face        "#efc80c") ; yellow
;	  (setq  font-lock-type-face  'my-font-lock-type-face)
	  
;	  (make-face 'my-font-lock-variable-name-face)
;	  (set-face-foreground 'my-font-lock-variable-name-face "LightGoldenrod") 
;	  (setq  font-lock-variable-name-face  'my-font-lock-variable-name-face)
;	  )
;      (progn
;	(make-face 'my-font-lock-function-name-face)
;	(set-face-foreground 'my-font-lock-function-name-face "DarkGreen") 
;	(setq  font-lock-function-name-face  'my-font-lock-function-name-face)
	
;	(make-face 'my-font-lock-keyword-face)
;	(set-face-foreground 'my-font-lock-keyword-face "indianred")
;	(setq  font-lock-keyword-face  'my-font-lock-keyword-face)
	
;	(make-face 'my-font-lock-string-face)
;	(set-face-foreground 'my-font-lock-string-face      "RoyalBlue")
;	(setq  font-lock-string-face  'my-font-lock-string-face)
	
;	(make-face 'my-font-lock-type-face)
;	(set-face-foreground 'my-font-lock-type-face        "#003800") ; yellow
;	(setq  font-lock-type-face  'my-font-lock-type-face)
	
;	(make-face 'my-font-lock-variable-name-face)
;	(set-face-foreground 'my-font-lock-variable-name-face "LightGoldenrod") 
;	(setq  font-lock-variable-name-face  'my-font-lock-variable-name-face)
;	)
;      )
;    )
; )

;(cond
; ((eq display-type 'color)
;  ;; Pretty Colors in source windows.
;  (require 'font-lock)
;  (autoload 'turn-on-fast-lock "fast-lock"
;    "Unconditionally turn on Fast Lock mode.")
;  (add-hook 'c-mode-hook 'font-lock-mode)
;  (add-hook 'verilog-mode-hook 'font-lock-mode)
;  (add-hook 'perl-mode-hook 'font-lock-mode)
;  (add-hook 'elisp-mode-hook 'font-lock-mode)
;  (add-hook 'asm-mode-hook 'font-lock-mode)
;  (setq fast-lock-cache-directories '("~/.backups" "."))
;  (setq c-font-lock-keywords c-font-lock-keywords-2)
;  (setq c++-font-lock-keywords c++-font-lock-keywords-2)
;  (autoload 'verilog-make-faces "verilog-mode" "Set up faces for verilog")
;  (if (not (string-match "XEmacs" emacs-version))
;      (progn
;	(cond 
;	 ((eq background-mode 'dark)
;	  ;; Make background a light gray
;	  (set-face-background (quote region) "gray30"))
;	 ;; Make background a dark gray
;	 ((eq background-mode 'light)    
;	  (set-face-background (quote region) "gray70"))
;	 )
;	)
;    )
;  )
; ((eq display-type 'mono)
;  (progn
;    ;; Frames are too expensive to create
;    ;; on my NCD running x-remote, which happens
;    ;; to be the only place I run X mono color
;    (setq vm-frame-per-composition nil
;	  vm-frame-per-folder nil)
;    )
;  )
; )
; ;;; - THERE -

;;; KNOWN BUGS / BUGREPORTS
;;; ======================= This is beta code, and likely has
;;; bugs. Please report any and all bugs to me at mac@silicon-sorcery.com.
;; 
;;; Code:

(provide 'verilog-mode)

;; This variable will always hold the version number of the mode
(defconst verilog-mode-version "$$Revision: 1.1 $$"
  "Version of this verilog mode.")

(defvar verilog-indent-level 3
  "*Indentation of Verilog statements with respect to containing block.")

(defvar verilog-cexp-indent 1
  "*Indentation of Verilog statements split across lines.")

(defvar verilog-case-indent 2
  "*Indentation for case statements.")

(defvar verilog-auto-newline t
  "*Non-nil means automatically newline after semicolons")

(defvar verilog-auto-indent-on-newline t
  "*Non-nil means automatically indent line after newline")

(defvar verilog-tab-always-indent t
  "*Non-nil means TAB in Verilog mode should always reindent the current line,
regardless of where in the line point is when the TAB command is used.")

(defvar verilog-indent-begin-after-if t
  "*If true, indent begin statements following if, else, while, for and repeat.
otherwise, line them up.")

(defvar verilog-auto-endcomments t
  "*Non-nil means a comment /* ... */ is set after the ends which ends cases and
functions. The name of the function or case will be set between the braces.")

(defvar verilog-minimum-comment-distance 40
  "*Minimum distance between begin and end required before a comment will be inserted.
Setting this variable to zero results in every end aquiring a comment; the default avoids 
too many redundanet comments in tight quarters")

(defvar verilog-auto-lineup '(all) "*List of contexts where auto
  lineup of :'s or ='s should be done.  Elements can be of type:
  'declaration' or 'case', which will do auto lineup in declarations
  or case-statements respectively. The word 'all' will do all
  lineups. '(case declaration) for instance will do lineup in
  case-statements and parameterlist, while '(all) will do all
  lineups." )

(defvar verilog-mode-abbrev-table nil
  "Abbrev table in use in Verilog-mode buffers.")

(defvar verilog-font-lock-keywords-after-1930
  '(
   ("^[ \t]*\\(function\\|task\\|module\\|macromodule\\|primitive\\)\\>[ \t]*"  
    1 font-lock-keyword-face) 
   ("^[ \t]*\\(function\\|task\\|module\\|macromodule\\|primitive\\)\\>[ \t]*\\(\\sw+\\)"  
    2 font-lock-function-name-face nil t)
   ("\\\\[^ \t]*" 0 'font-lock-function-name-face)  (
    "\\(@\\)\\|\\(#\[ \t\]*\\(\\(\[0-9\]+\\('[hdxbo][0-9_xz]*\\)?\\)\\|\\((\[^)\]*)\\)\\)\\)"
    0 font-lock-type-face)
   ("\\(`[ \t]*[A-Za-z][A-Za-z0-9_]*\\)"  0 font-lock-type-face)  
    ("\\<\\(in\\(teger\\|put\\|out\\)\\|parameter\\|defparam\\|output\\|supply[01]?\\|event\\|tri\\(0\\|1\\|reg\\|and\\|or\\)?\\|w\\(ire\\|or\\|and\\)\\|time\\|re\\(al\\(time\\)?\\|g\\)\\)\\>" 
     0 font-lock-type-face)  
    ("\\(\\$[a-zA-Z][a-zA-Z0-9_\\$]*\\)\\|\\(\\<\\(begin\\|case[xz]?\\|end\\(case\\|function\\|task\\|module\\|table\\|primitive\\|specify\\)?\\|a\\(ssign\\|lways\\)\\|default\\|initial\\|table\\|\\(pos\\|neg\\)edge\\|else\\|for\\(ever\\|k\\)?\\|join\\|if\\|repeat\\|then\\|while\\|specify\\)\\>\\)" 
     0 font-lock-keyword-face)
   )
)
(defvar verilog-font-lock-keywords nil)
(defvar verilog-font-lock-keywords-before-1930
  '(
    ("^[ \t]*\\(function\\|task\\|module\\|macromodule\\|primitive\\)\\>[ \t]*"  . 1)
    ("^[ \t]*\\(function\\|task\\|module\\|macromodule\\|primitive\\)\\>[ \t]*\\(\\sw+\\)"  
     2 font-lock-function-name-face nil t)
    ("\\(\\\\[^ \t]*\\)\\|\\(`[ \t]*[A-Za-z][A-Za-z0-9_]*\\)" 0 font-lock-function-name-face)
    ("[@#]" . font-lock-type-face)
    ("\\<\\(in\\(teger\\|put\\|out\\)\\|parameter\\|defparam\\|output\\|supply[01]?\\|event\\|tri\\(0\\|1\\|reg\\|and\\|or\\)?\\|w\\(ire\\|or\\|and\\)\\|time\\|re\\(al\\(time\\)?\\|g\\)\\)\\>" 
     0 font-lock-type-face)
    ("\\(\\$[a-zA-Z][a-zA-Z0-9_\\$]*\\)\\|\\(\\<\\(begin\\|case[xz]?\\|end\\(case\\|function\\|task\\|module\\|table\\|primitive\\|specify\\)?\\|a\\(ssign\\|lways\\)\\|default\\|initial\\|table\\|\\(pos\\|neg\\)edge\\|else\\|for\\(ever\\|k\\)?\\|join\\|if\\|repeat\\|then\\|while\\|specify\\)\\>\\)" . font-lock-keyword-face)
    )
)

(defvar verilog-imenu-generic-expression
  '("^[ \t]*\\(module\\|macromodule\\|primitive\\)[ \t\n]+\\([a-zA-Z0-9_.:]+\\)" . (2))
  "Imenu expression for Verilog-mode.  See `imenu-generic-expression'.")

(defvar verilog-mode-abbrev-table nil
  "Abbrev table in use in Verilog-mode buffers.")


(define-abbrev-table 'verilog-mode-abbrev-table ())

(defvar verilog-mode-map ()
  "Keymap used in Verilog mode.")
(if verilog-mode-map
    ()
  (setq verilog-mode-map (make-sparse-keymap))
  (define-key verilog-mode-map ";"        'electric-verilog-semi)
  (define-key verilog-mode-map ":"        'electric-verilog-colon)
  (define-key verilog-mode-map "="        'electric-verilog-equal)
  (define-key verilog-mode-map "\`"       'electric-verilog-tick)
  (define-key verilog-mode-map "\t"       'electric-verilog-tab)
  (define-key verilog-mode-map "\r"       'electric-verilog-terminate-line)
  (define-key verilog-mode-map "\M-\C-b"  'electric-verilog-backward-sexp)
  (define-key verilog-mode-map "\M-\C-f"  'electric-verilog-forward-sexp)
  (define-key verilog-mode-map "\M-\r"    (function (lambda ()
						      (interactive) (electric-verilog-terminate-line 1))))
  (define-key verilog-mode-map "\177"     'backward-delete-char-untabify)
  (define-key verilog-mode-map "\M-\t"    'verilog-complete-word)
  (define-key verilog-mode-map "\M-?"     'verilog-show-completions)
  (define-key verilog-mode-map "\M-\C-h"  'verilog-mark-defun)
  (define-key verilog-mode-map "\C-c\C-b" 'verilog-insert-block)
  (define-key verilog-mode-map "\C-cb"    'verilog-label-be)
  (define-key verilog-mode-map "\M-*"     'verilog-star-comment)
  (define-key verilog-mode-map "\C-c\C-c" 'verilog-comment-area)
  (define-key verilog-mode-map "\C-c\C-u" 'verilog-uncomment-area)
  (define-key verilog-mode-map "\M-\C-a"  'verilog-beg-of-defun)
  (define-key verilog-mode-map "\M-\C-e"  'verilog-end-of-defun)
  (define-key verilog-mode-map "\C-c\C-d" 'verilog-goto-defun)
  )


  
;;;
;;; Regular expressions used to calculate indent, etc.
;;;
(defconst verilog-symbol-re      "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>")
(defconst verilog-case-re        "\\(\\<case[xz]?\\>[^:]\\)")
;; Want to match
;; aa :
;; aa,bb :
;; a[34:32] :
;; a,
;;   b :
(defconst verilog-no-indent-begin-re "\\<\\(if\\|else\\|while\\|for\\|repeat\\|always\\)\\>")
(defconst verilog-endcomment-reason-re 
  (concat 
   "\\(\\<fork\\>\\)\\|\\(\\<begin\\>\\)\\|\\(\\<if\\>\\)\\|\\(\\<else\\>\\)\\|"
   "\\(\\<task\\>\\)\\|\\(\\<function\\>\\)\\|\\(\\<initial\\>\\)\\|\\(\\<always\\>\\(\[ \t\]*@\\)?\\)\\|"
   "\\(\\<while\\>\\)\\|\\(\\<for\\(ever\\)?\\>\\)\\|\\(\\<repeat\\>\\)\\|\\(\\<wait\\>\\)\\|"
   "#"))

(defconst verilog-named-block-re  "begin[ \t]*:")
(defconst verilog-beg-block-re   "\\<\\(begin\\|case\\|casex\\|casez\\|fork\\|table\\|specify\\)\\>")
(defconst verilog-beg-block-re-1 "\\<\\(begin\\)\\|\\(case[xz]?\\)\\|\\(fork\\)\\|\\(table\\)\\|\\(specify\\)\\|\\(function\\)\\|\\(task\\)\\>")
(defconst verilog-end-block-re   "\\<\\(end\\|join\\|endcase\\|endtable\\|endspecify\\)\\>")
(defconst verilog-end-block-re-1 "\\(\\<end\\>\\)\\|\\(\\<endcase\\>\\)\\|\\(\\<join\\>\\)\\|\\(\\<endtable\\>\\)\\|\\(\\<endspecify\\>\\)\\|\\(\\<endfunction\\>\\)\\|\\(\\<endtask\\>\\)")
(defconst verilog-declaration-re 
  (concat "\\(\\<in\\(put\\|out\\|teger\\)\\>\\|"
	  "\\<parameter\\>\\|\\<defparam\\>\\|\\<output\\>\\|\\<event\\>\\|"
	  "\\<re\\(al\\|g\\|altime\\)\\>\\|"
	  "\\<time\\>\\|\\<tri\\(0\\|1\\|and\\|or\\|reg\\)?\\>\\|"
	  "\\<supply[01]\\>\\|\\<w\\(and\\|or\\|ire\\)\\>\\)"))
(defconst verilog-declaration-re-1 (concat "^[ \t]*" verilog-declaration-re "[ \t]*\\(\\[[^]]*\\][ \t]*\\)?"))
(defconst verilog-defun-re       "\\<\\(module\\|macromodule\\|primitive\\)\\>")
(defconst verilog-end-defun-re   "\\<\\(endmodule\\|endprimitive\\)\\>")
(defconst verilog-zero-indent-re 
  (concat verilog-defun-re "\\|" verilog-end-defun-re))
(defconst verilog-directive-re
  "\\(`else\\)\\|\\(`ifdef\\)\\|\\(`endif\\)\\|\\(`define\\)\\|\\(`undef\\)\\|\\(`include\\)")
(defconst verilog-autoindent-lines-re
  (concat
   "\\<\\(\\(macro\\)?module\\|primitive\\|end\\(case\\|function\\|task\\|module\\|primitive\\|specify\\|table\\)?\\|join\\|begin\\|else\\)\\>\\|`\\(else\\|ifdef\\|endif\\)\\|"
   verilog-directive-re
   "\\>"))
(defconst verilog-behavorial-block-beg-re
  "\\(\\<initial\\>\\|\\<always\\>\\|\\<function\\>\\|\\<task\\>\\)")
(defconst verilog-indent-reg 
  (concat "\\(\\<begin\\>\\|\\<case[xz]?\\>[^:]\\|\\<specify\\>\\|\\<fork\\>\\|\\<table\\>\\)\\|"
	  "\\(\\<end\\>\\|\\<join\\>\\|\\<endcase\\>\\|\\<endtable\\>\\|\\<endspecify\\>\\)\\|" 
	  "\\(\\<module\\>\\|\\<macromodule\\>\\|\\<primitive\\>\\|\\<initial\\>\\|\\<always\\>\\)\\|"
	  "\\(\\<endmodule\\>\\|\\<endprimitive\\>\\)\\|"
	  "\\(\\<endtask\\>\\|\\<endfunction\\>\\)\\|"
	  "\\(\\<function\\>\\|\\<task\\>\\)"	  
;;	  "\\|\\(\\<if\\>\\|\\<else\\>\\)"
	  ))
(defconst verilog-complete-reg
  "\\(\\<always\\>\\)\\|\\(\\<repeat\\>\\)\\|\\(\\<case[xz]?\\>[^:]\\)\\|\\(\\<while\\>\\)\\|\\(\\<if\\>\\)\\|\\(\\<for\\(ever\\)?\\>\\)")
(defconst verilog-end-statement-re 
  (concat "\\(" verilog-beg-block-re "\\)\\|\\("
	  verilog-end-block-re "\\)"))
(defconst verilog-endcase-re 
  (concat verilog-case-re "\\|" 
	  "\\(endcase\\)\\|"
	  verilog-defun-re
	  ))
;;; Strings used to mark beginning and end of excluded text
(defconst verilog-exclude-str-start "/* -----\\/----- EXCLUDED -----\\/-----")
(defconst verilog-exclude-str-end " -----/\\----- EXCLUDED -----/\\----- */")

(defconst verilog-emacs-features
  (let ((major (and (boundp 'emacs-major-version)
		    emacs-major-version))
	(minor (and (boundp 'emacs-minor-version)
		    emacs-minor-version))
	flavor comments)
    ;; figure out version numbers if not already discovered
    (and (or (not major) (not minor))
	 (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
	 (setq major (string-to-int (substring emacs-version
					       (match-beginning 1)
					       (match-end 1)))
	       minor (string-to-int (substring emacs-version
					       (match-beginning 2)
					       (match-end 2)))))
    (if (not (and major minor))
	(error "Cannot figure out the major and minor version numbers."))
    ;; calculate the major version
    (cond
     ((= major 18) (setq major 'v18))	;Emacs 18
     ((= major 4)  (setq major 'v18))	;Epoch 4
     ((= major 19) (setq major 'v19	;Emacs 19
			 flavor (if (or (string-match "Lucid" emacs-version)
					(string-match "XEmacs" emacs-version))
				    'XEmacs 'FSF)))
     ((= major 20) (setq major 'v20	;XEmacs 20
			 flavor 'XEmacs))
     ;; I don't know
     (t (error "Cannot recognize major version number: %s" major)))
    ;; All XEmacs 19's (formerly Lucid) use 8-bit modify-syntax-entry
    ;; flags, as do all patched (obsolete) Emacs 19, Emacs 18,
    ;; Epoch 4's.  Only vanilla Emacs 19 uses 1-bit flag.  Lets be
    ;; as smart as we can about figuring this out.
    (if (or (eq major 'v20) (eq major 'v19))
	(let ((table (copy-syntax-table)))
	  (modify-syntax-entry ?a ". 12345678" table)
	  (cond
	   ;; XEmacs pre 20 and Emacs pre 19.30 use vectors for syntax tables.
	   ((vectorp table)
	    (if (= (logand (lsh (aref table ?a) -16) 255) 255)
		(setq comments '8-bit)
	      (setq comments '1-bit)))
	   ;; XEmacs 20 is known to be 8-bit
	   ((eq flavor 'XEmacs) (setq comments '8-bit))
	   ;; Emacs 19.30 and beyond are known to be 1-bit
	   ((eq flavor 'FSF) (setq comments '1-bit))
	   ;; Don't know what this is
	   (t (error "Couldn't figure out syntax table format."))
	   ))
      ;; Emacs 18 has no support for dual comments
      (setq comments 'no-dual-comments))
    ;; lets do some minimal sanity checking.
    (if (or
	 ;; Lemacs before 19.6 had bugs
	 (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
	 ;; Emacs 19 before 19.21 has known bugs
	 (and (eq major 'v19) (eq flavor 'FSF) (< minor 21))
	 )
	(with-output-to-temp-buffer "*verilog-mode warnings*"
	  (print (format
		  "The version of Emacs that you are running, %s,
has known bugs in its syntax parsing routines which will affect the
performance of verilog-mode. You should strongly consider upgrading to the
latest available version.  verilog-mode may continue to work, after a
fashion, but strange indentation errors could be encountered."
		  emacs-version))))
    ;; Emacs 18, with no patch is not too good
    (if (and (eq major 'v18) (eq comments 'no-dual-comments))
	(with-output-to-temp-buffer "*verilog-mode warnings*"
	  (print (format
		  "The version of Emacs 18 you are running, %s,
has known deficiencies in its ability to handle the dual verilog 
(and C++) comments, (e.g. the // and /* */ comments). This will
not be much of a problem for you if you only use the /* */ comments,
but you really should strongly consider upgrading to one of the latest 
Emacs 19's.  In Emacs 18, you may also experience performance degradations. 
Emacs 19 has some new built-in routines which will speed things up for you.
Because of these inherent problems, verilog-mode is not supported 
on emacs-18."
		  emacs-version))))
    ;; Emacs 18 with the syntax patches are no longer supported
    (if (and (eq major 'v18) (not (eq comments 'no-dual-comments)))
	(with-output-to-temp-buffer "*verilog-mode warnings*"
	  (print (format
		  "You are running a syntax patched Emacs 18 variant.  While this should
work for you, you may want to consider upgrading to Emacs 19.
The syntax patches are no longer supported either for verilog-mode."))))
    (list major comments))
  "A list of features extant in the Emacs you are using.
There are many flavors of Emacs out there, each with different
features supporting those needed by verilog-mode.  Here's the current
supported list, along with the values for this variable:

 Vanilla Emacs 18/Epoch 4:   (v18 no-dual-comments)
 Emacs 18/Epoch 4 (patch2):  (v18 8-bit)
 XEmacs (formerly Lucid) 19: (v19 8-bit)
 Emacs 19:                   (v19 1-bit).")

(defconst verilog-comment-start-regexp "//\\|/\\*"
  "Dual comment value for `comment-start-regexp'.")

(defun verilog-populate-syntax-table (table)
  ;; Populate the syntax TABLE
  ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
  (modify-syntax-entry ?\\ "\\" table)
  (modify-syntax-entry ?+ "." table)
  (modify-syntax-entry ?- "." table)
  (modify-syntax-entry ?= "." table)
  (modify-syntax-entry ?% "." table)
  (modify-syntax-entry ?< "." table)
  (modify-syntax-entry ?> "." table)
  (modify-syntax-entry ?& "." table)
  (modify-syntax-entry ?| "." table)
  (modify-syntax-entry ?_ "w" table)
  (modify-syntax-entry ?\' "." table)
)

(defun verilog-setup-dual-comments (table)
  ;; Set up TABLE to handle block and line style comments
  (cond
   ((memq '8-bit verilog-emacs-features)
    ;; XEmacs (formerly Lucid) has the best implementation
    (modify-syntax-entry ?/  ". 1456" table)
    (modify-syntax-entry ?*  ". 23"   table)
    (modify-syntax-entry ?\n "> b"    table)
    ;; Give CR the same syntax as newline, for selective-display
    (modify-syntax-entry ?\^m "> b"    table))
   ((memq '1-bit verilog-emacs-features)
    ;; Emacs 19 does things differently, but we can work with it
    (modify-syntax-entry ?/  ". 124b" table)
    (modify-syntax-entry ?*  ". 23"   table)
    (modify-syntax-entry ?\n "> b"    table)
    ;; Give CR the same syntax as newline, for selective-display
    (modify-syntax-entry ?\^m "> b"   table))
   ))

(defvar verilog-mode-syntax-table nil
  "Syntax table used in verilog-mode buffers.")
(if verilog-mode-syntax-table
    ()
  (setq verilog-mode-syntax-table (make-syntax-table))
  (verilog-populate-syntax-table verilog-mode-syntax-table)
  ;; add extra comment syntax
  (verilog-setup-dual-comments verilog-mode-syntax-table)
  )
;;;
;;;  Macros
;;;

(defsubst verilog-re-search-forward (REGEXP BOUND NOERROR)
  "Like re-search-forward, but skips over matches in comments or strings"
  (set-match-data '(nil nil))    
  (while (and
	  (re-search-forward REGEXP BOUND NOERROR)
	  (and (verilog-skip-forward-comment-or-string)
	       (progn 
		 (store-match-data '(nil nil))
		 (if BOUND
		     (< (point) BOUND)
		   t)
		 )
	       )
	  )
    )
  (match-end 0))

(defsubst verilog-re-search-backward (REGEXP BOUND NOERROR)
  "Like re-search-backward, but skips over matches in comments or strings"
  (set-match-data '(nil nil))
  (while (and
	  (re-search-backward REGEXP BOUND NOERROR)
	  (verilog-skip-backward-comment-or-string)
	  (not (set-match-data '(nil nil))))
    ())
  (match-end 0))

(defsubst verilog-get-beg-of-line (&optional arg)
  (save-excursion
    (beginning-of-line arg)
    (point)))

(defsubst verilog-get-end-of-line (&optional arg)
  (save-excursion
    (end-of-line arg)
    (point)))

(defun verilog-declaration-end ()
  (search-forward ";"))

(defun electric-verilog-backward-sexp ()
  "Move backward over a sexp"
  (interactive)
  ;; before that see if we are in a comment
  (verilog-backward-sexp)
)
(defun electric-verilog-forward-sexp ()
  "Move backward over a sexp"
  (interactive)
  ;; before that see if we are in a comment
  (verilog-forward-sexp)
)

(defun verilog-backward-sexp ()
  (let ((reg)
	(elsec 1)
	(found nil)
	)
    (if (not (looking-at "\\<"))
	(forward-word -1))
    (cond
     ((verilog-skip-backward-comment-or-string)
      )
     ((looking-at "\\<else\\>")
      (setq reg (concat
		 verilog-end-block-re
		 "\\|\\(\\<else\\>\\)"
		 "\\|\\(\\<if\\>\\)"
		 ))
      (while (and (not found)
		  (verilog-re-search-backward reg nil 'move))
	(cond 
	 ((match-end 1) ; endblock
					; try to leap back to matching outward block by striding across
					; indent level changing tokens then immediately
					; previous line governs indentation.
	  (verilog-leap-to-head)
	  )
	 ((match-end 2) ; else, we're in deep
	  (setq elsec (1+ elsec))				 
	  )
	 ((match-end 3) ; found it
	  (setq elsec (1- elsec))
	  (if (= 0 elsec)
	      ;; Now previous line describes syntax
	      (setq found 't)
	    ))
	 )
	)
      )
     ((looking-at verilog-end-block-re-1);; end|join|endcase|endtable|endspecify
      (verilog-leap-to-head)
      )
     ((looking-at "\\(endmodule\\>\\)\\|\\(\\<endprimitive\\>\\)")
      (cond
       ((match-end 1)
	(verilog-re-search-backward "\\<\\(macro\\)?module\\>" nil 'move))
       ((match-end 2)
	(verilog-re-search-backward "\\<primitive\\>" nil 'move))
       (t 
	(backward-sexp 1))))
     (t
      (backward-sexp))
     ) ;; cond
    )
  )
(defun verilog-forward-sexp ()
  (let ((reg)
	(st (point)))
    (if (not (looking-at "\\<"))
	(forward-word -1))
    (cond
     ((verilog-skip-forward-comment-or-string)
      (verilog-forward-syntactic-ws)
      )
     ((looking-at verilog-beg-block-re-1);; begin|fork|case|table|specify
      (cond 
       ((match-end 1) ; end
	;; Search forward for matching begin
	(setq reg "\\(\\<begin\\>\\)\\|\\(\\<end\\>\\)" )
	)
       ((match-end 2) ; endcase
	;; Search forward for matching case
	(setq reg "\\(\\<case[xz]?\\>[^:]\\)\\|\\(\\<endcase\\>\\)" )
	)
       ((match-end 3) ; join
	;; Search forward for matching fork
	(setq reg "\\(\\<fork\\>\\)\\|\\(\\<join\\>\\)" )
	)
       ((match-end 4) ; endtable
	;; Search forward for matching table
	(setq reg "\\(\\<table\\>\\)\\|\\(\\<endtable\\>\\)" )
	)
       ((match-end 5) ; endspecify
	;; Search forward for matching specify
	(setq reg "\\(\\<specify\\>\\)\\|\\(\\<endspecify\\>\\)" )
	)
       ((match-end 6) ; endfunction
	;; Search forward for matching function
	(setq reg "\\(\\<function\\>\\)\\|\\(\\<endfunction\\>\\)" )
	)
       ((match-end 7) ; endspecify
	;; Search forward for matching task
	(setq reg "\\(\\<task\\>\\)\\|\\(\\<endtask\\>\\)" )
	)
       )
      (if (forward-word 1)
	  (catch 'skip
	    (let ((nest 1))
	      (while (verilog-re-search-forward reg nil 'move)
		(cond 
		 ((match-end 2) ; end
		  (setq nest (1- nest))
		  (if (= 0 nest)
		      (throw 'skip 1)))
		 ((match-end 1) ; begin
		  (setq nest (1+ nest)))))
	      )
	    )
	)
      )
     ((looking-at "\\(\\<\\(macro\\)?module\\>\\)\\|\\(\\<primitive\\>\\)")
      (cond
       ((match-end 1)
	(verilog-re-search-forward "\\<endmodule\\>" nil 'move))
       ((match-end 2)
	(verilog-re-search-forward "\\<endprimitive\\>" nil 'move))
       (t 
	(goto-char st)
	(if (= (following-char) ?\) )
	    (forward-char 1)
	  (forward-sexp 1)))))
     (t
      (goto-char st)
      (if (= (following-char) ?\) )
	  (forward-char 1)
	(forward-sexp 1)))
     ) ;; cond
    )
  )


(defun verilog-declaration-beg ()
  (verilog-re-search-backward verilog-declaration-re (bobp) t))
  
(defsubst verilog-within-string ()
  (save-excursion
    (nth 3 (parse-partial-sexp (verilog-get-beg-of-line) (point)))))


;;;###autoload
(defun verilog-mode ()
"Major mode for editing Verilog code. \\<verilog-mode-map>
NEWLINE, TAB indents for Verilog code.  
Delete converts tabs to spaces as it moves back.
Supports highlighting.

Variables controlling indentation/edit style:

 verilog-indent-level           (default 3)
    Indentation of Verilog statements with respect to containing block.
 verilog-cexp-indent            (default 1)
    Indentation of Verilog statements broken across lines.
 verilog-case-indent            (default 2)
    Indentation for case statements.
 verilog-auto-newline           (default nil)
    Non-nil means automatically newline after simcolons and the punctation mark
    after an end.
 verilog-auto-indent-on-newline (default t)
    Non-nil means automatically indent line after newline
 verilog-tab-always-indent      (default t)
    Non-nil means TAB in Verilog mode should always reindent the current line,
    regardless of where in the line point is when the TAB command is used.
 verilog-indent-begin-after-if  (default t)
    Non-nil means to indent begin statements following a preceeding
    if, else, while, for and repeat statements, if any. otherwise,
    the begin is lined up with the preceeding token. If t, you get:
      if (a)
         begin
    otherwise you get:
      if (a)
      begin
 verilog-auto-endcomments       (default t)
    Non-nil means a comment /* ... */ is set after the ends which ends cases, tasks, functions and modules.
    The type and name of the object will be set between the braces.
 verilog-auto-lineup            (default `(all))
    List of contexts where auto lineup of :'s or ='s should be done.

Turning on Verilog mode calls the value of the variable verilog-mode-hook with
no args, if that value is non-nil.
Other useful functions are:
\\[verilog-complete-word]\t-complete word with appropriate possibilities (functions, verilog keywords...)
\\[verilog-comment-area]\t- Put marked area in a comment, fixing nested comments.
\\[verilog-uncomment-area]\t- Uncomment an area commented with \
\\[verilog-comment-area].
\\[verilog-insert-block]\t- insert begin ... end;
\\[verilog-star-comment]\t- insert /* ... */
\\[verilog-mark-defun]\t- Mark function.
\\[verilog-beg-of-defun]\t- Move to beginning of current function.
\\[verilog-end-of-defun]\t- Move to end of current function.
\\[verilog-label-be]\t- Label matching begin ... end, fork ... join and case ... endcase statements;
"
  (interactive)
  (kill-all-local-variables)
  (use-local-map verilog-mode-map)
  (setq major-mode 'verilog-mode)
  (setq mode-name "Verilog")
  (setq local-abbrev-table verilog-mode-abbrev-table)
  (set-syntax-table verilog-mode-syntax-table)
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'verilog-indent-line)
  (setq comment-indent-function 'verilog-indent-comment)
  (make-local-variable 'parse-sexp-ignore-comments)
  (setq parse-sexp-ignore-comments nil)
  (make-local-variable 'comment-start)
  (make-local-variable 'comment-end)
  (make-local-variable 'comment-multi-line)
  (make-local-variable 'comment-start-skip)
  (setq comment-start "// "
	comment-end ""
	comment-start-skip "/\\*+ *\\|// *"
	comment-multi-line nil)
  ;; Imenu support
  (make-local-variable 'imenu-generic-expression)
  (setq imenu-generic-expression verilog-imenu-generic-expression)
  ;; Font lock support
  (make-local-variable 'font-lock-keywords)
  (if (string-match "XEmacs\\|Lucid" emacs-version)
      (setq verilog-font-lock-keywords verilog-font-lock-keywords-after-1930 )
    (cond ((> emacs-minor-version 29)
	   (setq verilog-font-lock-keywords verilog-font-lock-keywords-after-1930 ))
	  ('t 	 
	   (setq verilog-font-lock-keywords verilog-font-lock-keywords-before-1930 ))
	  ))
  (setq font-lock-keywords verilog-font-lock-keywords)
  (run-hooks 'verilog-mode-hook))


;;;
;;;  Electric functions
;;;
(defun electric-verilog-terminate-line (&optional arg)
  "Terminate line and indent next line."
  (interactive)
  ;; before that see if we are in a comment
  (let ((state 
	 (save-excursion
	   (parse-partial-sexp (point-min) (point)))))
    (cond
     ((nth 7 state)			; Inside // comment
      (if (eolp)
	  (progn
	    (delete-horizontal-space)
	    (newline))
	(progn 
	  (newline)
	  (insert-string "// ")
	  (beginning-of-line)
	  ))
      (verilog-indent-line)
      )
     ((nth 4 state)			; Inside any comment (hence /**/)
      (newline)
      (beginning-of-line)

