changeset 20665:5d82beffb498

Initial revision
author Karl Heuer <kwzh@gnu.org>
date Sun, 18 Jan 1998 03:39:09 +0000
parents a3e36554a095
children 7e740edb4d52
files lisp/progmodes/vhdl-mode.el
diffstat 1 files changed, 6116 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/progmodes/vhdl-mode.el	Sun Jan 18 03:39:09 1998 +0000
@@ -0,0 +1,6116 @@
+;;; vhdl-mode.el --- major mode for editing VHDL code
+
+;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+
+;; Authors:       Reto Zimmermann             <mailto:Reto.Zimmermann@iaeth.ch>
+;;                                          <http://www.iis.ee.ethz.ch/~zimmi/>
+;;                Rodney J. Whitby               <mailto:rwhitby@geocities.com>
+;;                          <http://www.geocities.com/SiliconValley/Park/8287/>
+;; Maintainer:    vhdl-mode@geocities.com
+;; Maintainers' Version:       3.19
+;; Keywords:      languages vhdl
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; ############################################################################
+;;; Commentary:
+;; ############################################################################
+
+;; This package provides an Emacs major mode for editing VHDL code.
+;; It includes the following features:
+
+;;   - Highlighting of VHDL syntax
+;;   - Indentation based on versatile syntax analysis
+;;   - Template insertion (electrification) for most VHDL constructs
+;;   - Insertion of customizable VHDL file headers
+;;   - Word completion (dynamic abbreviations)
+;;   - Menu containing all VHDL Mode commands
+;;   - Index menu (jump index to main units and blocks in a file)
+;;   - Source file menu (menu of all source files in current directory)
+;;   - Source file compilation (syntax analysis)
+;;   - Postscript printing with fontification
+;;   - Lower and upper case keywords
+;;   - Hiding blocks of code
+;;   - Alignment functions
+;;   - Easy customization
+;;   - Works under GNU Emacs and XEmacs
+
+;; ############################################################################
+;; Usage
+;; ############################################################################
+
+;; see below (comment in vhdl-mode function) or type `C-c C-h' in Emacs.
+
+;; ############################################################################
+;; Emacs Versions
+;; ############################################################################
+
+;; - Emacs 20
+;; - XEmacs 19.15
+;; - This version does not support Emacs 19 (use VHDL Mode 3.10 instead)
+
+
+;; ############################################################################
+;; Acknowledgements
+;; ############################################################################
+
+;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
+;; and Steve Grout
+
+;; Fontification approach suggested by Ken Wood <ken@eda.com.au>
+;; Source file menu suggested by Michael Laajanen <mila@enea.se>
+;; Ideas about alignment from John Wiegley <johnw@borland.com>
+
+;; Many thanks to all the users who sent me bug reports and enhancement
+;; requests.
+;; Special thanks go to Dan Nicolaescu <done@ece.arizona.edu> for reviewing
+;; the code and for his valuable hints.
+
+;;; Code:
+
+;; ############################################################################
+;; User definable variables
+;; ############################################################################
+
+;; ############################################################################
+;; Variables for customization
+
+(defgroup vhdl nil
+  "Customizations for VHDL Mode."
+  :prefix "vhdl-"
+  :group 'languages)
+
+
+(defgroup vhdl-mode nil
+  "Customizations for modes."
+  :group 'vhdl)
+
+(defcustom vhdl-electric-mode t
+  "*If non-nil, electrification (automatic template generation) is enabled.
+If nil, template generators can still be invoked through key bindings
+and menu. Can be toggled by `\\[vhdl-electric-mode]'."
+  :type 'boolean
+  :group 'vhdl-mode)
+
+(defcustom vhdl-stutter-mode t
+  "*If non-nil, stuttering is enabled.
+Can be toggled by `\\[vhdl-stutter-mode]'."
+  :type 'boolean
+  :group 'vhdl-mode)
+
+(defcustom vhdl-indent-tabs-mode t
+  "*Indentation can insert tabs if this is non-nil.
+Overrides local variable `indent-tabs-mode'."
+  :type 'boolean
+  :group 'vhdl-mode)
+
+
+(defgroup vhdl-compile nil
+  "Customizations for compilation."
+  :group 'vhdl)
+
+(defcustom vhdl-compiler 'v-system
+  "*VHDL compiler to be used for syntax analysis.
+  cadence       Cadence Design Systems (`cv -file')
+  ikos          Ikos Voyager (`analyze')
+  quickhdl      QuickHDL, Mentor Graphics (`qvhcom')
+  synopsys      Synopsys, VHDL Analyzer (`vhdlan')
+  vantage       Vantage Analysis Systems (`analyze -libfile vsslib.ini -src')
+  viewlogic     Viewlogic (`analyze -libfile vsslib.ini -src')
+  v-system      V-System, Model Technology (`vcom')
+For incorporation of additional compilers, please send me their command syntax
+and some example error messages."
+  :type '(choice
+	  (const cadence)
+	  (const ikos)
+	  (const quickhdl)
+	  (const synopsys)
+	  (const vantage)
+	  (const viewlogic)
+	  (const v-system)
+	  )
+  :group 'vhdl-compile)
+
+(defcustom vhdl-compiler-options ""
+  "*Options to be added to the compile command."
+  :type 'string
+  :group 'vhdl-compile)
+
+
+(defgroup vhdl-style nil
+  "Customizations for code styles."
+  :group 'vhdl)
+
+(defcustom vhdl-basic-offset 4
+  "*Amount of basic offset used for indentation.
+This value is used by + and - symbols in `vhdl-offsets-alist'."
+  :type 'integer
+  :group 'vhdl-style)
+
+
+(defgroup vhdl-word-case nil
+  "Customizations for case of VHDL words."
+  :group 'vhdl-style)
+
+(defcustom vhdl-upper-case-keywords nil
+  "*If non-nil, keywords are converted to upper case
+when typed or by the fix case functions."
+  :type 'boolean
+  :group 'vhdl-word-case)
+
+(defcustom vhdl-upper-case-types nil
+  "*If non-nil, standardized types are converted to upper case
+by the fix case functions."
+  :type 'boolean
+  :group 'vhdl-word-case)
+
+(defcustom vhdl-upper-case-attributes nil
+  "*If non-nil, standardized attributes are converted to upper case
+by the fix case functions."
+  :type 'boolean
+  :group 'vhdl-word-case)
+
+(defcustom vhdl-upper-case-enum-values nil
+  "*If non-nil, standardized enumeration values are converted to upper case
+by the fix case functions."
+  :type 'boolean
+  :group 'vhdl-word-case)
+
+
+(defgroup vhdl-electric nil
+  "Customizations for comments."
+  :group 'vhdl)
+
+(defcustom vhdl-auto-align nil
+  "*If non-nil, some templates are automatically aligned after generation."
+  :type 'boolean
+  :group 'vhdl-electric)
+
+(defcustom vhdl-additional-empty-lines t
+  "*If non-nil, additional empty lines are inserted in some templates.
+This improves readability of code."
+  :type 'boolean
+  :group 'vhdl-electric)
+
+(defcustom vhdl-argument-list-indent t
+  "*If non-nil, argument lists are indented relative to the opening paren.
+Normal indentation is applied otherwise."
+  :type 'boolean
+  :group 'vhdl-electric)
+
+(defcustom vhdl-conditions-in-parenthesis nil
+  "*If non-nil, parenthesis are placed around condition expressions."
+  :type 'boolean
+  :group 'vhdl-electric)
+
+(defcustom vhdl-date-format 'scientific
+  "*Specifies date format to be used in header.
+Date formats are:
+  american (09/17/1997)
+  european (17.09.1997)
+  scientific (1997/09/17)"
+  :type '(choice (const american)
+                 (const european)
+                 (const scientific))
+  :group 'vhdl-electric)
+
+(defcustom vhdl-header-file nil
+  "*Pathname/filename of the file to be inserted as header.
+If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
+if the header needs to be version controlled.
+
+The following keywords for template generation are supported:
+  <filename>   : replaced by the name of the buffer
+  <author>     : replaced by the user name and email address
+  <date>       : replaced by the current date
+  <... string> : replaced by a prompted string (... is the prompt word)
+  <cursor>     : final cursor position
+
+Example:
+  -----------------------------------------
+  -- Title       : <title string>
+  -- File        : <filename>
+  -- Author      : <author>
+  -- Created     : <date>
+  -- Description : <cursor>
+  -----------------------------------------"
+  :type 'string
+  :group 'vhdl-electric)
+
+(defcustom vhdl-modify-date-prefix-string "-- Last modified : "
+  "*Prefix string of modification date in VHDL file header.
+If actualization of the modification date is called (menu, `\\[vhdl-modify]'),
+this string is searched and the rest of the line replaced by the current date."
+  :type 'string
+  :group 'vhdl-electric)
+
+(defcustom vhdl-zero-string "'0'"
+  "*String to use for a logic zero."
+  :type 'string
+  :group 'vhdl-electric)
+
+(defcustom vhdl-one-string "'1'"
+  "*String to use for a logic one."
+  :type 'string
+  :group 'vhdl-electric)
+
+
+(defgroup vhdl-comment nil
+  "Customizations for comments."
+  :group 'vhdl-electric)
+
+(defcustom vhdl-self-insert-comments t
+  "*If non-nil, variables templates automatically insert help comments."
+  :type 'boolean
+  :group 'vhdl-comment)
+
+(defcustom vhdl-prompt-for-comments t
+  "*If non-nil, various templates prompt for user definable comments."
+  :type 'boolean
+  :group 'vhdl-comment)
+
+(defcustom vhdl-comment-column 40
+  "*Column to indent right-margin comments to.
+Overrides local variable `comment-column'."
+  :type 'integer
+  :group 'vhdl-comment)
+
+(defcustom vhdl-end-comment-column 79
+  "*End of comment column."
+  :type 'integer
+  :group 'vhdl-comment)
+
+(defvar end-comment-column 79
+  "*End of comment column.")
+
+
+(defgroup vhdl-highlight nil
+  "Customizations for highlighting."
+  :group 'vhdl)
+
+(defcustom vhdl-highlight-names t
+  "*If non-nil, unit names, subprogram names, and labels are highlighted."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-highlight-keywords t
+  "*If non-nil, VHDL keywords and other predefined words are highlighted.
+That is, keywords, predefined types, predefined attributes, and predefined
+enumeration values are highlighted."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-highlight-signals nil
+  "*If non-nil, signals of different classes are highlighted using colors.
+Signal classes are: clock, reset, status/control, data, and test."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-highlight-case-sensitive nil
+  "*If non-nil, case is considered for highlighting.
+Possible trade-off:
+  non-nil  also upper-case VHDL words are highlighted, but case of signal names
+           is not considered (may lead to highlighting of unwanted words),
+  nil      only lower-case VHDL words are highlighted, but case of signal names
+           is considered.
+Overrides local variable `font-lock-keywords-case-fold-search'."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-use-default-colors nil
+  "*If non-nil, the default colors are taken for syntax highlighting.
+If nil, all colors are customized in VHDL Mode for better matching with the
+additional signal colors."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-use-default-faces nil
+  "*If non-nil, the default faces are taken for syntax highlighting.
+If nil, all faces are customized for better matching with the additional faces
+used in VHDL Mode. This variable comes only into effect if no colors are used
+for highlighting or printing (i.e. variable `ps-print-color-p' is nil)."
+  :type 'boolean
+  :group 'vhdl-highlight)
+
+
+(defgroup vhdl-signal-syntax nil
+  "Customizations of signal syntax for highlighting."
+  :group 'vhdl-highlight)
+
+(defcustom vhdl-signal-syntax-doc-string "
+Must be of the form \"\\ \<\\\(...\\\)\\\>\", where ... specifies the actual syntax.
+   (delete this space ^ , it's only a workaround to get this doc string.)
+The basic regexp elements are:
+  [A-Z]    any upper case letter
+  [A-Za-z] any letter
+  [0-9]    any digit
+  \\w       any letter or digit (corresponds to [A-Za-z0-9])
+  [XY]     letter \"X\" or \"Y\"
+  [^XY]    neither letter \"X\" nor \"Y\"
+  x        letter \"x\"
+  *        postfix operator for matching previous regexp element any times
+  +        postfix operator for matching previous regexp element at least once
+  ?        postfix operator for matching previous regexp element at most once"
+  "Common document string used for the custom variables below. Must be
+defined as custom variable due to a bug in XEmacs.")
+
+(defcustom vhdl-clock-signal-syntax "\\<\\([A-Z]\\w*xC\\w*\\)\\>"
+  (concat
+   "*Regular expression (regexp) for syntax of clock signals."
+   vhdl-signal-syntax-doc-string)
+  :type 'regexp
+  :group 'vhdl-signal-syntax)
+
+(defcustom vhdl-reset-signal-syntax "\\<\\([A-Z]\\w*xR\\w*\\)\\>"
+  (concat
+   "*Regular expression (regexp) for syntax of (asynchronous) reset signals."
+   vhdl-signal-syntax-doc-string)
+  :type 'regexp
+  :group 'vhdl-signal-syntax)
+
+(defcustom vhdl-control-signal-syntax "\\<\\([A-Z]\\w*x[IS]\\w*\\)\\>"
+  (concat
+   "*Regular expression (regexp) for syntax of status/control signals."
+   vhdl-signal-syntax-doc-string)
+  :type 'regexp
+  :group 'vhdl-signal-syntax)
+
+(defcustom vhdl-data-signal-syntax "\\<\\([A-Z]\\w*xD\\w*\\)\\>"
+  (concat
+   "*Regular expression (regexp) for syntax of data signals."
+   vhdl-signal-syntax-doc-string)
+  :type 'regexp
+  :group 'vhdl-signal-syntax)
+
+(defcustom vhdl-test-signal-syntax "\\<\\([A-Z]\\w*xT\\w*\\)\\>"
+  (concat
+   "*Regular expression (regexp) for syntax of test signals."
+   vhdl-signal-syntax-doc-string)
+  :type 'regexp
+  :group 'vhdl-signal-syntax)
+
+
+(defgroup vhdl-menu nil
+  "Customizations for menues."
+  :group 'vhdl)
+
+(defcustom vhdl-source-file-menu t
+  "*If non-nil, a menu of all source files in the current directory is created."
+  :type 'boolean
+  :group 'vhdl-menu)
+
+(defcustom vhdl-index-menu t
+  "*If non-nil, an index menu for the current source file is created."
+  :type 'boolean
+  :group 'vhdl-menu)
+
+(defcustom vhdl-hideshow-menu (not (string-match "XEmacs" emacs-version))
+  "*If non-nil, hideshow menu and functionality is added.
+Hideshow allows hiding code of VHDL processes and blocks.
+(Does not work under XEmacs.)"
+  :type 'boolean
+  :group 'vhdl-menu)
+
+
+(defgroup vhdl-print nil
+  "Customizations for printing."
+  :group 'vhdl)
+
+(defcustom vhdl-print-two-column t
+  "*If non-nil, code is printed in two columns and landscape format."
+  :type 'boolean
+  :group 'vhdl-print)
+
+
+(defgroup vhdl-misc nil
+  "Miscellaneous customizations."
+  :group 'vhdl)
+
+(defcustom vhdl-intelligent-tab t
+  "*If non-nil, `TAB' does indentation, word completion, and tab insertion.
+That is, if preceeding character is part of a word then complete word,
+else if not at beginning of line then insert tab,
+else if last command was a `TAB' or `RET' then dedent one step,
+else indent current line (i.e. `TAB' is bound to `vhdl-tab').
+If nil, TAB always indents current line (i.e. `TAB' is bound to
+`vhdl-indent-line')."
+  :type 'boolean
+  :group 'vhdl-misc)
+
+(defcustom vhdl-template-key-binding-prefix "\C-t"
+  "*`C-c' plus this key gives the key binding prefix for all VHDL templates.
+Default key binding prefix for templates is `C-c C-t' (example: architecture
+`C-c C-t a'). If you have no own `C-c LETTER' bindings, you can shorten the
+template key binding prefix to `C-c' (example: architecture `C-c a') by
+assigning the empty character (\"\") to this variable. The syntax to enter
+control keys is \"\\C-t\"."
+  :type 'sexp
+  :group 'vhdl-misc)
+
+(defcustom vhdl-word-completion-in-minibuffer t
+  "*If non-nil, word completion works in minibuffer (for template prompts)."
+  :type 'boolean
+  :group 'vhdl-misc)
+
+(defcustom vhdl-underscore-is-part-of-word nil
+  "*If non-nil, the underscore character `_' is considered as part of word.
+An identifier containing underscores is then treated as a single word in
+select and move operations. All parts of an identifier separated by underscore
+are treated as single words otherwise."
+  :type 'boolean
+  :group 'vhdl-misc)
+
+;; ############################################################################
+;; Other variables
+
+(defvar vhdl-inhibit-startup-warnings-p nil
+  "*If non-nil, inhibits start up compatibility warnings.")
+
+(defvar vhdl-strict-syntax-p nil
+  "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
+If the syntactic symbol for a particular line does not match a symbol
+in the offsets alist, an error is generated, otherwise no error is
+reported and the syntactic symbol is ignored.")
+
+(defvar vhdl-echo-syntactic-information-p nil
+  "*If non-nil, syntactic info is echoed when the line is indented.")
+
+(defconst vhdl-offsets-alist-default
+  '((string                . -1000)
+    (block-open            . 0)
+    (block-close           . 0)
+    (statement             . 0)
+    (statement-cont        . vhdl-lineup-statement-cont)
+    (statement-block-intro . +)
+    (statement-case-intro  . +)
+    (case-alternative      . +)
+    (comment               . vhdl-lineup-comment)
+    (arglist-intro         . +)
+    (arglist-cont          . 0)
+    (arglist-cont-nonempty . vhdl-lineup-arglist)
+    (arglist-close         . vhdl-lineup-arglist)
+    (entity                . 0)
+    (configuration         . 0)
+    (package               . 0)
+    (architecture          . 0)
+    (package-body          . 0)
+    )
+  "Default settings for offsets of syntactic elements.
+Do not change this constant!  See the variable `vhdl-offsets-alist' for
+more information.")
+
+(defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
+  "*Association list of syntactic element symbols and indentation offsets.
+As described below, each cons cell in this list has the form:
+
+    (SYNTACTIC-SYMBOL . OFFSET)
+
+When a line is indented, vhdl-mode first determines the syntactic
+context of the line by generating a list of symbols called syntactic
+elements.  This list can contain more than one syntactic element and
+the global variable `vhdl-syntactic-context' contains the context list
+for the line being indented.  Each element in this list is actually a
+cons cell of the syntactic symbol and a buffer position.  This buffer
+position is call the relative indent point for the line.  Some
+syntactic symbols may not have a relative indent point associated with
+them.
+
+After the syntactic context list for a line is generated, vhdl-mode
+calculates the absolute indentation for the line by looking at each
+syntactic element in the list.  First, it compares the syntactic
+element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'.  When it
+finds a match, it adds the OFFSET to the column of the relative indent
+point.  The sum of this calculation for each element in the syntactic
+list is the absolute offset for line being indented.
+
+If the syntactic element does not match any in the `vhdl-offsets-alist',
+an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
+the element is ignored.
+
+Actually, OFFSET can be an integer, a function, a variable, or one of
+the following symbols: `+', `-', `++', or `--'.  These latter
+designate positive or negative multiples of `vhdl-basic-offset',
+respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
+called with a single argument containing the cons of the syntactic
+element symbol and the relative indent point.  The function should
+return an integer offset.
+
+Here is the current list of valid syntactic element symbols:
+
+ string                 -- inside multi-line string
+ block-open             -- statement block open
+ block-close            -- statement block close
+ statement              -- a VHDL statement
+ statement-cont         -- a continuation of a VHDL statement
+ statement-block-intro  -- the first line in a new statement block
+ statement-case-intro   -- the first line in a case alternative block
+ case-alternative       -- a case statement alternative clause
+ comment                -- a line containing only a comment
+ arglist-intro          -- the first line in an argument list
+ arglist-cont           -- subsequent argument list lines when no
+                           arguments follow on the same line as the
+                           the arglist opening paren
+ arglist-cont-nonempty  -- subsequent argument list lines when at
+                           least one argument follows on the same
+                           line as the arglist opening paren
+ arglist-close          -- the solo close paren of an argument list
+ entity                 -- inside an entity declaration
+ configuration          -- inside a configuration declaration
+ package                -- inside a package declaration
+ architecture           -- inside an architecture body
+ package-body           -- inside a package body
+")
+
+(defvar vhdl-comment-only-line-offset 0
+  "*Extra offset for line which contains only the start of a comment.
+Can contain an integer or a cons cell of the form:
+
+ (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
+
+Where NON-ANCHORED-OFFSET is the amount of offset given to
+non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
+the amount of offset to give column-zero anchored comment-only lines.
+Just an integer as value is equivalent to (<val> . 0)")
+
+(defvar vhdl-special-indent-hook nil
+  "*Hook for user defined special indentation adjustments.
+This hook gets called after a line is indented by the mode.")
+
+(defvar vhdl-style-alist
+  '(("IEEE"
+     (vhdl-basic-offset . 4)
+     (vhdl-offsets-alist . ())
+     )
+    )
+  "Styles of Indentation.
+Elements of this alist are of the form:
+
+  (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
+
+where STYLE-STRING is a short descriptive string used to select a
+style, VARIABLE is any vhdl-mode variable, and VALUE is the intended
+value for that variable when using the selected style.
+
+There is one special case when VARIABLE is `vhdl-offsets-alist'.  In this
+case, the VALUE is a list containing elements of the form:
+
+  (SYNTACTIC-SYMBOL . VALUE)
+
+as described in `vhdl-offsets-alist'.  These are passed directly to
+`vhdl-set-offset' so there is no need to set every syntactic symbol in
+your style, only those that are different from the default.")
+
+;; dynamically append the default value of most variables
+(or (assoc "Default" vhdl-style-alist)
+    (let* ((varlist '(vhdl-inhibit-startup-warnings-p
+		      vhdl-strict-syntax-p
+		      vhdl-echo-syntactic-information-p
+		      vhdl-basic-offset
+		      vhdl-offsets-alist
+		      vhdl-comment-only-line-offset))
+	   (default (cons "Default"
+			  (mapcar
+			   (function
+			    (lambda (var)
+			      (cons var (symbol-value var))
+			      ))
+			   varlist))))
+      (setq vhdl-style-alist (cons default vhdl-style-alist))))
+
+(defvar vhdl-mode-hook nil
+  "*Hook called by `vhdl-mode'.")
+
+
+;; ############################################################################
+;; Emacs variant handling
+;; ############################################################################
+
+;; active regions
+
+(defun vhdl-keep-region-active ()
+  ;; do whatever is necessary to keep the region active in XEmacs
+  ;; (formerly Lucid). ignore byte-compiler warnings you might see
+  (and (boundp 'zmacs-region-stays)
+       (setq zmacs-region-stays t)))
+
+(defconst vhdl-emacs-features
+  (let ((major (and (boundp 'emacs-major-version)
+		    emacs-major-version))
+	(minor (and (boundp 'emacs-minor-version)
+		    emacs-minor-version))
+	flavor)
+    ;; 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 (cond
+				 ((string-match "Win-Emacs" emacs-version)
+				  'Win-Emacs)
+				 ((or (string-match "Lucid" emacs-version)
+				      (string-match "XEmacs" emacs-version))
+				  'XEmacs)
+				 (t
+				  t))))
+     ((= major 20) (setq major 'v20	;Emacs 20
+			 flavor (cond
+				 ((string-match "Win-Emacs" emacs-version)
+				  'Win-Emacs)
+				 ((or (string-match "Lucid" emacs-version)
+				      (string-match "XEmacs" emacs-version))
+				  'XEmacs)
+				 (t
+				  t))))
+     ;; I don't know
+     (t (error "Cannot recognize major version number: %s" major)))
+    ;; lets do some minimal sanity checking.
+    (if (and (or
+	      ;; Emacs 18 is brain dead
+	      (eq major 'v18)
+	      ;; Lemacs before 19.6 had bugs
+	      (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
+	      ;; Emacs 19 before 19.21 had bugs
+	      (and (eq major 'v19) (eq flavor t) (< minor 21)))
+	     (not vhdl-inhibit-startup-warnings-p))
+	(with-output-to-temp-buffer "*vhdl-mode warnings*"
+	  (print (format
+"The version of Emacs that you are running, %s,
+has known bugs in its syntax.c parsing routines which will affect the
+performance of vhdl-mode. You should strongly consider upgrading to the
+latest available version.  vhdl-mode may continue to work, after a
+fashion, but strange indentation errors could be encountered."
+		     emacs-version))))
+    (list major flavor))
+  "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 vhdl-mode.  Here's the current
+supported list, along with the values for this variable:
+
+ Emacs 18/Epoch 4:           (v18)
+ XEmacs (formerly Lucid) 19: (v19 XEmacs)
+ Win-Emacs 1.35:             (V19 Win-Emacs)
+ Emacs 19:               (v19 t)
+ Emacs 20:               (v20 t).")
+
+
+;; ############################################################################
+;; Bindings
+;; ############################################################################
+
+;; ############################################################################
+;; Key bindings
+
+(defvar vhdl-template-map ()
+  "Keymap for VHDL templates.")
+
+(if vhdl-template-map ()
+  (setq vhdl-template-map (make-sparse-keymap))
+  ;; key bindings for VHDL templates
+  (define-key vhdl-template-map "\M-A" 'vhdl-alias)
+  (define-key vhdl-template-map "a"    'vhdl-architecture)
+  (define-key vhdl-template-map "A"    'vhdl-array)
+  (define-key vhdl-template-map "\M-a" 'vhdl-assert)
+  (define-key vhdl-template-map "b"    'vhdl-block)
+  (define-key vhdl-template-map "c"    'vhdl-case)
+  (define-key vhdl-template-map "\M-c" 'vhdl-component)
+  (define-key vhdl-template-map "I"    'vhdl-component-instance)
+  (define-key vhdl-template-map "\M-s" 'vhdl-concurrent-signal-assignment)
+  (define-key vhdl-template-map "\M-Cb"'vhdl-block-configuration)
+  (define-key vhdl-template-map "\M-Cc"'vhdl-component-configuration)
+  (define-key vhdl-template-map "\M-Cd"'vhdl-configuration-decl)
+  (define-key vhdl-template-map "\M-Cs"'vhdl-configuration-spec)
+  (define-key vhdl-template-map "C"    'vhdl-constant)
+  (define-key vhdl-template-map "d"    'vhdl-disconnect)
+  (define-key vhdl-template-map "\M-e" 'vhdl-else)
+  (define-key vhdl-template-map "E"    'vhdl-elsif)
+  (define-key vhdl-template-map "e"    'vhdl-entity)
+  (define-key vhdl-template-map "x"    'vhdl-exit)
+  (define-key vhdl-template-map "f"    'vhdl-for)
+  (define-key vhdl-template-map "F"    'vhdl-function)
+  (define-key vhdl-template-map "g"    'vhdl-generate)
+  (define-key vhdl-template-map "G"    'vhdl-generic)
+  (define-key vhdl-template-map "h"    'vhdl-header)
+  (define-key vhdl-template-map "i"    'vhdl-if)
+  (define-key vhdl-template-map "L"    'vhdl-library)
+  (define-key vhdl-template-map "l"    'vhdl-loop)
+  (define-key vhdl-template-map "m"    'vhdl-modify)
+  (define-key vhdl-template-map "M"    'vhdl-map)
+  (define-key vhdl-template-map "n"    'vhdl-next)
+  (define-key vhdl-template-map "k"    'vhdl-package)
+  (define-key vhdl-template-map "("    'vhdl-paired-parens)
+  (define-key vhdl-template-map "\M-p" 'vhdl-port)
+  (define-key vhdl-template-map "p"    'vhdl-procedure)
+  (define-key vhdl-template-map "P"    'vhdl-process)
+  (define-key vhdl-template-map "R"    'vhdl-record)
+  (define-key vhdl-template-map "r"    'vhdl-return-value)
+  (define-key vhdl-template-map "\M-S" 'vhdl-selected-signal-assignment)
+  (define-key vhdl-template-map "s"    'vhdl-signal)
+  (define-key vhdl-template-map "S"    'vhdl-subtype)
+  (define-key vhdl-template-map "t"    'vhdl-type)
+  (define-key vhdl-template-map "u"    'vhdl-use)
+  (define-key vhdl-template-map "v"    'vhdl-variable)
+  (define-key vhdl-template-map "W"    'vhdl-wait)
+  (define-key vhdl-template-map "w"    'vhdl-while-loop)
+  (define-key vhdl-template-map "\M-w" 'vhdl-with)
+  (define-key vhdl-template-map "\M-W" 'vhdl-clocked-wait)
+  (define-key vhdl-template-map "Kb"   'vhdl-package-numeric-bit)
+  (define-key vhdl-template-map "Kn"   'vhdl-package-numeric-std)
+  (define-key vhdl-template-map "Ks"   'vhdl-package-std-logic-1164)
+  (define-key vhdl-template-map "Kt"   'vhdl-package-textio)
+  )
+
+(defvar vhdl-mode-map ()
+  "Keymap for VHDL Mode.")
+
+(if vhdl-mode-map ()
+  (setq vhdl-mode-map (make-sparse-keymap))
+  ;; key bindings for templates
+  (define-key vhdl-mode-map
+    (concat "\C-c" vhdl-template-key-binding-prefix) vhdl-template-map)
+  ;; standard key bindings
+  (define-key vhdl-mode-map "\M-a"     'vhdl-beginning-of-statement)
+  (define-key vhdl-mode-map "\M-e"     'vhdl-end-of-statement)
+  (define-key vhdl-mode-map "\M-\C-f"  'vhdl-forward-sexp)
+  (define-key vhdl-mode-map "\M-\C-b"  'vhdl-backward-sexp)
+  (define-key vhdl-mode-map "\M-\C-u"  'vhdl-backward-up-list)
+  ;(define-key vhdl-mode-map "\M-\C-d"	'vhdl-down-list)
+  (define-key vhdl-mode-map "\M-\C-a"  'vhdl-beginning-of-defun)
+  (define-key vhdl-mode-map "\M-\C-e"  'vhdl-end-of-defun)
+  (define-key vhdl-mode-map "\M-\C-h"  'vhdl-mark-defun)
+  (define-key vhdl-mode-map "\M-\C-q"  'vhdl-indent-sexp)
+  (define-key vhdl-mode-map "\177"     'backward-delete-char-untabify)
+  (define-key vhdl-mode-map "\r"       'vhdl-return)
+  (if vhdl-intelligent-tab
+      (define-key vhdl-mode-map "\t"       'vhdl-tab)
+    (define-key vhdl-mode-map "\t"       'vhdl-indent-line))
+  (define-key vhdl-mode-map " "        'vhdl-outer-space)
+  ;; new key bindings for VHDL Mode, with no counterpart to BOCM
+  (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
+  (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
+  (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
+  (define-key vhdl-mode-map "\C-c\C-f" 'font-lock-fontify-buffer)
+  (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
+  (define-key vhdl-mode-map "\C-c\C-r" 'vhdl-regress-line)
+  (define-key vhdl-mode-map "\C-c\C-i" 'vhdl-indent-line)
+  (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-noindent-region)
+  (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-comment-region)
+  (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
+  (define-key vhdl-mode-map "\C-c-"    'vhdl-inline-comment)
+  (define-key vhdl-mode-map "\C-c\M--" 'vhdl-display-comment-line)
+  (define-key vhdl-mode-map "\C-c\C-o" 'vhdl-open-line)
+  (define-key vhdl-mode-map "\C-c\C-g" 'goto-line)
+  (define-key vhdl-mode-map "\C-c\C-d" 'vhdl-kill-line)
+  (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-help)
+  (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
+  (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-submit-bug-report)
+  (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
+  (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
+  (define-key vhdl-mode-map "\M-\t"    'tab-to-tab-stop)
+  ;; key bindings for stuttering
+  (define-key vhdl-mode-map "-"        'vhdl-stutter-mode-dash)
+  (define-key vhdl-mode-map "'"        'vhdl-stutter-mode-quote)
+  (define-key vhdl-mode-map ";"        'vhdl-stutter-mode-semicolon)
+  (define-key vhdl-mode-map "["        'vhdl-stutter-mode-open-bracket)
+  (define-key vhdl-mode-map "]"        'vhdl-stutter-mode-close-bracket)
+  (define-key vhdl-mode-map "."        'vhdl-stutter-mode-period)
+  (define-key vhdl-mode-map ","        'vhdl-stutter-mode-comma)
+  (let ((c 97))
+    (while (< c 123) ; for little a-z
+      (define-key vhdl-mode-map (char-to-string c) 'vhdl-stutter-mode-caps)
+      (setq c (1+ c))
+      ))
+  )
+
+;; define special minibuffer keymap for enabling word completion in minibuffer
+;; (useful in template generator prompts)
+(defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
+  "Keymap for minibuffer used in VHDL Mode.")
+
+(define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab)
+
+(defvar vhdl-mode-syntax-table nil
+  "Syntax table used in vhdl-mode buffers.")
+
+(if vhdl-mode-syntax-table ()
+  (setq vhdl-mode-syntax-table (make-syntax-table))
+  ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
+  ;; why not? (is left to the user here)
+  (if vhdl-underscore-is-part-of-word
+      (modify-syntax-entry ?_ "w"     vhdl-mode-syntax-table))
+  (modify-syntax-entry ?\" "\""    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\$ "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\% "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\& "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\' "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\( "()"    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\) ")("    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\* "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\+ "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\. "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\/ "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\: "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\; "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\< "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\= "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\> "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\[ "(]"    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\\ "\\"    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\] ")["    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\{ "(}"    vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\| "."     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\} "){"    vhdl-mode-syntax-table)
+  ;; add comment syntax
+  (modify-syntax-entry ?\- ". 12"  vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\n ">"     vhdl-mode-syntax-table)
+  (modify-syntax-entry ?\^M ">"    vhdl-mode-syntax-table))
+
+(defvar vhdl-syntactic-context nil
+  "Buffer local variable containing syntactic analysis list.")
+(make-variable-buffer-local 'vhdl-syntactic-context)
+
+;; ############################################################################
+;; Abbrev hook bindings
+
+(defvar vhdl-mode-abbrev-table nil
+  "Abbrev table in use in vhdl-mode buffers.")
+
+(define-abbrev-table 'vhdl-mode-abbrev-table
+  '(
+    ("--" "" vhdl-display-comment-hook 0)
+    ("abs" "" vhdl-default-hook 0)
+    ("access" "" vhdl-default-hook 0)
+    ("after" "" vhdl-default-hook 0)
+    ("alias" "" vhdl-alias-hook 0)
+    ("all" "" vhdl-default-hook 0)
+    ("and" "" vhdl-default-hook 0)
+    ("arch" "" vhdl-architecture-hook 0)
+    ("architecture" "" vhdl-architecture-hook 0)
+    ("array" "" vhdl-array-hook 0)
+    ("assert" "" vhdl-assert-hook 0)
+    ("attr" "" vhdl-attribute-hook 0)
+    ("attribute" "" vhdl-attribute-hook 0)
+    ("begin" "" vhdl-default-indent-hook 0)
+    ("block" "" vhdl-block-hook 0)
+    ("body" "" vhdl-default-hook 0)
+    ("buffer" "" vhdl-default-hook 0)
+    ("bus" "" vhdl-default-hook 0)
+    ("case" "" vhdl-case-hook 0)
+    ("comp" "" vhdl-component-hook 0)
+    ("component" "" vhdl-component-hook 0)
+    ("conc" "" vhdl-concurrent-signal-assignment-hook 0)
+    ("concurrent" "" vhdl-concurrent-signal-assignment-hook 0)
+    ("conf" "" vhdl-configuration-hook 0)
+    ("configuration" "" vhdl-configuration-hook 0)
+    ("cons" "" vhdl-constant-hook 0)
+    ("constant" "" vhdl-constant-hook 0)
+    ("disconnect" "" vhdl-disconnect-hook 0)
+    ("downto" "" vhdl-default-hook 0)
+    ("else" "" vhdl-else-hook 0)
+    ("elseif" "" vhdl-elsif-hook 0)
+    ("elsif" "" vhdl-elsif-hook 0)
+    ("end" "" vhdl-default-indent-hook 0)
+    ("entity" "" vhdl-entity-hook 0)
+    ("exit" "" vhdl-exit-hook 0)
+    ("file" "" vhdl-default-hook 0)
+    ("for" "" vhdl-for-hook 0)
+    ("func" "" vhdl-function-hook 0)
+    ("function" "" vhdl-function-hook 0)
+    ("gen" "" vhdl-generate-hook 0)
+    ("generate" "" vhdl-generate-hook 0)
+    ("generic" "" vhdl-generic-hook 0)
+    ("group" "" vhdl-default-hook 0)
+    ("guarded" "" vhdl-default-hook 0)
+    ("header" "" vhdl-header-hook 0)
+    ("if" "" vhdl-if-hook 0)
+    ("impure" "" vhdl-default-hook 0)
+    ("in" "" vhdl-default-hook 0)
+    ("inertial" "" vhdl-default-hook 0)
+    ("inout" "" vhdl-default-hook 0)
+    ("inst" "" vhdl-component-instance-hook 0)
+    ("instance" "" vhdl-component-instance-hook 0)
+    ("is" "" vhdl-default-hook 0)
+    ("label" "" vhdl-default-hook 0)
+    ("library" "" vhdl-library-hook 0)
+    ("linkage" "" vhdl-default-hook 0)
+    ("literal" "" vhdl-default-hook 0)
+    ("loop" "" vhdl-loop-hook 0)
+    ("map" "" vhdl-map-hook 0)
+    ("mod" "" vhdl-default-hook 0)
+    ("modify" "" vhdl-modify-hook 0)
+    ("nand" "" vhdl-default-hook 0)
+    ("new" "" vhdl-default-hook 0)
+    ("next" "" vhdl-next-hook 0)
+    ("nor" "" vhdl-default-hook 0)
+    ("not" "" vhdl-default-hook 0)
+    ("null" "" vhdl-default-hook 0)
+    ("of" "" vhdl-default-hook 0)
+    ("on" "" vhdl-default-hook 0)
+    ("open" "" vhdl-default-hook 0)
+    ("or" "" vhdl-default-hook 0)
+    ("others" "" vhdl-default-hook 0)
+    ("out" "" vhdl-default-hook 0)
+    ("pack" "" vhdl-package-hook 0)
+    ("package" "" vhdl-package-hook 0)
+    ("port" "" vhdl-port-hook 0)
+    ("postponed" "" vhdl-default-hook 0)
+    ("procedure" "" vhdl-procedure-hook 0)
+    ("process" "" vhdl-process-hook 0)
+    ("pure" "" vhdl-default-hook 0)
+    ("range" "" vhdl-default-hook 0)
+    ("record" "" vhdl-record-hook 0)
+    ("register" "" vhdl-default-hook 0)
+    ("reject" "" vhdl-default-hook 0)
+    ("rem" "" vhdl-default-hook 0)
+    ("report" "" vhdl-default-hook 0)
+    ("ret" "" vhdl-return-hook 0)
+    ("return" "" vhdl-return-hook 0)
+    ("rol" "" vhdl-default-hook 0)
+    ("ror" "" vhdl-default-hook 0)
+    ("select" "" vhdl-selected-signal-assignment-hook 0)
+    ("severity" "" vhdl-default-hook 0)
+    ("shared" "" vhdl-default-hook 0)
+    ("sig" "" vhdl-signal-hook 0)
+    ("signal" "" vhdl-signal-hook 0)
+    ("sla" "" vhdl-default-hook 0)
+    ("sll" "" vhdl-default-hook 0)
+    ("sra" "" vhdl-default-hook 0)
+    ("srl" "" vhdl-default-hook 0)
+    ("sub" "" vhdl-subtype-hook 0)
+    ("subtype" "" vhdl-subtype-hook 0)
+    ("then" "" vhdl-default-hook 0)
+    ("to" "" vhdl-default-hook 0)
+    ("transport" "" vhdl-default-hook 0)
+    ("type" "" vhdl-type-hook 0)
+    ("unaffected" "" vhdl-default-hook 0)
+    ("units" "" vhdl-default-hook 0)
+    ("until" "" vhdl-default-hook 0)
+    ("use" "" vhdl-use-hook 0)
+    ("var" "" vhdl-variable-hook 0)
+    ("variable" "" vhdl-variable-hook 0)
+    ("wait" "" vhdl-wait-hook 0)
+    ("warning" "" vhdl-default-hook 0)
+    ("when" "" vhdl-when-hook 0)
+    ("while" "" vhdl-while-loop-hook 0)
+    ("with" "" vhdl-selected-signal-assignment-hook 0)
+    ("xnor" "" vhdl-default-hook 0)
+    ("xor" "" vhdl-default-hook 0)
+    ))
+
+
+;; ############################################################################
+;; Menues
+;; ############################################################################
+
+;; ############################################################################
+;; VHDL menu (using `easy-menu.el')
+
+;; `customize-menu-create' is included in `cus-edit.el' version 1.9954,
+;; which is not yet distributed with XEmacs 19.15
+(defun vhdl-customize-menu-create (symbol &optional name)
+  "Return a customize menu for customization group SYMBOL.
+If optional NAME is given, use that as the name of the menu.
+Otherwise the menu will be named `Customize'.
+The format is suitable for use with `easy-menu-define'."
+  (unless name
+    (setq name "Customize"))
+  (if (memq 'XEmacs vhdl-emacs-features)
+      ;; We can delay it under XEmacs.
+      `(,name
+        :filter (lambda (&rest junk)
+                  (cdr (custom-menu-create ',symbol))))
+    ;; But we must create it now under Emacs.
+    (cons name (cdr (custom-menu-create symbol)))))
+
+(defvar vhdl-mode-menu
+  (append
+  '("VHDL"
+    ("Mode"
+     ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
+     ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
+     )
+    "--"
+    ("Compile"
+     ["Compile Buffer" vhdl-compile t]
+     ["Stop Compilation" kill-compilation t]
+     "--"
+     ["Make" vhdl-make t]
+     ["Generate Makefile" vhdl-generate-makefile t]
+     "--"
+     ["Next Error" next-error t]
+     ["Previous Error" previous-error t]
+     ["First Error" first-error t]
+     )
+    "--"
+    ("Template"
+     ("VHDL Construct 1"
+      ["Alias" vhdl-alias t]
+      ["Architecture" vhdl-architecture t]
+      ["Array" vhdl-array t]
+      ["Assert" vhdl-assert t]
+      ["Attribute" vhdl-attribute t]
+      ["Block" vhdl-block t]
+      ["Case" vhdl-case t]
+      ["Component" vhdl-component t]
+      ["Concurrent (Signal Asst)" vhdl-concurrent-signal-assignment t]
+      ["Configuration (Block)" vhdl-block-configuration t]
+      ["Configuration (Comp)" vhdl-component-configuration t]
+      ["Configuration (Decl)" vhdl-configuration-decl t]
+      ["Configuration (Spec)" vhdl-configuration-spec t]
+      ["Constant" vhdl-constant t]
+      ["Disconnect" vhdl-disconnect t]
+      ["Else" vhdl-else t]
+      ["Elsif" vhdl-elsif t]
+      ["Entity" vhdl-entity t]
+      ["Exit" vhdl-exit t]
+      ["For (Loop)" vhdl-for t]
+      ["Function" vhdl-function t]
+      ["(For/If) Generate" vhdl-generate t]
+      ["Generic" vhdl-generic t]
+      )
+     ("VHDL Construct 2"
+      ["If" vhdl-if t]
+      ["Instance" vhdl-component-instance t]
+      ["Library" vhdl-library t]
+      ["Loop" vhdl-loop t]
+      ["Map" vhdl-map t]
+      ["Next" vhdl-next t]
+      ["Package" vhdl-package t]
+      ["Port" vhdl-port t]
+      ["Procedure" vhdl-procedure t]
+      ["Process" vhdl-process t]
+      ["Record" vhdl-record t]
+      ["Return" vhdl-return-value t]
+      ["Select" vhdl-selected-signal-assignment t]
+      ["Signal" vhdl-signal t]
+      ["Subtype" vhdl-subtype t]
+      ["Type" vhdl-type t]
+      ["Use" vhdl-use t]
+      ["Variable" vhdl-variable t]
+      ["Wait" vhdl-wait t]
+      ["(Clocked Wait)" vhdl-clocked-wait t]
+      ["When" vhdl-when t]
+      ["While (Loop)" vhdl-while-loop t]
+      ["With" vhdl-with t]
+      )
+     ("Standard Package"
+      ["numeric_bit" vhdl-package-numeric-bit t]
+      ["numeric_std" vhdl-package-numeric-std t]
+      ["std_logic_1164" vhdl-package-std-logic-1164 t]
+      ["textio" vhdl-package-textio t]
+      )
+     ["Header" vhdl-header t]
+     ["Modify (Date)" vhdl-modify t]
+     )
+    ("Comment"
+     ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
+     ["Insert Inline Comment" vhdl-inline-comment t]
+     ["Insert Horizontal Line" vhdl-display-comment-line t]
+     ["Insert Display Comment" vhdl-display-comment t]
+     ["Fill Comment" fill-paragraph t]
+     ["Fill Comment Region" fill-region (mark)]
+     )
+    ("Indent"
+     ["Line" vhdl-indent-line t]
+     ["Region" indent-region (mark)]
+     ["Buffer" vhdl-indent-buffer t]
+     )
+    ("Align"
+     ["Region" vhdl-align-noindent-region (mark)]
+     ["Comment Region" vhdl-align-comment-region (mark)]
+     )
+    ("Line"
+     ["Open" vhdl-open-line t]
+     ["Delete" vhdl-kill-line t]
+     ["Join" delete-indentation t]
+     ["Goto" goto-line t]
+     )
+    ("Move"
+     ["Forward Statement" vhdl-end-of-statement t]
+     ["Backward Statement" vhdl-beginning-of-statement t]
+     ["Forward Expression" vhdl-forward-sexp t]
+     ["Backward Expression" vhdl-backward-sexp t]
+     ["Forward Function" vhdl-end-of-defun t]
+     ["Backward Function" vhdl-beginning-of-defun t]
+     )
+     "--"
+    ("Fix Case"
+     ["Buffer" vhdl-fix-case-buffer t]
+     ["Region" vhdl-fix-case-region (mark)]
+     )
+    ["Fontify Buffer" font-lock-fontify-buffer t]
+    ["Syntactic Info" vhdl-show-syntactic-information t]
+     "--"
+    ["Help" vhdl-help t]
+    ["Version" vhdl-version t]
+    ["Bug Report" vhdl-submit-bug-report t]
+     "--"
+    )
+  (list (vhdl-customize-menu-create 'vhdl))
+))
+
+(require 'easymenu)
+
+;; ############################################################################
+;; Index menu (using `imenu.el')
+
+(defvar vhdl-imenu-generic-expression
+  '(
+    ("Entity"
+     "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Architecture"
+     "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Configuration"
+     "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Package Body"
+     "^\\s-*\\(package body\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Package"
+     "^\\s-*\\(package\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Type"
+     "^\\s-*\\(sub\\)?type\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Component"
+     "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Function / Procedure"
+     "^\\s-*\\(procedure\\|function\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
+     2)
+    ("Process / Block"
+     "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(process\\|block\\)"
+     1)
+    ("Instance"
+     "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
+     1)
+    )
+  "Imenu generic expression for VHDL Mode.  See `imenu-generic-expression'.")
+
+(defun vhdl-add-index-menu ()
+  (make-local-variable 'imenu-generic-expression)
+  (setq imenu-generic-expression vhdl-imenu-generic-expression)
+  (imenu-add-to-menubar "Index"))
+
+;; ############################################################################
+;; Source file menu (using `easy-menu.el')
+
+(defvar vhdl-extlist '("[A-Za-z0-9_.]*.vhdl?$"))
+(defvar vhdl-filelist-menu nil)
+
+(defun vhdl-add-source-files-menu ()
+  "Scan directory of current source file for all VHDL source files, and
+generate menu."
+  (interactive)
+  (message "Scanning directory for source files ...")
+  (let (filelist menulist tmpextlist found
+		 (newmap (current-local-map)))
+    (cd (file-name-directory (buffer-file-name)))
+    ;; find files
+    (setq menulist '())
+    (setq tmpextlist vhdl-extlist)
+    (while tmpextlist
+      (setq filelist (nreverse (directory-files
+				(file-name-directory (buffer-file-name))
+				nil (car tmpextlist) nil)))
+      ;; Create list for menu
+      (setq found nil)
+      (while filelist
+	(setq found t)
+	(setq menulist (cons (vector (car filelist)
+				     (list 'find-file (car filelist)) t)
+			     menulist))
+	(setq filelist (cdr filelist)))
+      (setq menulist (vhdl-menu-split menulist 25))
+      (if found
+	  (setq menulist (cons "--" menulist)))
+      (setq tmpextlist (cdr tmpextlist)))
+    (setq menulist (cons ["*Rescan*" vhdl-add-source-files-menu t] menulist))
+    (setq menulist (cons "Sources" menulist))
+    ;; Create menu
+    (easy-menu-add menulist)
+    (easy-menu-define vhdl-filelist-menu newmap
+		      "VHDL source files menu" menulist)
+;    (use-local-map (append (current-local-map) newmap))
+;    (use-local-map newmap)
+    )
+  (message ""))
+
+(defun vhdl-menu-split (list n)
+  "Split menu into several submenues, if number of elements > n."
+  (if (> (length list) n)
+      (let ((remain list)
+	    (result '())
+	    (sublist '())
+	    (menuno 1)
+	    (i 0))
+	(while remain
+	  (setq sublist (cons (car remain) sublist))
+	  (setq remain (cdr remain))
+	  (setq i (+ i 1))
+	  (if (= i n)
+	      (progn
+		(setq result (cons (cons (format "Sources %s" menuno)
+					 (nreverse sublist)) result))
+		(setq i 0)
+		(setq menuno (+ menuno 1))
+		(setq sublist '()))))
+	(and sublist
+	     (setq result (cons (cons (format "Sources %s" menuno)
+				      (nreverse sublist)) result)))
+	(nreverse result))
+    list))
+
+
+;; ############################################################################
+;; VHDL Mode definition
+;; ############################################################################
+
+(defun vhdl-mode ()
+  "Major mode for editing VHDL code.
+
+Usage:
+------
+
+- TEMPLATE INSERTION (electrification) (`\\[vhdl-outer-space]'): After typing
+  a VHDL keyword and entering `\\[vhdl-outer-space]', you are prompted for
+  arguments while a template is generated for that VHDL construct. Typing
+  `\\[vhdl-return]' (or `\\[keyboard-quit]' in yes-no queries) at the first
+  prompt aborts the current template generation. Typing `\\[just-one-space]'
+  after a keyword inserts a space without calling the template generator.
+  Automatic calling of the template generators (i.e. electrification) can be
+  disabled (enabled) by setting the variable `vhdl-electric-mode' to nil
+  (non-nil) or by typing `\\[vhdl-electric-mode]' (toggles electrification
+  mode).
+  Template generators can be called using the VHDL menu, the key bindings, or
+  by typing the keyword (first word of menu entry not in parenthesis) and
+  `\\[vhdl-outer-space]'. The following abbreviations can also be used:
+  arch, attr, conc, conf, comp, cons, func, inst, pack, ret, sig, sub, var.
+
+- HEADER INSERTION (`\\[vhdl-header]'): A customized header can be inserted
+  including the actual file name, user name, and current date as well as
+  prompted title strings. A custom header can be defined in a separate file
+  (see custom variable `vhdl-header-file').
+
+- STUTTERING (double strike): Double striking of some keys inserts cumbersome
+  VHDL syntax elements. Stuttering can be disabled by variable
+  `vhdl-stutter-mode' and be toggled by typing `\\[vhdl-stutter-mode]'.
+      ''   -->  \"             [   -->  (        --    -->  comment
+      ;;   -->  \" : \"         [[  -->  [        --CR  -->  comment-out code
+      ;;;  -->  \" := \"        ]   -->  )        ---   -->  horizontal line
+      ..   -->  \" => \"        ]]  -->  ]        ----  -->  display comment
+      ,,   -->  \" <= \"        aa  -->  A    -   zz  -->  Z
+
+- WORD COMPLETION (`\\[vhdl-tab]'): Typing `\\[vhdl-tab]' after a (not
+  completed) word looks for a word in the buffer that starts alike and
+  inserts it. Re-typing `\\[vhdl-tab]' toggles through alternative word
+  completions. This also works in the minibuffer (i.e. in template generator
+  prompts).
+
+  Typing `\\[vhdl-tab]' after a non-word character indents the line if at the
+  beginning of a line (i.e. no preceding non-blank characters), and inserts a
+  tabulator stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator
+  stop.
+
+- COMMENTS (`--', `---', `----', `--CR'):
+      `--'       puts a single comment.
+      `---'      draws a horizontal line for separating code segments.
+      `----'     inserts a display comment, i.e. two horizontal lines with a
+                 comment in between.
+      `--CR'     comments out code on that line. Re-hitting CR comments out
+                 following lines.
+      `\\[vhdl-comment-uncomment-region]'  comments out a region if not
+                 commented out, uncomments out a region if already
+                 commented out.
+
+  You are prompted for comments after object definitions (i.e. signals,
+  variables, constants, ports) and after subprogram and process specifications
+  if variable `vhdl-prompt-for-comments' is non-nil. Comments are
+  automatically inserted as additional labels (e.g. after begin statements)
+  and help comments if `vhdl-self-insert-comments' is non-nil.
+  Inline comments (i.e. comments after a piece of code on the same line) are
+  indented at least to `vhdl-comment-column'. Comments go at maximum to
+  `vhdl-end-comment-column'. `\\[vhdl-return]' after a space in a comment will
+  open a new comment line. Typing beyond `vhdl-end-comment-column' in a
+  comment automatically opens a new comment line. `\\[fill-paragraph]'
+  re-fills multi-line comments.
+
+- INDENTATION: `\\[vhdl-tab]' indents a line if at the beginning of the line.
+  The amount of indentation is specified by variable `vhdl-basic-offset'.
+  `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB'
+  if variable `vhdl-intelligent-tab' is nil). Indentation can be done for
+  an entire region (`\\[indent-region]') or buffer (menu). Argument and
+  port lists are indented normally (nil) or relative to the opening
+  parenthesis (non-nil) according to variable `vhdl-argument-list-indent'.
+  If variable `vhdl-indent-tabs-mode' is nil, spaces are used instead of tabs.
+  `\\[tabify]' and `\\[untabify]' allow to convert spaces to tabs and vice
+  versa.
+
+- ALIGNMENT: `\\[vhdl-align-noindent-region]' aligns port maps, signal and
+  variable assignments, inline comments, some keywords, etc., on consecutive
+  lines relative to each other within a defined region.
+  `\\[vhdl-align-comment-region]' only aligns inline comments (i.e. comments
+  that are at the end of a line of code). Some templates are automatically
+  aligned after generation if custom variable `vhdl-auto-align' is non-nil.
+
+- KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in menu).
+
+- VHDL MENU: All commands can be called from the VHDL menu.
+
+- INDEX MENU: For each VHDL source file, an index of the contained entities,
+  architectures, packages, procedures, processes, etc., is created as a menu.
+  Selecting a meny entry causes the cursor to jump to the corresponding
+  position in the file. Controlled by variable `vhdl-index-menu'.
+
+- SOURCE FILE MENU: A menu containing all VHDL source files in the directory
+  of the current file is generated. Selecting a menu entry loads the file.
+  Controlled by variable `vhdl-source-file-menu'.
+
+- SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
+  by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be
+  used is defined by variable `vhdl-compiler'. Currently supported are
+  `cadence', `ikos', `quickhdl', `synopsys', `vantage', `viewlogic', and
+  `v-system'. Not all compilers are tested. Please contact me for
+  incorporating additional VHDL compilers. An entire hierarchy of source
+  files can be compiled by the `make' command (menu, `\\[vhdl-make]').
+  This only works if an appropriate `Makefile' exists. Compiler options can
+  be defined by variable `vhdl-compiler-options'.
+
+- KEYWORD CASE: Lower and upper case for keywords, predefined types, predefined
+  attributes, and predefined enumeration values is supported. If the variable
+  `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in
+  lower case and are converted into upper case automatically (not for types,
+  attributes, and enumeration values). The case of keywords, types,
+  attributes, and enumeration values can be fixed for an entire region (menu)
+  or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
+  `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
+
+- HIGHLIGHTING (fontification): Keywords, predefined types, predefined
+  attributes, and predefined enumeration values (controlled by variable
+  `vhdl-highlight-keywords'), as well as comments, strings, and template
+  prompts are highlighted using different colors. Unit and subprogram names
+  as well as labels are highlighted if variable `vhdl-highlight-names' is
+  non-nil. The default colors from `font-lock.el' are used if variable
+  `vhdl-use-default-colors' is non-nil. Otherwise, an optimized set of colors
+  is taken, which uses bright colors for signals and muted colors for
+  everything else. Variable `vhdl-use-default-faces' does the same on
+  monochrome monitors.
+
+  Signal highlighting allows distinction between clock, reset,
+  status/control, data, and test signals according to some signal
+  naming convention. Their syntax is defined by variables
+  `vhdl-{clock,reset,control,data,test}-signal-syntax'. Signal coloring
+  is controlled by the variable `vhdl-highlight-signals'. The default
+  signal naming convention is as follows:
+
+  Signal attributes:
+      C  clock                   S  control and status
+      R  asynchronous reset      D  data and address
+      I  synchronous reset       T  test
+
+  Syntax:
+      signal name  ::=  \"[A-Z][a-zA-Z0-9]*x[CRISDT][a-zA-Z0-9]*\"
+      signal identifier -^^^^^^^^^^^^^^^^^
+      delimiter --------------------------^
+      above signal attributes -------------^^^^^^^^
+      additional attributes -----------------------^^^^^^^^^^^^
+
+  (`x' is used as delimiter because `_' is reserved by the VITAL standard.)
+  Examples: ClkxCfast, ResetxRB, ClearxI, SelectDataxS, DataxD, ScanEnablexT.
+
+  If all VHDL words are written in lower case (i.e. variables
+  `vhdl-upper-case-{keywords,types,attributes,enum-values}' are set to nil),
+  make highlighting case sensitive by setting variable
+  `vhdl-highlight-case-sensitive' to non-nil. This way, only names fulfilling
+  the above signal syntax including case are highlighted.
+
+- HIDE/SHOW: The code of entire VHDL processes or blocks can be hidden using
+  the `Hide/Show' menu or by pressing `S-mouse-2' within the code
+  (not in XEmacs).
+
+- PRINTING: Postscript printing with different fonts (`ps-print-color-p' is
+  nil, default faces from `font-lock.el' used if `vhdl-use-default-faces' is
+  non-nil) or colors (`ps-print-color-p' is non-nil) is possible using the
+  standard Emacs postscript printing commands. Variable `vhdl-print-two-column'
+  defines appropriate default settings for nice landscape two-column printing.
+  The paper format can be set by variable `ps-paper-type'.
+
+- CUSTOMIZATION: All variables can easily be customized using the `Customize'
+  menu entry. For some variables, customization only takes effect after
+  re-starting Emacs. Customization can also be done globally (i.e. site-wide,
+  read INSTALL file). Variables of VHDL Mode must NOT be set using the
+  `vhdl-mode-hook' in the .emacs file anymore (delete them if they still are).
+
+
+Maintenance:
+------------
+
+To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
+Add a description of the problem and include a reproducible test case.
+
+Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
+
+The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
+The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
+You are kindly invited to participate in beta testing. Subscribe to above
+mailing lists by sending an email to <vhdl-mode@geocities.com>.
+
+The archive with the latest version is located at
+<http://www.geocities.com/SiliconValley/Peaks/8287>.
+
+
+Bugs and Limitations:
+---------------------
+
+- Index menu does not work under XEmacs (limitation of XEmacs ?!).
+
+- Re-indenting large regions or expressions can be slow.
+
+- Hideshow does not work under XEmacs.
+
+- Parsing compilation error messages for Ikos and Vantage VHDL compilers
+  does not work under XEmacs.
+
+
+Key bindings:
+-------------
+
+\\{vhdl-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (set-syntax-table vhdl-mode-syntax-table)
+  (setq major-mode 'vhdl-mode)
+  (setq mode-name "VHDL")
+  (setq local-abbrev-table vhdl-mode-abbrev-table)
+  (use-local-map vhdl-mode-map)
+  ;; set local variable values
+  (set (make-local-variable 'paragraph-start) "\\s-*\\(---\\|[a-zA-Z]\\|$\\)")
+  (set (make-local-variable 'paragraph-separate) paragraph-start)
+  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
+  (set (make-local-variable 'require-final-newline) t)
+  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
+  (set (make-local-variable 'comment-start) "--")
+  (set (make-local-variable 'comment-end) "")
+  (set (make-local-variable 'comment-column) vhdl-comment-column)
+  (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
+  (set (make-local-variable 'comment-start-skip) "--+\\s-*")
+  (set (make-local-variable 'dabbrev-case-fold-search) nil)
+  (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
+
+  ;; setup the comment indent variable in a Emacs version portable way
+  ;; ignore any byte compiler warnings you might get here
+  (if (boundp 'comment-indent-function)
+      (progn (make-local-variable 'comment-indent-function)
+	     (setq comment-indent-function 'vhdl-comment-indent)))
+
+  ;; initialize font locking
+  (require 'font-lock)
+  (vhdl-font-lock-init)
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults (list 'vhdl-font-lock-keywords nil
+				 (not vhdl-highlight-case-sensitive)
+				 '((?\_ . "w"))))
+  (turn-on-font-lock)
+
+  ;; variables for source file compilation
+  (make-local-variable 'compile-command)
+  (set (make-local-variable 'compilation-error-regexp-alist)
+       vhdl-compilation-error-regexp-alist)
+
+  ;; add menus
+  (if vhdl-index-menu
+      (if (or (not (consp font-lock-maximum-size))
+	      (> font-lock-maximum-size (buffer-size)))
+	  (vhdl-add-index-menu)
+	(message "Scanning buffer for index...buffer too big")))
+  (if vhdl-source-file-menu (vhdl-add-source-files-menu))
+  (easy-menu-add vhdl-mode-menu)
+  (easy-menu-define vhdl-mode-easy-menu vhdl-mode-map
+                    "Menu keymap for VHDL Mode." vhdl-mode-menu)
+  (run-hooks 'menu-bar-update-hook)
+
+  ;; initialize hideshow and add menu
+  (if vhdl-hideshow-menu (hs-minor-mode))
+
+  ;; initialize postscript printing
+  (vhdl-ps-init)
+
+  (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
+  (message "Type C-c C-h for VHDL Mode documentation.")
+
+  (run-hooks 'vhdl-mode-hook)
+  )
+
+
+;; ############################################################################
+;; Keywords and predefined words in VHDL'93
+;; ############################################################################
+
+;; `regexp-opt' was not used at this place because it is not yet implemented
+;; in XEmacs and because it resulted in SLOWER regexps!!
+
+(defconst vhdl-93-keywords-regexp
+  (eval-when-compile
+    (concat
+     "\\<\\("
+     (mapconcat
+      'identity
+      '(
+	"abs" "access" "after" "alias" "all" "and" "architecture" "array"
+	"assert" "attribute"
+	"begin" "block" "body" "buffer" "bus"
+	"case" "component" "configuration" "constant"
+	"disconnect" "downto"
+	"else" "elsif" "end" "entity" "exit"
+	"file" "for" "function"
+	"generate" "generic" "group" "guarded"
+	"if" "impure" "in" "inertial" "inout" "is"
+	"label" "library" "linkage" "literal" "loop"
+	"map" "mod"
+	"nand" "new" "next" "nor" "not" "null"
+	"of" "on" "open" "or" "others" "out"
+	"package" "port" "postponed" "procedure" "process" "pure"
+	"range" "record" "register" "reject" "rem" "report" "return"
+	"rol" "ror"
+	"select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
+	"then" "to" "transport" "type"
+	"unaffected" "units" "until" "use"
+	"variable"
+	"wait" "warning" "when" "while" "with"
+	"xnor" "xor"
+	)
+      "\\|")
+     "\\)\\>"))
+  "Regexp for VHDL'93 keywords.")
+
+(defconst vhdl-93-types-regexp
+  (eval-when-compile
+    (concat
+     "\\<\\("
+     (mapconcat
+      'identity
+      '(
+	"boolean" "bit" "bit_vector" "character" "severity_level" "integer"
+	"real" "time" "natural" "positive" "string" "text" "line"
+	"unsigned" "signed"
+	"std_logic" "std_logic_vector"
+	"std_ulogic" "std_ulogic_vector"
+	)
+      "\\|")
+     "\\)\\>"))
+  "Regexp for VHDL'93 standardized types.")
+
+(defconst vhdl-93-attributes-regexp
+  (eval-when-compile
+    (concat
+     "\\<\\("
+     (mapconcat
+      'identity
+      '(
+	"base" "left" "right" "high" "low" "pos" "val" "succ"
+	"pred" "leftof" "rightof" "range" "reverse_range"
+	"length" "delayed" "stable" "quiet" "transaction"
+	"event" "active" "last_event" "last_active" "last_value"
+	"driving" "driving_value" "ascending" "value" "image"
+	"simple_name" "instance_name" "path_name"
+	"foreign"
+	)
+      "\\|")
+     "\\)\\>"))
+  "Regexp for VHDL'93 standardized attributes.")
+
+(defconst vhdl-93-enum-values-regexp
+  (eval-when-compile
+    (concat
+     "\\<\\("
+     (mapconcat
+      'identity
+      '(
+	"true" "false"
+	"note" "warning" "error" "failure"
+	"fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
+	)
+      "\\|")
+     "\\)\\>"))
+  "Regexp for VHDL'93 standardized enumeration values.")
+
+
+;; ############################################################################
+;; Syntax analysis and indentation
+;; ############################################################################
+
+;; ############################################################################
+;; Syntax analysis
+
+;; constant regular expressions for looking at various constructs
+
+(defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
+  "Regexp describing a VHDL symbol.
+We cannot use just `word' syntax class since `_' cannot be in word
+class.  Putting underscore in word class breaks forward word movement
+behavior that users are familiar with.")
+
+(defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
+  "Regexp describing a case statement header key.")
+
+(defconst vhdl-label-key
+  (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
+  "Regexp describing a VHDL label.")
+
+;; Macro definitions:
+
+(defmacro vhdl-point (position)
+  ;; Returns the value of point at certain commonly referenced POSITIONs.
+  ;; POSITION can be one of the following symbols:
+  ;;
+  ;; bol  -- beginning of line
+  ;; eol  -- end of line
+  ;; bod  -- beginning of defun
+  ;; boi  -- back to indentation
+  ;; eoi  -- last whitespace on line
+  ;; ionl -- indentation of next line
+  ;; iopl -- indentation of previous line
+  ;; bonl -- beginning of next line
+  ;; bopl -- beginning of previous line
+  ;;
+  ;; This function does not modify point or mark.
+  (or (and (eq 'quote (car-safe position))
+	   (null (cdr (cdr position))))
+      (error "bad buffer position requested: %s" position))
+  (setq position (nth 1 position))
+  (` (let ((here (point)))
+       (,@ (cond
+	    ((eq position 'bol)  '((beginning-of-line)))
+	    ((eq position 'eol)  '((end-of-line)))
+	    ((eq position 'bod)  '((save-match-data
+				     (vhdl-beginning-of-defun))))
+	    ((eq position 'boi)  '((back-to-indentation)))
+	    ((eq position 'eoi)  '((end-of-line)(skip-chars-backward " \t")))
+	    ((eq position 'bonl) '((forward-line 1)))
+	    ((eq position 'bopl) '((forward-line -1)))
+	    ((eq position 'iopl)
+	     '((forward-line -1)
+	       (back-to-indentation)))
+	    ((eq position 'ionl)
+	     '((forward-line 1)
+	       (back-to-indentation)))
+	    (t (error "unknown buffer position requested: %s" position))
+	    ))
+       (prog1
+	   (point)
+	 (goto-char here))
+       ;; workaround for an Emacs18 bug -- blech! Well, at least it
+       ;; doesn't hurt for v19
+       (,@ nil)
+       )))
+
+(defmacro vhdl-safe (&rest body)
+  ;; safely execute BODY, return nil if an error occurred
+  (` (condition-case nil
+	 (progn (,@ body))
+       (error nil))))
+
+(defmacro vhdl-add-syntax (symbol &optional relpos)
+  ;; a simple macro to append the syntax in symbol to the syntax list.
+  ;; try to increase performance by using this macro
+  (` (setq vhdl-syntactic-context
+	   (cons (cons (, symbol) (, relpos)) vhdl-syntactic-context))))
+
+(defmacro vhdl-has-syntax (symbol)
+  ;; a simple macro to return check the syntax list.
+  ;; try to increase performance by using this macro
+  (` (assoc (, symbol) vhdl-syntactic-context)))
+
+;; Syntactic element offset manipulation:
+
+(defun vhdl-read-offset (langelem)
+  ;; read new offset value for LANGELEM from minibuffer. return a
+  ;; legal value only
+  (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
+	(errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
+	(prompt "Offset: ")
+	offset input interned)
+    (while (not offset)
+      (setq input (read-string prompt oldoff)
+	    offset (cond ((string-equal "+" input) '+)
+			 ((string-equal "-" input) '-)
+			 ((string-equal "++" input) '++)
+			 ((string-equal "--" input) '--)
+			 ((string-match "^-?[0-9]+$" input)
+			  (string-to-int input))
+			 ((fboundp (setq interned (intern input)))
+			  interned)
+			 ((boundp interned) interned)
+			 ;; error, but don't signal one, keep trying
+			 ;; to read an input value
+			 (t (ding)
+			    (setq prompt errmsg)
+			    nil))))
+    offset))
+
+(defun vhdl-set-offset (symbol offset &optional add-p)
+  "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
+SYMBOL is the syntactic element symbol to change and OFFSET is the new
+offset for that syntactic element.  Optional ADD says to add SYMBOL to
+`vhdl-offsets-alist' if it doesn't already appear there."
+  (interactive
+   (let* ((langelem
+	   (intern (completing-read
+		    (concat "Syntactic symbol to change"
+			    (if current-prefix-arg " or add" "")
+			    ": ")
+		    (mapcar
+		     (function
+		      (lambda (langelem)
+			(cons (format "%s" (car langelem)) nil)))
+		     vhdl-offsets-alist)
+		    nil (not current-prefix-arg)
+		    ;; initial contents tries to be the last element
+		    ;; on the syntactic analysis list for the current
+		    ;; line
+		    (let* ((syntax (vhdl-get-syntactic-context))
+			   (len (length syntax))
+			   (ic (format "%s" (car (nth (1- len) syntax)))))
+		      (if (memq 'v19 vhdl-emacs-features)
+			  (cons ic 0)
+			ic))
+		    )))
+	  (offset (vhdl-read-offset langelem)))
+     (list langelem offset current-prefix-arg)))
+  ;; sanity check offset
+  (or (eq offset '+)
+      (eq offset '-)
+      (eq offset '++)
+      (eq offset '--)
+      (integerp offset)
+      (fboundp offset)
+      (boundp offset)
+      (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
+	     offset))
+  (let ((entry (assq symbol vhdl-offsets-alist)))
+    (if entry
+	(setcdr entry offset)
+      (if add-p
+	  (setq vhdl-offsets-alist (cons (cons symbol offset) vhdl-offsets-alist))
+	(error "%s is not a valid syntactic symbol." symbol))))
+  (vhdl-keep-region-active))
+
+(defun vhdl-set-style (style &optional local)
+  "Set vhdl-mode variables to use one of several different indentation styles.
+STYLE is a string representing the desired style and optional LOCAL is
+a flag which, if non-nil, means to make the style variables being
+changed buffer local, instead of the default, which is to set the
+global variables.  Interactively, the flag comes from the prefix
+argument.  The styles are chosen from the `vhdl-style-alist' variable."
+  (interactive (list (completing-read "Use which VHDL indentation style? "
+                                      vhdl-style-alist nil t)
+		     current-prefix-arg))
+  (let ((vars (cdr (assoc style vhdl-style-alist))))
+    (or vars
+	(error "Invalid VHDL indentation style `%s'" style))
+    ;; set all the variables
+    (mapcar
+     (function
+      (lambda (varentry)
+	(let ((var (car varentry))
+	      (val (cdr varentry)))
+	  (and local
+	       (make-local-variable var))
+	  ;; special case for vhdl-offsets-alist
+	  (if (not (eq var 'vhdl-offsets-alist))
+	      (set var val)
+	    ;; reset vhdl-offsets-alist to the default value first
+	    (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
+	    ;; now set the langelems that are different
+	    (mapcar
+	     (function
+	      (lambda (langentry)
+		(let ((langelem (car langentry))
+		      (offset (cdr langentry)))
+		  (vhdl-set-offset langelem offset)
+		  )))
+	     val))
+	  )))
+     vars))
+  (vhdl-keep-region-active))
+
+(defun vhdl-get-offset (langelem)
+  ;; Get offset from LANGELEM which is a cons cell of the form:
+  ;; (SYMBOL . RELPOS).  The symbol is matched against
+  ;; vhdl-offsets-alist and the offset found there is either returned,
+  ;; or added to the indentation at RELPOS.  If RELPOS is nil, then
+  ;; the offset is simply returned.
+  (let* ((symbol (car langelem))
+	 (relpos (cdr langelem))
+	 (match  (assq symbol vhdl-offsets-alist))
+	 (offset (cdr-safe match)))
+    ;; offset can be a number, a function, a variable, or one of the
+    ;; symbols + or -
+    (cond
+     ((not match)
+      (if vhdl-strict-syntax-p
+	  (error "don't know how to indent a %s" symbol)
+	(setq offset 0
+	      relpos 0)))
+     ((eq offset '+)  (setq offset vhdl-basic-offset))
+     ((eq offset '-)  (setq offset (- vhdl-basic-offset)))
+     ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
+     ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
+     ((and (not (numberp offset))
+	   (fboundp offset))
+      (setq offset (funcall offset langelem)))
+     ((not (numberp offset))
+      (setq offset (eval offset)))
+     )
+    (+ (if (and relpos
+		(< relpos (vhdl-point 'bol)))
+	   (save-excursion
+	     (goto-char relpos)
+	     (current-column))
+	 0)
+       offset)))
+
+;; Syntactic support functions:
+
+;; Returns `comment' if in a comment, `string' if in a string literal,
+;; or nil if not in a literal at all.  Optional LIM is used as the
+;; backward limit of the search.  If omitted, or nil, (point-min) is
+;; used.
+
+(defun vhdl-in-literal (&optional lim)
+  ;; Determine if point is in a VHDL literal.
+  (save-excursion
+    (let* ((lim (or lim (point-min)))
+	   (state (parse-partial-sexp lim (point))))
+      (cond
+       ((nth 3 state) 'string)
+       ((nth 4 state) 'comment)
+       (t nil)))
+    ))
+
+;; This is the best we can do in Win-Emacs.
+(defun vhdl-win-il (&optional lim)
+  ;; Determine if point is in a VHDL literal
+  (save-excursion
+    (let* ((here (point))
+	   (state nil)
+	   (match nil)
+	   (lim  (or lim (vhdl-point 'bod))))
+      (goto-char lim )
+      (while (< (point) here)
+	(setq match
+	      (and (re-search-forward "--\\|[\"']"
+				      here 'move)
+		   (buffer-substring (match-beginning 0) (match-end 0))))
+	(setq state
+	      (cond
+	       ;; no match
+	       ((null match) nil)
+	       ;; looking at the opening of a VHDL style comment
+	       ((string= "--" match)
+		(if (<= here (progn (end-of-line) (point))) 'comment))
+	       ;; looking at the opening of a double quote string
+	       ((string= "\"" match)
+		(if (not (save-restriction
+			   ;; this seems to be necessary since the
+			   ;; re-search-forward will not work without it
+			   (narrow-to-region (point) here)
+			   (re-search-forward
+			    ;; this regexp matches a double quote
+			    ;; which is preceded by an even number
+			    ;; of backslashes, including zero
+			    "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
+		    'string))
+	       ;; looking at the opening of a single quote string
+	       ((string= "'" match)
+		(if (not (save-restriction
+			   ;; see comments from above
+			   (narrow-to-region (point) here)
+			   (re-search-forward
+			    ;; this matches a single quote which is
+			    ;; preceded by zero or two backslashes.
+			    "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
+			    here 'move)))
+		    'string))
+	       (t nil)))
+	) ; end-while
+      state)))
+
+(and (memq 'Win-Emacs vhdl-emacs-features)
+     (fset 'vhdl-in-literal 'vhdl-win-il))
+
+;; Skipping of "syntactic whitespace".  Syntactic whitespace is
+;; defined as lexical whitespace or comments.  Search no farther back
+;; or forward than optional LIM.  If LIM is omitted, (point-min) is
+;; used for backward skipping, (point-max) is used for forward
+;; skipping.
+
+(defun vhdl-forward-syntactic-ws (&optional lim)
+  ;; Forward skip of syntactic whitespace.
+  (save-restriction
+    (let* ((lim (or lim (point-max)))
+	   (here lim)
+	   (hugenum (point-max)))
+      (narrow-to-region lim (point))
+      (while (/= here (point))
+	(setq here (point))
+	(forward-comment hugenum))
+      )))
+
+;; This is the best we can do in Win-Emacs.
+(defun vhdl-win-fsws (&optional lim)
+  ;; Forward skip syntactic whitespace for Win-Emacs.
+  (let ((lim (or lim (point-max)))
+	stop)
+    (while (not stop)
+      (skip-chars-forward " \t\n\r\f" lim)
+      (cond
+       ;; vhdl comment
+       ((looking-at "--") (end-of-line))
+       ;; none of the above
+       (t (setq stop t))
+       ))))
+
+(and (memq 'Win-Emacs vhdl-emacs-features)
+     (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
+
+(defun vhdl-backward-syntactic-ws (&optional lim)
+  ;; Backward skip over syntactic whitespace.
+  (save-restriction
+    (let* ((lim (or lim (point-min)))
+	   (here lim)
+	   (hugenum (- (point-max))))
+      (if (< lim (point))
+	  (progn
+	    (narrow-to-region lim (point))
+	    (while (/= here (point))
+	      (setq here (point))
+	      (forward-comment hugenum)
+	      )))
+      )))
+
+;; This is the best we can do in Win-Emacs.
+(defun vhdl-win-bsws (&optional lim)
+  ;; Backward skip syntactic whitespace for Win-Emacs.
+  (let ((lim (or lim (vhdl-point 'bod)))
+	stop)
+    (while (not stop)
+      (skip-chars-backward " \t\n\r\f" lim)
+      (cond
+       ;; vhdl comment
+       ((eq (vhdl-in-literal lim) 'comment)
+	(skip-chars-backward "^-" lim)
+	(skip-chars-backward "-" lim)
+	(while (not (or (and (= (following-char) ?-)
+			     (= (char-after (1+ (point))) ?-))
+			(<= (point) lim)))
+	  (skip-chars-backward "^-" lim)
+	  (skip-chars-backward "-" lim)))
+       ;; none of the above
+       (t (setq stop t))
+       ))))
+
+(and (memq 'Win-Emacs vhdl-emacs-features)
+    (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
+
+;; Functions to help finding the correct indentation column:
+
+(defun vhdl-first-word (point)
+  "If the keyword at POINT is at boi, then return (current-column) at
+that point, else nil."
+  (save-excursion
+    (and (goto-char point)
+	 (eq (point) (vhdl-point 'boi))
+	 (current-column))))
+
+(defun vhdl-last-word (point)
+  "If the keyword at POINT is at eoi, then return (current-column) at
+that point, else nil."
+  (save-excursion
+    (and (goto-char point)
+	 (save-excursion (or (eq (progn (forward-sexp) (point))
+				 (vhdl-point 'eoi))
+			     (looking-at "\\s-*\\(--\\)?")))
+	 (current-column))))
+
+;; Core syntactic evaluation functions:
+
+(defconst vhdl-libunit-re
+  "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
+
+(defun vhdl-libunit-p ()
+  (and
+   (save-excursion
+     (forward-sexp)
+     (skip-chars-forward " \t\n")
+     (not (looking-at "is\\b[^_]")))
+   (save-excursion
+     (backward-sexp)
+     (and (not (looking-at "use\\b[^_]"))
+	  (progn
+	    (forward-sexp)
+	    (vhdl-forward-syntactic-ws)
+	    (/= (following-char) ?:))))
+   ))
+
+(defconst vhdl-defun-re
+  "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedure\\|function\\)\\b[^_]")
+
+(defun vhdl-defun-p ()
+  (save-excursion
+    (if (looking-at "block\\|process")
+	;; "block", "process":
+	(save-excursion
+	  (backward-sexp)
+	  (not (looking-at "end\\s-+\\w")))
+      ;; "architecture", "configuration", "entity",
+      ;; "package", "procedure", "function":
+      t)))
+
+(defun vhdl-corresponding-defun ()
+  "If the word at the current position corresponds to a \"defun\"
+keyword, then return a string that can be used to find the
+corresponding \"begin\" keyword, else return nil."
+  (save-excursion
+    (and (looking-at vhdl-defun-re)
+	 (vhdl-defun-p)
+	 (if (looking-at "block\\|process")
+	     ;; "block", "process":
+	     (buffer-substring (match-beginning 0) (match-end 0))
+	   ;; "architecture", "configuration", "entity", "package",
+	   ;; "procedure", "function":
+	   "is"))))
+
+(defconst vhdl-begin-fwd-re
+  "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
+  "A regular expression for searching forward that matches all known
+\"begin\" keywords.")
+
+(defconst vhdl-begin-bwd-re
+  "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b[^_]"
+  "A regular expression for searching backward that matches all known
+\"begin\" keywords.")
+
+(defun vhdl-begin-p (&optional lim)
+  "Return t if we are looking at a real \"begin\" keyword.
+Assumes that the caller will make sure that we are looking at
+vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
+the middle of an identifier that just happens to contain a \"begin\"
+keyword."
+  (cond
+   ;; "[architecture|case|configuration|entity|package|
+   ;;   procedure|function] ... is":
+   ((and (looking-at "i")
+	 (save-excursion
+	   ;; Skip backward over first sexp (needed to skip over a
+	   ;; procedure interface list, and is harmless in other
+	   ;; situations).  Note that we need "return" in the
+	   ;; following search list so that we don't run into
+	   ;; semicolons in the function interface list.
+	   (backward-sexp)
+	   (let (foundp)
+	     (while (and (not foundp)
+			 (re-search-backward
+			  ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|block\\)\\b[^_]"
+			  lim 'move))
+	       (if (or (= (preceding-char) ?_)
+		       (vhdl-in-literal lim))
+		   (backward-char)
+		 (setq foundp t))))
+	   (and (/= (following-char) ?\;)
+		(not (looking-at "is\\|begin\\|process\\|block")))))
+    t)
+   ;; "begin", "then":
+   ((looking-at "be\\|t")
+    t)
+   ;; "else":
+   ((and (looking-at "e")
+	 ;; make sure that the "else" isn't inside a
+	 ;; conditional signal assignment.
+	 (save-excursion
+	   (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
+	   (or (eq (following-char) ?\;)
+	       (eq (point) lim))))
+    t)
+   ;; "block", "generate", "loop", "process",
+   ;; "units", "record":
+   ((and (looking-at "bl\\|[glpur]")
+	 (save-excursion
+	   (backward-sexp)
+	   (not (looking-at "end\\s-+\\w"))))
+    t)
+   ;; "component":
+   ((and (looking-at "c")
+	 (save-excursion
+	   (backward-sexp)
+	   (not (looking-at "end\\s-+\\w")))
+	 ;; look out for the dreaded entity class in an attribute
+	 (save-excursion
+	   (vhdl-backward-syntactic-ws lim)
+	   (/= (preceding-char) ?:)))
+    t)
+   ;; "for" (inside configuration declaration):
+   ((and (looking-at "f")
+	 (save-excursion
+	   (backward-sexp)
+	   (not (looking-at "end\\s-+\\w")))
+	 (vhdl-has-syntax 'configuration))
+    t)
+   ))
+
+(defun vhdl-corresponding-mid (&optional lim)
+  (cond
+   ((looking-at "is\\|block\\|process")
+    "begin")
+   ((looking-at "then")
+    "<else>")
+   (t
+    "end")))
+
+(defun vhdl-corresponding-end (&optional lim)
+  "If the word at the current position corresponds to a \"begin\"
+keyword, then return a vector containing enough information to find
+the corresponding \"end\" keyword, else return nil.  The keyword to
+search forward for is aref 0.  The column in which the keyword must
+appear is aref 1 or nil if any column is suitable.
+Assumes that the caller will make sure that we are not in the middle
+of an identifier that just happens to contain a \"begin\" keyword."
+  (save-excursion
+    (and (looking-at vhdl-begin-fwd-re)
+	 (/= (preceding-char) ?_)
+	 (not (vhdl-in-literal lim))
+	 (vhdl-begin-p lim)
+	 (cond
+	  ;; "is", "generate", "loop":
+	  ((looking-at "[igl]")
+	   (vector "end"
+		   (and (vhdl-last-word (point))
+			(or (vhdl-first-word (point))
+			    (save-excursion
+			      (vhdl-beginning-of-statement-1 lim)
+			      (vhdl-backward-skip-label lim)
+			      (vhdl-first-word (point)))))))
+	  ;; "begin", "else", "for":
+	  ((looking-at "be\\|[ef]")
+	   (vector "end"
+		   (and (vhdl-last-word (point))
+			(or (vhdl-first-word (point))
+			    (save-excursion
+			      (vhdl-beginning-of-statement-1 lim)
+			      (vhdl-backward-skip-label lim)
+			      (vhdl-first-word (point)))))))
+	  ;; "component", "units", "record":
+	  ((looking-at "[cur]")
+	   ;; The first end found will close the block
+	   (vector "end" nil))
+	  ;; "block", "process":
+	  ((looking-at "bl\\|p")
+	   (vector "end"
+		   (or (vhdl-first-word (point))
+		       (save-excursion
+			 (vhdl-beginning-of-statement-1 lim)
+			 (vhdl-backward-skip-label lim)
+			 (vhdl-first-word (point))))))
+	  ;; "then":
+	  ((looking-at "t")
+	   (vector "elsif\\|else\\|end\\s-+if"
+		   (and (vhdl-last-word (point))
+			(or (vhdl-first-word (point))
+			    (save-excursion
+			      (vhdl-beginning-of-statement-1 lim)
+			      (vhdl-backward-skip-label lim)
+			      (vhdl-first-word (point)))))))
+	  ))))
+
+(defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
+
+(defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
+
+(defun vhdl-end-p (&optional lim)
+  "Return t if we are looking at a real \"end\" keyword.
+Assumes that the caller will make sure that we are looking at
+vhdl-end-fwd-re, and are not inside a literal, and that we are not in
+the middle of an identifier that just happens to contain an \"end\"
+keyword."
+  (or (not (looking-at "else"))
+      ;; make sure that the "else" isn't inside a conditional signal
+      ;; assignment.
+      (save-excursion
+	(re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
+	(or (eq (following-char) ?\;)
+	    (eq (point) lim)))))
+
+(defun vhdl-corresponding-begin (&optional lim)
+  "If the word at the current position corresponds to an \"end\"
+keyword, then return a vector containing enough information to find
+the corresponding \"begin\" keyword, else return nil.  The keyword to
+search backward for is aref 0.  The column in which the keyword must
+appear is aref 1 or nil if any column is suitable.  The supplementary
+keyword to search forward for is aref 2 or nil if this is not
+required.  If aref 3 is t, then the \"begin\" keyword may be found in
+the middle of a statement.
+Assumes that the caller will make sure that we are not in the middle
+of an identifier that just happens to contain an \"end\" keyword."
+  (save-excursion
+    (let (pos)
+      (if (and (looking-at vhdl-end-fwd-re)
+	       (not (vhdl-in-literal lim))
+	       (vhdl-end-p lim))
+	  (if (looking-at "el")
+	      ;; "else", "elsif":
+	      (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
+	    ;; "end ...":
+	    (setq pos (point))
+	    (forward-sexp)
+	    (skip-chars-forward " \t\n")
+	    (cond
+	     ;; "end if":
+	     ((looking-at "if\\b[^_]")
+	      (vector "else\\|elsif\\|if"
+		      (vhdl-first-word pos)
+		      "else\\|then" nil))
+	     ;; "end component":
+	     ((looking-at "component\\b[^_]")
+	      (vector (buffer-substring (match-beginning 1)
+					(match-end 1))
+		      (vhdl-first-word pos)
+		      nil nil))
+	     ;; "end units", "end record":
+	     ((looking-at "\\(units\\|record\\)\\b[^_]")
+	      (vector (buffer-substring (match-beginning 1)
+					(match-end 1))
+		      (vhdl-first-word pos)
+		      nil t))
+	     ;; "end block", "end process":
+	     ((looking-at "\\(block\\|process\\)\\b[^_]")
+	      (vector "begin" (vhdl-first-word pos) nil nil))
+	     ;; "end case":
+	     ((looking-at "case\\b[^_]")
+	      (vector "case" (vhdl-first-word pos) "is" nil))
+	     ;; "end generate":
+	     ((looking-at "generate\\b[^_]")
+	      (vector "generate\\|for\\|if"
+		      (vhdl-first-word pos)
+		      "generate" nil))
+	     ;; "end loop":
+	     ((looking-at "loop\\b[^_]")
+	      (vector "loop\\|while\\|for"
+		      (vhdl-first-word pos)
+		      "loop" nil))
+	     ;; "end for" (inside configuration declaration):
+	     ((looking-at "for\\b[^_]")
+	      (vector "for" (vhdl-first-word pos) nil nil))
+	     ;; "end [id]":
+	     (t
+	      (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
+		      (vhdl-first-word pos)
+		      ;; return an alist of (statement . keyword) mappings
+		      '(
+			;; "begin ... end [id]":
+			("begin"          . nil)
+			;; "architecture ... is ... begin ... end [id]":
+			("architecture"   . "is")
+			;; "configuration ... is ... end [id]":
+			("configuration"  . "is")
+			;; "entity ... is ... end [id]":
+			("entity"         . "is")
+			;; "package ... is ... end [id]":
+			("package"        . "is")
+			;; "procedure ... is ... begin ... end [id]":
+			("procedure"      . "is")
+			;; "function ... is ... begin ... end [id]":
+			("function"       . "is")
+			)
+		      nil))
+	     ))) ; "end ..."
+      )))
+
+(defconst vhdl-leader-re
+  "\\b\\(block\\|component\\|process\\|for\\)\\b[^_]")
+
+(defun vhdl-end-of-leader ()
+  (save-excursion
+    (cond ((looking-at "block\\|process")
+	   (if (save-excursion
+		 (forward-sexp)
+		 (skip-chars-forward " \t\n")
+		 (= (following-char) ?\())
+	       (forward-sexp 2)
+	     (forward-sexp))
+	   (point))
+	  ((looking-at "component")
+	   (forward-sexp 2)
+	   (point))
+	  ((looking-at "for")
+	   (forward-sexp 2)
+	   (skip-chars-forward " \t\n")
+	   (while (looking-at "[,:(]")
+	     (forward-sexp)
+	     (skip-chars-forward " \t\n"))
+	   (point))
+	  (t nil)
+	  )))
+
+(defconst vhdl-trailer-re
+  "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
+
+(defconst vhdl-statement-fwd-re
+  "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
+  "A regular expression for searching forward that matches all known
+\"statement\" keywords.")
+
+(defconst vhdl-statement-bwd-re
+  "\\b\\(if\\|for\\|while\\)\\b[^_]"
+  "A regular expression for searching backward that matches all known
+\"statement\" keywords.")
+
+(defun vhdl-statement-p (&optional lim)
+  "Return t if we are looking at a real \"statement\" keyword.
+Assumes that the caller will make sure that we are looking at
+vhdl-statement-fwd-re, and are not inside a literal, and that we are not in
+the middle of an identifier that just happens to contain a \"statement\"
+keyword."
+  (cond
+   ;; "for" ... "generate":
+   ((and (looking-at "f")
+	 ;; Make sure it's the start of a parameter specification.
+	 (save-excursion
+	   (forward-sexp 2)
+	   (skip-chars-forward " \t\n")
+	   (looking-at "in\\b[^_]"))
+	 ;; Make sure it's not an "end for".
+	 (save-excursion
+	   (backward-sexp)
+	   (not (looking-at "end\\s-+\\w"))))
+    t)
+   ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
+   ((and (looking-at "i")
+	 ;; Make sure it's not an "end if".
+	 (save-excursion
+	   (backward-sexp)
+	   (not (looking-at "end\\s-+\\w"))))
+    t)
+   ;; "while" ... "loop":
+   ((looking-at "w")
+    t)
+   ))
+
+(defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
+  "Regexp describing a case statement alternative key.")
+
+(defun vhdl-case-alternative-p (&optional lim)
+  "Return t if we are looking at a real case alternative.
+Assumes that the caller will make sure that we are looking at
+vhdl-case-alternative-re, and are not inside a literal, and that
+we are not in the middle of an identifier that just happens to
+contain a \"when\" keyword."
+  (save-excursion
+    (let (foundp)
+      (while (and (not foundp)
+		  (re-search-backward ";\\|<=" lim 'move))
+	(if (or (= (preceding-char) ?_)
+		(vhdl-in-literal lim))
+	    (backward-char)
+	  (setq foundp t)))
+      (or (eq (following-char) ?\;)
+	  (eq (point) lim)))
+    ))
+
+;; Core syntactic movement functions:
+
+(defconst vhdl-b-t-b-re
+  (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
+
+(defun vhdl-backward-to-block (&optional lim)
+  "Move backward to the previous \"begin\" or \"end\" keyword."
+  (let (foundp)
+    (while (and (not foundp)
+		(re-search-backward vhdl-b-t-b-re lim 'move))
+      (if (or (= (preceding-char) ?_)
+	      (vhdl-in-literal lim))
+	  (backward-char)
+	(cond
+	 ;; "begin" keyword:
+	 ((and (looking-at vhdl-begin-fwd-re)
+	       (/= (preceding-char) ?_)
+	       (vhdl-begin-p lim))
+	  (setq foundp 'begin))
+	 ;; "end" keyword:
+	 ((and (looking-at vhdl-end-fwd-re)
+	       (/= (preceding-char) ?_)
+	       (vhdl-end-p lim))
+	  (setq foundp 'end))
+	 ))
+      )
+    foundp
+    ))
+
+(defun vhdl-forward-sexp (&optional count lim)
+  "Move forward across one balanced expression (sexp).
+With COUNT, do it that many times."
+  (interactive "p")
+  (let ((count (or count 1))
+	(case-fold-search t)
+	end-vec target)
+    (save-excursion
+      (while (> count 0)
+	;; skip whitespace
+	(skip-chars-forward " \t\n")
+	;; Check for an unbalanced "end" keyword
+	(if (and (looking-at vhdl-end-fwd-re)
+		 (/= (preceding-char) ?_)
+		 (not (vhdl-in-literal lim))
+		 (vhdl-end-p lim)
+		 (not (looking-at "else")))
+	    (error
+	     "Containing expression ends prematurely in vhdl-forward-sexp"))
+	;; If the current keyword is a "begin" keyword, then find the
+	;; corresponding "end" keyword.
+	(if (setq end-vec (vhdl-corresponding-end lim))
+	    (let (
+		  ;; end-re is the statement keyword to search for
+		  (end-re
+		   (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
+		  ;; column is either the statement keyword target column
+		  ;; or nil
+		  (column (aref end-vec 1))
+		  (eol (vhdl-point 'eol))
+		  foundp literal placeholder)
+	      ;; Look for the statement keyword.
+	      (while (and (not foundp)
+			  (re-search-forward end-re nil t)
+			  (setq placeholder (match-end 1))
+			  (goto-char (match-beginning 0)))
+		;; If we are in a literal, or not in the right target
+		;; column and not on the same line as the begin, then
+		;; try again.
+		(if (or (and column
+			     (/= (current-indentation) column)
+			     (> (point) eol))
+			(= (preceding-char) ?_)
+			(setq literal (vhdl-in-literal lim)))
+		    (if (eq literal 'comment)
+			(end-of-line)
+		      (forward-char))
+		  ;; An "else" keyword corresponds to both the opening brace
+		  ;; of the following sexp and the closing brace of the
+		  ;; previous sexp.
+		  (if (not (looking-at "else"))
+		      (goto-char placeholder))
+		  (setq foundp t))
+		)
+	      (if (not foundp)
+		  (error "Unbalanced keywords in vhdl-forward-sexp"))
+	      )
+	  ;; If the current keyword is not a "begin" keyword, then just
+	  ;; perform the normal forward-sexp.
+	  (forward-sexp)
+	  )
+	(setq count (1- count))
+	)
+      (setq target (point)))
+    (goto-char target)
+    nil))
+
+(defun vhdl-backward-sexp (&optional count lim)
+  "Move backward across one balanced expression (sexp).
+With COUNT, do it that many times.  LIM bounds any required backward
+searches."
+  (interactive "p")
+  (let ((count (or count 1))
+	(case-fold-search t)
+	begin-vec target)
+    (save-excursion
+      (while (> count 0)
+	;; Perform the normal backward-sexp, unless we are looking at
+	;; "else" - an "else" keyword corresponds to both the opening brace
+	;; of the following sexp and the closing brace of the previous sexp.
+	(if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
+		 (/= (preceding-char) ?_)
+		 (not (vhdl-in-literal lim)))
+	    nil
+	  (backward-sexp)
+	  (if (and (looking-at vhdl-begin-fwd-re)
+		   (/= (preceding-char) ?_)
+		   (not (vhdl-in-literal lim))
+		   (vhdl-begin-p lim))
+	      (error "Containing expression ends prematurely in vhdl-backward-sexp")))
+	;; If the current keyword is an "end" keyword, then find the
+	;; corresponding "begin" keyword.
+	(if (and (setq begin-vec (vhdl-corresponding-begin lim))
+		 (/= (preceding-char) ?_))
+	    (let (
+		  ;; begin-re is the statement keyword to search for
+		  (begin-re
+		   (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
+		  ;; column is either the statement keyword target column
+		  ;; or nil
+		  (column (aref begin-vec 1))
+		  ;; internal-p controls where the statement keyword can
+		  ;; be found.
+		  (internal-p (aref begin-vec 3))
+		  (last-backward (point)) last-forward
+		  foundp literal keyword)
+	      ;; Look for the statement keyword.
+	      (while (and (not foundp)
+			  (re-search-backward begin-re lim t)
+			  (setq keyword
+				(buffer-substring (match-beginning 1)
+						  (match-end 1))))
+		;; If we are in a literal or in the wrong column,
+		;; then try again.
+		(if (or (and column
+			     (and (/= (current-indentation) column)
+				  ;; possibly accept current-column as
+				  ;; well as current-indentation.
+				  (or (not internal-p)
+				      (/= (current-column) column))))
+			(= (preceding-char) ?_)
+			(vhdl-in-literal lim))
+		    (backward-char)
+		  ;; If there is a supplementary keyword, then
+		  ;; search forward for it.
+		  (if (and (setq begin-re (aref begin-vec 2))
+			   (or (not (listp begin-re))
+			       ;; If begin-re is an alist, then find the
+			       ;; element corresponding to the actual
+			       ;; keyword that we found.
+			       (progn
+				 (setq begin-re
+				       (assoc keyword begin-re))
+				 (and begin-re
+				      (setq begin-re (cdr begin-re))))))
+		      (and
+		       (setq begin-re
+			     (concat "\\b\\(" begin-re "\\)\\b[^_]"))
+		       (save-excursion
+			 (setq last-forward (point))
+			 ;; Look for the supplementary keyword
+			 ;; (bounded by the backward search start
+			 ;; point).
+			 (while (and (not foundp)
+				     (re-search-forward begin-re
+							last-backward t)
+				     (goto-char (match-beginning 1)))
+			   ;; If we are in a literal, then try again.
+			   (if (or (= (preceding-char) ?_)
+				   (setq literal
+					 (vhdl-in-literal last-forward)))
+			       (if (eq literal 'comment)
+				   (goto-char
+				    (min (vhdl-point 'eol) last-backward))
+				 (forward-char))
+			     ;; We have found the supplementary keyword.
+			     ;; Save the position of the keyword in foundp.
+			     (setq foundp (point)))
+			   )
+			 foundp)
+		       ;; If the supplementary keyword was found, then
+		       ;; move point to the supplementary keyword.
+		       (goto-char foundp))
+		    ;; If there was no supplementary keyword, then
+		    ;; point is already at the statement keyword.
+		    (setq foundp t)))
+		) ; end of the search for the statement keyword
+	      (if (not foundp)
+		  (error "Unbalanced keywords in vhdl-backward-sexp"))
+	      ))
+	(setq count (1- count))
+	)
+      (setq target (point)))
+    (goto-char target)
+    nil))
+
+(defun vhdl-backward-up-list (&optional count limit)
+  "Move backward out of one level of blocks.
+With argument, do this that many times."
+  (interactive "p")
+  (let ((count (or count 1))
+	target)
+    (save-excursion
+      (while (> count 0)
+	(if (looking-at vhdl-defun-re)
+	    (error "Unbalanced blocks"))
+	(vhdl-backward-to-block limit)
+	(setq count (1- count)))
+      (setq target (point)))
+    (goto-char target)))
+
+(defun vhdl-end-of-defun (&optional count)
+  "Move forward to the end of a VHDL defun."
+  (interactive)
+  (let ((case-fold-search t))
+    (vhdl-beginning-of-defun)
+    (if (not (looking-at "block\\|process"))
+	(re-search-forward "\\bis\\b"))
+    (vhdl-forward-sexp)))
+
+(defun vhdl-mark-defun ()
+  "Put mark at end of this \"defun\", point at beginning."
+  (interactive)
+  (let ((case-fold-search t))
+    (push-mark)
+    (vhdl-beginning-of-defun)
+    (push-mark)
+    (if (not (looking-at "block\\|process"))
+	(re-search-forward "\\bis\\b"))
+    (vhdl-forward-sexp)
+    (exchange-point-and-mark)))
+
+(defun vhdl-beginning-of-libunit ()
+  "Move backward to the beginning of a VHDL library unit.
+Returns the location of the corresponding begin keyword, unless search
+stops due to beginning or end of buffer."
+  ;; Note that if point is between the "libunit" keyword and the
+  ;; corresponding "begin" keyword, then that libunit will not be
+  ;; recognised, and the search will continue backwards.  If point is
+  ;; at the "begin" keyword, then the defun will be recognised.  The
+  ;; returned point is at the first character of the "libunit" keyword.
+  (let ((last-forward (point))
+	(last-backward
+	 ;; Just in case we are actually sitting on the "begin"
+	 ;; keyword, allow for the keyword and an extra character,
+	 ;; as this will be used when looking forward for the
+	 ;; "begin" keyword.
+	 (save-excursion (forward-word 1) (1+ (point))))
+	foundp literal placeholder)
+    ;; Find the "libunit" keyword.
+    (while (and (not foundp)
+		(re-search-backward vhdl-libunit-re nil 'move))
+      ;; If we are in a literal, or not at a real libunit, then try again.
+      (if (or (= (preceding-char) ?_)
+	      (vhdl-in-literal (point-min))
+	      (not (vhdl-libunit-p)))
+	  (backward-char)
+	;; Find the corresponding "begin" keyword.
+	(setq last-forward (point))
+	(while (and (not foundp)
+		    (re-search-forward "\\bis\\b[^_]" last-backward t)
+		    (setq placeholder (match-beginning 0)))
+	  (if (or (= (preceding-char) ?_)
+		  (setq literal (vhdl-in-literal last-forward)))
+	      ;; It wasn't a real keyword, so keep searching.
+	      (if (eq literal 'comment)
+		  (goto-char
+		   (min (vhdl-point 'eol) last-backward))
+		(forward-char))
+	    ;; We have found the begin keyword, loop will exit.
+	    (setq foundp placeholder)))
+	;; Go back to the libunit keyword
+	(goto-char last-forward)))
+    foundp))
+
+(defun vhdl-beginning-of-defun (&optional count)
+  "Move backward to the beginning of a VHDL defun.
+With argument, do it that many times.
+Returns the location of the corresponding begin keyword, unless search
+stops due to beginning or end of buffer."
+  ;; Note that if point is between the "defun" keyword and the
+  ;; corresponding "begin" keyword, then that defun will not be
+  ;; recognised, and the search will continue backwards.  If point is
+  ;; at the "begin" keyword, then the defun will be recognised.  The
+  ;; returned point is at the first character of the "defun" keyword.
+  (interactive "p")
+  (let ((count (or count 1))
+	(case-fold-search t)
+	(last-forward (point))
+	foundp)
+    (while (> count 0)
+      (setq foundp nil)
+      (goto-char last-forward)
+      (let ((last-backward
+	     ;; Just in case we are actually sitting on the "begin"
+	     ;; keyword, allow for the keyword and an extra character,
+	     ;; as this will be used when looking forward for the
+	     ;; "begin" keyword.
+	     (save-excursion (forward-word 1) (1+ (point))))
+	    begin-string literal)
+	(while (and (not foundp)
+		    (re-search-backward vhdl-defun-re nil 'move))
+	  ;; If we are in a literal, then try again.
+	  (if (or (= (preceding-char) ?_)
+		  (vhdl-in-literal (point-min)))
+	      (backward-char)
+	    (if (setq begin-string (vhdl-corresponding-defun))
+		;; This is a real defun keyword.
+		;; Find the corresponding "begin" keyword.
+		;; Look for the begin keyword.
+		(progn
+		  ;; Save the search start point.
+		  (setq last-forward (point))
+		  (while (and (not foundp)
+			      (search-forward begin-string last-backward t))
+		    (if (or (= (preceding-char) ?_)
+			    (save-match-data
+			      (setq literal (vhdl-in-literal last-forward))))
+			;; It wasn't a real keyword, so keep searching.
+			(if (eq literal 'comment)
+			    (goto-char
+			     (min (vhdl-point 'eol) last-backward))
+			  (forward-char))
+		      ;; We have found the begin keyword, loop will exit.
+		      (setq foundp (match-beginning 0)))
+		    )
+		  ;; Go back to the defun keyword
+		  (goto-char last-forward)) ; end search for begin keyword
+	      ))
+	  ) ; end of the search for the defun keyword
+	)
+      (setq count (1- count))
+      )
+    (vhdl-keep-region-active)
+    foundp))
+
+(defun vhdl-beginning-of-statement (&optional count lim)
+  "Go to the beginning of the innermost VHDL statement.
+With prefix arg, go back N - 1 statements.  If already at the
+beginning of a statement then go to the beginning of the preceding
+one.  If within a string or comment, or next to a comment (only
+whitespace between), move by sentences instead of statements.
+
+When called from a program, this function takes 2 optional args: the
+prefix arg, and a buffer position limit which is the farthest back to
+search."
+  (interactive "p")
+  (let ((count (or count 1))
+	(case-fold-search t)
+	(lim (or lim (point-min)))
+	(here (point))
+	state)
+    (save-excursion
+      (goto-char lim)
+      (setq state (parse-partial-sexp (point) here nil nil)))
+    (if (and (interactive-p)
+	     (or (nth 3 state)
+		 (nth 4 state)
+		 (looking-at (concat "[ \t]*" comment-start-skip))))
+	(forward-sentence (- count))
+      (while (> count 0)
+	(vhdl-beginning-of-statement-1 lim)
+	(setq count (1- count))))
+    ;; its possible we've been left up-buf of lim
+    (goto-char (max (point) lim))
+    )
+  (vhdl-keep-region-active))
+
+(defconst vhdl-e-o-s-re
+  (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
+
+(defun vhdl-end-of-statement ()
+  "Very simple implementation."
+  (interactive)
+  (re-search-forward vhdl-e-o-s-re))
+
+(defconst vhdl-b-o-s-re
+  (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
+	  vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
+
+(defun vhdl-beginning-of-statement-1 (&optional lim)
+  ;; move to the start of the current statement, or the previous
+  ;; statement if already at the beginning of one.
+  (let ((lim (or lim (point-min)))
+	(here (point))
+	(pos (point))
+	donep)
+    ;; go backwards one balanced expression, but be careful of
+    ;; unbalanced paren being reached
+    (if (not (vhdl-safe (progn (backward-sexp) t)))
+	(progn
+	  (backward-up-list 1)
+	  (forward-char)
+	  (vhdl-forward-syntactic-ws here)
+	  (setq donep t)))
+    (while (and (not donep)
+		(not (bobp))
+		;; look backwards for a statement boundary
+		(re-search-backward vhdl-b-o-s-re lim 'move))
+      (if (or (= (preceding-char) ?_)
+	      (vhdl-in-literal lim))
+	  (backward-char)
+	(cond
+	 ;; If we are looking at an open paren, then stop after it
+	 ((eq (following-char) ?\()
+	  (forward-char)
+	  (vhdl-forward-syntactic-ws here)
+	  (setq donep t))
+	 ;; If we are looking at a close paren, then skip it
+	 ((eq (following-char) ?\))
+	  (forward-char)
+	  (setq pos (point))
+	  (backward-sexp)
+	  (if (< (point) lim)
+	      (progn (goto-char pos)
+		     (vhdl-forward-syntactic-ws here)
+		     (setq donep t))))
+	 ;; If we are looking at a semicolon, then stop
+	 ((eq (following-char) ?\;)
+	  (progn
+	    (forward-char)
+	    (vhdl-forward-syntactic-ws here)
+	    (setq donep t)))
+	 ;; If we are looking at a "begin", then stop
+	 ((and (looking-at vhdl-begin-fwd-re)
+	       (/= (preceding-char) ?_)
+	       (vhdl-begin-p nil))
+	  ;; If it's a leader "begin", then find the
+	  ;; right place
+	  (if (looking-at vhdl-leader-re)
+	      (save-excursion
+		;; set a default stop point at the begin
+		(setq pos (point))
+		;; is the start point inside the leader area ?
+		(goto-char (vhdl-end-of-leader))
+		(vhdl-forward-syntactic-ws here)
+		(if (< (point) here)
+		    ;; start point was not inside leader area
+		    ;; set stop point at word after leader
+		    (setq pos (point))))
+	    (forward-word 1)
+	    (vhdl-forward-syntactic-ws here)
+	    (setq pos (point)))
+	  (goto-char pos)
+	  (setq donep t))
+	 ;; If we are looking at a "statement", then stop
+	 ((and (looking-at vhdl-statement-fwd-re)
+	       (/= (preceding-char) ?_)
+	       (vhdl-statement-p nil))
+	  (setq donep t))
+	 ;; If we are looking at a case alternative key, then stop
+ 	 ((and (looking-at vhdl-case-alternative-re)
+ 	       (vhdl-case-alternative-p lim))
+	  (save-excursion
+	    ;; set a default stop point at the when
+	    (setq pos (point))
+	    ;; is the start point inside the case alternative key ?
+	    (looking-at vhdl-case-alternative-re)
+	    (goto-char (match-end 0))
+	    (vhdl-forward-syntactic-ws here)
+	    (if (< (point) here)
+		;; start point was not inside the case alternative key
+		;; set stop point at word after case alternative keyleader
+		(setq pos (point))))
+	  (goto-char pos)
+	  (setq donep t))
+	 ;; Bogus find, continue
+	 (t
+	  (backward-char)))))
+    ))
+
+;; Defuns for calculating the current syntactic state:
+
+(defun vhdl-get-library-unit (bod placeholder)
+  ;; If there is an enclosing library unit at bod, with it's \"begin\"
+  ;; keyword at placeholder, then return the library unit type.
+  (let ((here (vhdl-point 'bol)))
+    (if (save-excursion
+	  (goto-char placeholder)
+	  (vhdl-safe (vhdl-forward-sexp 1 bod))
+	  (<= here (point)))
+	(save-excursion
+	  (goto-char bod)
+	  (cond
+	   ((looking-at "e") 'entity)
+	   ((looking-at "a") 'architecture)
+	   ((looking-at "c") 'configuration)
+	   ((looking-at "p")
+	    (save-excursion
+	      (goto-char bod)
+	      (forward-sexp)
+	      (vhdl-forward-syntactic-ws here)
+	      (if (looking-at "body\\b[^_]")
+		  'package-body 'package))))))
+    ))
+
+(defun vhdl-get-block-state (&optional lim)
+  ;; Finds and records all the closest opens.
+  ;; lim is the furthest back we need to search (it should be the
+  ;; previous libunit keyword).
+  (let ((here (point))
+	(lim (or lim (point-min)))
+	keyword sexp-start sexp-mid sexp-end
+	preceding-sexp containing-sexp
+	containing-begin containing-mid containing-paren)
+    (save-excursion
+      ;; Find the containing-paren, and use that as the limit
+      (if (setq containing-paren
+		(save-restriction
+		  (narrow-to-region lim (point))
+		  (vhdl-safe (scan-lists (point) -1 1))))
+	  (setq lim containing-paren))
+      ;; Look backwards for "begin" and "end" keywords.
+      (while (and (> (point) lim)
+		  (not containing-sexp))
+	(setq keyword (vhdl-backward-to-block lim))
+	(cond
+	 ((eq keyword 'begin)
+	  ;; Found a "begin" keyword
+	  (setq sexp-start (point))
+	  (setq sexp-mid (vhdl-corresponding-mid lim))
+	  (setq sexp-end (vhdl-safe
+			  (save-excursion
+			    (vhdl-forward-sexp 1 lim) (point))))
+	  (if (and sexp-end (<= sexp-end here))
+	      ;; we want to record this sexp, but we only want to
+	      ;; record the last-most of any of them before here
+	      (or preceding-sexp
+		  (setq preceding-sexp sexp-start))
+	    ;; we're contained in this sexp so put sexp-start on
+	    ;; front of list
+	    (setq containing-sexp sexp-start)
+	    (setq containing-mid sexp-mid)
+	    (setq containing-begin t)))
+	 ((eq keyword 'end)
+	  ;; Found an "end" keyword
+	  (forward-sexp)
+	  (setq sexp-end (point))
+	  (setq sexp-mid nil)
+	  (setq sexp-start
+		(or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
+		    (progn (backward-sexp) (point))))
+	  ;; we want to record this sexp, but we only want to
+	  ;; record the last-most of any of them before here
+	  (or preceding-sexp
+	      (setq preceding-sexp sexp-start)))
+	 )))
+    ;; Check if the containing-paren should be the containing-sexp
+    (if (and containing-paren
+	     (or (null containing-sexp)
+		 (< containing-sexp containing-paren)))
+	(setq containing-sexp containing-paren
+	      preceding-sexp nil
+	      containing-begin nil
+	      containing-mid nil))
+    (vector containing-sexp preceding-sexp containing-begin containing-mid)
+    ))
+
+
+(defconst vhdl-s-c-a-re
+  (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
+
+(defun vhdl-skip-case-alternative (&optional lim)
+  ;; skip forward over case/when bodies, with optional maximal
+  ;; limit. if no next case alternative is found, nil is returned and point
+  ;; is not moved
+  (let ((lim (or lim (point-max)))
+	(here (point))
+	donep foundp)
+    (while (and (< (point) lim)
+		(not donep))
+      (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
+	       (save-match-data
+		 (not (vhdl-in-literal)))
+	       (/= (match-beginning 0) here))
+	  (progn
+	    (goto-char (match-beginning 0))
+	    (cond
+	     ((and (looking-at "case")
+		   (re-search-forward "\\bis[^_]" lim t))
+	      (backward-sexp)
+	      (vhdl-forward-sexp))
+	     (t
+	      (setq donep t
+		    foundp t))))))
+    (if (not foundp)
+	(goto-char here))
+    foundp))
+
+(defun vhdl-backward-skip-label (&optional lim)
+  ;; skip backward over a label, with optional maximal
+  ;; limit. if label is not found, nil is returned and point
+  ;; is not moved
+  (let ((lim (or lim (point-min)))
+	placeholder)
+    (if (save-excursion
+	  (vhdl-backward-syntactic-ws lim)
+	  (and (eq (preceding-char) ?:)
+	       (progn
+		 (backward-sexp)
+		 (setq placeholder (point))
+		 (looking-at vhdl-label-key))))
+	(goto-char placeholder))
+    ))
+
+(defun vhdl-forward-skip-label (&optional lim)
+  ;; skip forward over a label, with optional maximal
+  ;; limit. if label is not found, nil is returned and point
+  ;; is not moved
+  (let ((lim (or lim (point-max))))
+    (if (looking-at vhdl-label-key)
+	(progn
+	  (goto-char (match-end 0))
+	  (vhdl-forward-syntactic-ws lim)))
+    ))
+
+(defun vhdl-get-syntactic-context ()
+  ;; guess the syntactic description of the current line of VHDL code.
+  (save-excursion
+    (save-restriction
+      (beginning-of-line)
+      (let* ((indent-point (point))
+	     (case-fold-search t)
+	     vec literal containing-sexp preceding-sexp
+	     containing-begin containing-mid containing-leader
+	     char-before-ip char-after-ip begin-after-ip end-after-ip
+	     placeholder lim library-unit
+	    )
+
+	;; Reset the syntactic context
+	(setq vhdl-syntactic-context nil)
+
+	(save-excursion
+	  ;; Move to the start of the previous library unit, and
+	  ;; record the position of the "begin" keyword.
+	  (setq placeholder (vhdl-beginning-of-libunit))
+	  ;; The position of the "libunit" keyword gives us a gross
+	  ;; limit point.
+	  (setq lim (point))
+	  )
+
+	;; If there is a previous library unit, and we are enclosed by
+	;; it, then set the syntax accordingly.
+	(and placeholder
+	     (setq library-unit (vhdl-get-library-unit lim placeholder))
+	     (vhdl-add-syntax library-unit lim))
+
+	;; Find the surrounding state.
+	(if (setq vec (vhdl-get-block-state lim))
+	    (progn
+	      (setq containing-sexp (aref vec 0))
+	      (setq preceding-sexp (aref vec 1))
+	      (setq containing-begin (aref vec 2))
+	      (setq containing-mid (aref vec 3))
+	      ))
+
+	;; set the limit on the farthest back we need to search
+	(setq lim (if containing-sexp
+		      (save-excursion
+			(goto-char containing-sexp)
+			;; set containing-leader if required
+			(if (looking-at vhdl-leader-re)
+			    (setq containing-leader (vhdl-end-of-leader)))
+			(vhdl-point 'bol))
+		    (point-min)))
+
+	;; cache char before and after indent point, and move point to
+	;; the most likely position to perform the majority of tests
+	(goto-char indent-point)
+	(skip-chars-forward " \t")
+	(setq literal (vhdl-in-literal lim))
+	(setq char-after-ip (following-char))
+	(setq begin-after-ip (and
+			      (not literal)
+			      (looking-at vhdl-begin-fwd-re)
+			      (vhdl-begin-p)))
+	(setq end-after-ip (and
+			    (not literal)
+			    (looking-at vhdl-end-fwd-re)
+			    (vhdl-end-p)))
+	(vhdl-backward-syntactic-ws lim)
+	(setq char-before-ip (preceding-char))
+	(goto-char indent-point)
+	(skip-chars-forward " \t")
+
+	;; now figure out syntactic qualities of the current line
+	(cond
+	 ;; CASE 1: in a string or comment.
+	 ((memq literal '(string comment))
+	  (vhdl-add-syntax literal (vhdl-point 'bopl)))
+	 ;; CASE 2: Line is at top level.
+	 ((null containing-sexp)
+	  ;; Find the point to which indentation will be relative
+	  (save-excursion
+	    (if (null preceding-sexp)
+		;; CASE 2X.1
+		;; no preceding-sexp -> use the preceding statement
+		(vhdl-beginning-of-statement-1 lim)
+	      ;; CASE 2X.2
+	      ;; if there is a preceding-sexp then indent relative to it
+	      (goto-char preceding-sexp)
+	      ;; if not at boi, then the block-opening keyword is
+	      ;; probably following a label, so we need a different
+	      ;; relpos
+	      (if (/= (point) (vhdl-point 'boi))
+		  ;; CASE 2X.3
+		  (vhdl-beginning-of-statement-1 lim)))
+	    ;; v-b-o-s could have left us at point-min
+	    (and (bobp)
+		 ;; CASE 2X.4
+		 (vhdl-forward-syntactic-ws indent-point))
+	    (setq placeholder (point)))
+	  (cond
+	   ;; CASE 2A : we are looking at a block-open
+	   (begin-after-ip
+	    (vhdl-add-syntax 'block-open placeholder))
+	   ;; CASE 2B: we are looking at a block-close
+	   (end-after-ip
+	    (vhdl-add-syntax 'block-close placeholder))
+	   ;; CASE 2C: we are looking at a top-level statement
+	   ((progn
+	      (vhdl-backward-syntactic-ws lim)
+	      (or (bobp)
+		  (= (preceding-char) ?\;)))
+	    (vhdl-add-syntax 'statement placeholder))
+	   ;; CASE 2D: we are looking at a top-level statement-cont
+	   (t
+	    (vhdl-beginning-of-statement-1 lim)
+	    ;; v-b-o-s could have left us at point-min
+	    (and (bobp)
+		 ;; CASE 2D.1
+		 (vhdl-forward-syntactic-ws indent-point))
+	    (vhdl-add-syntax 'statement-cont (point)))
+	   )) ; end CASE 2
+	 ;; CASE 3: line is inside parentheses.  Most likely we are
+	 ;; either in a subprogram argument (interface) list, or a
+	 ;; continued expression containing parentheses.
+	 ((null containing-begin)
+	  (vhdl-backward-syntactic-ws containing-sexp)
+	  (cond
+	   ;; CASE 3A: we are looking at the arglist closing paren
+	   ((eq char-after-ip ?\))
+	    (goto-char containing-sexp)
+	    (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
+	   ;; CASE 3B: we are looking at the first argument in an empty
+	   ;; argument list.
+	   ((eq char-before-ip ?\()
+	    (goto-char containing-sexp)
+	    (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
+	   ;; CASE 3C: we are looking at an arglist continuation line,
+	   ;; but the preceding argument is on the same line as the
+	   ;; opening paren.  This case includes multi-line
+	   ;; expression paren groupings.
+	   ((and (save-excursion
+		   (goto-char (1+ containing-sexp))
+		   (skip-chars-forward " \t")
+		   (not (eolp))
+		   (not (looking-at "--")))
+		 (save-excursion
+		   (vhdl-beginning-of-statement-1 containing-sexp)
+		   (skip-chars-backward " \t(")
+		   (<= (point) containing-sexp)))
+	    (goto-char containing-sexp)
+	    (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
+	   ;; CASE 3D: we are looking at just a normal arglist
+	   ;; continuation line
+	   (t (vhdl-beginning-of-statement-1 containing-sexp)
+	      (vhdl-forward-syntactic-ws indent-point)
+	      (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
+	   ))
+	 ;; CASE 4: A block mid open
+	 ((and begin-after-ip
+	       (looking-at containing-mid))
+	  (goto-char containing-sexp)
+	  ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
+	  (if (looking-at vhdl-trailer-re)
+	      ;; CASE 4.1
+	      (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
+	  (vhdl-backward-skip-label (vhdl-point 'boi))
+	  (vhdl-add-syntax 'block-open (point)))
+	 ;; CASE 5: block close brace
+	 (end-after-ip
+	  (goto-char containing-sexp)
+	  ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
+	  (if (looking-at vhdl-trailer-re)
+	      ;; CASE 5.1
+	      (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
+	  (vhdl-backward-skip-label (vhdl-point 'boi))
+	  (vhdl-add-syntax 'block-close (point)))
+	 ;; CASE 6: A continued statement
+	 ((and (/= char-before-ip ?\;)
+	       ;; check it's not a trailer begin keyword, or a begin
+	       ;; keyword immediately following a label.
+	       (not (and begin-after-ip
+			 (or (looking-at vhdl-trailer-re)
+			     (save-excursion
+			       (vhdl-backward-skip-label containing-sexp)))))
+	       ;; check it's not a statement keyword
+	       (not (and (looking-at vhdl-statement-fwd-re)
+			 (vhdl-statement-p)))
+	       ;; see if the b-o-s is before the indent point
+	       (> indent-point
+		  (save-excursion
+		    (vhdl-beginning-of-statement-1 containing-sexp)
+		    ;; If we ended up after a leader, then this will
+		    ;; move us forward to the start of the first
+		    ;; statement.  Note that a containing sexp here is
+		    ;; always a keyword, not a paren, so this will
+		    ;; have no effect if we hit the containing-sexp.
+		    (vhdl-forward-syntactic-ws indent-point)
+		    (setq placeholder (point))))
+	       ;; check it's not a block-intro
+	       (/= placeholder containing-sexp)
+	       ;; check it's not a case block-intro
+	       (save-excursion
+		 (goto-char placeholder)
+		 (or (not (looking-at vhdl-case-alternative-re))
+		     (> (match-end 0) indent-point))))
+	  ;; Make placeholder skip a label, but only if it puts us
+	  ;; before the indent point at the start of a line.
+	  (let ((new placeholder))
+	    (if (and (> indent-point
+			(save-excursion
+			  (goto-char placeholder)
+			  (vhdl-forward-skip-label indent-point)
+			  (setq new (point))))
+		     (save-excursion
+		       (goto-char new)
+		       (eq new (progn (back-to-indentation) (point)))))
+		(setq placeholder new)))
+	  (vhdl-add-syntax 'statement-cont placeholder)
+	  (if begin-after-ip
+	      (vhdl-add-syntax 'block-open)))
+	 ;; Statement. But what kind?
+	 ;; CASE 7: A case alternative key
+	 ((and (looking-at vhdl-case-alternative-re)
+	       (vhdl-case-alternative-p containing-sexp))
+	  ;; for a case alternative key, we set relpos to the first
+	  ;; non-whitespace char on the line containing the "case"
+	  ;; keyword.
+	  (goto-char containing-sexp)
+	  ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
+	  (if (looking-at vhdl-trailer-re)
+	      (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
+	  (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
+	 ;; CASE 8: statement catchall
+	 (t
+	  ;; we know its a statement, but we need to find out if it is
+	  ;; the first statement in a block
+	  (if containing-leader
+	      (goto-char containing-leader)
+	    (goto-char containing-sexp)
+	    ;; Note that a containing sexp here is always a keyword,
+	    ;; not a paren, so skip over the keyword.
+	    (forward-sexp))
+	  ;; move to the start of the first statement
+	  (vhdl-forward-syntactic-ws indent-point)
+	  (setq placeholder (point))
+	  ;; we want to ignore case alternatives keys when skipping forward
+	  (let (incase-p)
+	    (while (looking-at vhdl-case-alternative-re)
+	      (setq incase-p (point))
+	      ;; we also want to skip over the body of the
+	      ;; case/when statement if that doesn't put us at
+	      ;; after the indent-point
+	      (while (vhdl-skip-case-alternative indent-point))
+	      ;; set up the match end
+	      (looking-at vhdl-case-alternative-re)
+	      (goto-char (match-end 0))
+	      ;; move to the start of the first case alternative statement
+	      (vhdl-forward-syntactic-ws indent-point)
+	      (setq placeholder (point)))
+	    (cond
+	     ;; CASE 8A: we saw a case/when statement so we must be
+	     ;; in a switch statement.  find out if we are at the
+	     ;; statement just after a case alternative key
+	     ((and incase-p
+		   (= (point) indent-point))
+	      ;; relpos is the "when" keyword
+	      (vhdl-add-syntax 'statement-case-intro incase-p))
+	     ;; CASE 8B: any old statement
+	     ((< (point) indent-point)
+	      ;; relpos is the first statement of the block
+	      (vhdl-add-syntax 'statement placeholder)
+	      (if begin-after-ip
+		  (vhdl-add-syntax 'block-open)))
+	     ;; CASE 8C: first statement in a block
+	     (t
+	      (goto-char containing-sexp)
+	      ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
+	      (if (looking-at vhdl-trailer-re)
+		  (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
+	      (vhdl-backward-skip-label (vhdl-point 'boi))
+	      (vhdl-add-syntax 'statement-block-intro (point))
+	      (if begin-after-ip
+		  (vhdl-add-syntax 'block-open)))
+	     )))
+	 )
+
+	;; now we need to look at any modifiers
+	(goto-char indent-point)
+	(skip-chars-forward " \t")
+	(if (looking-at "--")
+	    (vhdl-add-syntax 'comment))
+	;; return the syntax
+	vhdl-syntactic-context))))
+
+;; Standard indentation line-ups:
+
+(defun vhdl-lineup-arglist (langelem)
+  ;; lineup the current arglist line with the arglist appearing just
+  ;; after the containing paren which starts the arglist.
+  (save-excursion
+    (let* ((containing-sexp
+	    (save-excursion
+	      ;; arglist-cont-nonempty gives relpos ==
+	      ;; to boi of containing-sexp paren. This
+	      ;; is good when offset is +, but bad
+	      ;; when it is vhdl-lineup-arglist, so we
+	      ;; have to special case a kludge here.
+	      (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
+		  (progn
+		    (beginning-of-line)
+		    (backward-up-list 1)
+		    (skip-chars-forward " \t" (vhdl-point 'eol)))
+		(goto-char (cdr langelem)))
+	      (point)))
+	   (cs-curcol (save-excursion
+			(goto-char (cdr langelem))
+			(current-column))))
+      (if (save-excursion
+	    (beginning-of-line)
+	    (looking-at "[ \t]*)"))
+	  (progn (goto-char (match-end 0))
+		 (backward-sexp)
+		 (forward-char)
+		 (vhdl-forward-syntactic-ws)
+		 (- (current-column) cs-curcol))
+	(goto-char containing-sexp)
+	(or (eolp)
+	    (let ((eol (vhdl-point 'eol))
+		  (here (progn
+			  (forward-char)
+			  (skip-chars-forward " \t")
+			  (point))))
+	      (vhdl-forward-syntactic-ws)
+	      (if (< (point) eol)
+		  (goto-char here))))
+	(- (current-column) cs-curcol)
+	))))
+
+(defun vhdl-lineup-arglist-intro (langelem)
+  ;; lineup an arglist-intro line to just after the open paren
+  (save-excursion
+    (let ((cs-curcol (save-excursion
+		       (goto-char (cdr langelem))
+		       (current-column)))
+	  (ce-curcol (save-excursion
+		       (beginning-of-line)
+		       (backward-up-list 1)
+		       (skip-chars-forward " \t" (vhdl-point 'eol))
+		       (current-column))))
+      (- ce-curcol cs-curcol -1))))
+
+(defun vhdl-lineup-comment (langelem)
+  ;; support old behavior for comment indentation. we look at
+  ;; vhdl-comment-only-line-offset to decide how to indent comment
+  ;; only-lines
+  (save-excursion
+    (back-to-indentation)
+    ;; at or to the right of comment-column
+    (if (>= (current-column) comment-column)
+	(vhdl-comment-indent)
+      ;; otherwise, indent as specified by vhdl-comment-only-line-offset
+      (if (not (bolp))
+	  (or (car-safe vhdl-comment-only-line-offset)
+	      vhdl-comment-only-line-offset)
+	(or (cdr-safe vhdl-comment-only-line-offset)
+	    (car-safe vhdl-comment-only-line-offset)
+	    -1000			;jam it against the left side
+	    )))))
+
+(defun vhdl-lineup-statement-cont (langelem)
+  ;; line up statement-cont after the assignment operator
+  (save-excursion
+    (let* ((relpos (cdr langelem))
+	   (assignp (save-excursion
+		     (goto-char (vhdl-point 'boi))
+		     (and (re-search-forward "\\(<\\|:\\)="
+					     (vhdl-point 'eol) t)
+			  (- (point) (vhdl-point 'boi)))))
+	   (curcol (progn
+		     (goto-char relpos)
+		     (current-column)))
+	   foundp)
+      (while (and (not foundp)
+		  (< (point) (vhdl-point 'eol)))
+	(re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
+	(if (vhdl-in-literal (cdr langelem))
+	    (forward-char)
+	  (if (= (preceding-char) ?\()
+	      ;; skip over any parenthesized expressions
+	      (goto-char (min (vhdl-point 'eol)
+			      (scan-lists (point) 1 1)))
+	    ;; found an assignment operator (not at eol)
+	    (setq foundp (not (looking-at "\\s-*$"))))))
+      (if (not foundp)
+	  ;; there's no assignment operator on the line
+	  vhdl-basic-offset
+	;; calculate indentation column after assign and ws, unless
+	;; our line contains an assignment operator
+	(if (not assignp)
+	    (progn
+	      (forward-char)
+	      (skip-chars-forward " \t")
+	      (setq assignp 0)))
+	(- (current-column) assignp curcol))
+      )))
+
+;; ############################################################################
+;; Indentation commands
+
+(defun vhdl-tab (&optional pre-arg)
+  "If preceeding character is part of a word then dabbrev-expand,
+else if right of non whitespace on line then tab-to-tab-stop,
+else if last command was a tab or return then dedent one step,
+else indent `correctly'."
+  (interactive "*P")
+  (cond ((= (char-syntax (preceding-char)) ?w)
+	 (let ((case-fold-search nil)) (dabbrev-expand pre-arg)))
+	((> (current-column) (current-indentation))
+	 (tab-to-tab-stop))
+	((and (or (eq last-command 'vhdl-tab)
+		  (eq last-command 'vhdl-return))
+	      (/= 0 (current-indentation)))
+	 (backward-delete-char-untabify vhdl-basic-offset nil))
+	((vhdl-indent-line))
+        )
+  (setq this-command 'vhdl-tab)
+  )
+
+(defun vhdl-untab ()
+  "Delete backwards to previous tab stop."
+  (interactive)
+  (backward-delete-char-untabify vhdl-basic-offset nil)
+  )
+
+(defun vhdl-return ()
+  "newline-and-indent or indent-new-comment-line if in comment and preceding
+character is a space."
+  (interactive)
+  (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
+      (indent-new-comment-line)
+    (newline-and-indent)
+    )
+  )
+
+(defun vhdl-indent-line ()
+  "Indent the current line as VHDL code. Returns the amount of
+indentation change."
+  (interactive)
+  (let* ((syntax (vhdl-get-syntactic-context))
+	 (pos (- (point-max) (point)))
+	 (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
+	 (shift-amt  (- (current-indentation) indent)))
+    (and vhdl-echo-syntactic-information-p
+	 (message "syntax: %s, indent= %d" syntax indent))
+    (if (zerop shift-amt)
+	nil
+      (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
+      (beginning-of-line)
+      (indent-to indent))
+    (if (< (point) (vhdl-point 'boi))
+	(back-to-indentation)
+      ;; If initial point was within line's indentation, position after
+      ;; the indentation.  Else stay at same point in text.
+      (if (> (- (point-max) pos) (point))
+	  (goto-char (- (point-max) pos)))
+      )
+    (run-hooks 'vhdl-special-indent-hook)
+    shift-amt))
+
+(defun vhdl-indent-buffer ()
+  "Indent whole buffer as VHDL code."
+  (interactive)
+  (indent-region (point-min) (point-max) nil)
+  )
+
+(defun vhdl-indent-sexp (&optional endpos)
+  "Indent each line of the list starting just after point.
+If optional arg ENDPOS is given, indent each line, stopping when
+ENDPOS is encountered."
+  (interactive)
+  (save-excursion
+    (let ((beg (point))
+	  (end (progn
+		 (vhdl-forward-sexp nil endpos)
+		 (point))))
+      (indent-region beg end nil))))
+
+;; ############################################################################
+;; Miscellaneous commands
+
+(defun vhdl-show-syntactic-information ()
+  "Show syntactic information for current line."
+  (interactive)
+  (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
+  (vhdl-keep-region-active))
+
+;; Verification and regression functions:
+
+(defun vhdl-regress-line (&optional arg)
+  "Check syntactic information for current line."
+  (interactive "P")
+  (let ((expected (save-excursion
+		    (end-of-line)
+		    (if (search-backward " -- ((" (vhdl-point 'bol) t)
+			(progn
+			  (forward-char 4)
+			  (read (current-buffer))))))
+	(actual (vhdl-get-syntactic-context))
+	(expurgated))
+    ;; remove the library unit symbols
+    (mapcar
+     (function
+      (lambda (elt)
+	(if (memq (car elt) '(entity configuration package
+				     package-body architecture))
+	    nil
+	  (setq expurgated (append expurgated (list elt))))))
+     actual)
+    (if (and (not arg) expected (listp expected))
+	(if (not (equal expected expurgated))
+	    (error "Should be: %s, is: %s" expected expurgated))
+      (save-excursion
+	(beginning-of-line)
+	(if (not (looking-at "^\\s-*\\(--.*\\)?$"))
+	    (progn
+	      (end-of-line)
+	      (if (search-backward " -- ((" (vhdl-point 'bol) t)
+		  (kill-line))
+	      (insert " -- ")
+	      (insert (format "%s" expurgated)))))))
+  (vhdl-keep-region-active))
+
+
+;; ############################################################################
+;; Alignment
+;; ############################################################################
+
+(defvar vhdl-align-alist
+  '(
+    ;; after some keywords
+    (vhdl-mode "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)[ \t]"
+	       "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)\\([ \t]+\\)" 2)
+    ;; before ':'
+    (vhdl-mode ":[^=]" "[^ \t]\\([ \t]*\\):[^=]")
+    ;; after ':'
+    (vhdl-mode ":[^=]" ":\\([ \t]*\\)[^=]" 1)
+    ;; after direction specifications
+    (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\>"
+	       ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\([ \t]+\\)" 2)
+    ;; before "<=", "=>", and ":="
+    (vhdl-mode "<=" "[^ \t]\\([ \t]*\\)<=" 1)
+    (vhdl-mode "=>" "[^ \t]\\([ \t]*\\)=>" 1)
+    (vhdl-mode ":=" "[^ \t]\\([ \t]*\\):=" 1)
+    ;; after "<=", "=>", and ":="
+    (vhdl-mode "<=" "<=\\([ \t]*\\)" 1)
+    (vhdl-mode "=>" "=>\\([ \t]*\\)" 1)
+    (vhdl-mode ":=" ":=\\([ \t]*\\)" 1)
+    ;; before some keywords
+    (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
+    (vhdl-mode "[ \t]\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>"
+	       "[^ \t]\\([ \t]+\\)\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" 1)
+    (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
+    (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
+    (vhdl-mode "[ \t]is\\>" "[^ \t]\\([ \t]+\\)is\\>" 1)
+    (vhdl-mode "[ \t]of\\>" "[^ \t]\\([ \t]+\\)of\\>" 1)
+    (vhdl-mode "[ \t]use\\>" "[^ \t]\\([ \t]+\\)use\\>" 1)
+    ;; before comments (two steps required for correct insertion of two spaces)
+    (vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)
+    (vhdl-mode "--" "[^ \t][ \t]\\([ \t]*\\)--" 1)
+    )
+  "The format of this alist is
+  (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
+It is searched in order.  If REGEXP is found anywhere in the first
+line of a region to be aligned, ALIGN-PATTERN will be used for that
+region.  ALIGN-PATTERN must include the whitespace to be expanded or
+contracted. It may also provide regexps for the text surrounding the
+whitespace. SUBEXP specifies which sub-expression of
+ALIGN-PATTERN matches the white space to be expanded/contracted.")
+
+(defvar vhdl-align-try-all-clauses t
+  "If REGEXP is not found on the first line of the region that clause
+is ignored. If this variable is non-nil, then the clause is tried anyway.")
+
+(defun vhdl-align (begin end spacing &optional alignment-list quick)
+  "Attempt to align a range of lines based on the content of the
+lines.  The definition of 'alignment-list' determines the matching
+order and the manner in which the lines are aligned. If ALIGNMENT-LIST
+is not specified 'vhdl-align-alist' is used. If QUICK is non-nil, no
+indentation is done before aligning."
+  (interactive "r\np")
+  (if (not alignment-list)
+      (setq alignment-list vhdl-align-alist))
+  (if (not spacing)
+      (setq spacing 1))
+  (save-excursion
+    (let (bol indent)
+      (goto-char end)
+      (setq end (point-marker))
+      (goto-char begin)
+      (setq bol
+            (setq begin (progn (beginning-of-line) (point))))
+      (untabify bol end)
+      (if quick
+          nil
+        (indent-region bol end nil))))
+  (let ((copy (copy-alist alignment-list)))
+    (while copy
+      (save-excursion
+        (goto-char begin)
+        (let (element
+              (eol (save-excursion (progn (end-of-line) (point)))))
+          (setq element (nth 0 copy))
+          (if (and (or (and (listp (car element))
+                            (memq major-mode (car element)))
+                       (eq major-mode (car element)))
+                   (or vhdl-align-try-all-clauses
+                       (re-search-forward (car (cdr element)) eol t)))
+              (progn
+                (vhdl-align-region begin end (car (cdr (cdr element)))
+                              (car (cdr (cdr (cdr element)))) spacing)))
+          (setq copy (cdr copy)))))))
+
+(defun vhdl-align-region (begin end match &optional substr spacing)
+  "Align a range of lines from BEGIN to END.  The regular expression
+MATCH must match exactly one fields: the whitespace to be
+contracted/expanded.  The alignment column will equal the
+rightmost column of the widest whitespace block. SPACING is
+the amount of extra spaces to add to the calculated maximum required.
+SPACING defaults to 1 so that at least one space is inserted after
+the token in MATCH."
+  (if (not spacing)
+      (setq spacing 1))
+  (if (not substr)
+      (setq substr 1))
+  (save-excursion
+    (let (distance (max 0) (lines 0) bol eol width)
+      ;; Determine the greatest whitespace distance to the alignment
+      ;; character
+      (goto-char begin)
+      (setq eol (progn (end-of-line) (point))
+            bol (setq begin (progn (beginning-of-line) (point))))
+      (while (< bol end)
+        (save-excursion
+          (if (re-search-forward match eol t)
+              (progn
+                (setq distance (- (match-beginning substr) bol))
+                (if (> distance max)
+                    (setq max distance)))))
+        (forward-line)
+        (setq bol (point)
+              eol (save-excursion
+                    (end-of-line)
+                    (point)))
+        (setq lines (1+ lines)))
+      ;; Now insert enough maxs to push each assignment operator to
+      ;; the same column.  We need to use 'lines' as a counter, since
+      ;; the location of the mark may change
+      (goto-char (setq bol begin))
+      (setq eol (save-excursion
+                  (end-of-line)
+                  (point)))
+      (while (> lines 0)
+        (if (re-search-forward match eol t)
+            (progn
+              (setq width (- (match-end substr) (match-beginning substr)))
+              (setq distance (- (match-beginning substr) bol))
+              (goto-char (match-beginning substr))
+              (delete-char width)
+              (insert-char ?  (+ (- max distance) spacing))))
+        (beginning-of-line)
+        (forward-line)
+        (setq bol (point)
+              eol (save-excursion
+                    (end-of-line)
+                    (point)))
+        (setq lines (1- lines))
+        ))))
+
+(defun vhdl-align-comment-region (begin end spacing)
+  "Aligns inline comments within a region relative to first comment."
+  (interactive "r\nP")
+  (vhdl-align begin end (or spacing 2)
+	      `((vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)) t))
+
+(defun vhdl-align-noindent-region (begin end spacing)
+  "Align without indentation."
+  (interactive "r\nP")
+  (vhdl-align begin end spacing nil t)
+  )
+
+
+;; ############################################################################
+;; VHDL electrification
+;; ############################################################################
+
+;; ############################################################################
+;;  Stuttering
+
+(defun vhdl-stutter-mode-caps (count)
+  "Double first letters of a word replaced by a single capital of the letter."
+  (interactive "p")
+  (if vhdl-stutter-mode
+      (if (and
+	   (= (preceding-char) last-input-char) ; doubled
+	   (or (= (point) 2)		; beginning of buffer
+	       (/= (char-syntax (char-after (- (point) 2))) ?w) ;not mid-word
+	       (<               (char-after (- (point) 2))  ?A))) ;alfa-numeric
+	  (progn (delete-char -1) (insert-char (- last-input-char 32) count))
+	(self-insert-command count))
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-close-bracket (count) " ']' --> ')', ')]' --> ']'"
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (progn
+	(if (= (preceding-char) 41)	; close-paren
+	    (progn (delete-char -1) (insert-char 93 1)) ; close-bracket
+	  (insert-char 41 1)		; close-paren
+	  )
+	(blink-matching-open))
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-semicolon (count) " ';;' --> ' : ', ': ;' --> ' := '"
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (progn
+	(cond ((= (preceding-char) last-input-char)
+	       (progn (delete-char -1)
+		      (if (not (eq (preceding-char) ? )) (insert " "))
+		      (insert ": ")))
+	      ((and
+		(eq last-command 'vhdl-stutter-mode-colon) (= (preceding-char) ? ))
+	       (progn (delete-char -1) (insert "= ")))
+	      (t
+	       (insert-char 59 1))	; semi-colon
+	      )
+	(setq this-command 'vhdl-stutter-mode-colon))
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-open-bracket (count) " '[' --> '(', '([' --> '['"
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (if (= (preceding-char) 40)	; open-paren
+	  (progn (delete-char -1) (insert-char 91 1)) ; open-bracket
+	(insert-char 40 1))		; open-paren
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-quote (count) " '' --> \""
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (if (= (preceding-char) last-input-char)
+	  (progn (delete-backward-char 1) (insert-char 34 1)) ; double-quote
+	(insert-char 39 1))		; single-quote
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-comma (count) " ',,' --> ' <= '"
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (cond ((= (preceding-char) last-input-char)
+	     (progn (delete-char -1)
+		    (if (not (eq (preceding-char) ? )) (insert " "))
+		    (insert "<= ")))
+	    (t
+	     (insert-char 44 1)))	; comma
+    (self-insert-command count)
+    ))
+
+(defun vhdl-stutter-mode-period (count) " '..' --> ' => '"
+  (interactive "p")
+  (if (and vhdl-stutter-mode (= count 1))
+      (cond ((= (preceding-char) last-input-char)
+	     (progn (delete-char -1)
+		    (if (not (eq (preceding-char) ? )) (insert " "))
+		    (insert "=> ")))
+	    (t
+	     (insert-char 46 1)))	; period
+    (self-insert-command count)
+    ))
+
+(defun vhdl-paired-parens ()
+  "Insert a pair of round parentheses, placing point between them."
+  (interactive)
+  (insert "()")
+  (backward-char)
+  )
+
+(defun vhdl-stutter-mode-dash (count)
+  "-- starts a comment, --- draws a horizontal line,
+---- starts a display comment"
+  (interactive "p")
+  (if vhdl-stutter-mode
+      (cond ((and abbrev-start-location (= abbrev-start-location (point)))
+	     (setq abbrev-start-location nil)
+	     (goto-char last-abbrev-location)
+	     (beginning-of-line nil)
+	     (vhdl-display-comment))
+	    ((/= (preceding-char) ?-)	; standard dash (minus)
+	     (self-insert-command count))
+	    (t
+	     (self-insert-command count)
+	     (message "Enter - for horiz. line, CR for commenting-out code, else 1st char of comment")
+	     (let ((next-input (read-char)))
+	       (if (= next-input ?-)	; triple dash
+		   (progn
+		     (vhdl-display-comment-line)
+		     (message
+		      "Enter - for display comment, else continue with coding")
+		     (let ((next-input (read-char)))
+		       (if (= next-input ?-) ; four dashes
+			   (vhdl-display-comment t)
+			 (setq unread-command-events ;pushback the char
+			       (list
+				(vhdl-character-to-event-hack next-input)))
+			 )))
+		 (setq unread-command-events ;pushback the char
+		       (list (vhdl-character-to-event-hack next-input)))
+		 (vhdl-inline-comment)
+		 ))))
+    (self-insert-command count)
+    ))
+
+;; ############################################################################
+;;  VHDL templates
+
+(defun vhdl-alias ()
+  "Insert alias declaration."
+  (interactive)
+  (vhdl-insert-keyword "ALIAS ")
+  (if (equal (vhdl-field "name") "")
+      nil
+    (insert " : ")
+    (vhdl-field "type")
+    (vhdl-insert-keyword " IS ")
+    (vhdl-field "name" ";")
+    (vhdl-declaration-comment)
+    ))
+
+(defun vhdl-architecture ()
+  "Insert architecture template."
+  (interactive)
+  (let ((margin (current-column))
+	(vhdl-architecture-name)
+	(position)
+	(entity-exists)
+	(string)
+	(case-fold-search t))
+    (vhdl-insert-keyword "ARCHITECTURE ")
+    (if (equal (setq vhdl-architecture-name (vhdl-field "name")) "")
+	nil
+      (vhdl-insert-keyword " OF ")
+      (setq position (point))
+      (setq entity-exists
+	    (re-search-backward "entity \\(\\(\\w\\|\\s_\\)+\\) is" nil t))
+      (setq string (match-string 1))
+      (goto-char position)
+      (if (and entity-exists (not (equal string "")))
+  	  (insert string)
+        (vhdl-field "entity name"))
+      (vhdl-insert-keyword " IS")
+      (vhdl-begin-end (cons vhdl-architecture-name margin))
+      (vhdl-block-comment)
+      )))
+
+
+(defun vhdl-array ()
+  "Insert array type definition."
+  (interactive)
+  (vhdl-insert-keyword "ARRAY (")
+  (if (equal (vhdl-field "range") "")
+      (delete-char -1)
+    (vhdl-insert-keyword ") OF ")
+    (vhdl-field "type")
+    (vhdl-insert-keyword ";")
+    ))
+
+(defun vhdl-assert ()
+  "Inserts a assertion statement."
+  (interactive)
+  (vhdl-insert-keyword "ASSERT ")
+  (if vhdl-conditions-in-parenthesis (insert "("))
+  (if (equal (vhdl-field "condition (negated)") "")
+      (progn (undo 0) (insert " "))
+    (if vhdl-conditions-in-parenthesis (insert ")"))
+    (vhdl-insert-keyword " REPORT \"")
+    (vhdl-field "string-expression" "\" ")
+    (vhdl-insert-keyword "SEVERITY ")
+    (if (equal (vhdl-field "[note | warning | error | failure]") "")
+	(delete-char -10))
+    (insert ";")
+    ))
+
+(defun vhdl-attribute ()
+  "Inserts an attribute declaration or specification."
+  (interactive)
+  (vhdl-insert-keyword "ATTRIBUTE ")
+  (if (y-or-n-p "declaration (or specification)? ")
+      (progn
+	(vhdl-field "name" " : ")
+        (vhdl-field "type" ";")
+	(vhdl-declaration-comment))
+    (vhdl-field "name")
+    (vhdl-insert-keyword " OF ")
+    (vhdl-field "entity name" " : ")
+    (vhdl-field "entity class")
+    (vhdl-insert-keyword " IS ")
+    (vhdl-field "expression" ";")
+    ))
+
+(defun vhdl-block ()
+  "Insert a block template."
+  (interactive)
+  (let ((position (point)))
+    (vhdl-insert-keyword " : BLOCK ")
+    (goto-char position))
+  (let* ((margin (current-column))
+	 (name (vhdl-field "label")))
+    (if (equal name "")
+	(progn (undo 0) (insert " "))
+      (end-of-line)
+      (insert "(")
+      (if (equal (vhdl-field "[guard expression]") "")
+	  (delete-char -2)
+	(insert ")"))
+      (vhdl-begin-end (cons (concat (vhdl-case-keyword "BLOCK ") name) margin))
+      (vhdl-block-comment)
+      )))
+
+(defun vhdl-block-configuration ()
+  "Insert a block configuration statement."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-insert-keyword "FOR ")
+    (if (equal (setq name (vhdl-field "block specification")) "")
+	nil
+      (vhdl-insert-keyword "\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END FOR;")
+      (end-of-line 0)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-case ()
+  "Inserts a case statement."
+  (interactive)
+  (let ((margin (current-column))
+        (name))
+    (vhdl-insert-keyword "CASE ")
+    (if (equal (setq name (vhdl-field "expression")) "")
+	nil
+      (vhdl-insert-keyword " IS\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END CASE;")
+;      (if vhdl-self-insert-comments (insert "  -- " name))
+      (forward-line -1)
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-insert-keyword "WHEN  => ")
+      (backward-char 4)
+      )))
+
+(defun vhdl-component ()
+  "Inserts a component declaration."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-insert-keyword "COMPONENT ")
+    (if (equal (vhdl-field "name") "")
+	nil
+      (insert "\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END COMPONENT;")
+      (end-of-line -0)
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-insert-keyword "GENERIC (")
+      (vhdl-get-generic t t)
+      (insert "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-insert-keyword "PORT (")
+      (vhdl-get-port t t)
+      (forward-line 1))
+    ))
+
+(defun vhdl-component-configuration ()
+  "Inserts a component configuration (uses `vhdl-configuration-spec' since
+these are almost equivalent)."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-configuration-spec)
+    (insert "\n")
+    (indent-to margin)
+    (vhdl-insert-keyword "END FOR;")
+    ))
+
+(defun vhdl-component-instance ()
+  "Inserts a component instantiation statement."
+  (interactive)
+  (let ((margin (current-column)))
+    (if (equal (vhdl-field "instance label") "")
+	nil
+      (insert " : ")
+      (vhdl-field "component name" "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (let ((position (point)))
+	(vhdl-insert-keyword "GENERIC MAP (")
+	(if (equal (vhdl-field "[association list]") "")
+	    (progn (goto-char position)
+		   (kill-line))
+	  (insert ")\n")
+	  (indent-to (+ margin vhdl-basic-offset))))
+      (vhdl-insert-keyword "PORT MAP (")
+      (vhdl-field "association list" ");")
+    )))
+
+(defun vhdl-concurrent-signal-assignment ()
+  "Inserts a concurrent signal assignment."
+  (interactive)
+  (if (equal (vhdl-field "target signal") "")
+      nil
+    (insert " <= ")
+;    (if (not (equal (vhdl-field "[GUARDED] [TRANSPORT]") ""))
+;	(insert " "))
+    (let ((margin (current-column))
+	  (start (point)))
+      (vhdl-field "waveform")
+      (vhdl-insert-keyword " WHEN ")
+      (if vhdl-conditions-in-parenthesis (insert "("))
+      (while (not (equal (vhdl-field "[condition]") ""))
+	(if vhdl-conditions-in-parenthesis (insert ")"))
+	(vhdl-insert-keyword " ELSE")
+	(insert "\n")
+	(indent-to margin)
+	(vhdl-field "waveform")
+	(vhdl-insert-keyword " WHEN ")
+	(if vhdl-conditions-in-parenthesis (insert "(")))
+      (delete-char -6)
+      (if vhdl-conditions-in-parenthesis (delete-char -1))
+      (insert ";")
+      (if vhdl-auto-align (vhdl-align start (point) 1))
+      )))
+
+(defun vhdl-configuration ()
+  "Inserts a configuration specification if within an architecture,
+a block or component configuration if within a configuration declaration,
+a configuration declaration if not within a design unit."
+  (interactive)
+  (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'architecture)
+	 (vhdl-configuration-spec))
+	((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
+	 (if (y-or-n-p "block configuration (or component configuration)? ")
+	     (vhdl-block-configuration)
+	   (vhdl-component-configuration)))
+	(t (vhdl-configuration-decl)))
+  )
+
+(defun vhdl-configuration-spec ()
+  "Inserts a configuration specification."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-insert-keyword "FOR ")
+    (if (equal (vhdl-field "(component names | ALL)" " : ") "")
+	(progn (undo 0) (insert " "))
+      (vhdl-field "component type" "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-insert-keyword "USE ENTITY ")
+      (vhdl-field "library name" ".")
+      (vhdl-field "entity name" "(")
+      (if (equal (vhdl-field "[architecture name]") "")
+	  (delete-char -1)
+	(insert ")"))
+      (insert "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-insert-keyword "GENERIC MAP (")
+      (if (equal (vhdl-field "[association list]") "")
+	  (progn (kill-line -0)
+		 (indent-to (+ margin vhdl-basic-offset)))
+	(insert ")\n")
+	(indent-to (+ margin vhdl-basic-offset)))
+      (vhdl-insert-keyword "PORT MAP (")
+      (if (equal (vhdl-field "[association list]") "")
+	  (progn (kill-line -0)
+		 (delete-char -1))
+	(insert ")"))
+      (insert ";")
+      )))
+
+(defun vhdl-configuration-decl ()
+  "Inserts a configuration declaration."
+  (interactive)
+  (let ((margin (current-column))
+	(position)
+	(entity-exists)
+	(string)
+	(name))
+    (vhdl-insert-keyword "CONFIGURATION ")
+    (if (equal (setq name (vhdl-field "name")) "")
+	nil
+      (vhdl-insert-keyword " OF ")
+      (setq position (point))
+      (setq entity-exists
+	    (re-search-backward "entity \\(\\(\\w\\|\\s_\\)*\\) is" nil t))
+      (setq string (match-string 1))
+      (goto-char position)
+      (if (and entity-exists (not (equal string "")))
+  	  (insert string)
+        (vhdl-field "entity name"))
+      (vhdl-insert-keyword " IS\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END ")
+      (insert name ";")
+      (end-of-line 0)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-constant ()
+  "Inserts a constant declaration."
+  (interactive)
+  (vhdl-insert-keyword "CONSTANT ")
+  (let ((in-arglist (string-match "arglist"
+		     (format "%s" (car (car (vhdl-get-syntactic-context)))))))
+    (if (not in-arglist)
+	(let ((opoint (point)))
+	  (beginning-of-line)
+	  (setq in-arglist (looking-at ".*("))
+	  (goto-char opoint)))
+    (if (equal  (vhdl-field "name") "")
+	nil
+      (insert " : ")
+      (if in-arglist (vhdl-insert-keyword "IN "))
+      (vhdl-field "type")
+      (if in-arglist
+	  (insert ";")
+	(let ((position (point)))
+	  (insert " := ")
+	  (if (equal (vhdl-field "[initialization]" ";") "")
+	      (progn (goto-char position) (kill-line) (insert ";")))
+	  (vhdl-declaration-comment))
+    ))))
+
+(defun vhdl-default ()
+  "Insert nothing."
+  (interactive)
+  (insert " ")
+  (unexpand-abbrev)
+  (backward-word 1)
+  (vhdl-case-word 1)
+  (forward-char 1)
+  )
+
+(defun vhdl-default-indent ()
+  "Insert nothing and indent."
+  (interactive)
+  (insert " ")
+  (unexpand-abbrev)
+  (backward-word 1)
+  (vhdl-case-word 1)
+  (forward-char 1)
+  (vhdl-indent-line)
+  )
+
+(defun vhdl-disconnect ()
+  "Insert a disconnect statement."
+  (interactive)
+  (vhdl-insert-keyword "DISCONNECT ")
+  (if (equal (vhdl-field "guarded signal specification") "")
+      nil
+    (vhdl-insert-keyword " AFTER ")
+    (vhdl-field "time expression" ";")
+  ))
+
+(defun vhdl-else ()
+  "Insert an else statement."
+  (interactive)
+  (let ((margin))
+    (vhdl-insert-keyword "ELSE")
+    (if (not (equal 'block-close (car (car (vhdl-get-syntactic-context)))))
+	(insert " ")
+      (vhdl-indent-line)
+      (setq margin (current-indentation))
+      (insert "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+    )))
+
+(defun vhdl-elsif ()
+  "Insert an elsif statement."
+  (interactive)
+  (let ((margin))
+    (vhdl-insert-keyword "ELSIF ")
+    (if vhdl-conditions-in-parenthesis (insert "("))
+    (if (equal (vhdl-field "condition") "")
+	(progn (undo 0) (insert " "))
+      (if vhdl-conditions-in-parenthesis (insert ")"))
+      (vhdl-indent-line)
+      (setq margin (current-indentation))
+      (vhdl-insert-keyword " THEN\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-entity ()
+  "Insert an entity template."
+  (interactive)
+  (let ((margin (current-column))
+	(vhdl-entity-name))
+    (vhdl-insert-keyword "ENTITY ")
+    (if (equal (setq vhdl-entity-name (vhdl-field "entity name")) "")
+	nil
+      (vhdl-insert-keyword " IS\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END ")
+      (insert vhdl-entity-name ";")
+      (end-of-line -0)
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-entity-body)
+      )))
+
+(defun vhdl-entity-body ()
+  "Insert an entity body."
+  (interactive)
+  (let ((margin (current-column)))
+    (if vhdl-additional-empty-lines (insert "\n"))
+    (indent-to margin)
+    (vhdl-insert-keyword "GENERIC (")
+    (if (vhdl-get-generic t)
+	(if vhdl-additional-empty-lines (insert "\n")))
+    (insert "\n")
+    (indent-to margin)
+    (vhdl-insert-keyword "PORT (")
+    (if (vhdl-get-port t)
+	(if vhdl-additional-empty-lines (insert "\n")))
+    (end-of-line 2)
+    ))
+
+(defun vhdl-exit ()
+  "Insert an exit statement."
+  (interactive)
+  (vhdl-insert-keyword "EXIT ")
+  (if (string-equal (vhdl-field "[loop label]") "")
+      (delete-char -1))
+  (let ((opoint (point)))
+    (vhdl-insert-keyword " WHEN ")
+    (if vhdl-conditions-in-parenthesis (insert "("))
+    (if (equal (vhdl-field "[condition]") "")
+      (progn (goto-char opoint)
+	     (kill-line))
+      (if vhdl-conditions-in-parenthesis (insert ")"))))
+  (insert ";")
+  )
+
+(defun vhdl-for ()
+  "Inserts a block or component configuration if within a configuration
+declaration, a for loop otherwise."
+  (interactive)
+  (if (equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
+      (if (y-or-n-p "block configuration (or component configuration)? ")
+	  (vhdl-block-configuration)
+	(vhdl-component-configuration))
+    (vhdl-for-loop)))
+
+(defun vhdl-for-loop ()
+  "Insert a for loop template."
+  (interactive)
+  (let ((position (point)))
+    (vhdl-insert-keyword " : FOR ")
+    (goto-char position))
+  (let* ((margin (current-column))
+	 (name (vhdl-field "[label]"))
+	 (named (not (string-equal name "")))
+	 (index))
+    (if (not named) (delete-char 3))
+    (end-of-line)
+    (if (equal (setq index (vhdl-field "loop variable")) "")
+	nil
+      (vhdl-insert-keyword " IN ")
+      (vhdl-field "range")
+      (vhdl-insert-keyword " LOOP\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END LOOP")
+      (if named (insert " " name ";")
+	(insert ";")
+	(if vhdl-self-insert-comments (insert "  -- " index)))
+      (forward-line -1)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-function ()
+  "Insert function specification or body template."
+  (interactive)
+  (let ((margin (current-column))
+	(name))
+    (vhdl-insert-keyword "FUNCTION ")
+    (if (equal (setq name (vhdl-field "name")) "")
+	nil
+      (vhdl-get-arg-list)
+      (vhdl-insert-keyword " RETURN ")
+      (vhdl-field "type" " ")
+      (if (y-or-n-p "insert body? ")
+	  (progn (vhdl-insert-keyword "IS")
+	         (vhdl-begin-end (cons name margin))
+		 (vhdl-block-comment))
+        (delete-char -1)
+        (insert ";\n")
+        (indent-to margin)))
+    ))
+
+(defun vhdl-generate ()
+  "Insert a generate template."
+  (interactive)
+  (let ((position (point)))
+    (vhdl-insert-keyword " GENERATE")
+    (goto-char position))
+  (let ((margin (current-column))
+	(label (vhdl-field "label"))
+	(string))
+    (if (equal label "")
+	(progn (undo 0) (insert " "))
+      (insert " : ")
+      (setq string (vhdl-field "(FOR | IF)"))
+      (insert " ")
+      (if (equal (upcase string) "IF")
+	  (progn
+	    (if vhdl-conditions-in-parenthesis (insert "("))
+	    (vhdl-field "condition")
+	    (if vhdl-conditions-in-parenthesis (insert ")")))
+        (vhdl-field "loop variable")
+	(vhdl-insert-keyword " IN ")
+	(vhdl-field "range"))
+      (end-of-line)
+      (insert "\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END GENERATE ")
+      (insert label ";")
+      (end-of-line 0)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-generic ()
+  "Insert generic declaration, or generic map in instantiation statements."
+  (interactive)
+  (vhdl-insert-keyword "GENERIC (")
+  (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
+	 (vhdl-get-generic nil))
+	((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
+	  (save-excursion
+	   (and (backward-word 2) (skip-chars-backward " ")
+		(eq (preceding-char) ?:))))
+	 (delete-char -1) (vhdl-map))
+	(t (vhdl-get-generic nil t))))
+
+(defun vhdl-header ()
+  "Insert a VHDL file header."
+  (interactive)
+  (let (eot)
+    (save-excursion
+      (save-restriction
+ 	(widen)
+	(goto-char (point-min))
+	(if vhdl-header-file
+	    (setq eot (car (cdr (insert-file-contents vhdl-header-file))))
+	  ; insert default header
+	  (insert "\
+-------------------------------------------------------------------------------
+-- Title         : <title string>
+-- Project       : <project string>
+-------------------------------------------------------------------------------
+-- File          : <filename>
+-- Author        : <author>
+-- Created       : <date>
+-- Last modified : <date>
+-------------------------------------------------------------------------------
+-- Description :
+-- <cursor>
+-------------------------------------------------------------------------------
+-- Modification history :
+-- <date> : created
+-------------------------------------------------------------------------------
+
+")
+	  (setq eot (point)))
+ 	(narrow-to-region (point-min) eot)
+	(goto-char (point-min))
+	(while (search-forward "<filename>" nil t)
+	  (replace-match (buffer-name) t t))
+	(goto-char (point-min))
+	(while (search-forward "<author>" nil t)
+	  (replace-match "" t t)
+	  (insert (user-full-name) "  <" user-mail-address ">"))
+	(goto-char (point-min))
+ 	;; Replace <RCS> with $, so that RCS for the source is
+ 	;; not over-enthusiastic with replacements
+ 	(while (search-forward "<RCS>" nil t)
+ 	  (replace-match "$" nil t))
+	(goto-char (point-min))
+	(while (search-forward "<date>" nil t)
+	  (replace-match "" t t)
+	  (vhdl-insert-date))
+	(goto-char (point-min))
+	(let (string)
+	  (while (re-search-forward "<\\(\\w*\\) string>" nil t)
+	    (setq string (read-string (concat (match-string 1) ": ")))
+	    (replace-match string t t)))))
+    (goto-char (point-min))
+    (if (search-forward "<cursor>" nil t)
+	(replace-match "" t t))))
+
+(defun vhdl-if ()
+  "Insert an if statement template."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-insert-keyword "IF ")
+    (if vhdl-conditions-in-parenthesis (insert "("))
+    (if (equal (vhdl-field "condition") "")
+	(progn (undo 0) (insert " "))
+      (if vhdl-conditions-in-parenthesis (insert ")"))
+      (vhdl-insert-keyword " THEN\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END IF;")
+      (forward-line -1)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-library ()
+  "Insert a library specification."
+  (interactive)
+  (let ((margin (current-column))
+	(lib-name))
+    (vhdl-insert-keyword "LIBRARY ")
+    (if (equal  (setq lib-name (vhdl-field "library name")) "")
+	nil
+      (insert ";\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "USE ")
+      (insert lib-name)
+      (vhdl-insert-keyword "..ALL;")
+      (backward-char 5)
+      (if (equal (vhdl-field "package name") "")
+	  (progn (vhdl-kill-entire-line)
+	         (end-of-line -0))
+        (end-of-line)
+	))))
+
+(defun vhdl-loop ()
+  "Insert a loop template."
+  (interactive)
+  (let ((position (point)))
+    (vhdl-insert-keyword " : LOOP")
+    (goto-char position))
+  (let* ((margin (current-column))
+	 (name (vhdl-field "[label]"))
+	 (named (not (string-equal name ""))))
+    (if (not named) (delete-char 3))
+    (end-of-line)
+    (insert "\n\n")
+    (indent-to margin)
+    (vhdl-insert-keyword "END LOOP")
+    (insert (if named (concat " " name ";") ?;))
+    (forward-line -1)
+    (indent-to (+ margin vhdl-basic-offset))
+    ))
+
+(defun vhdl-map ()
+  "Insert a map specification."
+  (interactive)
+  (vhdl-insert-keyword "MAP (")
+  (if (equal (vhdl-field "[association list]") "")
+      (progn (undo 0) (insert " "))
+    (insert ")")
+    ))
+
+(defun vhdl-modify ()
+  "Actualize modification date."
+  (interactive)
+  (goto-char (point-min))
+  (if (search-forward vhdl-modify-date-prefix-string nil t)
+      (progn (kill-line)
+	     (vhdl-insert-date))
+    (message (concat "Modification date prefix string \""
+		     vhdl-modify-date-prefix-string
+		     "\" not found!"))
+    (beep)))
+
+(defun vhdl-next ()
+  "Inserts a next statement."
+  (interactive)
+  (vhdl-insert-keyword "NEXT ")
+  (if (string-equal (vhdl-field "[loop label]") "")
+      (delete-char -1))
+  (let ((opoint (point)))
+    (vhdl-insert-keyword " WHEN ")
+    (if vhdl-conditions-in-parenthesis (insert "("))
+    (if (equal (vhdl-field "[condition]") "")
+	(progn (goto-char opoint)
+	       (kill-line))
+      (if vhdl-conditions-in-parenthesis (insert ")"))))
+  (insert ";")
+  )
+
+(defun vhdl-package ()
+  "Insert a package specification or body."
+  (interactive)
+  (let ((margin (current-column))
+	(name))
+    (vhdl-insert-keyword "PACKAGE ")
+    (if (y-or-n-p "body? ")
+	(vhdl-insert-keyword "BODY "))
+    (setq name (vhdl-field "name" " is\n\n"))
+    (indent-to margin)
+    (vhdl-insert-keyword "END ")
+    (insert name ";")
+    (forward-line -1)
+    (indent-to (+ margin vhdl-basic-offset))
+    ))
+
+(defun vhdl-port ()
+  "Insert a port declaration, or port map in instantiation statements."
+  (interactive)
+  (vhdl-insert-keyword "PORT (")
+  (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
+	 (vhdl-get-port nil))
+	((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
+	  (save-excursion
+	   (and (backward-word 2) (skip-chars-backward " ")
+		(eq (preceding-char) ?:))))
+	 (delete-char -1) (vhdl-map))
+	(t (vhdl-get-port nil t))))
+
+(defun vhdl-procedure ()
+  "Insert a procedure specification or body template."
+  (interactive)
+  (let ((margin (current-column))
+	(name))
+    (vhdl-insert-keyword "PROCEDURE ")
+    (if (equal (setq name (vhdl-field "name")) "")
+	nil
+      (vhdl-get-arg-list)
+      (insert " ")
+      (if (y-or-n-p "insert body? ")
+	  (progn (vhdl-insert-keyword "IS")
+	         (vhdl-begin-end (cons name margin))
+		 (vhdl-block-comment))
+        (delete-char -1)
+        (insert ";\n")
+        (indent-to margin)
+	))))
+
+(defun vhdl-process ()
+  "Insert a process template."
+  (interactive)
+  (let ((clocked))
+    (let ((position (point)))
+      (vhdl-insert-keyword "PROCESS")
+      (setq clocked (y-or-n-p "clocked process? "))
+      (goto-char position)
+      (insert " : ")
+      (goto-char position))
+    (let* ((margin (current-column))
+           (finalline)
+	   (name (vhdl-field "[label]"))
+	   (named (not (string-equal name "")))
+	   (clock) (reset)
+	   (case-fold-search t))
+      (if (not named) (delete-char 3))
+      (end-of-line)
+      (insert " (")
+      (if (not clocked)
+	  (if (equal (vhdl-field "[sensitivity list]" ")") "")
+	      (delete-char -3))
+        (setq clock (vhdl-field "clock name" ", "))
+        (setq reset (vhdl-field "reset name" ")")))
+      (vhdl-begin-end (cons (concat (vhdl-case-keyword "PROCESS")
+				    (if named (concat " " name))) margin))
+      (if clocked (vhdl-clock-async-reset clock reset))
+      (if vhdl-prompt-for-comments
+	  (progn
+	    (setq finalline (vhdl-current-line))
+	    (if (and (re-search-backward "\\<begin\\>" nil t)
+		     (re-search-backward "\\<process\\>" nil t))
+		(progn
+		  (end-of-line -0)
+		  (insert "\n")
+		  (indent-to margin)
+		  (insert "-- purpose: ")
+		  (if (equal (vhdl-field "description") "")
+		      (vhdl-kill-entire-line)
+		    (newline)
+		    (indent-to margin)
+		    (insert "-- type:    ")
+		    (insert (if clocked "memorizing" "memoryless") "\n")
+		    (indent-to margin)
+		    (insert "-- inputs:  ")
+		    (if clocked
+			(insert clock ", " reset ", "))
+		    (if (and (equal (vhdl-field "signal names") "")
+			     clocked)
+			(delete-char -2))
+		    (insert "\n")
+		    (indent-to margin)
+		    (insert "-- outputs: ")
+		    (vhdl-field "signal names")
+		    (setq finalline (+ finalline 4)))))
+	    (goto-line finalline)
+	    (end-of-line)
+	    )))))
+
+(defun vhdl-record ()
+  "Insert a record type declaration."
+  (interactive)
+  (let ((margin (current-column))
+	(start (point))
+	(first t))
+    (vhdl-insert-keyword "RECORD\n")
+    (indent-to (+ margin vhdl-basic-offset))
+    (if (equal (vhdl-field "identifiers") "")
+	(progn (kill-line -0)
+	       (delete-char -1)
+	       (insert " "))
+      (while (or first (not (equal (vhdl-field "[identifiers]") "")))
+        (insert " : ")
+        (vhdl-field "type" ";")
+        (vhdl-declaration-comment)
+        (newline)
+	(indent-to (+ margin vhdl-basic-offset))
+        (setq first nil))
+      (kill-line -0)
+      (indent-to margin)
+      (vhdl-insert-keyword "END RECORD;")
+      (if vhdl-auto-align (vhdl-align start (point) 1))
+      )))
+
+(defun vhdl-return-value ()
+  "Insert a return statement."
+  (interactive)
+  (vhdl-insert-keyword "RETURN ")
+  (if (equal (vhdl-field "[expression]") "")
+      (delete-char -1))
+  (insert ";")
+  )
+
+(defun vhdl-selected-signal-assignment ()
+  "Insert a selected signal assignment."
+  (interactive)
+  (let ((margin (current-column))
+	(start (point)))
+    (let ((position (point)))
+      (vhdl-insert-keyword " SELECT")
+      (goto-char position))
+    (vhdl-insert-keyword "WITH ")
+    (if (equal (vhdl-field "selector expression") "")
+	(progn (undo 0) (insert " "))
+      (end-of-line)
+      (insert "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (vhdl-field "target signal" " <= ")
+;      (vhdl-field "[GUARDED] [TRANSPORT]")
+      (insert "\n")
+      (indent-to (+ margin vhdl-basic-offset))
+      (while (not (equal (vhdl-field "[waveform]") ""))
+	(vhdl-insert-keyword " WHEN ")
+	(vhdl-field "choices" ",")
+	(newline)
+	(indent-to (+ margin vhdl-basic-offset)))
+      (if (not (equal (vhdl-field "[alternative waveform]") ""))
+	  (vhdl-insert-keyword " WHEN OTHERS")
+	(fixup-whitespace)
+	(delete-char -2))
+      (insert ";")
+      (if vhdl-auto-align (vhdl-align start (point) 1))
+      )))
+
+(defun vhdl-signal ()
+  "Insert a signal declaration."
+  (interactive)
+  (vhdl-insert-keyword "SIGNAL ")
+  (let ((in-arglist (string-match "arglist"
+		     (format "%s" (car (car (vhdl-get-syntactic-context)))))))
+    (if (not in-arglist)
+	(let ((opoint (point)))
+	  (beginning-of-line)
+	  (setq in-arglist (looking-at ".*("))
+	  (goto-char opoint)))
+    (if (equal (vhdl-field "names") "")
+	nil
+      (insert " : ")
+      (if in-arglist
+	  (progn (vhdl-field "direction")
+		 (insert " ")))
+      (vhdl-field "type")
+      (if in-arglist
+	  (insert ";")
+	(let ((position (point)))
+	  (insert " := ")
+	  (if (equal (vhdl-field "[initialization]" ";") "")
+	      (progn (goto-char position) (kill-line) (insert ";")))
+	  (vhdl-declaration-comment))
+	))))
+
+(defun vhdl-subtype ()
+  "Insert a subtype declaration."
+  (interactive)
+  (vhdl-insert-keyword "SUBTYPE ")
+  (if (equal (vhdl-field "name") "")
+      nil
+    (vhdl-insert-keyword " IS ")
+    (vhdl-field "type" " ")
+    (if (equal (vhdl-field "[RANGE value range | ( index range )]") "")
+	(delete-char -1))
+    (insert ";")
+    (vhdl-declaration-comment)
+    ))
+
+(defun vhdl-type ()
+  "Insert a type declaration."
+  (interactive)
+  (vhdl-insert-keyword "TYPE ")
+  (if (equal (vhdl-field "name") "")
+      nil
+    (vhdl-insert-keyword " IS ")
+    (let ((definition (upcase (vhdl-field "(scalar type | ARRAY | RECORD | ACCESS | FILE)"))))
+      (cond ((equal definition "ARRAY")
+	     (kill-word -1) (vhdl-array))
+            ((equal definition "RECORD")
+	     (kill-word -1) (vhdl-record))
+            ((equal definition "ACCESS")
+	     (insert " ") (vhdl-field "type" ";"))
+            ((equal definition "FILE")
+	     (vhdl-insert-keyword " OF ") (vhdl-field "type" ";"))
+	    (t (insert ";")))
+      (vhdl-declaration-comment)
+      )))
+
+(defun vhdl-use ()
+  "Insert a use clause."
+  (interactive)
+  (vhdl-insert-keyword "USE ..ALL;")
+  (backward-char 6)
+  (if (equal (vhdl-field "library name") "")
+      (progn (undo 0) (insert " "))
+    (forward-char 1)
+    (vhdl-field "package name")
+    (end-of-line)
+    ))
+
+(defun vhdl-variable ()
+  "Insert a variable declaration."
+  (interactive)
+  (vhdl-insert-keyword "VARIABLE ")
+  (let ((in-arglist (string-match "arglist"
+		     (format "%s" (car (car (vhdl-get-syntactic-context)))))))
+    (if (not in-arglist)
+	(let ((opoint (point)))
+	  (beginning-of-line)
+	  (setq in-arglist (looking-at ".*("))
+	  (goto-char opoint)))
+    (if (equal (vhdl-field "names") "")
+	nil
+      (insert " : ")
+      (if in-arglist
+	  (progn (vhdl-field "direction")
+		 (insert " ")))
+      (vhdl-field "type")
+      (if in-arglist
+	  (insert ";")
+	(let ((position (point)))
+	  (insert " := ")
+	  (if (equal (vhdl-field "[initialization]" ";") "")
+	      (progn (goto-char position) (kill-line) (insert ";")))
+	  (vhdl-declaration-comment))
+    ))))
+
+(defun vhdl-wait ()
+  "Insert a wait statement."
+  (interactive)
+  (vhdl-insert-keyword "WAIT ")
+  (if (equal (vhdl-field
+	      "[ON sensitivity list] [UNTIL condition] [FOR time expression]")
+	     "")
+      (delete-char -1))
+  (insert ";")
+  )
+
+(defun vhdl-when ()
+  "Indent correctly if within a case statement."
+  (interactive)
+  (let ((position (point))
+	(margin))
+    (if (and (re-search-forward "\\<end\\>" nil t)
+	     (looking-at "\\s-*\\<case\\>"))
+	(progn
+	  (setq margin (current-indentation))
+	  (goto-char position)
+	  (delete-horizontal-space)
+	  (indent-to (+ margin vhdl-basic-offset)))
+      (goto-char position)
+      )
+    (vhdl-insert-keyword "WHEN ")
+    ))
+
+(defun vhdl-while-loop ()
+  "Insert a while loop template."
+  (interactive)
+  (let ((position (point)))
+    (vhdl-insert-keyword " : WHILE ")
+    (goto-char position))
+  (let* ((margin (current-column))
+	 (name (vhdl-field "[label]"))
+	 (named (not (string-equal name ""))))
+    (if (not named) (delete-char 3))
+    (end-of-line)
+    (if vhdl-conditions-in-parenthesis (insert "("))
+    (if (equal (vhdl-field "condition") "")
+	(progn (undo 0) (insert " "))
+      (if vhdl-conditions-in-parenthesis (insert ")"))
+      (vhdl-insert-keyword " LOOP\n\n")
+      (indent-to margin)
+      (vhdl-insert-keyword "END LOOP")
+      (insert (if named (concat " " name ";") ?;))
+      (forward-line -1)
+      (indent-to (+ margin vhdl-basic-offset))
+      )))
+
+(defun vhdl-with ()
+  "Insert a with statement (i.e. selected signal assignment)."
+  (interactive)
+  (vhdl-selected-signal-assignment)
+  )
+
+;; ############################################################################
+;; Custom functions
+
+(defun vhdl-clocked-wait ()
+  "Insert a wait statement for rising clock edge."
+  (interactive)
+  (vhdl-insert-keyword "WAIT UNTIL ")
+  (let* ((clock  (vhdl-field "clock name")))
+    (insert "'event")
+    (vhdl-insert-keyword " AND ")
+    (insert clock)
+    (insert " = " vhdl-one-string ";")
+  ))
+
+(defun vhdl-clock-async-reset (clock reset)
+  "Insert a template reacting on asynchronous reset and rising clock edge
+for inside a memorizing processes."
+  (interactive)
+  (let* ( (margin (current-column))
+	  (opoint))
+    (if vhdl-self-insert-comments
+       (insert "-- activities triggered by asynchronous reset (active low)\n"))
+    (indent-to margin)
+    (vhdl-insert-keyword "IF ")
+    (insert reset " = " vhdl-zero-string)
+    (vhdl-insert-keyword " THEN\n")
+    (indent-to (+ margin vhdl-basic-offset))
+    (setq opoint (point))
+    (newline)
+    (indent-to margin)
+    (if vhdl-self-insert-comments
+	(insert "-- activities triggered by rising edge of clock\n"))
+    (indent-to margin)
+    (vhdl-insert-keyword "ELSIF ")
+    (insert clock "'event")
+    (vhdl-insert-keyword " AND ")
+    (insert clock " = " vhdl-one-string)
+    (vhdl-insert-keyword " THEN\n")
+    (indent-to (+ margin vhdl-basic-offset))
+    (newline)
+    (indent-to margin)
+    (vhdl-insert-keyword "END IF;")
+;    (if vhdl-self-insert-comments (insert "  -- " clock))
+    (goto-char opoint)
+    ))
+
+(defun vhdl-standard-package (library package)
+  "Insert specification of a standard package."
+  (interactive)
+  (let ((margin (current-column)))
+    (vhdl-insert-keyword "LIBRARY ")
+    (insert library ";\n")
+    (indent-to margin)
+    (vhdl-insert-keyword "USE ")
+    (insert library "." package)
+    (vhdl-insert-keyword ".ALL;")
+    ))
+
+(defun vhdl-package-numeric-bit ()
+  "Insert specification of 'numeric_bit' package."
+  (interactive)
+  (vhdl-standard-package "ieee" "numeric_bit"))
+
+(defun vhdl-package-numeric-std ()
+  "Insert specification of 'numeric_std' package."
+  (interactive)
+  (vhdl-standard-package "ieee" "numeric_std"))
+
+(defun vhdl-package-std-logic-1164 ()
+  "Insert specification of 'std_logic_1164' package."
+  (interactive)
+  (vhdl-standard-package "ieee" "std_logic_1164"))
+
+(defun vhdl-package-textio ()
+  "Insert specification of 'textio' package."
+  (interactive)
+  (vhdl-standard-package "std" "textio"))
+
+;; ############################################################################
+;; Comment functions
+
+(defun vhdl-comment-indent ()
+  (let* ((opoint (point))
+	(col (progn
+	       (forward-line -1)
+	       (if (re-search-forward "--" opoint t)
+		   (- (current-column) 2) ;Existing comment at bol stays there.
+		 (goto-char opoint)
+		 (skip-chars-backward " \t")
+		 (max comment-column  ;else indent to comment column
+		      (1+ (current-column))) ;except leave at least one space.
+		 ))))
+    (goto-char opoint)
+    col
+    ))
+
+(defun vhdl-inline-comment ()
+  "Start a comment at the end of the line.
+  if on line with code, indent at least comment-column.
+  if starting after end-comment-column, start a new line."
+  (interactive)
+  (if (> (current-column) end-comment-column) (newline-and-indent))
+  (if (or (looking-at "\\s-*$")	;end of line
+	  (and (not unread-command-events) ; called with key binding or menu
+	       (not (end-of-line))))
+      (let ((margin))
+        (while (= (preceding-char) ?-) (delete-char -1))
+	(setq margin (current-column))
+        (delete-horizontal-space)
+        (if (bolp)
+            (progn (indent-to margin) (insert "--"))
+	  (insert "  ")
+          (indent-to comment-column)
+          (insert "--"))
+	(if (not unread-command-events) (insert " ")))
+     ; else code following current point implies commenting out code
+    (let (next-input code)
+      (while (= (preceding-char) ?-) (delete-char -2))
+      (while (= (setq next-input (read-char)) 13) ; CR
+	(insert "--"); or have a space after it?
+	(forward-char -2)
+	(forward-line 1)
+	(message "Enter CR if commenting out a line of code.")
+	(setq code t)
+	)
+      (if (not code) (progn
+;	  (indent-to comment-column)
+	  (insert "--") ;hardwire to 1 space or use vhdl-basic-offset?
+	  ))
+      (setq unread-command-events
+	    (list (vhdl-character-to-event-hack next-input))) ;pushback the char
+      )))
+
+(defun vhdl-display-comment (&optional line-exists)
+  "Add 2 comment lines at the current indent, making a display comment."
+  (interactive)
+  (if (not line-exists)
+      (vhdl-display-comment-line))
+  (let* ((col (current-column))
+	 (len (- end-comment-column col)))
+    (insert "\n")
+    (insert-char ?  col)
+    (insert-char ?- len)
+    (insert "\n")
+    (insert-char ?  col)
+    (end-of-line -1)
+    )
+  (insert "-- ")
+  )
+
+(defun vhdl-display-comment-line ()
+  "Displays one line of dashes."
+  (interactive)
+  (while (= (preceding-char) ?-) (delete-char -2))
+  (let* ((col (current-column))
+	 (len (- end-comment-column col)))
+    (insert-char ?- len)
+    (insert-char ?\n 1)
+    (insert-char ?  col)
+    ))
+
+(defun vhdl-declaration-comment ()
+  (if vhdl-prompt-for-comments
+      (let ((position (point)))
+	(insert "  ")
+	(indent-to comment-column)
+	(insert "-- ")
+	(if (equal (vhdl-field "comment") "")
+	    (progn (goto-char position) (kill-line))
+	  ))))
+
+(defun vhdl-block-comment ()
+  (if vhdl-prompt-for-comments
+      (let ((finalline (vhdl-current-line))
+	    (case-fold-search t))
+	(beginning-of-line -0)
+	(if (re-search-backward "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\)\\>" nil t)
+	    (let ((margin))
+	      (back-to-indentation)
+	      (setq margin (current-column))
+	      (end-of-line -0)
+	      (insert "\n")
+	      (indent-to margin)
+	      (insert "-- purpose: ")
+	      (if (equal (vhdl-field "description") "")
+		  (vhdl-kill-entire-line)
+		(setq finalline (+ finalline 1)))))
+	(goto-line finalline)
+	(end-of-line)
+	)))
+
+(defun vhdl-comment-uncomment-region (beg end &optional arg)
+  "Comment out region if not commented out, uncomment out region if already
+commented out."
+  (interactive "r\nP")
+  (goto-char beg)
+  (if (looking-at comment-start)
+      (comment-region beg end -1)
+    (comment-region beg end)
+      ))
+
+;; ############################################################################
+;; Help functions
+
+(defun vhdl-outer-space (count)
+  "Expand abbreviations and self-insert space(s), do indent-new-comment-line
+if in comment and past end-comment-column."
+  (interactive "p")
+  (if (or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
+	  (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
+      (expand-abbrev))
+  (if (not (vhdl-in-comment-p))
+      (self-insert-command count)
+    (if (< (current-column) end-comment-column)
+	(self-insert-command count)
+      (while (> (current-column) end-comment-column) (forward-word -1))
+      (while (> (preceding-char) ? ) (forward-word -1))
+      (delete-horizontal-space)
+      (indent-new-comment-line)
+      (end-of-line nil)
+      (insert-char ?  count)
+      )))
+
+(defun vhdl-field (prompt &optional following-string)
+  "Prompt for string and insert it in buffer with optional following-string."
+  (let ((opoint (point)))
+    (insert "<" prompt ">")
+    (let ((string (read-from-minibuffer (concat prompt ": ") ""
+					vhdl-minibuffer-local-map)))
+      (delete-region opoint (point))
+      (insert string (or following-string ""))
+      (if vhdl-upper-case-keywords
+	  (vhdl-fix-case-region-1
+	   opoint (point) t vhdl-93-keywords-regexp))
+      string
+      )))
+
+(defun vhdl-in-comment-p ()
+  "Check if point is to right of beginning comment delimiter."
+  (interactive)
+  (let ((opoint (point)))
+    (save-excursion ; finds an unquoted comment
+      (beginning-of-line)
+      (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" opoint t)
+      )))
+
+(defun vhdl-in-string-p ()
+  "Check if point is in a string."
+  (interactive)
+  (let ((opoint (point)))
+    (save-excursion ; preceeded by odd number of string delimiters?
+      (beginning-of-line)
+      (equal
+       opoint
+       (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*" opoint t))
+      )))
+
+(defun vhdl-begin-end (list)
+  "Insert a begin ... end pair with optional name after the end.
+Point is left between them."
+  (let ((return)
+	(name (car list))
+	(margin (cdr list)))
+    (if vhdl-additional-empty-lines
+	(progn
+	  (insert "\n")
+	  (indent-to (+ margin vhdl-basic-offset))))
+    (insert "\n")
+    (indent-to margin)
+    (vhdl-insert-keyword "BEGIN")
+    (if vhdl-self-insert-comments
+	(insert (and name (concat "  -- " name))))
+    (insert "\n")
+    (indent-to (+ margin vhdl-basic-offset))
+    (setq return (point))
+    (newline)
+    (indent-to margin)
+    (vhdl-insert-keyword "END")
+    (insert (and name (concat " " name)) ";")
+    (goto-char return)
+    ))
+
+(defun vhdl-get-arg-list ()
+  "Read from user a procedure or function argument list."
+  (insert " (")
+  (let ((margin (current-column)))
+    (if (not vhdl-argument-list-indent)
+	(let ((opoint (point)))
+	  (back-to-indentation)
+	  (setq margin (+ (current-column) vhdl-basic-offset))
+	  (goto-char opoint)
+	  (newline)
+	  (indent-to margin)))
+    (let (not-empty interface)
+      (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
+      (if (not (equal interface ""))
+	  (insert " "))
+      (while (not (string-equal (vhdl-field "[names]") ""))
+	(setq not-empty t)
+	(insert " : ")
+	(if (not (equal (vhdl-field "[direction]") ""))
+	    (insert " "))
+	(vhdl-field "type" ";\n")
+	(indent-to margin)
+	(setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
+	(if (not (equal interface ""))
+	    (insert " ")))
+      (if not-empty
+	  (progn (kill-line -0)
+		 (delete-char -2)
+		 (if (not vhdl-argument-list-indent)
+		     (progn (insert "\n") (indent-to margin)))
+		 (insert ")"))
+	(if vhdl-argument-list-indent
+	    (backward-delete-char 2)
+	  (kill-line -0)
+	  (backward-delete-char 3)))
+;	(while (string-match "[,;]$" args)
+;	  (newline)
+;	  (indent-to margin) (setq args (vhdl-field "next argument")))
+;	(insert 41) ;close-paren
+	)))
+
+(defun vhdl-get-port (optional &optional no-comment)
+  "Read from user a port spec argument list."
+  (let ((margin (current-column))
+	(start (point)))
+    (if (not vhdl-argument-list-indent)
+	(let ((opoint (point)))
+	  (back-to-indentation)
+	  (setq margin (+ (current-column) vhdl-basic-offset))
+	  (goto-char opoint)
+	  (newline)
+	  (indent-to margin)))
+    (let ((vhdl-ports (vhdl-field "[names]")))
+      (if (string-equal vhdl-ports "")
+	  (if optional
+	      (progn (vhdl-kill-entire-line) (forward-line -1)
+		     (if (not vhdl-argument-list-indent)
+			 (progn (vhdl-kill-entire-line) (forward-line -1))))
+	    (progn (undo 0) (insert " "))
+	    nil )
+	(insert " : ")
+	(progn
+	  (let ((semicolon-pos))
+	    (while (not (string-equal "" vhdl-ports))
+	      (vhdl-field "direction")
+	      (insert " ")
+	      (vhdl-field "type")
+	      (setq semicolon-pos (point))
+	      (insert ";")
+	      (if (not no-comment)
+		  (vhdl-declaration-comment))
+	      (newline)
+	      (indent-to margin)
+	      (setq vhdl-ports (vhdl-field "[names]" " : ")))
+	    (goto-char semicolon-pos)
+	    (if (not vhdl-argument-list-indent)
+		(progn (insert "\n") (indent-to margin)))
+	    (insert ")")
+	    (forward-char 1)
+	    (if (= (following-char) ? )
+		(delete-char 1))
+	    (forward-line 1)
+	    (vhdl-kill-entire-line)
+	    (end-of-line -0)
+	    (if vhdl-auto-align (vhdl-align start (point) 1))
+	    t))))))
+
+(defun vhdl-get-generic (optional &optional no-value )
+  "Read from user a generic spec argument list."
+  (let ((margin (current-column))
+	(start (point)))
+    (if (not vhdl-argument-list-indent)
+	(let ((opoint (point)))
+	  (back-to-indentation)
+	  (setq margin (+ (current-column) vhdl-basic-offset))
+	  (goto-char opoint)
+	  (newline)
+	  (indent-to margin)))
+    (let ((vhdl-generic))
+      (if no-value
+	  (setq vhdl-generic (vhdl-field "[names]"))
+	(setq vhdl-generic (vhdl-field "[name]")))
+      (if (string-equal vhdl-generic "")
+	  (if optional
+	      (progn (vhdl-kill-entire-line) (end-of-line -0)
+		     (if (not vhdl-argument-list-indent)
+			 (progn (vhdl-kill-entire-line) (end-of-line -0))))
+	    (progn (undo 0) (insert " "))
+	    nil )
+	(insert " : ")
+	(progn
+	  (let ((semicolon-pos))
+	    (while (not(string-equal "" vhdl-generic))
+	      (vhdl-field "type")
+	      (if no-value
+		  (progn (setq semicolon-pos (point))
+			 (insert ";"))
+		(insert " := ")
+		(if (equal (vhdl-field "[value]") "")
+		    (delete-char -4))
+		(setq semicolon-pos (point))
+		(insert ";")
+		(vhdl-declaration-comment))
+	      (newline)
+	      (indent-to margin)
+	      (if no-value
+		  (setq vhdl-generic (vhdl-field "[names]" " : "))
+		(setq vhdl-generic (vhdl-field "[name]" " : "))))
+	    (goto-char semicolon-pos)
+	    (if (not vhdl-argument-list-indent)
+		(progn (insert "\n") (indent-to margin)))
+	    (insert ")")
+	    (forward-char 1)
+	    (if (= (following-char) ? )
+		(delete-char 1))
+	    (forward-line 1)
+	    (vhdl-kill-entire-line)
+	    (end-of-line -0)
+	    (if vhdl-auto-align (vhdl-align start (point) 1))
+	    t))))))
+
+(defun vhdl-insert-date ()
+  "Insert date in appropriate format."
+  (interactive)
+    (insert
+     (cond
+      ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
+      ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
+      ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
+      )))
+
+(defun vhdl-insert-keyword (keyword)
+  (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
+  )
+
+(defun vhdl-case-keyword (keyword)
+  (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))
+  )
+
+(defun vhdl-case-word (num)
+  (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num))
+  )
+
+(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
+  "Convert all words matching word-regexp in region to lower or upper case,
+depending on parameter upper-case."
+  (let ((case-fold-search t)
+	(case-replace nil)
+	(busy-counter 0))
+    (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
+    (save-excursion
+      (goto-char beg)
+      (while (re-search-forward word-regexp end t)
+	(or (vhdl-in-comment-p)
+	    (vhdl-in-string-p)
+	    (if upper-case
+		(upcase-word -1)
+	      (downcase-word -1)))
+	(if (and count
+		 (/= busy-counter (setq busy-counter
+		     (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg))))))
+	    (message (format "Fixing case ... (%2d%s)" busy-counter "%%"))))
+      (goto-char end))
+    (if (not vhdl-underscore-is-part-of-word)
+	(modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
+    (message "")
+    ))
+
+(defun vhdl-fix-case-region (beg end &optional arg)
+  "Convert all VHDL words in region to lower or upper case, depending on
+variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
+  (interactive "r\nP")
+  (vhdl-fix-case-region-1
+   beg end vhdl-upper-case-keywords vhdl-93-keywords-regexp 0)
+  (vhdl-fix-case-region-1
+   beg end vhdl-upper-case-types vhdl-93-types-regexp 1)
+  (vhdl-fix-case-region-1
+   beg end vhdl-upper-case-attributes vhdl-93-attributes-regexp 2)
+  (vhdl-fix-case-region-1
+   beg end vhdl-upper-case-enum-values vhdl-93-enum-values-regexp 3)
+  )
+
+(defun vhdl-fix-case-buffer ()
+  "Convert all VHDL words in buffer to lower or upper case, depending on
+variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
+  (interactive)
+  (vhdl-fix-case-region (point-min) (point-max))
+  )
+
+(defun vhdl-minibuffer-tab (&optional prefix-arg)
+  "If preceeding character is part of a word then dabbrev-expand,
+else if right of non whitespace on line then tab-to-tab-stop,
+else indent line in proper way for current major mode
+(used for word completion in VHDL minibuffer)."
+  (interactive "P")
+  (cond ((= (char-syntax (preceding-char)) ?w)
+	 (let ((case-fold-search nil)) (dabbrev-expand prefix-arg)))
+	((> (current-column) (current-indentation))
+	 (tab-to-tab-stop))
+	(t
+	 (if (eq indent-line-function 'indent-to-left-margin)
+	     (insert-tab prefix-arg)
+	   (if prefix-arg
+	       (funcall indent-line-function prefix-arg)
+	     (funcall indent-line-function))))))
+
+(defun vhdl-help ()
+  "Display help information in '*Help*' buffer ."
+  (interactive)
+  (with-output-to-temp-buffer "*Help*"
+    (princ mode-name)
+    (princ " mode:\n")
+    (princ (documentation major-mode))
+    (save-excursion
+      (set-buffer standard-output)
+      (help-mode))
+    (print-help-return-message)))
+
+(defun vhdl-current-line ()
+  "Return the line number of the line containing point."
+  (save-restriction
+    (widen)
+    (save-excursion
+      (beginning-of-line)
+      (1+ (count-lines 1 (point)))))
+  )
+
+(defun vhdl-kill-entire-line ()
+  "Delete entire line."
+  (interactive)
+  (end-of-line)
+  (kill-line -0)
+  (delete-char 1)
+  )
+
+(defun vhdl-open-line ()
+  "Open a new line and indent."
+  (interactive)
+  (end-of-line)
+  (newline-and-indent)
+  )
+
+(defun vhdl-kill-line ()
+  "Kill current line."
+  (interactive)
+  (vhdl-kill-entire-line)
+  )
+
+(defun vhdl-character-to-event-hack (char)
+  (if (memq 'XEmacs vhdl-emacs-features)
+      (character-to-event char)
+    char))
+
+;; ############################################################################
+;; Abbrev hooks
+
+(defun vhdl-electric-mode ()
+  "Toggle VHDL Electric mode."
+  (interactive)
+  (setq vhdl-electric-mode (not vhdl-electric-mode))
+  (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
+  (force-mode-line-update)
+  )
+
+(defun vhdl-stutter-mode ()
+  "Toggle VHDL Stuttering mode."
+  (interactive)
+  (setq vhdl-stutter-mode (not vhdl-stutter-mode))
+  )
+
+(defun vhdl-hooked-abbrev (fun)
+  "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
+but not if inside a comment or quote)"
+  (if (or (vhdl-in-comment-p)
+	  (vhdl-in-string-p)
+	  (save-excursion (forward-word -1) (looking-at "end")))
+      (progn
+	(insert " ")
+	(unexpand-abbrev)
+	(delete-char -1))
+    (if (not vhdl-electric-mode)
+	(progn
+	  (insert " ")
+	  (unexpand-abbrev)
+	  (backward-word 1)
+	  (vhdl-case-word 1)
+	  (delete-char 1)
+	)
+      (let ((invoke-char last-command-char) (abbrev-mode -1))
+	(funcall fun)
+	(if (= invoke-char ?-) (setq abbrev-start-location (point)))
+	;; delete CR which is still in event queue
+	(if (memq 'XEmacs vhdl-emacs-features)
+	    (enqueue-eval-event 'delete-char -1)
+	  (setq unread-command-events		; push back a delete char
+		(list (vhdl-character-to-event-hack ?\177))))
+	))))
+
+(defun vhdl-alias-hook () "hooked version of vhdl-alias."
+  (vhdl-hooked-abbrev 'vhdl-alias))
+(defun vhdl-architecture-hook () "hooked version of vhdl-architecture."
+  (vhdl-hooked-abbrev 'vhdl-architecture))
+(defun vhdl-array-hook () "hooked version of vhdl-array."
+  (vhdl-hooked-abbrev 'vhdl-array))
+(defun vhdl-assert-hook () "hooked version of vhdl-assert."
+  (vhdl-hooked-abbrev 'vhdl-assert))
+(defun vhdl-attribute-hook () "hooked version of vhdl-attribute."
+  (vhdl-hooked-abbrev 'vhdl-attribute))
+(defun vhdl-block-hook () "hooked version of vhdl-block."
+  (vhdl-hooked-abbrev 'vhdl-block))
+(defun vhdl-case-hook () "hooked version of vhdl-case."
+  (vhdl-hooked-abbrev 'vhdl-case))
+(defun vhdl-component-hook () "hooked version of vhdl-component."
+  (vhdl-hooked-abbrev 'vhdl-component))
+(defun vhdl-component-instance-hook ()
+  "hooked version of vhdl-component-instance."
+  (vhdl-hooked-abbrev 'vhdl-component-instance))
+(defun vhdl-concurrent-signal-assignment-hook ()
+  "hooked version of vhdl-concurrent-signal-assignment."
+  (vhdl-hooked-abbrev 'vhdl-concurrent-signal-assignment))
+(defun vhdl-configuration-hook ()
+  "hooked version of vhdl-configuration."
+  (vhdl-hooked-abbrev 'vhdl-configuration))
+(defun vhdl-constant-hook () "hooked version of vhdl-constant."
+  (vhdl-hooked-abbrev 'vhdl-constant))
+(defun vhdl-disconnect-hook () "hooked version of vhdl-disconnect."
+  (vhdl-hooked-abbrev 'vhdl-disconnect))
+(defun vhdl-display-comment-hook () "hooked version of vhdl-display-comment."
+  (vhdl-hooked-abbrev 'vhdl-display-comment))
+(defun vhdl-else-hook () "hooked version of vhdl-else."
+  (vhdl-hooked-abbrev 'vhdl-else))
+(defun vhdl-elsif-hook () "hooked version of vhdl-elsif."
+  (vhdl-hooked-abbrev 'vhdl-elsif))
+(defun vhdl-entity-hook () "hooked version of vhdl-entity."
+  (vhdl-hooked-abbrev 'vhdl-entity))
+(defun vhdl-exit-hook () "hooked version of vhdl-exit."
+  (vhdl-hooked-abbrev 'vhdl-exit))
+(defun vhdl-for-hook () "hooked version of vhdl-for."
+  (vhdl-hooked-abbrev 'vhdl-for))
+(defun vhdl-function-hook () "hooked version of vhdl-function."
+  (vhdl-hooked-abbrev 'vhdl-function))
+(defun vhdl-generate-hook () "hooked version of vhdl-generate."
+  (vhdl-hooked-abbrev 'vhdl-generate))
+(defun vhdl-generic-hook () "hooked version of vhdl-generic."
+  (vhdl-hooked-abbrev 'vhdl-generic))
+(defun vhdl-library-hook () "hooked version of vhdl-library."
+  (vhdl-hooked-abbrev 'vhdl-library))
+(defun vhdl-header-hook () "hooked version of vhdl-header."
+  (vhdl-hooked-abbrev 'vhdl-header))
+(defun vhdl-if-hook () "hooked version of vhdl-if."
+  (vhdl-hooked-abbrev 'vhdl-if))
+(defun vhdl-loop-hook () "hooked version of vhdl-loop."
+  (vhdl-hooked-abbrev 'vhdl-loop))
+(defun vhdl-map-hook () "hooked version of vhdl-map."
+  (vhdl-hooked-abbrev 'vhdl-map))
+(defun vhdl-modify-hook () "hooked version of vhdl-modify."
+  (vhdl-hooked-abbrev 'vhdl-modify))
+(defun vhdl-next-hook () "hooked version of vhdl-next."
+  (vhdl-hooked-abbrev 'vhdl-next))
+(defun vhdl-package-hook () "hooked version of vhdl-package."
+  (vhdl-hooked-abbrev 'vhdl-package))
+(defun vhdl-port-hook () "hooked version of vhdl-port."
+  (vhdl-hooked-abbrev 'vhdl-port))
+(defun vhdl-procedure-hook () "hooked version of vhdl-procedure."
+  (vhdl-hooked-abbrev 'vhdl-procedure))
+(defun vhdl-process-hook () "hooked version of vhdl-process."
+  (vhdl-hooked-abbrev 'vhdl-process))
+(defun vhdl-record-hook () "hooked version of vhdl-record."
+  (vhdl-hooked-abbrev 'vhdl-record))
+(defun vhdl-return-hook () "hooked version of vhdl-return-value."
+  (vhdl-hooked-abbrev 'vhdl-return-value))
+(defun vhdl-selected-signal-assignment-hook ()
+  "hooked version of vhdl-selected-signal-assignment."
+  (vhdl-hooked-abbrev 'vhdl-selected-signal-assignment))
+(defun vhdl-signal-hook () "hooked version of vhdl-signal."
+  (vhdl-hooked-abbrev 'vhdl-signal))
+(defun vhdl-subtype-hook () "hooked version of vhdl-subtype."
+  (vhdl-hooked-abbrev 'vhdl-subtype))
+(defun vhdl-type-hook () "hooked version of vhdl-type."
+  (vhdl-hooked-abbrev 'vhdl-type))
+(defun vhdl-use-hook () "hooked version of vhdl-use."
+  (vhdl-hooked-abbrev 'vhdl-use))
+(defun vhdl-variable-hook () "hooked version of vhdl-variable."
+  (vhdl-hooked-abbrev 'vhdl-variable))
+(defun vhdl-wait-hook () "hooked version of vhdl-wait."
+  (vhdl-hooked-abbrev 'vhdl-wait))
+(defun vhdl-when-hook () "hooked version of vhdl-when."
+  (vhdl-hooked-abbrev 'vhdl-when))
+(defun vhdl-while-loop-hook () "hooked version of vhdl-while-loop."
+  (vhdl-hooked-abbrev 'vhdl-while-loop))
+(defun vhdl-and-hook () "hooked version of vhdl-and."
+  (vhdl-hooked-abbrev 'vhdl-and))
+(defun vhdl-or-hook () "hooked version of vhdl-or."
+  (vhdl-hooked-abbrev 'vhdl-or))
+(defun vhdl-nand-hook () "hooked version of vhdl-nand."
+  (vhdl-hooked-abbrev 'vhdl-nand))
+(defun vhdl-nor-hook () "hooked version of vhdl-nor."
+  (vhdl-hooked-abbrev 'vhdl-nor))
+(defun vhdl-xor-hook () "hooked version of vhdl-xor."
+  (vhdl-hooked-abbrev 'vhdl-xor))
+(defun vhdl-xnor-hook () "hooked version of vhdl-xnor."
+  (vhdl-hooked-abbrev 'vhdl-xnor))
+(defun vhdl-not-hook () "hooked version of vhdl-not."
+  (vhdl-hooked-abbrev 'vhdl-not))
+
+(defun vhdl-default-hook () "hooked version of vhdl-default."
+  (vhdl-hooked-abbrev 'vhdl-default))
+(defun vhdl-default-indent-hook () "hooked version of vhdl-default-indent."
+  (vhdl-hooked-abbrev 'vhdl-default-indent))
+
+
+;; ############################################################################
+;; Font locking
+;; ############################################################################
+;; (using `font-lock.el')
+
+;; ############################################################################
+;; Syntax definitions
+
+(defvar vhdl-font-lock-keywords nil
+  "Regular expressions to highlight in VHDL Mode.")
+
+(defconst vhdl-font-lock-keywords-0
+ (list
+  ;; highlight template prompts
+  '("\\(^\\|[ (.\t]\\)\\(<[^ =].*[^ =]>\\)\\([ .]\\|$\\)"
+    2 vhdl-font-lock-prompt-face)
+
+  ;; highlight character literals
+  '("'\\(.\\)'" 1 'font-lock-string-face)
+  )
+  "For consideration as a value of `vhdl-font-lock-keywords'.
+This does highlighting of template prompts and character literals.")
+
+(defconst vhdl-font-lock-keywords-1
+  (list
+   ;; highlight names of units, subprograms, and components when declared
+   (list
+    (concat
+     "^\\s-*\\("
+     "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
+     "function\\|procedure\\|component"
+     "\\)\\s-+\\(\\w+\\)")
+    3 'font-lock-function-name-face)
+
+   ;; highlight labels of common constructs
+   (list
+    (concat
+     "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\("
+     "assert\\|block\\|case\\|exit\\|for\\|if\\|loop\\|"
+     "next\\|null\\|process\\| with\\|while\\|"
+     "\\w+\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map"
+     "\\)\\>")
+    1 'font-lock-function-name-face)
+
+   ;; highlight entity names of architectures and configurations
+   (list
+    "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
+    2 'font-lock-function-name-face)
+
+   ;; highlight names and labels at end of constructs
+   (list
+    (concat
+     "^\\s-*end\\s-+\\("
+     "\\(block\\|case\\|component\\|for\\|generate\\|if\\|loop\\|"
+     "process\\|record\\|units\\)\\>\\|"
+     "\\)\\s-*\\(\\w*\\)")
+     3 'font-lock-function-name-face)
+   )
+"For consideration as a value of `vhdl-font-lock-keywords'.
+This does highlighting of names and labels.")
+
+(defconst vhdl-font-lock-keywords-2
+ (list
+  ;; highlight keywords, and types, standardized attributes, enumeration values
+  (list (concat "'" vhdl-93-attributes-regexp)
+	                           1 'vhdl-font-lock-attribute-face)
+  (list vhdl-93-types-regexp       1 'font-lock-type-face)
+  (list vhdl-93-enum-values-regexp 1 'vhdl-font-lock-value-face)
+  (list vhdl-93-keywords-regexp    1 'font-lock-keyword-face)
+  )
+  "For consideration as a value of `vhdl-font-lock-keywords'.
+This does highlighting of comments, keywords, and standard types.")
+
+(defconst vhdl-font-lock-keywords-3
+ (list
+  ;; highlight clock signals.
+  (cons vhdl-clock-signal-syntax   'vhdl-font-lock-clock-signal-face)
+  (cons vhdl-reset-signal-syntax   'vhdl-font-lock-reset-signal-face)
+  (cons vhdl-control-signal-syntax 'vhdl-font-lock-control-signal-face)
+  (cons vhdl-data-signal-syntax    'vhdl-font-lock-data-signal-face)
+  (cons vhdl-test-signal-syntax    'vhdl-font-lock-test-signal-face)
+  )
+  "For consideration as a value of `vhdl-font-lock-keywords'.
+This does highlighting of signal names with specific syntax.")
+
+;; ############################################################################
+;; Font and color definitions
+
+(defvar vhdl-font-lock-prompt-face	   'vhdl-font-lock-prompt-face
+  "Face name to use for prompts.")
+
+(defvar vhdl-font-lock-attribute-face	   'vhdl-font-lock-attribute-face
+  "Face name to use for attributes.")
+
+(defvar vhdl-font-lock-value-face	   'vhdl-font-lock-value-face
+  "Face name to use for enumeration values.")
+
+(defvar vhdl-font-lock-clock-signal-face   'vhdl-font-lock-clock-signal-face
+  "Face name to use for clock signals.")
+
+(defvar vhdl-font-lock-reset-signal-face   'vhdl-font-lock-reset-signal-face
+  "Face name to use for reset signals.")
+
+(defvar vhdl-font-lock-control-signal-face 'vhdl-font-lock-control-signal-face
+  "Face name to use for control signals.")
+
+(defvar vhdl-font-lock-data-signal-face	   'vhdl-font-lock-data-signal-face
+  "Face name to use for data signals.")
+
+(defvar vhdl-font-lock-test-signal-face	   'vhdl-font-lock-test-signal-face
+  "Face name to use for test signals.")
+
+(defface vhdl-font-lock-prompt-face
+  '((((class color) (background light)) (:foreground "Red"))
+    (((class color) (background dark)) (:foreground "Red"))
+    (t (:inverse-video t)))
+  "Font Lock mode face used to highlight prompts."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-attribute-face
+  '((((class color) (background light)) (:foreground "CadetBlue"))
+    (((class color) (background dark)) (:foreground "CadetBlue"))
+    (t (:italic t :bold t)))
+  "Font Lock mode face used to highlight attributes."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-value-face
+  '((((class color) (background light)) (:foreground "DarkGoldenrod"))
+    (((class color) (background dark)) (:foreground "DarkGoldenrod"))
+    (t (:italic t :bold t)))
+  "Font Lock mode face used to highlight enumeration values."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-clock-signal-face
+  '((((class color) (background light)) (:foreground "LimeGreen"))
+    (((class color) (background dark)) (:foreground "LimeGreen"))
+    (t ()))
+  "Font Lock mode face used to highlight clock signals."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-reset-signal-face
+  '((((class color) (background light)) (:foreground "Red"))
+    (((class color) (background dark)) (:foreground "Red"))
+    (t ()))
+  "Font Lock mode face used to highlight reset signals."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-control-signal-face
+  '((((class color) (background light)) (:foreground "Blue"))
+    (((class color) (background dark)) (:foreground "Blue"))
+    (t ()))
+  "Font Lock mode face used to highlight control signals."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-data-signal-face
+  '((((class color) (background light)) (:foreground "Black"))
+    (((class color) (background dark)) (:foreground "Black"))
+    (t ()))
+  "Font Lock mode face used to highlight data signals."
+  :group 'font-lock-highlighting-faces)
+
+(defface vhdl-font-lock-test-signal-face
+  '((((class color) (background light)) (:foreground "Gold"))
+    (((class color) (background dark)) (:foreground "Gold"))
+    (t ()))
+  "Font Lock mode face used to highlight test signals."
+  :group 'font-lock-highlighting-faces)
+
+;; Custom color definitions for existing faces
+(defun vhdl-set-face-foreground ()
+  (set-face-foreground 'font-lock-comment-face "IndianRed")
+  (set-face-foreground 'font-lock-function-name-face "MediumOrchid")
+  (set-face-foreground 'font-lock-keyword-face "SlateBlue")
+  (set-face-foreground 'font-lock-string-face "RosyBrown")
+  (set-face-foreground 'font-lock-type-face "ForestGreen")
+  )
+
+(defun vhdl-set-face-grayscale ()
+  (interactive)
+  (set-face-bold-p 'font-lock-comment-face nil)
+  (set-face-inverse-video-p 'font-lock-comment-face nil)
+  (set-face-italic-p 'font-lock-comment-face t)
+  (set-face-underline-p 'font-lock-comment-face nil)
+
+  (set-face-bold-p 'font-lock-function-name-face nil)
+  (set-face-inverse-video-p 'font-lock-function-name-face nil)
+  (set-face-italic-p 'font-lock-function-name-face t)
+  (set-face-underline-p 'font-lock-function-name-face nil)
+
+  (set-face-bold-p 'font-lock-keyword-face t)
+  (set-face-inverse-video-p 'font-lock-keyword-face nil)
+  (set-face-italic-p 'font-lock-keyword-face nil)
+  (set-face-underline-p 'font-lock-keyword-face nil)
+
+  (set-face-bold-p 'font-lock-string-face nil)
+  (set-face-inverse-video-p 'font-lock-string-face nil)
+  (set-face-italic-p 'font-lock-string-face nil)
+  (set-face-underline-p 'font-lock-string-face t)
+
+  (set-face-bold-p 'font-lock-type-face t)
+  (set-face-inverse-video-p 'font-lock-type-face nil)
+  (set-face-italic-p 'font-lock-type-face t)
+  (set-face-underline-p 'font-lock-type-face nil)
+  )
+
+;; ############################################################################
+;; Font lock initialization
+
+(defun vhdl-font-lock-init ()
+  "Initializes fontification."
+  (setq vhdl-font-lock-keywords
+	(append vhdl-font-lock-keywords-0
+		(if vhdl-highlight-names vhdl-font-lock-keywords-1)
+	        (if vhdl-highlight-keywords vhdl-font-lock-keywords-2)
+		(if (and vhdl-highlight-signals (x-display-color-p))
+		    vhdl-font-lock-keywords-3)))
+  (if (x-display-color-p)
+      (if (not vhdl-use-default-colors) (vhdl-set-face-foreground))
+    (if (not vhdl-use-default-faces) (vhdl-set-face-grayscale))
+  ))
+
+;; ############################################################################
+;; Fontification for postscript printing
+
+(defun vhdl-ps-init ()
+  "Initializes face and page settings for postscript printing."
+  (require 'ps-print)
+  (unless (or vhdl-use-default-faces
+	      ps-print-color-p)
+    (set (make-local-variable 'ps-bold-faces)
+	 '(font-lock-keyword-face
+	   font-lock-type-face
+	   vhdl-font-lock-attribute-face
+	   vhdl-font-lock-value-face))
+    (set (make-local-variable 'ps-italic-faces)
+	 '(font-lock-comment-face
+	   font-lock-function-name-face
+	   font-lock-type-face
+	   vhdl-font-lock-prompt-face
+	   vhdl-font-lock-attribute-face
+	   vhdl-font-lock-value-face))
+    (set (make-local-variable 'ps-underlined-faces)
+	 '(font-lock-string-face))
+    )
+  ;; define page settings, so that a line containing 79 characters (default)
+  ;; fits into one column
+  (if vhdl-print-two-column
+      (progn
+	(set (make-local-variable 'ps-landscape-mode) t)
+	(set (make-local-variable 'ps-number-of-columns) 2)
+	(set (make-local-variable 'ps-font-size) 7.0)
+	(set (make-local-variable 'ps-header-title-font-size) 10.0)
+	(set (make-local-variable 'ps-header-font-size) 9.0)
+	(set (make-local-variable 'ps-header-offset) 12.0)
+	(if (eq ps-paper-type 'letter)
+	    (progn
+	      (set (make-local-variable 'ps-inter-column) 40.0)
+	      (set (make-local-variable 'ps-left-margin) 40.0)
+	      (set (make-local-variable 'ps-right-margin) 40.0)
+	)))))
+
+
+;; ############################################################################
+;; Hideshow
+;; ############################################################################
+;; (using `hideshow.el')
+
+(defun vhdl-forward-sexp-function (&optional count)
+  "Find begin and end of VHDL process or block (for hideshow)."
+  (interactive "p")
+  (let (name
+	(case-fold-search t))
+    (end-of-line)
+    (if (< count 0)
+	(re-search-backward "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|block\\)\\>" nil t)
+      (re-search-forward "\\s-*\\<end\\s-+\\(process\\|block\\)\\>" nil t)
+  )))
+
+(require 'hideshow)
+
+(unless (assq 'vhdl-mode hs-special-modes-alist)
+    (setq hs-special-modes-alist
+	  (cons
+	   '(vhdl-mode
+	     "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
+	     "\\s-*\\<\\(end\\|END\\)\\s-+\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
+	     "-- "
+	     vhdl-forward-sexp-function)
+	   hs-special-modes-alist)))
+
+
+;; ############################################################################
+;; Compilation
+;; ############################################################################
+;; (using `compile.el')
+
+(defvar vhdl-compile-commands
+  '(
+    (cadence "cv -file" nil)
+    (ikos "analyze" nil)
+    (quickhdl "qvhcom" nil)
+    (synopsys "vhdlan" nil)
+    (vantage "analyze -libfile vsslib.ini -src" nil)
+    (viewlogic "analyze -libfile vsslib.ini -src" nil)
+    (v-system "vcom" "vmake > Makefile")
+    )
+  "Commands to be called in the shell for compilation (syntax analysis) of a
+single buffer and `Makefile' generation for different tools. First item is tool
+identifier, second item is shell command for compilation, and third item is
+shell command for `Makefile' generation. A tool is specified by assigning a
+tool identifier to variable `vhdl-compiler'.")
+
+(defvar vhdl-compilation-error-regexp-alist
+  (list
+    ;; Cadence Design Systems: cv -file test.vhd
+    ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
+    '("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2)
+
+    ;; Ikos Voyager: analyze test.vhd
+    ;; E L4/C5:        this library unit is inaccessible
+    ; Xemacs does not support error messages without included file name
+    (if (not (memq 'XEmacs vhdl-emacs-features))
+	'("E L\\([0-9]+\\)/C[0-9]+:" nil 1)
+      '("E L\\([0-9]+\\)/C[0-9]+:" 2 1)
+      )
+
+    ;; QuickHDL, Mentor Graphics: qvhcom test.vhd
+    ;; ERROR: test.vhd(24): near "dnd": expecting: END
+    '("ERROR: \\(.+\\)(\\([0-9]+\\)):" 1 2)
+
+    ;; Synopsys, VHDL Analyzer: vhdlan test.vhd
+    ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
+    '("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2)
+
+    ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
+    ;; **Error: LINE 499 *** No aggregate value is valid in this context.
+    ; Xemacs does not support error messages without included file name
+    (if (not (memq 'XEmacs vhdl-emacs-features))
+	'("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1)
+      '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 2 1)
+      )
+
+    ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
+    ;; **Error: LINE 499 *** No aggregate value is valid in this context.
+    ;; same regexp as for Vantage
+
+    ;; V-System, Model Technology: vcom test.vhd
+    ;; ERROR: test.vhd(14): Unknown identifier: positiv
+    ;; same regexp as for QuickHDL
+
+    ) "Alist that specifies how to match errors in VHDL compiler output.")
+
+(defvar compilation-file-regexp-alist
+  '(
+    ;; Ikos Voyager: analyze -libfile vsslib.ini -src test.vhd
+    ;; analyze sdrctl.vhd
+    ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2)
+
+    ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
+    ;;     Compiling "pcu.vhd" line 1...
+    (" *Compiling \"\\(.+\\)\" " 1)
+
+    ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
+    ;;     Compiling "pcu.vhd" line 1...
+    ;; same regexp as for Vantage
+
+    ) "Alist specifying how to match lines that indicate a new current file.
+Used for compilers with no file name in the error messages.")
+
+(defun vhdl-compile ()
+  "Compile current buffer using the VHDL compiler specified in
+`vhdl-compiler'."
+  (interactive)
+  (let ((command-list vhdl-compile-commands)
+	command)
+    (while command-list
+      (if (eq vhdl-compiler (car (car command-list)))
+	  (setq command (car (cdr (car command-list)))))
+      (setq command-list (cdr command-list)))
+    (if command
+	(compile (concat command " " vhdl-compiler-options
+			 (if (not (string-equal vhdl-compiler-options "")) " ")
+			 (file-name-nondirectory (buffer-file-name)))))))
+
+(defun vhdl-make ()
+  "Call make command for compilation of all updated source files
+(requires `Makefile')."
+  (interactive)
+  (compile "make"))
+
+(defun vhdl-generate-makefile ()
+  "Generate new `Makefile'."
+  (interactive)
+  (let ((command-list vhdl-compile-commands)
+	command)
+    (while command-list
+      (if (eq vhdl-compiler (car (car command-list)))
+	  (setq command (car (cdr (cdr (car command-list))))))
+      (setq command-list (cdr command-list)))
+    (if command
+	(compile command )
+      (message (format "Not implemented for `%s'!" vhdl-compiler))
+      (beep))))
+
+
+;; ############################################################################
+;; Bug reports
+;; ############################################################################
+;; (using `reporter.el')
+
+(defconst vhdl-version "3.19"
+  "VHDL Mode version number.")
+
+(defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
+  "Address for VHDL Mode bug reports.")
+
+(defun vhdl-version ()
+  "Echo the current version of VHDL Mode in the minibuffer."
+  (interactive)
+  (message "Using VHDL Mode version %s" vhdl-version)
+  (vhdl-keep-region-active))
+
+;; get reporter-submit-bug-report when byte-compiling
+(and (fboundp 'eval-when-compile)
+     (eval-when-compile
+      (require 'reporter)))
+
+(defun vhdl-submit-bug-report ()
+  "Submit via mail a bug report on VHDL Mode."
+  (interactive)
+  ;; load in reporter
+  (and
+   (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
+   (require 'reporter)
+   (reporter-submit-bug-report
+    vhdl-mode-help-address
+    (concat "VHDL Mode " vhdl-version)
+    (list
+     ;; report all important variables
+     'vhdl-basic-offset
+     'vhdl-offsets-alist
+     'vhdl-comment-only-line-offset
+     'tab-width
+     'vhdl-electric-mode
+     'vhdl-stutter-mode
+     'vhdl-indent-tabs-mode
+     'vhdl-compiler
+     'vhdl-compiler-options
+     'vhdl-upper-case-keywords
+     'vhdl-upper-case-types
+     'vhdl-upper-case-attributes
+     'vhdl-upper-case-enum-values
+     'vhdl-auto-align
+     'vhdl-additional-empty-lines
+     'vhdl-argument-list-indent
+     'vhdl-conditions-in-parenthesis
+     'vhdl-date-format
+     'vhdl-header-file
+     'vhdl-modify-date-prefix-string
+     'vhdl-zero-string
+     'vhdl-one-string
+     'vhdl-self-insert-comments
+     'vhdl-prompt-for-comments
+     'vhdl-comment-column
+     'vhdl-end-comment-column
+     'vhdl-highlight-names
+     'vhdl-highlight-keywords
+     'vhdl-highlight-signals
+     'vhdl-highlight-case-sensitive
+     'vhdl-use-default-colors
+     'vhdl-use-default-faces
+     'vhdl-clock-signal-syntax
+     'vhdl-reset-signal-syntax
+     'vhdl-control-signal-syntax
+     'vhdl-data-signal-syntax
+     'vhdl-test-signal-syntax
+     'vhdl-source-file-menu
+     'vhdl-index-menu
+     'vhdl-hideshow-menu
+     'vhdl-print-two-column
+     'vhdl-intelligent-tab
+     'vhdl-template-key-binding-prefix
+     'vhdl-word-completion-in-minibuffer
+     'vhdl-underscore-is-part-of-word
+     'vhdl-mode-hook
+     )
+    (function
+     (lambda ()
+       (insert
+	(if vhdl-special-indent-hook
+	    (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+		    "vhdl-special-indent-hook is set to '"
+		    (format "%s" vhdl-special-indent-hook)
+		    ".\nPerhaps this is your problem?\n"
+		    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
+	  "\n")
+	(format "vhdl-emacs-features: %s\n" vhdl-emacs-features)
+	)))
+    nil
+    "Dear VHDL Mode maintainers,"
+    )))
+
+
+;; ############################################################################
+
+(provide 'vhdl-mode)
+
+;;; vhdl-mode.el ends here