aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Heuer1998-01-18 03:39:09 +0000
committerKarl Heuer1998-01-18 03:39:09 +0000
commitd2ddb974691b899deaf80e09f468ab04f186b8cc (patch)
tree3e463fb043cc034815dd1078a49dd8fd9bd67a97
parentd0ed5e526ec33c396e3b491d1cc93bdb7592652a (diff)
downloademacs-d2ddb974691b899deaf80e09f468ab04f186b8cc.tar.gz
emacs-d2ddb974691b899deaf80e09f468ab04f186b8cc.zip
Initial revision
-rw-r--r--lisp/progmodes/vhdl-mode.el6116
1 files changed, 6116 insertions, 0 deletions
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
new file mode 100644
index 00000000000..a79bf25232f
--- /dev/null
+++ b/lisp/progmodes/vhdl-mode.el
@@ -0,0 +1,6116 @@
1;;; vhdl-mode.el --- major mode for editing VHDL code
2
3;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
4
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
12
13;; This file is part of GNU Emacs.
14
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)
18;; any later version.
19
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.
24
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.
29
30;; ############################################################################
31;;; Commentary:
32;; ############################################################################
33
34;; This package provides an Emacs major mode for editing VHDL code.
35;; It includes the following features:
36
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 GNU Emacs and XEmacs
52
53;; ############################################################################
54;; Usage
55;; ############################################################################
56
57;; see below (comment in vhdl-mode function) or type `C-c C-h' in Emacs.
58
59;; ############################################################################
60;; Emacs Versions
61;; ############################################################################
62
63;; - Emacs 20
64;; - XEmacs 19.15
65;; - This version does not support Emacs 19 (use VHDL Mode 3.10 instead)
66
67
68;; ############################################################################
69;; Acknowledgements
70;; ############################################################################
71
72;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
73;; and Steve Grout
74
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>
78
79;; Many thanks to all the users who sent me bug reports and enhancement
80;; requests.
81;; Special thanks go to Dan Nicolaescu <done@ece.arizona.edu> for reviewing
82;; the code and for his valuable hints.
83
84;;; Code:
85
86;; ############################################################################
87;; User definable variables
88;; ############################################################################
89
90;; ############################################################################
91;; Variables for customization
92
93(defgroup vhdl nil
94 "Customizations for VHDL Mode."
95 :prefix "vhdl-"
96 :group 'languages)
97
98
99(defgroup vhdl-mode nil
100 "Customizations for modes."
101 :group 'vhdl)
102
103(defcustom vhdl-electric-mode t
104 "*If non-nil, electrification (automatic template generation) is enabled.
105If nil, template generators can still be invoked through key bindings
106and menu. Can be toggled by `\\[vhdl-electric-mode]'."
107 :type 'boolean
108 :group 'vhdl-mode)
109
110(defcustom vhdl-stutter-mode t
111 "*If non-nil, stuttering is enabled.
112Can be toggled by `\\[vhdl-stutter-mode]'."
113 :type 'boolean
114 :group 'vhdl-mode)
115
116(defcustom vhdl-indent-tabs-mode t
117 "*Indentation can insert tabs if this is non-nil.
118Overrides local variable `indent-tabs-mode'."
119 :type 'boolean
120 :group 'vhdl-mode)
121
122
123(defgroup vhdl-compile nil
124 "Customizations for compilation."
125 :group 'vhdl)
126
127(defcustom vhdl-compiler 'v-system
128 "*VHDL compiler to be used for syntax analysis.
129 cadence Cadence Design Systems (`cv -file')
130 ikos Ikos Voyager (`analyze')
131 quickhdl QuickHDL, Mentor Graphics (`qvhcom')
132 synopsys Synopsys, VHDL Analyzer (`vhdlan')
133 vantage Vantage Analysis Systems (`analyze -libfile vsslib.ini -src')
134 viewlogic Viewlogic (`analyze -libfile vsslib.ini -src')
135 v-system V-System, Model Technology (`vcom')
136For incorporation of additional compilers, please send me their command syntax
137and some example error messages."
138 :type '(choice
139 (const cadence)
140 (const ikos)
141 (const quickhdl)
142 (const synopsys)
143 (const vantage)
144 (const viewlogic)
145 (const v-system)
146 )
147 :group 'vhdl-compile)
148
149(defcustom vhdl-compiler-options ""
150 "*Options to be added to the compile command."
151 :type 'string
152 :group 'vhdl-compile)
153
154
155(defgroup vhdl-style nil
156 "Customizations for code styles."
157 :group 'vhdl)
158
159(defcustom vhdl-basic-offset 4
160 "*Amount of basic offset used for indentation.
161This value is used by + and - symbols in `vhdl-offsets-alist'."
162 :type 'integer
163 :group 'vhdl-style)
164
165
166(defgroup vhdl-word-case nil
167 "Customizations for case of VHDL words."
168 :group 'vhdl-style)
169
170(defcustom vhdl-upper-case-keywords nil
171 "*If non-nil, keywords are converted to upper case
172when typed or by the fix case functions."
173 :type 'boolean
174 :group 'vhdl-word-case)
175
176(defcustom vhdl-upper-case-types nil
177 "*If non-nil, standardized types are converted to upper case
178by the fix case functions."
179 :type 'boolean
180 :group 'vhdl-word-case)
181
182(defcustom vhdl-upper-case-attributes nil
183 "*If non-nil, standardized attributes are converted to upper case
184by the fix case functions."
185 :type 'boolean
186 :group 'vhdl-word-case)
187
188(defcustom vhdl-upper-case-enum-values nil
189 "*If non-nil, standardized enumeration values are converted to upper case
190by the fix case functions."
191 :type 'boolean
192 :group 'vhdl-word-case)
193
194
195(defgroup vhdl-electric nil
196 "Customizations for comments."
197 :group 'vhdl)
198
199(defcustom vhdl-auto-align nil
200 "*If non-nil, some templates are automatically aligned after generation."
201 :type 'boolean
202 :group 'vhdl-electric)
203
204(defcustom vhdl-additional-empty-lines t
205 "*If non-nil, additional empty lines are inserted in some templates.
206This improves readability of code."
207 :type 'boolean
208 :group 'vhdl-electric)
209
210(defcustom vhdl-argument-list-indent t
211 "*If non-nil, argument lists are indented relative to the opening paren.
212Normal indentation is applied otherwise."
213 :type 'boolean
214 :group 'vhdl-electric)
215
216(defcustom vhdl-conditions-in-parenthesis nil
217 "*If non-nil, parenthesis are placed around condition expressions."
218 :type 'boolean
219 :group 'vhdl-electric)
220
221(defcustom vhdl-date-format 'scientific
222 "*Specifies date format to be used in header.
223Date formats are:
224 american (09/17/1997)
225 european (17.09.1997)
226 scientific (1997/09/17)"
227 :type '(choice (const american)
228 (const european)
229 (const scientific))
230 :group 'vhdl-electric)
231
232(defcustom vhdl-header-file nil
233 "*Pathname/filename of the file to be inserted as header.
234If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
235if the header needs to be version controlled.
236
237The following keywords for template generation are supported:
238 <filename> : replaced by the name of the buffer
239 <author> : replaced by the user name and email address
240 <date> : replaced by the current date
241 <... string> : replaced by a prompted string (... is the prompt word)
242 <cursor> : final cursor position
243
244Example:
245 -----------------------------------------
246 -- Title : <title string>
247 -- File : <filename>
248 -- Author : <author>
249 -- Created : <date>
250 -- Description : <cursor>
251 -----------------------------------------"
252 :type 'string
253 :group 'vhdl-electric)
254
255(defcustom vhdl-modify-date-prefix-string "-- Last modified : "
256 "*Prefix string of modification date in VHDL file header.
257If actualization of the modification date is called (menu, `\\[vhdl-modify]'),
258this string is searched and the rest of the line replaced by the current date."
259 :type 'string
260 :group 'vhdl-electric)
261
262(defcustom vhdl-zero-string "'0'"
263 "*String to use for a logic zero."
264 :type 'string
265 :group 'vhdl-electric)
266
267(defcustom vhdl-one-string "'1'"
268 "*String to use for a logic one."
269 :type 'string
270 :group 'vhdl-electric)
271
272
273(defgroup vhdl-comment nil
274 "Customizations for comments."
275 :group 'vhdl-electric)
276
277(defcustom vhdl-self-insert-comments t
278 "*If non-nil, variables templates automatically insert help comments."
279 :type 'boolean
280 :group 'vhdl-comment)
281
282(defcustom vhdl-prompt-for-comments t
283 "*If non-nil, various templates prompt for user definable comments."
284 :type 'boolean
285 :group 'vhdl-comment)
286
287(defcustom vhdl-comment-column 40
288 "*Column to indent right-margin comments to.
289Overrides local variable `comment-column'."
290 :type 'integer
291 :group 'vhdl-comment)
292
293(defcustom vhdl-end-comment-column 79
294 "*End of comment column."
295 :type 'integer
296 :group 'vhdl-comment)
297
298(defvar end-comment-column 79
299 "*End of comment column.")
300
301
302(defgroup vhdl-highlight nil
303 "Customizations for highlighting."
304 :group 'vhdl)
305
306(defcustom vhdl-highlight-names t
307 "*If non-nil, unit names, subprogram names, and labels are highlighted."
308 :type 'boolean
309 :group 'vhdl-highlight)
310
311(defcustom vhdl-highlight-keywords t
312 "*If non-nil, VHDL keywords and other predefined words are highlighted.
313That is, keywords, predefined types, predefined attributes, and predefined
314enumeration values are highlighted."
315 :type 'boolean
316 :group 'vhdl-highlight)
317
318(defcustom vhdl-highlight-signals nil
319 "*If non-nil, signals of different classes are highlighted using colors.
320Signal classes are: clock, reset, status/control, data, and test."
321 :type 'boolean
322 :group 'vhdl-highlight)
323
324(defcustom vhdl-highlight-case-sensitive nil
325 "*If non-nil, case is considered for highlighting.
326Possible trade-off:
327 non-nil also upper-case VHDL words are highlighted, but case of signal names
328 is not considered (may lead to highlighting of unwanted words),
329 nil only lower-case VHDL words are highlighted, but case of signal names
330 is considered.
331Overrides local variable `font-lock-keywords-case-fold-search'."
332 :type 'boolean
333 :group 'vhdl-highlight)
334
335(defcustom vhdl-use-default-colors nil
336 "*If non-nil, the default colors are taken for syntax highlighting.
337If nil, all colors are customized in VHDL Mode for better matching with the
338additional signal colors."
339 :type 'boolean
340 :group 'vhdl-highlight)
341
342(defcustom vhdl-use-default-faces nil
343 "*If non-nil, the default faces are taken for syntax highlighting.
344If nil, all faces are customized for better matching with the additional faces
345used in VHDL Mode. This variable comes only into effect if no colors are used
346for highlighting or printing (i.e. variable `ps-print-color-p' is nil)."
347 :type 'boolean
348 :group 'vhdl-highlight)
349
350
351(defgroup vhdl-signal-syntax nil
352 "Customizations of signal syntax for highlighting."
353 :group 'vhdl-highlight)
354
355(defcustom vhdl-signal-syntax-doc-string "
356Must be of the form \"\\ \<\\\(...\\\)\\\>\", where ... specifies the actual syntax.
357 (delete this space ^ , it's only a workaround to get this doc string.)
358The basic regexp elements are:
359 [A-Z] any upper case letter
360 [A-Za-z] any letter
361 [0-9] any digit
362 \\w any letter or digit (corresponds to [A-Za-z0-9])
363 [XY] letter \"X\" or \"Y\"
364 [^XY] neither letter \"X\" nor \"Y\"
365 x letter \"x\"
366 * postfix operator for matching previous regexp element any times
367 + postfix operator for matching previous regexp element at least once
368 ? postfix operator for matching previous regexp element at most once"
369 "Common document string used for the custom variables below. Must be
370defined as custom variable due to a bug in XEmacs.")
371
372(defcustom vhdl-clock-signal-syntax "\\<\\([A-Z]\\w*xC\\w*\\)\\>"
373 (concat
374 "*Regular expression (regexp) for syntax of clock signals."
375 vhdl-signal-syntax-doc-string)
376 :type 'regexp
377 :group 'vhdl-signal-syntax)
378
379(defcustom vhdl-reset-signal-syntax "\\<\\([A-Z]\\w*xR\\w*\\)\\>"
380 (concat
381 "*Regular expression (regexp) for syntax of (asynchronous) reset signals."
382 vhdl-signal-syntax-doc-string)
383 :type 'regexp
384 :group 'vhdl-signal-syntax)
385
386(defcustom vhdl-control-signal-syntax "\\<\\([A-Z]\\w*x[IS]\\w*\\)\\>"
387 (concat
388 "*Regular expression (regexp) for syntax of status/control signals."
389 vhdl-signal-syntax-doc-string)
390 :type 'regexp
391 :group 'vhdl-signal-syntax)
392
393(defcustom vhdl-data-signal-syntax "\\<\\([A-Z]\\w*xD\\w*\\)\\>"
394 (concat
395 "*Regular expression (regexp) for syntax of data signals."
396 vhdl-signal-syntax-doc-string)
397 :type 'regexp
398 :group 'vhdl-signal-syntax)
399
400(defcustom vhdl-test-signal-syntax "\\<\\([A-Z]\\w*xT\\w*\\)\\>"
401 (concat
402 "*Regular expression (regexp) for syntax of test signals."
403 vhdl-signal-syntax-doc-string)
404 :type 'regexp
405 :group 'vhdl-signal-syntax)
406
407
408(defgroup vhdl-menu nil
409 "Customizations for menues."
410 :group 'vhdl)
411
412(defcustom vhdl-source-file-menu t
413 "*If non-nil, a menu of all source files in the current directory is created."
414 :type 'boolean
415 :group 'vhdl-menu)
416
417(defcustom vhdl-index-menu t
418 "*If non-nil, an index menu for the current source file is created."
419 :type 'boolean
420 :group 'vhdl-menu)
421
422(defcustom vhdl-hideshow-menu (not (string-match "XEmacs" emacs-version))
423 "*If non-nil, hideshow menu and functionality is added.
424Hideshow allows hiding code of VHDL processes and blocks.
425(Does not work under XEmacs.)"
426 :type 'boolean
427 :group 'vhdl-menu)
428
429
430(defgroup vhdl-print nil
431 "Customizations for printing."
432 :group 'vhdl)
433
434(defcustom vhdl-print-two-column t
435 "*If non-nil, code is printed in two columns and landscape format."
436 :type 'boolean
437 :group 'vhdl-print)
438
439
440(defgroup vhdl-misc nil
441 "Miscellaneous customizations."
442 :group 'vhdl)
443
444(defcustom vhdl-intelligent-tab t
445 "*If non-nil, `TAB' does indentation, word completion, and tab insertion.
446That is, if preceeding character is part of a word then complete word,
447else if not at beginning of line then insert tab,
448else if last command was a `TAB' or `RET' then dedent one step,
449else indent current line (i.e. `TAB' is bound to `vhdl-tab').
450If nil, TAB always indents current line (i.e. `TAB' is bound to
451`vhdl-indent-line')."
452 :type 'boolean
453 :group 'vhdl-misc)
454
455(defcustom vhdl-template-key-binding-prefix "\C-t"
456 "*`C-c' plus this key gives the key binding prefix for all VHDL templates.
457Default key binding prefix for templates is `C-c C-t' (example: architecture
458`C-c C-t a'). If you have no own `C-c LETTER' bindings, you can shorten the
459template key binding prefix to `C-c' (example: architecture `C-c a') by
460assigning the empty character (\"\") to this variable. The syntax to enter
461control keys is \"\\C-t\"."
462 :type 'sexp
463 :group 'vhdl-misc)
464
465(defcustom vhdl-word-completion-in-minibuffer t
466 "*If non-nil, word completion works in minibuffer (for template prompts)."
467 :type 'boolean
468 :group 'vhdl-misc)
469
470(defcustom vhdl-underscore-is-part-of-word nil
471 "*If non-nil, the underscore character `_' is considered as part of word.
472An identifier containing underscores is then treated as a single word in
473select and move operations. All parts of an identifier separated by underscore
474are treated as single words otherwise."
475 :type 'boolean
476 :group 'vhdl-misc)
477
478;; ############################################################################
479;; Other variables
480
481(defvar vhdl-inhibit-startup-warnings-p nil
482 "*If non-nil, inhibits start up compatibility warnings.")
483
484(defvar vhdl-strict-syntax-p nil
485 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
486If the syntactic symbol for a particular line does not match a symbol
487in the offsets alist, an error is generated, otherwise no error is
488reported and the syntactic symbol is ignored.")
489
490(defvar vhdl-echo-syntactic-information-p nil
491 "*If non-nil, syntactic info is echoed when the line is indented.")
492
493(defconst vhdl-offsets-alist-default
494 '((string . -1000)
495 (block-open . 0)
496 (block-close . 0)
497 (statement . 0)
498 (statement-cont . vhdl-lineup-statement-cont)
499 (statement-block-intro . +)
500 (statement-case-intro . +)
501 (case-alternative . +)
502 (comment . vhdl-lineup-comment)
503 (arglist-intro . +)
504 (arglist-cont . 0)
505 (arglist-cont-nonempty . vhdl-lineup-arglist)
506 (arglist-close . vhdl-lineup-arglist)
507 (entity . 0)
508 (configuration . 0)
509 (package . 0)
510 (architecture . 0)
511 (package-body . 0)
512 )
513 "Default settings for offsets of syntactic elements.
514Do not change this constant! See the variable `vhdl-offsets-alist' for
515more information.")
516
517(defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
518 "*Association list of syntactic element symbols and indentation offsets.
519As described below, each cons cell in this list has the form:
520
521 (SYNTACTIC-SYMBOL . OFFSET)
522
523When a line is indented, vhdl-mode first determines the syntactic
524context of the line by generating a list of symbols called syntactic
525elements. This list can contain more than one syntactic element and
526the global variable `vhdl-syntactic-context' contains the context list
527for the line being indented. Each element in this list is actually a
528cons cell of the syntactic symbol and a buffer position. This buffer
529position is call the relative indent point for the line. Some
530syntactic symbols may not have a relative indent point associated with
531them.
532
533After the syntactic context list for a line is generated, vhdl-mode
534calculates the absolute indentation for the line by looking at each
535syntactic element in the list. First, it compares the syntactic
536element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
537finds a match, it adds the OFFSET to the column of the relative indent
538point. The sum of this calculation for each element in the syntactic
539list is the absolute offset for line being indented.
540
541If the syntactic element does not match any in the `vhdl-offsets-alist',
542an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
543the element is ignored.
544
545Actually, OFFSET can be an integer, a function, a variable, or one of
546the following symbols: `+', `-', `++', or `--'. These latter
547designate positive or negative multiples of `vhdl-basic-offset',
548respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
549called with a single argument containing the cons of the syntactic
550element symbol and the relative indent point. The function should
551return an integer offset.
552
553Here is the current list of valid syntactic element symbols:
554
555 string -- inside multi-line string
556 block-open -- statement block open
557 block-close -- statement block close
558 statement -- a VHDL statement
559 statement-cont -- a continuation of a VHDL statement
560 statement-block-intro -- the first line in a new statement block
561 statement-case-intro -- the first line in a case alternative block
562 case-alternative -- a case statement alternative clause
563 comment -- a line containing only a comment
564 arglist-intro -- the first line in an argument list
565 arglist-cont -- subsequent argument list lines when no
566 arguments follow on the same line as the
567 the arglist opening paren
568 arglist-cont-nonempty -- subsequent argument list lines when at
569 least one argument follows on the same
570 line as the arglist opening paren
571 arglist-close -- the solo close paren of an argument list
572 entity -- inside an entity declaration
573 configuration -- inside a configuration declaration
574 package -- inside a package declaration
575 architecture -- inside an architecture body
576 package-body -- inside a package body
577")
578
579(defvar vhdl-comment-only-line-offset 0
580 "*Extra offset for line which contains only the start of a comment.
581Can contain an integer or a cons cell of the form:
582
583 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
584
585Where NON-ANCHORED-OFFSET is the amount of offset given to
586non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
587the amount of offset to give column-zero anchored comment-only lines.
588Just an integer as value is equivalent to (<val> . 0)")
589
590(defvar vhdl-special-indent-hook nil
591 "*Hook for user defined special indentation adjustments.
592This hook gets called after a line is indented by the mode.")
593
594(defvar vhdl-style-alist
595 '(("IEEE"
596 (vhdl-basic-offset . 4)
597 (vhdl-offsets-alist . ())
598 )
599 )
600 "Styles of Indentation.
601Elements of this alist are of the form:
602
603 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
604
605where STYLE-STRING is a short descriptive string used to select a
606style, VARIABLE is any vhdl-mode variable, and VALUE is the intended
607value for that variable when using the selected style.
608
609There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
610case, the VALUE is a list containing elements of the form:
611
612 (SYNTACTIC-SYMBOL . VALUE)
613
614as described in `vhdl-offsets-alist'. These are passed directly to
615`vhdl-set-offset' so there is no need to set every syntactic symbol in
616your style, only those that are different from the default.")
617
618;; dynamically append the default value of most variables
619(or (assoc "Default" vhdl-style-alist)
620 (let* ((varlist '(vhdl-inhibit-startup-warnings-p
621 vhdl-strict-syntax-p
622 vhdl-echo-syntactic-information-p
623 vhdl-basic-offset
624 vhdl-offsets-alist
625 vhdl-comment-only-line-offset))
626 (default (cons "Default"
627 (mapcar
628 (function
629 (lambda (var)
630 (cons var (symbol-value var))
631 ))
632 varlist))))
633 (setq vhdl-style-alist (cons default vhdl-style-alist))))
634
635(defvar vhdl-mode-hook nil
636 "*Hook called by `vhdl-mode'.")
637
638
639;; ############################################################################
640;; Emacs variant handling
641;; ############################################################################
642
643;; active regions
644
645(defun vhdl-keep-region-active ()
646 ;; do whatever is necessary to keep the region active in XEmacs
647 ;; (formerly Lucid). ignore byte-compiler warnings you might see
648 (and (boundp 'zmacs-region-stays)
649 (setq zmacs-region-stays t)))
650
651(defconst vhdl-emacs-features
652 (let ((major (and (boundp 'emacs-major-version)
653 emacs-major-version))
654 (minor (and (boundp 'emacs-minor-version)
655 emacs-minor-version))
656 flavor)
657 ;; figure out version numbers if not already discovered
658 (and (or (not major) (not minor))
659 (string-match "\\([0-9]+\\).\\([0-9]+\\)" emacs-version)
660 (setq major (string-to-int (substring emacs-version
661 (match-beginning 1)
662 (match-end 1)))
663 minor (string-to-int (substring emacs-version
664 (match-beginning 2)
665 (match-end 2)))))
666 (if (not (and major minor))
667 (error "Cannot figure out the major and minor version numbers."))
668 ;; calculate the major version
669 (cond
670 ((= major 18) (setq major 'v18)) ;Emacs 18
671 ((= major 4) (setq major 'v18)) ;Epoch 4
672 ((= major 19) (setq major 'v19 ;Emacs 19
673 flavor (cond
674 ((string-match "Win-Emacs" emacs-version)
675 'Win-Emacs)
676 ((or (string-match "Lucid" emacs-version)
677 (string-match "XEmacs" emacs-version))
678 'XEmacs)
679 (t
680 t))))
681 ((= major 20) (setq major 'v20 ;Emacs 20
682 flavor (cond
683 ((string-match "Win-Emacs" emacs-version)
684 'Win-Emacs)
685 ((or (string-match "Lucid" emacs-version)
686 (string-match "XEmacs" emacs-version))
687 'XEmacs)
688 (t
689 t))))
690 ;; I don't know
691 (t (error "Cannot recognize major version number: %s" major)))
692 ;; lets do some minimal sanity checking.
693 (if (and (or
694 ;; Emacs 18 is brain dead
695 (eq major 'v18)
696 ;; Lemacs before 19.6 had bugs
697 (and (eq major 'v19) (eq flavor 'XEmacs) (< minor 6))
698 ;; Emacs 19 before 19.21 had bugs
699 (and (eq major 'v19) (eq flavor t) (< minor 21)))
700 (not vhdl-inhibit-startup-warnings-p))
701 (with-output-to-temp-buffer "*vhdl-mode warnings*"
702 (print (format
703"The version of Emacs that you are running, %s,
704has known bugs in its syntax.c parsing routines which will affect the
705performance of vhdl-mode. You should strongly consider upgrading to the
706latest available version. vhdl-mode may continue to work, after a
707fashion, but strange indentation errors could be encountered."
708 emacs-version))))
709 (list major flavor))
710 "A list of features extant in the Emacs you are using.
711There are many flavors of Emacs out there, each with different
712features supporting those needed by vhdl-mode. Here's the current
713supported list, along with the values for this variable:
714
715 Emacs 18/Epoch 4: (v18)
716 XEmacs (formerly Lucid) 19: (v19 XEmacs)
717 Win-Emacs 1.35: (V19 Win-Emacs)
718 Emacs 19: (v19 t)
719 Emacs 20: (v20 t).")
720
721
722;; ############################################################################
723;; Bindings
724;; ############################################################################
725
726;; ############################################################################
727;; Key bindings
728
729(defvar vhdl-template-map ()
730 "Keymap for VHDL templates.")
731
732(if vhdl-template-map ()
733 (setq vhdl-template-map (make-sparse-keymap))
734 ;; key bindings for VHDL templates
735 (define-key vhdl-template-map "\M-A" 'vhdl-alias)
736 (define-key vhdl-template-map "a" 'vhdl-architecture)
737 (define-key vhdl-template-map "A" 'vhdl-array)
738 (define-key vhdl-template-map "\M-a" 'vhdl-assert)
739 (define-key vhdl-template-map "b" 'vhdl-block)
740 (define-key vhdl-template-map "c" 'vhdl-case)
741 (define-key vhdl-template-map "\M-c" 'vhdl-component)
742 (define-key vhdl-template-map "I" 'vhdl-component-instance)
743 (define-key vhdl-template-map "\M-s" 'vhdl-concurrent-signal-assignment)
744 (define-key vhdl-template-map "\M-Cb"'vhdl-block-configuration)
745 (define-key vhdl-template-map "\M-Cc"'vhdl-component-configuration)
746 (define-key vhdl-template-map "\M-Cd"'vhdl-configuration-decl)
747 (define-key vhdl-template-map "\M-Cs"'vhdl-configuration-spec)
748 (define-key vhdl-template-map "C" 'vhdl-constant)
749 (define-key vhdl-template-map "d" 'vhdl-disconnect)
750 (define-key vhdl-template-map "\M-e" 'vhdl-else)
751 (define-key vhdl-template-map "E" 'vhdl-elsif)
752 (define-key vhdl-template-map "e" 'vhdl-entity)
753 (define-key vhdl-template-map "x" 'vhdl-exit)
754 (define-key vhdl-template-map "f" 'vhdl-for)
755 (define-key vhdl-template-map "F" 'vhdl-function)
756 (define-key vhdl-template-map "g" 'vhdl-generate)
757 (define-key vhdl-template-map "G" 'vhdl-generic)
758 (define-key vhdl-template-map "h" 'vhdl-header)
759 (define-key vhdl-template-map "i" 'vhdl-if)
760 (define-key vhdl-template-map "L" 'vhdl-library)
761 (define-key vhdl-template-map "l" 'vhdl-loop)
762 (define-key vhdl-template-map "m" 'vhdl-modify)
763 (define-key vhdl-template-map "M" 'vhdl-map)
764 (define-key vhdl-template-map "n" 'vhdl-next)
765 (define-key vhdl-template-map "k" 'vhdl-package)
766 (define-key vhdl-template-map "(" 'vhdl-paired-parens)
767 (define-key vhdl-template-map "\M-p" 'vhdl-port)
768 (define-key vhdl-template-map "p" 'vhdl-procedure)
769 (define-key vhdl-template-map "P" 'vhdl-process)
770 (define-key vhdl-template-map "R" 'vhdl-record)
771 (define-key vhdl-template-map "r" 'vhdl-return-value)
772 (define-key vhdl-template-map "\M-S" 'vhdl-selected-signal-assignment)
773 (define-key vhdl-template-map "s" 'vhdl-signal)
774 (define-key vhdl-template-map "S" 'vhdl-subtype)
775 (define-key vhdl-template-map "t" 'vhdl-type)
776 (define-key vhdl-template-map "u" 'vhdl-use)
777 (define-key vhdl-template-map "v" 'vhdl-variable)
778 (define-key vhdl-template-map "W" 'vhdl-wait)
779 (define-key vhdl-template-map "w" 'vhdl-while-loop)
780 (define-key vhdl-template-map "\M-w" 'vhdl-with)
781 (define-key vhdl-template-map "\M-W" 'vhdl-clocked-wait)
782 (define-key vhdl-template-map "Kb" 'vhdl-package-numeric-bit)
783 (define-key vhdl-template-map "Kn" 'vhdl-package-numeric-std)
784 (define-key vhdl-template-map "Ks" 'vhdl-package-std-logic-1164)
785 (define-key vhdl-template-map "Kt" 'vhdl-package-textio)
786 )
787
788(defvar vhdl-mode-map ()
789 "Keymap for VHDL Mode.")
790
791(if vhdl-mode-map ()
792 (setq vhdl-mode-map (make-sparse-keymap))
793 ;; key bindings for templates
794 (define-key vhdl-mode-map
795 (concat "\C-c" vhdl-template-key-binding-prefix) vhdl-template-map)
796 ;; standard key bindings
797 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
798 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
799 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
800 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
801 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
802 ;(define-key vhdl-mode-map "\M-\C-d" 'vhdl-down-list)
803 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
804 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
805 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
806 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
807 (define-key vhdl-mode-map "\177" 'backward-delete-char-untabify)
808 (define-key vhdl-mode-map "\r" 'vhdl-return)
809 (if vhdl-intelligent-tab
810 (define-key vhdl-mode-map "\t" 'vhdl-tab)
811 (define-key vhdl-mode-map "\t" 'vhdl-indent-line))
812 (define-key vhdl-mode-map " " 'vhdl-outer-space)
813 ;; new key bindings for VHDL Mode, with no counterpart to BOCM
814 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
815 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
816 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
817 (define-key vhdl-mode-map "\C-c\C-f" 'font-lock-fontify-buffer)
818 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
819 (define-key vhdl-mode-map "\C-c\C-r" 'vhdl-regress-line)
820 (define-key vhdl-mode-map "\C-c\C-i" 'vhdl-indent-line)
821 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-noindent-region)
822 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-comment-region)
823 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
824 (define-key vhdl-mode-map "\C-c-" 'vhdl-inline-comment)
825 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-display-comment-line)
826 (define-key vhdl-mode-map "\C-c\C-o" 'vhdl-open-line)
827 (define-key vhdl-mode-map "\C-c\C-g" 'goto-line)
828 (define-key vhdl-mode-map "\C-c\C-d" 'vhdl-kill-line)
829 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-help)
830 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
831 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-submit-bug-report)
832 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
833 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
834 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
835 ;; key bindings for stuttering
836 (define-key vhdl-mode-map "-" 'vhdl-stutter-mode-dash)
837 (define-key vhdl-mode-map "'" 'vhdl-stutter-mode-quote)
838 (define-key vhdl-mode-map ";" 'vhdl-stutter-mode-semicolon)
839 (define-key vhdl-mode-map "[" 'vhdl-stutter-mode-open-bracket)
840 (define-key vhdl-mode-map "]" 'vhdl-stutter-mode-close-bracket)
841 (define-key vhdl-mode-map "." 'vhdl-stutter-mode-period)
842 (define-key vhdl-mode-map "," 'vhdl-stutter-mode-comma)
843 (let ((c 97))
844 (while (< c 123) ; for little a-z
845 (define-key vhdl-mode-map (char-to-string c) 'vhdl-stutter-mode-caps)
846 (setq c (1+ c))
847 ))
848 )
849
850;; define special minibuffer keymap for enabling word completion in minibuffer
851;; (useful in template generator prompts)
852(defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
853 "Keymap for minibuffer used in VHDL Mode.")
854
855(define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab)
856
857(defvar vhdl-mode-syntax-table nil
858 "Syntax table used in vhdl-mode buffers.")
859
860(if vhdl-mode-syntax-table ()
861 (setq vhdl-mode-syntax-table (make-syntax-table))
862 ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS!
863 ;; why not? (is left to the user here)
864 (if vhdl-underscore-is-part-of-word
865 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
866 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
867 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
868 (modify-syntax-entry ?\% "." 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 ;; add comment syntax
889 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
890 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
891 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table))
892
893(defvar vhdl-syntactic-context nil
894 "Buffer local variable containing syntactic analysis list.")
895(make-variable-buffer-local 'vhdl-syntactic-context)
896
897;; ############################################################################
898;; Abbrev hook bindings
899
900(defvar vhdl-mode-abbrev-table nil
901 "Abbrev table in use in vhdl-mode buffers.")
902
903(define-abbrev-table 'vhdl-mode-abbrev-table
904 '(
905 ("--" "" vhdl-display-comment-hook 0)
906 ("abs" "" vhdl-default-hook 0)
907 ("access" "" vhdl-default-hook 0)
908 ("after" "" vhdl-default-hook 0)
909 ("alias" "" vhdl-alias-hook 0)
910 ("all" "" vhdl-default-hook 0)
911 ("and" "" vhdl-default-hook 0)
912 ("arch" "" vhdl-architecture-hook 0)
913 ("architecture" "" vhdl-architecture-hook 0)
914 ("array" "" vhdl-array-hook 0)
915 ("assert" "" vhdl-assert-hook 0)
916 ("attr" "" vhdl-attribute-hook 0)
917 ("attribute" "" vhdl-attribute-hook 0)
918 ("begin" "" vhdl-default-indent-hook 0)
919 ("block" "" vhdl-block-hook 0)
920 ("body" "" vhdl-default-hook 0)
921 ("buffer" "" vhdl-default-hook 0)
922 ("bus" "" vhdl-default-hook 0)
923 ("case" "" vhdl-case-hook 0)
924 ("comp" "" vhdl-component-hook 0)
925 ("component" "" vhdl-component-hook 0)
926 ("conc" "" vhdl-concurrent-signal-assignment-hook 0)
927 ("concurrent" "" vhdl-concurrent-signal-assignment-hook 0)
928 ("conf" "" vhdl-configuration-hook 0)
929 ("configuration" "" vhdl-configuration-hook 0)
930 ("cons" "" vhdl-constant-hook 0)
931 ("constant" "" vhdl-constant-hook 0)
932 ("disconnect" "" vhdl-disconnect-hook 0)
933 ("downto" "" vhdl-default-hook 0)
934 ("else" "" vhdl-else-hook 0)
935 ("elseif" "" vhdl-elsif-hook 0)
936 ("elsif" "" vhdl-elsif-hook 0)
937 ("end" "" vhdl-default-indent-hook 0)
938 ("entity" "" vhdl-entity-hook 0)
939 ("exit" "" vhdl-exit-hook 0)
940 ("file" "" vhdl-default-hook 0)
941 ("for" "" vhdl-for-hook 0)
942 ("func" "" vhdl-function-hook 0)
943 ("function" "" vhdl-function-hook 0)
944 ("gen" "" vhdl-generate-hook 0)
945 ("generate" "" vhdl-generate-hook 0)
946 ("generic" "" vhdl-generic-hook 0)
947 ("group" "" vhdl-default-hook 0)
948 ("guarded" "" vhdl-default-hook 0)
949 ("header" "" vhdl-header-hook 0)
950 ("if" "" vhdl-if-hook 0)
951 ("impure" "" vhdl-default-hook 0)
952 ("in" "" vhdl-default-hook 0)
953 ("inertial" "" vhdl-default-hook 0)
954 ("inout" "" vhdl-default-hook 0)
955 ("inst" "" vhdl-component-instance-hook 0)
956 ("instance" "" vhdl-component-instance-hook 0)
957 ("is" "" vhdl-default-hook 0)
958 ("label" "" vhdl-default-hook 0)
959 ("library" "" vhdl-library-hook 0)
960 ("linkage" "" vhdl-default-hook 0)
961 ("literal" "" vhdl-default-hook 0)
962 ("loop" "" vhdl-loop-hook 0)
963 ("map" "" vhdl-map-hook 0)
964 ("mod" "" vhdl-default-hook 0)
965 ("modify" "" vhdl-modify-hook 0)
966 ("nand" "" vhdl-default-hook 0)
967 ("new" "" vhdl-default-hook 0)
968 ("next" "" vhdl-next-hook 0)
969 ("nor" "" vhdl-default-hook 0)
970 ("not" "" vhdl-default-hook 0)
971 ("null" "" vhdl-default-hook 0)
972 ("of" "" vhdl-default-hook 0)
973 ("on" "" vhdl-default-hook 0)
974 ("open" "" vhdl-default-hook 0)
975 ("or" "" vhdl-default-hook 0)
976 ("others" "" vhdl-default-hook 0)
977 ("out" "" vhdl-default-hook 0)
978 ("pack" "" vhdl-package-hook 0)
979 ("package" "" vhdl-package-hook 0)
980 ("port" "" vhdl-port-hook 0)
981 ("postponed" "" vhdl-default-hook 0)
982 ("procedure" "" vhdl-procedure-hook 0)
983 ("process" "" vhdl-process-hook 0)
984 ("pure" "" vhdl-default-hook 0)
985 ("range" "" vhdl-default-hook 0)
986 ("record" "" vhdl-record-hook 0)
987 ("register" "" vhdl-default-hook 0)
988 ("reject" "" vhdl-default-hook 0)
989 ("rem" "" vhdl-default-hook 0)
990 ("report" "" vhdl-default-hook 0)
991 ("ret" "" vhdl-return-hook 0)
992 ("return" "" vhdl-return-hook 0)
993 ("rol" "" vhdl-default-hook 0)
994 ("ror" "" vhdl-default-hook 0)
995 ("select" "" vhdl-selected-signal-assignment-hook 0)
996 ("severity" "" vhdl-default-hook 0)
997 ("shared" "" vhdl-default-hook 0)
998 ("sig" "" vhdl-signal-hook 0)
999 ("signal" "" vhdl-signal-hook 0)
1000 ("sla" "" vhdl-default-hook 0)
1001 ("sll" "" vhdl-default-hook 0)
1002 ("sra" "" vhdl-default-hook 0)
1003 ("srl" "" vhdl-default-hook 0)
1004 ("sub" "" vhdl-subtype-hook 0)
1005 ("subtype" "" vhdl-subtype-hook 0)
1006 ("then" "" vhdl-default-hook 0)
1007 ("to" "" vhdl-default-hook 0)
1008 ("transport" "" vhdl-default-hook 0)
1009 ("type" "" vhdl-type-hook 0)
1010 ("unaffected" "" vhdl-default-hook 0)
1011 ("units" "" vhdl-default-hook 0)
1012 ("until" "" vhdl-default-hook 0)
1013 ("use" "" vhdl-use-hook 0)
1014 ("var" "" vhdl-variable-hook 0)
1015 ("variable" "" vhdl-variable-hook 0)
1016 ("wait" "" vhdl-wait-hook 0)
1017 ("warning" "" vhdl-default-hook 0)
1018 ("when" "" vhdl-when-hook 0)
1019 ("while" "" vhdl-while-loop-hook 0)
1020 ("with" "" vhdl-selected-signal-assignment-hook 0)
1021 ("xnor" "" vhdl-default-hook 0)
1022 ("xor" "" vhdl-default-hook 0)
1023 ))
1024
1025
1026;; ############################################################################
1027;; Menues
1028;; ############################################################################
1029
1030;; ############################################################################
1031;; VHDL menu (using `easy-menu.el')
1032
1033;; `customize-menu-create' is included in `cus-edit.el' version 1.9954,
1034;; which is not yet distributed with XEmacs 19.15
1035(defun vhdl-customize-menu-create (symbol &optional name)
1036 "Return a customize menu for customization group SYMBOL.
1037If optional NAME is given, use that as the name of the menu.
1038Otherwise the menu will be named `Customize'.
1039The format is suitable for use with `easy-menu-define'."
1040 (unless name
1041 (setq name "Customize"))
1042 (if (memq 'XEmacs vhdl-emacs-features)
1043 ;; We can delay it under XEmacs.
1044 `(,name
1045 :filter (lambda (&rest junk)
1046 (cdr (custom-menu-create ',symbol))))
1047 ;; But we must create it now under Emacs.
1048 (cons name (cdr (custom-menu-create symbol)))))
1049
1050(defvar vhdl-mode-menu
1051 (append
1052 '("VHDL"
1053 ("Mode"
1054 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
1055 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
1056 )
1057 "--"
1058 ("Compile"
1059 ["Compile Buffer" vhdl-compile t]
1060 ["Stop Compilation" kill-compilation t]
1061 "--"
1062 ["Make" vhdl-make t]
1063 ["Generate Makefile" vhdl-generate-makefile t]
1064 "--"
1065 ["Next Error" next-error t]
1066 ["Previous Error" previous-error t]
1067 ["First Error" first-error t]
1068 )
1069 "--"
1070 ("Template"
1071 ("VHDL Construct 1"
1072 ["Alias" vhdl-alias t]
1073 ["Architecture" vhdl-architecture t]
1074 ["Array" vhdl-array t]
1075 ["Assert" vhdl-assert t]
1076 ["Attribute" vhdl-attribute t]
1077 ["Block" vhdl-block t]
1078 ["Case" vhdl-case t]
1079 ["Component" vhdl-component t]
1080 ["Concurrent (Signal Asst)" vhdl-concurrent-signal-assignment t]
1081 ["Configuration (Block)" vhdl-block-configuration t]
1082 ["Configuration (Comp)" vhdl-component-configuration t]
1083 ["Configuration (Decl)" vhdl-configuration-decl t]
1084 ["Configuration (Spec)" vhdl-configuration-spec t]
1085 ["Constant" vhdl-constant t]
1086 ["Disconnect" vhdl-disconnect t]
1087 ["Else" vhdl-else t]
1088 ["Elsif" vhdl-elsif t]
1089 ["Entity" vhdl-entity t]
1090 ["Exit" vhdl-exit t]
1091 ["For (Loop)" vhdl-for t]
1092 ["Function" vhdl-function t]
1093 ["(For/If) Generate" vhdl-generate t]
1094 ["Generic" vhdl-generic t]
1095 )
1096 ("VHDL Construct 2"
1097 ["If" vhdl-if t]
1098 ["Instance" vhdl-component-instance t]
1099 ["Library" vhdl-library t]
1100 ["Loop" vhdl-loop t]
1101 ["Map" vhdl-map t]
1102 ["Next" vhdl-next t]
1103 ["Package" vhdl-package t]
1104 ["Port" vhdl-port t]
1105 ["Procedure" vhdl-procedure t]
1106 ["Process" vhdl-process t]
1107 ["Record" vhdl-record t]
1108 ["Return" vhdl-return-value t]
1109 ["Select" vhdl-selected-signal-assignment t]
1110 ["Signal" vhdl-signal t]
1111 ["Subtype" vhdl-subtype t]
1112 ["Type" vhdl-type t]
1113 ["Use" vhdl-use t]
1114 ["Variable" vhdl-variable t]
1115 ["Wait" vhdl-wait t]
1116 ["(Clocked Wait)" vhdl-clocked-wait t]
1117 ["When" vhdl-when t]
1118 ["While (Loop)" vhdl-while-loop t]
1119 ["With" vhdl-with t]
1120 )
1121 ("Standard Package"
1122 ["numeric_bit" vhdl-package-numeric-bit t]
1123 ["numeric_std" vhdl-package-numeric-std t]
1124 ["std_logic_1164" vhdl-package-std-logic-1164 t]
1125 ["textio" vhdl-package-textio t]
1126 )
1127 ["Header" vhdl-header t]
1128 ["Modify (Date)" vhdl-modify t]
1129 )
1130 ("Comment"
1131 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
1132 ["Insert Inline Comment" vhdl-inline-comment t]
1133 ["Insert Horizontal Line" vhdl-display-comment-line t]
1134 ["Insert Display Comment" vhdl-display-comment t]
1135 ["Fill Comment" fill-paragraph t]
1136 ["Fill Comment Region" fill-region (mark)]
1137 )
1138 ("Indent"
1139 ["Line" vhdl-indent-line t]
1140 ["Region" indent-region (mark)]
1141 ["Buffer" vhdl-indent-buffer t]
1142 )
1143 ("Align"
1144 ["Region" vhdl-align-noindent-region (mark)]
1145 ["Comment Region" vhdl-align-comment-region (mark)]
1146 )
1147 ("Line"
1148 ["Open" vhdl-open-line t]
1149 ["Delete" vhdl-kill-line t]
1150 ["Join" delete-indentation t]
1151 ["Goto" goto-line t]
1152 )
1153 ("Move"
1154 ["Forward Statement" vhdl-end-of-statement t]
1155 ["Backward Statement" vhdl-beginning-of-statement t]
1156 ["Forward Expression" vhdl-forward-sexp t]
1157 ["Backward Expression" vhdl-backward-sexp t]
1158 ["Forward Function" vhdl-end-of-defun t]
1159 ["Backward Function" vhdl-beginning-of-defun t]
1160 )
1161 "--"
1162 ("Fix Case"
1163 ["Buffer" vhdl-fix-case-buffer t]
1164 ["Region" vhdl-fix-case-region (mark)]
1165 )
1166 ["Fontify Buffer" font-lock-fontify-buffer t]
1167 ["Syntactic Info" vhdl-show-syntactic-information t]
1168 "--"
1169 ["Help" vhdl-help t]
1170 ["Version" vhdl-version t]
1171 ["Bug Report" vhdl-submit-bug-report t]
1172 "--"
1173 )
1174 (list (vhdl-customize-menu-create 'vhdl))
1175))
1176
1177(require 'easymenu)
1178
1179;; ############################################################################
1180;; Index menu (using `imenu.el')
1181
1182(defvar vhdl-imenu-generic-expression
1183 '(
1184 ("Entity"
1185 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1186 2)
1187 ("Architecture"
1188 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
1189 2)
1190 ("Configuration"
1191 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
1192 2)
1193 ("Package Body"
1194 "^\\s-*\\(package body\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1195 2)
1196 ("Package"
1197 "^\\s-*\\(package\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1198 2)
1199 ("Type"
1200 "^\\s-*\\(sub\\)?type\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1201 2)
1202 ("Component"
1203 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1204 2)
1205 ("Function / Procedure"
1206 "^\\s-*\\(procedure\\|function\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
1207 2)
1208 ("Process / Block"
1209 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(process\\|block\\)"
1210 1)
1211 ("Instance"
1212 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
1213 1)
1214 )
1215 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
1216
1217(defun vhdl-add-index-menu ()
1218 (make-local-variable 'imenu-generic-expression)
1219 (setq imenu-generic-expression vhdl-imenu-generic-expression)
1220 (imenu-add-to-menubar "Index"))
1221
1222;; ############################################################################
1223;; Source file menu (using `easy-menu.el')
1224
1225(defvar vhdl-extlist '("[A-Za-z0-9_.]*.vhdl?$"))
1226(defvar vhdl-filelist-menu nil)
1227
1228(defun vhdl-add-source-files-menu ()
1229 "Scan directory of current source file for all VHDL source files, and
1230generate menu."
1231 (interactive)
1232 (message "Scanning directory for source files ...")
1233 (let (filelist menulist tmpextlist found
1234 (newmap (current-local-map)))
1235 (cd (file-name-directory (buffer-file-name)))
1236 ;; find files
1237 (setq menulist '())
1238 (setq tmpextlist vhdl-extlist)
1239 (while tmpextlist
1240 (setq filelist (nreverse (directory-files
1241 (file-name-directory (buffer-file-name))
1242 nil (car tmpextlist) nil)))
1243 ;; Create list for menu
1244 (setq found nil)
1245 (while filelist
1246 (setq found t)
1247 (setq menulist (cons (vector (car filelist)
1248 (list 'find-file (car filelist)) t)
1249 menulist))
1250 (setq filelist (cdr filelist)))
1251 (setq menulist (vhdl-menu-split menulist 25))
1252 (if found
1253 (setq menulist (cons "--" menulist)))
1254 (setq tmpextlist (cdr tmpextlist)))
1255 (setq menulist (cons ["*Rescan*" vhdl-add-source-files-menu t] menulist))
1256 (setq menulist (cons "Sources" menulist))
1257 ;; Create menu
1258 (easy-menu-add menulist)
1259 (easy-menu-define vhdl-filelist-menu newmap
1260 "VHDL source files menu" menulist)
1261; (use-local-map (append (current-local-map) newmap))
1262; (use-local-map newmap)
1263 )
1264 (message ""))
1265
1266(defun vhdl-menu-split (list n)
1267 "Split menu into several submenues, if number of elements > n."
1268 (if (> (length list) n)
1269 (let ((remain list)
1270 (result '())
1271 (sublist '())
1272 (menuno 1)
1273 (i 0))
1274 (while remain
1275 (setq sublist (cons (car remain) sublist))
1276 (setq remain (cdr remain))
1277 (setq i (+ i 1))
1278 (if (= i n)
1279 (progn
1280 (setq result (cons (cons (format "Sources %s" menuno)
1281 (nreverse sublist)) result))
1282 (setq i 0)
1283 (setq menuno (+ menuno 1))
1284 (setq sublist '()))))
1285 (and sublist
1286 (setq result (cons (cons (format "Sources %s" menuno)
1287 (nreverse sublist)) result)))
1288 (nreverse result))
1289 list))
1290
1291
1292;; ############################################################################
1293;; VHDL Mode definition
1294;; ############################################################################
1295
1296(defun vhdl-mode ()
1297 "Major mode for editing VHDL code.
1298
1299Usage:
1300------
1301
1302- TEMPLATE INSERTION (electrification) (`\\[vhdl-outer-space]'): After typing
1303 a VHDL keyword and entering `\\[vhdl-outer-space]', you are prompted for
1304 arguments while a template is generated for that VHDL construct. Typing
1305 `\\[vhdl-return]' (or `\\[keyboard-quit]' in yes-no queries) at the first
1306 prompt aborts the current template generation. Typing `\\[just-one-space]'
1307 after a keyword inserts a space without calling the template generator.
1308 Automatic calling of the template generators (i.e. electrification) can be
1309 disabled (enabled) by setting the variable `vhdl-electric-mode' to nil
1310 (non-nil) or by typing `\\[vhdl-electric-mode]' (toggles electrification
1311 mode).
1312 Template generators can be called using the VHDL menu, the key bindings, or
1313 by typing the keyword (first word of menu entry not in parenthesis) and
1314 `\\[vhdl-outer-space]'. The following abbreviations can also be used:
1315 arch, attr, conc, conf, comp, cons, func, inst, pack, ret, sig, sub, var.
1316
1317- HEADER INSERTION (`\\[vhdl-header]'): A customized header can be inserted
1318 including the actual file name, user name, and current date as well as
1319 prompted title strings. A custom header can be defined in a separate file
1320 (see custom variable `vhdl-header-file').
1321
1322- STUTTERING (double strike): Double striking of some keys inserts cumbersome
1323 VHDL syntax elements. Stuttering can be disabled by variable
1324 `vhdl-stutter-mode' and be toggled by typing `\\[vhdl-stutter-mode]'.
1325 '' --> \" [ --> ( -- --> comment
1326 ;; --> \" : \" [[ --> [ --CR --> comment-out code
1327 ;;; --> \" := \" ] --> ) --- --> horizontal line
1328 .. --> \" => \" ]] --> ] ---- --> display comment
1329 ,, --> \" <= \" aa --> A - zz --> Z
1330
1331- WORD COMPLETION (`\\[vhdl-tab]'): Typing `\\[vhdl-tab]' after a (not
1332 completed) word looks for a word in the buffer that starts alike and
1333 inserts it. Re-typing `\\[vhdl-tab]' toggles through alternative word
1334 completions. This also works in the minibuffer (i.e. in template generator
1335 prompts).
1336
1337 Typing `\\[vhdl-tab]' after a non-word character indents the line if at the
1338 beginning of a line (i.e. no preceding non-blank characters), and inserts a
1339 tabulator stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator
1340 stop.
1341
1342- COMMENTS (`--', `---', `----', `--CR'):
1343 `--' puts a single comment.
1344 `---' draws a horizontal line for separating code segments.
1345 `----' inserts a display comment, i.e. two horizontal lines with a
1346 comment in between.
1347 `--CR' comments out code on that line. Re-hitting CR comments out
1348 following lines.
1349 `\\[vhdl-comment-uncomment-region]' comments out a region if not
1350 commented out, uncomments out a region if already
1351 commented out.
1352
1353 You are prompted for comments after object definitions (i.e. signals,
1354 variables, constants, ports) and after subprogram and process specifications
1355 if variable `vhdl-prompt-for-comments' is non-nil. Comments are
1356 automatically inserted as additional labels (e.g. after begin statements)
1357 and help comments if `vhdl-self-insert-comments' is non-nil.
1358 Inline comments (i.e. comments after a piece of code on the same line) are
1359 indented at least to `vhdl-comment-column'. Comments go at maximum to
1360 `vhdl-end-comment-column'. `\\[vhdl-return]' after a space in a comment will
1361 open a new comment line. Typing beyond `vhdl-end-comment-column' in a
1362 comment automatically opens a new comment line. `\\[fill-paragraph]'
1363 re-fills multi-line comments.
1364
1365- INDENTATION: `\\[vhdl-tab]' indents a line if at the beginning of the line.
1366 The amount of indentation is specified by variable `vhdl-basic-offset'.
1367 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB'
1368 if variable `vhdl-intelligent-tab' is nil). Indentation can be done for
1369 an entire region (`\\[indent-region]') or buffer (menu). Argument and
1370 port lists are indented normally (nil) or relative to the opening
1371 parenthesis (non-nil) according to variable `vhdl-argument-list-indent'.
1372 If variable `vhdl-indent-tabs-mode' is nil, spaces are used instead of tabs.
1373 `\\[tabify]' and `\\[untabify]' allow to convert spaces to tabs and vice
1374 versa.
1375
1376- ALIGNMENT: `\\[vhdl-align-noindent-region]' aligns port maps, signal and
1377 variable assignments, inline comments, some keywords, etc., on consecutive
1378 lines relative to each other within a defined region.
1379 `\\[vhdl-align-comment-region]' only aligns inline comments (i.e. comments
1380 that are at the end of a line of code). Some templates are automatically
1381 aligned after generation if custom variable `vhdl-auto-align' is non-nil.
1382
1383- KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in menu).
1384
1385- VHDL MENU: All commands can be called from the VHDL menu.
1386
1387- INDEX MENU: For each VHDL source file, an index of the contained entities,
1388 architectures, packages, procedures, processes, etc., is created as a menu.
1389 Selecting a meny entry causes the cursor to jump to the corresponding
1390 position in the file. Controlled by variable `vhdl-index-menu'.
1391
1392- SOURCE FILE MENU: A menu containing all VHDL source files in the directory
1393 of the current file is generated. Selecting a menu entry loads the file.
1394 Controlled by variable `vhdl-source-file-menu'.
1395
1396- SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
1397 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be
1398 used is defined by variable `vhdl-compiler'. Currently supported are
1399 `cadence', `ikos', `quickhdl', `synopsys', `vantage', `viewlogic', and
1400 `v-system'. Not all compilers are tested. Please contact me for
1401 incorporating additional VHDL compilers. An entire hierarchy of source
1402 files can be compiled by the `make' command (menu, `\\[vhdl-make]').
1403 This only works if an appropriate `Makefile' exists. Compiler options can
1404 be defined by variable `vhdl-compiler-options'.
1405
1406- KEYWORD CASE: Lower and upper case for keywords, predefined types, predefined
1407 attributes, and predefined enumeration values is supported. If the variable
1408 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in
1409 lower case and are converted into upper case automatically (not for types,
1410 attributes, and enumeration values). The case of keywords, types,
1411 attributes, and enumeration values can be fixed for an entire region (menu)
1412 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
1413 `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
1414
1415- HIGHLIGHTING (fontification): Keywords, predefined types, predefined
1416 attributes, and predefined enumeration values (controlled by variable
1417 `vhdl-highlight-keywords'), as well as comments, strings, and template
1418 prompts are highlighted using different colors. Unit and subprogram names
1419 as well as labels are highlighted if variable `vhdl-highlight-names' is
1420 non-nil. The default colors from `font-lock.el' are used if variable
1421 `vhdl-use-default-colors' is non-nil. Otherwise, an optimized set of colors
1422 is taken, which uses bright colors for signals and muted colors for
1423 everything else. Variable `vhdl-use-default-faces' does the same on
1424 monochrome monitors.
1425
1426 Signal highlighting allows distinction between clock, reset,
1427 status/control, data, and test signals according to some signal
1428 naming convention. Their syntax is defined by variables
1429 `vhdl-{clock,reset,control,data,test}-signal-syntax'. Signal coloring
1430 is controlled by the variable `vhdl-highlight-signals'. The default
1431 signal naming convention is as follows:
1432
1433 Signal attributes:
1434 C clock S control and status
1435 R asynchronous reset D data and address
1436 I synchronous reset T test
1437
1438 Syntax:
1439 signal name ::= \"[A-Z][a-zA-Z0-9]*x[CRISDT][a-zA-Z0-9]*\"
1440 signal identifier -^^^^^^^^^^^^^^^^^
1441 delimiter --------------------------^
1442 above signal attributes -------------^^^^^^^^
1443 additional attributes -----------------------^^^^^^^^^^^^
1444
1445 (`x' is used as delimiter because `_' is reserved by the VITAL standard.)
1446 Examples: ClkxCfast, ResetxRB, ClearxI, SelectDataxS, DataxD, ScanEnablexT.
1447
1448 If all VHDL words are written in lower case (i.e. variables
1449 `vhdl-upper-case-{keywords,types,attributes,enum-values}' are set to nil),
1450 make highlighting case sensitive by setting variable
1451 `vhdl-highlight-case-sensitive' to non-nil. This way, only names fulfilling
1452 the above signal syntax including case are highlighted.
1453
1454- HIDE/SHOW: The code of entire VHDL processes or blocks can be hidden using
1455 the `Hide/Show' menu or by pressing `S-mouse-2' within the code
1456 (not in XEmacs).
1457
1458- PRINTING: Postscript printing with different fonts (`ps-print-color-p' is
1459 nil, default faces from `font-lock.el' used if `vhdl-use-default-faces' is
1460 non-nil) or colors (`ps-print-color-p' is non-nil) is possible using the
1461 standard Emacs postscript printing commands. Variable `vhdl-print-two-column'
1462 defines appropriate default settings for nice landscape two-column printing.
1463 The paper format can be set by variable `ps-paper-type'.
1464
1465- CUSTOMIZATION: All variables can easily be customized using the `Customize'
1466 menu entry. For some variables, customization only takes effect after
1467 re-starting Emacs. Customization can also be done globally (i.e. site-wide,
1468 read INSTALL file). Variables of VHDL Mode must NOT be set using the
1469 `vhdl-mode-hook' in the .emacs file anymore (delete them if they still are).
1470
1471
1472Maintenance:
1473------------
1474
1475To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
1476Add a description of the problem and include a reproducible test case.
1477
1478Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
1479
1480The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
1481The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
1482You are kindly invited to participate in beta testing. Subscribe to above
1483mailing lists by sending an email to <vhdl-mode@geocities.com>.
1484
1485The archive with the latest version is located at
1486<http://www.geocities.com/SiliconValley/Peaks/8287>.
1487
1488
1489Bugs and Limitations:
1490---------------------
1491
1492- Index menu does not work under XEmacs (limitation of XEmacs ?!).
1493
1494- Re-indenting large regions or expressions can be slow.
1495
1496- Hideshow does not work under XEmacs.
1497
1498- Parsing compilation error messages for Ikos and Vantage VHDL compilers
1499 does not work under XEmacs.
1500
1501
1502Key bindings:
1503-------------
1504
1505\\{vhdl-mode-map}"
1506 (interactive)
1507 (kill-all-local-variables)
1508 (set-syntax-table vhdl-mode-syntax-table)
1509 (setq major-mode 'vhdl-mode)
1510 (setq mode-name "VHDL")
1511 (setq local-abbrev-table vhdl-mode-abbrev-table)
1512 (use-local-map vhdl-mode-map)
1513 ;; set local variable values
1514 (set (make-local-variable 'paragraph-start) "\\s-*\\(---\\|[a-zA-Z]\\|$\\)")
1515 (set (make-local-variable 'paragraph-separate) paragraph-start)
1516 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
1517 (set (make-local-variable 'require-final-newline) t)
1518 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1519 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
1520 (set (make-local-variable 'comment-start) "--")
1521 (set (make-local-variable 'comment-end) "")
1522 (set (make-local-variable 'comment-column) vhdl-comment-column)
1523 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
1524 (set (make-local-variable 'comment-start-skip) "--+\\s-*")
1525 (set (make-local-variable 'dabbrev-case-fold-search) nil)
1526 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
1527
1528 ;; setup the comment indent variable in a Emacs version portable way
1529 ;; ignore any byte compiler warnings you might get here
1530 (if (boundp 'comment-indent-function)
1531 (progn (make-local-variable 'comment-indent-function)
1532 (setq comment-indent-function 'vhdl-comment-indent)))
1533
1534 ;; initialize font locking
1535 (require 'font-lock)
1536 (vhdl-font-lock-init)
1537 (make-local-variable 'font-lock-defaults)
1538 (setq font-lock-defaults (list 'vhdl-font-lock-keywords nil
1539 (not vhdl-highlight-case-sensitive)
1540 '((?\_ . "w"))))
1541 (turn-on-font-lock)
1542
1543 ;; variables for source file compilation
1544 (make-local-variable 'compile-command)
1545 (set (make-local-variable 'compilation-error-regexp-alist)
1546 vhdl-compilation-error-regexp-alist)
1547
1548 ;; add menus
1549 (if vhdl-index-menu
1550 (if (or (not (consp font-lock-maximum-size))
1551 (> font-lock-maximum-size (buffer-size)))
1552 (vhdl-add-index-menu)
1553 (message "Scanning buffer for index...buffer too big")))
1554 (if vhdl-source-file-menu (vhdl-add-source-files-menu))
1555 (easy-menu-add vhdl-mode-menu)
1556 (easy-menu-define vhdl-mode-easy-menu vhdl-mode-map
1557 "Menu keymap for VHDL Mode." vhdl-mode-menu)
1558 (run-hooks 'menu-bar-update-hook)
1559
1560 ;; initialize hideshow and add menu
1561 (if vhdl-hideshow-menu (hs-minor-mode))
1562
1563 ;; initialize postscript printing
1564 (vhdl-ps-init)
1565
1566 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
1567 (message "Type C-c C-h for VHDL Mode documentation.")
1568
1569 (run-hooks 'vhdl-mode-hook)
1570 )
1571
1572
1573;; ############################################################################
1574;; Keywords and predefined words in VHDL'93
1575;; ############################################################################
1576
1577;; `regexp-opt' was not used at this place because it is not yet implemented
1578;; in XEmacs and because it resulted in SLOWER regexps!!
1579
1580(defconst vhdl-93-keywords-regexp
1581 (eval-when-compile
1582 (concat
1583 "\\<\\("
1584 (mapconcat
1585 'identity
1586 '(
1587 "abs" "access" "after" "alias" "all" "and" "architecture" "array"
1588 "assert" "attribute"
1589 "begin" "block" "body" "buffer" "bus"
1590 "case" "component" "configuration" "constant"
1591 "disconnect" "downto"
1592 "else" "elsif" "end" "entity" "exit"
1593 "file" "for" "function"
1594 "generate" "generic" "group" "guarded"
1595 "if" "impure" "in" "inertial" "inout" "is"
1596 "label" "library" "linkage" "literal" "loop"
1597 "map" "mod"
1598 "nand" "new" "next" "nor" "not" "null"
1599 "of" "on" "open" "or" "others" "out"
1600 "package" "port" "postponed" "procedure" "process" "pure"
1601 "range" "record" "register" "reject" "rem" "report" "return"
1602 "rol" "ror"
1603 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
1604 "then" "to" "transport" "type"
1605 "unaffected" "units" "until" "use"
1606 "variable"
1607 "wait" "warning" "when" "while" "with"
1608 "xnor" "xor"
1609 )
1610 "\\|")
1611 "\\)\\>"))
1612 "Regexp for VHDL'93 keywords.")
1613
1614(defconst vhdl-93-types-regexp
1615 (eval-when-compile
1616 (concat
1617 "\\<\\("
1618 (mapconcat
1619 'identity
1620 '(
1621 "boolean" "bit" "bit_vector" "character" "severity_level" "integer"
1622 "real" "time" "natural" "positive" "string" "text" "line"
1623 "unsigned" "signed"
1624 "std_logic" "std_logic_vector"
1625 "std_ulogic" "std_ulogic_vector"
1626 )
1627 "\\|")
1628 "\\)\\>"))
1629 "Regexp for VHDL'93 standardized types.")
1630
1631(defconst vhdl-93-attributes-regexp
1632 (eval-when-compile
1633 (concat
1634 "\\<\\("
1635 (mapconcat
1636 'identity
1637 '(
1638 "base" "left" "right" "high" "low" "pos" "val" "succ"
1639 "pred" "leftof" "rightof" "range" "reverse_range"
1640 "length" "delayed" "stable" "quiet" "transaction"
1641 "event" "active" "last_event" "last_active" "last_value"
1642 "driving" "driving_value" "ascending" "value" "image"
1643 "simple_name" "instance_name" "path_name"
1644 "foreign"
1645 )
1646 "\\|")
1647 "\\)\\>"))
1648 "Regexp for VHDL'93 standardized attributes.")
1649
1650(defconst vhdl-93-enum-values-regexp
1651 (eval-when-compile
1652 (concat
1653 "\\<\\("
1654 (mapconcat
1655 'identity
1656 '(
1657 "true" "false"
1658 "note" "warning" "error" "failure"
1659 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
1660 )
1661 "\\|")
1662 "\\)\\>"))
1663 "Regexp for VHDL'93 standardized enumeration values.")
1664
1665
1666;; ############################################################################
1667;; Syntax analysis and indentation
1668;; ############################################################################
1669
1670;; ############################################################################
1671;; Syntax analysis
1672
1673;; constant regular expressions for looking at various constructs
1674
1675(defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
1676 "Regexp describing a VHDL symbol.
1677We cannot use just `word' syntax class since `_' cannot be in word
1678class. Putting underscore in word class breaks forward word movement
1679behavior that users are familiar with.")
1680
1681(defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
1682 "Regexp describing a case statement header key.")
1683
1684(defconst vhdl-label-key
1685 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
1686 "Regexp describing a VHDL label.")
1687
1688;; Macro definitions:
1689
1690(defmacro vhdl-point (position)
1691 ;; Returns the value of point at certain commonly referenced POSITIONs.
1692 ;; POSITION can be one of the following symbols:
1693 ;;
1694 ;; bol -- beginning of line
1695 ;; eol -- end of line
1696 ;; bod -- beginning of defun
1697 ;; boi -- back to indentation
1698 ;; eoi -- last whitespace on line
1699 ;; ionl -- indentation of next line
1700 ;; iopl -- indentation of previous line
1701 ;; bonl -- beginning of next line
1702 ;; bopl -- beginning of previous line
1703 ;;
1704 ;; This function does not modify point or mark.
1705 (or (and (eq 'quote (car-safe position))
1706 (null (cdr (cdr position))))
1707 (error "bad buffer position requested: %s" position))
1708 (setq position (nth 1 position))
1709 (` (let ((here (point)))
1710 (,@ (cond
1711 ((eq position 'bol) '((beginning-of-line)))
1712 ((eq position 'eol) '((end-of-line)))
1713 ((eq position 'bod) '((save-match-data
1714 (vhdl-beginning-of-defun))))
1715 ((eq position 'boi) '((back-to-indentation)))
1716 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
1717 ((eq position 'bonl) '((forward-line 1)))
1718 ((eq position 'bopl) '((forward-line -1)))
1719 ((eq position 'iopl)
1720 '((forward-line -1)
1721 (back-to-indentation)))
1722 ((eq position 'ionl)
1723 '((forward-line 1)
1724 (back-to-indentation)))
1725 (t (error "unknown buffer position requested: %s" position))
1726 ))
1727 (prog1
1728 (point)
1729 (goto-char here))
1730 ;; workaround for an Emacs18 bug -- blech! Well, at least it
1731 ;; doesn't hurt for v19
1732 (,@ nil)
1733 )))
1734
1735(defmacro vhdl-safe (&rest body)
1736 ;; safely execute BODY, return nil if an error occurred
1737 (` (condition-case nil
1738 (progn (,@ body))
1739 (error nil))))
1740
1741(defmacro vhdl-add-syntax (symbol &optional relpos)
1742 ;; a simple macro to append the syntax in symbol to the syntax list.
1743 ;; try to increase performance by using this macro
1744 (` (setq vhdl-syntactic-context
1745 (cons (cons (, symbol) (, relpos)) vhdl-syntactic-context))))
1746
1747(defmacro vhdl-has-syntax (symbol)
1748 ;; a simple macro to return check the syntax list.
1749 ;; try to increase performance by using this macro
1750 (` (assoc (, symbol) vhdl-syntactic-context)))
1751
1752;; Syntactic element offset manipulation:
1753
1754(defun vhdl-read-offset (langelem)
1755 ;; read new offset value for LANGELEM from minibuffer. return a
1756 ;; legal value only
1757 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
1758 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
1759 (prompt "Offset: ")
1760 offset input interned)
1761 (while (not offset)
1762 (setq input (read-string prompt oldoff)
1763 offset (cond ((string-equal "+" input) '+)
1764 ((string-equal "-" input) '-)
1765 ((string-equal "++" input) '++)
1766 ((string-equal "--" input) '--)
1767 ((string-match "^-?[0-9]+$" input)
1768 (string-to-int input))
1769 ((fboundp (setq interned (intern input)))
1770 interned)
1771 ((boundp interned) interned)
1772 ;; error, but don't signal one, keep trying
1773 ;; to read an input value
1774 (t (ding)
1775 (setq prompt errmsg)
1776 nil))))
1777 offset))
1778
1779(defun vhdl-set-offset (symbol offset &optional add-p)
1780 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
1781SYMBOL is the syntactic element symbol to change and OFFSET is the new
1782offset for that syntactic element. Optional ADD says to add SYMBOL to
1783`vhdl-offsets-alist' if it doesn't already appear there."
1784 (interactive
1785 (let* ((langelem
1786 (intern (completing-read
1787 (concat "Syntactic symbol to change"
1788 (if current-prefix-arg " or add" "")
1789 ": ")
1790 (mapcar
1791 (function
1792 (lambda (langelem)
1793 (cons (format "%s" (car langelem)) nil)))
1794 vhdl-offsets-alist)
1795 nil (not current-prefix-arg)
1796 ;; initial contents tries to be the last element
1797 ;; on the syntactic analysis list for the current
1798 ;; line
1799 (let* ((syntax (vhdl-get-syntactic-context))
1800 (len (length syntax))
1801 (ic (format "%s" (car (nth (1- len) syntax)))))
1802 (if (memq 'v19 vhdl-emacs-features)
1803 (cons ic 0)
1804 ic))
1805 )))
1806 (offset (vhdl-read-offset langelem)))
1807 (list langelem offset current-prefix-arg)))
1808 ;; sanity check offset
1809 (or (eq offset '+)
1810 (eq offset '-)
1811 (eq offset '++)
1812 (eq offset '--)
1813 (integerp offset)
1814 (fboundp offset)
1815 (boundp offset)
1816 (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
1817 offset))
1818 (let ((entry (assq symbol vhdl-offsets-alist)))
1819 (if entry
1820 (setcdr entry offset)
1821 (if add-p
1822 (setq vhdl-offsets-alist (cons (cons symbol offset) vhdl-offsets-alist))
1823 (error "%s is not a valid syntactic symbol." symbol))))
1824 (vhdl-keep-region-active))
1825
1826(defun vhdl-set-style (style &optional local)
1827 "Set vhdl-mode variables to use one of several different indentation styles.
1828STYLE is a string representing the desired style and optional LOCAL is
1829a flag which, if non-nil, means to make the style variables being
1830changed buffer local, instead of the default, which is to set the
1831global variables. Interactively, the flag comes from the prefix
1832argument. The styles are chosen from the `vhdl-style-alist' variable."
1833 (interactive (list (completing-read "Use which VHDL indentation style? "
1834 vhdl-style-alist nil t)
1835 current-prefix-arg))
1836 (let ((vars (cdr (assoc style vhdl-style-alist))))
1837 (or vars
1838 (error "Invalid VHDL indentation style `%s'" style))
1839 ;; set all the variables
1840 (mapcar
1841 (function
1842 (lambda (varentry)
1843 (let ((var (car varentry))
1844 (val (cdr varentry)))
1845 (and local
1846 (make-local-variable var))
1847 ;; special case for vhdl-offsets-alist
1848 (if (not (eq var 'vhdl-offsets-alist))
1849 (set var val)
1850 ;; reset vhdl-offsets-alist to the default value first
1851 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
1852 ;; now set the langelems that are different
1853 (mapcar
1854 (function
1855 (lambda (langentry)
1856 (let ((langelem (car langentry))
1857 (offset (cdr langentry)))
1858 (vhdl-set-offset langelem offset)
1859 )))
1860 val))
1861 )))
1862 vars))
1863 (vhdl-keep-region-active))
1864
1865(defun vhdl-get-offset (langelem)
1866 ;; Get offset from LANGELEM which is a cons cell of the form:
1867 ;; (SYMBOL . RELPOS). The symbol is matched against
1868 ;; vhdl-offsets-alist and the offset found there is either returned,
1869 ;; or added to the indentation at RELPOS. If RELPOS is nil, then
1870 ;; the offset is simply returned.
1871 (let* ((symbol (car langelem))
1872 (relpos (cdr langelem))
1873 (match (assq symbol vhdl-offsets-alist))
1874 (offset (cdr-safe match)))
1875 ;; offset can be a number, a function, a variable, or one of the
1876 ;; symbols + or -
1877 (cond
1878 ((not match)
1879 (if vhdl-strict-syntax-p
1880 (error "don't know how to indent a %s" symbol)
1881 (setq offset 0
1882 relpos 0)))
1883 ((eq offset '+) (setq offset vhdl-basic-offset))
1884 ((eq offset '-) (setq offset (- vhdl-basic-offset)))
1885 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
1886 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
1887 ((and (not (numberp offset))
1888 (fboundp offset))
1889 (setq offset (funcall offset langelem)))
1890 ((not (numberp offset))
1891 (setq offset (eval offset)))
1892 )
1893 (+ (if (and relpos
1894 (< relpos (vhdl-point 'bol)))
1895 (save-excursion
1896 (goto-char relpos)
1897 (current-column))
1898 0)
1899 offset)))
1900
1901;; Syntactic support functions:
1902
1903;; Returns `comment' if in a comment, `string' if in a string literal,
1904;; or nil if not in a literal at all. Optional LIM is used as the
1905;; backward limit of the search. If omitted, or nil, (point-min) is
1906;; used.
1907
1908(defun vhdl-in-literal (&optional lim)
1909 ;; Determine if point is in a VHDL literal.
1910 (save-excursion
1911 (let* ((lim (or lim (point-min)))
1912 (state (parse-partial-sexp lim (point))))
1913 (cond
1914 ((nth 3 state) 'string)
1915 ((nth 4 state) 'comment)
1916 (t nil)))
1917 ))
1918
1919;; This is the best we can do in Win-Emacs.
1920(defun vhdl-win-il (&optional lim)
1921 ;; Determine if point is in a VHDL literal
1922 (save-excursion
1923 (let* ((here (point))
1924 (state nil)
1925 (match nil)
1926 (lim (or lim (vhdl-point 'bod))))
1927 (goto-char lim )
1928 (while (< (point) here)
1929 (setq match
1930 (and (re-search-forward "--\\|[\"']"
1931 here 'move)
1932 (buffer-substring (match-beginning 0) (match-end 0))))
1933 (setq state
1934 (cond
1935 ;; no match
1936 ((null match) nil)
1937 ;; looking at the opening of a VHDL style comment
1938 ((string= "--" match)
1939 (if (<= here (progn (end-of-line) (point))) 'comment))
1940 ;; looking at the opening of a double quote string
1941 ((string= "\"" match)
1942 (if (not (save-restriction
1943 ;; this seems to be necessary since the
1944 ;; re-search-forward will not work without it
1945 (narrow-to-region (point) here)
1946 (re-search-forward
1947 ;; this regexp matches a double quote
1948 ;; which is preceded by an even number
1949 ;; of backslashes, including zero
1950 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
1951 'string))
1952 ;; looking at the opening of a single quote string
1953 ((string= "'" match)
1954 (if (not (save-restriction
1955 ;; see comments from above
1956 (narrow-to-region (point) here)
1957 (re-search-forward
1958 ;; this matches a single quote which is
1959 ;; preceded by zero or two backslashes.
1960 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
1961 here 'move)))
1962 'string))
1963 (t nil)))
1964 ) ; end-while
1965 state)))
1966
1967(and (memq 'Win-Emacs vhdl-emacs-features)
1968 (fset 'vhdl-in-literal 'vhdl-win-il))
1969
1970;; Skipping of "syntactic whitespace". Syntactic whitespace is
1971;; defined as lexical whitespace or comments. Search no farther back
1972;; or forward than optional LIM. If LIM is omitted, (point-min) is
1973;; used for backward skipping, (point-max) is used for forward
1974;; skipping.
1975
1976(defun vhdl-forward-syntactic-ws (&optional lim)
1977 ;; Forward skip of syntactic whitespace.
1978 (save-restriction
1979 (let* ((lim (or lim (point-max)))
1980 (here lim)
1981 (hugenum (point-max)))
1982 (narrow-to-region lim (point))
1983 (while (/= here (point))
1984 (setq here (point))
1985 (forward-comment hugenum))
1986 )))
1987
1988;; This is the best we can do in Win-Emacs.
1989(defun vhdl-win-fsws (&optional lim)
1990 ;; Forward skip syntactic whitespace for Win-Emacs.
1991 (let ((lim (or lim (point-max)))
1992 stop)
1993 (while (not stop)
1994 (skip-chars-forward " \t\n\r\f" lim)
1995 (cond
1996 ;; vhdl comment
1997 ((looking-at "--") (end-of-line))
1998 ;; none of the above
1999 (t (setq stop t))
2000 ))))
2001
2002(and (memq 'Win-Emacs vhdl-emacs-features)
2003 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
2004
2005(defun vhdl-backward-syntactic-ws (&optional lim)
2006 ;; Backward skip over syntactic whitespace.
2007 (save-restriction
2008 (let* ((lim (or lim (point-min)))
2009 (here lim)
2010 (hugenum (- (point-max))))
2011 (if (< lim (point))
2012 (progn
2013 (narrow-to-region lim (point))
2014 (while (/= here (point))
2015 (setq here (point))
2016 (forward-comment hugenum)
2017 )))
2018 )))
2019
2020;; This is the best we can do in Win-Emacs.
2021(defun vhdl-win-bsws (&optional lim)
2022 ;; Backward skip syntactic whitespace for Win-Emacs.
2023 (let ((lim (or lim (vhdl-point 'bod)))
2024 stop)
2025 (while (not stop)
2026 (skip-chars-backward " \t\n\r\f" lim)
2027 (cond
2028 ;; vhdl comment
2029 ((eq (vhdl-in-literal lim) 'comment)
2030 (skip-chars-backward "^-" lim)
2031 (skip-chars-backward "-" lim)
2032 (while (not (or (and (= (following-char) ?-)
2033 (= (char-after (1+ (point))) ?-))
2034 (<= (point) lim)))
2035 (skip-chars-backward "^-" lim)
2036 (skip-chars-backward "-" lim)))
2037 ;; none of the above
2038 (t (setq stop t))
2039 ))))
2040
2041(and (memq 'Win-Emacs vhdl-emacs-features)
2042 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
2043
2044;; Functions to help finding the correct indentation column:
2045
2046(defun vhdl-first-word (point)
2047 "If the keyword at POINT is at boi, then return (current-column) at
2048that point, else nil."
2049 (save-excursion
2050 (and (goto-char point)
2051 (eq (point) (vhdl-point 'boi))
2052 (current-column))))
2053
2054(defun vhdl-last-word (point)
2055 "If the keyword at POINT is at eoi, then return (current-column) at
2056that point, else nil."
2057 (save-excursion
2058 (and (goto-char point)
2059 (save-excursion (or (eq (progn (forward-sexp) (point))
2060 (vhdl-point 'eoi))
2061 (looking-at "\\s-*\\(--\\)?")))
2062 (current-column))))
2063
2064;; Core syntactic evaluation functions:
2065
2066(defconst vhdl-libunit-re
2067 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
2068
2069(defun vhdl-libunit-p ()
2070 (and
2071 (save-excursion
2072 (forward-sexp)
2073 (skip-chars-forward " \t\n")
2074 (not (looking-at "is\\b[^_]")))
2075 (save-excursion
2076 (backward-sexp)
2077 (and (not (looking-at "use\\b[^_]"))
2078 (progn
2079 (forward-sexp)
2080 (vhdl-forward-syntactic-ws)
2081 (/= (following-char) ?:))))
2082 ))
2083
2084(defconst vhdl-defun-re
2085 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedure\\|function\\)\\b[^_]")
2086
2087(defun vhdl-defun-p ()
2088 (save-excursion
2089 (if (looking-at "block\\|process")
2090 ;; "block", "process":
2091 (save-excursion
2092 (backward-sexp)
2093 (not (looking-at "end\\s-+\\w")))
2094 ;; "architecture", "configuration", "entity",
2095 ;; "package", "procedure", "function":
2096 t)))
2097
2098(defun vhdl-corresponding-defun ()
2099 "If the word at the current position corresponds to a \"defun\"
2100keyword, then return a string that can be used to find the
2101corresponding \"begin\" keyword, else return nil."
2102 (save-excursion
2103 (and (looking-at vhdl-defun-re)
2104 (vhdl-defun-p)
2105 (if (looking-at "block\\|process")
2106 ;; "block", "process":
2107 (buffer-substring (match-beginning 0) (match-end 0))
2108 ;; "architecture", "configuration", "entity", "package",
2109 ;; "procedure", "function":
2110 "is"))))
2111
2112(defconst vhdl-begin-fwd-re
2113 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
2114 "A regular expression for searching forward that matches all known
2115\"begin\" keywords.")
2116
2117(defconst vhdl-begin-bwd-re
2118 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|units\\|record\\|for\\)\\b[^_]"
2119 "A regular expression for searching backward that matches all known
2120\"begin\" keywords.")
2121
2122(defun vhdl-begin-p (&optional lim)
2123 "Return t if we are looking at a real \"begin\" keyword.
2124Assumes that the caller will make sure that we are looking at
2125vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
2126the middle of an identifier that just happens to contain a \"begin\"
2127keyword."
2128 (cond
2129 ;; "[architecture|case|configuration|entity|package|
2130 ;; procedure|function] ... is":
2131 ((and (looking-at "i")
2132 (save-excursion
2133 ;; Skip backward over first sexp (needed to skip over a
2134 ;; procedure interface list, and is harmless in other
2135 ;; situations). Note that we need "return" in the
2136 ;; following search list so that we don't run into
2137 ;; semicolons in the function interface list.
2138 (backward-sexp)
2139 (let (foundp)
2140 (while (and (not foundp)
2141 (re-search-backward
2142 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|block\\)\\b[^_]"
2143 lim 'move))
2144 (if (or (= (preceding-char) ?_)
2145 (vhdl-in-literal lim))
2146 (backward-char)
2147 (setq foundp t))))
2148 (and (/= (following-char) ?\;)
2149 (not (looking-at "is\\|begin\\|process\\|block")))))
2150 t)
2151 ;; "begin", "then":
2152 ((looking-at "be\\|t")
2153 t)
2154 ;; "else":
2155 ((and (looking-at "e")
2156 ;; make sure that the "else" isn't inside a
2157 ;; conditional signal assignment.
2158 (save-excursion
2159 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
2160 (or (eq (following-char) ?\;)
2161 (eq (point) lim))))
2162 t)
2163 ;; "block", "generate", "loop", "process",
2164 ;; "units", "record":
2165 ((and (looking-at "bl\\|[glpur]")
2166 (save-excursion
2167 (backward-sexp)
2168 (not (looking-at "end\\s-+\\w"))))
2169 t)
2170 ;; "component":
2171 ((and (looking-at "c")
2172 (save-excursion
2173 (backward-sexp)
2174 (not (looking-at "end\\s-+\\w")))
2175 ;; look out for the dreaded entity class in an attribute
2176 (save-excursion
2177 (vhdl-backward-syntactic-ws lim)
2178 (/= (preceding-char) ?:)))
2179 t)
2180 ;; "for" (inside configuration declaration):
2181 ((and (looking-at "f")
2182 (save-excursion
2183 (backward-sexp)
2184 (not (looking-at "end\\s-+\\w")))
2185 (vhdl-has-syntax 'configuration))
2186 t)
2187 ))
2188
2189(defun vhdl-corresponding-mid (&optional lim)
2190 (cond
2191 ((looking-at "is\\|block\\|process")
2192 "begin")
2193 ((looking-at "then")
2194 "<else>")
2195 (t
2196 "end")))
2197
2198(defun vhdl-corresponding-end (&optional lim)
2199 "If the word at the current position corresponds to a \"begin\"
2200keyword, then return a vector containing enough information to find
2201the corresponding \"end\" keyword, else return nil. The keyword to
2202search forward for is aref 0. The column in which the keyword must
2203appear is aref 1 or nil if any column is suitable.
2204Assumes that the caller will make sure that we are not in the middle
2205of an identifier that just happens to contain a \"begin\" keyword."
2206 (save-excursion
2207 (and (looking-at vhdl-begin-fwd-re)
2208 (/= (preceding-char) ?_)
2209 (not (vhdl-in-literal lim))
2210 (vhdl-begin-p lim)
2211 (cond
2212 ;; "is", "generate", "loop":
2213 ((looking-at "[igl]")
2214 (vector "end"
2215 (and (vhdl-last-word (point))
2216 (or (vhdl-first-word (point))
2217 (save-excursion
2218 (vhdl-beginning-of-statement-1 lim)
2219 (vhdl-backward-skip-label lim)
2220 (vhdl-first-word (point)))))))
2221 ;; "begin", "else", "for":
2222 ((looking-at "be\\|[ef]")
2223 (vector "end"
2224 (and (vhdl-last-word (point))
2225 (or (vhdl-first-word (point))
2226 (save-excursion
2227 (vhdl-beginning-of-statement-1 lim)
2228 (vhdl-backward-skip-label lim)
2229 (vhdl-first-word (point)))))))
2230 ;; "component", "units", "record":
2231 ((looking-at "[cur]")
2232 ;; The first end found will close the block
2233 (vector "end" nil))
2234 ;; "block", "process":
2235 ((looking-at "bl\\|p")
2236 (vector "end"
2237 (or (vhdl-first-word (point))
2238 (save-excursion
2239 (vhdl-beginning-of-statement-1 lim)
2240 (vhdl-backward-skip-label lim)
2241 (vhdl-first-word (point))))))
2242 ;; "then":
2243 ((looking-at "t")
2244 (vector "elsif\\|else\\|end\\s-+if"
2245 (and (vhdl-last-word (point))
2246 (or (vhdl-first-word (point))
2247 (save-excursion
2248 (vhdl-beginning-of-statement-1 lim)
2249 (vhdl-backward-skip-label lim)
2250 (vhdl-first-word (point)))))))
2251 ))))
2252
2253(defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
2254
2255(defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
2256
2257(defun vhdl-end-p (&optional lim)
2258 "Return t if we are looking at a real \"end\" keyword.
2259Assumes that the caller will make sure that we are looking at
2260vhdl-end-fwd-re, and are not inside a literal, and that we are not in
2261the middle of an identifier that just happens to contain an \"end\"
2262keyword."
2263 (or (not (looking-at "else"))
2264 ;; make sure that the "else" isn't inside a conditional signal
2265 ;; assignment.
2266 (save-excursion
2267 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
2268 (or (eq (following-char) ?\;)
2269 (eq (point) lim)))))
2270
2271(defun vhdl-corresponding-begin (&optional lim)
2272 "If the word at the current position corresponds to an \"end\"
2273keyword, then return a vector containing enough information to find
2274the corresponding \"begin\" keyword, else return nil. The keyword to
2275search backward for is aref 0. The column in which the keyword must
2276appear is aref 1 or nil if any column is suitable. The supplementary
2277keyword to search forward for is aref 2 or nil if this is not
2278required. If aref 3 is t, then the \"begin\" keyword may be found in
2279the middle of a statement.
2280Assumes that the caller will make sure that we are not in the middle
2281of an identifier that just happens to contain an \"end\" keyword."
2282 (save-excursion
2283 (let (pos)
2284 (if (and (looking-at vhdl-end-fwd-re)
2285 (not (vhdl-in-literal lim))
2286 (vhdl-end-p lim))
2287 (if (looking-at "el")
2288 ;; "else", "elsif":
2289 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
2290 ;; "end ...":
2291 (setq pos (point))
2292 (forward-sexp)
2293 (skip-chars-forward " \t\n")
2294 (cond
2295 ;; "end if":
2296 ((looking-at "if\\b[^_]")
2297 (vector "else\\|elsif\\|if"
2298 (vhdl-first-word pos)
2299 "else\\|then" nil))
2300 ;; "end component":
2301 ((looking-at "component\\b[^_]")
2302 (vector (buffer-substring (match-beginning 1)
2303 (match-end 1))
2304 (vhdl-first-word pos)
2305 nil nil))
2306 ;; "end units", "end record":
2307 ((looking-at "\\(units\\|record\\)\\b[^_]")
2308 (vector (buffer-substring (match-beginning 1)
2309 (match-end 1))
2310 (vhdl-first-word pos)
2311 nil t))
2312 ;; "end block", "end process":
2313 ((looking-at "\\(block\\|process\\)\\b[^_]")
2314 (vector "begin" (vhdl-first-word pos) nil nil))
2315 ;; "end case":
2316 ((looking-at "case\\b[^_]")
2317 (vector "case" (vhdl-first-word pos) "is" nil))
2318 ;; "end generate":
2319 ((looking-at "generate\\b[^_]")
2320 (vector "generate\\|for\\|if"
2321 (vhdl-first-word pos)
2322 "generate" nil))
2323 ;; "end loop":
2324 ((looking-at "loop\\b[^_]")
2325 (vector "loop\\|while\\|for"
2326 (vhdl-first-word pos)
2327 "loop" nil))
2328 ;; "end for" (inside configuration declaration):
2329 ((looking-at "for\\b[^_]")
2330 (vector "for" (vhdl-first-word pos) nil nil))
2331 ;; "end [id]":
2332 (t
2333 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
2334 (vhdl-first-word pos)
2335 ;; return an alist of (statement . keyword) mappings
2336 '(
2337 ;; "begin ... end [id]":
2338 ("begin" . nil)
2339 ;; "architecture ... is ... begin ... end [id]":
2340 ("architecture" . "is")
2341 ;; "configuration ... is ... end [id]":
2342 ("configuration" . "is")
2343 ;; "entity ... is ... end [id]":
2344 ("entity" . "is")
2345 ;; "package ... is ... end [id]":
2346 ("package" . "is")
2347 ;; "procedure ... is ... begin ... end [id]":
2348 ("procedure" . "is")
2349 ;; "function ... is ... begin ... end [id]":
2350 ("function" . "is")
2351 )
2352 nil))
2353 ))) ; "end ..."
2354 )))
2355
2356(defconst vhdl-leader-re
2357 "\\b\\(block\\|component\\|process\\|for\\)\\b[^_]")
2358
2359(defun vhdl-end-of-leader ()
2360 (save-excursion
2361 (cond ((looking-at "block\\|process")
2362 (if (save-excursion
2363 (forward-sexp)
2364 (skip-chars-forward " \t\n")
2365 (= (following-char) ?\())
2366 (forward-sexp 2)
2367 (forward-sexp))
2368 (point))
2369 ((looking-at "component")
2370 (forward-sexp 2)
2371 (point))
2372 ((looking-at "for")
2373 (forward-sexp 2)
2374 (skip-chars-forward " \t\n")
2375 (while (looking-at "[,:(]")
2376 (forward-sexp)
2377 (skip-chars-forward " \t\n"))
2378 (point))
2379 (t nil)
2380 )))
2381
2382(defconst vhdl-trailer-re
2383 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
2384
2385(defconst vhdl-statement-fwd-re
2386 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
2387 "A regular expression for searching forward that matches all known
2388\"statement\" keywords.")
2389
2390(defconst vhdl-statement-bwd-re
2391 "\\b\\(if\\|for\\|while\\)\\b[^_]"
2392 "A regular expression for searching backward that matches all known
2393\"statement\" keywords.")
2394
2395(defun vhdl-statement-p (&optional lim)
2396 "Return t if we are looking at a real \"statement\" keyword.
2397Assumes that the caller will make sure that we are looking at
2398vhdl-statement-fwd-re, and are not inside a literal, and that we are not in
2399the middle of an identifier that just happens to contain a \"statement\"
2400keyword."
2401 (cond
2402 ;; "for" ... "generate":
2403 ((and (looking-at "f")
2404 ;; Make sure it's the start of a parameter specification.
2405 (save-excursion
2406 (forward-sexp 2)
2407 (skip-chars-forward " \t\n")
2408 (looking-at "in\\b[^_]"))
2409 ;; Make sure it's not an "end for".
2410 (save-excursion
2411 (backward-sexp)
2412 (not (looking-at "end\\s-+\\w"))))
2413 t)
2414 ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
2415 ((and (looking-at "i")
2416 ;; Make sure it's not an "end if".
2417 (save-excursion
2418 (backward-sexp)
2419 (not (looking-at "end\\s-+\\w"))))
2420 t)
2421 ;; "while" ... "loop":
2422 ((looking-at "w")
2423 t)
2424 ))
2425
2426(defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
2427 "Regexp describing a case statement alternative key.")
2428
2429(defun vhdl-case-alternative-p (&optional lim)
2430 "Return t if we are looking at a real case alternative.
2431Assumes that the caller will make sure that we are looking at
2432vhdl-case-alternative-re, and are not inside a literal, and that
2433we are not in the middle of an identifier that just happens to
2434contain a \"when\" keyword."
2435 (save-excursion
2436 (let (foundp)
2437 (while (and (not foundp)
2438 (re-search-backward ";\\|<=" lim 'move))
2439 (if (or (= (preceding-char) ?_)
2440 (vhdl-in-literal lim))
2441 (backward-char)
2442 (setq foundp t)))
2443 (or (eq (following-char) ?\;)
2444 (eq (point) lim)))
2445 ))
2446
2447;; Core syntactic movement functions:
2448
2449(defconst vhdl-b-t-b-re
2450 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
2451
2452(defun vhdl-backward-to-block (&optional lim)
2453 "Move backward to the previous \"begin\" or \"end\" keyword."
2454 (let (foundp)
2455 (while (and (not foundp)
2456 (re-search-backward vhdl-b-t-b-re lim 'move))
2457 (if (or (= (preceding-char) ?_)
2458 (vhdl-in-literal lim))
2459 (backward-char)
2460 (cond
2461 ;; "begin" keyword:
2462 ((and (looking-at vhdl-begin-fwd-re)
2463 (/= (preceding-char) ?_)
2464 (vhdl-begin-p lim))
2465 (setq foundp 'begin))
2466 ;; "end" keyword:
2467 ((and (looking-at vhdl-end-fwd-re)
2468 (/= (preceding-char) ?_)
2469 (vhdl-end-p lim))
2470 (setq foundp 'end))
2471 ))
2472 )
2473 foundp
2474 ))
2475
2476(defun vhdl-forward-sexp (&optional count lim)
2477 "Move forward across one balanced expression (sexp).
2478With COUNT, do it that many times."
2479 (interactive "p")
2480 (let ((count (or count 1))
2481 (case-fold-search t)
2482 end-vec target)
2483 (save-excursion
2484 (while (> count 0)
2485 ;; skip whitespace
2486 (skip-chars-forward " \t\n")
2487 ;; Check for an unbalanced "end" keyword
2488 (if (and (looking-at vhdl-end-fwd-re)
2489 (/= (preceding-char) ?_)
2490 (not (vhdl-in-literal lim))
2491 (vhdl-end-p lim)
2492 (not (looking-at "else")))
2493 (error
2494 "Containing expression ends prematurely in vhdl-forward-sexp"))
2495 ;; If the current keyword is a "begin" keyword, then find the
2496 ;; corresponding "end" keyword.
2497 (if (setq end-vec (vhdl-corresponding-end lim))
2498 (let (
2499 ;; end-re is the statement keyword to search for
2500 (end-re
2501 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
2502 ;; column is either the statement keyword target column
2503 ;; or nil
2504 (column (aref end-vec 1))
2505 (eol (vhdl-point 'eol))
2506 foundp literal placeholder)
2507 ;; Look for the statement keyword.
2508 (while (and (not foundp)
2509 (re-search-forward end-re nil t)
2510 (setq placeholder (match-end 1))
2511 (goto-char (match-beginning 0)))
2512 ;; If we are in a literal, or not in the right target
2513 ;; column and not on the same line as the begin, then
2514 ;; try again.
2515 (if (or (and column
2516 (/= (current-indentation) column)
2517 (> (point) eol))
2518 (= (preceding-char) ?_)
2519 (setq literal (vhdl-in-literal lim)))
2520 (if (eq literal 'comment)
2521 (end-of-line)
2522 (forward-char))
2523 ;; An "else" keyword corresponds to both the opening brace
2524 ;; of the following sexp and the closing brace of the
2525 ;; previous sexp.
2526 (if (not (looking-at "else"))
2527 (goto-char placeholder))
2528 (setq foundp t))
2529 )
2530 (if (not foundp)
2531 (error "Unbalanced keywords in vhdl-forward-sexp"))
2532 )
2533 ;; If the current keyword is not a "begin" keyword, then just
2534 ;; perform the normal forward-sexp.
2535 (forward-sexp)
2536 )
2537 (setq count (1- count))
2538 )
2539 (setq target (point)))
2540 (goto-char target)
2541 nil))
2542
2543(defun vhdl-backward-sexp (&optional count lim)
2544 "Move backward across one balanced expression (sexp).
2545With COUNT, do it that many times. LIM bounds any required backward
2546searches."
2547 (interactive "p")
2548 (let ((count (or count 1))
2549 (case-fold-search t)
2550 begin-vec target)
2551 (save-excursion
2552 (while (> count 0)
2553 ;; Perform the normal backward-sexp, unless we are looking at
2554 ;; "else" - an "else" keyword corresponds to both the opening brace
2555 ;; of the following sexp and the closing brace of the previous sexp.
2556 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
2557 (/= (preceding-char) ?_)
2558 (not (vhdl-in-literal lim)))
2559 nil
2560 (backward-sexp)
2561 (if (and (looking-at vhdl-begin-fwd-re)
2562 (/= (preceding-char) ?_)
2563 (not (vhdl-in-literal lim))
2564 (vhdl-begin-p lim))
2565 (error "Containing expression ends prematurely in vhdl-backward-sexp")))
2566 ;; If the current keyword is an "end" keyword, then find the
2567 ;; corresponding "begin" keyword.
2568 (if (and (setq begin-vec (vhdl-corresponding-begin lim))
2569 (/= (preceding-char) ?_))
2570 (let (
2571 ;; begin-re is the statement keyword to search for
2572 (begin-re
2573 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
2574 ;; column is either the statement keyword target column
2575 ;; or nil
2576 (column (aref begin-vec 1))
2577 ;; internal-p controls where the statement keyword can
2578 ;; be found.
2579 (internal-p (aref begin-vec 3))
2580 (last-backward (point)) last-forward
2581 foundp literal keyword)
2582 ;; Look for the statement keyword.
2583 (while (and (not foundp)
2584 (re-search-backward begin-re lim t)
2585 (setq keyword
2586 (buffer-substring (match-beginning 1)
2587 (match-end 1))))
2588 ;; If we are in a literal or in the wrong column,
2589 ;; then try again.
2590 (if (or (and column
2591 (and (/= (current-indentation) column)
2592 ;; possibly accept current-column as
2593 ;; well as current-indentation.
2594 (or (not internal-p)
2595 (/= (current-column) column))))
2596 (= (preceding-char) ?_)
2597 (vhdl-in-literal lim))
2598 (backward-char)
2599 ;; If there is a supplementary keyword, then
2600 ;; search forward for it.
2601 (if (and (setq begin-re (aref begin-vec 2))
2602 (or (not (listp begin-re))
2603 ;; If begin-re is an alist, then find the
2604 ;; element corresponding to the actual
2605 ;; keyword that we found.
2606 (progn
2607 (setq begin-re
2608 (assoc keyword begin-re))
2609 (and begin-re
2610 (setq begin-re (cdr begin-re))))))
2611 (and
2612 (setq begin-re
2613 (concat "\\b\\(" begin-re "\\)\\b[^_]"))
2614 (save-excursion
2615 (setq last-forward (point))
2616 ;; Look for the supplementary keyword
2617 ;; (bounded by the backward search start
2618 ;; point).
2619 (while (and (not foundp)
2620 (re-search-forward begin-re
2621 last-backward t)
2622 (goto-char (match-beginning 1)))
2623 ;; If we are in a literal, then try again.
2624 (if (or (= (preceding-char) ?_)
2625 (setq literal
2626 (vhdl-in-literal last-forward)))
2627 (if (eq literal 'comment)
2628 (goto-char
2629 (min (vhdl-point 'eol) last-backward))
2630 (forward-char))
2631 ;; We have found the supplementary keyword.
2632 ;; Save the position of the keyword in foundp.
2633 (setq foundp (point)))
2634 )
2635 foundp)
2636 ;; If the supplementary keyword was found, then
2637 ;; move point to the supplementary keyword.
2638 (goto-char foundp))
2639 ;; If there was no supplementary keyword, then
2640 ;; point is already at the statement keyword.
2641 (setq foundp t)))
2642 ) ; end of the search for the statement keyword
2643 (if (not foundp)
2644 (error "Unbalanced keywords in vhdl-backward-sexp"))
2645 ))
2646 (setq count (1- count))
2647 )
2648 (setq target (point)))
2649 (goto-char target)
2650 nil))
2651
2652(defun vhdl-backward-up-list (&optional count limit)
2653 "Move backward out of one level of blocks.
2654With argument, do this that many times."
2655 (interactive "p")
2656 (let ((count (or count 1))
2657 target)
2658 (save-excursion
2659 (while (> count 0)
2660 (if (looking-at vhdl-defun-re)
2661 (error "Unbalanced blocks"))
2662 (vhdl-backward-to-block limit)
2663 (setq count (1- count)))
2664 (setq target (point)))
2665 (goto-char target)))
2666
2667(defun vhdl-end-of-defun (&optional count)
2668 "Move forward to the end of a VHDL defun."
2669 (interactive)
2670 (let ((case-fold-search t))
2671 (vhdl-beginning-of-defun)
2672 (if (not (looking-at "block\\|process"))
2673 (re-search-forward "\\bis\\b"))
2674 (vhdl-forward-sexp)))
2675
2676(defun vhdl-mark-defun ()
2677 "Put mark at end of this \"defun\", point at beginning."
2678 (interactive)
2679 (let ((case-fold-search t))
2680 (push-mark)
2681 (vhdl-beginning-of-defun)
2682 (push-mark)
2683 (if (not (looking-at "block\\|process"))
2684 (re-search-forward "\\bis\\b"))
2685 (vhdl-forward-sexp)
2686 (exchange-point-and-mark)))
2687
2688(defun vhdl-beginning-of-libunit ()
2689 "Move backward to the beginning of a VHDL library unit.
2690Returns the location of the corresponding begin keyword, unless search
2691stops due to beginning or end of buffer."
2692 ;; Note that if point is between the "libunit" keyword and the
2693 ;; corresponding "begin" keyword, then that libunit will not be
2694 ;; recognised, and the search will continue backwards. If point is
2695 ;; at the "begin" keyword, then the defun will be recognised. The
2696 ;; returned point is at the first character of the "libunit" keyword.
2697 (let ((last-forward (point))
2698 (last-backward
2699 ;; Just in case we are actually sitting on the "begin"
2700 ;; keyword, allow for the keyword and an extra character,
2701 ;; as this will be used when looking forward for the
2702 ;; "begin" keyword.
2703 (save-excursion (forward-word 1) (1+ (point))))
2704 foundp literal placeholder)
2705 ;; Find the "libunit" keyword.
2706 (while (and (not foundp)
2707 (re-search-backward vhdl-libunit-re nil 'move))
2708 ;; If we are in a literal, or not at a real libunit, then try again.
2709 (if (or (= (preceding-char) ?_)
2710 (vhdl-in-literal (point-min))
2711 (not (vhdl-libunit-p)))
2712 (backward-char)
2713 ;; Find the corresponding "begin" keyword.
2714 (setq last-forward (point))
2715 (while (and (not foundp)
2716 (re-search-forward "\\bis\\b[^_]" last-backward t)
2717 (setq placeholder (match-beginning 0)))
2718 (if (or (= (preceding-char) ?_)
2719 (setq literal (vhdl-in-literal last-forward)))
2720 ;; It wasn't a real keyword, so keep searching.
2721 (if (eq literal 'comment)
2722 (goto-char
2723 (min (vhdl-point 'eol) last-backward))
2724 (forward-char))
2725 ;; We have found the begin keyword, loop will exit.
2726 (setq foundp placeholder)))
2727 ;; Go back to the libunit keyword
2728 (goto-char last-forward)))
2729 foundp))
2730
2731(defun vhdl-beginning-of-defun (&optional count)
2732 "Move backward to the beginning of a VHDL defun.
2733With argument, do it that many times.
2734Returns the location of the corresponding begin keyword, unless search
2735stops due to beginning or end of buffer."
2736 ;; Note that if point is between the "defun" keyword and the
2737 ;; corresponding "begin" keyword, then that defun will not be
2738 ;; recognised, and the search will continue backwards. If point is
2739 ;; at the "begin" keyword, then the defun will be recognised. The
2740 ;; returned point is at the first character of the "defun" keyword.
2741 (interactive "p")
2742 (let ((count (or count 1))
2743 (case-fold-search t)
2744 (last-forward (point))
2745 foundp)
2746 (while (> count 0)
2747 (setq foundp nil)
2748 (goto-char last-forward)
2749 (let ((last-backward
2750 ;; Just in case we are actually sitting on the "begin"
2751 ;; keyword, allow for the keyword and an extra character,
2752 ;; as this will be used when looking forward for the
2753 ;; "begin" keyword.
2754 (save-excursion (forward-word 1) (1+ (point))))
2755 begin-string literal)
2756 (while (and (not foundp)
2757 (re-search-backward vhdl-defun-re nil 'move))
2758 ;; If we are in a literal, then try again.
2759 (if (or (= (preceding-char) ?_)
2760 (vhdl-in-literal (point-min)))
2761 (backward-char)
2762 (if (setq begin-string (vhdl-corresponding-defun))
2763 ;; This is a real defun keyword.
2764 ;; Find the corresponding "begin" keyword.
2765 ;; Look for the begin keyword.
2766 (progn
2767 ;; Save the search start point.
2768 (setq last-forward (point))
2769 (while (and (not foundp)
2770 (search-forward begin-string last-backward t))
2771 (if (or (= (preceding-char) ?_)
2772 (save-match-data
2773 (setq literal (vhdl-in-literal last-forward))))
2774 ;; It wasn't a real keyword, so keep searching.
2775 (if (eq literal 'comment)
2776 (goto-char
2777 (min (vhdl-point 'eol) last-backward))
2778 (forward-char))
2779 ;; We have found the begin keyword, loop will exit.
2780 (setq foundp (match-beginning 0)))
2781 )
2782 ;; Go back to the defun keyword
2783 (goto-char last-forward)) ; end search for begin keyword
2784 ))
2785 ) ; end of the search for the defun keyword
2786 )
2787 (setq count (1- count))
2788 )
2789 (vhdl-keep-region-active)
2790 foundp))
2791
2792(defun vhdl-beginning-of-statement (&optional count lim)
2793 "Go to the beginning of the innermost VHDL statement.
2794With prefix arg, go back N - 1 statements. If already at the
2795beginning of a statement then go to the beginning of the preceding
2796one. If within a string or comment, or next to a comment (only
2797whitespace between), move by sentences instead of statements.
2798
2799When called from a program, this function takes 2 optional args: the
2800prefix arg, and a buffer position limit which is the farthest back to
2801search."
2802 (interactive "p")
2803 (let ((count (or count 1))
2804 (case-fold-search t)
2805 (lim (or lim (point-min)))
2806 (here (point))
2807 state)
2808 (save-excursion
2809 (goto-char lim)
2810 (setq state (parse-partial-sexp (point) here nil nil)))
2811 (if (and (interactive-p)
2812 (or (nth 3 state)
2813 (nth 4 state)
2814 (looking-at (concat "[ \t]*" comment-start-skip))))
2815 (forward-sentence (- count))
2816 (while (> count 0)
2817 (vhdl-beginning-of-statement-1 lim)
2818 (setq count (1- count))))
2819 ;; its possible we've been left up-buf of lim
2820 (goto-char (max (point) lim))
2821 )
2822 (vhdl-keep-region-active))
2823
2824(defconst vhdl-e-o-s-re
2825 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
2826
2827(defun vhdl-end-of-statement ()
2828 "Very simple implementation."
2829 (interactive)
2830 (re-search-forward vhdl-e-o-s-re))
2831
2832(defconst vhdl-b-o-s-re
2833 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
2834 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
2835
2836(defun vhdl-beginning-of-statement-1 (&optional lim)
2837 ;; move to the start of the current statement, or the previous
2838 ;; statement if already at the beginning of one.
2839 (let ((lim (or lim (point-min)))
2840 (here (point))
2841 (pos (point))
2842 donep)
2843 ;; go backwards one balanced expression, but be careful of
2844 ;; unbalanced paren being reached
2845 (if (not (vhdl-safe (progn (backward-sexp) t)))
2846 (progn
2847 (backward-up-list 1)
2848 (forward-char)
2849 (vhdl-forward-syntactic-ws here)
2850 (setq donep t)))
2851 (while (and (not donep)
2852 (not (bobp))
2853 ;; look backwards for a statement boundary
2854 (re-search-backward vhdl-b-o-s-re lim 'move))
2855 (if (or (= (preceding-char) ?_)
2856 (vhdl-in-literal lim))
2857 (backward-char)
2858 (cond
2859 ;; If we are looking at an open paren, then stop after it
2860 ((eq (following-char) ?\()
2861 (forward-char)
2862 (vhdl-forward-syntactic-ws here)
2863 (setq donep t))
2864 ;; If we are looking at a close paren, then skip it
2865 ((eq (following-char) ?\))
2866 (forward-char)
2867 (setq pos (point))
2868 (backward-sexp)
2869 (if (< (point) lim)
2870 (progn (goto-char pos)
2871 (vhdl-forward-syntactic-ws here)
2872 (setq donep t))))
2873 ;; If we are looking at a semicolon, then stop
2874 ((eq (following-char) ?\;)
2875 (progn
2876 (forward-char)
2877 (vhdl-forward-syntactic-ws here)
2878 (setq donep t)))
2879 ;; If we are looking at a "begin", then stop
2880 ((and (looking-at vhdl-begin-fwd-re)
2881 (/= (preceding-char) ?_)
2882 (vhdl-begin-p nil))
2883 ;; If it's a leader "begin", then find the
2884 ;; right place
2885 (if (looking-at vhdl-leader-re)
2886 (save-excursion
2887 ;; set a default stop point at the begin
2888 (setq pos (point))
2889 ;; is the start point inside the leader area ?
2890 (goto-char (vhdl-end-of-leader))
2891 (vhdl-forward-syntactic-ws here)
2892 (if (< (point) here)
2893 ;; start point was not inside leader area
2894 ;; set stop point at word after leader
2895 (setq pos (point))))
2896 (forward-word 1)
2897 (vhdl-forward-syntactic-ws here)
2898 (setq pos (point)))
2899 (goto-char pos)
2900 (setq donep t))
2901 ;; If we are looking at a "statement", then stop
2902 ((and (looking-at vhdl-statement-fwd-re)
2903 (/= (preceding-char) ?_)
2904 (vhdl-statement-p nil))
2905 (setq donep t))
2906 ;; If we are looking at a case alternative key, then stop
2907 ((and (looking-at vhdl-case-alternative-re)
2908 (vhdl-case-alternative-p lim))
2909 (save-excursion
2910 ;; set a default stop point at the when
2911 (setq pos (point))
2912 ;; is the start point inside the case alternative key ?
2913 (looking-at vhdl-case-alternative-re)
2914 (goto-char (match-end 0))
2915 (vhdl-forward-syntactic-ws here)
2916 (if (< (point) here)
2917 ;; start point was not inside the case alternative key
2918 ;; set stop point at word after case alternative keyleader
2919 (setq pos (point))))
2920 (goto-char pos)
2921 (setq donep t))
2922 ;; Bogus find, continue
2923 (t
2924 (backward-char)))))
2925 ))
2926
2927;; Defuns for calculating the current syntactic state:
2928
2929(defun vhdl-get-library-unit (bod placeholder)
2930 ;; If there is an enclosing library unit at bod, with it's \"begin\"
2931 ;; keyword at placeholder, then return the library unit type.
2932 (let ((here (vhdl-point 'bol)))
2933 (if (save-excursion
2934 (goto-char placeholder)
2935 (vhdl-safe (vhdl-forward-sexp 1 bod))
2936 (<= here (point)))
2937 (save-excursion
2938 (goto-char bod)
2939 (cond
2940 ((looking-at "e") 'entity)
2941 ((looking-at "a") 'architecture)
2942 ((looking-at "c") 'configuration)
2943 ((looking-at "p")
2944 (save-excursion
2945 (goto-char bod)
2946 (forward-sexp)
2947 (vhdl-forward-syntactic-ws here)
2948 (if (looking-at "body\\b[^_]")
2949 'package-body 'package))))))
2950 ))
2951
2952(defun vhdl-get-block-state (&optional lim)
2953 ;; Finds and records all the closest opens.
2954 ;; lim is the furthest back we need to search (it should be the
2955 ;; previous libunit keyword).
2956 (let ((here (point))
2957 (lim (or lim (point-min)))
2958 keyword sexp-start sexp-mid sexp-end
2959 preceding-sexp containing-sexp
2960 containing-begin containing-mid containing-paren)
2961 (save-excursion
2962 ;; Find the containing-paren, and use that as the limit
2963 (if (setq containing-paren
2964 (save-restriction
2965 (narrow-to-region lim (point))
2966 (vhdl-safe (scan-lists (point) -1 1))))
2967 (setq lim containing-paren))
2968 ;; Look backwards for "begin" and "end" keywords.
2969 (while (and (> (point) lim)
2970 (not containing-sexp))
2971 (setq keyword (vhdl-backward-to-block lim))
2972 (cond
2973 ((eq keyword 'begin)
2974 ;; Found a "begin" keyword
2975 (setq sexp-start (point))
2976 (setq sexp-mid (vhdl-corresponding-mid lim))
2977 (setq sexp-end (vhdl-safe
2978 (save-excursion
2979 (vhdl-forward-sexp 1 lim) (point))))
2980 (if (and sexp-end (<= sexp-end here))
2981 ;; we want to record this sexp, but we only want to
2982 ;; record the last-most of any of them before here
2983 (or preceding-sexp
2984 (setq preceding-sexp sexp-start))
2985 ;; we're contained in this sexp so put sexp-start on
2986 ;; front of list
2987 (setq containing-sexp sexp-start)
2988 (setq containing-mid sexp-mid)
2989 (setq containing-begin t)))
2990 ((eq keyword 'end)
2991 ;; Found an "end" keyword
2992 (forward-sexp)
2993 (setq sexp-end (point))
2994 (setq sexp-mid nil)
2995 (setq sexp-start
2996 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
2997 (progn (backward-sexp) (point))))
2998 ;; we want to record this sexp, but we only want to
2999 ;; record the last-most of any of them before here
3000 (or preceding-sexp
3001 (setq preceding-sexp sexp-start)))
3002 )))
3003 ;; Check if the containing-paren should be the containing-sexp
3004 (if (and containing-paren
3005 (or (null containing-sexp)
3006 (< containing-sexp containing-paren)))
3007 (setq containing-sexp containing-paren
3008 preceding-sexp nil
3009 containing-begin nil
3010 containing-mid nil))
3011 (vector containing-sexp preceding-sexp containing-begin containing-mid)
3012 ))
3013
3014
3015(defconst vhdl-s-c-a-re
3016 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
3017
3018(defun vhdl-skip-case-alternative (&optional lim)
3019 ;; skip forward over case/when bodies, with optional maximal
3020 ;; limit. if no next case alternative is found, nil is returned and point
3021 ;; is not moved
3022 (let ((lim (or lim (point-max)))
3023 (here (point))
3024 donep foundp)
3025 (while (and (< (point) lim)
3026 (not donep))
3027 (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
3028 (save-match-data
3029 (not (vhdl-in-literal)))
3030 (/= (match-beginning 0) here))
3031 (progn
3032 (goto-char (match-beginning 0))
3033 (cond
3034 ((and (looking-at "case")
3035 (re-search-forward "\\bis[^_]" lim t))
3036 (backward-sexp)
3037 (vhdl-forward-sexp))
3038 (t
3039 (setq donep t
3040 foundp t))))))
3041 (if (not foundp)
3042 (goto-char here))
3043 foundp))
3044
3045(defun vhdl-backward-skip-label (&optional lim)
3046 ;; skip backward over a label, with optional maximal
3047 ;; limit. if label is not found, nil is returned and point
3048 ;; is not moved
3049 (let ((lim (or lim (point-min)))
3050 placeholder)
3051 (if (save-excursion
3052 (vhdl-backward-syntactic-ws lim)
3053 (and (eq (preceding-char) ?:)
3054 (progn
3055 (backward-sexp)
3056 (setq placeholder (point))
3057 (looking-at vhdl-label-key))))
3058 (goto-char placeholder))
3059 ))
3060
3061(defun vhdl-forward-skip-label (&optional lim)
3062 ;; skip forward over a label, with optional maximal
3063 ;; limit. if label is not found, nil is returned and point
3064 ;; is not moved
3065 (let ((lim (or lim (point-max))))
3066 (if (looking-at vhdl-label-key)
3067 (progn
3068 (goto-char (match-end 0))
3069 (vhdl-forward-syntactic-ws lim)))
3070 ))
3071
3072(defun vhdl-get-syntactic-context ()
3073 ;; guess the syntactic description of the current line of VHDL code.
3074 (save-excursion
3075 (save-restriction
3076 (beginning-of-line)
3077 (let* ((indent-point (point))
3078 (case-fold-search t)
3079 vec literal containing-sexp preceding-sexp
3080 containing-begin containing-mid containing-leader
3081 char-before-ip char-after-ip begin-after-ip end-after-ip
3082 placeholder lim library-unit
3083 )
3084
3085 ;; Reset the syntactic context
3086 (setq vhdl-syntactic-context nil)
3087
3088 (save-excursion
3089 ;; Move to the start of the previous library unit, and
3090 ;; record the position of the "begin" keyword.
3091 (setq placeholder (vhdl-beginning-of-libunit))
3092 ;; The position of the "libunit" keyword gives us a gross
3093 ;; limit point.
3094 (setq lim (point))
3095 )
3096
3097 ;; If there is a previous library unit, and we are enclosed by
3098 ;; it, then set the syntax accordingly.
3099 (and placeholder
3100 (setq library-unit (vhdl-get-library-unit lim placeholder))
3101 (vhdl-add-syntax library-unit lim))
3102
3103 ;; Find the surrounding state.
3104 (if (setq vec (vhdl-get-block-state lim))
3105 (progn
3106 (setq containing-sexp (aref vec 0))
3107 (setq preceding-sexp (aref vec 1))
3108 (setq containing-begin (aref vec 2))
3109 (setq containing-mid (aref vec 3))
3110 ))
3111
3112 ;; set the limit on the farthest back we need to search
3113 (setq lim (if containing-sexp
3114 (save-excursion
3115 (goto-char containing-sexp)
3116 ;; set containing-leader if required
3117 (if (looking-at vhdl-leader-re)
3118 (setq containing-leader (vhdl-end-of-leader)))
3119 (vhdl-point 'bol))
3120 (point-min)))
3121
3122 ;; cache char before and after indent point, and move point to
3123 ;; the most likely position to perform the majority of tests
3124 (goto-char indent-point)
3125 (skip-chars-forward " \t")
3126 (setq literal (vhdl-in-literal lim))
3127 (setq char-after-ip (following-char))
3128 (setq begin-after-ip (and
3129 (not literal)
3130 (looking-at vhdl-begin-fwd-re)
3131 (vhdl-begin-p)))
3132 (setq end-after-ip (and
3133 (not literal)
3134 (looking-at vhdl-end-fwd-re)
3135 (vhdl-end-p)))
3136 (vhdl-backward-syntactic-ws lim)
3137 (setq char-before-ip (preceding-char))
3138 (goto-char indent-point)
3139 (skip-chars-forward " \t")
3140
3141 ;; now figure out syntactic qualities of the current line
3142 (cond
3143 ;; CASE 1: in a string or comment.
3144 ((memq literal '(string comment))
3145 (vhdl-add-syntax literal (vhdl-point 'bopl)))
3146 ;; CASE 2: Line is at top level.
3147 ((null containing-sexp)
3148 ;; Find the point to which indentation will be relative
3149 (save-excursion
3150 (if (null preceding-sexp)
3151 ;; CASE 2X.1
3152 ;; no preceding-sexp -> use the preceding statement
3153 (vhdl-beginning-of-statement-1 lim)
3154 ;; CASE 2X.2
3155 ;; if there is a preceding-sexp then indent relative to it
3156 (goto-char preceding-sexp)
3157 ;; if not at boi, then the block-opening keyword is
3158 ;; probably following a label, so we need a different
3159 ;; relpos
3160 (if (/= (point) (vhdl-point 'boi))
3161 ;; CASE 2X.3
3162 (vhdl-beginning-of-statement-1 lim)))
3163 ;; v-b-o-s could have left us at point-min
3164 (and (bobp)
3165 ;; CASE 2X.4
3166 (vhdl-forward-syntactic-ws indent-point))
3167 (setq placeholder (point)))
3168 (cond
3169 ;; CASE 2A : we are looking at a block-open
3170 (begin-after-ip
3171 (vhdl-add-syntax 'block-open placeholder))
3172 ;; CASE 2B: we are looking at a block-close
3173 (end-after-ip
3174 (vhdl-add-syntax 'block-close placeholder))
3175 ;; CASE 2C: we are looking at a top-level statement
3176 ((progn
3177 (vhdl-backward-syntactic-ws lim)
3178 (or (bobp)
3179 (= (preceding-char) ?\;)))
3180 (vhdl-add-syntax 'statement placeholder))
3181 ;; CASE 2D: we are looking at a top-level statement-cont
3182 (t
3183 (vhdl-beginning-of-statement-1 lim)
3184 ;; v-b-o-s could have left us at point-min
3185 (and (bobp)
3186 ;; CASE 2D.1
3187 (vhdl-forward-syntactic-ws indent-point))
3188 (vhdl-add-syntax 'statement-cont (point)))
3189 )) ; end CASE 2
3190 ;; CASE 3: line is inside parentheses. Most likely we are
3191 ;; either in a subprogram argument (interface) list, or a
3192 ;; continued expression containing parentheses.
3193 ((null containing-begin)
3194 (vhdl-backward-syntactic-ws containing-sexp)
3195 (cond
3196 ;; CASE 3A: we are looking at the arglist closing paren
3197 ((eq char-after-ip ?\))
3198 (goto-char containing-sexp)
3199 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
3200 ;; CASE 3B: we are looking at the first argument in an empty
3201 ;; argument list.
3202 ((eq char-before-ip ?\()
3203 (goto-char containing-sexp)
3204 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
3205 ;; CASE 3C: we are looking at an arglist continuation line,
3206 ;; but the preceding argument is on the same line as the
3207 ;; opening paren. This case includes multi-line
3208 ;; expression paren groupings.
3209 ((and (save-excursion
3210 (goto-char (1+ containing-sexp))
3211 (skip-chars-forward " \t")
3212 (not (eolp))
3213 (not (looking-at "--")))
3214 (save-excursion
3215 (vhdl-beginning-of-statement-1 containing-sexp)
3216 (skip-chars-backward " \t(")
3217 (<= (point) containing-sexp)))
3218 (goto-char containing-sexp)
3219 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
3220 ;; CASE 3D: we are looking at just a normal arglist
3221 ;; continuation line
3222 (t (vhdl-beginning-of-statement-1 containing-sexp)
3223 (vhdl-forward-syntactic-ws indent-point)
3224 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
3225 ))
3226 ;; CASE 4: A block mid open
3227 ((and begin-after-ip
3228 (looking-at containing-mid))
3229 (goto-char containing-sexp)
3230 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3231 (if (looking-at vhdl-trailer-re)
3232 ;; CASE 4.1
3233 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3234 (vhdl-backward-skip-label (vhdl-point 'boi))
3235 (vhdl-add-syntax 'block-open (point)))
3236 ;; CASE 5: block close brace
3237 (end-after-ip
3238 (goto-char containing-sexp)
3239 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3240 (if (looking-at vhdl-trailer-re)
3241 ;; CASE 5.1
3242 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3243 (vhdl-backward-skip-label (vhdl-point 'boi))
3244 (vhdl-add-syntax 'block-close (point)))
3245 ;; CASE 6: A continued statement
3246 ((and (/= char-before-ip ?\;)
3247 ;; check it's not a trailer begin keyword, or a begin
3248 ;; keyword immediately following a label.
3249 (not (and begin-after-ip
3250 (or (looking-at vhdl-trailer-re)
3251 (save-excursion
3252 (vhdl-backward-skip-label containing-sexp)))))
3253 ;; check it's not a statement keyword
3254 (not (and (looking-at vhdl-statement-fwd-re)
3255 (vhdl-statement-p)))
3256 ;; see if the b-o-s is before the indent point
3257 (> indent-point
3258 (save-excursion
3259 (vhdl-beginning-of-statement-1 containing-sexp)
3260 ;; If we ended up after a leader, then this will
3261 ;; move us forward to the start of the first
3262 ;; statement. Note that a containing sexp here is
3263 ;; always a keyword, not a paren, so this will
3264 ;; have no effect if we hit the containing-sexp.
3265 (vhdl-forward-syntactic-ws indent-point)
3266 (setq placeholder (point))))
3267 ;; check it's not a block-intro
3268 (/= placeholder containing-sexp)
3269 ;; check it's not a case block-intro
3270 (save-excursion
3271 (goto-char placeholder)
3272 (or (not (looking-at vhdl-case-alternative-re))
3273 (> (match-end 0) indent-point))))
3274 ;; Make placeholder skip a label, but only if it puts us
3275 ;; before the indent point at the start of a line.
3276 (let ((new placeholder))
3277 (if (and (> indent-point
3278 (save-excursion
3279 (goto-char placeholder)
3280 (vhdl-forward-skip-label indent-point)
3281 (setq new (point))))
3282 (save-excursion
3283 (goto-char new)
3284 (eq new (progn (back-to-indentation) (point)))))
3285 (setq placeholder new)))
3286 (vhdl-add-syntax 'statement-cont placeholder)
3287 (if begin-after-ip
3288 (vhdl-add-syntax 'block-open)))
3289 ;; Statement. But what kind?
3290 ;; CASE 7: A case alternative key
3291 ((and (looking-at vhdl-case-alternative-re)
3292 (vhdl-case-alternative-p containing-sexp))
3293 ;; for a case alternative key, we set relpos to the first
3294 ;; non-whitespace char on the line containing the "case"
3295 ;; keyword.
3296 (goto-char containing-sexp)
3297 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3298 (if (looking-at vhdl-trailer-re)
3299 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3300 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
3301 ;; CASE 8: statement catchall
3302 (t
3303 ;; we know its a statement, but we need to find out if it is
3304 ;; the first statement in a block
3305 (if containing-leader
3306 (goto-char containing-leader)
3307 (goto-char containing-sexp)
3308 ;; Note that a containing sexp here is always a keyword,
3309 ;; not a paren, so skip over the keyword.
3310 (forward-sexp))
3311 ;; move to the start of the first statement
3312 (vhdl-forward-syntactic-ws indent-point)
3313 (setq placeholder (point))
3314 ;; we want to ignore case alternatives keys when skipping forward
3315 (let (incase-p)
3316 (while (looking-at vhdl-case-alternative-re)
3317 (setq incase-p (point))
3318 ;; we also want to skip over the body of the
3319 ;; case/when statement if that doesn't put us at
3320 ;; after the indent-point
3321 (while (vhdl-skip-case-alternative indent-point))
3322 ;; set up the match end
3323 (looking-at vhdl-case-alternative-re)
3324 (goto-char (match-end 0))
3325 ;; move to the start of the first case alternative statement
3326 (vhdl-forward-syntactic-ws indent-point)
3327 (setq placeholder (point)))
3328 (cond
3329 ;; CASE 8A: we saw a case/when statement so we must be
3330 ;; in a switch statement. find out if we are at the
3331 ;; statement just after a case alternative key
3332 ((and incase-p
3333 (= (point) indent-point))
3334 ;; relpos is the "when" keyword
3335 (vhdl-add-syntax 'statement-case-intro incase-p))
3336 ;; CASE 8B: any old statement
3337 ((< (point) indent-point)
3338 ;; relpos is the first statement of the block
3339 (vhdl-add-syntax 'statement placeholder)
3340 (if begin-after-ip
3341 (vhdl-add-syntax 'block-open)))
3342 ;; CASE 8C: first statement in a block
3343 (t
3344 (goto-char containing-sexp)
3345 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
3346 (if (looking-at vhdl-trailer-re)
3347 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
3348 (vhdl-backward-skip-label (vhdl-point 'boi))
3349 (vhdl-add-syntax 'statement-block-intro (point))
3350 (if begin-after-ip
3351 (vhdl-add-syntax 'block-open)))
3352 )))
3353 )
3354
3355 ;; now we need to look at any modifiers
3356 (goto-char indent-point)
3357 (skip-chars-forward " \t")
3358 (if (looking-at "--")
3359 (vhdl-add-syntax 'comment))
3360 ;; return the syntax
3361 vhdl-syntactic-context))))
3362
3363;; Standard indentation line-ups:
3364
3365(defun vhdl-lineup-arglist (langelem)
3366 ;; lineup the current arglist line with the arglist appearing just
3367 ;; after the containing paren which starts the arglist.
3368 (save-excursion
3369 (let* ((containing-sexp
3370 (save-excursion
3371 ;; arglist-cont-nonempty gives relpos ==
3372 ;; to boi of containing-sexp paren. This
3373 ;; is good when offset is +, but bad
3374 ;; when it is vhdl-lineup-arglist, so we
3375 ;; have to special case a kludge here.
3376 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
3377 (progn
3378 (beginning-of-line)
3379 (backward-up-list 1)
3380 (skip-chars-forward " \t" (vhdl-point 'eol)))
3381 (goto-char (cdr langelem)))
3382 (point)))
3383 (cs-curcol (save-excursion
3384 (goto-char (cdr langelem))
3385 (current-column))))
3386 (if (save-excursion
3387 (beginning-of-line)
3388 (looking-at "[ \t]*)"))
3389 (progn (goto-char (match-end 0))
3390 (backward-sexp)
3391 (forward-char)
3392 (vhdl-forward-syntactic-ws)
3393 (- (current-column) cs-curcol))
3394 (goto-char containing-sexp)
3395 (or (eolp)
3396 (let ((eol (vhdl-point 'eol))
3397 (here (progn
3398 (forward-char)
3399 (skip-chars-forward " \t")
3400 (point))))
3401 (vhdl-forward-syntactic-ws)
3402 (if (< (point) eol)
3403 (goto-char here))))
3404 (- (current-column) cs-curcol)
3405 ))))
3406
3407(defun vhdl-lineup-arglist-intro (langelem)
3408 ;; lineup an arglist-intro line to just after the open paren
3409 (save-excursion
3410 (let ((cs-curcol (save-excursion
3411 (goto-char (cdr langelem))
3412 (current-column)))
3413 (ce-curcol (save-excursion
3414 (beginning-of-line)
3415 (backward-up-list 1)
3416 (skip-chars-forward " \t" (vhdl-point 'eol))
3417 (current-column))))
3418 (- ce-curcol cs-curcol -1))))
3419
3420(defun vhdl-lineup-comment (langelem)
3421 ;; support old behavior for comment indentation. we look at
3422 ;; vhdl-comment-only-line-offset to decide how to indent comment
3423 ;; only-lines
3424 (save-excursion
3425 (back-to-indentation)
3426 ;; at or to the right of comment-column
3427 (if (>= (current-column) comment-column)
3428 (vhdl-comment-indent)
3429 ;; otherwise, indent as specified by vhdl-comment-only-line-offset
3430 (if (not (bolp))
3431 (or (car-safe vhdl-comment-only-line-offset)
3432 vhdl-comment-only-line-offset)
3433 (or (cdr-safe vhdl-comment-only-line-offset)
3434 (car-safe vhdl-comment-only-line-offset)
3435 -1000 ;jam it against the left side
3436 )))))
3437
3438(defun vhdl-lineup-statement-cont (langelem)
3439 ;; line up statement-cont after the assignment operator
3440 (save-excursion
3441 (let* ((relpos (cdr langelem))
3442 (assignp (save-excursion
3443 (goto-char (vhdl-point 'boi))
3444 (and (re-search-forward "\\(<\\|:\\)="
3445 (vhdl-point 'eol) t)
3446 (- (point) (vhdl-point 'boi)))))
3447 (curcol (progn
3448 (goto-char relpos)
3449 (current-column)))
3450 foundp)
3451 (while (and (not foundp)
3452 (< (point) (vhdl-point 'eol)))
3453 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
3454 (if (vhdl-in-literal (cdr langelem))
3455 (forward-char)
3456 (if (= (preceding-char) ?\()
3457 ;; skip over any parenthesized expressions
3458 (goto-char (min (vhdl-point 'eol)
3459 (scan-lists (point) 1 1)))
3460 ;; found an assignment operator (not at eol)
3461 (setq foundp (not (looking-at "\\s-*$"))))))
3462 (if (not foundp)
3463 ;; there's no assignment operator on the line
3464 vhdl-basic-offset
3465 ;; calculate indentation column after assign and ws, unless
3466 ;; our line contains an assignment operator
3467 (if (not assignp)
3468 (progn
3469 (forward-char)
3470 (skip-chars-forward " \t")
3471 (setq assignp 0)))
3472 (- (current-column) assignp curcol))
3473 )))
3474
3475;; ############################################################################
3476;; Indentation commands
3477
3478(defun vhdl-tab (&optional pre-arg)
3479 "If preceeding character is part of a word then dabbrev-expand,
3480else if right of non whitespace on line then tab-to-tab-stop,
3481else if last command was a tab or return then dedent one step,
3482else indent `correctly'."
3483 (interactive "*P")
3484 (cond ((= (char-syntax (preceding-char)) ?w)
3485 (let ((case-fold-search nil)) (dabbrev-expand pre-arg)))
3486 ((> (current-column) (current-indentation))
3487 (tab-to-tab-stop))
3488 ((and (or (eq last-command 'vhdl-tab)
3489 (eq last-command 'vhdl-return))
3490 (/= 0 (current-indentation)))
3491 (backward-delete-char-untabify vhdl-basic-offset nil))
3492 ((vhdl-indent-line))
3493 )
3494 (setq this-command 'vhdl-tab)
3495 )
3496
3497(defun vhdl-untab ()
3498 "Delete backwards to previous tab stop."
3499 (interactive)
3500 (backward-delete-char-untabify vhdl-basic-offset nil)
3501 )
3502
3503(defun vhdl-return ()
3504 "newline-and-indent or indent-new-comment-line if in comment and preceding
3505character is a space."
3506 (interactive)
3507 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
3508 (indent-new-comment-line)
3509 (newline-and-indent)
3510 )
3511 )
3512
3513(defun vhdl-indent-line ()
3514 "Indent the current line as VHDL code. Returns the amount of
3515indentation change."
3516 (interactive)
3517 (let* ((syntax (vhdl-get-syntactic-context))
3518 (pos (- (point-max) (point)))
3519 (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
3520 (shift-amt (- (current-indentation) indent)))
3521 (and vhdl-echo-syntactic-information-p
3522 (message "syntax: %s, indent= %d" syntax indent))
3523 (if (zerop shift-amt)
3524 nil
3525 (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
3526 (beginning-of-line)
3527 (indent-to indent))
3528 (if (< (point) (vhdl-point 'boi))
3529 (back-to-indentation)
3530 ;; If initial point was within line's indentation, position after
3531 ;; the indentation. Else stay at same point in text.
3532 (if (> (- (point-max) pos) (point))
3533 (goto-char (- (point-max) pos)))
3534 )
3535 (run-hooks 'vhdl-special-indent-hook)
3536 shift-amt))
3537
3538(defun vhdl-indent-buffer ()
3539 "Indent whole buffer as VHDL code."
3540 (interactive)
3541 (indent-region (point-min) (point-max) nil)
3542 )
3543
3544(defun vhdl-indent-sexp (&optional endpos)
3545 "Indent each line of the list starting just after point.
3546If optional arg ENDPOS is given, indent each line, stopping when
3547ENDPOS is encountered."
3548 (interactive)
3549 (save-excursion
3550 (let ((beg (point))
3551 (end (progn
3552 (vhdl-forward-sexp nil endpos)
3553 (point))))
3554 (indent-region beg end nil))))
3555
3556;; ############################################################################
3557;; Miscellaneous commands
3558
3559(defun vhdl-show-syntactic-information ()
3560 "Show syntactic information for current line."
3561 (interactive)
3562 (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
3563 (vhdl-keep-region-active))
3564
3565;; Verification and regression functions:
3566
3567(defun vhdl-regress-line (&optional arg)
3568 "Check syntactic information for current line."
3569 (interactive "P")
3570 (let ((expected (save-excursion
3571 (end-of-line)
3572 (if (search-backward " -- ((" (vhdl-point 'bol) t)
3573 (progn
3574 (forward-char 4)
3575 (read (current-buffer))))))
3576 (actual (vhdl-get-syntactic-context))
3577 (expurgated))
3578 ;; remove the library unit symbols
3579 (mapcar
3580 (function
3581 (lambda (elt)
3582 (if (memq (car elt) '(entity configuration package
3583 package-body architecture))
3584 nil
3585 (setq expurgated (append expurgated (list elt))))))
3586 actual)
3587 (if (and (not arg) expected (listp expected))
3588 (if (not (equal expected expurgated))
3589 (error "Should be: %s, is: %s" expected expurgated))
3590 (save-excursion
3591 (beginning-of-line)
3592 (if (not (looking-at "^\\s-*\\(--.*\\)?$"))
3593 (progn
3594 (end-of-line)
3595 (if (search-backward " -- ((" (vhdl-point 'bol) t)
3596 (kill-line))
3597 (insert " -- ")
3598 (insert (format "%s" expurgated)))))))
3599 (vhdl-keep-region-active))
3600
3601
3602;; ############################################################################
3603;; Alignment
3604;; ############################################################################
3605
3606(defvar vhdl-align-alist
3607 '(
3608 ;; after some keywords
3609 (vhdl-mode "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)[ \t]"
3610 "\\<\\(alias\\|constant\\|signal\\|subtype\\|type\\|variable\\)\\([ \t]+\\)" 2)
3611 ;; before ':'
3612 (vhdl-mode ":[^=]" "[^ \t]\\([ \t]*\\):[^=]")
3613 ;; after ':'
3614 (vhdl-mode ":[^=]" ":\\([ \t]*\\)[^=]" 1)
3615 ;; after direction specifications
3616 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\>"
3617 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\)\\([ \t]+\\)" 2)
3618 ;; before "<=", "=>", and ":="
3619 (vhdl-mode "<=" "[^ \t]\\([ \t]*\\)<=" 1)
3620 (vhdl-mode "=>" "[^ \t]\\([ \t]*\\)=>" 1)
3621 (vhdl-mode ":=" "[^ \t]\\([ \t]*\\):=" 1)
3622 ;; after "<=", "=>", and ":="
3623 (vhdl-mode "<=" "<=\\([ \t]*\\)" 1)
3624 (vhdl-mode "=>" "=>\\([ \t]*\\)" 1)
3625 (vhdl-mode ":=" ":=\\([ \t]*\\)" 1)
3626 ;; before some keywords
3627 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
3628 (vhdl-mode "[ \t]\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>"
3629 "[^ \t]\\([ \t]+\\)\\(fs\\|ps\\|ns\\|us\\|ms\\|sec\\|min\\|hr\\)\\>" 1)
3630 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
3631 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
3632 (vhdl-mode "[ \t]is\\>" "[^ \t]\\([ \t]+\\)is\\>" 1)
3633 (vhdl-mode "[ \t]of\\>" "[^ \t]\\([ \t]+\\)of\\>" 1)
3634 (vhdl-mode "[ \t]use\\>" "[^ \t]\\([ \t]+\\)use\\>" 1)
3635 ;; before comments (two steps required for correct insertion of two spaces)
3636 (vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)
3637 (vhdl-mode "--" "[^ \t][ \t]\\([ \t]*\\)--" 1)
3638 )
3639 "The format of this alist is
3640 (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
3641It is searched in order. If REGEXP is found anywhere in the first
3642line of a region to be aligned, ALIGN-PATTERN will be used for that
3643region. ALIGN-PATTERN must include the whitespace to be expanded or
3644contracted. It may also provide regexps for the text surrounding the
3645whitespace. SUBEXP specifies which sub-expression of
3646ALIGN-PATTERN matches the white space to be expanded/contracted.")
3647
3648(defvar vhdl-align-try-all-clauses t
3649 "If REGEXP is not found on the first line of the region that clause
3650is ignored. If this variable is non-nil, then the clause is tried anyway.")
3651
3652(defun vhdl-align (begin end spacing &optional alignment-list quick)
3653 "Attempt to align a range of lines based on the content of the
3654lines. The definition of 'alignment-list' determines the matching
3655order and the manner in which the lines are aligned. If ALIGNMENT-LIST
3656is not specified 'vhdl-align-alist' is used. If QUICK is non-nil, no
3657indentation is done before aligning."
3658 (interactive "r\np")
3659 (if (not alignment-list)
3660 (setq alignment-list vhdl-align-alist))
3661 (if (not spacing)
3662 (setq spacing 1))
3663 (save-excursion
3664 (let (bol indent)
3665 (goto-char end)
3666 (setq end (point-marker))
3667 (goto-char begin)
3668 (setq bol
3669 (setq begin (progn (beginning-of-line) (point))))
3670 (untabify bol end)
3671 (if quick
3672 nil
3673 (indent-region bol end nil))))
3674 (let ((copy (copy-alist alignment-list)))
3675 (while copy
3676 (save-excursion
3677 (goto-char begin)
3678 (let (element
3679 (eol (save-excursion (progn (end-of-line) (point)))))
3680 (setq element (nth 0 copy))
3681 (if (and (or (and (listp (car element))
3682 (memq major-mode (car element)))
3683 (eq major-mode (car element)))
3684 (or vhdl-align-try-all-clauses
3685 (re-search-forward (car (cdr element)) eol t)))
3686 (progn
3687 (vhdl-align-region begin end (car (cdr (cdr element)))
3688 (car (cdr (cdr (cdr element)))) spacing)))
3689 (setq copy (cdr copy)))))))
3690
3691(defun vhdl-align-region (begin end match &optional substr spacing)
3692 "Align a range of lines from BEGIN to END. The regular expression
3693MATCH must match exactly one fields: the whitespace to be
3694contracted/expanded. The alignment column will equal the
3695rightmost column of the widest whitespace block. SPACING is
3696the amount of extra spaces to add to the calculated maximum required.
3697SPACING defaults to 1 so that at least one space is inserted after
3698the token in MATCH."
3699 (if (not spacing)
3700 (setq spacing 1))
3701 (if (not substr)
3702 (setq substr 1))
3703 (save-excursion
3704 (let (distance (max 0) (lines 0) bol eol width)
3705 ;; Determine the greatest whitespace distance to the alignment
3706 ;; character
3707 (goto-char begin)
3708 (setq eol (progn (end-of-line) (point))
3709 bol (setq begin (progn (beginning-of-line) (point))))
3710 (while (< bol end)
3711 (save-excursion
3712 (if (re-search-forward match eol t)
3713 (progn
3714 (setq distance (- (match-beginning substr) bol))
3715 (if (> distance max)
3716 (setq max distance)))))
3717 (forward-line)
3718 (setq bol (point)
3719 eol (save-excursion
3720 (end-of-line)
3721 (point)))
3722 (setq lines (1+ lines)))
3723 ;; Now insert enough maxs to push each assignment operator to
3724 ;; the same column. We need to use 'lines' as a counter, since
3725 ;; the location of the mark may change
3726 (goto-char (setq bol begin))
3727 (setq eol (save-excursion
3728 (end-of-line)
3729 (point)))
3730 (while (> lines 0)
3731 (if (re-search-forward match eol t)
3732 (progn
3733 (setq width (- (match-end substr) (match-beginning substr)))
3734 (setq distance (- (match-beginning substr) bol))
3735 (goto-char (match-beginning substr))
3736 (delete-char width)
3737 (insert-char ? (+ (- max distance) spacing))))
3738 (beginning-of-line)
3739 (forward-line)
3740 (setq bol (point)
3741 eol (save-excursion
3742 (end-of-line)
3743 (point)))
3744 (setq lines (1- lines))
3745 ))))
3746
3747(defun vhdl-align-comment-region (begin end spacing)
3748 "Aligns inline comments within a region relative to first comment."
3749 (interactive "r\nP")
3750 (vhdl-align begin end (or spacing 2)
3751 `((vhdl-mode "--" "[^ \t]\\([ \t]*\\)--" 1)) t))
3752
3753(defun vhdl-align-noindent-region (begin end spacing)
3754 "Align without indentation."
3755 (interactive "r\nP")
3756 (vhdl-align begin end spacing nil t)
3757 )
3758
3759
3760;; ############################################################################
3761;; VHDL electrification
3762;; ############################################################################
3763
3764;; ############################################################################
3765;; Stuttering
3766
3767(defun vhdl-stutter-mode-caps (count)
3768 "Double first letters of a word replaced by a single capital of the letter."
3769 (interactive "p")
3770 (if vhdl-stutter-mode
3771 (if (and
3772 (= (preceding-char) last-input-char) ; doubled
3773 (or (= (point) 2) ; beginning of buffer
3774 (/= (char-syntax (char-after (- (point) 2))) ?w) ;not mid-word
3775 (< (char-after (- (point) 2)) ?A))) ;alfa-numeric
3776 (progn (delete-char -1) (insert-char (- last-input-char 32) count))
3777 (self-insert-command count))
3778 (self-insert-command count)
3779 ))
3780
3781(defun vhdl-stutter-mode-close-bracket (count) " ']' --> ')', ')]' --> ']'"
3782 (interactive "p")
3783 (if (and vhdl-stutter-mode (= count 1))
3784 (progn
3785 (if (= (preceding-char) 41) ; close-paren
3786 (progn (delete-char -1) (insert-char 93 1)) ; close-bracket
3787 (insert-char 41 1) ; close-paren
3788 )
3789 (blink-matching-open))
3790 (self-insert-command count)
3791 ))
3792
3793(defun vhdl-stutter-mode-semicolon (count) " ';;' --> ' : ', ': ;' --> ' := '"
3794 (interactive "p")
3795 (if (and vhdl-stutter-mode (= count 1))
3796 (progn
3797 (cond ((= (preceding-char) last-input-char)
3798 (progn (delete-char -1)
3799 (if (not (eq (preceding-char) ? )) (insert " "))
3800 (insert ": ")))
3801 ((and
3802 (eq last-command 'vhdl-stutter-mode-colon) (= (preceding-char) ? ))
3803 (progn (delete-char -1) (insert "= ")))
3804 (t
3805 (insert-char 59 1)) ; semi-colon
3806 )
3807 (setq this-command 'vhdl-stutter-mode-colon))
3808 (self-insert-command count)
3809 ))
3810
3811(defun vhdl-stutter-mode-open-bracket (count) " '[' --> '(', '([' --> '['"
3812 (interactive "p")
3813 (if (and vhdl-stutter-mode (= count 1))
3814 (if (= (preceding-char) 40) ; open-paren
3815 (progn (delete-char -1) (insert-char 91 1)) ; open-bracket
3816 (insert-char 40 1)) ; open-paren
3817 (self-insert-command count)
3818 ))
3819
3820(defun vhdl-stutter-mode-quote (count) " '' --> \""
3821 (interactive "p")
3822 (if (and vhdl-stutter-mode (= count 1))
3823 (if (= (preceding-char) last-input-char)
3824 (progn (delete-backward-char 1) (insert-char 34 1)) ; double-quote
3825 (insert-char 39 1)) ; single-quote
3826 (self-insert-command count)
3827 ))
3828
3829(defun vhdl-stutter-mode-comma (count) " ',,' --> ' <= '"
3830 (interactive "p")
3831 (if (and vhdl-stutter-mode (= count 1))
3832 (cond ((= (preceding-char) last-input-char)
3833 (progn (delete-char -1)
3834 (if (not (eq (preceding-char) ? )) (insert " "))
3835 (insert "<= ")))
3836 (t
3837 (insert-char 44 1))) ; comma
3838 (self-insert-command count)
3839 ))
3840
3841(defun vhdl-stutter-mode-period (count) " '..' --> ' => '"
3842 (interactive "p")
3843 (if (and vhdl-stutter-mode (= count 1))
3844 (cond ((= (preceding-char) last-input-char)
3845 (progn (delete-char -1)
3846 (if (not (eq (preceding-char) ? )) (insert " "))
3847 (insert "=> ")))
3848 (t
3849 (insert-char 46 1))) ; period
3850 (self-insert-command count)
3851 ))
3852
3853(defun vhdl-paired-parens ()
3854 "Insert a pair of round parentheses, placing point between them."
3855 (interactive)
3856 (insert "()")
3857 (backward-char)
3858 )
3859
3860(defun vhdl-stutter-mode-dash (count)
3861 "-- starts a comment, --- draws a horizontal line,
3862---- starts a display comment"
3863 (interactive "p")
3864 (if vhdl-stutter-mode
3865 (cond ((and abbrev-start-location (= abbrev-start-location (point)))
3866 (setq abbrev-start-location nil)
3867 (goto-char last-abbrev-location)
3868 (beginning-of-line nil)
3869 (vhdl-display-comment))
3870 ((/= (preceding-char) ?-) ; standard dash (minus)
3871 (self-insert-command count))
3872 (t
3873 (self-insert-command count)
3874 (message "Enter - for horiz. line, CR for commenting-out code, else 1st char of comment")
3875 (let ((next-input (read-char)))
3876 (if (= next-input ?-) ; triple dash
3877 (progn
3878 (vhdl-display-comment-line)
3879 (message
3880 "Enter - for display comment, else continue with coding")
3881 (let ((next-input (read-char)))
3882 (if (= next-input ?-) ; four dashes
3883 (vhdl-display-comment t)
3884 (setq unread-command-events ;pushback the char
3885 (list
3886 (vhdl-character-to-event-hack next-input)))
3887 )))
3888 (setq unread-command-events ;pushback the char
3889 (list (vhdl-character-to-event-hack next-input)))
3890 (vhdl-inline-comment)
3891 ))))
3892 (self-insert-command count)
3893 ))
3894
3895;; ############################################################################
3896;; VHDL templates
3897
3898(defun vhdl-alias ()
3899 "Insert alias declaration."
3900 (interactive)
3901 (vhdl-insert-keyword "ALIAS ")
3902 (if (equal (vhdl-field "name") "")
3903 nil
3904 (insert " : ")
3905 (vhdl-field "type")
3906 (vhdl-insert-keyword " IS ")
3907 (vhdl-field "name" ";")
3908 (vhdl-declaration-comment)
3909 ))
3910
3911(defun vhdl-architecture ()
3912 "Insert architecture template."
3913 (interactive)
3914 (let ((margin (current-column))
3915 (vhdl-architecture-name)
3916 (position)
3917 (entity-exists)
3918 (string)
3919 (case-fold-search t))
3920 (vhdl-insert-keyword "ARCHITECTURE ")
3921 (if (equal (setq vhdl-architecture-name (vhdl-field "name")) "")
3922 nil
3923 (vhdl-insert-keyword " OF ")
3924 (setq position (point))
3925 (setq entity-exists
3926 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)+\\) is" nil t))
3927 (setq string (match-string 1))
3928 (goto-char position)
3929 (if (and entity-exists (not (equal string "")))
3930 (insert string)
3931 (vhdl-field "entity name"))
3932 (vhdl-insert-keyword " IS")
3933 (vhdl-begin-end (cons vhdl-architecture-name margin))
3934 (vhdl-block-comment)
3935 )))
3936
3937
3938(defun vhdl-array ()
3939 "Insert array type definition."
3940 (interactive)
3941 (vhdl-insert-keyword "ARRAY (")
3942 (if (equal (vhdl-field "range") "")
3943 (delete-char -1)
3944 (vhdl-insert-keyword ") OF ")
3945 (vhdl-field "type")
3946 (vhdl-insert-keyword ";")
3947 ))
3948
3949(defun vhdl-assert ()
3950 "Inserts a assertion statement."
3951 (interactive)
3952 (vhdl-insert-keyword "ASSERT ")
3953 (if vhdl-conditions-in-parenthesis (insert "("))
3954 (if (equal (vhdl-field "condition (negated)") "")
3955 (progn (undo 0) (insert " "))
3956 (if vhdl-conditions-in-parenthesis (insert ")"))
3957 (vhdl-insert-keyword " REPORT \"")
3958 (vhdl-field "string-expression" "\" ")
3959 (vhdl-insert-keyword "SEVERITY ")
3960 (if (equal (vhdl-field "[note | warning | error | failure]") "")
3961 (delete-char -10))
3962 (insert ";")
3963 ))
3964
3965(defun vhdl-attribute ()
3966 "Inserts an attribute declaration or specification."
3967 (interactive)
3968 (vhdl-insert-keyword "ATTRIBUTE ")
3969 (if (y-or-n-p "declaration (or specification)? ")
3970 (progn
3971 (vhdl-field "name" " : ")
3972 (vhdl-field "type" ";")
3973 (vhdl-declaration-comment))
3974 (vhdl-field "name")
3975 (vhdl-insert-keyword " OF ")
3976 (vhdl-field "entity name" " : ")
3977 (vhdl-field "entity class")
3978 (vhdl-insert-keyword " IS ")
3979 (vhdl-field "expression" ";")
3980 ))
3981
3982(defun vhdl-block ()
3983 "Insert a block template."
3984 (interactive)
3985 (let ((position (point)))
3986 (vhdl-insert-keyword " : BLOCK ")
3987 (goto-char position))
3988 (let* ((margin (current-column))
3989 (name (vhdl-field "label")))
3990 (if (equal name "")
3991 (progn (undo 0) (insert " "))
3992 (end-of-line)
3993 (insert "(")
3994 (if (equal (vhdl-field "[guard expression]") "")
3995 (delete-char -2)
3996 (insert ")"))
3997 (vhdl-begin-end (cons (concat (vhdl-case-keyword "BLOCK ") name) margin))
3998 (vhdl-block-comment)
3999 )))
4000
4001(defun vhdl-block-configuration ()
4002 "Insert a block configuration statement."
4003 (interactive)
4004 (let ((margin (current-column)))
4005 (vhdl-insert-keyword "FOR ")
4006 (if (equal (setq name (vhdl-field "block specification")) "")
4007 nil
4008 (vhdl-insert-keyword "\n\n")
4009 (indent-to margin)
4010 (vhdl-insert-keyword "END FOR;")
4011 (end-of-line 0)
4012 (indent-to (+ margin vhdl-basic-offset))
4013 )))
4014
4015(defun vhdl-case ()
4016 "Inserts a case statement."
4017 (interactive)
4018 (let ((margin (current-column))
4019 (name))
4020 (vhdl-insert-keyword "CASE ")
4021 (if (equal (setq name (vhdl-field "expression")) "")
4022 nil
4023 (vhdl-insert-keyword " IS\n\n")
4024 (indent-to margin)
4025 (vhdl-insert-keyword "END CASE;")
4026; (if vhdl-self-insert-comments (insert " -- " name))
4027 (forward-line -1)
4028 (indent-to (+ margin vhdl-basic-offset))
4029 (vhdl-insert-keyword "WHEN => ")
4030 (backward-char 4)
4031 )))
4032
4033(defun vhdl-component ()
4034 "Inserts a component declaration."
4035 (interactive)
4036 (let ((margin (current-column)))
4037 (vhdl-insert-keyword "COMPONENT ")
4038 (if (equal (vhdl-field "name") "")
4039 nil
4040 (insert "\n\n")
4041 (indent-to margin)
4042 (vhdl-insert-keyword "END COMPONENT;")
4043 (end-of-line -0)
4044 (indent-to (+ margin vhdl-basic-offset))
4045 (vhdl-insert-keyword "GENERIC (")
4046 (vhdl-get-generic t t)
4047 (insert "\n")
4048 (indent-to (+ margin vhdl-basic-offset))
4049 (vhdl-insert-keyword "PORT (")
4050 (vhdl-get-port t t)
4051 (forward-line 1))
4052 ))
4053
4054(defun vhdl-component-configuration ()
4055 "Inserts a component configuration (uses `vhdl-configuration-spec' since
4056these are almost equivalent)."
4057 (interactive)
4058 (let ((margin (current-column)))
4059 (vhdl-configuration-spec)
4060 (insert "\n")
4061 (indent-to margin)
4062 (vhdl-insert-keyword "END FOR;")
4063 ))
4064
4065(defun vhdl-component-instance ()
4066 "Inserts a component instantiation statement."
4067 (interactive)
4068 (let ((margin (current-column)))
4069 (if (equal (vhdl-field "instance label") "")
4070 nil
4071 (insert " : ")
4072 (vhdl-field "component name" "\n")
4073 (indent-to (+ margin vhdl-basic-offset))
4074 (let ((position (point)))
4075 (vhdl-insert-keyword "GENERIC MAP (")
4076 (if (equal (vhdl-field "[association list]") "")
4077 (progn (goto-char position)
4078 (kill-line))
4079 (insert ")\n")
4080 (indent-to (+ margin vhdl-basic-offset))))
4081 (vhdl-insert-keyword "PORT MAP (")
4082 (vhdl-field "association list" ");")
4083 )))
4084
4085(defun vhdl-concurrent-signal-assignment ()
4086 "Inserts a concurrent signal assignment."
4087 (interactive)
4088 (if (equal (vhdl-field "target signal") "")
4089 nil
4090 (insert " <= ")
4091; (if (not (equal (vhdl-field "[GUARDED] [TRANSPORT]") ""))
4092; (insert " "))
4093 (let ((margin (current-column))
4094 (start (point)))
4095 (vhdl-field "waveform")
4096 (vhdl-insert-keyword " WHEN ")
4097 (if vhdl-conditions-in-parenthesis (insert "("))
4098 (while (not (equal (vhdl-field "[condition]") ""))
4099 (if vhdl-conditions-in-parenthesis (insert ")"))
4100 (vhdl-insert-keyword " ELSE")
4101 (insert "\n")
4102 (indent-to margin)
4103 (vhdl-field "waveform")
4104 (vhdl-insert-keyword " WHEN ")
4105 (if vhdl-conditions-in-parenthesis (insert "(")))
4106 (delete-char -6)
4107 (if vhdl-conditions-in-parenthesis (delete-char -1))
4108 (insert ";")
4109 (if vhdl-auto-align (vhdl-align start (point) 1))
4110 )))
4111
4112(defun vhdl-configuration ()
4113 "Inserts a configuration specification if within an architecture,
4114a block or component configuration if within a configuration declaration,
4115a configuration declaration if not within a design unit."
4116 (interactive)
4117 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'architecture)
4118 (vhdl-configuration-spec))
4119 ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
4120 (if (y-or-n-p "block configuration (or component configuration)? ")
4121 (vhdl-block-configuration)
4122 (vhdl-component-configuration)))
4123 (t (vhdl-configuration-decl)))
4124 )
4125
4126(defun vhdl-configuration-spec ()
4127 "Inserts a configuration specification."
4128 (interactive)
4129 (let ((margin (current-column)))
4130 (vhdl-insert-keyword "FOR ")
4131 (if (equal (vhdl-field "(component names | ALL)" " : ") "")
4132 (progn (undo 0) (insert " "))
4133 (vhdl-field "component type" "\n")
4134 (indent-to (+ margin vhdl-basic-offset))
4135 (vhdl-insert-keyword "USE ENTITY ")
4136 (vhdl-field "library name" ".")
4137 (vhdl-field "entity name" "(")
4138 (if (equal (vhdl-field "[architecture name]") "")
4139 (delete-char -1)
4140 (insert ")"))
4141 (insert "\n")
4142 (indent-to (+ margin vhdl-basic-offset))
4143 (vhdl-insert-keyword "GENERIC MAP (")
4144 (if (equal (vhdl-field "[association list]") "")
4145 (progn (kill-line -0)
4146 (indent-to (+ margin vhdl-basic-offset)))
4147 (insert ")\n")
4148 (indent-to (+ margin vhdl-basic-offset)))
4149 (vhdl-insert-keyword "PORT MAP (")
4150 (if (equal (vhdl-field "[association list]") "")
4151 (progn (kill-line -0)
4152 (delete-char -1))
4153 (insert ")"))
4154 (insert ";")
4155 )))
4156
4157(defun vhdl-configuration-decl ()
4158 "Inserts a configuration declaration."
4159 (interactive)
4160 (let ((margin (current-column))
4161 (position)
4162 (entity-exists)
4163 (string)
4164 (name))
4165 (vhdl-insert-keyword "CONFIGURATION ")
4166 (if (equal (setq name (vhdl-field "name")) "")
4167 nil
4168 (vhdl-insert-keyword " OF ")
4169 (setq position (point))
4170 (setq entity-exists
4171 (re-search-backward "entity \\(\\(\\w\\|\\s_\\)*\\) is" nil t))
4172 (setq string (match-string 1))
4173 (goto-char position)
4174 (if (and entity-exists (not (equal string "")))
4175 (insert string)
4176 (vhdl-field "entity name"))
4177 (vhdl-insert-keyword " IS\n\n")
4178 (indent-to margin)
4179 (vhdl-insert-keyword "END ")
4180 (insert name ";")
4181 (end-of-line 0)
4182 (indent-to (+ margin vhdl-basic-offset))
4183 )))
4184
4185(defun vhdl-constant ()
4186 "Inserts a constant declaration."
4187 (interactive)
4188 (vhdl-insert-keyword "CONSTANT ")
4189 (let ((in-arglist (string-match "arglist"
4190 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4191 (if (not in-arglist)
4192 (let ((opoint (point)))
4193 (beginning-of-line)
4194 (setq in-arglist (looking-at ".*("))
4195 (goto-char opoint)))
4196 (if (equal (vhdl-field "name") "")
4197 nil
4198 (insert " : ")
4199 (if in-arglist (vhdl-insert-keyword "IN "))
4200 (vhdl-field "type")
4201 (if in-arglist
4202 (insert ";")
4203 (let ((position (point)))
4204 (insert " := ")
4205 (if (equal (vhdl-field "[initialization]" ";") "")
4206 (progn (goto-char position) (kill-line) (insert ";")))
4207 (vhdl-declaration-comment))
4208 ))))
4209
4210(defun vhdl-default ()
4211 "Insert nothing."
4212 (interactive)
4213 (insert " ")
4214 (unexpand-abbrev)
4215 (backward-word 1)
4216 (vhdl-case-word 1)
4217 (forward-char 1)
4218 )
4219
4220(defun vhdl-default-indent ()
4221 "Insert nothing and indent."
4222 (interactive)
4223 (insert " ")
4224 (unexpand-abbrev)
4225 (backward-word 1)
4226 (vhdl-case-word 1)
4227 (forward-char 1)
4228 (vhdl-indent-line)
4229 )
4230
4231(defun vhdl-disconnect ()
4232 "Insert a disconnect statement."
4233 (interactive)
4234 (vhdl-insert-keyword "DISCONNECT ")
4235 (if (equal (vhdl-field "guarded signal specification") "")
4236 nil
4237 (vhdl-insert-keyword " AFTER ")
4238 (vhdl-field "time expression" ";")
4239 ))
4240
4241(defun vhdl-else ()
4242 "Insert an else statement."
4243 (interactive)
4244 (let ((margin))
4245 (vhdl-insert-keyword "ELSE")
4246 (if (not (equal 'block-close (car (car (vhdl-get-syntactic-context)))))
4247 (insert " ")
4248 (vhdl-indent-line)
4249 (setq margin (current-indentation))
4250 (insert "\n")
4251 (indent-to (+ margin vhdl-basic-offset))
4252 )))
4253
4254(defun vhdl-elsif ()
4255 "Insert an elsif statement."
4256 (interactive)
4257 (let ((margin))
4258 (vhdl-insert-keyword "ELSIF ")
4259 (if vhdl-conditions-in-parenthesis (insert "("))
4260 (if (equal (vhdl-field "condition") "")
4261 (progn (undo 0) (insert " "))
4262 (if vhdl-conditions-in-parenthesis (insert ")"))
4263 (vhdl-indent-line)
4264 (setq margin (current-indentation))
4265 (vhdl-insert-keyword " THEN\n")
4266 (indent-to (+ margin vhdl-basic-offset))
4267 )))
4268
4269(defun vhdl-entity ()
4270 "Insert an entity template."
4271 (interactive)
4272 (let ((margin (current-column))
4273 (vhdl-entity-name))
4274 (vhdl-insert-keyword "ENTITY ")
4275 (if (equal (setq vhdl-entity-name (vhdl-field "entity name")) "")
4276 nil
4277 (vhdl-insert-keyword " IS\n\n")
4278 (indent-to margin)
4279 (vhdl-insert-keyword "END ")
4280 (insert vhdl-entity-name ";")
4281 (end-of-line -0)
4282 (indent-to (+ margin vhdl-basic-offset))
4283 (vhdl-entity-body)
4284 )))
4285
4286(defun vhdl-entity-body ()
4287 "Insert an entity body."
4288 (interactive)
4289 (let ((margin (current-column)))
4290 (if vhdl-additional-empty-lines (insert "\n"))
4291 (indent-to margin)
4292 (vhdl-insert-keyword "GENERIC (")
4293 (if (vhdl-get-generic t)
4294 (if vhdl-additional-empty-lines (insert "\n")))
4295 (insert "\n")
4296 (indent-to margin)
4297 (vhdl-insert-keyword "PORT (")
4298 (if (vhdl-get-port t)
4299 (if vhdl-additional-empty-lines (insert "\n")))
4300 (end-of-line 2)
4301 ))
4302
4303(defun vhdl-exit ()
4304 "Insert an exit statement."
4305 (interactive)
4306 (vhdl-insert-keyword "EXIT ")
4307 (if (string-equal (vhdl-field "[loop label]") "")
4308 (delete-char -1))
4309 (let ((opoint (point)))
4310 (vhdl-insert-keyword " WHEN ")
4311 (if vhdl-conditions-in-parenthesis (insert "("))
4312 (if (equal (vhdl-field "[condition]") "")
4313 (progn (goto-char opoint)
4314 (kill-line))
4315 (if vhdl-conditions-in-parenthesis (insert ")"))))
4316 (insert ";")
4317 )
4318
4319(defun vhdl-for ()
4320 "Inserts a block or component configuration if within a configuration
4321declaration, a for loop otherwise."
4322 (interactive)
4323 (if (equal (car (car (cdr (vhdl-get-syntactic-context)))) 'configuration)
4324 (if (y-or-n-p "block configuration (or component configuration)? ")
4325 (vhdl-block-configuration)
4326 (vhdl-component-configuration))
4327 (vhdl-for-loop)))
4328
4329(defun vhdl-for-loop ()
4330 "Insert a for loop template."
4331 (interactive)
4332 (let ((position (point)))
4333 (vhdl-insert-keyword " : FOR ")
4334 (goto-char position))
4335 (let* ((margin (current-column))
4336 (name (vhdl-field "[label]"))
4337 (named (not (string-equal name "")))
4338 (index))
4339 (if (not named) (delete-char 3))
4340 (end-of-line)
4341 (if (equal (setq index (vhdl-field "loop variable")) "")
4342 nil
4343 (vhdl-insert-keyword " IN ")
4344 (vhdl-field "range")
4345 (vhdl-insert-keyword " LOOP\n\n")
4346 (indent-to margin)
4347 (vhdl-insert-keyword "END LOOP")
4348 (if named (insert " " name ";")
4349 (insert ";")
4350 (if vhdl-self-insert-comments (insert " -- " index)))
4351 (forward-line -1)
4352 (indent-to (+ margin vhdl-basic-offset))
4353 )))
4354
4355(defun vhdl-function ()
4356 "Insert function specification or body template."
4357 (interactive)
4358 (let ((margin (current-column))
4359 (name))
4360 (vhdl-insert-keyword "FUNCTION ")
4361 (if (equal (setq name (vhdl-field "name")) "")
4362 nil
4363 (vhdl-get-arg-list)
4364 (vhdl-insert-keyword " RETURN ")
4365 (vhdl-field "type" " ")
4366 (if (y-or-n-p "insert body? ")
4367 (progn (vhdl-insert-keyword "IS")
4368 (vhdl-begin-end (cons name margin))
4369 (vhdl-block-comment))
4370 (delete-char -1)
4371 (insert ";\n")
4372 (indent-to margin)))
4373 ))
4374
4375(defun vhdl-generate ()
4376 "Insert a generate template."
4377 (interactive)
4378 (let ((position (point)))
4379 (vhdl-insert-keyword " GENERATE")
4380 (goto-char position))
4381 (let ((margin (current-column))
4382 (label (vhdl-field "label"))
4383 (string))
4384 (if (equal label "")
4385 (progn (undo 0) (insert " "))
4386 (insert " : ")
4387 (setq string (vhdl-field "(FOR | IF)"))
4388 (insert " ")
4389 (if (equal (upcase string) "IF")
4390 (progn
4391 (if vhdl-conditions-in-parenthesis (insert "("))
4392 (vhdl-field "condition")
4393 (if vhdl-conditions-in-parenthesis (insert ")")))
4394 (vhdl-field "loop variable")
4395 (vhdl-insert-keyword " IN ")
4396 (vhdl-field "range"))
4397 (end-of-line)
4398 (insert "\n\n")
4399 (indent-to margin)
4400 (vhdl-insert-keyword "END GENERATE ")
4401 (insert label ";")
4402 (end-of-line 0)
4403 (indent-to (+ margin vhdl-basic-offset))
4404 )))
4405
4406(defun vhdl-generic ()
4407 "Insert generic declaration, or generic map in instantiation statements."
4408 (interactive)
4409 (vhdl-insert-keyword "GENERIC (")
4410 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
4411 (vhdl-get-generic nil))
4412 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
4413 (save-excursion
4414 (and (backward-word 2) (skip-chars-backward " ")
4415 (eq (preceding-char) ?:))))
4416 (delete-char -1) (vhdl-map))
4417 (t (vhdl-get-generic nil t))))
4418
4419(defun vhdl-header ()
4420 "Insert a VHDL file header."
4421 (interactive)
4422 (let (eot)
4423 (save-excursion
4424 (save-restriction
4425 (widen)
4426 (goto-char (point-min))
4427 (if vhdl-header-file
4428 (setq eot (car (cdr (insert-file-contents vhdl-header-file))))
4429 ; insert default header
4430 (insert "\
4431-------------------------------------------------------------------------------
4432-- Title : <title string>
4433-- Project : <project string>
4434-------------------------------------------------------------------------------
4435-- File : <filename>
4436-- Author : <author>
4437-- Created : <date>
4438-- Last modified : <date>
4439-------------------------------------------------------------------------------
4440-- Description :
4441-- <cursor>
4442-------------------------------------------------------------------------------
4443-- Modification history :
4444-- <date> : created
4445-------------------------------------------------------------------------------
4446
4447")
4448 (setq eot (point)))
4449 (narrow-to-region (point-min) eot)
4450 (goto-char (point-min))
4451 (while (search-forward "<filename>" nil t)
4452 (replace-match (buffer-name) t t))
4453 (goto-char (point-min))
4454 (while (search-forward "<author>" nil t)
4455 (replace-match "" t t)
4456 (insert (user-full-name) " <" user-mail-address ">"))
4457 (goto-char (point-min))
4458 ;; Replace <RCS> with $, so that RCS for the source is
4459 ;; not over-enthusiastic with replacements
4460 (while (search-forward "<RCS>" nil t)
4461 (replace-match "$" nil t))
4462 (goto-char (point-min))
4463 (while (search-forward "<date>" nil t)
4464 (replace-match "" t t)
4465 (vhdl-insert-date))
4466 (goto-char (point-min))
4467 (let (string)
4468 (while (re-search-forward "<\\(\\w*\\) string>" nil t)
4469 (setq string (read-string (concat (match-string 1) ": ")))
4470 (replace-match string t t)))))
4471 (goto-char (point-min))
4472 (if (search-forward "<cursor>" nil t)
4473 (replace-match "" t t))))
4474
4475(defun vhdl-if ()
4476 "Insert an if statement template."
4477 (interactive)
4478 (let ((margin (current-column)))
4479 (vhdl-insert-keyword "IF ")
4480 (if vhdl-conditions-in-parenthesis (insert "("))
4481 (if (equal (vhdl-field "condition") "")
4482 (progn (undo 0) (insert " "))
4483 (if vhdl-conditions-in-parenthesis (insert ")"))
4484 (vhdl-insert-keyword " THEN\n\n")
4485 (indent-to margin)
4486 (vhdl-insert-keyword "END IF;")
4487 (forward-line -1)
4488 (indent-to (+ margin vhdl-basic-offset))
4489 )))
4490
4491(defun vhdl-library ()
4492 "Insert a library specification."
4493 (interactive)
4494 (let ((margin (current-column))
4495 (lib-name))
4496 (vhdl-insert-keyword "LIBRARY ")
4497 (if (equal (setq lib-name (vhdl-field "library name")) "")
4498 nil
4499 (insert ";\n")
4500 (indent-to margin)
4501 (vhdl-insert-keyword "USE ")
4502 (insert lib-name)
4503 (vhdl-insert-keyword "..ALL;")
4504 (backward-char 5)
4505 (if (equal (vhdl-field "package name") "")
4506 (progn (vhdl-kill-entire-line)
4507 (end-of-line -0))
4508 (end-of-line)
4509 ))))
4510
4511(defun vhdl-loop ()
4512 "Insert a loop template."
4513 (interactive)
4514 (let ((position (point)))
4515 (vhdl-insert-keyword " : LOOP")
4516 (goto-char position))
4517 (let* ((margin (current-column))
4518 (name (vhdl-field "[label]"))
4519 (named (not (string-equal name ""))))
4520 (if (not named) (delete-char 3))
4521 (end-of-line)
4522 (insert "\n\n")
4523 (indent-to margin)
4524 (vhdl-insert-keyword "END LOOP")
4525 (insert (if named (concat " " name ";") ?;))
4526 (forward-line -1)
4527 (indent-to (+ margin vhdl-basic-offset))
4528 ))
4529
4530(defun vhdl-map ()
4531 "Insert a map specification."
4532 (interactive)
4533 (vhdl-insert-keyword "MAP (")
4534 (if (equal (vhdl-field "[association list]") "")
4535 (progn (undo 0) (insert " "))
4536 (insert ")")
4537 ))
4538
4539(defun vhdl-modify ()
4540 "Actualize modification date."
4541 (interactive)
4542 (goto-char (point-min))
4543 (if (search-forward vhdl-modify-date-prefix-string nil t)
4544 (progn (kill-line)
4545 (vhdl-insert-date))
4546 (message (concat "Modification date prefix string \""
4547 vhdl-modify-date-prefix-string
4548 "\" not found!"))
4549 (beep)))
4550
4551(defun vhdl-next ()
4552 "Inserts a next statement."
4553 (interactive)
4554 (vhdl-insert-keyword "NEXT ")
4555 (if (string-equal (vhdl-field "[loop label]") "")
4556 (delete-char -1))
4557 (let ((opoint (point)))
4558 (vhdl-insert-keyword " WHEN ")
4559 (if vhdl-conditions-in-parenthesis (insert "("))
4560 (if (equal (vhdl-field "[condition]") "")
4561 (progn (goto-char opoint)
4562 (kill-line))
4563 (if vhdl-conditions-in-parenthesis (insert ")"))))
4564 (insert ";")
4565 )
4566
4567(defun vhdl-package ()
4568 "Insert a package specification or body."
4569 (interactive)
4570 (let ((margin (current-column))
4571 (name))
4572 (vhdl-insert-keyword "PACKAGE ")
4573 (if (y-or-n-p "body? ")
4574 (vhdl-insert-keyword "BODY "))
4575 (setq name (vhdl-field "name" " is\n\n"))
4576 (indent-to margin)
4577 (vhdl-insert-keyword "END ")
4578 (insert name ";")
4579 (forward-line -1)
4580 (indent-to (+ margin vhdl-basic-offset))
4581 ))
4582
4583(defun vhdl-port ()
4584 "Insert a port declaration, or port map in instantiation statements."
4585 (interactive)
4586 (vhdl-insert-keyword "PORT (")
4587 (cond ((equal (car (car (cdr (vhdl-get-syntactic-context)))) 'entity)
4588 (vhdl-get-port nil))
4589 ((or (equal 'statement-cont (car (car (vhdl-get-syntactic-context))))
4590 (save-excursion
4591 (and (backward-word 2) (skip-chars-backward " ")
4592 (eq (preceding-char) ?:))))
4593 (delete-char -1) (vhdl-map))
4594 (t (vhdl-get-port nil t))))
4595
4596(defun vhdl-procedure ()
4597 "Insert a procedure specification or body template."
4598 (interactive)
4599 (let ((margin (current-column))
4600 (name))
4601 (vhdl-insert-keyword "PROCEDURE ")
4602 (if (equal (setq name (vhdl-field "name")) "")
4603 nil
4604 (vhdl-get-arg-list)
4605 (insert " ")
4606 (if (y-or-n-p "insert body? ")
4607 (progn (vhdl-insert-keyword "IS")
4608 (vhdl-begin-end (cons name margin))
4609 (vhdl-block-comment))
4610 (delete-char -1)
4611 (insert ";\n")
4612 (indent-to margin)
4613 ))))
4614
4615(defun vhdl-process ()
4616 "Insert a process template."
4617 (interactive)
4618 (let ((clocked))
4619 (let ((position (point)))
4620 (vhdl-insert-keyword "PROCESS")
4621 (setq clocked (y-or-n-p "clocked process? "))
4622 (goto-char position)
4623 (insert " : ")
4624 (goto-char position))
4625 (let* ((margin (current-column))
4626 (finalline)
4627 (name (vhdl-field "[label]"))
4628 (named (not (string-equal name "")))
4629 (clock) (reset)
4630 (case-fold-search t))
4631 (if (not named) (delete-char 3))
4632 (end-of-line)
4633 (insert " (")
4634 (if (not clocked)
4635 (if (equal (vhdl-field "[sensitivity list]" ")") "")
4636 (delete-char -3))
4637 (setq clock (vhdl-field "clock name" ", "))
4638 (setq reset (vhdl-field "reset name" ")")))
4639 (vhdl-begin-end (cons (concat (vhdl-case-keyword "PROCESS")
4640 (if named (concat " " name))) margin))
4641 (if clocked (vhdl-clock-async-reset clock reset))
4642 (if vhdl-prompt-for-comments
4643 (progn
4644 (setq finalline (vhdl-current-line))
4645 (if (and (re-search-backward "\\<begin\\>" nil t)
4646 (re-search-backward "\\<process\\>" nil t))
4647 (progn
4648 (end-of-line -0)
4649 (insert "\n")
4650 (indent-to margin)
4651 (insert "-- purpose: ")
4652 (if (equal (vhdl-field "description") "")
4653 (vhdl-kill-entire-line)
4654 (newline)
4655 (indent-to margin)
4656 (insert "-- type: ")
4657 (insert (if clocked "memorizing" "memoryless") "\n")
4658 (indent-to margin)
4659 (insert "-- inputs: ")
4660 (if clocked
4661 (insert clock ", " reset ", "))
4662 (if (and (equal (vhdl-field "signal names") "")
4663 clocked)
4664 (delete-char -2))
4665 (insert "\n")
4666 (indent-to margin)
4667 (insert "-- outputs: ")
4668 (vhdl-field "signal names")
4669 (setq finalline (+ finalline 4)))))
4670 (goto-line finalline)
4671 (end-of-line)
4672 )))))
4673
4674(defun vhdl-record ()
4675 "Insert a record type declaration."
4676 (interactive)
4677 (let ((margin (current-column))
4678 (start (point))
4679 (first t))
4680 (vhdl-insert-keyword "RECORD\n")
4681 (indent-to (+ margin vhdl-basic-offset))
4682 (if (equal (vhdl-field "identifiers") "")
4683 (progn (kill-line -0)
4684 (delete-char -1)
4685 (insert " "))
4686 (while (or first (not (equal (vhdl-field "[identifiers]") "")))
4687 (insert " : ")
4688 (vhdl-field "type" ";")
4689 (vhdl-declaration-comment)
4690 (newline)
4691 (indent-to (+ margin vhdl-basic-offset))
4692 (setq first nil))
4693 (kill-line -0)
4694 (indent-to margin)
4695 (vhdl-insert-keyword "END RECORD;")
4696 (if vhdl-auto-align (vhdl-align start (point) 1))
4697 )))
4698
4699(defun vhdl-return-value ()
4700 "Insert a return statement."
4701 (interactive)
4702 (vhdl-insert-keyword "RETURN ")
4703 (if (equal (vhdl-field "[expression]") "")
4704 (delete-char -1))
4705 (insert ";")
4706 )
4707
4708(defun vhdl-selected-signal-assignment ()
4709 "Insert a selected signal assignment."
4710 (interactive)
4711 (let ((margin (current-column))
4712 (start (point)))
4713 (let ((position (point)))
4714 (vhdl-insert-keyword " SELECT")
4715 (goto-char position))
4716 (vhdl-insert-keyword "WITH ")
4717 (if (equal (vhdl-field "selector expression") "")
4718 (progn (undo 0) (insert " "))
4719 (end-of-line)
4720 (insert "\n")
4721 (indent-to (+ margin vhdl-basic-offset))
4722 (vhdl-field "target signal" " <= ")
4723; (vhdl-field "[GUARDED] [TRANSPORT]")
4724 (insert "\n")
4725 (indent-to (+ margin vhdl-basic-offset))
4726 (while (not (equal (vhdl-field "[waveform]") ""))
4727 (vhdl-insert-keyword " WHEN ")
4728 (vhdl-field "choices" ",")
4729 (newline)
4730 (indent-to (+ margin vhdl-basic-offset)))
4731 (if (not (equal (vhdl-field "[alternative waveform]") ""))
4732 (vhdl-insert-keyword " WHEN OTHERS")
4733 (fixup-whitespace)
4734 (delete-char -2))
4735 (insert ";")
4736 (if vhdl-auto-align (vhdl-align start (point) 1))
4737 )))
4738
4739(defun vhdl-signal ()
4740 "Insert a signal declaration."
4741 (interactive)
4742 (vhdl-insert-keyword "SIGNAL ")
4743 (let ((in-arglist (string-match "arglist"
4744 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4745 (if (not in-arglist)
4746 (let ((opoint (point)))
4747 (beginning-of-line)
4748 (setq in-arglist (looking-at ".*("))
4749 (goto-char opoint)))
4750 (if (equal (vhdl-field "names") "")
4751 nil
4752 (insert " : ")
4753 (if in-arglist
4754 (progn (vhdl-field "direction")
4755 (insert " ")))
4756 (vhdl-field "type")
4757 (if in-arglist
4758 (insert ";")
4759 (let ((position (point)))
4760 (insert " := ")
4761 (if (equal (vhdl-field "[initialization]" ";") "")
4762 (progn (goto-char position) (kill-line) (insert ";")))
4763 (vhdl-declaration-comment))
4764 ))))
4765
4766(defun vhdl-subtype ()
4767 "Insert a subtype declaration."
4768 (interactive)
4769 (vhdl-insert-keyword "SUBTYPE ")
4770 (if (equal (vhdl-field "name") "")
4771 nil
4772 (vhdl-insert-keyword " IS ")
4773 (vhdl-field "type" " ")
4774 (if (equal (vhdl-field "[RANGE value range | ( index range )]") "")
4775 (delete-char -1))
4776 (insert ";")
4777 (vhdl-declaration-comment)
4778 ))
4779
4780(defun vhdl-type ()
4781 "Insert a type declaration."
4782 (interactive)
4783 (vhdl-insert-keyword "TYPE ")
4784 (if (equal (vhdl-field "name") "")
4785 nil
4786 (vhdl-insert-keyword " IS ")
4787 (let ((definition (upcase (vhdl-field "(scalar type | ARRAY | RECORD | ACCESS | FILE)"))))
4788 (cond ((equal definition "ARRAY")
4789 (kill-word -1) (vhdl-array))
4790 ((equal definition "RECORD")
4791 (kill-word -1) (vhdl-record))
4792 ((equal definition "ACCESS")
4793 (insert " ") (vhdl-field "type" ";"))
4794 ((equal definition "FILE")
4795 (vhdl-insert-keyword " OF ") (vhdl-field "type" ";"))
4796 (t (insert ";")))
4797 (vhdl-declaration-comment)
4798 )))
4799
4800(defun vhdl-use ()
4801 "Insert a use clause."
4802 (interactive)
4803 (vhdl-insert-keyword "USE ..ALL;")
4804 (backward-char 6)
4805 (if (equal (vhdl-field "library name") "")
4806 (progn (undo 0) (insert " "))
4807 (forward-char 1)
4808 (vhdl-field "package name")
4809 (end-of-line)
4810 ))
4811
4812(defun vhdl-variable ()
4813 "Insert a variable declaration."
4814 (interactive)
4815 (vhdl-insert-keyword "VARIABLE ")
4816 (let ((in-arglist (string-match "arglist"
4817 (format "%s" (car (car (vhdl-get-syntactic-context)))))))
4818 (if (not in-arglist)
4819 (let ((opoint (point)))
4820 (beginning-of-line)
4821 (setq in-arglist (looking-at ".*("))
4822 (goto-char opoint)))
4823 (if (equal (vhdl-field "names") "")
4824 nil
4825 (insert " : ")
4826 (if in-arglist
4827 (progn (vhdl-field "direction")
4828 (insert " ")))
4829 (vhdl-field "type")
4830 (if in-arglist
4831 (insert ";")
4832 (let ((position (point)))
4833 (insert " := ")
4834 (if (equal (vhdl-field "[initialization]" ";") "")
4835 (progn (goto-char position) (kill-line) (insert ";")))
4836 (vhdl-declaration-comment))
4837 ))))
4838
4839(defun vhdl-wait ()
4840 "Insert a wait statement."
4841 (interactive)
4842 (vhdl-insert-keyword "WAIT ")
4843 (if (equal (vhdl-field
4844 "[ON sensitivity list] [UNTIL condition] [FOR time expression]")
4845 "")
4846 (delete-char -1))
4847 (insert ";")
4848 )
4849
4850(defun vhdl-when ()
4851 "Indent correctly if within a case statement."
4852 (interactive)
4853 (let ((position (point))
4854 (margin))
4855 (if (and (re-search-forward "\\<end\\>" nil t)
4856 (looking-at "\\s-*\\<case\\>"))
4857 (progn
4858 (setq margin (current-indentation))
4859 (goto-char position)
4860 (delete-horizontal-space)
4861 (indent-to (+ margin vhdl-basic-offset)))
4862 (goto-char position)
4863 )
4864 (vhdl-insert-keyword "WHEN ")
4865 ))
4866
4867(defun vhdl-while-loop ()
4868 "Insert a while loop template."
4869 (interactive)
4870 (let ((position (point)))
4871 (vhdl-insert-keyword " : WHILE ")
4872 (goto-char position))
4873 (let* ((margin (current-column))
4874 (name (vhdl-field "[label]"))
4875 (named (not (string-equal name ""))))
4876 (if (not named) (delete-char 3))
4877 (end-of-line)
4878 (if vhdl-conditions-in-parenthesis (insert "("))
4879 (if (equal (vhdl-field "condition") "")
4880 (progn (undo 0) (insert " "))
4881 (if vhdl-conditions-in-parenthesis (insert ")"))
4882 (vhdl-insert-keyword " LOOP\n\n")
4883 (indent-to margin)
4884 (vhdl-insert-keyword "END LOOP")
4885 (insert (if named (concat " " name ";") ?;))
4886 (forward-line -1)
4887 (indent-to (+ margin vhdl-basic-offset))
4888 )))
4889
4890(defun vhdl-with ()
4891 "Insert a with statement (i.e. selected signal assignment)."
4892 (interactive)
4893 (vhdl-selected-signal-assignment)
4894 )
4895
4896;; ############################################################################
4897;; Custom functions
4898
4899(defun vhdl-clocked-wait ()
4900 "Insert a wait statement for rising clock edge."
4901 (interactive)
4902 (vhdl-insert-keyword "WAIT UNTIL ")
4903 (let* ((clock (vhdl-field "clock name")))
4904 (insert "'event")
4905 (vhdl-insert-keyword " AND ")
4906 (insert clock)
4907 (insert " = " vhdl-one-string ";")
4908 ))
4909
4910(defun vhdl-clock-async-reset (clock reset)
4911 "Insert a template reacting on asynchronous reset and rising clock edge
4912for inside a memorizing processes."
4913 (interactive)
4914 (let* ( (margin (current-column))
4915 (opoint))
4916 (if vhdl-self-insert-comments
4917 (insert "-- activities triggered by asynchronous reset (active low)\n"))
4918 (indent-to margin)
4919 (vhdl-insert-keyword "IF ")
4920 (insert reset " = " vhdl-zero-string)
4921 (vhdl-insert-keyword " THEN\n")
4922 (indent-to (+ margin vhdl-basic-offset))
4923 (setq opoint (point))
4924 (newline)
4925 (indent-to margin)
4926 (if vhdl-self-insert-comments
4927 (insert "-- activities triggered by rising edge of clock\n"))
4928 (indent-to margin)
4929 (vhdl-insert-keyword "ELSIF ")
4930 (insert clock "'event")
4931 (vhdl-insert-keyword " AND ")
4932 (insert clock " = " vhdl-one-string)
4933 (vhdl-insert-keyword " THEN\n")
4934 (indent-to (+ margin vhdl-basic-offset))
4935 (newline)
4936 (indent-to margin)
4937 (vhdl-insert-keyword "END IF;")
4938; (if vhdl-self-insert-comments (insert " -- " clock))
4939 (goto-char opoint)
4940 ))
4941
4942(defun vhdl-standard-package (library package)
4943 "Insert specification of a standard package."
4944 (interactive)
4945 (let ((margin (current-column)))
4946 (vhdl-insert-keyword "LIBRARY ")
4947 (insert library ";\n")
4948 (indent-to margin)
4949 (vhdl-insert-keyword "USE ")
4950 (insert library "." package)
4951 (vhdl-insert-keyword ".ALL;")
4952 ))
4953
4954(defun vhdl-package-numeric-bit ()
4955 "Insert specification of 'numeric_bit' package."
4956 (interactive)
4957 (vhdl-standard-package "ieee" "numeric_bit"))
4958
4959(defun vhdl-package-numeric-std ()
4960 "Insert specification of 'numeric_std' package."
4961 (interactive)
4962 (vhdl-standard-package "ieee" "numeric_std"))
4963
4964(defun vhdl-package-std-logic-1164 ()
4965 "Insert specification of 'std_logic_1164' package."
4966 (interactive)
4967 (vhdl-standard-package "ieee" "std_logic_1164"))
4968
4969(defun vhdl-package-textio ()
4970 "Insert specification of 'textio' package."
4971 (interactive)
4972 (vhdl-standard-package "std" "textio"))
4973
4974;; ############################################################################
4975;; Comment functions
4976
4977(defun vhdl-comment-indent ()
4978 (let* ((opoint (point))
4979 (col (progn
4980 (forward-line -1)
4981 (if (re-search-forward "--" opoint t)
4982 (- (current-column) 2) ;Existing comment at bol stays there.
4983 (goto-char opoint)
4984 (skip-chars-backward " \t")
4985 (max comment-column ;else indent to comment column
4986 (1+ (current-column))) ;except leave at least one space.
4987 ))))
4988 (goto-char opoint)
4989 col
4990 ))
4991
4992(defun vhdl-inline-comment ()
4993 "Start a comment at the end of the line.
4994 if on line with code, indent at least comment-column.
4995 if starting after end-comment-column, start a new line."
4996 (interactive)
4997 (if (> (current-column) end-comment-column) (newline-and-indent))
4998 (if (or (looking-at "\\s-*$") ;end of line
4999 (and (not unread-command-events) ; called with key binding or menu
5000 (not (end-of-line))))
5001 (let ((margin))
5002 (while (= (preceding-char) ?-) (delete-char -1))
5003 (setq margin (current-column))
5004 (delete-horizontal-space)
5005 (if (bolp)
5006 (progn (indent-to margin) (insert "--"))
5007 (insert " ")
5008 (indent-to comment-column)
5009 (insert "--"))
5010 (if (not unread-command-events) (insert " ")))
5011 ; else code following current point implies commenting out code
5012 (let (next-input code)
5013 (while (= (preceding-char) ?-) (delete-char -2))
5014 (while (= (setq next-input (read-char)) 13) ; CR
5015 (insert "--"); or have a space after it?
5016 (forward-char -2)
5017 (forward-line 1)
5018 (message "Enter CR if commenting out a line of code.")
5019 (setq code t)
5020 )
5021 (if (not code) (progn
5022; (indent-to comment-column)
5023 (insert "--") ;hardwire to 1 space or use vhdl-basic-offset?
5024 ))
5025 (setq unread-command-events
5026 (list (vhdl-character-to-event-hack next-input))) ;pushback the char
5027 )))
5028
5029(defun vhdl-display-comment (&optional line-exists)
5030 "Add 2 comment lines at the current indent, making a display comment."
5031 (interactive)
5032 (if (not line-exists)
5033 (vhdl-display-comment-line))
5034 (let* ((col (current-column))
5035 (len (- end-comment-column col)))
5036 (insert "\n")
5037 (insert-char ? col)
5038 (insert-char ?- len)
5039 (insert "\n")
5040 (insert-char ? col)
5041 (end-of-line -1)
5042 )
5043 (insert "-- ")
5044 )
5045
5046(defun vhdl-display-comment-line ()
5047 "Displays one line of dashes."
5048 (interactive)
5049 (while (= (preceding-char) ?-) (delete-char -2))
5050 (let* ((col (current-column))
5051 (len (- end-comment-column col)))
5052 (insert-char ?- len)
5053 (insert-char ?\n 1)
5054 (insert-char ? col)
5055 ))
5056
5057(defun vhdl-declaration-comment ()
5058 (if vhdl-prompt-for-comments
5059 (let ((position (point)))
5060 (insert " ")
5061 (indent-to comment-column)
5062 (insert "-- ")
5063 (if (equal (vhdl-field "comment") "")
5064 (progn (goto-char position) (kill-line))
5065 ))))
5066
5067(defun vhdl-block-comment ()
5068 (if vhdl-prompt-for-comments
5069 (let ((finalline (vhdl-current-line))
5070 (case-fold-search t))
5071 (beginning-of-line -0)
5072 (if (re-search-backward "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\)\\>" nil t)
5073 (let ((margin))
5074 (back-to-indentation)
5075 (setq margin (current-column))
5076 (end-of-line -0)
5077 (insert "\n")
5078 (indent-to margin)
5079 (insert "-- purpose: ")
5080 (if (equal (vhdl-field "description") "")
5081 (vhdl-kill-entire-line)
5082 (setq finalline (+ finalline 1)))))
5083 (goto-line finalline)
5084 (end-of-line)
5085 )))
5086
5087(defun vhdl-comment-uncomment-region (beg end &optional arg)
5088 "Comment out region if not commented out, uncomment out region if already
5089commented out."
5090 (interactive "r\nP")
5091 (goto-char beg)
5092 (if (looking-at comment-start)
5093 (comment-region beg end -1)
5094 (comment-region beg end)
5095 ))
5096
5097;; ############################################################################
5098;; Help functions
5099
5100(defun vhdl-outer-space (count)
5101 "Expand abbreviations and self-insert space(s), do indent-new-comment-line
5102if in comment and past end-comment-column."
5103 (interactive "p")
5104 (if (or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
5105 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
5106 (expand-abbrev))
5107 (if (not (vhdl-in-comment-p))
5108 (self-insert-command count)
5109 (if (< (current-column) end-comment-column)
5110 (self-insert-command count)
5111 (while (> (current-column) end-comment-column) (forward-word -1))
5112 (while (> (preceding-char) ? ) (forward-word -1))
5113 (delete-horizontal-space)
5114 (indent-new-comment-line)
5115 (end-of-line nil)
5116 (insert-char ? count)
5117 )))
5118
5119(defun vhdl-field (prompt &optional following-string)
5120 "Prompt for string and insert it in buffer with optional following-string."
5121 (let ((opoint (point)))
5122 (insert "<" prompt ">")
5123 (let ((string (read-from-minibuffer (concat prompt ": ") ""
5124 vhdl-minibuffer-local-map)))
5125 (delete-region opoint (point))
5126 (insert string (or following-string ""))
5127 (if vhdl-upper-case-keywords
5128 (vhdl-fix-case-region-1
5129 opoint (point) t vhdl-93-keywords-regexp))
5130 string
5131 )))
5132
5133(defun vhdl-in-comment-p ()
5134 "Check if point is to right of beginning comment delimiter."
5135 (interactive)
5136 (let ((opoint (point)))
5137 (save-excursion ; finds an unquoted comment
5138 (beginning-of-line)
5139 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" opoint t)
5140 )))
5141
5142(defun vhdl-in-string-p ()
5143 "Check if point is in a string."
5144 (interactive)
5145 (let ((opoint (point)))
5146 (save-excursion ; preceeded by odd number of string delimiters?
5147 (beginning-of-line)
5148 (equal
5149 opoint
5150 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*" opoint t))
5151 )))
5152
5153(defun vhdl-begin-end (list)
5154 "Insert a begin ... end pair with optional name after the end.
5155Point is left between them."
5156 (let ((return)
5157 (name (car list))
5158 (margin (cdr list)))
5159 (if vhdl-additional-empty-lines
5160 (progn
5161 (insert "\n")
5162 (indent-to (+ margin vhdl-basic-offset))))
5163 (insert "\n")
5164 (indent-to margin)
5165 (vhdl-insert-keyword "BEGIN")
5166 (if vhdl-self-insert-comments
5167 (insert (and name (concat " -- " name))))
5168 (insert "\n")
5169 (indent-to (+ margin vhdl-basic-offset))
5170 (setq return (point))
5171 (newline)
5172 (indent-to margin)
5173 (vhdl-insert-keyword "END")
5174 (insert (and name (concat " " name)) ";")
5175 (goto-char return)
5176 ))
5177
5178(defun vhdl-get-arg-list ()
5179 "Read from user a procedure or function argument list."
5180 (insert " (")
5181 (let ((margin (current-column)))
5182 (if (not vhdl-argument-list-indent)
5183 (let ((opoint (point)))
5184 (back-to-indentation)
5185 (setq margin (+ (current-column) vhdl-basic-offset))
5186 (goto-char opoint)
5187 (newline)
5188 (indent-to margin)))
5189 (let (not-empty interface)
5190 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
5191 (if (not (equal interface ""))
5192 (insert " "))
5193 (while (not (string-equal (vhdl-field "[names]") ""))
5194 (setq not-empty t)
5195 (insert " : ")
5196 (if (not (equal (vhdl-field "[direction]") ""))
5197 (insert " "))
5198 (vhdl-field "type" ";\n")
5199 (indent-to margin)
5200 (setq interface (vhdl-field "[CONSTANT] [SIGNAL] [VARIABLE]"))
5201 (if (not (equal interface ""))
5202 (insert " ")))
5203 (if not-empty
5204 (progn (kill-line -0)
5205 (delete-char -2)
5206 (if (not vhdl-argument-list-indent)
5207 (progn (insert "\n") (indent-to margin)))
5208 (insert ")"))
5209 (if vhdl-argument-list-indent
5210 (backward-delete-char 2)
5211 (kill-line -0)
5212 (backward-delete-char 3)))
5213; (while (string-match "[,;]$" args)
5214; (newline)
5215; (indent-to margin) (setq args (vhdl-field "next argument")))
5216; (insert 41) ;close-paren
5217 )))
5218
5219(defun vhdl-get-port (optional &optional no-comment)
5220 "Read from user a port spec argument list."
5221 (let ((margin (current-column))
5222 (start (point)))
5223 (if (not vhdl-argument-list-indent)
5224 (let ((opoint (point)))
5225 (back-to-indentation)
5226 (setq margin (+ (current-column) vhdl-basic-offset))
5227 (goto-char opoint)
5228 (newline)
5229 (indent-to margin)))
5230 (let ((vhdl-ports (vhdl-field "[names]")))
5231 (if (string-equal vhdl-ports "")
5232 (if optional
5233 (progn (vhdl-kill-entire-line) (forward-line -1)
5234 (if (not vhdl-argument-list-indent)
5235 (progn (vhdl-kill-entire-line) (forward-line -1))))
5236 (progn (undo 0) (insert " "))
5237 nil )
5238 (insert " : ")
5239 (progn
5240 (let ((semicolon-pos))
5241 (while (not (string-equal "" vhdl-ports))
5242 (vhdl-field "direction")
5243 (insert " ")
5244 (vhdl-field "type")
5245 (setq semicolon-pos (point))
5246 (insert ";")
5247 (if (not no-comment)
5248 (vhdl-declaration-comment))
5249 (newline)
5250 (indent-to margin)
5251 (setq vhdl-ports (vhdl-field "[names]" " : ")))
5252 (goto-char semicolon-pos)
5253 (if (not vhdl-argument-list-indent)
5254 (progn (insert "\n") (indent-to margin)))
5255 (insert ")")
5256 (forward-char 1)
5257 (if (= (following-char) ? )
5258 (delete-char 1))
5259 (forward-line 1)
5260 (vhdl-kill-entire-line)
5261 (end-of-line -0)
5262 (if vhdl-auto-align (vhdl-align start (point) 1))
5263 t))))))
5264
5265(defun vhdl-get-generic (optional &optional no-value )
5266 "Read from user a generic spec argument list."
5267 (let ((margin (current-column))
5268 (start (point)))
5269 (if (not vhdl-argument-list-indent)
5270 (let ((opoint (point)))
5271 (back-to-indentation)
5272 (setq margin (+ (current-column) vhdl-basic-offset))
5273 (goto-char opoint)
5274 (newline)
5275 (indent-to margin)))
5276 (let ((vhdl-generic))
5277 (if no-value
5278 (setq vhdl-generic (vhdl-field "[names]"))
5279 (setq vhdl-generic (vhdl-field "[name]")))
5280 (if (string-equal vhdl-generic "")
5281 (if optional
5282 (progn (vhdl-kill-entire-line) (end-of-line -0)
5283 (if (not vhdl-argument-list-indent)
5284 (progn (vhdl-kill-entire-line) (end-of-line -0))))
5285 (progn (undo 0) (insert " "))
5286 nil )
5287 (insert " : ")
5288 (progn
5289 (let ((semicolon-pos))
5290 (while (not(string-equal "" vhdl-generic))
5291 (vhdl-field "type")
5292 (if no-value
5293 (progn (setq semicolon-pos (point))
5294 (insert ";"))
5295 (insert " := ")
5296 (if (equal (vhdl-field "[value]") "")
5297 (delete-char -4))
5298 (setq semicolon-pos (point))
5299 (insert ";")
5300 (vhdl-declaration-comment))
5301 (newline)
5302 (indent-to margin)
5303 (if no-value
5304 (setq vhdl-generic (vhdl-field "[names]" " : "))
5305 (setq vhdl-generic (vhdl-field "[name]" " : "))))
5306 (goto-char semicolon-pos)
5307 (if (not vhdl-argument-list-indent)
5308 (progn (insert "\n") (indent-to margin)))
5309 (insert ")")
5310 (forward-char 1)
5311 (if (= (following-char) ? )
5312 (delete-char 1))
5313 (forward-line 1)
5314 (vhdl-kill-entire-line)
5315 (end-of-line -0)
5316 (if vhdl-auto-align (vhdl-align start (point) 1))
5317 t))))))
5318
5319(defun vhdl-insert-date ()
5320 "Insert date in appropriate format."
5321 (interactive)
5322 (insert
5323 (cond
5324 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
5325 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
5326 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
5327 )))
5328
5329(defun vhdl-insert-keyword (keyword)
5330 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
5331 )
5332
5333(defun vhdl-case-keyword (keyword)
5334 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))
5335 )
5336
5337(defun vhdl-case-word (num)
5338 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num))
5339 )
5340
5341(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
5342 "Convert all words matching word-regexp in region to lower or upper case,
5343depending on parameter upper-case."
5344 (let ((case-fold-search t)
5345 (case-replace nil)
5346 (busy-counter 0))
5347 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
5348 (save-excursion
5349 (goto-char beg)
5350 (while (re-search-forward word-regexp end t)
5351 (or (vhdl-in-comment-p)
5352 (vhdl-in-string-p)
5353 (if upper-case
5354 (upcase-word -1)
5355 (downcase-word -1)))
5356 (if (and count
5357 (/= busy-counter (setq busy-counter
5358 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg))))))
5359 (message (format "Fixing case ... (%2d%s)" busy-counter "%%"))))
5360 (goto-char end))
5361 (if (not vhdl-underscore-is-part-of-word)
5362 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
5363 (message "")
5364 ))
5365
5366(defun vhdl-fix-case-region (beg end &optional arg)
5367 "Convert all VHDL words in region to lower or upper case, depending on
5368variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
5369 (interactive "r\nP")
5370 (vhdl-fix-case-region-1
5371 beg end vhdl-upper-case-keywords vhdl-93-keywords-regexp 0)
5372 (vhdl-fix-case-region-1
5373 beg end vhdl-upper-case-types vhdl-93-types-regexp 1)
5374 (vhdl-fix-case-region-1
5375 beg end vhdl-upper-case-attributes vhdl-93-attributes-regexp 2)
5376 (vhdl-fix-case-region-1
5377 beg end vhdl-upper-case-enum-values vhdl-93-enum-values-regexp 3)
5378 )
5379
5380(defun vhdl-fix-case-buffer ()
5381 "Convert all VHDL words in buffer to lower or upper case, depending on
5382variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
5383 (interactive)
5384 (vhdl-fix-case-region (point-min) (point-max))
5385 )
5386
5387(defun vhdl-minibuffer-tab (&optional prefix-arg)
5388 "If preceeding character is part of a word then dabbrev-expand,
5389else if right of non whitespace on line then tab-to-tab-stop,
5390else indent line in proper way for current major mode
5391(used for word completion in VHDL minibuffer)."
5392 (interactive "P")
5393 (cond ((= (char-syntax (preceding-char)) ?w)
5394 (let ((case-fold-search nil)) (dabbrev-expand prefix-arg)))
5395 ((> (current-column) (current-indentation))
5396 (tab-to-tab-stop))
5397 (t
5398 (if (eq indent-line-function 'indent-to-left-margin)
5399 (insert-tab prefix-arg)
5400 (if prefix-arg
5401 (funcall indent-line-function prefix-arg)
5402 (funcall indent-line-function))))))
5403
5404(defun vhdl-help ()
5405 "Display help information in '*Help*' buffer ."
5406 (interactive)
5407 (with-output-to-temp-buffer "*Help*"
5408 (princ mode-name)
5409 (princ " mode:\n")
5410 (princ (documentation major-mode))
5411 (save-excursion
5412 (set-buffer standard-output)
5413 (help-mode))
5414 (print-help-return-message)))
5415
5416(defun vhdl-current-line ()
5417 "Return the line number of the line containing point."
5418 (save-restriction
5419 (widen)
5420 (save-excursion
5421 (beginning-of-line)
5422 (1+ (count-lines 1 (point)))))
5423 )
5424
5425(defun vhdl-kill-entire-line ()
5426 "Delete entire line."
5427 (interactive)
5428 (end-of-line)
5429 (kill-line -0)
5430 (delete-char 1)
5431 )
5432
5433(defun vhdl-open-line ()
5434 "Open a new line and indent."
5435 (interactive)
5436 (end-of-line)
5437 (newline-and-indent)
5438 )
5439
5440(defun vhdl-kill-line ()
5441 "Kill current line."
5442 (interactive)
5443 (vhdl-kill-entire-line)
5444 )
5445
5446(defun vhdl-character-to-event-hack (char)
5447 (if (memq 'XEmacs vhdl-emacs-features)
5448 (character-to-event char)
5449 char))
5450
5451;; ############################################################################
5452;; Abbrev hooks
5453
5454(defun vhdl-electric-mode ()
5455 "Toggle VHDL Electric mode."
5456 (interactive)
5457 (setq vhdl-electric-mode (not vhdl-electric-mode))
5458 (setq mode-name (if vhdl-electric-mode "Electric VHDL" "VHDL"))
5459 (force-mode-line-update)
5460 )
5461
5462(defun vhdl-stutter-mode ()
5463 "Toggle VHDL Stuttering mode."
5464 (interactive)
5465 (setq vhdl-stutter-mode (not vhdl-stutter-mode))
5466 )
5467
5468(defun vhdl-hooked-abbrev (fun)
5469 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
5470but not if inside a comment or quote)"
5471 (if (or (vhdl-in-comment-p)
5472 (vhdl-in-string-p)
5473 (save-excursion (forward-word -1) (looking-at "end")))
5474 (progn
5475 (insert " ")
5476 (unexpand-abbrev)
5477 (delete-char -1))
5478 (if (not vhdl-electric-mode)
5479 (progn
5480 (insert " ")
5481 (unexpand-abbrev)
5482 (backward-word 1)
5483 (vhdl-case-word 1)
5484 (delete-char 1)
5485 )
5486 (let ((invoke-char last-command-char) (abbrev-mode -1))
5487 (funcall fun)
5488 (if (= invoke-char ?-) (setq abbrev-start-location (point)))
5489 ;; delete CR which is still in event queue
5490 (if (memq 'XEmacs vhdl-emacs-features)
5491 (enqueue-eval-event 'delete-char -1)
5492 (setq unread-command-events ; push back a delete char
5493 (list (vhdl-character-to-event-hack ?\177))))
5494 ))))
5495
5496(defun vhdl-alias-hook () "hooked version of vhdl-alias."
5497 (vhdl-hooked-abbrev 'vhdl-alias))
5498(defun vhdl-architecture-hook () "hooked version of vhdl-architecture."
5499 (vhdl-hooked-abbrev 'vhdl-architecture))
5500(defun vhdl-array-hook () "hooked version of vhdl-array."
5501 (vhdl-hooked-abbrev 'vhdl-array))
5502(defun vhdl-assert-hook () "hooked version of vhdl-assert."
5503 (vhdl-hooked-abbrev 'vhdl-assert))
5504(defun vhdl-attribute-hook () "hooked version of vhdl-attribute."
5505 (vhdl-hooked-abbrev 'vhdl-attribute))
5506(defun vhdl-block-hook () "hooked version of vhdl-block."
5507 (vhdl-hooked-abbrev 'vhdl-block))
5508(defun vhdl-case-hook () "hooked version of vhdl-case."
5509 (vhdl-hooked-abbrev 'vhdl-case))
5510(defun vhdl-component-hook () "hooked version of vhdl-component."
5511 (vhdl-hooked-abbrev 'vhdl-component))
5512(defun vhdl-component-instance-hook ()
5513 "hooked version of vhdl-component-instance."
5514 (vhdl-hooked-abbrev 'vhdl-component-instance))
5515(defun vhdl-concurrent-signal-assignment-hook ()
5516 "hooked version of vhdl-concurrent-signal-assignment."
5517 (vhdl-hooked-abbrev 'vhdl-concurrent-signal-assignment))
5518(defun vhdl-configuration-hook ()
5519 "hooked version of vhdl-configuration."
5520 (vhdl-hooked-abbrev 'vhdl-configuration))
5521(defun vhdl-constant-hook () "hooked version of vhdl-constant."
5522 (vhdl-hooked-abbrev 'vhdl-constant))
5523(defun vhdl-disconnect-hook () "hooked version of vhdl-disconnect."
5524 (vhdl-hooked-abbrev 'vhdl-disconnect))
5525(defun vhdl-display-comment-hook () "hooked version of vhdl-display-comment."
5526 (vhdl-hooked-abbrev 'vhdl-display-comment))
5527(defun vhdl-else-hook () "hooked version of vhdl-else."
5528 (vhdl-hooked-abbrev 'vhdl-else))
5529(defun vhdl-elsif-hook () "hooked version of vhdl-elsif."
5530 (vhdl-hooked-abbrev 'vhdl-elsif))
5531(defun vhdl-entity-hook () "hooked version of vhdl-entity."
5532 (vhdl-hooked-abbrev 'vhdl-entity))
5533(defun vhdl-exit-hook () "hooked version of vhdl-exit."
5534 (vhdl-hooked-abbrev 'vhdl-exit))
5535(defun vhdl-for-hook () "hooked version of vhdl-for."
5536 (vhdl-hooked-abbrev 'vhdl-for))
5537(defun vhdl-function-hook () "hooked version of vhdl-function."
5538 (vhdl-hooked-abbrev 'vhdl-function))
5539(defun vhdl-generate-hook () "hooked version of vhdl-generate."
5540 (vhdl-hooked-abbrev 'vhdl-generate))
5541(defun vhdl-generic-hook () "hooked version of vhdl-generic."
5542 (vhdl-hooked-abbrev 'vhdl-generic))
5543(defun vhdl-library-hook () "hooked version of vhdl-library."
5544 (vhdl-hooked-abbrev 'vhdl-library))
5545(defun vhdl-header-hook () "hooked version of vhdl-header."
5546 (vhdl-hooked-abbrev 'vhdl-header))
5547(defun vhdl-if-hook () "hooked version of vhdl-if."
5548 (vhdl-hooked-abbrev 'vhdl-if))
5549(defun vhdl-loop-hook () "hooked version of vhdl-loop."
5550 (vhdl-hooked-abbrev 'vhdl-loop))
5551(defun vhdl-map-hook () "hooked version of vhdl-map."
5552 (vhdl-hooked-abbrev 'vhdl-map))
5553(defun vhdl-modify-hook () "hooked version of vhdl-modify."
5554 (vhdl-hooked-abbrev 'vhdl-modify))
5555(defun vhdl-next-hook () "hooked version of vhdl-next."
5556 (vhdl-hooked-abbrev 'vhdl-next))
5557(defun vhdl-package-hook () "hooked version of vhdl-package."
5558 (vhdl-hooked-abbrev 'vhdl-package))
5559(defun vhdl-port-hook () "hooked version of vhdl-port."
5560 (vhdl-hooked-abbrev 'vhdl-port))
5561(defun vhdl-procedure-hook () "hooked version of vhdl-procedure."
5562 (vhdl-hooked-abbrev 'vhdl-procedure))
5563(defun vhdl-process-hook () "hooked version of vhdl-process."
5564 (vhdl-hooked-abbrev 'vhdl-process))
5565(defun vhdl-record-hook () "hooked version of vhdl-record."
5566 (vhdl-hooked-abbrev 'vhdl-record))
5567(defun vhdl-return-hook () "hooked version of vhdl-return-value."
5568 (vhdl-hooked-abbrev 'vhdl-return-value))
5569(defun vhdl-selected-signal-assignment-hook ()
5570 "hooked version of vhdl-selected-signal-assignment."
5571 (vhdl-hooked-abbrev 'vhdl-selected-signal-assignment))
5572(defun vhdl-signal-hook () "hooked version of vhdl-signal."
5573 (vhdl-hooked-abbrev 'vhdl-signal))
5574(defun vhdl-subtype-hook () "hooked version of vhdl-subtype."
5575 (vhdl-hooked-abbrev 'vhdl-subtype))
5576(defun vhdl-type-hook () "hooked version of vhdl-type."
5577 (vhdl-hooked-abbrev 'vhdl-type))
5578(defun vhdl-use-hook () "hooked version of vhdl-use."
5579 (vhdl-hooked-abbrev 'vhdl-use))
5580(defun vhdl-variable-hook () "hooked version of vhdl-variable."
5581 (vhdl-hooked-abbrev 'vhdl-variable))
5582(defun vhdl-wait-hook () "hooked version of vhdl-wait."
5583 (vhdl-hooked-abbrev 'vhdl-wait))
5584(defun vhdl-when-hook () "hooked version of vhdl-when."
5585 (vhdl-hooked-abbrev 'vhdl-when))
5586(defun vhdl-while-loop-hook () "hooked version of vhdl-while-loop."
5587 (vhdl-hooked-abbrev 'vhdl-while-loop))
5588(defun vhdl-and-hook () "hooked version of vhdl-and."
5589 (vhdl-hooked-abbrev 'vhdl-and))
5590(defun vhdl-or-hook () "hooked version of vhdl-or."
5591 (vhdl-hooked-abbrev 'vhdl-or))
5592(defun vhdl-nand-hook () "hooked version of vhdl-nand."
5593 (vhdl-hooked-abbrev 'vhdl-nand))
5594(defun vhdl-nor-hook () "hooked version of vhdl-nor."
5595 (vhdl-hooked-abbrev 'vhdl-nor))
5596(defun vhdl-xor-hook () "hooked version of vhdl-xor."
5597 (vhdl-hooked-abbrev 'vhdl-xor))
5598(defun vhdl-xnor-hook () "hooked version of vhdl-xnor."
5599 (vhdl-hooked-abbrev 'vhdl-xnor))
5600(defun vhdl-not-hook () "hooked version of vhdl-not."
5601 (vhdl-hooked-abbrev 'vhdl-not))
5602
5603(defun vhdl-default-hook () "hooked version of vhdl-default."
5604 (vhdl-hooked-abbrev 'vhdl-default))
5605(defun vhdl-default-indent-hook () "hooked version of vhdl-default-indent."
5606 (vhdl-hooked-abbrev 'vhdl-default-indent))
5607
5608
5609;; ############################################################################
5610;; Font locking
5611;; ############################################################################
5612;; (using `font-lock.el')
5613
5614;; ############################################################################
5615;; Syntax definitions
5616
5617(defvar vhdl-font-lock-keywords nil
5618 "Regular expressions to highlight in VHDL Mode.")
5619
5620(defconst vhdl-font-lock-keywords-0
5621 (list
5622 ;; highlight template prompts
5623 '("\\(^\\|[ (.\t]\\)\\(<[^ =].*[^ =]>\\)\\([ .]\\|$\\)"
5624 2 vhdl-font-lock-prompt-face)
5625
5626 ;; highlight character literals
5627 '("'\\(.\\)'" 1 'font-lock-string-face)
5628 )
5629 "For consideration as a value of `vhdl-font-lock-keywords'.
5630This does highlighting of template prompts and character literals.")
5631
5632(defconst vhdl-font-lock-keywords-1
5633 (list
5634 ;; highlight names of units, subprograms, and components when declared
5635 (list
5636 (concat
5637 "^\\s-*\\("
5638 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
5639 "function\\|procedure\\|component"
5640 "\\)\\s-+\\(\\w+\\)")
5641 3 'font-lock-function-name-face)
5642
5643 ;; highlight labels of common constructs
5644 (list
5645 (concat
5646 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\("
5647 "assert\\|block\\|case\\|exit\\|for\\|if\\|loop\\|"
5648 "next\\|null\\|process\\| with\\|while\\|"
5649 "\\w+\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map"
5650 "\\)\\>")
5651 1 'font-lock-function-name-face)
5652
5653 ;; highlight entity names of architectures and configurations
5654 (list
5655 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
5656 2 'font-lock-function-name-face)
5657
5658 ;; highlight names and labels at end of constructs
5659 (list
5660 (concat
5661 "^\\s-*end\\s-+\\("
5662 "\\(block\\|case\\|component\\|for\\|generate\\|if\\|loop\\|"
5663 "process\\|record\\|units\\)\\>\\|"
5664 "\\)\\s-*\\(\\w*\\)")
5665 3 'font-lock-function-name-face)
5666 )
5667"For consideration as a value of `vhdl-font-lock-keywords'.
5668This does highlighting of names and labels.")
5669
5670(defconst vhdl-font-lock-keywords-2
5671 (list
5672 ;; highlight keywords, and types, standardized attributes, enumeration values
5673 (list (concat "'" vhdl-93-attributes-regexp)
5674 1 'vhdl-font-lock-attribute-face)
5675 (list vhdl-93-types-regexp 1 'font-lock-type-face)
5676 (list vhdl-93-enum-values-regexp 1 'vhdl-font-lock-value-face)
5677 (list vhdl-93-keywords-regexp 1 'font-lock-keyword-face)
5678 )
5679 "For consideration as a value of `vhdl-font-lock-keywords'.
5680This does highlighting of comments, keywords, and standard types.")
5681
5682(defconst vhdl-font-lock-keywords-3
5683 (list
5684 ;; highlight clock signals.
5685 (cons vhdl-clock-signal-syntax 'vhdl-font-lock-clock-signal-face)
5686 (cons vhdl-reset-signal-syntax 'vhdl-font-lock-reset-signal-face)
5687 (cons vhdl-control-signal-syntax 'vhdl-font-lock-control-signal-face)
5688 (cons vhdl-data-signal-syntax 'vhdl-font-lock-data-signal-face)
5689 (cons vhdl-test-signal-syntax 'vhdl-font-lock-test-signal-face)
5690 )
5691 "For consideration as a value of `vhdl-font-lock-keywords'.
5692This does highlighting of signal names with specific syntax.")
5693
5694;; ############################################################################
5695;; Font and color definitions
5696
5697(defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
5698 "Face name to use for prompts.")
5699
5700(defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
5701 "Face name to use for attributes.")
5702
5703(defvar vhdl-font-lock-value-face 'vhdl-font-lock-value-face
5704 "Face name to use for enumeration values.")
5705
5706(defvar vhdl-font-lock-clock-signal-face 'vhdl-font-lock-clock-signal-face
5707 "Face name to use for clock signals.")
5708
5709(defvar vhdl-font-lock-reset-signal-face 'vhdl-font-lock-reset-signal-face
5710 "Face name to use for reset signals.")
5711
5712(defvar vhdl-font-lock-control-signal-face 'vhdl-font-lock-control-signal-face
5713 "Face name to use for control signals.")
5714
5715(defvar vhdl-font-lock-data-signal-face 'vhdl-font-lock-data-signal-face
5716 "Face name to use for data signals.")
5717
5718(defvar vhdl-font-lock-test-signal-face 'vhdl-font-lock-test-signal-face
5719 "Face name to use for test signals.")
5720
5721(defface vhdl-font-lock-prompt-face
5722 '((((class color) (background light)) (:foreground "Red"))
5723 (((class color) (background dark)) (:foreground "Red"))
5724 (t (:inverse-video t)))
5725 "Font Lock mode face used to highlight prompts."
5726 :group 'font-lock-highlighting-faces)
5727
5728(defface vhdl-font-lock-attribute-face
5729 '((((class color) (background light)) (:foreground "CadetBlue"))
5730 (((class color) (background dark)) (:foreground "CadetBlue"))
5731 (t (:italic t :bold t)))
5732 "Font Lock mode face used to highlight attributes."
5733 :group 'font-lock-highlighting-faces)
5734
5735(defface vhdl-font-lock-value-face
5736 '((((class color) (background light)) (:foreground "DarkGoldenrod"))
5737 (((class color) (background dark)) (:foreground "DarkGoldenrod"))
5738 (t (:italic t :bold t)))
5739 "Font Lock mode face used to highlight enumeration values."
5740 :group 'font-lock-highlighting-faces)
5741
5742(defface vhdl-font-lock-clock-signal-face
5743 '((((class color) (background light)) (:foreground "LimeGreen"))
5744 (((class color) (background dark)) (:foreground "LimeGreen"))
5745 (t ()))
5746 "Font Lock mode face used to highlight clock signals."
5747 :group 'font-lock-highlighting-faces)
5748
5749(defface vhdl-font-lock-reset-signal-face
5750 '((((class color) (background light)) (:foreground "Red"))
5751 (((class color) (background dark)) (:foreground "Red"))
5752 (t ()))
5753 "Font Lock mode face used to highlight reset signals."
5754 :group 'font-lock-highlighting-faces)
5755
5756(defface vhdl-font-lock-control-signal-face
5757 '((((class color) (background light)) (:foreground "Blue"))
5758 (((class color) (background dark)) (:foreground "Blue"))
5759 (t ()))
5760 "Font Lock mode face used to highlight control signals."
5761 :group 'font-lock-highlighting-faces)
5762
5763(defface vhdl-font-lock-data-signal-face
5764 '((((class color) (background light)) (:foreground "Black"))
5765 (((class color) (background dark)) (:foreground "Black"))
5766 (t ()))
5767 "Font Lock mode face used to highlight data signals."
5768 :group 'font-lock-highlighting-faces)
5769
5770(defface vhdl-font-lock-test-signal-face
5771 '((((class color) (background light)) (:foreground "Gold"))
5772 (((class color) (background dark)) (:foreground "Gold"))
5773 (t ()))
5774 "Font Lock mode face used to highlight test signals."
5775 :group 'font-lock-highlighting-faces)
5776
5777;; Custom color definitions for existing faces
5778(defun vhdl-set-face-foreground ()
5779 (set-face-foreground 'font-lock-comment-face "IndianRed")
5780 (set-face-foreground 'font-lock-function-name-face "MediumOrchid")
5781 (set-face-foreground 'font-lock-keyword-face "SlateBlue")
5782 (set-face-foreground 'font-lock-string-face "RosyBrown")
5783 (set-face-foreground 'font-lock-type-face "ForestGreen")
5784 )
5785
5786(defun vhdl-set-face-grayscale ()
5787 (interactive)
5788 (set-face-bold-p 'font-lock-comment-face nil)
5789 (set-face-inverse-video-p 'font-lock-comment-face nil)
5790 (set-face-italic-p 'font-lock-comment-face t)
5791 (set-face-underline-p 'font-lock-comment-face nil)
5792
5793 (set-face-bold-p 'font-lock-function-name-face nil)
5794 (set-face-inverse-video-p 'font-lock-function-name-face nil)
5795 (set-face-italic-p 'font-lock-function-name-face t)
5796 (set-face-underline-p 'font-lock-function-name-face nil)
5797
5798 (set-face-bold-p 'font-lock-keyword-face t)
5799 (set-face-inverse-video-p 'font-lock-keyword-face nil)
5800 (set-face-italic-p 'font-lock-keyword-face nil)
5801 (set-face-underline-p 'font-lock-keyword-face nil)
5802
5803 (set-face-bold-p 'font-lock-string-face nil)
5804 (set-face-inverse-video-p 'font-lock-string-face nil)
5805 (set-face-italic-p 'font-lock-string-face nil)
5806 (set-face-underline-p 'font-lock-string-face t)
5807
5808 (set-face-bold-p 'font-lock-type-face t)
5809 (set-face-inverse-video-p 'font-lock-type-face nil)
5810 (set-face-italic-p 'font-lock-type-face t)
5811 (set-face-underline-p 'font-lock-type-face nil)
5812 )
5813
5814;; ############################################################################
5815;; Font lock initialization
5816
5817(defun vhdl-font-lock-init ()
5818 "Initializes fontification."
5819 (setq vhdl-font-lock-keywords
5820 (append vhdl-font-lock-keywords-0
5821 (if vhdl-highlight-names vhdl-font-lock-keywords-1)
5822 (if vhdl-highlight-keywords vhdl-font-lock-keywords-2)
5823 (if (and vhdl-highlight-signals (x-display-color-p))
5824 vhdl-font-lock-keywords-3)))
5825 (if (x-display-color-p)
5826 (if (not vhdl-use-default-colors) (vhdl-set-face-foreground))
5827 (if (not vhdl-use-default-faces) (vhdl-set-face-grayscale))
5828 ))
5829
5830;; ############################################################################
5831;; Fontification for postscript printing
5832
5833(defun vhdl-ps-init ()
5834 "Initializes face and page settings for postscript printing."
5835 (require 'ps-print)
5836 (unless (or vhdl-use-default-faces
5837 ps-print-color-p)
5838 (set (make-local-variable 'ps-bold-faces)
5839 '(font-lock-keyword-face
5840 font-lock-type-face
5841 vhdl-font-lock-attribute-face
5842 vhdl-font-lock-value-face))
5843 (set (make-local-variable 'ps-italic-faces)
5844 '(font-lock-comment-face
5845 font-lock-function-name-face
5846 font-lock-type-face
5847 vhdl-font-lock-prompt-face
5848 vhdl-font-lock-attribute-face
5849 vhdl-font-lock-value-face))
5850 (set (make-local-variable 'ps-underlined-faces)
5851 '(font-lock-string-face))
5852 )
5853 ;; define page settings, so that a line containing 79 characters (default)
5854 ;; fits into one column
5855 (if vhdl-print-two-column
5856 (progn
5857 (set (make-local-variable 'ps-landscape-mode) t)
5858 (set (make-local-variable 'ps-number-of-columns) 2)
5859 (set (make-local-variable 'ps-font-size) 7.0)
5860 (set (make-local-variable 'ps-header-title-font-size) 10.0)
5861 (set (make-local-variable 'ps-header-font-size) 9.0)
5862 (set (make-local-variable 'ps-header-offset) 12.0)
5863 (if (eq ps-paper-type 'letter)
5864 (progn
5865 (set (make-local-variable 'ps-inter-column) 40.0)
5866 (set (make-local-variable 'ps-left-margin) 40.0)
5867 (set (make-local-variable 'ps-right-margin) 40.0)
5868 )))))
5869
5870
5871;; ############################################################################
5872;; Hideshow
5873;; ############################################################################
5874;; (using `hideshow.el')
5875
5876(defun vhdl-forward-sexp-function (&optional count)
5877 "Find begin and end of VHDL process or block (for hideshow)."
5878 (interactive "p")
5879 (let (name
5880 (case-fold-search t))
5881 (end-of-line)
5882 (if (< count 0)
5883 (re-search-backward "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|block\\)\\>" nil t)
5884 (re-search-forward "\\s-*\\<end\\s-+\\(process\\|block\\)\\>" nil t)
5885 )))
5886
5887(require 'hideshow)
5888
5889(unless (assq 'vhdl-mode hs-special-modes-alist)
5890 (setq hs-special-modes-alist
5891 (cons
5892 '(vhdl-mode
5893 "\\s-*\\(\\w\\|\\s_\\)+\\s-*:\\s-*\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
5894 "\\s-*\\<\\(end\\|END\\)\\s-+\\(process\\|PROCESS\\|block\\|BLOCK\\)\\>"
5895 "-- "
5896 vhdl-forward-sexp-function)
5897 hs-special-modes-alist)))
5898
5899
5900;; ############################################################################
5901;; Compilation
5902;; ############################################################################
5903;; (using `compile.el')
5904
5905(defvar vhdl-compile-commands
5906 '(
5907 (cadence "cv -file" nil)
5908 (ikos "analyze" nil)
5909 (quickhdl "qvhcom" nil)
5910 (synopsys "vhdlan" nil)
5911 (vantage "analyze -libfile vsslib.ini -src" nil)
5912 (viewlogic "analyze -libfile vsslib.ini -src" nil)
5913 (v-system "vcom" "vmake > Makefile")
5914 )
5915 "Commands to be called in the shell for compilation (syntax analysis) of a
5916single buffer and `Makefile' generation for different tools. First item is tool
5917identifier, second item is shell command for compilation, and third item is
5918shell command for `Makefile' generation. A tool is specified by assigning a
5919tool identifier to variable `vhdl-compiler'.")
5920
5921(defvar vhdl-compilation-error-regexp-alist
5922 (list
5923 ;; Cadence Design Systems: cv -file test.vhd
5924 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
5925 '("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2)
5926
5927 ;; Ikos Voyager: analyze test.vhd
5928 ;; E L4/C5: this library unit is inaccessible
5929 ; Xemacs does not support error messages without included file name
5930 (if (not (memq 'XEmacs vhdl-emacs-features))
5931 '("E L\\([0-9]+\\)/C[0-9]+:" nil 1)
5932 '("E L\\([0-9]+\\)/C[0-9]+:" 2 1)
5933 )
5934
5935 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd
5936 ;; ERROR: test.vhd(24): near "dnd": expecting: END
5937 '("ERROR: \\(.+\\)(\\([0-9]+\\)):" 1 2)
5938
5939 ;; Synopsys, VHDL Analyzer: vhdlan test.vhd
5940 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
5941 '("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2)
5942
5943 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
5944 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
5945 ; Xemacs does not support error messages without included file name
5946 (if (not (memq 'XEmacs vhdl-emacs-features))
5947 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" nil 1)
5948 '("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 2 1)
5949 )
5950
5951 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
5952 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
5953 ;; same regexp as for Vantage
5954
5955 ;; V-System, Model Technology: vcom test.vhd
5956 ;; ERROR: test.vhd(14): Unknown identifier: positiv
5957 ;; same regexp as for QuickHDL
5958
5959 ) "Alist that specifies how to match errors in VHDL compiler output.")
5960
5961(defvar compilation-file-regexp-alist
5962 '(
5963 ;; Ikos Voyager: analyze -libfile vsslib.ini -src test.vhd
5964 ;; analyze sdrctl.vhd
5965 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2)
5966
5967 ;; Vantage Analysis Systems: analyze -libfile vsslib.ini -src test.vhd
5968 ;; Compiling "pcu.vhd" line 1...
5969 (" *Compiling \"\\(.+\\)\" " 1)
5970
5971 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
5972 ;; Compiling "pcu.vhd" line 1...
5973 ;; same regexp as for Vantage
5974
5975 ) "Alist specifying how to match lines that indicate a new current file.
5976Used for compilers with no file name in the error messages.")
5977
5978(defun vhdl-compile ()
5979 "Compile current buffer using the VHDL compiler specified in
5980`vhdl-compiler'."
5981 (interactive)
5982 (let ((command-list vhdl-compile-commands)
5983 command)
5984 (while command-list
5985 (if (eq vhdl-compiler (car (car command-list)))
5986 (setq command (car (cdr (car command-list)))))
5987 (setq command-list (cdr command-list)))
5988 (if command
5989 (compile (concat command " " vhdl-compiler-options
5990 (if (not (string-equal vhdl-compiler-options "")) " ")
5991 (file-name-nondirectory (buffer-file-name)))))))
5992
5993(defun vhdl-make ()
5994 "Call make command for compilation of all updated source files
5995(requires `Makefile')."
5996 (interactive)
5997 (compile "make"))
5998
5999(defun vhdl-generate-makefile ()
6000 "Generate new `Makefile'."
6001 (interactive)
6002 (let ((command-list vhdl-compile-commands)
6003 command)
6004 (while command-list
6005 (if (eq vhdl-compiler (car (car command-list)))
6006 (setq command (car (cdr (cdr (car command-list))))))
6007 (setq command-list (cdr command-list)))
6008 (if command
6009 (compile command )
6010 (message (format "Not implemented for `%s'!" vhdl-compiler))
6011 (beep))))
6012
6013
6014;; ############################################################################
6015;; Bug reports
6016;; ############################################################################
6017;; (using `reporter.el')
6018
6019(defconst vhdl-version "3.19"
6020 "VHDL Mode version number.")
6021
6022(defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
6023 "Address for VHDL Mode bug reports.")
6024
6025(defun vhdl-version ()
6026 "Echo the current version of VHDL Mode in the minibuffer."
6027 (interactive)
6028 (message "Using VHDL Mode version %s" vhdl-version)
6029 (vhdl-keep-region-active))
6030
6031;; get reporter-submit-bug-report when byte-compiling
6032(and (fboundp 'eval-when-compile)
6033 (eval-when-compile
6034 (require 'reporter)))
6035
6036(defun vhdl-submit-bug-report ()
6037 "Submit via mail a bug report on VHDL Mode."
6038 (interactive)
6039 ;; load in reporter
6040 (and
6041 (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
6042 (require 'reporter)
6043 (reporter-submit-bug-report
6044 vhdl-mode-help-address
6045 (concat "VHDL Mode " vhdl-version)
6046 (list
6047 ;; report all important variables
6048 'vhdl-basic-offset
6049 'vhdl-offsets-alist
6050 'vhdl-comment-only-line-offset
6051 'tab-width
6052 'vhdl-electric-mode
6053 'vhdl-stutter-mode
6054 'vhdl-indent-tabs-mode
6055 'vhdl-compiler
6056 'vhdl-compiler-options
6057 'vhdl-upper-case-keywords
6058 'vhdl-upper-case-types
6059 'vhdl-upper-case-attributes
6060 'vhdl-upper-case-enum-values
6061 'vhdl-auto-align
6062 'vhdl-additional-empty-lines
6063 'vhdl-argument-list-indent
6064 'vhdl-conditions-in-parenthesis
6065 'vhdl-date-format
6066 'vhdl-header-file
6067 'vhdl-modify-date-prefix-string
6068 'vhdl-zero-string
6069 'vhdl-one-string
6070 'vhdl-self-insert-comments
6071 'vhdl-prompt-for-comments
6072 'vhdl-comment-column
6073 'vhdl-end-comment-column
6074 'vhdl-highlight-names
6075 'vhdl-highlight-keywords
6076 'vhdl-highlight-signals
6077 'vhdl-highlight-case-sensitive
6078 'vhdl-use-default-colors
6079 'vhdl-use-default-faces
6080 'vhdl-clock-signal-syntax
6081 'vhdl-reset-signal-syntax
6082 'vhdl-control-signal-syntax
6083 'vhdl-data-signal-syntax
6084 'vhdl-test-signal-syntax
6085 'vhdl-source-file-menu
6086 'vhdl-index-menu
6087 'vhdl-hideshow-menu
6088 'vhdl-print-two-column
6089 'vhdl-intelligent-tab
6090 'vhdl-template-key-binding-prefix
6091 'vhdl-word-completion-in-minibuffer
6092 'vhdl-underscore-is-part-of-word
6093 'vhdl-mode-hook
6094 )
6095 (function
6096 (lambda ()
6097 (insert
6098 (if vhdl-special-indent-hook
6099 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
6100 "vhdl-special-indent-hook is set to '"
6101 (format "%s" vhdl-special-indent-hook)
6102 ".\nPerhaps this is your problem?\n"
6103 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
6104 "\n")
6105 (format "vhdl-emacs-features: %s\n" vhdl-emacs-features)
6106 )))
6107 nil
6108 "Dear VHDL Mode maintainers,"
6109 )))
6110
6111
6112;; ############################################################################
6113
6114(provide 'vhdl-mode)
6115
6116;;; vhdl-mode.el ends here