1 ;;; vhdl-mode.el --- major mode for editing VHDL code
3 ;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
5 ;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch>
6 ;; <http://www.iis.ee.ethz.ch/~zimmi/>
7 ;; Rodney J. Whitby <mailto:rwhitby@geocities.com>
8 ;; <http://www.geocities.com/SiliconValley/Park/8287/>
9 ;; Maintainer: vhdl-mode@geocities.com
10 ;; Maintainers' Version: 3.19
11 ;; Keywords: languages vhdl
13 ;; This file is part of GNU Emacs.
15 ;; GNU Emacs is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING. If not, write to the
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28 ;; Boston, MA 02111-1307, USA.
30 ;; ############################################################################
32 ;; ############################################################################
34 ;; This package provides an Emacs major mode for editing VHDL code.
35 ;; It includes the following features:
37 ;; - Highlighting of VHDL syntax
38 ;; - Indentation based on versatile syntax analysis
39 ;; - Template insertion (electrification) for most VHDL constructs
40 ;; - Insertion of customizable VHDL file headers
41 ;; - Word completion (dynamic abbreviations)
42 ;; - Menu containing all VHDL Mode commands
43 ;; - Index menu (jump index to main units and blocks in a file)
44 ;; - Source file menu (menu of all source files in current directory)
45 ;; - Source file compilation (syntax analysis)
46 ;; - Postscript printing with fontification
47 ;; - Lower and upper case keywords
48 ;; - Hiding blocks of code
49 ;; - Alignment functions
50 ;; - Easy customization
51 ;; - Works under Emacs and XEmacs
53 ;; ############################################################################
55 ;; ############################################################################
57 ;; see below (comment in vhdl-mode function) or type `C-c C-h' in Emacs.
59 ;; ############################################################################
61 ;; ############################################################################
65 ;; - This version does not support Emacs 19 (use VHDL Mode 3.10 instead)
68 ;; ############################################################################
70 ;; ############################################################################
72 ;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
75 ;; Fontification approach suggested by Ken Wood <ken@eda.com.au>
76 ;; Source file menu suggested by Michael Laajanen <mila@enea.se>
77 ;; Ideas about alignment from John Wiegley <johnw@borland.com>
79 ;; Many thanks to all the users who sent me bug reports and enhancement
81 ;; Special thanks go to Dan Nicolaescu <done@ece.arizona.edu> for reviewing
82 ;; the code and for his valuable hints.
86 ;; ############################################################################
87 ;; User definable variables
88 ;; ############################################################################
90 ;; ############################################################################
91 ;; Variables for customization
94 "Customizations for VHDL Mode."
100 (defgroup vhdl-mode nil
101 "Customizations for modes."
104 (defcustom vhdl-electric-mode t
105 "*If non-nil, electrification (automatic template generation) is enabled.
106 If nil, template generators can still be invoked through key bindings
107 and menu. Can be toggled by `\\[vhdl-electric-mode]'."
111 (defcustom vhdl-stutter-mode t
112 "*If non-nil, stuttering is enabled.
113 Can be toggled by `\\[vhdl-stutter-mode]'."
117 (defcustom vhdl-indent-tabs-mode t
118 "*Indentation can insert tabs if this is non-nil.
119 Overrides local variable `indent-tabs-mode'."
124 (defgroup vhdl-compile nil
125 "Customizations for compilation."
128 (defcustom vhdl-compiler 'v-system
129 "*VHDL compiler to be used for syntax analysis.
130 cadence Cadence Design Systems (`cv -file')
131 ikos Ikos Voyager (`analyze')
132 quickhdl QuickHDL, Mentor Graphics (`qvhcom')
133 synopsys Synopsys, VHDL Analyzer (`vhdlan')
134 vantage Vantage Analysis Systems (`analyze -libfile vsslib.ini -src')
135 viewlogic Viewlogic (`analyze -libfile vsslib.ini -src')
136 v-system V-System, Model Technology (`vcom')
137 For incorporation of additional compilers, please send me their command syntax
138 and some example error messages."
148 :group 'vhdl-compile)
150 (defcustom vhdl-compiler-options ""
151 "*Options to be added to the compile command."
153 :group 'vhdl-compile)
156 (defgroup vhdl-style nil
157 "Customizations for code styles."
160 (defcustom vhdl-basic-offset 4
161 "*Amount of basic offset used for indentation.
162 This value is used by + and - symbols in `vhdl-offsets-alist'."
167 (defgroup vhdl-word-case nil
168 "Customizations for case of VHDL words."
171 (defcustom vhdl-upper-case-keywords nil
172 "*If non-nil, keywords are converted to upper case
173 when typed or by the fix case functions."
175 :group 'vhdl-word-case)
177 (defcustom vhdl-upper-case-types nil
178 "*If non-nil, standardized types are converted to upper case
179 by the fix case functions."
181 :group 'vhdl-word-case)
183 (defcustom vhdl-upper-case-attributes nil
184 "*If non-nil, standardized attributes are converted to upper case
185 by the fix case functions."
187 :group 'vhdl-word-case)
189 (defcustom vhdl-upper-case-enum-values nil
190 "*If non-nil, standardized enumeration values are converted to upper case
191 by the fix case functions."
193 :group 'vhdl-word-case)
196 (defgroup vhdl-electric nil
197 "Customizations for comments."
200 (defcustom vhdl-auto-align nil
201 "*If non-nil, some templates are automatically aligned after generation."
203 :group 'vhdl-electric)
205 (defcustom vhdl-additional-empty-lines t
206 "*If non-nil, additional empty lines are inserted in some templates.
207 This improves readability of code."
209 :group 'vhdl-electric)
211 (defcustom vhdl-argument-list-indent t
212 "*If non-nil, argument lists are indented relative to the opening paren.
213 Normal indentation is applied otherwise."
215 :group 'vhdl-electric)
217 (defcustom vhdl-conditions-in-parenthesis nil
218 "*If non-nil, parenthesis are placed around condition expressions."
220 :group 'vhdl-electric)
222 (defcustom vhdl-date-format 'scientific
223 "*Specifies date format to be used in header.
225 american (09/17/1997)
226 european (17.09.1997)
227 scientific (1997/09/17)"
228 :type '(choice (const american)
231 :group 'vhdl-electric)
233 (defcustom vhdl-header-file nil
234 "*Pathname/filename of the file to be inserted as header.
235 If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
236 if the header needs to be version controlled.
238 The following keywords for template generation are supported:
239 <filename> : replaced by the name of the buffer
240 <author> : replaced by the user name and email address
241 <date> : replaced by the current date
242 <... string> : replaced by a prompted string (... is the prompt word)
243 <cursor> : final cursor position
246 -----------------------------------------
247 -- Title : <title string>
251 -- Description : <cursor>
252 -----------------------------------------"
253 :type '(choice (const nil) string)
254 :group 'vhdl-electric)
256 (defcustom vhdl-modify-date-prefix-string "-- Last modified : "
257 "*Prefix string of modification date in VHDL file header.
258 If actualization of the modification date is called (menu, `\\[vhdl-modify]'),
259 this string is searched and the rest of the line replaced by the current date."
261 :group 'vhdl-electric)
263 (defcustom vhdl-zero-string "'0'"
264 "*String to use for a logic zero."
266 :group 'vhdl-electric)
268 (defcustom vhdl-one-string "'1'"
269 "*String to use for a logic one."
271 :group 'vhdl-electric)
274 (defgroup vhdl-comment nil
275 "Customizations for comments."
276 :group 'vhdl-electric)
278 (defcustom vhdl-self-insert-comments t
279 "*If non-nil, variables templates automatically insert help comments."
281 :group 'vhdl-comment)
283 (defcustom vhdl-prompt-for-comments t
284 "*If non-nil, various templates prompt for user definable comments."
286 :group 'vhdl-comment)
288 (defcustom vhdl-comment-column 40
289 "*Column to indent right-margin comments to.
290 Overrides local variable `comment-column'."
292 :group 'vhdl-comment)
294 (defcustom vhdl-end-comment-column 79
295 "*End of comment column."
297 :group 'vhdl-comment)
299 (defvar end-comment-column 79
300 "*End of comment column.")
303 (defgroup vhdl-highlight nil
304 "Customizations for highlighting."
307 (defcustom vhdl-highlight-names t
308 "*If non-nil, unit names, subprogram names, and labels are highlighted."
310 :group 'vhdl-highlight)
312 (defcustom vhdl-highlight-keywords t
313 "*If non-nil, VHDL keywords and other predefined words are highlighted.
314 That is, keywords, predefined types, predefined attributes, and predefined
315 enumeration values are highlighted."
317 :group 'vhdl-highlight)
319 (defcustom vhdl-highlight-signals nil
320 "*If non-nil, signals of different classes are highlighted using colors.
321 Signal classes are: clock, reset, status/control, data, and test."
323 :group 'vhdl-highlight)
325 (defcustom vhdl-highlight-case-sensitive nil
326 "*If non-nil, case is considered for highlighting.
328 non-nil also upper-case VHDL words are highlighted, but case of signal names
329 is not considered (may lead to highlighting of unwanted words),
330 nil only lower-case VHDL words are highlighted, but case of signal names
332 Overrides local variable `font-lock-keywords-case-fold-search'."
334 :group 'vhdl-highlight)
336 (defcustom vhdl-customize-colors nil
337 "*If non-nil, colors are customized to go with the additional signal colors.
338 NOTE: this alters the behavior of Emacs for *all* modes,
339 so it is not enabled by default."
341 :group 'vhdl-highlight)
343 (defcustom vhdl-customize-faces t
344 "*If non-nil, faces are customized to work better with VHDL Mode.
345 This variable comes only into effect if no colors are used
346 for highlighting or printing (i.e. variable `ps-print-color-p' is nil).
348 NOTE: this alters the behavior of Emacs for *all* modes,
349 so it is not enabled by default."
351 :group 'vhdl-highlight)
354 (defgroup vhdl-signal-syntax nil
355 "Customizations of signal syntax for highlighting."
356 :group 'vhdl-highlight)
358 (defcustom vhdl-signal-syntax-doc-string "
359 Must be of the form \"\\ \<\\\(...\\\)\\\>\", where ... specifies the actual syntax.
360 (delete this space ^ , it's only a workaround to get this doc string.)
361 The basic regexp elements are:
362 [A-Z] any upper case letter
365 \\w any letter or digit (corresponds to [A-Za-z0-9])
366 [XY] letter \"X\" or \"Y\"
367 [^XY] neither letter \"X\" nor \"Y\"
369 * postfix operator for matching previous regexp element any times
370 + postfix operator for matching previous regexp element at least once
371 ? postfix operator for matching previous regexp element at most once"
372 "Common document string used for the custom variables below. Must be
373 defined as custom variable due to a bug in XEmacs.")
375 (defcustom vhdl-clock-signal-syntax "\\<\\([A-Z]\\w*xC\\w*\\)\\>"
377 "*Regular expression (regexp) for syntax of clock signals."
378 vhdl-signal-syntax-doc-string)
380 :group 'vhdl-signal-syntax)
382 (defcustom vhdl-reset-signal-syntax "\\<\\([A-Z]\\w*xR\\w*\\)\\>"
384 "*Regular expression (regexp) for syntax of (asynchronous) reset signals."
385 vhdl-signal-syntax-doc-string)
387 :group 'vhdl-signal-syntax)
389 (defcustom vhdl-control-signal-syntax "\\<\\([A-Z]\\w*x[IS]\\w*\\)\\>"
391 "*Regular expression (regexp) for syntax of status/control signals."
392 vhdl-signal-syntax-doc-string)
394 :group 'vhdl-signal-syntax)
396 (defcustom vhdl-data-signal-syntax "\\<\\([A-Z]\\w*xD\\w*\\)\\>"
398 "*Regular expression (regexp) for syntax of data signals."
399 vhdl-signal-syntax-doc-string)
401 :group 'vhdl-signal-syntax)
403 (defcustom vhdl-test-signal-syntax "\\<\\([A-Z]\\w*xT\\w*\\)\\>"
405 "*Regular expression (regexp) for syntax of test signals."
406 vhdl-signal-syntax-doc-string)
408 :group 'vhdl-signal-syntax)
411 (defgroup vhdl-menu nil
412 "Customizations for menues."
415 (defcustom vhdl-source-file-menu t
416 "*If non-nil, a menu of all source files in the current directory is created."
420 (defcustom vhdl-index-menu t
421 "*If non-nil, an index menu for the current source file is created."
425 (defcustom vhdl-hideshow-menu (not (string-match "XEmacs" emacs-version))
426 "*If non-nil, hideshow menu and functionality is added.
427 Hideshow allows hiding code of VHDL processes and blocks.
428 (Does not work under XEmacs.)"
433 (defgroup vhdl-print nil
434 "Customizations for printing."
437 (defcustom vhdl-print-two-column t
438 "*If non-nil, code is printed in two columns and landscape format."
443 (defgroup vhdl-misc nil
444 "Miscellaneous customizations."
447 (defcustom vhdl-intelligent-tab t
448 "*If non-nil, `TAB' does indentation, word completion, and tab insertion.
449 That is, if preceeding character is part of a word then complete word,
450 else if not at beginning of line then insert tab,
451 else if last command was a `TAB' or `RET' then dedent one step,
452 else indent current line (i.e. `TAB' is bound to `vhdl-tab').
453 If nil, TAB always indents current line (i.e. `TAB' is bound to
454 `vhdl-indent-line')."
458 (defcustom vhdl-template-key-binding-prefix "\C-t"
459 "*`C-c' plus this key gives the key binding prefix for all VHDL templates.
460 Default key binding prefix for templates is `C-c C-t' (example: architecture
461 `C-c C-t a'). If you have no own `C-c LETTER' bindings, you can shorten the
462 template key binding prefix to `C-c' (example: architecture `C-c a') by
463 assigning the empty character (\"\") to this variable. The syntax to enter
464 control keys is \"\\C-t\"."
468 (defcustom vhdl-word-completion-in-minibuffer t
469 "*If non-nil, word completion works in minibuffer (for template prompts)."
473 (defcustom vhdl-underscore-is-part-of-word nil
474 "*If non-nil, the underscore character `_' is considered as part of word.
475 An identifier containing underscores is then treated as a single word in
476 select and move operations. All parts of an identifier separated by underscore
477 are treated as single words otherwise."
481 ;; ############################################################################
484 (defvar vhdl-inhibit-startup-warnings-p nil
485 "*If non-nil, inhibits start up compatibility warnings.")
487 (defvar vhdl-strict-syntax-p nil
488 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
489 If the syntactic symbol for a particular line does not match a symbol
490 in the offsets alist, an error is generated, otherwise no error is
491 reported and the syntactic symbol is ignored.")
493 (defvar vhdl-echo-syntactic-information-p nil
494 "*If non-nil, syntactic info is echoed when the line is indented.")
496 (defconst vhdl-offsets-alist-default
501 (statement-cont . vhdl-lineup-statement-cont)
502 (statement-block-intro . +)
503 (statement-case-intro . +)
504 (case-alternative . +)
505 (comment . vhdl-lineup-comment)
508 (arglist-cont-nonempty . vhdl-lineup-arglist)
509 (arglist-close . vhdl-lineup-arglist)
516 "Default settings for offsets of syntactic elements.
517 Do not change this constant! See the variable `vhdl-offsets-alist' for
520 (defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
521 "*Association list of syntactic element symbols and indentation offsets.
522 As described below, each cons cell in this list has the form:
524 (SYNTACTIC-SYMBOL . OFFSET)
526 When a line is indented, vhdl-mode first determines the syntactic
527 context of the line by generating a list of symbols called syntactic
528 elements. This list can contain more than one syntactic element and
529 the global variable `vhdl-syntactic-context' contains the context list
530 for the line being indented. Each element in this list is actually a
531 cons cell of the syntactic symbol and a buffer position. This buffer
532 position is call the relative indent point for the line. Some
533 syntactic symbols may not have a relative indent point associated with
536 After the syntactic context list for a line is generated, vhdl-mode
537 calculates the absolute indentation for the line by looking at each
538 syntactic element in the list. First, it compares the syntactic
539 element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
540 finds a match, it adds the OFFSET to the column of the relative indent
541 point. The sum of this calculation for each element in the syntactic
542 list is the absolute offset for line being indented.
544 If the syntactic element does not match any in the `vhdl-offsets-alist',
545 an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
546 the element is ignored.
548 Actually, OFFSET can be an integer, a function, a variable, or one of
549 the following symbols: `+', `-', `++', or `--'. These latter
550 designate positive or negative multiples of `vhdl-basic-offset',
551 respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
552 called with a single argument containing the cons of the syntactic
553 element symbol and the relative indent point. The function should
554 return an integer offset.
556 Here is the current list of valid syntactic element symbols:
558 string -- inside multi-line string
559 block-open -- statement block open
560 block-close -- statement block close
561 statement -- a VHDL statement
562 statement-cont -- a continuation of a VHDL statement
563 statement-block-intro -- the first line in a new statement block
564 statement-case-intro -- the first line in a case alternative block
565 case-alternative -- a case statement alternative clause
566 comment -- a line containing only a comment
567 arglist-intro -- the first line in an argument list
568 arglist-cont -- subsequent argument list lines when no
569 arguments follow on the same line as the
570 the arglist opening paren
571 arglist-cont-nonempty -- subsequent argument list lines when at
572 least one argument follows on the same
573 line as the arglist opening paren
574 arglist-close -- the solo close paren of an argument list
575 entity -- inside an entity declaration
576 configuration -- inside a configuration declaration
577 package -- inside a package declaration
578 architecture -- inside an architecture body
579 package-body -- inside a package body
582 (defvar vhdl-comment-only-line-offset 0
583 "*Extra offset for line which contains only the start of a comment.
584 Can contain an integer or a cons cell of the form:
586 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
588 Where NON-ANCHORED-OFFSET is the amount of offset given to
589 non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
590 the amount of offset to give column-zero anchored comment-only lines.
591 Just an integer as value is equivalent to (<val> . 0)")
593 (defvar vhdl-special-indent-hook nil
594 "*Hook for user defined special indentation adjustments.
595 This hook gets called after a line is indented by the mode.")
597 (defvar vhdl-style-alist
599 (vhdl-basic-offset . 4)
600 (vhdl-offsets-alist . ())
603 "Styles of Indentation.
604 Elements of this alist are of the form:
606 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
608 where STYLE-STRING is a short descriptive string used to select a
609 style, VARIABLE is any vhdl-mode variable, and VALUE is the intended
610 value for that variable when using the selected style.
612 There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
613 case, the VALUE is a list containing elements of the form:
615 (SYNTACTIC-SYMBOL . VALUE)
617 as described in `vhdl-offsets-alist'. These are passed directly to
618 `vhdl-set-offset' so there is no need to set every syntactic symbol in
619 your style, only those that are different from the default.")
621 ;; dynamically append the default value of most variables
622 (or (assoc "Default" vhdl-style-alist)
623 (let* ((varlist '(vhdl-inhibit-startup-warnings-p
625 vhdl-echo-syntactic-information-p
628 vhdl-comment-only-line-offset))
629 (default (cons "Default"
633 (cons var (symbol-value var))
636 (setq vhdl-style-alist (cons default vhdl-style-alist))))
638 (defvar vhdl-mode-hook nil
639 "*Hook called by `vhdl-mode'.")
642 ;; ############################################################################
643 ;; Emacs variant handling
644 ;; ############################################################################
648 (defun vhdl-keep-region-active ()
649 ;; do whatever is necessary to keep the region active in XEmacs
650 ;; (formerly Lucid). ignore byte-compiler warnings you might see
651 (and (boundp 'zmacs-region-stays)
652 (setq zmacs-region-stays t)))
654 (defconst vhdl-emacs-features
655 (let ((major (and (boundp 'emacs-major-version)
656 emacs-major-version))
657 (minor (and (boundp 'emacs-minor-version)
658 emacs-minor-version))
660 ;; figure out version numbers if not already discovered
661 (and (or (not major) (not minor))
662 (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
663 (setq major (string-to-int (substring emacs-version
666 minor (string-to-int (substring emacs-version
669 (if (not (and major minor))
670 (error "Cannot figure out the major and minor version numbers."))
671 ;; calculate the major version
673 ((= major 18) (setq major 'v18)) ;Emacs 18
674 ((= major 4) (setq major 'v18)) ;Epoch 4
675 ((= major 19) (setq major 'v19 ;Emacs 19
677 ((string-match "Win-Emacs" emacs-version)
679 ((or (string-match "Lucid" emacs-version)
680 (string-match "XEmacs" emacs-version))
684 ((= major 20) (setq major 'v20 ;Emacs 20
686 ((string-match "Win-Emacs" emacs-version)
688 ((or (string-match "Lucid" emacs-version)
689 (string-match "XEmacs" emacs-version))
694 (t (error "Cannot recognize major version number: %s" major)))
695 ;; lets do some minimal sanity checking.
697 ;; Emacs 18 is brain dead
699 ;; Lemacs before 19.6 had bugs
700 (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
701 ;; Emacs 19 before 19.21 had bugs
702 (and (eq major 'v19) (eq flavor t) (< minor 21)))
703 (not vhdl-inhibit-startup-warnings-p))
704 (with-output-to-temp-buffer "*vhdl-mode warnings*"
706 "The version of Emacs that you are running, %s,
707 has known bugs in its syntax.c parsing routines which will affect the
708 performance of vhdl-mode. You should strongly consider upgrading to the
709 latest available version. vhdl-mode may continue to work, after a
710 fashion, but strange indentation errors could be encountered."
713 "A list of features extant in the Emacs you are using.
714 There are many flavors of Emacs out there, each with different
715 features supporting those needed by vhdl-mode. Here's the current
716 supported list, along with the values for this variable:
718 Emacs 18/Epoch 4: (v18)
719 XEmacs (formerly Lucid) 19: (v19 XEmacs)
720 Win-Emacs 1.35: (V19 Win-Emacs)
725 ;; ############################################################################
727 ;; ############################################################################
729 ;; ############################################################################
732 (defvar vhdl-template-map ()
733 "Keymap for VHDL templates.")
735 (if vhdl-template-map ()
736 (setq vhdl-template-map (make-sparse-keymap))
737 ;; key bindings for VHDL templates
738 (define-key vhdl-template-map "\M-A" 'vhdl-alias)
739 (define-key vhdl-template-map "a" 'vhdl-architecture)
740 (define-key vhdl-template-map "A" 'vhdl-array)
741 (define-key vhdl-template-map "\M-a" 'vhdl-assert)
742 (define-key vhdl-template-map "b" 'vhdl-block)
743 (define-key vhdl-template-map "c" 'vhdl-case)
744 (define-key vhdl-template-map "\M-c" 'vhdl-component)
745 (define-key vhdl-template-map "I" 'vhdl-component-instance)
746 (define-key vhdl-template-map "\M-s" 'vhdl-concurrent-signal-assignment)
747 (define-key vhdl-template-map "\M-Cb"'vhdl-block-configuration)
748 (define-key vhdl-template-map "\M-Cc"'vhdl-component-configuration)
749 (define-key vhdl-template-map "\M-Cd"'vhdl-configuration-decl)
750 (define-key vhdl-template-map "\M-Cs"'vhdl-configuration-spec)
751 (define-key vhdl-template-map "C" 'vhdl-constant)
752 (define-key vhdl-template-map "d" 'vhdl-disconnect)
753 (define-key vhdl-template-map "\M-e" 'vhdl-else)
754 (define-key vhdl-template-map "E" 'vhdl-elsif)
755 (define-key vhdl-template-map "e" 'vhdl-entity)
756 (define-key vhdl-template-map "x" 'vhdl-exit)
757 (define-key vhdl-template-map "f" 'vhdl-for)
758 (define-key vhdl-template-map "F" 'vhdl-function)
759 (define-key vhdl-template-map "g" 'vhdl-generate)
760 (define-key vhdl-template-map "G" 'vhdl-generic)
761 (define-key vhdl-template-map "h" 'vhdl-header)
762 (define-key vhdl-template-map "i" 'vhdl-if)
763 (define-key vhdl-template-map "L" 'vhdl-library)
764 (define-key vhdl-template-map "l" 'vhdl-loop)
765 (define-key vhdl-template-map "m" 'vhdl-modify)
766 (define-key vhdl-template-map "M" 'vhdl-map)
767 (define-key vhdl-template-map "n" 'vhdl-next)
768 (define-key vhdl-template-map "k" 'vhdl-package)
769 (define-key vhdl-template-map "(" 'vhdl-paired-parens)
770 (define-key vhdl-template-map "\M-p" 'vhdl-port)
771 (define-key vhdl-template-map "p" 'vhdl-procedure)
772 (define-key vhdl-template-map "P" 'vhdl-process)
773 (define-key vhdl-template-map "R" 'vhdl-record)
774 (define-key vhdl-template-map "r" 'vhdl-return-value)
775 (define-key vhdl-template-map "\M-S" 'vhdl-selected-signal-assignment)
776 (define-key vhdl-template-map "s" 'vhdl-signal)
777 (define-key vhdl-template-map "S" 'vhdl-subtype)
778 (define-key vhdl-template-map "t" 'vhdl-type)
779 (define-key vhdl-template-map "u" 'vhdl-use)
780 (define-key vhdl-template-map "v" 'vhdl-variable)
781 (define-key vhdl-template-map "W" 'vhdl-wait)
782 (define-key vhdl-template-map "w" 'vhdl-while-loop)
783 (define-key vhdl-template-map "\M-w" 'vhdl-with)
784 (define-key vhdl-template-map "\M-W" 'vhdl-clocked-wait)
785 (define-key vhdl-template-map "Kb" 'vhdl-package-numeric-bit)
786 (define-key vhdl-template-map "Kn" 'vhdl-package-numeric-std)
787 (define-key vhdl-template-map "Ks" 'vhdl-package-std-logic-1164)
788 (define-key vhdl-template-map "Kt" 'vhdl-package-textio)
791 (defvar vhdl-mode-map ()
792 "Keymap for VHDL Mode.")
795 (setq vhdl-mode-map (make-sparse-keymap))
796 ;; key bindings for templates
797 (define-key vhdl-mode-map
798 (concat "\C-c" vhdl-template-key-binding-prefix) vhdl-template-map)
799 ;; standard key bindings
800 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
801 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
802 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
803 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
804 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
805 ;(define-key vhdl-mode-map "\M-\C-d" 'vhdl-down-list)
806 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
807 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
808 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
809 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
810 (define-key vhdl-mode-map "\177" 'backward-delete-char-untabify)
811 (define-key vhdl-mode-map "\r" 'vhdl-return)
812 (if vhdl-intelligent-tab
813 (define-key vhdl-mode-map "\t" 'vhdl-tab)
814 (define-key vhdl-mode-map "\t" 'vhdl-indent-line))
815 (define-key vhdl-mode-map " " 'vhdl-outer-space)
816 ;; new key bindings for VHDL Mode, with no counterpart to BOCM
817 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
818 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
819 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
820 (define-key vhdl-mode-map "\C-c\C-f" 'font-lock-fontify-buffer)
821 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
822 (define-key vhdl-mode-map "\C-c\C-r" 'vhdl-regress-line)
823 (define-key vhdl-mode-map "\C-c\C-i" 'vhdl-indent-line)
824 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-noindent-region)
825 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-comment-region)
826 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
827 (define-key vhdl-mode-map "\C-c-" 'vhdl-inline-comment)
828 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-display-comment-line)
829 (define-key vhdl-mode-map "\C-c\C-o" 'vhdl-open-line)
830 (define-key vhdl-mode-map "\C-c\C-g" 'goto-line)
831 (define-key vhdl-mode-map "\C-c\C-d" 'vhdl-kill-line)
832 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-help)
833 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
834 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-submit-bug-report)
835 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
836 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
837 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
838 ;; key bindings for stuttering
839 (define-key vhdl-mode-map "-" 'vhdl-stutter-mode-dash)
840 (define-key vhdl-mode-map "'" 'vhdl-stutter-mode-quote)
841 (define-key vhdl-mode-map ";" 'vhdl-stutter-mode-semicolon)
842 (define-key vhdl-mode-map "[" 'vhdl-stutter-mode-open-bracket)
843 (define-key vhdl-mode-map "]" 'vhdl-stutter-mode-close-bracket)
844 (define-key vhdl-mode-map "." 'vhdl-stutter-mode-period)
845 (define-key vhdl-mode-map "," 'vhdl-stutter-mode-comma)
847 (while (< c 123) ; for little a-z
848 (define-key vhdl-mode-map (char-to-string c) 'vhdl-stutter-mode-caps)
853 ;; define special minibuffer keymap for enabling word completion in minibuffer
854 ;; (useful in template generator prompts)
855 (defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
856 "Keymap for minibuffer used in VHDL Mode.")
858 (define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab)
860 (defvar vhdl-mode-syntax-table nil
861 "Syntax table used in vhdl-mode buffers.")
863 (if vhdl-mode-syntax-table ()
864 (setq vhdl-mode-syntax-table (make-syntax-table))
865 ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
866 ;; why not? (is left to the user here)
867 (if vhdl-underscore-is-part-of-word
868 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
869 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
870 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
871 (modify-syntax-entry ?\% "." vhdl-mode-syntax-table)
872 (modify-syntax-entry ?\& "." vhdl-mode-syntax-table)
873 (modify-syntax-entry ?\' "." vhdl-mode-syntax-table)
874 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
875 (modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table)
876 (modify-syntax-entry ?\* "." vhdl-mode-syntax-table)
877 (modify-syntax-entry ?\+ "." vhdl-mode-syntax-table)
878 (modify-syntax-entry ?\. "." vhdl-mode-syntax-table)
879 (modify-syntax-entry ?\/ "." vhdl-mode-syntax-table)
880 (modify-syntax-entry ?\: "." vhdl-mode-syntax-table)
881 (modify-syntax-entry ?\; "." vhdl-mode-syntax-table)
882 (modify-syntax-entry ?\< "." vhdl-mode-syntax-table)
883 (modify-syntax-entry ?\= "." vhdl-mode-syntax-table)
884 (modify-syntax-entry ?\> "." vhdl-mode-syntax-table)
885 (modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table)
886 (modify-syntax-entry ?\\ "\\" vhdl-mode-syntax-table)
887 (modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table)
888 (modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table)
889 (modify-syntax-entry ?\| "." vhdl-mode-syntax-table)
890 (modify-syntax-entry ?\} "){" vhdl-mode-syntax-table)
891 ;; add comment syntax
892 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
893 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
894 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table))
896 (defvar vhdl-syntactic-context nil
897 "Buffer local variable containing syntactic analysis list.")
898 (make-variable-buffer-local 'vhdl-syntactic-context)
900 ;; ############################################################################
901 ;; Abbrev hook bindings
903 (defvar vhdl-mode-abbrev-table nil
904 "Abbrev table in use in vhdl-mode buffers.")
906 (define-abbrev-table 'vhdl-mode-abbrev-table
908 ("--" "" vhdl-display-comment-hook 0)
909 ("abs" "" vhdl-default-hook 0)
910 ("access" "" vhdl-default-hook 0)
911 ("after" "" vhdl-default-hook 0)
912 ("alias" "" vhdl-alias-hook 0)
913 ("all" "" vhdl-default-hook 0)
914 ("and" "" vhdl-default-hook 0)
915 ("arch" "" vhdl-architecture-hook 0)
916 ("architecture" "" vhdl-architecture-hook 0)
917 ("array" "" vhdl-array-hook 0)
918 ("assert" "" vhdl-assert-hook 0)
919 ("attr" "" vhdl-attribute-hook 0)
920 ("attribute" "" vhdl-attribute-hook 0)
921 ("begin" "" vhdl-default-indent-hook 0)
922 ("block" "" vhdl-block-hook 0)
923 ("body" "" vhdl-default-hook 0)
924 ("buffer" "" vhdl-default-hook 0)
925 ("bus" "" vhdl-default-hook 0)
926 ("case" "" vhdl-case-hook 0)
927 ("comp" "" vhdl-component-hook 0)
928 ("component" "" vhdl-component-hook 0)
929 ("conc" "" vhdl-concurrent-signal-assignment-hook 0)
930 ("concurrent" "" vhdl-concurrent-signal-assignment-hook 0)
931 ("conf" "" vhdl-configuration-hook 0)
932 ("configuration" "" vhdl-configuration-hook 0)
933 ("cons" "" vhdl-constant-hook 0)
934 ("constant" "" vhdl-constant-hook 0)
935 ("disconnect" "" vhdl-disconnect-hook 0)
936 ("downto" "" vhdl-default-hook 0)
937 ("else" "" vhdl-else-hook 0)
938 ("elseif" "" vhdl-elsif-hook 0)
939 ("elsif" "" vhdl-elsif-hook 0)
940 ("end" "" vhdl-default-indent-hook 0)
941 ("entity" "" vhdl-entity-hook 0)
942 ("exit" "" vhdl-exit-hook 0)
943 ("file" "" vhdl-default-hook 0)
944 ("for" "" vhdl-for-hook 0)
945 ("func" "" vhdl-function-hook 0)
946 ("function" "" vhdl-function-hook 0)
947 ("gen" "" vhdl-generate-hook 0)
948 ("generate" "" vhdl-generate-hook 0)
949 ("generic" "" vhdl-generic-hook 0)
950 ("group" "" vhdl-default-hook 0)
951 ("guarded" "" vhdl-default-hook 0)
952 ("header" "" vhdl-header-hook 0)
953 ("if" "" vhdl-if-hook 0)
954 ("impure" "" vhdl-default-hook 0)
955 ("in" "" vhdl-default-hook 0)
956 ("inertial" "" vhdl-default-hook 0)
957 ("inout" "" vhdl-default-hook 0)
958 ("inst" "" vhdl-component-instance-hook 0)
959 ("instance" "" vhdl-component-instance-hook 0)
960 ("is" "" vhdl-default-hook 0)
961 ("label" "" vhdl-default-hook 0)
962 ("library" "" vhdl-library-hook 0)
963 ("linkage" "" vhdl-default-hook 0)
964 ("literal" "" vhdl-default-hook 0)
965 ("loop" "" vhdl-loop-hook 0)
966 ("map" "" vhdl-map-hook 0)
967 ("mod" "" vhdl-default-hook 0)
968 ("modify" "" vhdl-modify-hook 0)
969 ("nand" "" vhdl-default-hook 0)
970 ("new" "" vhdl-default-hook 0)
971 ("next" "" vhdl-next-hook 0)
972 ("nor" "" vhdl-default-hook 0)
973 ("not" "" vhdl-default-hook 0)
974 ("null" "" vhdl-default-hook 0)
975 ("of" "" vhdl-default-hook 0)
976 ("on" "" vhdl-default-hook 0)
977 ("open" "" vhdl-default-hook 0)
978 ("or" "" vhdl-default-hook 0)
979 ("others" "" vhdl-default-hook 0)
980 ("out" "" vhdl-default-hook 0)
981 ("pack" "" vhdl-package-hook 0)
982 ("package" "" vhdl-package-hook 0)
983 ("port" "" vhdl-port-hook 0)
984 ("postponed" "" vhdl-default-hook 0)
985 ("procedure" "" vhdl-procedure-hook 0)
986 ("process" "" vhdl-process-hook 0)
987 ("pure" "" vhdl-default-hook 0)
988 ("range" "" vhdl-default-hook 0)
989 ("record" "" vhdl-record-hook 0)
990 ("register" "" vhdl-default-hook 0)
991 ("reject" "" vhdl-default-hook 0)
992 ("rem" "" vhdl-default-hook 0)
993 ("report" "" vhdl-default-hook 0)
994 ("ret" "" vhdl-return-hook 0)
995 ("return" "" vhdl-return-hook 0)
996 ("rol" "" vhdl-default-hook 0)
997 ("ror" "" vhdl-default-hook 0)
998 ("select" "" vhdl-selected-signal-assignment-hook 0)
999 ("severity" "" vhdl-default-hook 0)
1000 ("shared" "" vhdl-default-hook 0)
1001 ("sig" "" vhdl-signal-hook 0)
1002 ("signal" "" vhdl-signal-hook 0)
1003 ("sla" "" vhdl-default-hook 0)
1004 ("sll" "" vhdl-default-hook 0)
1005 ("sra" "" vhdl-default-hook 0)
1006 ("srl" "" vhdl-default-hook 0)
1007 ("sub" "" vhdl-subtype-hook 0)
1008 ("subtype" "" vhdl-subtype-hook 0)
1009 ("then" "" vhdl-default-hook 0)
1010 ("to" "" vhdl-default-hook 0)
1011 ("transport" "" vhdl-default-hook 0)
1012 ("type" "" vhdl-type-hook 0)
1013 ("unaffected" "" vhdl-default-hook 0)
1014 ("units" "" vhdl-default-hook 0)
1015 ("until" "" vhdl-default-hook 0)
1016 ("use" "" vhdl-use-hook 0)
1017 ("var" "" vhdl-variable-hook 0)
1018 ("variable" "" vhdl-variable-hook 0)
1019 ("wait" "" vhdl-wait-hook 0)
1020 ("warning" "" vhdl-default-hook 0)
1021 ("when" "" vhdl-when-hook 0)
1022 ("while" "" vhdl-while-loop-hook 0)
1023 ("with" "" vhdl-selected-signal-assignment-hook 0)
1024 ("xnor" "" vhdl-default-hook 0)
1025 ("xor" "" vhdl-default-hook 0)
1029 ;; ############################################################################
1031 ;; ############################################################################
1033 ;; ############################################################################
1034 ;; VHDL menu (using `easy-menu.el')
1036 ;; `customize-menu-create' is included in `cus-edit.el' version 1.9954,
1037 ;; which is not yet distributed with XEmacs 19.15
1038 (defun vhdl-customize-menu-create (symbol &optional name)
1039 "Return a customize menu for customization group SYMBOL.
1040 If optional NAME is given, use that as the name of the menu.
1041 Otherwise the menu will be named `Customize'.
1042 The format is suitable for use with `easy-menu-define'."
1044 (setq name "Customize"))
1045 (if (memq 'XEmacs vhdl-emacs-features)
1046 ;; We can delay it under XEmacs.
1048 :filter (lambda (&rest junk)
1049 (cdr (custom-menu-create ',symbol))))
1050 ;; But we must create it now under Emacs.
1051 (cons name (cdr (custom-menu-create symbol)))))
1053 (defvar vhdl-mode-menu
1057 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
1058 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
1062 ["Compile Buffer" vhdl-compile t]
1063 ["Stop Compilation" kill-compilation t]
1065 ["Make" vhdl-make t]
1066 ["Generate Makefile" vhdl-generate-makefile t]
1068 ["Next Error" next-error t]
1069 ["Previous Error" previous-error t]
1070 ["First Error" first-error t]
1075 ["Alias" vhdl-alias t]
1076 ["Architecture" vhdl-architecture t]
1077 ["Array" vhdl-array t]
1078 ["Assert" vhdl-assert t]
1079 ["Attribute" vhdl-attribute t]
1080 ["Block" vhdl-block t]
1081 ["Case" vhdl-case t]
1082 ["Component" vhdl-component t]
1083 ["Concurrent (Signal Asst)" vhdl-concurrent-signal-assignment t]
1084 ["Configuration (Block)" vhdl-block-configuration t]
1085 ["Configuration (Comp)" vhdl-component-configuration t]
1086 ["Configuration (Decl)" vhdl-configuration-decl t]
1087 ["Configuration (Spec)" vhdl-configuration-spec t]
1088 ["Constant" vhdl-constant t]
1089 ["Disconnect" vhdl-disconnect t]
1090 ["Else" vhdl-else t]
1091 ["Elsif" vhdl-elsif t]
1092 ["Entity" vhdl-entity t]
1093 ["Exit" vhdl-exit t]
1094 ["For (Loop)" vhdl-for t]
1095 ["Function" vhdl-function t]
1096 ["(For/If) Generate" vhdl-generate t]
1097 ["Generic" vhdl-generic t]
1101 ["Instance" vhdl-component-instance t]
1102 ["Library" vhdl-library t]
1103 ["Loop" vhdl-loop t]
1105 ["Next" vhdl-next t]
1106 ["Package" vhdl-package t]
1107 ["Port" vhdl-port t]
1108 ["Procedure" vhdl-procedure t]
1109 ["Process" vhdl-process t]
1110 ["Record" vhdl-record t]
1111 ["Return" vhdl-return-value t]
1112 ["Select" vhdl-selected-signal-assignment t]
1113 ["Signal" vhdl-signal t]
1114 ["Subtype" vhdl-subtype t]
1115 ["Type" vhdl-type t]
1117 ["Variable" vhdl-variable t]
1118 ["Wait" vhdl-wait t]
1119 ["(Clocked Wait)" vhdl-clocked-wait t]
1120 ["When" vhdl-when t]
1121 ["While (Loop)" vhdl-while-loop t]
1122 ["With" vhdl-with t]
1125 ["numeric_bit" vhdl-package-numeric-bit t]
1126 ["numeric_std" vhdl-package-numeric-std t]
1127 ["std_logic_1164" vhdl-package-std-logic-1164 t]
1128 ["textio" vhdl-package-textio t]
1130 ["Header" vhdl-header t]
1131 ["Modify (Date)" vhdl-modify t]
1134 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
1135 ["Insert Inline Comment" vhdl-inline-comment t]
1136 ["Insert Horizontal Line" vhdl-display-comment-line t]
1137 ["Insert Display Comment" vhdl-display-comment t]
1138 ["Fill Comment" fill-paragraph t]
1139 ["Fill Comment Region" fill-region (mark)]
1142 ["Line" vhdl-indent-line t]
1143 ["Region" indent-region (mark)]
1144 ["Buffer" vhdl-indent-buffer t]
1147 ["Region" vhdl-align-noindent-region (mark)]
1148 ["Comment Region" vhdl-align-comment-region (mark)]
1151 ["Open" vhdl-open-line t]
1152 ["Delete" vhdl-kill-line t]
1153 ["Join" delete-indentation t]
1154 ["Goto" goto-line t]
1157 ["Forward Statement" vhdl-end-of-statement t]
1158 ["Backward Statement" vhdl-beginning-of-statement t]
1159 ["Forward Expression" vhdl-forward-sexp t]
1160 ["Backward Expression" vhdl-backward-sexp t]
1161 ["Forward Function" vhdl-end-of-defun t]
1162 ["Backward Function" vhdl-beginning-of-defun t]
1166 ["Buffer" vhdl-fix-case-buffer t]
1167 ["Region" vhdl-fix-case-region (mark)]
1169 ["Fontify Buffer" font-lock-fontify-buffer t]
1170 ["Syntactic Info" vhdl-show-syntactic-information t]
1172 ["Help" vhdl-help t]
1173 ["Version" vhdl-version t]
1174 ["Bug Report" vhdl-submit-bug-report t]
1177 (list (vhdl-customize-menu-create 'vhdl))
1182 ;; ############################################################################
1183 ;; Index menu (using `imenu.el')
1185 (defvar vhdl-imenu-generic-expression
1188 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1191 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
1194 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
1197 "^\\s-*\\(package body\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1200 "^\\s-*\\(package\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1203 "^\\s-*\\(sub\\)?type\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1206 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1208 ("Function / Procedure"
1209 "^\\s-*\\(procedure\\|function\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1212 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(process\\|block\\)"
1215 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
1218 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
1220 (defun vhdl-add-index-menu ()
1221 (make-local-variable 'imenu-generic-expression)
1222 (setq imenu-generic-expression (nreverse vhdl-imenu-generic-expression))
1223 (imenu-add-to-menubar "Index"))
1225 ;; ############################################################################
1226 ;; Source file menu (using `easy-menu.el')
1228 (defvar vhdl-extlist '("[A-Za-z0-9_.]*.vhdl?$"))
1229 (defvar vhdl-filelist-menu nil)
1231 (defun vhdl-add-source-files-menu ()
1232 "Scan directory of current source file for all VHDL source files, and
1235 (message "Scanning directory for source files ...")
1236 (let (filelist menulist tmpextlist found
1237 (newmap (current-local-map)))
1238 (cd (file-name-directory (buffer-file-name)))
1241 (setq tmpextlist vhdl-extlist)
1243 (setq filelist (nreverse (directory-files
1244 (file-name-directory (buffer-file-name))
1245 nil (car tmpextlist) nil)))
1246 ;; Create list for menu
1250 (setq menulist (cons (vector (car filelist)
1251 (list 'find-file (car filelist)) t)
1253 (setq filelist (cdr filelist)))
1254 (setq menulist (vhdl-menu-split menulist 25))
1256 (setq menulist (cons "--" menulist)))
1257 (setq tmpextlist (cdr tmpextlist)))
1258 (setq menulist (cons ["*Rescan*" vhdl-add-source-files-menu t] menulist))
1259 (setq menulist (cons "Sources" menulist))
1261 (easy-menu-add menulist)
1262 (easy-menu-define vhdl-filelist-menu newmap
1263 "VHDL source files menu" menulist)
1264 ; (use-local-map (append (current-local-map) newmap))
1265 ; (use-local-map newmap)
1269 (defun vhdl-menu-split (list n)
1270 "Split menu into several submenues, if number of elements > n."
1271 (if (> (length list) n)
1278 (setq sublist (cons (car remain) sublist))
1279 (setq remain (cdr remain))
1283 (setq result (cons (cons (format "Sources %s" menuno)
1284 (nreverse sublist)) result))
1286 (setq menuno (+ menuno 1))
1287 (setq sublist '()))))
1289 (setq result (cons (cons (format "Sources %s" menuno)
1290 (nreverse sublist)) result)))
1295 ;; ############################################################################
1296 ;; VHDL Mode definition
1297 ;; ############################################################################
1300 "Major mode for editing VHDL code.
1305 - TEMPLATE INSERTION (electrification) (`\\[vhdl-outer-space]'): After typing
1306 a VHDL keyword and entering `\\[vhdl-outer-space]', you are prompted for
1307 arguments while a template is generated for that VHDL construct. Typing
1308 `\\[vhdl-return]' (or `\\[keyboard-quit]' in yes-no queries) at the first
1309 prompt aborts the current template generation. Typing `\\[just-one-space]'
1310 after a keyword inserts a space without calling the template generator.
1311 Automatic calling of the template generators (i.e. electrification) can be
1312 disabled (enabled) by setting the variable `vhdl-electric-mode' to nil
1313 (non-nil) or by typing `\\[vhdl-electric-mode]' (toggles electrification
1315 Template generators can be called using the VHDL menu, the key bindings, or
1316 by typing the keyword (first word of menu entry not in parenthesis) and
1317 `\\[vhdl-outer-space]'. The following abbreviations can also be used:
1318 arch, attr, conc, conf, comp, cons, func, inst, pack, ret, sig, sub, var.
1320 - HEADER INSERTION (`\\[vhdl-header]'): A customized header can be inserted
1321 including the actual file name, user name, and current date as well as
1322 prompted title strings. A custom header can be defined in a separate file
1323 (see custom variable `vhdl-header-file').
1325 - STUTTERING (double strike): Double striking of some keys inserts cumbersome
1326 VHDL syntax elements. Stuttering can be disabled by variable
1327 `vhdl-stutter-mode' and be toggled by typing `\\[vhdl-stutter-mode]'.
1328 '' --> \" [ --> ( -- --> comment
1329 ;; --> \" : \" [[ --> [ --CR --> comment-out code
1330 ;;; --> \" := \" ] --> ) --- --> horizontal line
1331 .. --> \" => \" ]] --> ] ---- --> display comment
1332 ,, --> \" <= \" aa --> A - zz --> Z
1334 - WORD COMPLETION (`\\[vhdl-tab]'): Typing `\\[vhdl-tab]' after a (not
1335 completed) word looks for a word in the buffer that starts alike and
1336 inserts it. Re-typing `\\[vhdl-tab]' toggles through alternative word
1337 completions. This also works in the minibuffer (i.e. in template generator
1340 Typing `\\[vhdl-tab]' after a non-word character indents the line if at the
1341 beginning of a line (i.e. no preceding non-blank characters), and inserts a
1342 tabulator stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator
1345 - COMMENTS (`--', `---', `----', `--CR'):
1346 `--' puts a single comment.
1347 `---' draws a horizontal line for separating code segments.
1348 `----' inserts a display comment, i.e. two horizontal lines with a
1350 `--CR' comments out code on that line. Re-hitting CR comments out
1352 `\\[vhdl-comment-uncomment-region]' comments out a region if not
1353 commented out, uncomments out a region if already
1356 You are prompted for comments after object definitions (i.e. signals,
1357 variables, constants, ports) and after subprogram and process specifications
1358 if variable `vhdl-prompt-for-comments' is non-nil. Comments are
1359 automatically inserted as additional labels (e.g. after begin statements)
1360 and help comments if `vhdl-self-insert-comments' is non-nil.
1361 Inline comments (i.e. comments after a piece of code on the same line) are
1362 indented at least to `vhdl-comment-column'. Comments go at maximum to
1363 `vhdl-end-comment-column'. `\\[vhdl-return]' after a space in a comment will
1364 open a new comment line. Typing beyond `vhdl-end-comment-column' in a
1365 comment automatically opens a new comment line. `\\[fill-paragraph]'
1366 re-fills multi-line comments.
1368 - INDENTATION: `\\[vhdl-tab]' indents a line if at the beginning of the line.
1369 The amount of indentation is specified by variable `vhdl-basic-offset'.
1370 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB'
1371 if variable `vhdl-intelligent-tab' is nil). Indentation can be done for
1372 an entire region (`\\[indent-region]') or buffer (menu). Argument and
1373 port lists are indented normally (nil) or relative to the opening
1374 parenthesis (non-nil) according to variable `vhdl-argument-list-indent'.
1375 If variable `vhdl-indent-tabs-mode' is nil, spaces are used instead of tabs.
1376 `\\[tabify]' and `\\[untabify]' allow to convert spaces to tabs and vice
1379 - ALIGNMENT: `\\[vhdl-align-noindent-region]' aligns port maps, signal and
1380 variable assignments, inline comments, some keywords, etc., on consecutive
1381 lines relative to each other within a defined region.
1382 `\\[vhdl-align-comment-region]' only aligns inline comments (i.e. comments
1383 that are at the end of a line of code). Some templates are automatically
1384 aligned after generation if custom variable `vhdl-auto-align' is non-nil.
1386 - KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in menu).
1388 - VHDL MENU: All commands can be called from the VHDL menu.
1390 - INDEX MENU: For each VHDL source file, an index of the contained entities,
1391 architectures, packages, procedures, processes, etc., is created as a menu.
1392 Selecting a meny entry causes the cursor to jump to the corresponding
1393 position in the file. Controlled by variable `vhdl-index-menu'.
1395 - SOURCE FILE MENU: A menu containing all VHDL source files in the directory
1396 of the current file is generated. Selecting a menu entry loads the file.
1397 Controlled by variable `vhdl-source-file-menu'.
1399 - SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
1400 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be
1401 used is defined by variable `vhdl-compiler'. Currently supported are
1402 `cadence', `ikos', `quickhdl', `synopsys', `vantage', `viewlogic', and
1403 `v-system'. Not all compilers are tested. Please contact me for
1404 incorporating additional VHDL compilers. An entire hierarchy of source
1405 files can be compiled by the `make' command (menu, `\\[vhdl-make]').
1406 This only works if an appropriate `Makefile' exists. Compiler options can
1407 be defined by variable `vhdl-compiler-options'.
1409 - KEYWORD CASE: Lower and upper case for keywords, predefined types, predefined
1410 attributes, and predefined enumeration values is supported. If the variable
1411 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in
1412 lower case and are converted into upper case automatically (not for types,
1413 attributes, and enumeration values). The case of keywords, types,
1414 attributes, and enumeration values can be fixed for an entire region (menu)
1415 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
1416 `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
1418 - HIGHLIGHTING (fontification): Keywords, predefined types, predefined
1419 attributes, and predefined enumeration values (controlled by variable
1420 `vhdl-highlight-keywords'), as well as comments, strings, and template
1421 prompts are highlighted using different colors. Unit and subprogram names
1422 as well as labels are highlighted if variable `vhdl-highlight-names' is
1423 non-nil. The default colors from `font-lock.el' are used if variable
1424 `vhdl-customize-colors' is nil. Otherwise, an optimized set of colors
1425 is taken, which uses bright colors for signals and muted colors for
1426 everything else. Variable `vhdl-customize-faces' does the same on
1427 monochrome monitors.
1429 Signal highlighting allows distinction between clock, reset,
1430 status/control, data, and test signals according to some signal
1431 naming convention. Their syntax is defined by variables
1432 `vhdl-{clock,reset,control,data,test}-signal-syntax'. Signal coloring
1433 is controlled by the variable `vhdl-highlight-signals'. The default
1434 signal naming convention is as follows:
1437 C clock S control and status
1438 R asynchronous reset D data and address
1439 I synchronous reset T test
1442 signal name ::= \"[A-Z][a-zA-Z0-9]*x[CRISDT][a-zA-Z0-9]*\"
1443 signal identifier -^^^^^^^^^^^^^^^^^
1444 delimiter --------------------------^
1445 above signal attributes -------------^^^^^^^^
1446 additional attributes -----------------------^^^^^^^^^^^^
1448 (`x' is used as delimiter because `_' is reserved by the VITAL standard.)
1449 Examples: ClkxCfast, ResetxRB, ClearxI, SelectDataxS, DataxD, ScanEnablexT.
1451 If all VHDL words are written in lower case (i.e. variables
1452 `vhdl-upper-case-{keywords,types,attributes,enum-values}' are set to nil),
1453 make highlighting case sensitive by setting variable
1454 `vhdl-highlight-case-sensitive' to non-nil. This way, only names fulfilling
1455 the above signal syntax including case are highlighted.
1457 - HIDE/SHOW: The code of entire VHDL processes or blocks can be hidden using
1458 the `Hide/Show' menu or by pressing `S-mouse-2' within the code
1461 - PRINTING: Postscript printing with different fonts (`ps-print-color-p' is
1462 nil, default faces from `font-lock.el' used if `vhdl-customize-faces' is
1463 nil) or colors (`ps-print-color-p' is non-nil) is possible using the
1464 standard Emacs postscript printing commands. Variable `vhdl-print-two-column'
1465 defines appropriate default settings for nice landscape two-column printing.
1466 The paper format can be set by variable `ps-paper-type'.
1468 - CUSTOMIZATION: All variables can easily be customized using the `Customize'
1469 menu entry. For some variables, customization only takes effect after
1470 re-starting Emacs. Customization can also be done globally (i.e. site-wide,
1471 read INSTALL file). Variables of VHDL Mode must NOT be set using the
1472 `vhdl-mode-hook' in the .emacs file anymore (delete them if they still are).
1478 To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
1479 Add a description of the problem and include a reproducible test case.
1481 Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
1483 The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
1484 The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
1485 You are kindly invited to participate in beta testing. Subscribe to above
1486 mailing lists by sending an email to <vhdl-mode@geocities.com>.
1488 The archive with the latest version is located at
1489 <http://www.geocities.com/SiliconValley/Peaks/8287>.
1492 Bugs and Limitations:
1493 ---------------------
1495 - Index menu does not work under XEmacs (limitation of XEmacs ?!).
1497 - Re-indenting large regions or expressions can be slow.
1499 - Hideshow does not work under XEmacs.
1501 - Parsing compilation error messages for Ikos and Vantage VHDL compilers
1502 does not work under XEmacs.
1510 (kill-all-local-variables)
1511 (set-syntax-table vhdl-mode-syntax-table)
1512 (setq major-mode 'vhdl-mode)
1513 (setq mode-name "VHDL")
1514 (setq local-abbrev-table vhdl-mode-abbrev-table)
1515 (use-local-map vhdl-mode-map)
1516 ;; set local variable values
1517 (set (make-local-variable 'paragraph-start) "\\s-*\\(---\\|[a-zA-Z]\\|$\\)")
1518 (set (make-local-variable 'paragraph-separate) paragraph-start)
1519 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
1520 (set (make-local-variable 'require-final-newline) t)
1521 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1522 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
1523 (set (make-local-variable 'comment-start) "--")
1524 (set (make-local-variable 'comment-end) "")
1525 (set (make-local-variable 'comment-column) vhdl-comment-column)
1526 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
1527 (set (make-local-variable 'comment-start-skip) "--+\\s-*")
1528 (set (make-local-variable 'dabbrev-case-fold-search) nil)
1529 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
1531 ;; setup the comment indent variable in a Emacs version portable way
1532 ;; ignore any byte compiler warnings you might get here
1533 (if (boundp 'comment-indent-function)
1534 (progn (make-local-variable 'comment-indent-function)
1535 (setq comment-indent-function 'vhdl-comment-indent)))
1537 ;; initialize font locking
1538 (require 'font-lock)
1539 (vhdl-font-lock-init)
1540 (make-local-variable 'font-lock-defaults)
1541 (setq font-lock-defaults (list 'vhdl-font-lock-keywords nil
1542 (not vhdl-highlight-case-sensitive)
1546 ;; variables for source file compilation
1547 (make-local-variable 'compile-command)
1548 (set (make-local-variable 'compilation-error-regexp-alist)
1549 vhdl-compilation-error-regexp-alist)
1553 (if (or (not (consp font-lock-maximum-size))
1554 (> font-lock-maximum-size (buffer-size)))
1555 (vhdl-add-index-menu)
1556 (message "Scanning buffer for index...buffer too big")))
1557 (if vhdl-source-file-menu (vhdl-add-source-files-menu))
1558 (easy-menu-add vhdl-mode-menu)
1559 (easy-menu-define vhdl-mode-easy-menu vhdl-mode-map
1560 "Menu keymap for VHDL Mode." vhdl-mode-menu)
1561 (run-hooks 'menu-bar-update-hook)
1563 ;; initialize hideshow and add menu
1564 (if vhdl-hideshow-menu (hs-minor-mode))
1566 ;; initialize postscript printing
1569 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
1570 (message "Type C-c C-h for VHDL Mode documentation.")
1572 (run-hooks 'vhdl-mode-hook)
1576 ;; ############################################################################
1577 ;; Keywords and predefined words in VHDL'93
1578 ;; ############################################################################
1580 ;; `regexp-opt' was not used at this place because it is not yet implemented
1581 ;; in XEmacs and because it resulted in SLOWER regexps!!
1583 (defconst vhdl-93-keywords-regexp
1590 "abs" "access" "after" "alias" "all" "and" "architecture" "array"
1591 "assert" "attribute"
1592 "begin" "block" "body" "buffer" "bus"
1593 "case" "component" "configuration" "constant"
1594 "disconnect" "downto"
1595 "else" "elsif" "end" "entity" "exit"
1596 "file" "for" "function"
1597 "generate" "generic" "group" "guarded"
1598 "if" "impure" "in" "inertial" "inout" "is"
1599 "label" "library" "linkage" "literal" "loop"
1601 "nand" "new" "next" "nor" "not" "null"
1602 "of" "on" "open" "or" "others" "out"
1603 "package" "port" "postponed" "procedure" "process" "pure"
1604 "range" "record" "register" "reject" "rem" "report" "return"
1606 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
1607 "then" "to" "transport" "type"
1608 "unaffected" "units" "until" "use"
1610 "wait" "warning" "when" "while" "with"
1615 "Regexp for VHDL'93 keywords.")
1617 (defconst vhdl-93-types-regexp
1624 "boolean" "bit" "bit_vector" "character" "severity_level" "integer"
1625 "real" "time" "natural" "positive" "string" "text" "line"
1627 "std_logic" "std_logic_vector"
1628 "std_ulogic" "std_ulogic_vector"
1632 "Regexp for VHDL'93 standardized types.")
1634 (defconst vhdl-93-attributes-regexp
1641 "base" "left" "right" "high" "low" "pos" "val" "succ"
1642 "pred" "leftof" "rightof" "range" "reverse_range"
1643 "length" "delayed" "stable" "quiet" "transaction"
1644 "event" "active" "last_event" "last_active" "last_value"
1645 "driving" "driving_value" "ascending" "value" "image"
1646 "simple_name" "instance_name" "path_name"
1651 "Regexp for VHDL'93 standardized attributes.")
1653 (defconst vhdl-93-enum-values-regexp
1661 "note" "warning" "error" "failure"
1662 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
1666 "Regexp for VHDL'93 standardized enumeration values.")
1669 ;; ############################################################################
1670 ;; Syntax analysis and indentation
1671 ;; ############################################################################
1673 ;; ############################################################################
1676 ;; constant regular expressions for looking at various constructs
1678 (defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
1679 "Regexp describing a VHDL symbol.
1680 We cannot use just `word' syntax class since `_' cannot be in word
1681 class. Putting underscore in word class breaks forward word movement
1682 behavior that users are familiar with.")
1684 (defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
1685 "Regexp describing a case statement header key.")
1687 (defconst vhdl-label-key
1688 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
1689 "Regexp describing a VHDL label.")
1691 ;; Macro definitions:
1693 (defmacro vhdl-point (position)
1694 ;; Returns the value of point at certain commonly referenced POSITIONs.
1695 ;; POSITION can be one of the following symbols:
1697 ;; bol -- beginning of line
1698 ;; eol -- end of line
1699 ;; bod -- beginning of defun
1700 ;; boi -- back to indentation
1701 ;; eoi -- last whitespace on line
1702 ;; ionl -- indentation of next line
1703 ;; iopl -- indentation of previous line
1704 ;; bonl -- beginning of next line
1705 ;; bopl -- beginning of previous line
1707 ;; This function does not modify point or mark.
1708 (or (and (eq 'quote (car-safe position))
1709 (null (cdr (cdr position))))
1710 (error "bad buffer position requested: %s" position))
1711 (setq position (nth 1 position))
1712 (` (let ((here (point)))
1714 ((eq position 'bol) '((beginning-of-line)))
1715 ((eq position 'eol) '((end-of-line)))
1716 ((eq position 'bod) '((save-match-data
1717 (vhdl-beginning-of-defun))))
1718 ((eq position 'boi) '((back-to-indentation)))
1719 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
1720 ((eq position 'bonl) '((forward-line 1)))
1721 ((eq position 'bopl) '((forward-line -1)))
1722 ((eq position 'iopl)
1724 (back-to-indentation)))
1725 ((eq position 'ionl)
1727 (back-to-indentation)))
1728 (t (error "unknown buffer position requested: %s" position))
1733 ;; workaround for an Emacs18 bug -- blech! Well, at least it
1734 ;; doesn't hurt for v19
1738 (defmacro vhdl-safe (&rest body)
1739 ;; safely execute BODY, return nil if an error occurred
1740 (` (condition-case nil
1744 (defmacro vhdl-add-syntax (symbol &optional relpos)
1745 ;; a simple macro to append the syntax in symbol to the syntax list.
1746 ;; try to increase performance by using this macro
1747 (` (setq vhdl-syntactic-context
1748 (cons (cons (, symbol) (, relpos)) vhdl-syntactic-context))))
1750 (defmacro vhdl-has-syntax (symbol)
1751 ;; a simple macro to return check the syntax list.
1752 ;; try to increase performance by using this macro
1753 (` (assoc (, symbol) vhdl-syntactic-context)))
1755 ;; Syntactic element offset manipulation:
1757 (defun vhdl-read-offset (langelem)
1758 ;; read new offset value for LANGELEM from minibuffer. return a
1760 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
1761 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
1763 offset input interned)
1765 (setq input (read-string prompt oldoff)
1766 offset (cond ((string-equal "+" input) '+)
1767 ((string-equal "-" input) '-)
1768 ((string-equal "++" input) '++)
1769 ((string-equal "--" input) '--)
1770 ((string-match "^-?[0-9]+$" input)
1771 (string-to-int input))
1772 ((fboundp (setq interned (intern input)))
1774 ((boundp interned) interned)
1775 ;; error, but don't signal one, keep trying
1776 ;; to read an input value
1778 (setq prompt errmsg)
1782 (defun vhdl-set-offset (symbol offset &optional add-p)
1783 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
1784 SYMBOL is the syntactic element symbol to change and OFFSET is the new
1785 offset for that syntactic element. Optional ADD says to add SYMBOL to
1786 `vhdl-offsets-alist' if it doesn't already appear there."
1789 (intern (completing-read
1790 (concat "Syntactic symbol to change"
1791 (if current-prefix-arg " or add" "")
1796 (cons (format "%s" (car langelem)) nil)))
1798 nil (not current-prefix-arg)
1799 ;; initial contents tries to be the last element
1800 ;; on the syntactic analysis list for the current
1802 (let* ((syntax (vhdl-get-syntactic-context))
1803 (len (length syntax))
1804 (ic (format "%s" (car (nth (1- len) syntax)))))
1805 (if (memq 'v19 vhdl-emacs-features)
1809 (offset (vhdl-read-offset langelem)))
1810 (list langelem offset current-prefix-arg)))
1811 ;; sanity check offset
1819 (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
1821 (let ((entry (assq symbol vhdl-offsets-alist)))
1823 (setcdr entry offset)
1825 (setq vhdl-offsets-alist (cons (cons symbol offset) vhdl-offsets-alist))
1826 (error "%s is not a valid syntactic symbol." symbol))))
1827 (vhdl-keep-region-active))
1829 (defun vhdl-set-style (style &optional local)
1830 "Set vhdl-mode variables to use one of several different indentation styles.
1831 STYLE is a string representing the desired style and optional LOCAL is
1832 a flag which, if non-nil, means to make the style variables being
1833 changed buffer local, instead of the default, which is to set the
1834 global variables. Interactively, the flag comes from the prefix
1835 argument. The styles are chosen from the `vhdl-style-alist' variable."
1836 (interactive (list (completing-read "Use which VHDL indentation style? "
1837 vhdl-style-alist nil t)
1838 current-prefix-arg))
1839 (let ((vars (cdr (assoc style vhdl-style-alist))))
1841 (error "Invalid VHDL indentation style `%s'" style))
1842 ;; set all the variables
1846 (let ((var (car varentry))
1847 (val (cdr varentry)))
1849 (make-local-variable var))
1850 ;; special case for vhdl-offsets-alist
1851 (if (not (eq var 'vhdl-offsets-alist))
1853 ;; reset vhdl-offsets-alist to the default value first
1854 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
1855 ;; now set the langelems that are different
1859 (let ((langelem (car langentry))
1860 (offset (cdr langentry)))
1861 (vhdl-set-offset langelem offset)
1866 (vhdl-keep-region-active))
1868 (defun vhdl-get-offset (langelem)
1869 ;; Get offset from LANGELEM which is a cons cell of the form:
1870 ;; (SYMBOL . RELPOS). The symbol is matched against
1871 ;; vhdl-offsets-alist and the offset found there is either returned,
1872 ;; or added to the indentation at RELPOS. If RELPOS is nil, then
1873 ;; the offset is simply returned.
1874 (let* ((symbol (car langelem))
1875 (relpos (cdr langelem))
1876 (match (assq symbol vhdl-offsets-alist))
1877 (offset (cdr-safe match)))
1878 ;; offset can be a number, a function, a variable, or one of the
1882 (if vhdl-strict-syntax-p
1883 (error "don't know how to indent a %s" symbol)
1886 ((eq offset '+) (setq offset vhdl-basic-offset))
1887 ((eq offset '-) (setq offset (- vhdl-basic-offset)))
1888 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
1889 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
1890 ((and (not (numberp offset))
1892 (setq offset (funcall offset langelem)))
1893 ((not (numberp offset))
1894 (setq offset (eval offset)))
1897 (< relpos (vhdl-point 'bol)))
1904 ;; Syntactic support functions:
1906 ;; Returns `comment' if in a comment, `string' if in a string literal,
1907 ;; or nil if not in a literal at all. Optional LIM is used as the
1908 ;; backward limit of the search. If omitted, or nil, (point-min) is
1911 (defun vhdl-in-literal (&optional lim)
1912 ;; Determine if point is in a VHDL literal.
1914 (let* ((lim (or lim (point-min)))
1915 (state (parse-partial-sexp lim (point))))
1917 ((nth 3 state) 'string)
1918 ((nth 4 state) 'comment)
1922 ;; This is the best we can do in Win-Emacs.
1923 (defun vhdl-win-il (&optional lim)
1924 ;; Determine if point is in a VHDL literal
1926 (let* ((here (point))
1929 (lim (or lim (vhdl-point 'bod))))
1931 (while (< (point) here)
1933 (and (re-search-forward "--\\|[\"']"
1935 (buffer-substring (match-beginning 0) (match-end 0))))
1940 ;; looking at the opening of a VHDL style comment
1941 ((string= "--" match)
1942 (if (<= here (progn (end-of-line) (point))) 'comment))
1943 ;; looking at the opening of a double quote string
1944 ((string= "\"" match)
1945 (if (not (save-restriction
1946 ;; this seems to be necessary since the
1947 ;; re-search-forward will not work without it
1948 (narrow-to-region (point) here)
1950 ;; this regexp matches a double quote
1951 ;; which is preceded by an even number
1952 ;; of backslashes, including zero
1953 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
1955 ;; looking at the opening of a single quote string
1956 ((string= "'" match)
1957 (if (not (save-restriction
1958 ;; see comments from above
1959 (narrow-to-region (point) here)
1961 ;; this matches a single quote which is
1962 ;; preceded by zero or two backslashes.
1963 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
1970 (and (memq 'Win-Emacs vhdl-emacs-features)
1971 (fset 'vhdl-in-literal 'vhdl-win-il))
1973 ;; Skipping of "syntactic whitespace". Syntactic whitespace is
1974 ;; defined as lexical whitespace or comments. Search no farther back
1975 ;; or forward than optional LIM. If LIM is omitted, (point-min) is
1976 ;; used for backward skipping, (point-max) is used for forward
1979 (defun vhdl-forward-syntactic-ws (&optional lim)
1980 ;; Forward skip of syntactic whitespace.
1982 (let* ((lim (or lim (point-max)))
1984 (hugenum (point-max)))
1985 (narrow-to-region lim (point))
1986 (while (/= here (point))
1988 (forward-comment hugenum))
1991 ;; This is the best we can do in Win-Emacs.
1992 (defun vhdl-win-fsws (&optional lim)
1993 ;; Forward skip syntactic whitespace for Win-Emacs.
1994 (let ((lim (or lim (point-max)))
1997 (skip-chars-forward " \t\n\r\f" lim)
2000 ((looking-at "--") (end-of-line))
2001 ;; none of the above
2005 (and (memq 'Win-Emacs vhdl-emacs-features)
2006 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
2008 (defun vhdl-backward-syntactic-ws (&optional lim)
2009 ;; Backward skip over syntactic whitespace.
2011 (let* ((lim (or lim (point-min)))
2013 (hugenum (- (point-max))))
2016 (narrow-to-region lim (point))
2017 (while (/= here (point))
2019 (forward-comment hugenum)
2023 ;; This is the best we can do in Win-Emacs.
2024 (defun vhdl-win-bsws (&optional lim)
2025 ;; Backward skip syntactic whitespace for Win-Emacs.
2026 (let ((lim (or lim (vhdl-point 'bod)))
2029 (skip-chars-backward " \t\n\r\f" lim)
2032 ((eq (vhdl-in-literal lim) 'comment)
2033 (skip-chars-backward "^-" lim)
2034 (skip-chars-backward "-" lim)
2035 (while (not (or (and (= (following-char) ?-)
2036 (= (char-after (1+ (point))) ?-))
2038 (skip-chars-backward "^-" lim)
2039 (skip-chars-backward "-" lim)))
2040 ;; none of the above
2044 (and (memq 'Win-Emacs vhdl-emacs-features)
2045 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
2047 ;; Functions to help finding the correct indentation column:
2049 (defun vhdl-first-word (point)
2050 "If the keyword at POINT is at boi, then return (current-column) at
2051 that point, else nil."
2053 (and (goto-char point)
2054 (eq (point) (vhdl-point 'boi))
2057 (defun vhdl-last-word (point)
2058 "If the keyword at POINT is at eoi, then return (current-column) at
2059 that point, else nil."
2061 (and (goto-char point)
2062 (save-excursion (or (eq (progn (forward-sexp) (point))
2064 (looking-at "\\s-*\\(--\\)?")))
2067 ;; Core syntactic evaluation functions:
2069 (defconst vhdl-libunit-re
2070 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
2072 (defun vhdl-libunit-p ()
2076 (skip-chars-forward " \t\n")
2077 (not (looking-at "is\\b[^_]")))
2080 (and (not (looking-at "use\\b[^_]"))
2083 (vhdl-forward-syntactic-ws)
2084 (/= (following-char) ?:))))
2087 (defconst vhdl-defun-re
2088 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedure\\|function\\)\\b[^_]")
2090 (defun vhdl-defun-p ()
2092 (if (looking-at "block\\|process")
2093 ;; "block", "process":
2096 (not (looking-at "end\\s-+\\w")))
2097 ;; "architecture", "configuration", "entity",
2098 ;; "package", "procedure", "function":
2101 (defun vhdl-corresponding-defun ()
2102 "If the word at the current position corresponds to a \"defun\"
2103 keyword, then return a string that can be used to find the
2104 corresponding \"begin\" keyword, else return nil."
2106 (and (looking-at vhdl-defun-re)
2108 (if (looking-at "block\\|process")
2109 ;; "block", "process":
2110 (buffer-substring (match-beginning 0) (match-end 0))
2111 ;; "architecture", "configuration", "entity", "package",
2112 ;; "procedure", "function":
2115 (defconst vhdl-begin-fwd-re
2116 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
2117 "A regular expression for searching forward that matches all known
2118 \"begin\" keywords.")
2120 (defconst vhdl-begin-bwd-re
2121 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b[^_]"
2122 "A regular expression for searching backward that matches all known
2123 \"begin\" keywords.")
2125 (defun vhdl-begin-p (&optional lim)
2126 "Return t if we are looking at a real \"begin\" keyword.
2127 Assumes that the caller will make sure that we are looking at
2128 vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
2129 the middle of an identifier that just happens to contain a \"begin\"
2132 ;; "[architecture|case|configuration|entity|package|
2133 ;; procedure|function] ... is":
2134 ((and (looking-at "i")
2136 ;; Skip backward over first sexp (needed to skip over a
2137 ;; procedure interface list, and is harmless in other
2138 ;; situations). Note that we need "return" in the
2139 ;; following search list so that we don't run into
2140 ;; semicolons in the function interface list.
2143 (while (and (not foundp)
2145 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|block\\)\\b[^_]"
2147 (if (or (= (preceding-char) ?_)
2148 (vhdl-in-literal lim))
2151 (and (/= (following-char) ?\;)
2152 (not (looking-at "is\\|begin\\|process\\|block")))))
2155 ((looking-at "be\\|t")
2158 ((and (looking-at "e")
2159 ;; make sure that the "else" isn't inside a
2160 ;; conditional signal assignment.
2162 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
2163 (or (eq (following-char) ?\;)
2166 ;; "block", "generate", "loop", "process",
2167 ;; "units", "record":
2168 ((and (looking-at "bl\\|[glpur]")
2171 (not (looking-at "end\\s-+\\w"))))
2174 ((and (looking-at "c")
2177 (not (looking-at "end\\s-+\\w")))
2178 ;; look out for the dreaded entity class in an attribute
2180 (vhdl-backward-syntactic-ws lim)
2181 (/= (preceding-char) ?:)))
2183 ;; "for" (inside configuration declaration):
2184 ((and (looking-at "f")
2187 (not (looking-at "end\\s-+\\w")))
2188 (vhdl-has-syntax 'configuration))
2192 (defun vhdl-corresponding-mid (&optional lim)
2194 ((looking-at "is\\|block\\|process")
2196 ((looking-at "then")
2201 (defun vhdl-corresponding-end (&optional lim)
2202 "If the word at the current position corresponds to a \"begin\"
2203 keyword, then return a vector containing enough information to find
2204 the corresponding \"end\" keyword, else return nil. The keyword to
2205 search forward for is aref 0. The column in which the keyword must
2206 appear is aref 1 or nil if any column is suitable.
2207 Assumes that the caller will make sure that we are not in the middle
2208 of an identifier that just happens to contain a \"begin\" keyword."
2210 (and (looking-at vhdl-begin-fwd-re)
2211 (/= (preceding-char) ?_)
2212 (not (vhdl-in-literal lim))
2215 ;; "is", "generate", "loop":
2216 ((looking-at "[igl]")
2218 (and (vhdl-last-word (point))
2219 (or (vhdl-first-word (point))
2221 (vhdl-beginning-of-statement-1 lim)
2222 (vhdl-backward-skip-label lim)
2223 (vhdl-first-word (point)))))))
2224 ;; "begin", "else", "for":
2225 ((looking-at "be\\|[ef]")
2227 (and (vhdl-last-word (point))
2228 (or (vhdl-first-word (point))
2230 (vhdl-beginning-of-statement-1 lim)
2231 (vhdl-backward-skip-label lim)
2232 (vhdl-first-word (point)))))))
2233 ;; "component", "units", "record":
2234 ((looking-at "[cur]")
2235 ;; The first end found will close the block
2237 ;; "block", "process":
2238 ((looking-at "bl\\|p")
2240 (or (vhdl-first-word (point))
2242 (vhdl-beginning-of-statement-1 lim)
2243 (vhdl-backward-skip-label lim)
2244 (vhdl-first-word (point))))))
2247 (vector "elsif\\|else\\|end\\s-+if"
2248 (and (vhdl-last-word (point))
2249 (or (vhdl-first-word (point))
2251 (vhdl-beginning-of-statement-1 lim)
2252 (vhdl-backward-skip-label lim)
2253 (vhdl-first-word (point)))))))
2256 (defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
2258 (defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
2260 (defun vhdl-end-p (&optional lim)
2261 "Return t if we are looking at a real \"end\" keyword.
2262 Assumes that the caller will make sure that we are looking at
2263 vhdl-end-fwd-re, and are not inside a literal, and that we are not in
2264 the middle of an identifier that just happens to contain an \"end\"
2266 (or (not (looking-at "else"))
2267 ;; make sure that the "else" isn't inside a conditional signal
2270 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
2271 (or (eq (following-char) ?\;)
2272 (eq (point) lim)))))
2274 (defun vhdl-corresponding-begin (&optional lim)
2275 "If the word at the current position corresponds to an \"end\"
2276 keyword, then return a vector containing enough information to find
2277 the corresponding \"begin\" keyword, else return nil. The keyword to
2278 search backward for is aref 0. The column in which the keyword must
2279 appear is aref 1 or nil if any column is suitable. The supplementary
2280 keyword to search forward for is aref 2 or nil if this is not
2281 required. If aref 3 is t, then the \"begin\" keyword may be found in
2282 the middle of a statement.
2283 Assumes that the caller will make sure that we are not in the middle
2284 of an identifier that just happens to contain an \"end\" keyword."
2287 (if (and (looking-at vhdl-end-fwd-re)
2288 (not (vhdl-in-literal lim))
2290 (if (looking-at "el")
2292 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
2296 (skip-chars-forward " \t\n")
2299 ((looking-at "if\\b[^_]")
2300 (vector "else\\|elsif\\|if"
2301 (vhdl-first-word pos)
2304 ((looking-at "component\\b[^_]")
2305 (vector (buffer-substring (match-beginning 1)
2307 (vhdl-first-word pos)
2309 ;; "end units", "end record":
2310 ((looking-at "\\(units\\|record\\)\\b[^_]")
2311 (vector (buffer-substring (match-beginning 1)
2313 (vhdl-first-word pos)
2315 ;; "end block", "end process":
2316 ((looking-at "\\(block\\|process\\)\\b[^_]")
2317 (vector "begin" (vhdl-first-word pos) nil nil))
2319 ((looking-at "case\\b[^_]")
2320 (vector "case" (vhdl-first-word pos) "is" nil))
2322 ((looking-at "generate\\b[^_]")
2323 (vector "generate\\|for\\|if"
2324 (vhdl-first-word pos)
2327 ((looking-at "loop\\b[^_]")
2328 (vector "loop\\|while\\|for"
2329 (vhdl-first-word pos)
2331 ;; "end for" (inside configuration declaration):
2332 ((looking-at "for\\b[^_]")
2333 (vector "for" (vhdl-first-word pos) nil nil))
2336 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
2337 (vhdl-first-word pos)
2338 ;; return an alist of (statement . keyword) mappings
2340 ;; "begin ... end [id]":
2342 ;; "architecture ... is ... begin ... end [id]":
2343 ("architecture" . "is")
2344 ;; "configuration ... is ... end [id]":
2345 ("configuration" . "is")
2346 ;; "entity ... is ... end [id]":
2348 ;; "package ... is ... end [id]":
2350 ;; "procedure ... is ... begin ... end [id]":
2351 ("procedure" . "is")
2352 ;; "function ... is ... begin ... end [id]":
2359 (defconst vhdl-leader-re
2360 "\\b\\(block\\|component\\|process\\|for\\)\\b[^_]")
2362 (defun vhdl-end-of-leader ()
2364 (cond ((looking-at "block\\|process")
2367 (skip-chars-forward " \t\n")
2368 (= (following-char) ?\())
2372 ((looking-at "component")
2377 (skip-chars-forward " \t\n")
2378 (while (looking-at "[,:(]")
2380 (skip-chars-forward " \t\n"))
2385 (defconst vhdl-trailer-re
2386 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
2388 (defconst vhdl-statement-fwd-re
2389 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
2390 "A regular expression for searching forward that matches all known
2391 \"statement\" keywords.")
2393 (defconst vhdl-statement-bwd-re
2394 "\\b\\(if\\|for\\|while\\)\\b[^_]"
2395 "A regular expression for searching backward that matches all known
2396 \"statement\" keywords.")
2398 (defun vhdl-statement-p (&optional lim)
2399 "Return t if we are looking at a real \"statement\" keyword.
2400 Assumes that the caller will make sure that we are looking at
2401 vhdl-statement-fwd-re, and are not inside a literal, and that we are not in
2402 the middle of an identifier that just happens to contain a \"statement\"
2405 ;; "for" ... "generate":
2406 ((and (looking-at "f")
2407 ;; Make sure it's the start of a parameter specification.
2410 (skip-chars-forward " \t\n")
2411 (looking-at "in\\b[^_]"))
2412 ;; Make sure it's not an "end for".
2415 (not (looking-at "end\\s-+\\w"))))
2417 ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
2418 ((and (looking-at "i")
2419 ;; Make sure it's not an "end if".
2422 (not (looking-at "end\\s-+\\w"))))
2424 ;; "while" ... "loop":
2429 (defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
2430 "Regexp describing a case statement alternative key.")
2432 (defun vhdl-case-alternative-p (&optional lim)
2433 "Return t if we are looking at a real case alternative.
2434 Assumes that the caller will make sure that we are looking at
2435 vhdl-case-alternative-re, and are not inside a literal, and that
2436 we are not in the middle of an identifier that just happens to
2437 contain a \"when\" keyword."
2440 (while (and (not foundp)
2441 (re-search-backward ";\\|<=" lim 'move))
2442 (if (or (= (preceding-char) ?_)
2443 (vhdl-in-literal lim))
2446 (or (eq (following-char) ?\;)
2450 ;; Core syntactic movement functions:
2452 (defconst vhdl-b-t-b-re
2453 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
2455 (defun vhdl-backward-to-block (&optional lim)
2456 "Move backward to the previous \"begin\" or \"end\" keyword."
2458 (while (and (not foundp)
2459 (re-search-backward vhdl-b-t-b-re lim 'move))
2460 (if (or (= (preceding-char) ?_)
2461 (vhdl-in-literal lim))
2465 ((and (looking-at vhdl-begin-fwd-re)
2466 (/= (preceding-char) ?_)
2468 (setq foundp 'begin))
2470 ((and (looking-at vhdl-end-fwd-re)
2471 (/= (preceding-char) ?_)
2479 (defun vhdl-forward-sexp (&optional count lim)
2480 "Move forward across one balanced expression (sexp).
2481 With COUNT, do it that many times."
2483 (let ((count (or count 1))
2484 (case-fold-search t)
2489 (skip-chars-forward " \t\n")
2490 ;; Check for an unbalanced "end" keyword
2491 (if (and (looking-at vhdl-end-fwd-re)
2492 (/= (preceding-char) ?_)
2493 (not (vhdl-in-literal lim))
2495 (not (looking-at "else")))
2497 "Containing expression ends prematurely in vhdl-forward-sexp"))
2498 ;; If the current keyword is a "begin" keyword, then find the
2499 ;; corresponding "end" keyword.
2500 (if (setq end-vec (vhdl-corresponding-end lim))
2502 ;; end-re is the statement keyword to search for
2504 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
2505 ;; column is either the statement keyword target column
2507 (column (aref end-vec 1))
2508 (eol (vhdl-point 'eol))
2509 foundp literal placeholder)
2510 ;; Look for the statement keyword.
2511 (while (and (not foundp)
2512 (re-search-forward end-re nil t)
2513 (setq placeholder (match-end 1))
2514 (goto-char (match-beginning 0)))
2515 ;; If we are in a literal, or not in the right target
2516 ;; column and not on the same line as the begin, then
2519 (/= (current-indentation) column)
2521 (= (preceding-char) ?_)
2522 (setq literal (vhdl-in-literal lim)))
2523 (if (eq literal 'comment)
2526 ;; An "else" keyword corresponds to both the opening brace
2527 ;; of the following sexp and the closing brace of the
2529 (if (not (looking-at "else"))
2530 (goto-char placeholder))
2534 (error "Unbalanced keywords in vhdl-forward-sexp"))
2536 ;; If the current keyword is not a "begin" keyword, then just
2537 ;; perform the normal forward-sexp.
2540 (setq count (1- count))
2542 (setq target (point)))
2546 (defun vhdl-backward-sexp (&optional count lim)
2547 "Move backward across one balanced expression (sexp).
2548 With COUNT, do it that many times. LIM bounds any required backward
2551 (let ((count (or count 1))
2552 (case-fold-search t)
2556 ;; Perform the normal backward-sexp, unless we are looking at
2557 ;; "else" - an "else" keyword corresponds to both the opening brace
2558 ;; of the following sexp and the closing brace of the previous sexp.
2559 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
2560 (/= (preceding-char) ?_)
2561 (not (vhdl-in-literal lim)))
2564 (if (and (looking-at vhdl-begin-fwd-re)
2565 (/= (preceding-char) ?_)
2566 (not (vhdl-in-literal lim))
2568 (error "Containing expression ends prematurely in vhdl-backward-sexp")))
2569 ;; If the current keyword is an "end" keyword, then find the
2570 ;; corresponding "begin" keyword.
2571 (if (and (setq begin-vec (vhdl-corresponding-begin lim))
2572 (/= (preceding-char) ?_))
2574 ;; begin-re is the statement keyword to search for
2576 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
2577 ;; column is either the statement keyword target column
2579 (column (aref begin-vec 1))
2580 ;; internal-p controls where the statement keyword can
2582 (internal-p (aref begin-vec 3))
2583 (last-backward (point)) last-forward
2584 foundp literal keyword)
2585 ;; Look for the statement keyword.
2586 (while (and (not foundp)
2587 (re-search-backward begin-re lim t)
2589 (buffer-substring (match-beginning 1)
2591 ;; If we are in a literal or in the wrong column,
2594 (and (/= (current-indentation) column)
2595 ;; possibly accept current-column as
2596 ;; well as current-indentation.
2597 (or (not internal-p)
2598 (/= (current-column) column))))
2599 (= (preceding-char) ?_)
2600 (vhdl-in-literal lim))
2602 ;; If there is a supplementary keyword, then
2603 ;; search forward for it.
2604 (if (and (setq begin-re (aref begin-vec 2))
2605 (or (not (listp begin-re))
2606 ;; If begin-re is an alist, then find the
2607 ;; element corresponding to the actual
2608 ;; keyword that we found.
2611 (assoc keyword begin-re))
2613 (setq begin-re (cdr begin-re))))))
2616 (concat "\\b\\(" begin-re "\\)\\b[^_]"))
2618 (setq last-forward (point))
2619 ;; Look for the supplementary keyword
2620 ;; (bounded by the backward search start
2622 (while (and (not foundp)
2623 (re-search-forward begin-re
2625 (goto-char (match-beginning 1)))
2626 ;; If we are in a literal, then try again.
2627 (if (or (= (preceding-char) ?_)
2629 (vhdl-in-literal last-forward)))
2630 (if (eq literal 'comment)
2632 (min (vhdl-point 'eol) last-backward))
2634 ;; We have found the supplementary keyword.
2635 ;; Save the position of the keyword in foundp.
2636 (setq foundp (point)))
2639 ;; If the supplementary keyword was found, then
2640 ;; move point to the supplementary keyword.
2642 ;; If there was no supplementary keyword, then
2643 ;; point is already at the statement keyword.
2645 ) ; end of the search for the statement keyword
2647 (error "Unbalanced keywords in vhdl-backward-sexp"))
2649 (setq count (1- count))
2651 (setq target (point)))
2655 (defun vhdl-backward-up-list (&optional count limit)
2656 "Move backward out of one level of blocks.
2657 With argument, do this that many times."
2659 (let ((count (or count 1))
2663 (if (looking-at vhdl-defun-re)
2664 (error "Unbalanced blocks"))
2665 (vhdl-backward-to-block limit)
2666 (setq count (1- count)))
2667 (setq target (point)))
2668 (goto-char target)))
2670 (defun vhdl-end-of-defun (&optional count)
2671 "Move forward to the end of a VHDL defun."
2673 (let ((case-fold-search t))
2674 (vhdl-beginning-of-defun)
2675 (if (not (looking-at "block\\|process"))
2676 (re-search-forward "\\bis\\b"))
2677 (vhdl-forward-sexp)))
2679 (defun vhdl-mark-defun ()
2680 "Put mark at end of this \"defun\", point at beginning."
2682 (let ((case-fold-search t))
2684 (vhdl-beginning-of-defun)
2686 (if (not (looking-at "block\\|process"))
2687 (re-search-forward "\\bis\\b"))
2689 (exchange-point-and-mark)))
2691 (defun vhdl-beginning-of-libunit ()
2692 "Move backward to the beginning of a VHDL library unit.
2693 Returns the location of the corresponding begin keyword, unless search
2694 stops due to beginning or end of buffer."
2695 ;; Note that if point is between the "libunit" keyword and the
2696 ;; corresponding "begin" keyword, then that libunit will not be
2697 ;; recognised, and the search will continue backwards. If point is
2698 ;; at the "begin" keyword, then the defun will be recognised. The
2699 ;; returned point is at the first character of the "libunit" keyword.
2700 (let ((last-forward (point))
2702 ;; Just in case we are actually sitting on the "begin"
2703 ;; keyword, allow for the keyword and an extra character,
2704 ;; as this will be used when looking forward for the
2706 (save-excursion (forward-word 1) (1+ (point))))
2707 foundp literal placeholder)
2708 ;; Find the "libunit" keyword.
2709 (while (and (not foundp)
2710 (re-search-backward vhdl-libunit-re nil 'move))
2711 ;; If we are in a literal, or not at a real libunit, then try again.
2712 (if (or (= (preceding-char) ?_)
2713 (vhdl-in-literal (point-min))
2714 (not (vhdl-libunit-p)))
2716 ;; Find the corresponding "begin" keyword.
2717 (setq last-forward (point))
2718 (while (and (not foundp)
2719 (re-search-forward "\\bis\\b[^_]" last-backward t)
2720 (setq placeholder (match-beginning 0)))
2721 (if (or (= (preceding-char) ?_)
2722 (setq literal (vhdl-in-literal last-forward)))
2723 ;; It wasn't a real keyword, so keep searching.
2724 (if (eq literal 'comment)
2726 (min (vhdl-point 'eol) last-backward))
2728 ;; We have found the begin keyword, loop will exit.
2729 (setq foundp placeholder)))
2730 ;; Go back to the libunit keyword
2731 (goto-char last-forward)))
2734 (defun vhdl-beginning-of-defun (&optional count)
2735 "Move backward to the beginning of a VHDL defun.
2736 With argument, do it that many times.
2737 Returns the location of the corresponding begin keyword, unless search
2738 stops due to beginning or end of buffer."
2739 ;; Note that if point is between the "defun" keyword and the
2740 ;; corresponding "begin" keyword, then that defun will not be
2741 ;; recognised, and the search will continue backwards. If point is
2742 ;; at the "begin" keyword, then the defun will be recognised. The
2743 ;; returned point is at the first character of the "defun" keyword.
2745 (let ((count (or count 1))
2746 (case-fold-search t)
2747 (last-forward (point))
2751 (goto-char last-forward)
2752 (let ((last-backward
2753 ;; Just in case we are actually sitting on the "begin"
2754 ;; keyword, allow for the keyword and an extra character,
2755 ;; as this will be used when looking forward for the
2757 (save-excursion (forward-word 1) (1+ (point))))
2758 begin-string literal)
2759 (while (and (not foundp)
2760 (re-search-backward vhdl-defun-re nil 'move))
2761 ;; If we are in a literal, then try again.
2762 (if (or (= (preceding-char) ?_)
2763 (vhdl-in-literal (point-min)))
2765 (if (setq begin-string (vhdl-corresponding-defun))
2766 ;; This is a real defun keyword.
2767 ;; Find the corresponding "begin" keyword.
2768 ;; Look for the begin keyword.
2770 ;; Save the search start point.
2771 (setq last-forward (point))
2772 (while (and (not foundp)
2773 (search-forward begin-string last-backward t))
2774 (if (or (= (preceding-char) ?_)
2776 (setq literal (vhdl-in-literal last-forward))))
2777 ;; It wasn't a real keyword, so keep searching.
2778 (if (eq literal 'comment)
2780 (min (vhdl-point 'eol) last-backward))
2782 ;; We have found the begin keyword, loop will exit.
2783 (setq foundp (match-beginning 0)))
2785 ;; Go back to the defun keyword
2786 (goto-char last-forward)) ; end search for begin keyword
2788 ) ; end of the search for the defun keyword
2790 (setq count (1- count))
2792 (vhdl-keep-region-active)
2795 (defun vhdl-beginning-of-statement (&optional count lim)
2796 "Go to the beginning of the innermost VHDL statement.
2797 With prefix arg, go back N - 1 statements. If already at the
2798 beginning of a statement then go to the beginning of the preceding
2799 one. If within a string or comment, or next to a comment (only
2800 whitespace between), move by sentences instead of statements.
2802 When called from a program, this function takes 2 optional args: the
2803 prefix arg, and a buffer position limit which is the farthest back to
2806 (let ((count (or count 1))
2807 (case-fold-search t)
2808 (lim (or lim (point-min)))
2813 (setq state (parse-partial-sexp (point) here nil nil)))
2814 (if (and (interactive-p)
2817 (looking-at (concat "[ \t]*" comment-start-skip))))
2818 (forward-sentence (- count))
2820 (vhdl-beginning-of-statement-1 lim)
2821 (setq count (1- count))))
2822 ;; its possible we've been left up-buf of lim
2823 (goto-char (max (point) lim))
2825 (vhdl-keep-region-active))
2827 (defconst vhdl-e-o-s-re
2828 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
2830 (defun vhdl-end-of-statement ()
2831 "Very simple implementation."
2833 (re-search-forward vhdl-e-o-s-re))
2835 (defconst vhdl-b-o-s-re
2836 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
2837 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
2839 (defun vhdl-beginning-of-statement-1 (&optional lim)
2840 ;; move to the start of the current statement, or the previous
2841 ;; statement if already at the beginning of one.
2842 (let ((lim (or lim (point-min)))
2846 ;; go backwards one balanced expression, but be careful of
2847 ;; unbalanced paren being reached
2848 (if (not (vhdl-safe (progn (backward-sexp) t)))
2850 (backward-up-list 1)
2852 (vhdl-forward-syntactic-ws here)
2854 (while (and (not donep)
2856 ;; look backwards for a statement boundary
2857 (re-search-backward vhdl-b-o-s-re lim 'move))
2858 (if (or (= (preceding-char) ?_)
2859 (vhdl-in-literal lim))
2862 ;; If we are looking at an open paren, then stop after it
2863 ((eq (following-char) ?\()
2865 (vhdl-forward-syntactic-ws here)
2867 ;; If we are looking at a close paren, then skip it
2868 ((eq (following-char) ?\))
2873 (progn (goto-char pos)
2874 (vhdl-forward-syntactic-ws here)
2876 ;; If we are looking at a semicolon, then stop
2877 ((eq (following-char) ?\;)
2880 (vhdl-forward-syntactic-ws here)
2882 ;; If we are looking at a "begin", then stop
2883 ((and (looking-at vhdl-begin-fwd-re)
2884 (/= (preceding-char) ?_)
2886 ;; If it's a leader "begin", then find the
2888 (if (looking-at vhdl-leader-re)
2890 ;; set a default stop point at the begin
2892 ;; is the start point inside the leader area ?
2893 (goto-char (vhdl-end-of-leader))
2894 (vhdl-forward-syntactic-ws here)
2895 (if (< (point) here)
2896 ;; start point was not inside leader area
2897 ;; set stop point at word after leader
2898 (setq pos (point))))
2900 (vhdl-forward-syntactic-ws here)
2904 ;; If we are looking at a "statement", then stop
2905 ((and (looking-at vhdl-statement-fwd-re)
2906 (/= (preceding-char) ?_)
2907 (vhdl-statement-p nil))
2909 ;; If we are looking at a case alternative key, then stop
2910 ((and (looking-at vhdl-case-alternative-re)
2911 (vhdl-case-alternative-p lim))
2913 ;; set a default stop point at the when
2915 ;; is the start point inside the case alternative key ?
2916 (looking-at vhdl-case-alternative-re)
2917 (goto-char (match-end 0))
2918 (vhdl-forward-syntactic-ws here)
2919 (if (< (point) here)
2920 ;; start point was not inside the case alternative key
2921 ;; set stop point at word after case alternative keyleader
2922 (setq pos (point))))
2925 ;; Bogus find, continue
2930 ;; Defuns for calculating the current syntactic state:
2932 (defun vhdl-get-library-unit (bod placeholder)
2933 ;; If there is an enclosing library unit at bod, with it's \"begin\"
2934 ;; keyword at placeholder, then return the library unit type.
2935 (let ((here (vhdl-point 'bol)))
2937 (goto-char placeholder)
2938 (vhdl-safe (vhdl-forward-sexp 1 bod))
2943 ((looking-at "e") 'entity)
2944 ((looking-at "a") 'architecture)
2945 ((looking-at "c") 'configuration)
2950 (vhdl-forward-syntactic-ws here)
2951 (if (looking-at "body\\b[^_]")
2952 'package-body 'package))))))
2955 (defun vhdl-get-block-state (&optional lim)
2956 ;; Finds and records all the closest opens.
2957 ;; lim is the furthest back we need to search (it should be the
2958 ;; previous libunit keyword).
2959 (let ((here (point))
2960 (lim (or lim (point-min)))
2961 keyword sexp-start sexp-mid sexp-end
2962 preceding-sexp containing-sexp
2963 containing-begin containing-mid containing-paren)
2965 ;; Find the containing-paren, and use that as the limit
2966 (if (setq containing-paren
2968 (narrow-to-region lim (point))
2969 (vhdl-safe (scan-lists (point) -1 1))))
2970 (setq lim containing-paren))
2971 ;; Look backwards for "begin" and "end" keywords.
2972 (while (and (> (point) lim)
2973 (not containing-sexp))
2974 (setq keyword (vhdl-backward-to-block lim))
2976 ((eq keyword 'begin)
2977 ;; Found a "begin" keyword
2978 (setq sexp-start (point))
2979 (setq sexp-mid (vhdl-corresponding-mid lim))
2980 (setq sexp-end (vhdl-safe
2982 (vhdl-forward-sexp 1 lim) (point))))
2983 (if (and sexp-end (<= sexp-end here))
2984 ;; we want to record this sexp, but we only want to
2985 ;; record the last-most of any of them before here
2987 (setq preceding-sexp sexp-start))
2988 ;; we're contained in this sexp so put sexp-start on
2990 (setq containing-sexp sexp-start)
2991 (setq containing-mid sexp-mid)
2992 (setq containing-begin t)))
2994 ;; Found an "end" keyword
2996 (setq sexp-end (point))
2999 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
3000 (progn (backward-sexp) (point))))
3001 ;; we want to record this sexp, but we only want to
3002 ;; record the last-most of any of them before here
3004 (setq preceding-sexp sexp-start)))
3006 ;; Check if the containing-paren should be the containing-sexp
3007 (if (and containing-paren
3008 (or (null containing-sexp)
3009 (< containing-sexp containing-paren)))
3010 (setq containing-sexp containing-paren
3012 containing-begin nil
3013 containing-mid nil))
3014 (vector containing-sexp preceding-sexp containing-begin containing-mid)
3018 (defconst vhdl-s-c-a-re
3019 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
3021 (defun vhdl-skip-case-alternative (&optional lim)
3022 ;; skip forward over case/when bodies, with optional maximal
3023 ;; limit. if no next case alternative is found, nil is returned and point
3025 (let ((lim (or lim (point-max)))
3028 (while (and (< (point) lim)
3030 (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
3032 (not (vhdl-in-literal)))
3033 (/= (match-beginning 0) here))
3035 (goto-char (match-beginning 0))
3037 ((and (looking-at "case")
3038 (re-search-forward "\\bis[^_]" lim t))
3040 (vhdl-forward-sexp))
3048 (defun vhdl-backward-skip-label (&optional lim)
3049 ;; skip backward over a label, with optional maximal
3050 ;; limit. if label is not found, nil is returned and point
3052 (let ((lim (or lim (point-min)))
3055 (vhdl-backward-syntactic-ws lim)
3056 (and (eq (preceding-char) ?:)
3059 (setq placeholder (point))
3060 (looking-at vhdl-label-key))))
3061 (goto-char placeholder))
3064 (defun vhdl-forward-skip-label (&optional lim)
3065 ;; skip forward over a label, with optional maximal
3066 ;; limit. if label is not found, nil is returned and point
3068 (let ((lim (or lim (point-max))))
3069 (if (looking-at vhdl-label-key)
3071 (goto-char (match-end 0))
3072 (vhdl-forward-syntactic-ws lim)))
3075 (defun vhdl-get-syntactic-context ()
3076 ;; guess the syntactic description of the current line of VHDL code.
3080 (let* ((indent-point (point))
3081 (case-fold-search t)
3082 vec literal containing-sexp preceding-sexp
3083 containing-begin containing-mid containing-leader
3084 char-before-ip char-after-ip begin-after-ip end-after-ip
3085 placeholder lim library-unit
3088 ;; Reset the syntactic context
3089 (setq vhdl-syntactic-context nil)
3092 ;; Move to the start of the previous library unit, and
3093 ;; record the position of the "begin" keyword.
3094 (setq placeholder (vhdl-beginning-of-libunit))
3095 ;; The position of the "libunit" keyword gives us a gross
3100 ;; If there is a previous library unit, and we are enclosed by
3101 ;; it, then set the syntax accordingly.
3103 (setq library-unit (vhdl-get-library-unit lim placeholder))
3104 (vhdl-add-syntax library-unit lim))
3106 ;; Find the surrounding state.
3107 (if (setq vec (vhdl-get-block-state lim))
3109 (setq containing-sexp (aref vec 0))
3110 (setq preceding-sexp (aref vec 1))
3111 (setq containing-begin (aref vec 2))
3112 (setq containing-mid (aref vec 3))
3115 ;; set the limit on the farthest back we need to search
3116 (setq lim (if containing-sexp
3118 (goto-char containing-sexp)
3119 ;; set containing-leader if required
3120 (if (looking-at vhdl-leader-re)
3121 (setq containing-leader (vhdl-end-of-leader)))
3125 ;; cache char before and after indent point, and move point to
3126 ;; the most likely position to perform the majority of tests
3127 (goto-char indent-point)
3128 (skip-chars-forward " \t")
3129 (setq literal (vhdl-in-literal lim))
3130 (setq char-after-ip (following-char))
3131 (setq begin-after-ip (and
3133 (looking-at vhdl-begin-fwd-re)
3135 (setq end-after-ip (and
3137 (looking-at vhdl-end-fwd-re)
3139 (vhdl-backward-syntactic-ws lim)
3140 (setq char-before-ip (preceding-char))
3141 (goto-char indent-point)
3142 (skip-chars-forward " \t")
3144 ;; now figure out syntactic qualities of the current line
3146 ;; CASE 1: in a string or comment.
3147 ((memq literal '(string comment))
3148 (vhdl-add-syntax literal (vhdl-point 'bopl)))
3149 ;; CASE 2: Line is at top level.
3150 ((null containing-sexp)
3151 ;; Find the point to which indentation will be relative
3153 (if (null preceding-sexp)
3155 ;; no preceding-sexp -> use the preceding statement
3156 (vhdl-beginning-of-statement-1 lim)
3158 ;; if there is a preceding-sexp then indent relative to it
3159 (goto-char preceding-sexp)
3160 ;; if not at boi, then the block-opening keyword is
3161 ;; probably following a label, so we need a different
3163 (if (/= (point) (vhdl-point 'boi))
3165 (vhdl-beginning-of-statement-1 lim)))
3166 ;; v-b-o-s could have left us at point-min
3169 (vhdl-forward-syntactic-ws indent-point))
3170 (setq placeholder (point)))
3172 ;; CASE 2A : we are looking at a block-open
3174 (vhdl-add-syntax 'block-open placeholder))
3175 ;; CASE 2B: we are looking at a block-close
3177 (vhdl-add-syntax 'block-close placeholder))
3178 ;; CASE 2C: we are looking at a top-level statement
3180 (vhdl-backward-syntactic-ws lim)
3182 (= (preceding-char) ?\;)))
3183 (vhdl-add-syntax 'statement placeholder))
3184 ;; CASE 2D: we are looking at a top-level statement-cont
3186 (vhdl-beginning-of-statement-1 lim)
3187 ;; v-b-o-s could have left us at point-min
3190 (vhdl-forward-syntactic-ws indent-point))
3191 (vhdl-add-syntax 'statement-cont (point)))
3193 ;; CASE 3: line is inside parentheses. Most likely we are
3194 ;; either in a subprogram argument (interface) list, or a
3195 ;; continued expression containing parentheses.
3196 ((null containing-begin)
3197 (vhdl-backward-syntactic-ws containing-sexp)
3199 ;; CASE 3A: we are looking at the arglist closing paren
3200 ((eq char-after-ip ?\))
3201 (goto-char containing-sexp)
3202 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
3203 ;; CASE 3B: we are looking at the first argument in an empty
3205 ((eq char-before-ip ?\()
3206 (goto-char containing-sexp)
3207 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
3208 ;; CASE 3C: we are looking at an arglist continuation line,
3209 ;; but the preceding argument is on the same line as the
3210 ;; opening paren. This case includes multi-line
3211 ;; expression paren groupings.
3212 ((and (save-excursion
3213 (goto-char (1+ containing-sexp))
3214 (skip-chars-forward " \t")
3216 (not (looking-at "--")))
3218 (vhdl-beginning-of-statement-1 containing-sexp)
3219 (skip-chars-backward " \t(")
3220 (<= (point) containing-sexp)))
3221 (goto-char containing-sexp)
3222 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
3223 ;; CASE 3D: we are looking at just a normal arglist
3224 ;; continuation line
3225 (t (vhdl-beginning-of-statement-1 containing-sexp)
3226 (vhdl-forward-syntactic-ws indent-point)
3227 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
3229 ;; CASE 4: A block mid open
3230 ((and begin-after-ip
3231 (looking-at containing-mid))
3232 (goto-char containing-sexp)
3233 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3234 (if (looking-at vhdl-trailer-re)
3236 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3237 (vhdl-backward-skip-label (vhdl-point 'boi))
3238 (vhdl-add-syntax 'block-open (point)))
3239 ;; CASE 5: block close brace
3241 (goto-char containing-sexp)
3242 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3243 (if (looking-at vhdl-trailer-re)
3245 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3246 (vhdl-backward-skip-label (vhdl-point 'boi))
3247 (vhdl-add-syntax 'block-close (point)))
3248 ;; CASE 6: A continued statement
3249 ((and (/= char-before-ip ?\;)
3250 ;; check it's not a trailer begin keyword, or a begin
3251 ;; keyword immediately following a label.
3252 (not (and begin-after-ip
3253 (or (looking-at vhdl-trailer-re)
3255 (vhdl-backward-skip-label containing-sexp)))))
3256 ;; check it's not a statement keyword
3257 (not (and (looking-at vhdl-statement-fwd-re)
3258 (vhdl-statement-p)))
3259 ;; see if the b-o-s is before the indent point
3262 (vhdl-beginning-of-statement-1 containing-sexp)
3263 ;; If we ended up after a leader, then this will
3264 ;; move us forward to the start of the first
3265 ;; statement. Note that a containing sexp here is
3266 ;; always a keyword, not a paren, so this will
3267 ;; have no effect if we hit the containing-sexp.
3268 (vhdl-forward-syntactic-ws indent-point)
3269 (setq placeholder (point))))
3270 ;; check it's not a block-intro
3271 (/= placeholder containing-sexp)
3272 ;; check it's not a case block-intro
3274 (goto-char placeholder)
3275 (or (not (looking-at vhdl-case-alternative-re))
3276 (> (match-end 0) indent-point))))
3277 ;; Make placeholder skip a label, but only if it puts us
3278 ;; before the indent point at the start of a line.
3279 (let ((new placeholder))
3280 (if (and (> indent-point
3282 (goto-char placeholder)
3283 (vhdl-forward-skip-label indent-point)
3284 (setq new (point))))
3287 (eq new (progn (back-to-indentation) (point)))))
3288 (setq placeholder new)))
3289 (vhdl-add-syntax 'statement-cont placeholder)
3291 (vhdl-add-syntax 'block-open)))
3292 ;; Statement. But what kind?
3293 ;; CASE 7: A case alternative key
3294 ((and (looking-at vhdl-case-alternative-re)
3295 (vhdl-case-alternative-p containing-sexp))
3296 ;; for a case alternative key, we set relpos to the first
3297 ;; non-whitespace char on the line containing the "case"
3299 (goto-char containing-sexp)
3300 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3301 (if (looking-at vhdl-trailer-re)
3302 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3303 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
3304 ;; CASE 8: statement catchall
3306 ;; we know its a statement, but we need to find out if it is
3307 ;; the first statement in a block
3308 (if containing-leader
3309 (goto-char containing-leader)
3310 (goto-char containing-sexp)
3311 ;; Note that a containing sexp here is always a keyword,
3312 ;; not a paren, so skip over the keyword.
3314 ;; move to the start of the first statement
3315 (vhdl-forward-syntactic-ws indent-point)
3316 (setq placeholder (point))
3317 ;; we want to ignore case alternatives keys when skipping forward
3319 (while (looking-at vhdl-case-alternative-re)
3320 (setq incase-p (point))
3321 ;; we also want to skip over the body of the
3322 ;; case/when statement if that doesn't put us at
3323 ;; after the indent-point
3324 (while (vhdl-skip-case-alternative indent-point))
3325 ;; set up the match end
3326 (looking-at vhdl-case-alternative-re)
3327 (goto-char (match-end 0))
3328 ;; move to the start of the first case alternative statement
3329 (vhdl-forward-syntactic-ws indent-point)
3330 (setq placeholder (point)))
3332 ;; CASE 8A: we saw a case/when statement so we must be
3333 ;; in a switch statement. find out if we are at the
3334 ;; statement just after a case alternative key
3336 (= (point) indent-point))
3337 ;; relpos is the "when" keyword
3338 (vhdl-add-syntax 'statement-case-intro incase-p))
3339 ;; CASE 8B: any old statement
3340 ((< (point) indent-point)
3341 ;; relpos is the first statement of the block
3342 (vhdl-add-syntax 'statement placeholder)
3344 (vhdl-add-syntax 'block-open)))
3345 ;; CASE 8C: first statement in a block
3347 (goto-char containing-sexp)
3348 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3349 (if (looking-at vhdl-trailer-re)
3350 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3351 (vhdl-backward-skip-label (vhdl-point 'boi))
3352 (vhdl-add-syntax 'statement-block-intro (point))
3354 (vhdl-add-syntax 'block-open)))
3358 ;; now we need to look at any modifiers
3359 (goto-char indent-point)
3360 (skip-chars-forward " \t")
3361 (if (looking-at "--")
3362 (vhdl-add-syntax 'comment))
3363 ;; return the syntax
3364 vhdl-syntactic-context))))
3366 ;; Standard indentation line-ups:
3368 (defun vhdl-lineup-arglist (langelem)
3369 ;; lineup the current arglist line with the arglist appearing just
3370 ;; after the containing paren which starts the arglist.
3372 (let* ((containing-sexp
3374 ;; arglist-cont-nonempty gives relpos ==
3375 ;; to boi of containing-sexp paren. This
3376 ;; is good when offset is +, but bad
3377 ;; when it is vhdl-lineup-arglist, so we
3378 ;; have to special case a kludge here.
3379 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
3382 (backward-up-list 1)
3383 (skip-chars-forward " \t" (vhdl-point 'eol)))
3384 (goto-char (cdr langelem)))
3386 (cs-curcol (save-excursion
3387 (goto-char (cdr langelem))
3391 (looking-at "[ \t]*)"))
3392 (progn (goto-char (match-end 0))
3395 (vhdl-forward-syntactic-ws)
3396 (- (current-column) cs-curcol))
3397 (goto-char containing-sexp)
3399 (let ((eol (vhdl-point 'eol))
3402 (skip-chars-forward " \t")
3404 (vhdl-forward-syntactic-ws)
3407 (- (current-column) cs-curcol)
3410 (defun vhdl-lineup-arglist-intro (langelem)
3411 ;; lineup an arglist-intro line to just after the open paren
3413 (let ((cs-curcol (save-excursion
3414 (goto-char (cdr langelem))
3416 (ce-curcol (save-excursion
3418 (backward-up-list 1)
3419 (skip-chars-forward " \t" (vhdl-point 'eol))
3421 (- ce-curcol cs-curcol -1))))
3423 (defun vhdl-lineup-comment (langelem)
3424 ;; support old behavior for comment indentation. we look at
3425 ;; vhdl-comment-only-line-offset to decide how to indent comment
3428 (back-to-indentation)
3429 ;; at or to the right of comment-column
3430 (if (>= (current-column) comment-column)
3431 (vhdl-comment-indent)
3432 ;; otherwise, indent as specified by vhdl-comment-only-line-offset
3434 (or (car-safe vhdl-comment-only-line-offset)
3435 vhdl-comment-only-line-offset)
3436 (or (cdr-safe vhdl-comment-only-line-offset)
3437 (car-safe vhdl-comment-only-line-offset)
3438 -1000 ;jam it against the left side
3441 (defun vhdl-lineup-statement-cont (langelem)
3442 ;; line up statement-cont after the assignment operator
3444 (let* ((relpos (cdr langelem))
3445 (assignp (save-excursion
3446 (goto-char (vhdl-point 'boi))
3447 (and (re-search-forward "\\(<\\|:\\)="
3448 (vhdl-point 'eol) t)
3449 (- (point) (vhdl-point 'boi)))))
3454 (while (and (not foundp)
3455 (< (point) (vhdl-point 'eol)))
3456 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
3457 (if (vhdl-in-literal (cdr langelem))
3459 (if (= (preceding-char) ?\()
3460 ;; skip over any parenthesized expressions
3461 (goto-char (min (vhdl-point 'eol)
3462 (scan-lists (point) 1 1)))
3463 ;; found an assignment operator (not at eol)
3464 (setq foundp (not (looking-at "\\s-*$"))))))
3466 ;; there's no assignment operator on the line
3468 ;; calculate indentation column after assign and ws, unless
3469 ;; our line contains an assignment operator
3473 (skip-chars-forward " \t")
3475 (- (current-column) assignp curcol))
3478 ;; ############################################################################
3479 ;; Indentation commands
3481 (defun vhdl-tab (&optional pre-arg)
3482 "If preceeding character is part of a word then dabbrev-expand,
3483 else if right of non whitespace on line then tab-to-tab-stop,
3484 else if last command was a tab or return then dedent one step,
3485 else indent `correctly'."
3487 (cond ((= (char-syntax (preceding-char)) ?w)
3488 (let ((case-fold-search nil)) (dabbrev-expand pre-arg)))
3489 ((> (current-column) (current-indentation))
3491 ((and (or (eq last-command 'vhdl-tab)
3492 (eq last-command 'vhdl-return))
3493 (/= 0 (current-indentation)))
3494 (backward-delete-char-untabify vhdl-basic-offset nil))
3495 ((vhdl-indent-line))
3497 (setq this-command 'vhdl-tab)
3500 (defun vhdl-untab ()
3501 "Delete backwards to previous tab stop."
3503 (backward-delete-char-untabify vhdl-basic-offset nil)
3506 (defun vhdl-return ()
3507 "newline-and-indent or indent-new-comment-line if in comment and preceding
3508 character is a space."
3510 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
3511 (indent-new-comment-line)
3512 (newline-and-indent)
3516 (defun vhdl-indent-line ()
3517 "Indent the current line as VHDL code. Returns the amount of
3518 indentation change."
3520 (let* ((syntax (vhdl-get-syntactic-context))
3521 (pos (- (point-max) (point)))
3522 (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
3523 (shift-amt (- (current-indentation) indent)))
3524 (and vhdl-echo-syntactic-information-p
3525 (message "syntax: %s, indent= %d" syntax indent))
3526 (if (zerop shift-amt)
3528 (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
3531 (if (< (point) (vhdl-point 'boi))
3532 (back-to-indentation)
3533 ;; If initial point was within line's indentation, position after
3534 ;; the indentation. Else stay at same point in text.
3535 (if (> (- (point-max) pos) (point))
3536 (goto-char (- (point-max) pos)))
3538 (run-hooks 'vhdl-special-indent-hook)
3541 (defun vhdl-indent-buffer ()
3542 "Indent whole buffer as VHDL code."
3544 (indent-region (point-min) (point-max) nil)
3547 (defun vhdl-indent-sexp (&optional endpos)
3548 "Indent each line of the list starting just after point.
3549 If optional arg ENDPOS is given, indent each line, stopping when
3550 ENDPOS is encountered."
3555 (vhdl-forward-sexp nil endpos)
3557 (indent-region beg end nil))))
3559 ;; ############################################################################
3560 ;; Miscellaneous commands
3562 (defun vhdl-show-syntactic-information ()
3563 "Show syntactic information for current line."
3565 (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
3566 (vhdl-keep-region-active))
3568 ;; Verification and regression functions:
3570 (defun vhdl-regress-line (&optional arg)
3571 "Check syntactic information for current line."
3573 (let ((expected (save-excursion
3575 (if (search-backward " -- ((" (vhdl-point 'bol) t)
3578 (read (current-buffer))))))
3579 (actual (vhdl-get-syntactic-context))
3581 ;; remove the library unit symbols
3585 (if (memq (car elt) '(entity configuration package
3586 package-body architecture))
3588 (setq expurgated (append expurgated (list elt))))))
3590 (if (and (not arg) expected (listp expected))
3591 (if (not (equal expected expurgated))
3592 (error "Should be: %s, is: %s" expected expurgated))
3595 (if (not (looking-at "^\\s-*\\(--.*\\)?$"))
3598 (if (search-backward " -- ((" (vhdl-point 'bol) t)
3601 (insert (format "%s" expurgated)))))))
3602 (vhdl-keep-region-active))
3605 ;; ############################################################################
3607 ;; ############################################################################
3609 (defvar vhdl-align-alist
3611 ;; after some keywords
3612 (vhdl-mode "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)[ \t]"
3613 "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)\\([ \t]+\\)" 2)
3615 (vhdl-mode ":[^=]" "[^ \t]\\([ \t]*\\):[^=]")
3617 (vhdl-mode ":[^=]" ":\\([ \t]*\\)[^=]" 1)
3618 ;; after direction specifications
3619 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\>"
3620 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\([ \t]+\\)" 2)
3621 ;; before "<=", "=>", and ":="
3622 (vhdl-mode "<=" "[^ \t]\\([ \t]*\\)<=" 1)
3623 (vhdl-mode "=>" "[^ \t]\\([ \t]*\\)=>" 1)
3624 (vhdl-mode ":=" "[^ \t]\\([ \t]*\\):=" 1)
3625 ;; after "<=", "=>", and ":="
3626 (vhdl-mode "<=" "<=\\([ \t]*\\)" 1)
3627 (vhdl-mode "=>" "=>\\([ \t]*\\)" 1)
3628 (vhdl-mode ":=" ":=\\([ \t]*\\)" 1)
3629 ;; before some keywords
3630 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
3631 (vhdl-mode "[ \t]\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>"
3632 "[^ \t]\\([ \t]+\\)\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" 1)
3633 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
3634 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
3635 (vhdl-mode "[ \t]is\\>" "[^ \t]\\([ \t]+\\)is\\>" 1)
3636 (vhdl-mode "[ \t]of\\>" "[^ \t]\\([ \t]+\\)of\\>" 1)
3637 (vhdl-mode "[ \t]use\\>" "[^ \t]\\([ \t]+\\)use\\>" 1)
3638 ;; before comments (two steps required for correct insertion of two spaces)
3639 (vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)
3640 (vhdl-mode "--" "[^ \t][ \t]\\([ \t]*\\)--" 1)
3642 "The format of this alist is
3643 (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
3644 It is searched in order. If REGEXP is found anywhere in the first
3645 line of a region to be aligned, ALIGN-PATTERN will be used for that
3646 region. ALIGN-PATTERN must include the whitespace to be expanded or
3647 contracted. It may also provide regexps for the text surrounding the
3648 whitespace. SUBEXP specifies which sub-expression of
3649 ALIGN-PATTERN matches the white space to be expanded/contracted.")
3651 (defvar vhdl-align-try-all-clauses t
3652 "If REGEXP is not found on the first line of the region that clause
3653 is ignored. If this variable is non-nil, then the clause is tried anyway.")
3655 (defun vhdl-align (begin end spacing &optional alignment-list quick)
3656 "Attempt to align a range of lines based on the content of the
3657 lines. The definition of 'alignment-list' determines the matching
3658 order and the manner in which the lines are aligned. If ALIGNMENT-LIST
3659 is not specified 'vhdl-align-alist' is used. If QUICK is non-nil, no
3660 indentation is done before aligning."
3661 (interactive "r\np")
3662 (if (not alignment-list)
3663 (setq alignment-list vhdl-align-alist))
3669 (setq end (point-marker))
3672 (setq begin (progn (beginning-of-line) (point))))
3676 (indent-region bol end nil))))
3677 (let ((copy (copy-alist alignment-list)))
3682 (eol (save-excursion (progn (end-of-line) (point)))))
3683 (setq element (nth 0 copy))
3684 (if (and (or (and (listp (car element))
3685 (memq major-mode (car element)))
3686 (eq major-mode (car element)))
3687 (or vhdl-align-try-all-clauses
3688 (re-search-forward (car (cdr element)) eol t)))
3690 (vhdl-align-region begin end (car (cdr (cdr element)))
3691 (car (cdr (cdr (cdr element)))) spacing)))
3692 (setq copy (cdr copy)))))))
3694 (defun vhdl-align-region (begin end match &optional substr spacing)
3695 "Align a range of lines from BEGIN to END. The regular expression
3696 MATCH must match exactly one fields: the whitespace to be
3697 contracted/expanded. The alignment column will equal the
3698 rightmost column of the widest whitespace block. SPACING is
3699 the amount of extra spaces to add to the calculated maximum required.
3700 SPACING defaults to 1 so that at least one space is inserted after
3701 the token in MATCH."
3707 (let (distance (max 0) (lines 0) bol eol width)
3708 ;; Determine the greatest whitespace distance to the alignment
3711 (setq eol (progn (end-of-line) (point))
3712 bol (setq begin (progn (beginning-of-line) (point))))
3715 (if (re-search-forward match eol t)
3717 (setq distance (- (match-beginning substr) bol))
3718 (if (> distance max)
3719 (setq max distance)))))
3725 (setq lines (1+ lines)))
3726 ;; Now insert enough maxs to push each assignment operator to
3727 ;; the same column. We need to use 'lines' as a counter, since
3728 ;; the location of the mark may change
3729 (goto-char (setq bol begin))
3730 (setq eol (save-excursion
3734 (if (re-search-forward match eol t)
3736 (setq width (- (match-end substr) (match-beginning substr)))
3737 (setq distance (- (match-beginning substr) bol))
3738 (goto-char (match-beginning substr))
3740 (insert-char ? (+ (- max distance) spacing))))
3747 (setq lines (1- lines))
3750 (defun vhdl-align-comment-region (begin end spacing)
3751 "Aligns inline comments within a region relative to first comment."
3752 (interactive "r\nP")
3753 (vhdl-align begin end (or spacing 2)
3754 `((vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)) t))
3756 (defun vhdl-align-noindent-region (begin end spacing)
3757 "Align without indentation."
3758 (interactive "r\nP")
3759 (vhdl-align begin end spacing nil t)
3763 ;; ############################################################################
3764 ;; VHDL electrification
3765 ;; ############################################################################
3767 ;; ############################################################################
3770 (defun vhdl-stutter-mode-caps (count)
3771 "Double first letters of a word replaced by a single capital of the letter."
3773 (if vhdl-stutter-mode
3775 (= (preceding-char) last-input-char) ; doubled
3776 (or (= (point) 2) ; beginning of buffer
3777 (/= (char-syntax (char-after (- (point) 2))) ?w) ;not mid-word
3778 (< (char-after (- (point) 2)) ?A))) ;alfa-numeric
3779 (progn (delete-char -1) (insert-char (- last-input-char 32) count))
3780 (self-insert-command count))
3781 (self-insert-command count)
3784 (defun vhdl-stutter-mode-close-bracket (count) " ']' --> ')', ')]' --> ']'"
3786 (if (and vhdl-stutter-mode (= count 1))
3788 (if (= (preceding-char) 41) ; close-paren
3789 (progn (delete-char -1) (insert-char 93 1)) ; close-bracket
3790 (insert-char 41 1) ; close-paren
3792 (blink-matching-open))
3793 (self-insert-command count)
3796 (defun vhdl-stutter-mode-semicolon (count) " ';;' --> ' : ', ': ;' --> ' := '"
3798 (if (and vhdl-stutter-mode (= count 1))
3800 (cond ((= (preceding-char) last-input-char)
3801 (progn (delete-char -1)
3802 (if (not (eq (preceding-char) ? )) (insert " "))
3805 (eq last-command 'vhdl-stutter-mode-colon) (= (preceding-char) ? ))
3806 (progn (delete-char -1) (insert "= ")))
3808 (insert-char 59 1)) ; semi-colon
3810 (setq this-command 'vhdl-stutter-mode-colon))
3811 (self-insert-command count)
3814 (defun vhdl-stutter-mode-open-bracket (count) " '[' --> '(', '([' --> '['"
3816 (if (and vhdl-stutter-mode (= count 1))
3817 (if (= (preceding-char) 40) ; open-paren
3818 (progn (delete-char -1) (insert-char 91 1)) ; open-bracket
3819 (insert-char 40 1)) ; open-paren
3820 (self-insert-command count)
3823 (defun vhdl-stutter-mode-quote (count) " '' --> \""
3825 (if (and vhdl-stutter-mode (= count 1))
3826 (if (= (preceding-char) last-input-char)
3827 (progn (delete-backward-char 1) (insert-char 34 1)) ; double-quote
3828 (insert-char 39 1)) ; single-quote
3829 (self-insert-command count)
3832 (defun vhdl-stutter-mode-comma (count) " ',,' --> ' <= '"
3834 (if (and vhdl-stutter-mode (= count 1))
3835 (cond ((= (preceding-char) last-input-char)
3836 (progn (delete-char -1)
3837 (if (not (eq (preceding-char) ? )) (insert " "))
3840 (insert-char 44 1))) ; comma
3841 (self-insert-command count)
3844 (defun vhdl-stutter-mode-period (count) " '..' --> ' => '"
3846 (if (and vhdl-stutter-mode (= count 1))
3847 (cond ((= (preceding-char) last-input-char)
3848 (progn (delete-char -1)
3849 (if (not (eq (preceding-char) ? )) (insert " "))
3852 (insert-char 46 1))) ; period
3853 (self-insert-command count)
3856 (defun vhdl-paired-parens ()
3857 "Insert a pair of round parentheses, placing point between them."
3863 (defun vhdl-stutter-mode-dash (count)
3864 "-- starts a comment, --- draws a horizontal line,
3865 ---- starts a display comment"
3867 (if vhdl-stutter-mode
3868 (cond ((and abbrev-start-location (= abbrev-start-location (point)))
3869 (setq abbrev-start-location nil)
3870 (goto-char last-abbrev-location)
3871 (beginning-of-line nil)
3872 (vhdl-display-comment))
3873 ((/= (preceding-char) ?-) ; standard dash (minus)
3874 (self-insert-command count))
3876 (self-insert-command count)
3877 (message "Enter - for horiz. line, CR for commenting-out code, else 1st char of comment")
3878 (let ((next-input (read-char)))
3879 (if (= next-input ?-) ; triple dash
3881 (vhdl-display-comment-line)
3883 "Enter - for display comment, else continue with coding")
3884 (let ((next-input (read-char)))
3885 (if (= next-input ?-) ; four dashes
3886 (vhdl-display-comment t)
3887 (setq unread-command-events ;pushback the char
3889 (vhdl-character-to-event-hack next-input)))
3891 (setq unread-command-events ;pushback the char
3892 (list (vhdl-character-to-event-hack next-input)))
3893 (vhdl-inline-comment)
3895 (self-insert-command count)
3898 ;; ############################################################################
3901 (defun vhdl-alias ()
3902 "Insert alias declaration."
3904 (vhdl-insert-keyword "ALIAS ")
3905 (if (equal (vhdl-field "name") "")
3909 (vhdl-insert-keyword " IS ")
3910 (vhdl-field "name" ";")
3911 (vhdl-declaration-comment)
3914 (defun vhdl-architecture ()
3915 "Insert architecture template."
3917 (let ((margin (current-column))
3918 (vhdl-architecture-name)
3922 (case-fold-search t))
3923 (vhdl-insert-keyword "ARCHITECTURE ")
3924 (if (equal (setq vhdl-architecture-name (vhdl-field "name")) "")
3926 (vhdl-insert-keyword " OF ")
3927 (setq position (point))
3929 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)+\\) is" nil t))
3930 (setq string (match-string 1))
3931 (goto-char position)
3932 (if (and entity-exists (not (equal string "")))
3934 (vhdl-field "entity name"))
3935 (vhdl-insert-keyword " IS")
3936 (vhdl-begin-end (cons vhdl-architecture-name margin))
3937 (vhdl-block-comment)
3941 (defun vhdl-array ()
3942 "Insert array type definition."
3944 (vhdl-insert-keyword "ARRAY (")
3945 (if (equal (vhdl-field "range") "")
3947 (vhdl-insert-keyword ") OF ")
3949 (vhdl-insert-keyword ";")
3952 (defun vhdl-assert ()
3953 "Inserts a assertion statement."
3955 (vhdl-insert-keyword "ASSERT ")
3956 (if vhdl-conditions-in-parenthesis (insert "("))
3957 (if (equal (vhdl-field "condition (negated)") "")
3958 (progn (undo) (insert " "))
3959 (if vhdl-conditions-in-parenthesis (insert ")"))
3960 (vhdl-insert-keyword " REPORT \"")
3961 (vhdl-field "string-expression" "\" ")
3962 (vhdl-insert-keyword "SEVERITY ")
3963 (if (equal (vhdl-field "[note | warning | error | failure]") "")
3968 (defun vhdl-attribute ()
3969 "Inserts an attribute declaration or specification."
3971 (vhdl-insert-keyword "ATTRIBUTE ")
3972 (if (y-or-n-p "declaration (or specification)? ")
3974 (vhdl-field "name" " : ")
3975 (vhdl-field "type" ";")
3976 (vhdl-declaration-comment))
3978 (vhdl-insert-keyword " OF ")
3979 (vhdl-field "entity name" " : ")
3980 (vhdl-field "entity class")
3981 (vhdl-insert-keyword " IS ")
3982 (vhdl-field "expression" ";")
3985 (defun vhdl-block ()
3986 "Insert a block template."
3988 (let ((position (point)))
3989 (vhdl-insert-keyword " : BLOCK ")
3990 (goto-char position))
3991 (let* ((margin (current-column))
3992 (name (vhdl-field "label")))
3994 (progn (undo) (insert " "))
3997 (if (equal (vhdl-field "[guard expression]") "")
4000 (vhdl-begin-end (cons (concat (vhdl-case-keyword "BLOCK ") name) margin))
4001 (vhdl-block-comment)
4004 (defun vhdl-block-configuration ()
4005 "Insert a block configuration statement."
4007 (let ((margin (current-column)))
4008 (vhdl-insert-keyword "FOR ")
4009 (if (equal (setq name (vhdl-field "block specification")) "")
4011 (vhdl-insert-keyword "\n\n")
4013 (vhdl-insert-keyword "END FOR;")
4015 (indent-to (+ margin vhdl-basic-offset))
4019 "Inserts a case statement."
4021 (let ((margin (current-column))
4023 (vhdl-insert-keyword "CASE ")
4024 (if (equal (setq name (vhdl-field "expression")) "")
4026 (vhdl-insert-keyword " IS\n\n")
4028 (vhdl-insert-keyword "END CASE;")
4029 ; (if vhdl-self-insert-comments (insert " -- " name))
4031 (indent-to (+ margin vhdl-basic-offset))
4032 (vhdl-insert-keyword "WHEN => ")
4036 (defun vhdl-component ()
4037 "Inserts a component declaration."
4039 (let ((margin (current-column)))
4040 (vhdl-insert-keyword "COMPONENT ")
4041 (if (equal (vhdl-field "name") "")
4045 (vhdl-insert-keyword "END COMPONENT;")
4047 (indent-to (+ margin vhdl-basic-offset))
4048 (vhdl-insert-keyword "GENERIC (")
4049 (vhdl-get-generic t t)
4051 (indent-to (+ margin vhdl-basic-offset))
4052 (vhdl-insert-keyword "PORT (")
4057 (defun vhdl-component-configuration ()
4058 "Inserts a component configuration (uses `vhdl-configuration-spec' since
4059 these are almost equivalent)."
4061 (let ((margin (current-column)))
4062 (vhdl-configuration-spec)
4065 (vhdl-insert-keyword "END FOR;")
4068 (defun vhdl-component-instance ()
4069 "Inserts a component instantiation statement."
4071 (let ((margin (current-column)))
4072 (if (equal (vhdl-field "instance label") "")
4075 (vhdl-field "component name" "\n")
4076 (indent-to (+ margin vhdl-basic-offset))
4077 (let ((position (point)))
4078 (vhdl-insert-keyword "GENERIC MAP (")
4079 (if (equal (vhdl-field "[association list]") "")
4080 (progn (goto-char position)
4083 (indent-to (+ margin vhdl-basic-offset))))
4084 (vhdl-insert-keyword "PORT MAP (")
4085 (vhdl-field "association list" ");")
4088 (defun vhdl-concurrent-signal-assignment ()
4089 "Inserts a concurrent signal assignment."
4091 (if (equal (vhdl-field "target signal") "")
4094 ; (if (not (equal (vhdl-field "[GUARDED] [TRANSPORT]") ""))
4096 (let ((margin (current-column))
4098 (vhdl-field "waveform")
4099 (vhdl-insert-keyword " WHEN ")
4100 (if vhdl-conditions-in-parenthesis (insert "("))
4101 (while (not (equal (vhdl-field "[condition]") ""))
4102 (if vhdl-conditions-in-parenthesis (insert ")"))
4103 (vhdl-insert-keyword " ELSE")
4106 (vhdl-field "waveform")
4107 (vhdl-insert-keyword " WHEN ")
4108 (if vhdl-conditions-in-parenthesis (insert "(")))
4110 (if vhdl-conditions-in-parenthesis (delete-char -1))
4112 (if vhdl-auto-align (vhdl-align start (point) 1))
4115 (defun vhdl-configuration ()
4116 "Inserts a configuration specification if within an architecture,
4117 a block or component configuration if within a configuration declaration,
4118 a configuration declaration if not within a design unit."
4120 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'architecture)
4121 (vhdl-configuration-spec))
4122 ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
4123 (if (y-or-n-p "block configuration (or component configuration)? ")
4124 (vhdl-block-configuration)
4125 (vhdl-component-configuration)))
4126 (t (vhdl-configuration-decl)))
4129 (defun vhdl-configuration-spec ()
4130 "Inserts a configuration specification."
4132 (let ((margin (current-column)))
4133 (vhdl-insert-keyword "FOR ")
4134 (if (equal (vhdl-field "(component names | ALL)" " : ") "")
4135 (progn (undo) (insert " "))
4136 (vhdl-field "component type" "\n")
4137 (indent-to (+ margin vhdl-basic-offset))
4138 (vhdl-insert-keyword "USE ENTITY ")
4139 (vhdl-field "library name" ".")
4140 (vhdl-field "entity name" "(")
4141 (if (equal (vhdl-field "[architecture name]") "")
4145 (indent-to (+ margin vhdl-basic-offset))
4146 (vhdl-insert-keyword "GENERIC MAP (")
4147 (if (equal (vhdl-field "[association list]") "")
4148 (progn (kill-line -0)
4149 (indent-to (+ margin vhdl-basic-offset)))
4151 (indent-to (+ margin vhdl-basic-offset)))
4152 (vhdl-insert-keyword "PORT MAP (")
4153 (if (equal (vhdl-field "[association list]") "")
4154 (progn (kill-line -0)
4160 (defun vhdl-configuration-decl ()
4161 "Inserts a configuration declaration."
4163 (let ((margin (current-column))
4168 (vhdl-insert-keyword "CONFIGURATION ")
4169 (if (equal (setq name (vhdl-field "name")) "")
4171 (vhdl-insert-keyword " OF ")
4172 (setq position (point))
4174 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)*\\) is" nil t))
4175 (setq string (match-string 1))
4176 (goto-char position)
4177 (if (and entity-exists (not (equal string "")))
4179 (vhdl-field "entity name"))
4180 (vhdl-insert-keyword " IS\n\n")
4182 (vhdl-insert-keyword "END ")
4185 (indent-to (+ margin vhdl-basic-offset))
4188 (defun vhdl-constant ()
4189 "Inserts a constant declaration."
4191 (vhdl-insert-keyword "CONSTANT ")
4192 (let ((in-arglist (string-match "arglist"
4193 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4194 (if (not in-arglist)
4195 (let ((opoint (point)))
4197 (setq in-arglist (looking-at ".*("))
4198 (goto-char opoint)))
4199 (if (equal (vhdl-field "name") "")
4202 (if in-arglist (vhdl-insert-keyword "IN "))
4206 (let ((position (point)))
4208 (if (equal (vhdl-field "[initialization]" ";") "")
4209 (progn (goto-char position) (kill-line) (insert ";")))
4210 (vhdl-declaration-comment))
4213 (defun vhdl-default ()
4223 (defun vhdl-default-indent ()
4224 "Insert nothing and indent."
4234 (defun vhdl-disconnect ()
4235 "Insert a disconnect statement."
4237 (vhdl-insert-keyword "DISCONNECT ")
4238 (if (equal (vhdl-field "guarded signal specification") "")
4240 (vhdl-insert-keyword " AFTER ")
4241 (vhdl-field "time expression" ";")
4245 "Insert an else statement."
4248 (vhdl-insert-keyword "ELSE")
4249 (if (not (equal 'block-close (car (car (vhdl-get-syntactic-context)))))
4252 (setq margin (current-indentation))
4254 (indent-to (+ margin vhdl-basic-offset))
4257 (defun vhdl-elsif ()
4258 "Insert an elsif statement."
4261 (vhdl-insert-keyword "ELSIF ")
4262 (if vhdl-conditions-in-parenthesis (insert "("))
4263 (if (equal (vhdl-field "condition") "")
4264 (progn (undo) (insert " "))
4265 (if vhdl-conditions-in-parenthesis (insert ")"))
4267 (setq margin (current-indentation))
4268 (vhdl-insert-keyword " THEN\n")
4269 (indent-to (+ margin vhdl-basic-offset))
4272 (defun vhdl-entity ()
4273 "Insert an entity template."
4275 (let ((margin (current-column))
4277 (vhdl-insert-keyword "ENTITY ")
4278 (if (equal (setq vhdl-entity-name (vhdl-field "entity name")) "")
4280 (vhdl-insert-keyword " IS\n\n")
4282 (vhdl-insert-keyword "END ")
4283 (insert vhdl-entity-name ";")
4285 (indent-to (+ margin vhdl-basic-offset))
4289 (defun vhdl-entity-body ()
4290 "Insert an entity body."
4292 (let ((margin (current-column)))
4293 (if vhdl-additional-empty-lines (insert "\n"))
4295 (vhdl-insert-keyword "GENERIC (")
4296 (if (vhdl-get-generic t)
4297 (if vhdl-additional-empty-lines (insert "\n")))
4300 (vhdl-insert-keyword "PORT (")
4301 (if (vhdl-get-port t)
4302 (if vhdl-additional-empty-lines (insert "\n")))
4307 "Insert an exit statement."
4309 (vhdl-insert-keyword "EXIT ")
4310 (if (string-equal (vhdl-field "[loop label]") "")
4312 (let ((opoint (point)))
4313 (vhdl-insert-keyword " WHEN ")
4314 (if vhdl-conditions-in-parenthesis (insert "("))
4315 (if (equal (vhdl-field "[condition]") "")
4316 (progn (goto-char opoint)
4318 (if vhdl-conditions-in-parenthesis (insert ")"))))
4323 "Inserts a block or component configuration if within a configuration
4324 declaration, a for loop otherwise."
4326 (if (equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
4327 (if (y-or-n-p "block configuration (or component configuration)? ")
4328 (vhdl-block-configuration)
4329 (vhdl-component-configuration))
4332 (defun vhdl-for-loop ()
4333 "Insert a for loop template."
4335 (let ((position (point)))
4336 (vhdl-insert-keyword " : FOR ")
4337 (goto-char position))
4338 (let* ((margin (current-column))
4339 (name (vhdl-field "[label]"))
4340 (named (not (string-equal name "")))
4342 (if (not named) (delete-char 3))
4344 (if (equal (setq index (vhdl-field "loop variable")) "")
4346 (vhdl-insert-keyword " IN ")
4347 (vhdl-field "range")
4348 (vhdl-insert-keyword " LOOP\n\n")
4350 (vhdl-insert-keyword "END LOOP")
4351 (if named (insert " " name ";")
4353 (if vhdl-self-insert-comments (insert " -- " index)))
4355 (indent-to (+ margin vhdl-basic-offset))
4358 (defun vhdl-function ()
4359 "Insert function specification or body template."
4361 (let ((margin (current-column))
4363 (vhdl-insert-keyword "FUNCTION ")
4364 (if (equal (setq name (vhdl-field "name")) "")
4367 (vhdl-insert-keyword " RETURN ")
4368 (vhdl-field "type" " ")
4369 (if (y-or-n-p "insert body? ")
4370 (progn (vhdl-insert-keyword "IS")
4371 (vhdl-begin-end (cons name margin))
4372 (vhdl-block-comment))
4375 (indent-to margin)))
4378 (defun vhdl-generate ()
4379 "Insert a generate template."
4381 (let ((position (point)))
4382 (vhdl-insert-keyword " GENERATE")
4383 (goto-char position))
4384 (let ((margin (current-column))
4385 (label (vhdl-field "label"))
4387 (if (equal label "")
4388 (progn (undo) (insert " "))
4390 (setq string (vhdl-field "(FOR | IF)"))
4392 (if (equal (upcase string) "IF")
4394 (if vhdl-conditions-in-parenthesis (insert "("))
4395 (vhdl-field "condition")
4396 (if vhdl-conditions-in-parenthesis (insert ")")))
4397 (vhdl-field "loop variable")
4398 (vhdl-insert-keyword " IN ")
4399 (vhdl-field "range"))
4403 (vhdl-insert-keyword "END GENERATE ")
4406 (indent-to (+ margin vhdl-basic-offset))
4409 (defun vhdl-generic ()
4410 "Insert generic declaration, or generic map in instantiation statements."
4412 (vhdl-insert-keyword "GENERIC (")
4413 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
4414 (vhdl-get-generic nil))
4415 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
4417 (and (backward-word 2) (skip-chars-backward " ")
4418 (eq (preceding-char) ?:))))
4419 (delete-char -1) (vhdl-map))
4420 (t (vhdl-get-generic nil t))))
4422 (defun vhdl-header ()
4423 "Insert a VHDL file header."
4429 (goto-char (point-min))
4430 (if vhdl-header-file
4431 (setq eot (car (cdr (insert-file-contents vhdl-header-file))))
4432 ; insert default header
4434 -------------------------------------------------------------------------------
4435 -- Title : <title string>
4436 -- Project : <project string>
4437 -------------------------------------------------------------------------------
4438 -- File : <filename>
4439 -- Author : <author>
4441 -- Last modified : <date>
4442 -------------------------------------------------------------------------------
4445 -------------------------------------------------------------------------------
4446 -- Modification history :
4448 -------------------------------------------------------------------------------
4452 (narrow-to-region (point-min) eot)
4453 (goto-char (point-min))
4454 (while (search-forward "<filename>" nil t)
4455 (replace-match (buffer-name) t t))
4456 (goto-char (point-min))
4457 (while (search-forward "<author>" nil t)
4458 (replace-match "" t t)
4459 (insert (user-full-name) " <" user-mail-address ">"))
4460 (goto-char (point-min))
4461 ;; Replace <RCS> with $, so that RCS for the source is
4462 ;; not over-enthusiastic with replacements
4463 (while (search-forward "<RCS>" nil t)
4464 (replace-match "$" nil t))
4465 (goto-char (point-min))
4466 (while (search-forward "<date>" nil t)
4467 (replace-match "" t t)
4469 (goto-char (point-min))
4471 (while (re-search-forward "<\\(\\w*\\) string>" nil t)
4472 (setq string (read-string (concat (match-string 1) ": ")))
4473 (replace-match string t t)))))
4474 (goto-char (point-min))
4475 (if (search-forward "<cursor>" nil t)
4476 (replace-match "" t t))))
4479 "Insert an if statement template."
4481 (let ((margin (current-column)))
4482 (vhdl-insert-keyword "IF ")
4483 (if vhdl-conditions-in-parenthesis (insert "("))
4484 (if (equal (vhdl-field "condition") "")
4485 (progn (undo) (insert " "))
4486 (if vhdl-conditions-in-parenthesis (insert ")"))
4487 (vhdl-insert-keyword " THEN\n\n")
4489 (vhdl-insert-keyword "END IF;")
4491 (indent-to (+ margin vhdl-basic-offset))
4494 (defun vhdl-library ()
4495 "Insert a library specification."
4497 (let ((margin (current-column))
4499 (vhdl-insert-keyword "LIBRARY ")
4500 (if (equal (setq lib-name (vhdl-field "library name")) "")
4504 (vhdl-insert-keyword "USE ")
4506 (vhdl-insert-keyword "..ALL;")
4508 (if (equal (vhdl-field "package name") "")
4509 (progn (vhdl-kill-entire-line)
4515 "Insert a loop template."
4517 (let ((position (point)))
4518 (vhdl-insert-keyword " : LOOP")
4519 (goto-char position))
4520 (let* ((margin (current-column))
4521 (name (vhdl-field "[label]"))
4522 (named (not (string-equal name ""))))
4523 (if (not named) (delete-char 3))
4527 (vhdl-insert-keyword "END LOOP")
4528 (insert (if named (concat " " name ";") ?\;))
4530 (indent-to (+ margin vhdl-basic-offset))
4534 "Insert a map specification."
4536 (vhdl-insert-keyword "MAP (")
4537 (if (equal (vhdl-field "[association list]") "")
4538 (progn (undo) (insert " "))
4542 (defun vhdl-modify ()
4543 "Actualize modification date."
4545 (goto-char (point-min))
4546 (if (search-forward vhdl-modify-date-prefix-string nil t)
4549 (message (concat "Modification date prefix string \""
4550 vhdl-modify-date-prefix-string
4555 "Inserts a next statement."
4557 (vhdl-insert-keyword "NEXT ")
4558 (if (string-equal (vhdl-field "[loop label]") "")
4560 (let ((opoint (point)))
4561 (vhdl-insert-keyword " WHEN ")
4562 (if vhdl-conditions-in-parenthesis (insert "("))
4563 (if (equal (vhdl-field "[condition]") "")
4564 (progn (goto-char opoint)
4566 (if vhdl-conditions-in-parenthesis (insert ")"))))
4570 (defun vhdl-package ()
4571 "Insert a package specification or body."
4573 (let ((margin (current-column))
4575 (vhdl-insert-keyword "PACKAGE ")
4576 (if (y-or-n-p "body? ")
4577 (vhdl-insert-keyword "BODY "))
4578 (setq name (vhdl-field "name" " is\n\n"))
4580 (vhdl-insert-keyword "END ")
4583 (indent-to (+ margin vhdl-basic-offset))
4587 "Insert a port declaration, or port map in instantiation statements."
4589 (vhdl-insert-keyword "PORT (")
4590 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
4591 (vhdl-get-port nil))
4592 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
4594 (and (backward-word 2) (skip-chars-backward " ")
4595 (eq (preceding-char) ?:))))
4596 (delete-char -1) (vhdl-map))
4597 (t (vhdl-get-port nil t))))
4599 (defun vhdl-procedure ()
4600 "Insert a procedure specification or body template."
4602 (let ((margin (current-column))
4604 (vhdl-insert-keyword "PROCEDURE ")
4605 (if (equal (setq name (vhdl-field "name")) "")
4609 (if (y-or-n-p "insert body? ")
4610 (progn (vhdl-insert-keyword "IS")
4611 (vhdl-begin-end (cons name margin))
4612 (vhdl-block-comment))
4618 (defun vhdl-process ()
4619 "Insert a process template."
4622 (let ((position (point)))
4623 (vhdl-insert-keyword "PROCESS")
4624 (setq clocked (y-or-n-p "clocked process? "))
4625 (goto-char position)
4627 (goto-char position))
4628 (let* ((margin (current-column))
4630 (name (vhdl-field "[label]"))
4631 (named (not (string-equal name "")))
4633 (case-fold-search t))
4634 (if (not named) (delete-char 3))
4638 (if (equal (vhdl-field "[sensitivity list]" ")") "")
4640 (setq clock (vhdl-field "clock name" ", "))
4641 (setq reset (vhdl-field "reset name" ")")))
4642 (vhdl-begin-end (cons (concat (vhdl-case-keyword "PROCESS")
4643 (if named (concat " " name))) margin))
4644 (if clocked (vhdl-clock-async-reset clock reset))
4645 (if vhdl-prompt-for-comments
4647 (setq finalline (vhdl-current-line))
4648 (if (and (re-search-backward "\\<begin\\>" nil t)
4649 (re-search-backward "\\<process\\>" nil t))
4654 (insert "-- purpose: ")
4655 (if (equal (vhdl-field "description") "")
4656 (vhdl-kill-entire-line)
4659 (insert "-- type: ")
4660 (insert (if clocked "memorizing" "memoryless") "\n")
4662 (insert "-- inputs: ")
4664 (insert clock ", " reset ", "))
4665 (if (and (equal (vhdl-field "signal names") "")
4670 (insert "-- outputs: ")
4671 (vhdl-field "signal names")
4672 (setq finalline (+ finalline 4)))))
4673 (goto-line finalline)
4677 (defun vhdl-record ()
4678 "Insert a record type declaration."
4680 (let ((margin (current-column))
4683 (vhdl-insert-keyword "RECORD\n")
4684 (indent-to (+ margin vhdl-basic-offset))
4685 (if (equal (vhdl-field "identifiers") "")
4686 (progn (kill-line -0)
4689 (while (or first (not (equal (vhdl-field "[identifiers]") "")))
4691 (vhdl-field "type" ";")
4692 (vhdl-declaration-comment)
4694 (indent-to (+ margin vhdl-basic-offset))
4698 (vhdl-insert-keyword "END RECORD;")
4699 (if vhdl-auto-align (vhdl-align start (point) 1))
4702 (defun vhdl-return-value ()
4703 "Insert a return statement."
4705 (vhdl-insert-keyword "RETURN ")
4706 (if (equal (vhdl-field "[expression]") "")
4711 (defun vhdl-selected-signal-assignment ()
4712 "Insert a selected signal assignment."
4714 (let ((margin (current-column))
4716 (let ((position (point)))
4717 (vhdl-insert-keyword " SELECT")
4718 (goto-char position))
4719 (vhdl-insert-keyword "WITH ")
4720 (if (equal (vhdl-field "selector expression") "")
4721 (progn (undo) (insert " "))
4724 (indent-to (+ margin vhdl-basic-offset))
4725 (vhdl-field "target signal" " <= ")
4726 ; (vhdl-field "[GUARDED] [TRANSPORT]")
4728 (indent-to (+ margin vhdl-basic-offset))
4729 (while (not (equal (vhdl-field "[waveform]") ""))
4730 (vhdl-insert-keyword " WHEN ")
4731 (vhdl-field "choices" ",")
4733 (indent-to (+ margin vhdl-basic-offset)))
4734 (if (not (equal (vhdl-field "[alternative waveform]") ""))
4735 (vhdl-insert-keyword " WHEN OTHERS")
4739 (if vhdl-auto-align (vhdl-align start (point) 1))
4742 (defun vhdl-signal ()
4743 "Insert a signal declaration."
4745 (vhdl-insert-keyword "SIGNAL ")
4746 (let ((in-arglist (string-match "arglist"
4747 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4748 (if (not in-arglist)
4749 (let ((opoint (point)))
4751 (setq in-arglist (looking-at ".*("))
4752 (goto-char opoint)))
4753 (if (equal (vhdl-field "names") "")
4757 (progn (vhdl-field "direction")
4762 (let ((position (point)))
4764 (if (equal (vhdl-field "[initialization]" ";") "")
4765 (progn (goto-char position) (kill-line) (insert ";")))
4766 (vhdl-declaration-comment))
4769 (defun vhdl-subtype ()
4770 "Insert a subtype declaration."
4772 (vhdl-insert-keyword "SUBTYPE ")
4773 (if (equal (vhdl-field "name") "")
4775 (vhdl-insert-keyword " IS ")
4776 (vhdl-field "type" " ")
4777 (if (equal (vhdl-field "[RANGE value range | ( index range )]") "")
4780 (vhdl-declaration-comment)
4784 "Insert a type declaration."
4786 (vhdl-insert-keyword "TYPE ")
4787 (if (equal (vhdl-field "name") "")
4789 (vhdl-insert-keyword " IS ")
4790 (let ((definition (upcase (vhdl-field "(scalar type | ARRAY | RECORD | ACCESS | FILE)"))))
4791 (cond ((equal definition "ARRAY")
4792 (kill-word -1) (vhdl-array))
4793 ((equal definition "RECORD")
4794 (kill-word -1) (vhdl-record))
4795 ((equal definition "ACCESS")
4796 (insert " ") (vhdl-field "type" ";"))
4797 ((equal definition "FILE")
4798 (vhdl-insert-keyword " OF ") (vhdl-field "type" ";"))
4800 (vhdl-declaration-comment)
4804 "Insert a use clause."
4806 (vhdl-insert-keyword "USE ..ALL;")
4808 (if (equal (vhdl-field "library name") "")
4809 (progn (undo) (insert " "))
4811 (vhdl-field "package name")
4815 (defun vhdl-variable ()
4816 "Insert a variable declaration."
4818 (vhdl-insert-keyword "VARIABLE ")
4819 (let ((in-arglist (string-match "arglist"
4820 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4821 (if (not in-arglist)
4822 (let ((opoint (point)))
4824 (setq in-arglist (looking-at ".*("))
4825 (goto-char opoint)))
4826 (if (equal (vhdl-field "names") "")
4830 (progn (vhdl-field "direction")
4835 (let ((position (point)))
4837 (if (equal (vhdl-field "[initialization]" ";") "")
4838 (progn (goto-char position) (kill-line) (insert ";")))
4839 (vhdl-declaration-comment))
4843 "Insert a wait statement."
4845 (vhdl-insert-keyword "WAIT ")
4846 (if (equal (vhdl-field
4847 "[ON sensitivity list] [UNTIL condition] [FOR time expression]")
4854 "Indent correctly if within a case statement."
4856 (let ((position (point))
4858 (if (and (= (current-column) (current-indentation))
4859 (re-search-forward "\\<end\\>" nil t)
4860 (looking-at "\\s-*\\<case\\>"))
4862 (setq margin (current-indentation))
4863 (goto-char position)
4864 (delete-horizontal-space)
4865 (indent-to (+ margin vhdl-basic-offset)))
4866 (goto-char position)
4868 (vhdl-insert-keyword "WHEN ")
4871 (defun vhdl-while-loop ()
4872 "Insert a while loop template."
4874 (let ((position (point)))
4875 (vhdl-insert-keyword " : WHILE ")
4876 (goto-char position))
4877 (let* ((margin (current-column))
4878 (name (vhdl-field "[label]"))
4879 (named (not (string-equal name ""))))
4880 (if (not named) (delete-char 3))
4882 (if vhdl-conditions-in-parenthesis (insert "("))
4883 (if (equal (vhdl-field "condition") "")
4885 (if vhdl-conditions-in-parenthesis (insert ")"))
4886 (vhdl-insert-keyword " LOOP\n\n")
4888 (vhdl-insert-keyword "END LOOP")
4889 (insert (if named (concat " " name ";") ?\;))
4891 (indent-to (+ margin vhdl-basic-offset))
4895 "Insert a with statement (i.e. selected signal assignment)."
4897 (vhdl-selected-signal-assignment)
4900 ;; ############################################################################
4903 (defun vhdl-clocked-wait ()
4904 "Insert a wait statement for rising clock edge."
4906 (vhdl-insert-keyword "WAIT UNTIL ")
4907 (let* ((clock (vhdl-field "clock name")))
4909 (vhdl-insert-keyword " AND ")
4911 (insert " = " vhdl-one-string ";")
4914 (defun vhdl-clock-async-reset (clock reset)
4915 "Insert a template reacting on asynchronous reset and rising clock edge
4916 for inside a memorizing processes."
4918 (let* ( (margin (current-column))
4920 (if vhdl-self-insert-comments
4921 (insert "-- activities triggered by asynchronous reset (active low)\n"))
4923 (vhdl-insert-keyword "IF ")
4924 (insert reset " = " vhdl-zero-string)
4925 (vhdl-insert-keyword " THEN\n")
4926 (indent-to (+ margin vhdl-basic-offset))
4927 (setq opoint (point))
4930 (if vhdl-self-insert-comments
4931 (insert "-- activities triggered by rising edge of clock\n"))
4933 (vhdl-insert-keyword "ELSIF ")
4934 (insert clock "'event")
4935 (vhdl-insert-keyword " AND ")
4936 (insert clock " = " vhdl-one-string)
4937 (vhdl-insert-keyword " THEN\n")
4938 (indent-to (+ margin vhdl-basic-offset))
4941 (vhdl-insert-keyword "END IF;")
4942 ; (if vhdl-self-insert-comments (insert " -- " clock))
4946 (defun vhdl-standard-package (library package)
4947 "Insert specification of a standard package."
4949 (let ((margin (current-column)))
4950 (vhdl-insert-keyword "LIBRARY ")
4951 (insert library ";\n")
4953 (vhdl-insert-keyword "USE ")
4954 (insert library "." package)
4955 (vhdl-insert-keyword ".ALL;")
4958 (defun vhdl-package-numeric-bit ()
4959 "Insert specification of 'numeric_bit' package."
4961 (vhdl-standard-package "ieee" "numeric_bit"))
4963 (defun vhdl-package-numeric-std ()
4964 "Insert specification of 'numeric_std' package."
4966 (vhdl-standard-package "ieee" "numeric_std"))
4968 (defun vhdl-package-std-logic-1164 ()
4969 "Insert specification of 'std_logic_1164' package."
4971 (vhdl-standard-package "ieee" "std_logic_1164"))
4973 (defun vhdl-package-textio ()
4974 "Insert specification of 'textio' package."
4976 (vhdl-standard-package "std" "textio"))
4978 ;; ############################################################################
4979 ;; Comment functions
4981 (defun vhdl-comment-indent ()
4982 (let* ((opoint (point))
4985 (if (re-search-forward "--" opoint t)
4986 (- (current-column) 2) ;Existing comment at bol stays there.
4988 (skip-chars-backward " \t")
4989 (max comment-column ;else indent to comment column
4990 (1+ (current-column))) ;except leave at least one space.
4996 (defun vhdl-inline-comment ()
4997 "Start a comment at the end of the line.
4998 if on line with code, indent at least comment-column.
4999 if starting after end-comment-column, start a new line."
5001 (if (> (current-column) end-comment-column) (newline-and-indent))
5002 (if (or (looking-at "\\s-*$") ;end of line
5003 (and (not unread-command-events) ; called with key binding or menu
5004 (not (end-of-line))))
5006 (while (= (preceding-char) ?-) (delete-char -1))
5007 (setq margin (current-column))
5008 (delete-horizontal-space)
5010 (progn (indent-to margin) (insert "--"))
5012 (indent-to comment-column)
5014 (if (not unread-command-events) (insert " ")))
5015 ; else code following current point implies commenting out code
5016 (let (next-input code)
5017 (while (= (preceding-char) ?-) (delete-char -2))
5018 (while (= (setq next-input (read-char)) 13) ; CR
5019 (insert "--"); or have a space after it?
5022 (message "Enter CR if commenting out a line of code.")
5025 (if (not code) (progn
5026 ; (indent-to comment-column)
5027 (insert "--") ;hardwire to 1 space or use vhdl-basic-offset?
5029 (setq unread-command-events
5030 (list (vhdl-character-to-event-hack next-input))) ;pushback the char
5033 (defun vhdl-display-comment (&optional line-exists)
5034 "Add 2 comment lines at the current indent, making a display comment."
5036 (if (not line-exists)
5037 (vhdl-display-comment-line))
5038 (let* ((col (current-column))
5039 (len (- end-comment-column col)))
5042 (insert-char ?- len)
5050 (defun vhdl-display-comment-line ()
5051 "Displays one line of dashes."
5053 (while (= (preceding-char) ?-) (delete-char -2))
5054 (let* ((col (current-column))
5055 (len (- end-comment-column col)))
5056 (insert-char ?- len)
5061 (defun vhdl-declaration-comment ()
5062 (if vhdl-prompt-for-comments
5063 (let ((position (point)))
5065 (indent-to comment-column)
5067 (if (equal (vhdl-field "comment") "")
5068 (progn (goto-char position) (kill-line))
5071 (defun vhdl-block-comment ()
5072 (if vhdl-prompt-for-comments
5073 (let ((finalline (vhdl-current-line))
5074 (case-fold-search t))
5075 (beginning-of-line -0)
5076 (if (re-search-backward "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\)\\>" nil t)
5078 (back-to-indentation)
5079 (setq margin (current-column))
5083 (insert "-- purpose: ")
5084 (if (equal (vhdl-field "description") "")
5085 (vhdl-kill-entire-line)
5086 (setq finalline (+ finalline 1)))))
5087 (goto-line finalline)
5091 (defun vhdl-comment-uncomment-region (beg end &optional arg)
5092 "Comment out region if not commented out, uncomment out region if already
5094 (interactive "r\nP")
5096 (if (looking-at comment-start)
5097 (comment-region beg end -1)
5098 (comment-region beg end)
5101 ;; ############################################################################
5104 (defun vhdl-outer-space (count)
5105 "Expand abbreviations and self-insert space(s), do indent-new-comment-line
5106 if in comment and past end-comment-column."
5108 (if (or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
5109 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
5111 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
5113 (if (not vhdl-underscore-is-part-of-word)
5114 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
5116 (if (not (vhdl-in-comment-p))
5117 (self-insert-command count)
5118 (if (< (current-column) end-comment-column)
5119 (self-insert-command count)
5120 (while (> (current-column) end-comment-column) (forward-word -1))
5121 (while (> (preceding-char) ? ) (forward-word -1))
5122 (delete-horizontal-space)
5123 (indent-new-comment-line)
5125 (insert-char ? count)
5128 (defun vhdl-field (prompt &optional following-string)
5129 "Prompt for string and insert it in buffer with optional following-string."
5130 (let ((opoint (point)))
5131 (insert "<" prompt ">")
5132 (let ((string (read-from-minibuffer (concat prompt ": ") ""
5133 vhdl-minibuffer-local-map)))
5134 (delete-region opoint (point))
5135 (insert string (or following-string ""))
5136 (if vhdl-upper-case-keywords
5137 (vhdl-fix-case-region-1
5138 opoint (point) t vhdl-93-keywords-regexp))
5142 (defun vhdl-in-comment-p ()
5143 "Check if point is to right of beginning comment delimiter."
5145 (let ((opoint (point)))
5146 (save-excursion ; finds an unquoted comment
5148 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" opoint t)
5151 (defun vhdl-in-string-p ()
5152 "Check if point is in a string."
5154 (let ((opoint (point)))
5155 (save-excursion ; preceeded by odd number of string delimiters?
5159 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*" opoint t))
5162 (defun vhdl-begin-end (list)
5163 "Insert a begin ... end pair with optional name after the end.
5164 Point is left between them."
5167 (margin (cdr list)))
5168 (if vhdl-additional-empty-lines
5171 (indent-to (+ margin vhdl-basic-offset))))
5174 (vhdl-insert-keyword "BEGIN")
5175 (if vhdl-self-insert-comments
5176 (insert (and name (concat " -- " name))))
5178 (indent-to (+ margin vhdl-basic-offset))
5179 (setq return (point))
5182 (vhdl-insert-keyword "END")
5183 (insert (and name (concat " " name)) ";")
5187 (defun vhdl-get-arg-list ()
5188 "Read from user a procedure or function argument list."
5190 (let ((margin (current-column)))
5191 (if (not vhdl-argument-list-indent)
5192 (let ((opoint (point)))
5193 (back-to-indentation)
5194 (setq margin (+ (current-column) vhdl-basic-offset))
5197 (indent-to margin)))
5198 (let (not-empty interface)
5199 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
5200 (if (not (equal interface ""))
5202 (while (not (string-equal (vhdl-field "[names]") ""))
5205 (if (not (equal (vhdl-field "[direction]") ""))
5207 (vhdl-field "type" ";\n")
5209 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
5210 (if (not (equal interface ""))
5213 (progn (kill-line -0)
5215 (if (not vhdl-argument-list-indent)
5216 (progn (insert "\n") (indent-to margin)))
5218 (if vhdl-argument-list-indent
5219 (backward-delete-char 2)
5221 (backward-delete-char 3)))
5222 ; (while (string-match "[,;]$" args)
5224 ; (indent-to margin) (setq args (vhdl-field "next argument")))
5225 ; (insert 41) ;close-paren
5228 (defun vhdl-get-port (optional &optional no-comment)
5229 "Read from user a port spec argument list."
5230 (let ((margin (current-column))
5232 (if (not vhdl-argument-list-indent)
5233 (let ((opoint (point)))
5234 (back-to-indentation)
5235 (setq margin (+ (current-column) vhdl-basic-offset))
5238 (indent-to margin)))
5239 (let ((vhdl-ports (vhdl-field "[names]")))
5240 (if (string-equal vhdl-ports "")
5242 (progn (vhdl-kill-entire-line) (forward-line -1)
5243 (if (not vhdl-argument-list-indent)
5244 (progn (vhdl-kill-entire-line) (forward-line -1))))
5245 (progn (undo) (insert " "))
5249 (let ((semicolon-pos))
5250 (while (not (string-equal "" vhdl-ports))
5251 (vhdl-field "direction")
5254 (setq semicolon-pos (point))
5256 (if (not no-comment)
5257 (vhdl-declaration-comment))
5260 (setq vhdl-ports (vhdl-field "[names]" " : ")))
5261 (goto-char semicolon-pos)
5262 (if (not vhdl-argument-list-indent)
5263 (progn (delete-char 1) (end-of-line) (insert "\n")
5264 (indent-to margin) (insert ";") (backward-char 1)))
5267 (if (= (following-char) ? )
5270 (vhdl-kill-entire-line)
5272 (if vhdl-auto-align (vhdl-align start (point) 1))
5275 (defun vhdl-get-generic (optional &optional no-value )
5276 "Read from user a generic spec argument list."
5277 (let ((margin (current-column))
5279 (if (not vhdl-argument-list-indent)
5280 (let ((opoint (point)))
5281 (back-to-indentation)
5282 (setq margin (+ (current-column) vhdl-basic-offset))
5285 (indent-to margin)))
5286 (let ((vhdl-generic))
5288 (setq vhdl-generic (vhdl-field "[names]"))
5289 (setq vhdl-generic (vhdl-field "[name]")))
5290 (if (string-equal vhdl-generic "")
5292 (progn (vhdl-kill-entire-line) (end-of-line -0)
5293 (if (not vhdl-argument-list-indent)
5294 (progn (vhdl-kill-entire-line) (end-of-line -0))))
5295 (progn (undo) (insert " "))
5299 (let ((semicolon-pos))
5300 (while (not(string-equal "" vhdl-generic))
5303 (progn (setq semicolon-pos (point))
5306 (if (equal (vhdl-field "[value]") "")
5308 (setq semicolon-pos (point))
5310 (vhdl-declaration-comment))
5314 (setq vhdl-generic (vhdl-field "[names]" " : "))
5315 (setq vhdl-generic (vhdl-field "[name]" " : "))))
5316 (goto-char semicolon-pos)
5317 (if (not vhdl-argument-list-indent)
5318 (progn (delete-char 1) (end-of-line) (insert "\n")
5319 (indent-to margin) (insert ";") (backward-char 1)))
5322 (if (= (following-char) ? )
5325 (vhdl-kill-entire-line)
5327 (if vhdl-auto-align (vhdl-align start (point) 1))
5330 (defun vhdl-insert-date ()
5331 "Insert date in appropriate format."
5335 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
5336 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
5337 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
5340 (defun vhdl-insert-keyword (keyword)
5341 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
5344 (defun vhdl-case-keyword (keyword)
5345 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))
5348 (defun vhdl-case-word (num)
5349 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num))
5352 (defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
5353 "Convert all words matching word-regexp in region to lower or upper case,
5354 depending on parameter upper-case."
5355 (let ((case-fold-search t)
5358 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
5361 (while (re-search-forward word-regexp end t)
5362 (or (vhdl-in-comment-p)
5366 (downcase-word -1)))
5368 (/= busy-counter (setq busy-counter
5369 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg))))))
5370 (message (format "Fixing case ... (%2d%s)" busy-counter "%%"))))
5372 (if (not vhdl-underscore-is-part-of-word)
5373 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
5377 (defun vhdl-fix-case-region (beg end &optional arg)
5378 "Convert all VHDL words in region to lower or upper case, depending on
5379 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
5380 (interactive "r\nP")
5381 (vhdl-fix-case-region-1
5382 beg end vhdl-upper-case-keywords vhdl-93-keywords-regexp 0)
5383 (vhdl-fix-case-region-1
5384 beg end vhdl-upper-case-types vhdl-93-types-regexp 1)
5385 (vhdl-fix-case-region-1
5386 beg end vhdl-upper-case-attributes vhdl-93-attributes-regexp 2)
5387 (vhdl-fix-case-region-1
5388 beg end vhdl-upper-case-enum-values vhdl-93-enum-values-regexp 3)
5391 (defun vhdl-fix-case-buffer ()
5392 "Convert all VHDL words in buffer to lower or upper case, depending on
5393 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
5395 (vhdl-fix-case-region (point-min) (point-max))
5398 (defun vhdl-minibuffer-tab (&optional prefix-arg)
5399 "If preceeding character is part of a word then dabbrev-expand,
5400 else if right of non whitespace on line then tab-to-tab-stop,
5401 else indent line in proper way for current major mode
5402 (used for word completion in VHDL minibuffer)."
5404 (cond ((= (char-syntax (preceding-char)) ?w)
5405 (let ((case-fold-search nil)) (dabbrev-expand prefix-arg)))
5406 ((> (current-column) (current-indentation))
5409 (if (eq indent-line-function 'indent-to-left-margin)
5410 (insert-tab prefix-arg)
5412 (funcall indent-line-function prefix-arg)
5413 (funcall indent-line-function))))))
5416 "Display help information in '*Help*' buffer ."
5418 (with-output-to-temp-buffer "*Help*"
5421 (princ (documentation major-mode))
5423 (set-buffer standard-output)
5425 (print-help-return-message)))
5427 (defun vhdl-current-line ()
5428 "Return the line number of the line containing point."
5433 (1+ (count-lines 1 (point)))))
5436 (defun vhdl-kill-entire-line ()
5437 "Delete entire line."
5444 (defun vhdl-open-line ()
5445 "Open a new line and indent."
5448 (newline-and-indent)
5451 (defun vhdl-kill-line ()
5452 "Kill current line."
5454 (vhdl-kill-entire-line)
5457 (defun vhdl-character-to-event-hack (char)
5458 (if (memq 'XEmacs vhdl-emacs-features)
5459 (character-to-event char)
5462 ;; ############################################################################
5465 (defun vhdl-electric-mode ()
5466 "Toggle VHDL Electric mode."
5468 (setq vhdl-electric-mode (not vhdl-electric-mode))
5469 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
5470 (force-mode-line-update)
5473 (defun vhdl-stutter-mode ()
5474 "Toggle VHDL Stuttering mode."
5476 (setq vhdl-stutter-mode (not vhdl-stutter-mode))
5479 (defun vhdl-hooked-abbrev (fun)
5480 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
5481 but not if inside a comment or quote)"
5482 (if (or (vhdl-in-comment-p)
5484 (save-excursion (forward-word -1)
5485 (and (looking-at "\\<end\\>")
5486 (not (looking-at "\\<end;")))))
5491 (if (not vhdl-electric-mode)
5499 (let ((invoke-char last-command-char) (abbrev-mode -1))
5501 (if (= invoke-char ?-) (setq abbrev-start-location (point)))
5502 ;; delete CR which is still in event queue
5503 (if (memq 'XEmacs vhdl-emacs-features)
5504 (enqueue-eval-event 'delete-char -1)
5505 (setq unread-command-events ; push back a delete char
5506 (list (vhdl-character-to-event-hack ?\177))))
5509 (defun vhdl-alias-hook () "hooked version of vhdl-alias."
5510 (vhdl-hooked-abbrev 'vhdl-alias))
5511 (defun vhdl-architecture-hook () "hooked version of vhdl-architecture."
5512 (vhdl-hooked-abbrev 'vhdl-architecture))
5513 (defun vhdl-array-hook () "hooked version of vhdl-array."
5514 (vhdl-hooked-abbrev 'vhdl-array))
5515 (defun vhdl-assert-hook () "hooked version of vhdl-assert."
5516 (vhdl-hooked-abbrev 'vhdl-assert))
5517 (defun vhdl-attribute-hook () "hooked version of vhdl-attribute."
5518 (vhdl-hooked-abbrev 'vhdl-attribute))
5519 (defun vhdl-block-hook () "hooked version of vhdl-block."
5520 (vhdl-hooked-abbrev 'vhdl-block))
5521 (defun vhdl-case-hook () "hooked version of vhdl-case."
5522 (vhdl-hooked-abbrev 'vhdl-case))
5523 (defun vhdl-component-hook () "hooked version of vhdl-component."
5524 (vhdl-hooked-abbrev 'vhdl-component))
5525 (defun vhdl-component-instance-hook ()
5526 "hooked version of vhdl-component-instance."
5527 (vhdl-hooked-abbrev 'vhdl-component-instance))
5528 (defun vhdl-concurrent-signal-assignment-hook ()
5529 "hooked version of vhdl-concurrent-signal-assignment."
5530 (vhdl-hooked-abbrev 'vhdl-concurrent-signal-assignment))
5531 (defun vhdl-configuration-hook ()
5532 "hooked version of vhdl-configuration."
5533 (vhdl-hooked-abbrev 'vhdl-configuration))
5534 (defun vhdl-constant-hook () "hooked version of vhdl-constant."
5535 (vhdl-hooked-abbrev 'vhdl-constant))
5536 (defun vhdl-disconnect-hook () "hooked version of vhdl-disconnect."
5537 (vhdl-hooked-abbrev 'vhdl-disconnect))
5538 (defun vhdl-display-comment-hook () "hooked version of vhdl-display-comment."
5539 (vhdl-hooked-abbrev 'vhdl-display-comment))
5540 (defun vhdl-else-hook () "hooked version of vhdl-else."
5541 (vhdl-hooked-abbrev 'vhdl-else))
5542 (defun vhdl-elsif-hook () "hooked version of vhdl-elsif."
5543 (vhdl-hooked-abbrev 'vhdl-elsif))
5544 (defun vhdl-entity-hook () "hooked version of vhdl-entity."
5545 (vhdl-hooked-abbrev 'vhdl-entity))
5546 (defun vhdl-exit-hook () "hooked version of vhdl-exit."
5547 (vhdl-hooked-abbrev 'vhdl-exit))
5548 (defun vhdl-for-hook () "hooked version of vhdl-for."
5549 (vhdl-hooked-abbrev 'vhdl-for))
5550 (defun vhdl-function-hook () "hooked version of vhdl-function."
5551 (vhdl-hooked-abbrev 'vhdl-function))
5552 (defun vhdl-generate-hook () "hooked version of vhdl-generate."
5553 (vhdl-hooked-abbrev 'vhdl-generate))
5554 (defun vhdl-generic-hook () "hooked version of vhdl-generic."
5555 (vhdl-hooked-abbrev 'vhdl-generic))
5556 (defun vhdl-library-hook () "hooked version of vhdl-library."
5557 (vhdl-hooked-abbrev 'vhdl-library))
5558 (defun vhdl-header-hook () "hooked version of vhdl-header."
5559 (vhdl-hooked-abbrev 'vhdl-header))
5560 (defun vhdl-if-hook () "hooked version of vhdl-if."
5561 (vhdl-hooked-abbrev 'vhdl-if))
5562 (defun vhdl-loop-hook () "hooked version of vhdl-loop."
5563 (vhdl-hooked-abbrev 'vhdl-loop))
5564 (defun vhdl-map-hook () "hooked version of vhdl-map."
5565 (vhdl-hooked-abbrev 'vhdl-map))
5566 (defun vhdl-modify-hook () "hooked version of vhdl-modify."
5567 (vhdl-hooked-abbrev 'vhdl-modify))
5568 (defun vhdl-next-hook () "hooked version of vhdl-next."
5569 (vhdl-hooked-abbrev 'vhdl-next))
5570 (defun vhdl-package-hook () "hooked version of vhdl-package."
5571 (vhdl-hooked-abbrev 'vhdl-package))
5572 (defun vhdl-port-hook () "hooked version of vhdl-port."
5573 (vhdl-hooked-abbrev 'vhdl-port))
5574 (defun vhdl-procedure-hook () "hooked version of vhdl-procedure."
5575 (vhdl-hooked-abbrev 'vhdl-procedure))
5576 (defun vhdl-process-hook () "hooked version of vhdl-process."
5577 (vhdl-hooked-abbrev 'vhdl-process))
5578 (defun vhdl-record-hook () "hooked version of vhdl-record."
5579 (vhdl-hooked-abbrev 'vhdl-record))
5580 (defun vhdl-return-hook () "hooked version of vhdl-return-value."
5581 (vhdl-hooked-abbrev 'vhdl-return-value))
5582 (defun vhdl-selected-signal-assignment-hook ()
5583 "hooked version of vhdl-selected-signal-assignment."
5584 (vhdl-hooked-abbrev 'vhdl-selected-signal-assignment))
5585 (defun vhdl-signal-hook () "hooked version of vhdl-signal."
5586 (vhdl-hooked-abbrev 'vhdl-signal))
5587 (defun vhdl-subtype-hook () "hooked version of vhdl-subtype."
5588 (vhdl-hooked-abbrev 'vhdl-subtype))
5589 (defun vhdl-type-hook () "hooked version of vhdl-type."
5590 (vhdl-hooked-abbrev 'vhdl-type))
5591 (defun vhdl-use-hook () "hooked version of vhdl-use."
5592 (vhdl-hooked-abbrev 'vhdl-use))
5593 (defun vhdl-variable-hook () "hooked version of vhdl-variable."
5594 (vhdl-hooked-abbrev 'vhdl-variable))
5595 (defun vhdl-wait-hook () "hooked version of vhdl-wait."
5596 (vhdl-hooked-abbrev 'vhdl-wait))
5597 (defun vhdl-when-hook () "hooked version of vhdl-when."
5598 (vhdl-hooked-abbrev 'vhdl-when))
5599 (defun vhdl-while-loop-hook () "hooked version of vhdl-while-loop."
5600 (vhdl-hooked-abbrev 'vhdl-while-loop))
5601 (defun vhdl-and-hook () "hooked version of vhdl-and."
5602 (vhdl-hooked-abbrev 'vhdl-and))
5603 (defun vhdl-or-hook () "hooked version of vhdl-or."
5604 (vhdl-hooked-abbrev 'vhdl-or))
5605 (defun vhdl-nand-hook () "hooked version of vhdl-nand."
5606 (vhdl-hooked-abbrev 'vhdl-nand))
5607 (defun vhdl-nor-hook () "hooked version of vhdl-nor."
5608 (vhdl-hooked-abbrev 'vhdl-nor))
5609 (defun vhdl-xor-hook () "hooked version of vhdl-xor."
5610 (vhdl-hooked-abbrev 'vhdl-xor))
5611 (defun vhdl-xnor-hook () "hooked version of vhdl-xnor."
5612 (vhdl-hooked-abbrev 'vhdl-xnor))
5613 (defun vhdl-not-hook () "hooked version of vhdl-not."
5614 (vhdl-hooked-abbrev 'vhdl-not))
5616 (defun vhdl-default-hook () "hooked version of vhdl-default."
5617 (vhdl-hooked-abbrev 'vhdl-default))
5618 (defun vhdl-default-indent-hook () "hooked version of vhdl-default-indent."
5619 (vhdl-hooked-abbrev 'vhdl-default-indent))
5622 ;; ############################################################################
5624 ;; ############################################################################
5625 ;; (using `font-lock.el')
5627 ;; ############################################################################
5628 ;; Syntax definitions
5630 (defvar vhdl-font-lock-keywords nil
5631 "Regular expressions to highlight in VHDL Mode.")
5633 (defconst vhdl-font-lock-keywords-0
5635 ;; highlight template prompts
5636 '("\\(^\\|[ (.\t]\\)\\(<[^ =].*[^ =]>\\)\\([ .]\\|$\\)"
5637 2 vhdl-font-lock-prompt-face)
5639 ;; highlight character literals
5640 '("'\\(.\\)'" 1 'font-lock-string-face)
5642 "For consideration as a value of `vhdl-font-lock-keywords'.
5643 This does highlighting of template prompts and character literals.")
5645 (defconst vhdl-font-lock-keywords-1
5647 ;; highlight names of units, subprograms, and components when declared
5651 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
5652 "function\\|procedure\\|component"
5653 "\\)\\s-+\\(\\w+\\)")
5654 3 'font-lock-function-name-face)
5656 ;; highlight labels of common constructs
5659 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\("
5660 "assert\\|block\\|case\\|exit\\|for\\|if\\|loop\\|"
5661 "next\\|null\\|process\\| with\\|while\\|"
5662 "\\w+\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map"
5664 1 'font-lock-function-name-face)
5666 ;; highlight entity names of architectures and configurations
5668 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
5669 2 'font-lock-function-name-face)
5671 ;; highlight names and labels at end of constructs
5675 "\\(block\\|case\\|component\\|for\\|generate\\|if\\|loop\\|"
5676 "process\\|record\\|units\\)\\>\\|"
5677 "\\)\\s-*\\(\\w*\\)")
5678 3 'font-lock-function-name-face)
5680 "For consideration as a value of `vhdl-font-lock-keywords'.
5681 This does highlighting of names and labels.")
5683 (defconst vhdl-font-lock-keywords-2
5685 ;; highlight keywords, and types, standardized attributes, enumeration values
5686 (list (concat "'" vhdl-93-attributes-regexp)
5687 1 'vhdl-font-lock-attribute-face)
5688 (list vhdl-93-types-regexp 1 'font-lock-type-face)
5689 (list vhdl-93-enum-values-regexp 1 'vhdl-font-lock-value-face)
5690 (list vhdl-93-keywords-regexp 1 'font-lock-keyword-face)
5692 "For consideration as a value of `vhdl-font-lock-keywords'.
5693 This does highlighting of comments, keywords, and standard types.")
5695 (defconst vhdl-font-lock-keywords-3
5697 ;; highlight clock signals.
5698 (cons vhdl-clock-signal-syntax 'vhdl-font-lock-clock-signal-face)
5699 (cons vhdl-reset-signal-syntax 'vhdl-font-lock-reset-signal-face)
5700 (cons vhdl-control-signal-syntax 'vhdl-font-lock-control-signal-face)
5701 (cons vhdl-data-signal-syntax 'vhdl-font-lock-data-signal-face)
5702 (cons vhdl-test-signal-syntax 'vhdl-font-lock-test-signal-face)
5704 "For consideration as a value of `vhdl-font-lock-keywords'.
5705 This does highlighting of signal names with specific syntax.")
5707 ;; ############################################################################
5708 ;; Font and color definitions
5710 (defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
5711 "Face name to use for prompts.")
5713 (defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
5714 "Face name to use for attributes.")
5716 (defvar vhdl-font-lock-value-face 'vhdl-font-lock-value-face
5717 "Face name to use for enumeration values.")
5719 (defvar vhdl-font-lock-clock-signal-face 'vhdl-font-lock-clock-signal-face
5720 "Face name to use for clock signals.")
5722 (defvar vhdl-font-lock-reset-signal-face 'vhdl-font-lock-reset-signal-face
5723 "Face name to use for reset signals.")
5725 (defvar vhdl-font-lock-control-signal-face 'vhdl-font-lock-control-signal-face
5726 "Face name to use for control signals.")
5728 (defvar vhdl-font-lock-data-signal-face 'vhdl-font-lock-data-signal-face
5729 "Face name to use for data signals.")
5731 (defvar vhdl-font-lock-test-signal-face 'vhdl-font-lock-test-signal-face
5732 "Face name to use for test signals.")
5734 (defface vhdl-font-lock-prompt-face
5735 '((((class color) (background light)) (:foreground "Red"))
5736 (((class color) (background dark)) (:foreground "Red"))
5737 (t (:inverse-video t)))
5738 "Font Lock mode face used to highlight prompts."
5739 :group 'font-lock-highlighting-faces)
5741 (defface vhdl-font-lock-attribute-face
5742 '((((class color) (background light)) (:foreground "CadetBlue"))
5743 (((class color) (background dark)) (:foreground "CadetBlue"))
5744 (t (:italic t :bold t)))
5745 "Font Lock mode face used to highlight attributes."
5746 :group 'font-lock-highlighting-faces)
5748 (defface vhdl-font-lock-value-face
5749 '((((class color) (background light)) (:foreground "DarkGoldenrod"))
5750 (((class color) (background dark)) (:foreground "DarkGoldenrod"))
5751 (t (:italic t :bold t)))
5752 "Font Lock mode face used to highlight enumeration values."
5753 :group 'font-lock-highlighting-faces)
5755 (defface vhdl-font-lock-clock-signal-face
5756 '((((class color) (background light)) (:foreground "LimeGreen"))
5757 (((class color) (background dark)) (:foreground "LimeGreen"))
5759 "Font Lock mode face used to highlight clock signals."
5760 :group 'font-lock-highlighting-faces)
5762 (defface vhdl-font-lock-reset-signal-face
5763 '((((class color) (background light)) (:foreground "Red"))
5764 (((class color) (background dark)) (:foreground "Red"))
5766 "Font Lock mode face used to highlight reset signals."
5767 :group 'font-lock-highlighting-faces)
5769 (defface vhdl-font-lock-control-signal-face
5770 '((((class color) (background light)) (:foreground "Blue"))
5771 (((class color) (background dark)) (:foreground "Blue"))
5773 "Font Lock mode face used to highlight control signals."
5774 :group 'font-lock-highlighting-faces)
5776 (defface vhdl-font-lock-data-signal-face
5777 '((((class color) (background light)) (:foreground "Black"))
5778 (((class color) (background dark)) (:foreground "Black"))
5780 "Font Lock mode face used to highlight data signals."
5781 :group 'font-lock-highlighting-faces)
5783 (defface vhdl-font-lock-test-signal-face
5784 '((((class color) (background light)) (:foreground "Gold"))
5785 (((class color) (background dark)) (:foreground "Gold"))
5787 "Font Lock mode face used to highlight test signals."
5788 :group 'font-lock-highlighting-faces)
5790 ;; Custom color definitions for existing faces
5791 (defun vhdl-set-face-foreground ()
5792 (set-face-foreground 'font-lock-comment-face "IndianRed")
5793 (set-face-foreground 'font-lock-function-name-face "MediumOrchid")
5794 (set-face-foreground 'font-lock-keyword-face "SlateBlue")
5795 (set-face-foreground 'font-lock-string-face "RosyBrown")
5796 (set-face-foreground 'font-lock-type-face "ForestGreen")
5799 (defun vhdl-set-face-grayscale ()
5801 (set-face-bold-p 'font-lock-comment-face nil)
5802 (set-face-inverse-video-p 'font-lock-comment-face nil)
5803 (set-face-italic-p 'font-lock-comment-face t)
5804 (set-face-underline-p 'font-lock-comment-face nil)
5806 (set-face-bold-p 'font-lock-function-name-face nil)
5807 (set-face-inverse-video-p 'font-lock-function-name-face nil)
5808 (set-face-italic-p 'font-lock-function-name-face t)
5809 (set-face-underline-p 'font-lock-function-name-face nil)
5811 (set-face-bold-p 'font-lock-keyword-face t)
5812 (set-face-inverse-video-p 'font-lock-keyword-face nil)
5813 (set-face-italic-p 'font-lock-keyword-face nil)
5814 (set-face-underline-p 'font-lock-keyword-face nil)
5816 (set-face-bold-p 'font-lock-string-face nil)
5817 (set-face-inverse-video-p 'font-lock-string-face nil)
5818 (set-face-italic-p 'font-lock-string-face nil)
5819 (set-face-underline-p 'font-lock-string-face t)
5821 (set-face-bold-p 'font-lock-type-face t)
5822 (set-face-inverse-video-p 'font-lock-type-face nil)
5823 (set-face-italic-p 'font-lock-type-face t)
5824 (set-face-underline-p 'font-lock-type-face nil)
5827 ;; ############################################################################
5828 ;; Font lock initialization
5830 (defun vhdl-font-lock-init ()
5831 "Initializes fontification."
5832 (setq vhdl-font-lock-keywords
5833 (append vhdl-font-lock-keywords-0
5834 (if vhdl-highlight-names vhdl-font-lock-keywords-1)
5835 (if vhdl-highlight-keywords vhdl-font-lock-keywords-2)
5836 (if (and vhdl-highlight-signals (x-display-color-p))
5837 vhdl-font-lock-keywords-3)))
5838 (if (x-display-color-p)
5839 (if vhdl-customize-colors (vhdl-set-face-foreground))
5840 (if vhdl-customize-faces (vhdl-set-face-grayscale))
5843 ;; ############################################################################
5844 ;; Fontification for postscript printing
5846 (defun vhdl-ps-init ()
5847 "Initializes face and page settings for postscript printing."
5849 (unless (or (not vhdl-customize-faces)
5851 (set (make-local-variable 'ps-bold-faces)
5852 '(font-lock-keyword-face
5854 vhdl-font-lock-attribute-face
5855 vhdl-font-lock-value-face))
5856 (set (make-local-variable 'ps-italic-faces)
5857 '(font-lock-comment-face
5858 font-lock-function-name-face
5860 vhdl-font-lock-prompt-face
5861 vhdl-font-lock-attribute-face
5862 vhdl-font-lock-value-face))
5863 (set (make-local-variable 'ps-underlined-faces)
5864 '(font-lock-string-face))
5866 ;; define page settings, so that a line containing 79 characters (default)
5867 ;; fits into one column
5868 (if vhdl-print-two-column
5870 (set (make-local-variable 'ps-landscape-mode) t)
5871 (set (make-local-variable 'ps-number-of-columns) 2)
5872 (set (make-local-variable 'ps-font-size) 7.0)
5873 (set (make-local-variable 'ps-header-title-font-size) 10.0)
5874 (set (make-local-variable 'ps-header-font-size) 9.0)
5875 (set (make-local-variable 'ps-header-offset) 12.0)
5876 (if (eq ps-paper-type 'letter)
5878 (set (make-local-variable 'ps-inter-column) 40.0)
5879 (set (make-local-variable 'ps-left-margin) 40.0)
5880 (set (make-local-variable 'ps-right-margin) 40.0)
5884 ;; ############################################################################
5886 ;; ############################################################################
5887 ;; (using `hideshow.el')
5889 (defun vhdl-forward-sexp-function (&optional count)
5890 "Find begin and end of VHDL process or block (for hideshow)."
5893 (case-fold-search t))
5896 (re-search-backward "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|block\\)\\>" nil t)
5897 (re-search-forward "\\s-*\\<end\\s-+\\(process\\|block\\)\\>" nil t)
5900 ;; Not needed `hs-special-modes-alist' is autoloaded.
5901 ;(require 'hideshow)
5903 (unless (assq 'vhdl-mode hs-special-modes-alist)
5904 (setq hs-special-modes-alist
5907 "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
5908 "\\s-*\\<\\(end\\|END\\)\\s-+\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
5910 vhdl-forward-sexp-function)
5911 hs-special-modes-alist)))
5914 ;; ############################################################################
5916 ;; ############################################################################
5917 ;; (using `compile.el')
5919 (defvar vhdl-compile-commands
5921 (cadence "cv -file" nil)
5922 (ikos "analyze" nil)
5923 (quickhdl "qvhcom" nil)
5924 (synopsys "vhdlan" nil)
5925 (vantage "analyze -libfile vsslib.ini -src" nil)
5926 (viewlogic "analyze -libfile vsslib.ini -src" nil)
5927 (v-system "vcom" "vmake > Makefile")
5929 "Commands to be called in the shell for compilation (syntax analysis) of a
5930 single buffer and `Makefile' generation for different tools. First item is tool
5931 identifier, second item is shell command for compilation, and third item is
5932 shell command for `Makefile' generation. A tool is specified by assigning a
5933 tool identifier to variable `vhdl-compiler'.")
5935 (defvar vhdl-compilation-error-regexp-alist
5937 ;; Cadence Design Systems: cv -file test.vhd
5938 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
5939 '("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2)
5941 ;; Ikos Voyager: analyze test.vhd
5942 ;; E L4/C5: this library unit is inaccessible
5943 ; Xemacs does not support error messages without included file name
5944 (if (not (memq 'XEmacs vhdl-emacs-features))
5945 '("E L\\([0-9]+\\)/C[0-9]+:" nil 1)
5946 '("E L\\([0-9]+\\)/C[0-9]+:" 2 1)
5949 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd
5950 ;; ERROR: test.vhd(24): near "dnd": expecting: END
5951 '("ERROR: \\(.+\\)(\\([0-9]+\\)):" 1 2)
5953 ;; Synopsys, VHDL Analyzer: vhdlan test.vhd
5954 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
5955 '("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2)
5957 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
5958 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
5959 ; Xemacs does not support error messages without included file name
5960 (if (not (memq 'XEmacs vhdl-emacs-features))
5961 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1)
5962 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 2 1)
5965 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
5966 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
5967 ;; same regexp as for Vantage
5969 ;; V-System, Model Technology: vcom test.vhd
5970 ;; ERROR: test.vhd(14): Unknown identifier: positiv
5971 ;; same regexp as for QuickHDL
5973 ) "Alist that specifies how to match errors in VHDL compiler output.")
5975 (defvar compilation-file-regexp-alist
5977 ;; Ikos Voyager: analyze -libfile vsslib.ini -src test.vhd
5978 ;; analyze sdrctl.vhd
5979 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2)
5981 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
5982 ;; Compiling "pcu.vhd" line 1...
5983 (" *Compiling \"\\(.+\\)\" " 1)
5985 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
5986 ;; Compiling "pcu.vhd" line 1...
5987 ;; same regexp as for Vantage
5989 ) "Alist specifying how to match lines that indicate a new current file.
5990 Used for compilers with no file name in the error messages.")
5992 (defun vhdl-compile ()
5993 "Compile current buffer using the VHDL compiler specified in
5996 (let ((command-list vhdl-compile-commands)
5999 (if (eq vhdl-compiler (car (car command-list)))
6000 (setq command (car (cdr (car command-list)))))
6001 (setq command-list (cdr command-list)))
6003 (compile (concat command " " vhdl-compiler-options
6004 (if (not (string-equal vhdl-compiler-options "")) " ")
6005 (file-name-nondirectory (buffer-file-name)))))))
6008 "Call make command for compilation of all updated source files
6009 (requires `Makefile')."
6013 (defun vhdl-generate-makefile ()
6014 "Generate new `Makefile'."
6016 (let ((command-list vhdl-compile-commands)
6019 (if (eq vhdl-compiler (car (car command-list)))
6020 (setq command (car (cdr (cdr (car command-list))))))
6021 (setq command-list (cdr command-list)))
6024 (message (format "Not implemented for `%s'!" vhdl-compiler))
6028 ;; ############################################################################
6030 ;; ############################################################################
6031 ;; (using `reporter.el')
6033 (defconst vhdl-version "3.19"
6034 "VHDL Mode version number.")
6036 (defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
6037 "Address for VHDL Mode bug reports.")
6039 (defun vhdl-version ()
6040 "Echo the current version of VHDL Mode in the minibuffer."
6042 (message "Using VHDL Mode version %s" vhdl-version)
6043 (vhdl-keep-region-active))
6045 ;; get reporter-submit-bug-report when byte-compiling
6046 (and (fboundp 'eval-when-compile)
6048 (require 'reporter)))
6050 (defun vhdl-submit-bug-report ()
6051 "Submit via mail a bug report on VHDL Mode."
6055 (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
6057 (reporter-submit-bug-report
6058 vhdl-mode-help-address
6059 (concat "VHDL Mode " vhdl-version)
6061 ;; report all important variables
6064 'vhdl-comment-only-line-offset
6068 'vhdl-indent-tabs-mode
6070 'vhdl-compiler-options
6071 'vhdl-upper-case-keywords
6072 'vhdl-upper-case-types
6073 'vhdl-upper-case-attributes
6074 'vhdl-upper-case-enum-values
6076 'vhdl-additional-empty-lines
6077 'vhdl-argument-list-indent
6078 'vhdl-conditions-in-parenthesis
6081 'vhdl-modify-date-prefix-string
6084 'vhdl-self-insert-comments
6085 'vhdl-prompt-for-comments
6086 'vhdl-comment-column
6087 'vhdl-end-comment-column
6088 'vhdl-highlight-names
6089 'vhdl-highlight-keywords
6090 'vhdl-highlight-signals
6091 'vhdl-highlight-case-sensitive
6092 'vhdl-customize-colors
6093 'vhdl-customize-faces
6094 'vhdl-clock-signal-syntax
6095 'vhdl-reset-signal-syntax
6096 'vhdl-control-signal-syntax
6097 'vhdl-data-signal-syntax
6098 'vhdl-test-signal-syntax
6099 'vhdl-source-file-menu
6102 'vhdl-print-two-column
6103 'vhdl-intelligent-tab
6104 'vhdl-template-key-binding-prefix
6105 'vhdl-word-completion-in-minibuffer
6106 'vhdl-underscore-is-part-of-word
6112 (if vhdl-special-indent-hook
6113 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
6114 "vhdl-special-indent-hook is set to '"
6115 (format "%s" vhdl-special-indent-hook)
6116 ".\nPerhaps this is your problem?\n"
6117 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
6119 (format "vhdl-emacs-features: %s\n" vhdl-emacs-features)
6122 "Dear VHDL Mode maintainers,"
6126 ;; ############################################################################
6128 (provide 'vhdl-mode)
6130 ;;; vhdl-mode.el ends here