Trailing whitepace deleted.
[emacs.git] / lisp / progmodes / vhdl-mode.el
blob9827ad3696e76156eff6de90353f51110feb9401
1 ;;; vhdl-mode.el --- major mode for editing VHDL code
3 ;; Copyright (C) 1992,93,94,95,96,97,98,99 Free Software Foundation, Inc.
5 ;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch>
6 ;; <http://www.iis.ee.ethz.ch/~zimmi/>
7 ;; Rodney J. Whitby <mailto:rwhitby@geocities.com>
8 ;; <http://www.geocities.com/SiliconValley/Park/8287/>
9 ;; Maintainer: VHDL Mode Maintainers <vhdl-mode@geocities.com>
10 ;; <http://www.geocities.com/SiliconValley/Peaks/8287/>
11 ;; Version: 3.29
12 ;; Keywords: languages vhdl
14 ;; This file is part of GNU Emacs.
16 ;; GNU Emacs is free software; you can redistribute it and/or modify
17 ;; it under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; any later version.
21 ;; GNU Emacs is distributed in the hope that it will be useful,
22 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 ;; GNU General Public License for more details.
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with GNU Emacs; see the file COPYING. If not, write to the
28 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
29 ;; Boston, MA 02111-1307, USA.
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;; Commentary:
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 ;; This package provides an Emacs major mode for editing VHDL code.
36 ;; It includes the following features:
38 ;; - Highlighting of VHDL syntax
39 ;; - Indentation based on versatile syntax analysis
40 ;; - Template insertion (electrification) for most VHDL constructs
41 ;; - Insertion of customizable VHDL file headers
42 ;; - Insertion of user-specified models
43 ;; - Word completion (dynamic abbreviations)
44 ;; - Comprehensive menu
45 ;; - File browser (using Speedbar or index/sources menu)
46 ;; - Design hierarchy browser (using Speedbar)
47 ;; - Source file compilation (syntax analysis)
48 ;; - Postscript printing with fontification
49 ;; - Lower and upper case keywords
50 ;; - Hiding code of design units
51 ;; - Code beautification
52 ;; - Port translation and test bench generation
53 ;; - VHDL'87/'93 and VHDL-AMS supported
54 ;; - Fully customizable
55 ;; - Works under GNU Emacs (Unix and Windows NT/95) and XEmacs
56 ;; (GNU Emacs is preferred due to higher robustness and functionality)
58 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
59 ;; Usage
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62 ;; see below (comment in `vhdl-mode' function) or type `C-c C-h' in Emacs.
64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65 ;; Emacs Versions
66 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
68 ;; supported: Emacs 20.X (Unix and Windows NT/95), XEmacs 20.X
69 ;; tested on: Emacs 20.3, XEmacs 20.4 (marginally)
71 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72 ;; Acknowledgements
73 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
75 ;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
76 ;; and Steve Grout.
78 ;; Fontification approach suggested by Ken Wood <ken@eda.com.au>.
79 ;; Ideas about alignment from John Wiegley <johnw@borland.com>.
81 ;; Many thanks to all the users who sent me bug reports and enhancement
82 ;; requests. Colin Marquardt, will you never stop asking for new features :-?
83 ;; Thanks to Dan Nicolaescu for reviewing the code and for his valuable hints.
84 ;; Thanks to Ulf Klaperski for the indentation speedup hint.
86 ;; Special thanks go to Wolfgang Fichtner and the crew from the Integrated
87 ;; Systems Laboratory, Swiss Federal Institute of Technology Zurich, for
88 ;; giving me the opportunity to develop this code.
89 ;; This work has been funded in part by MICROSWISS, a Microelectronics Program
90 ;; of the Swiss Government.
93 ;;; Code:
95 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 ;;; Variables
97 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
99 ;; help function
100 (defun vhdl-custom-set (variable value &rest functions)
101 "Set variables as in `custom-set-default' and call FUNCTIONS afterwards."
102 (if (fboundp 'custom-set-default)
103 (custom-set-default variable value)
104 (set-default variable value))
105 (while functions
106 (when (fboundp (car functions)) (funcall (car functions)))
107 (setq functions (cdr functions))))
109 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 ;; User variables
112 (defgroup vhdl nil
113 "Customizations for VHDL Mode."
114 :prefix "vhdl-"
115 :group 'languages
116 :version "20.4" ; comment out for XEmacs
119 (defgroup vhdl-mode nil
120 "Customizations for modes."
121 :group 'vhdl)
123 (defcustom vhdl-electric-mode t
124 "*Non-nil enables electrification (automatic template generation).
125 If nil, template generators can still be invoked through key bindings and
126 menu. Is indicated in the modeline by `/e' after the mode name and can be
127 toggled by `\\[vhdl-electric-mode]'."
128 :type 'boolean
129 :group 'vhdl-mode)
131 (defcustom vhdl-stutter-mode t
132 "*Non-nil enables stuttering.
133 Is indicated in the modeline by `/s' after the mode name and can be toggled
134 by `\\[vhdl-stutter-mode]'."
135 :type 'boolean
136 :group 'vhdl-mode)
138 (defcustom vhdl-indent-tabs-mode nil
139 "*Non-nil means indentation can insert tabs.
140 Overrides local variable `indent-tabs-mode'."
141 :type 'boolean
142 :group 'vhdl-mode)
145 (defgroup vhdl-project nil
146 "Customizations for projects."
147 :group 'vhdl)
149 (defcustom vhdl-project-alist
150 '(("example 1" "Project with individual source files"
151 ("~/example1/vhdl/system.vhd" "~/example1/vhdl/component_*.vhd") "\
152 -------------------------------------------------------------------------------
153 -- This is a multi-line project description
154 -- that can be used as a project dependent part of the file header.
156 ("example 2" "Project where source files are located in two directories"
157 ("$EXAMPLE2/vhdl/components/" "$EXAMPLE2/vhdl/system/") "")
158 ("example 3" "Project where source files are located in some directory trees"
159 ("-r ~/example3/*/vhdl/") ""))
160 "*List of projects and their properties.
161 Name : name of project
162 Title : title of project (one-line string)
163 Sources : a) source files : path + \"/\" + file name
164 b) directory : path + \"/\"
165 c) directory tree: \"-r \" + path + \"/\"
166 Description: description of project (multi-line string)
168 Project name and description are used to insert into the file header (see
169 variable `vhdl-file-header').
171 Path and file name can contain wildcards `*' and `?'. Environment variables
172 \(e.g. \"$EXAMPLE2\") are resolved.
174 The hierarchy browser shows the hierarchy of the design units found in
175 `Sources'. If no directories or files are specified, the current directory is
176 shown.
178 NOTE: Reflect the new setting in the choice list of variable `vhdl-project'
179 by restarting Emacs."
180 :type '(repeat (list :tag "Project" :indent 2
181 (string :tag "Name ")
182 (string :tag "Title")
183 (repeat :tag "Sources" :indent 4
184 (string :format "%v"))
185 (string :tag "Description: (type `C-j' for newline)"
186 :format "%t\n%v")))
187 :set (lambda (variable value)
188 (vhdl-custom-set variable value 'vhdl-update-mode-menu))
189 :group 'vhdl-project)
191 (defcustom vhdl-project ""
192 "*Specifies the default for the current project.
193 Select a project name from the ones defined in variable `vhdl-project-alist'.
194 Is used to determine the project title and description to be inserted in file
195 headers and the source files/directories to be scanned in the hierarchy
196 browser. The current project can also be changed temporarily in the menu."
197 :type (let ((project-alist vhdl-project-alist) choice-list)
198 (while project-alist
199 (setq choice-list (cons (list 'const (car (car project-alist)))
200 choice-list))
201 (setq project-alist (cdr project-alist)))
202 (append '(choice (const :tag "None" "") (const :tag "--"))
203 (nreverse choice-list)))
204 :group 'vhdl-project)
207 (defgroup vhdl-compile nil
208 "Customizations for compilation."
209 :group 'vhdl)
211 (defcustom vhdl-compiler-alist
213 ;; Cadence Design Systems: cv -file test.vhd
214 ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
215 ("Cadence" "cv -file" "" "" "./"
216 ("duluth: \\*E,[0-9]+ (\\(.+\\),\\([0-9]+\\)):" 1 2) ("" 0))
217 ;; Ikos Voyager: analyze test.vhd
218 ;; analyze sdrctl.vhd
219 ;; E L4/C5: this library unit is inaccessible
220 ("Ikos" "analyze" "" "" "./"
221 ("E L\\([0-9]+\\)/C[0-9]+:" 0 1)
222 ("^analyze +\\(.+ +\\)*\\(.+\\)$" 2))
223 ;; ModelSim, Model Technology: vcom test.vhd
224 ;; ERROR: test.vhd(14): Unknown identifier: positiv
225 ;; WARNING[2]: test.vhd(85): Possible infinite loop
226 ("ModelSim" "vcom" "" "vmake > Makefile" "./"
227 ("\\(ERROR\\|WARNING\\)[^:]*: \\(.+\\)(\\([0-9]+\\)):" 2 3) ("" 0))
228 ;; QuickHDL, Mentor Graphics: qvhcom test.vhd
229 ;; ERROR: test.vhd(24): near "dnd": expecting: END
230 ;; WARNING[4]: test.vhd(30): A space is required between ...
231 ("QuickHDL" "qvhcom" "" "qhmake >! Makefile" "./"
232 ("\\(ERROR\\|WARNING\\)[^:]*: \\(.+\\)(\\([0-9]+\\)):" 2 3) ("" 0))
233 ;; Synopsys, VHDL Analyzer: vhdlan test.vhd
234 ;; **Error: vhdlan,703 test.vhd(22): OTHERS is not legal in this context.
235 ("Synopsys" "vhdlan" "" "" "./"
236 ("\\*\\*Error: vhdlan,[0-9]+ \\(.+\\)(\\([0-9]+\\)):" 1 2) ("" 0))
237 ;; Vantage: analyze -libfile vsslib.ini -src test.vhd
238 ;; Compiling "pcu.vhd" line 1...
239 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
240 ("Vantage" "analyze -libfile vsslib.ini -src" "" "" "./"
241 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 0 1)
242 ("^ *Compiling \"\\(.+\\)\" " 1))
243 ;; Viewlogic: analyze -libfile vsslib.ini -src test.vhd
244 ;; Compiling "pcu.vhd" line 1...
245 ;; **Error: LINE 499 *** No aggregate value is valid in this context.
246 ("Viewlogic" "analyze -libfile vsslib.ini -src" "" "" "./"
247 ("\\*\\*Error: LINE \\([0-9]+\\) \\*\\*\\*" 0 1)
248 ("^ *Compiling \"\\(.+\\)\" " 1))
250 "*List of available VHDL compilers and their properties.
251 Each list entry specifies the following items for a compiler:
252 Compiler:
253 Compiler Name : name used in variable `vhdl-compiler' to choose compiler
254 Compile Command : command including options used for syntax analysis
255 Make Command : command including options used instead of `make' (default)
256 Generate Makefile: command to generate a Makefile (used by `make' command)
257 From Directory : directory where compilation is run (must end with '/')
258 Error Message:
259 Regexp : regular expression to match error messages
260 File Subexp Index: index of subexpression that matches the file name
261 Line Subexp Index: index of subexpression that matches the line number
262 File Message:
263 Regexp : regular expression to match a file name message
264 File Subexp Index: index of subexpression that matches the file name
266 See also variable `vhdl-compiler-options' to add options to the compile
267 command.
269 Some compilers do not include the file name in the error message, but print
270 out a file name message in advance. In this case, set \"File Subexp Index\"
271 to 0 and fill out the \"File Message\" entries.
273 A compiler is selected for syntax analysis (`\\[vhdl-compile]') by
274 assigning its name to variable `vhdl-compiler'.
276 NOTE: Reflect the new setting in the choice list of variable `vhdl-compiler'
277 by restarting Emacs."
278 :type '(repeat (list :tag "Compiler" :indent 2
279 (string :tag "Compiler Name ")
280 (string :tag "Compile Command ")
281 (string :tag "Make Command ")
282 (string :tag "Generate Makefile")
283 (string :tag "From Directory " "./")
284 (list :tag "Error Message" :indent 4
285 (regexp :tag "Regexp ")
286 (integer :tag "File Subexp Index")
287 (integer :tag "Line Subexp Index"))
288 (list :tag "File Message" :indent 4
289 (regexp :tag "Regexp ")
290 (integer :tag "File Subexp Index"))))
291 :set (lambda (variable value)
292 (vhdl-custom-set variable value 'vhdl-update-mode-menu))
293 :group 'vhdl-compile)
295 (defcustom vhdl-compiler "ModelSim"
296 "*Specifies the VHDL compiler to be used for syntax analysis.
297 Select a compiler name from the ones defined in variable `vhdl-compiler-alist'."
298 :type (let ((compiler-alist vhdl-compiler-alist) choice-list)
299 (while compiler-alist
300 (setq choice-list (cons (list 'const (car (car compiler-alist)))
301 choice-list))
302 (setq compiler-alist (cdr compiler-alist)))
303 (append '(choice) (nreverse choice-list)))
304 :group 'vhdl-compile)
306 (defcustom vhdl-compiler-options ""
307 "*Options to be added to the compile command."
308 :type 'string
309 :group 'vhdl-compile)
312 (defgroup vhdl-style nil
313 "Customizations for code styles."
314 :group 'vhdl)
316 (defcustom vhdl-standard '(87 nil)
317 "*VHDL standards used.
318 Basic standard:
319 VHDL'87 : IEEE Std 1076-1987
320 VHDL'93 : IEEE Std 1076-1993
321 Additional standards:
322 VHDL-AMS : IEEE Std 1076.1 (analog-mixed-signal)
323 Math Packages: IEEE Std 1076.2 (`math_real', `math_complex')
325 NOTE: Activate the new setting in a VHDL buffer using the menu entry
326 \"Activate New Customizations\"."
327 :type '(list (choice :tag "Basic standard"
328 (const :tag "VHDL'87" 87)
329 (const :tag "VHDL'93" 93))
330 (set :tag "Additional standards" :indent 2
331 (const :tag "VHDL-AMS" ams)
332 (const :tag "Math Packages" math)))
333 :set (lambda (variable value)
334 (vhdl-custom-set variable value
335 'vhdl-template-map-init
336 'vhdl-mode-abbrev-table-init
337 'vhdl-template-construct-alist-init
338 'vhdl-template-package-alist-init
339 'vhdl-update-mode-menu
340 'vhdl-words-init 'vhdl-font-lock-init))
341 :group 'vhdl-style)
343 (defcustom vhdl-basic-offset 2
344 "*Amount of basic offset used for indentation.
345 This value is used by + and - symbols in `vhdl-offsets-alist'."
346 :type 'integer
347 :group 'vhdl-style)
349 (defcustom vhdl-upper-case-keywords nil
350 "*Non-nil means convert keywords to upper case.
351 This is done when typed or expanded or by the fix case functions."
352 :type 'boolean
353 :set (lambda (variable value)
354 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
355 :group 'vhdl-style)
357 (defcustom vhdl-upper-case-types nil
358 "*Non-nil means convert standardized types to upper case.
359 This is done when expanded or by the fix case functions."
360 :type 'boolean
361 :set (lambda (variable value)
362 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
363 :group 'vhdl-style)
365 (defcustom vhdl-upper-case-attributes nil
366 "*Non-nil means convert standardized attributes to upper case.
367 This is done when expanded or by the fix case functions."
368 :type 'boolean
369 :set (lambda (variable value)
370 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
371 :group 'vhdl-style)
373 (defcustom vhdl-upper-case-enum-values nil
374 "*Non-nil means convert standardized enumeration values to upper case.
375 This is done when expanded or by the fix case functions."
376 :type 'boolean
377 :set (lambda (variable value)
378 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
379 :group 'vhdl-style)
381 (defcustom vhdl-upper-case-constants t
382 "*Non-nil means convert standardized constants to upper case.
383 This is done when expanded."
384 :type 'boolean
385 :set (lambda (variable value)
386 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
387 :group 'vhdl-style)
390 (defgroup vhdl-electric nil
391 "Customizations for electrification."
392 :group 'vhdl)
394 (defcustom vhdl-electric-keywords '(vhdl user)
395 "*Type of keywords for which electrification is enabled.
396 VHDL keywords: invoke built-in templates
397 User keywords: invoke user models (see variable `vhdl-model-alist')"
398 :type '(set (const :tag "VHDL keywords" vhdl)
399 (const :tag "User keywords" user))
400 :set (lambda (variable value)
401 (vhdl-custom-set variable value 'vhdl-mode-abbrev-table-init))
402 :group 'vhdl-electric)
404 (defcustom vhdl-optional-labels 'process
405 "*Constructs for which labels are to be queried.
406 Template generators prompt for optional labels for:
407 None : no constructs
408 Processes only: processes only (also procedurals in VHDL-AMS)
409 All constructs: all constructs with optional labels and keyword END"
410 :type '(choice (const :tag "None" none)
411 (const :tag "Processes only" process)
412 (const :tag "All constructs" all))
413 :group 'vhdl-electric)
415 (defcustom vhdl-insert-empty-lines 'unit
416 "*Specifies whether to insert empty lines in some templates.
417 This improves readability of code. Empty lines are inserted in:
418 None : no constructs
419 Design units only: entities, architectures, configurations, packages only
420 All constructs : also all constructs with BEGIN...END parts
422 Replaces variable `vhdl-additional-empty-lines'."
423 :type '(choice (const :tag "None" none)
424 (const :tag "Design units only" unit)
425 (const :tag "All constructs" all))
426 :group 'vhdl-electric)
428 (defcustom vhdl-argument-list-indent nil
429 "*Non-nil means indent argument lists relative to opening parenthesis.
430 That is, argument, association, and port lists start on the same line as the
431 opening parenthesis and subsequent lines are indented accordingly.
432 Otherwise, lists start on a new line and are indented as normal code."
433 :type 'boolean
434 :group 'vhdl-electric)
436 (defcustom vhdl-association-list-with-formals t
437 "*Non-nil means write association lists with formal parameters.
438 In templates, you are prompted for formal and actual parameters.
439 If nil, only a list of actual parameters is entered."
440 :type 'boolean
441 :group 'vhdl-electric)
443 (defcustom vhdl-conditions-in-parenthesis nil
444 "*Non-nil means place parenthesis around condition expressions."
445 :type 'boolean
446 :group 'vhdl-electric)
448 (defcustom vhdl-zero-string "'0'"
449 "*String to use for a logic zero."
450 :type 'string
451 :group 'vhdl-electric)
453 (defcustom vhdl-one-string "'1'"
454 "*String to use for a logic one."
455 :type 'string
456 :group 'vhdl-electric)
459 (defgroup vhdl-header nil
460 "Customizations for file header."
461 :group 'vhdl-electric)
463 (defcustom vhdl-file-header "\
464 -------------------------------------------------------------------------------
465 -- Title : <title string>
466 -- Project : <project>
467 -------------------------------------------------------------------------------
468 -- File : <filename>
469 -- Author : <author>
470 -- Company : <company>
471 -- Last update: <date>
472 -- Platform : <platform>
473 <projectdesc>-------------------------------------------------------------------------------
474 -- Description: <cursor>
475 -------------------------------------------------------------------------------
476 -- Revisions :
477 -- Date Version Author Description
478 -- <date> 1.0 <login>\tCreated
479 -------------------------------------------------------------------------------
482 "*String or file to insert as file header.
483 If the string specifies an existing file name, the contents of the file is
484 inserted, otherwise the string itself is inserted as file header.
485 Type `C-j' for newlines.
486 If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
487 if the header needs to be version controlled.
489 The following keywords for template generation are supported:
490 <filename> : replaced by the name of the buffer
491 <author> : replaced by the user name and email address (customize
492 `mail-host-address' or `user-mail-address' if required)
493 <login> : replaced by user login name
494 <company> : replaced by contents of variable `vhdl-company-name'
495 <date> : replaced by the current date
496 <project> : replaced by title of current project (`vhdl-project')
497 <projectdesc>: replaced by description of current project (`vhdl-project')
498 <platform> : replaced by contents of variable `vhdl-platform-spec'
499 <... string> : replaced by a queried string (... is the prompt word)
500 <cursor> : final cursor position
502 The (multi-line) project description <projectdesc> can be used as a project
503 dependent part of the file header and can also contain the above keywords."
504 :type 'string
505 :group 'vhdl-header)
507 (defcustom vhdl-file-footer ""
508 "*String or file to insert as file footer.
509 If the string specifies an existing file name, the contents of the file is
510 inserted, otherwise the string itself is inserted as file footer (i.e. at
511 the end of the file).
512 Type `C-j' for newlines."
513 :type 'string
514 :group 'vhdl-header)
516 (defcustom vhdl-company-name ""
517 "*Name of company to insert in file header."
518 :type 'string
519 :group 'vhdl-header)
521 (defcustom vhdl-platform-spec ""
522 "*Specification of VHDL platform to insert in file header.
523 The platform specification should contain names and versions of the
524 simulation and synthesis tools used."
525 :type 'string
526 :group 'vhdl-header)
528 (defcustom vhdl-date-format "%Y/%m/%d"
529 "*Specifies the date format to use in the header.
530 This string is passed as argument to the command `format-time-string'.
531 For more information on format strings, see the documentation for the
532 `format-time-string' command (C-h f `format-time-string')."
533 :type 'string
534 :group 'vhdl-header)
536 (defcustom vhdl-modify-date-prefix-string "-- Last update: "
537 "*Prefix string of modification date in VHDL file header.
538 If actualization of the modification date is called (menu,
539 `\\[vhdl-template-modify]'), this string is searched and the rest
540 of the line replaced by the current date."
541 :type 'string
542 :group 'vhdl-header)
544 (defcustom vhdl-modify-date-on-saving t
545 "*Non-nil means update the modification date when the buffer is saved.
546 Calls function `\\[vhdl-template-modify]').
548 NOTE: Activate the new setting in a VHDL buffer using the menu entry
549 \"Activate New Customizations\""
550 :type 'boolean
551 :group 'vhdl-header)
554 (defgroup vhdl-sequential-process nil
555 "Customizations for sequential processes."
556 :group 'vhdl-electric)
558 (defcustom vhdl-reset-kind 'async
559 "*Specifies which kind of reset to use in sequential processes."
560 :type '(choice (const :tag "None" none)
561 (const :tag "Synchronous" sync)
562 (const :tag "Asynchronous" async))
563 :group 'vhdl-sequential-process)
565 (defcustom vhdl-reset-active-high nil
566 "*Non-nil means reset in sequential processes is active high.
567 nil means active low."
568 :type 'boolean
569 :group 'vhdl-sequential-process)
571 (defcustom vhdl-clock-rising-edge t
572 "*Non-nil means rising edge of clock triggers sequential processes.
573 nil means falling edge."
574 :type 'boolean
575 :group 'vhdl-sequential-process)
577 (defcustom vhdl-clock-edge-condition 'standard
578 "*Syntax of the clock edge condition.
579 Standard: \"clk'event and clk = '1'\"
580 Function: \"rising_edge(clk)\""
581 :type '(choice (const :tag "Standard" standard)
582 (const :tag "Function" function))
583 :group 'vhdl-sequential-process)
585 (defcustom vhdl-clock-name ""
586 "*Name of clock signal to use in templates."
587 :type 'string
588 :group 'vhdl-sequential-process)
590 (defcustom vhdl-reset-name ""
591 "*Name of reset signal to use in templates."
592 :type 'string
593 :group 'vhdl-sequential-process)
596 (defgroup vhdl-model nil
597 "Customizations for user models."
598 :group 'vhdl)
600 (defcustom vhdl-model-alist
601 '(("example model"
602 "<label> : process (<clock>, <reset>)
603 begin -- process <label>
604 if <reset> = '0' then -- asynchronous reset (active low)
605 <cursor>
606 elsif <clock>'event and <clock> = '1' then -- rising clock edge
607 if <enable> = '1' then -- synchronous load
609 end if;
610 end if;
611 end process <label>;"
612 "e" ""))
613 "*List of user models.
614 VHDL models (templates) can be specified by the user in this list. They can be
615 invoked from the menu, through key bindings (`C-c C-m ...'), or by keyword
616 electrification (i.e. overriding existing or creating new keywords, see
617 variable `vhdl-electric-keywords').
618 Name : name of model (string of words and spaces)
619 String : string or name of file to be inserted as model (newline: `C-j')
620 Key Binding: key binding to invoke model, added to prefix `C-c C-m'
621 (must be in double-quotes, examples: \"i\", \"\\C-p\", \"\\M-s\")
622 Keyword : keyword to invoke model
624 The models can contain prompts to be queried. A prompt is of the form \"<...>\".
625 A prompt that appears several times is queried once and replaced throughout
626 the model. Special prompts are:
627 <clock> : name specified in `vhdl-clock-name' (if not empty)
628 <reset> : name specified in `vhdl-reset-name' (if not empty)
629 <cursor>: final cursor position
631 If the string specifies an existing file name, the contents of the file is
632 inserted, otherwise the string itself is inserted.
633 The code within the models should be correctly indented.
634 Type `C-j' for newlines.
636 NOTE: Activate the new setting in a VHDL buffer using the menu entry
637 \"Activate New Customizations\""
638 :type '(repeat (list :tag "Model" :indent 2
639 (string :tag "Name ")
640 (string :tag "String : (type `C-j' for newline)"
641 :format "%t\n%v")
642 (sexp :tag "Key Binding" x)
643 (string :tag "Keyword ")))
644 :set (lambda (variable value)
645 (vhdl-custom-set variable value
646 'vhdl-model-map-init
647 'vhdl-model-defun
648 'vhdl-mode-abbrev-table-init
649 'vhdl-update-mode-menu))
650 :group 'vhdl-model)
652 (defgroup vhdl-port nil
653 "Customizations for port transformation functions."
654 :group 'vhdl)
656 (defcustom vhdl-include-port-comments nil
657 "*Non-nil means include port comments when a port is pasted."
658 :type 'boolean
659 :group 'vhdl-port)
661 (defcustom vhdl-include-direction-comments nil
662 "*Non-nil means include signal direction in instantiations as comments."
663 :type 'boolean
664 :group 'vhdl-port)
666 (defconst vhdl-name-doc-string "
668 FROM REGEXP is a regular expression matching the formal port name:
669 `.*' matches the entire name
670 `\\(...\\)' matches a substring
671 TO STRING specifies the string to be inserted as actual port name:
672 `\\&' means substitute original matched text
673 `\\N' means substitute what matched the Nth `\\(...\\)'
674 Examples:
675 `.*' `\\&' leaves name as it is
676 `.*' `\\&_i' attaches `_i' to original name
677 `\\(.*\\)_[io]$' `\\1' strips off `_i' or `_o' from original name
678 `.*' `' leaves name empty")
680 (defcustom vhdl-actual-port-name '(".*" . "\\&_i")
681 (concat
682 "*Specifies how actual port names are obtained from formal port names.
683 In a component instantiation, an actual port name can be obtained by
684 modifying the formal port name (e.g. attaching or stripping off a substring)."
685 vhdl-name-doc-string)
686 :type '(cons (regexp :tag "From Regexp")
687 (string :tag "To String "))
688 :group 'vhdl-port)
690 (defcustom vhdl-instance-name '(".*" . "")
691 (concat
692 "*Specifies how an instance name is obtained.
693 The instance name can be obtained by modifying the name of the component to be
694 instantiated (e.g. attaching or stripping off a substring).
695 If TO STRING is empty, the instance name is queried."
696 vhdl-name-doc-string)
697 :type '(cons (regexp :tag "From Regexp")
698 (string :tag "To String "))
699 :group 'vhdl-port)
701 (defcustom vhdl-testbench-entity-name '(".*" . "\\&_tb")
702 (concat
703 "*Specifies how the test bench entity name is obtained.
704 The entity name of a test bench can be obtained by modifying the name of
705 the component to be tested (e.g. attaching or stripping off a substring)."
706 vhdl-name-doc-string)
707 :type '(cons (regexp :tag "From Regexp")
708 (string :tag "To String "))
709 :group 'vhdl-port)
711 (defcustom vhdl-testbench-architecture-name '(".*" . "")
712 (concat
713 "*Specifies how the test bench architecture name is obtained.
714 The test bench architecture name can be obtained by modifying the name of
715 the component to be tested (e.g. attaching or stripping off a substring).
716 If TO STRING is empty, the architecture name is queried."
717 vhdl-name-doc-string)
718 :type '(cons (regexp :tag "From Regexp")
719 (string :tag "To String "))
720 :group 'vhdl-port)
722 (defcustom vhdl-testbench-dut-name '(".*" . "DUT")
723 (concat
724 "*Specifies how a DUT instance name is obtained.
725 The design-under-test instance name (i.e. the component instantiated in the
726 test bench) can be obtained by modifying the component name (e.g. attaching
727 or stripping off a substring)."
728 vhdl-name-doc-string)
729 :type '(cons (regexp :tag "From Regexp")
730 (string :tag "To String "))
731 :group 'vhdl-port)
733 (defcustom vhdl-testbench-entity-header ""
734 "*String or file to be inserted as test bench entity header.
735 If the string specifies an existing file name, the contents of the file is
736 inserted, otherwise the string itself is inserted at the beginning of the test
737 bench entity template.
738 Type `C-j' for newlines."
739 :type 'string
740 :group 'vhdl-port)
742 (defcustom vhdl-testbench-architecture-header ""
743 "*String or file to be inserted as test bench architecture header.
744 If the string specifies an existing file name, the contents of the file is
745 inserted, otherwise the string itself is inserted at the beginning of the test
746 bench architecture template, if a separate file is created for the
747 architecture.
748 Type `C-j' for newlines."
749 :type 'string
750 :group 'vhdl-port)
752 (defcustom vhdl-testbench-declarations ""
753 "*String or file to be inserted in the test bench declarative part.
754 If the string specifies an existing file name, the contents of the file is
755 inserted, otherwise the string itself is inserted in the test bench
756 architecture before the BEGIN keyword.
757 Type `C-j' for newlines."
758 :type 'string
759 :group 'vhdl-port)
761 (defcustom vhdl-testbench-statements ""
762 "*String or file to be inserted in the test bench statement part.
763 If the string specifies an existing file name, the contents of the file is
764 inserted, otherwise the string itself is inserted in the test bench
765 architecture before the END keyword.
766 Type `C-j' for newlines."
767 :type 'string
768 :group 'vhdl-port)
770 (defcustom vhdl-testbench-initialize-signals nil
771 "*Non-nil means initialize signals with `0' when declared in test bench."
772 :type 'boolean
773 :group 'vhdl-port)
775 (defcustom vhdl-testbench-create-files 'single
776 "*Specifies whether new files should be created for the test bench.
777 Test bench entity and architecture are inserted:
778 None : in current buffer
779 Single file : in new single file
780 Separate files: in two separate files
781 Note that the files have the same name as the contained design unit."
782 :type '(choice (const :tag "None" none)
783 (const :tag "Single file" single)
784 (const :tag "Separate files" separate))
785 :group 'vhdl-port)
788 (defgroup vhdl-comment nil
789 "Customizations for comments."
790 :group 'vhdl)
792 (defcustom vhdl-self-insert-comments t
793 "*Non-nil means various templates automatically insert help comments."
794 :type 'boolean
795 :group 'vhdl-comment)
797 (defcustom vhdl-prompt-for-comments t
798 "*Non-nil means various templates prompt for user definable comments."
799 :type 'boolean
800 :group 'vhdl-comment)
802 (defcustom vhdl-inline-comment-column 40
803 "*Column to indent inline comments to.
804 Overrides local variable `comment-column'.
806 NOTE: Activate the new setting in a VHDL buffer using the menu entry
807 \"Activate New Customizations\""
808 :type 'integer
809 :group 'vhdl-comment)
811 (defcustom vhdl-end-comment-column 79
812 "*End of comment column.
813 Comments that exceed this column number are wrapped.
815 NOTE: Activate the new setting in a VHDL buffer using the menu entry
816 \"Activate New Customizations\""
817 :type 'integer
818 :group 'vhdl-comment)
820 (defvar end-comment-column)
823 (defgroup vhdl-align nil
824 "Customizations for alignment."
825 :group 'vhdl)
827 (defcustom vhdl-auto-align t
828 "*Non-nil means align some templates automatically after generation."
829 :type 'boolean
830 :group 'vhdl-align)
832 (defcustom vhdl-align-groups t
833 "*Non-nil means align groups of code lines separately.
834 A group of code lines is a region of lines with no empty lines inbetween."
835 :type 'boolean
836 :group 'vhdl-align)
839 (defgroup vhdl-highlight nil
840 "Customizations for highlighting."
841 :group 'vhdl)
843 (defcustom vhdl-highlight-keywords t
844 "*Non-nil means highlight VHDL keywords and other standardized words.
845 The following faces are used:
846 `font-lock-keyword-face' : keywords
847 `font-lock-type-face' : standardized types
848 `vhdl-font-lock-attribute-face' : standardized attributes
849 `vhdl-font-lock-enumvalue-face' : standardized enumeration values
850 `vhdl-font-lock-function-face' : standardized function and package names
852 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
853 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
854 :type 'boolean
855 :set (lambda (variable value)
856 (vhdl-custom-set variable value 'vhdl-font-lock-init))
857 :group 'vhdl-highlight)
859 (defcustom vhdl-highlight-names t
860 "*Non-nil means highlight declaration names and construct labels.
861 The following faces are used:
862 `font-lock-function-name-face' : names in declarations of units,
863 subprograms, components, as well as labels of VHDL constructs
864 `font-lock-type-face' : names in type/nature declarations
865 `vhdl-font-lock-attribute-face' : names in attribute declarations
866 `font-lock-variable-name-face' : names in declarations of signals,
867 variables, constants, subprogram parameters, generics, and ports
869 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
870 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
871 :type 'boolean
872 :set (lambda (variable value)
873 (vhdl-custom-set variable value 'vhdl-font-lock-init))
874 :group 'vhdl-highlight)
876 (defcustom vhdl-highlight-special-words nil
877 "*Non-nil means highlight words with special syntax.
878 The words with syntax and color specified in variable
879 `vhdl-special-syntax-alist' are highlighted accordingly.
880 Can be used for visual support of naming conventions.
882 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
883 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
884 :type 'boolean
885 :set (lambda (variable value)
886 (vhdl-custom-set variable value 'vhdl-font-lock-init))
887 :group 'vhdl-highlight)
889 (defcustom vhdl-highlight-forbidden-words nil
890 "*Non-nil means highlight forbidden words.
891 The reserved words specified in variable `vhdl-forbidden-words' or having the
892 syntax specified in variable `vhdl-forbidden-syntax' are highlighted in a
893 warning color (face `vhdl-font-lock-reserved-words-face') to indicate not to
894 use them.
896 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
897 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
898 :type 'boolean
899 :set (lambda (variable value)
900 (vhdl-custom-set variable value
901 'vhdl-words-init 'vhdl-font-lock-init))
902 :group 'vhdl-highlight)
904 (defcustom vhdl-highlight-verilog-keywords nil
905 "*Non-nil means highlight Verilog keywords as reserved words.
906 Verilog keywords are highlighted in a warning color (face
907 `vhdl-font-lock-reserved-words-face') to indicate not to use them.
909 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
910 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
911 :type 'boolean
912 :set (lambda (variable value)
913 (vhdl-custom-set variable value
914 'vhdl-words-init 'vhdl-font-lock-init))
915 :group 'vhdl-highlight)
917 (defcustom vhdl-highlight-translate-off nil
918 "*Non-nil means background-highlight code excluded from translation.
919 That is, all code between \"-- pragma translate_off\" and
920 \"-- pragma translate_on\" is highlighted using a different background color
921 \(face `vhdl-font-lock-translate-off-face').
922 Note: this might slow down on-the-fly fontification (and thus editing).
924 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
925 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
926 :type 'boolean
927 :set (lambda (variable value)
928 (vhdl-custom-set variable value 'vhdl-font-lock-init))
929 :group 'vhdl-highlight)
931 (defcustom vhdl-highlight-case-sensitive nil
932 "*Non-nil means consider case for highlighting.
933 Possible trade-off:
934 non-nil also upper-case VHDL words are highlighted, but case of words with
935 special syntax is not considered
936 nil only lower-case VHDL words are highlighted, but case of words with
937 special syntax is considered
938 Overrides local variable `font-lock-keywords-case-fold-search'.
940 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
941 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
942 :type 'boolean
943 :group 'vhdl-highlight)
945 (defcustom vhdl-special-syntax-alist nil
946 "*List of special syntax to be highlighted.
947 If variable `vhdl-highlight-special-words' is non-nil, words with the specified
948 syntax (as regular expression) are highlighted in the corresponding color.
950 Name : string of words and spaces
951 Regexp : regular expression describing word syntax
952 (e.g. \"\\\w+_c\" matches word with suffix \"_c\")
953 Color (light): foreground color for light background
954 (matching color examples: Gold3, Grey50, LimeGreen, Tomato,
955 LightSeaGreen, DodgerBlue, Gold, PaleVioletRed)
956 Color (dark) : foreground color for dark background
957 (matching color examples: BurlyWood1, Grey80, Green, Coral,
958 AquaMarine2, LightSkyBlue1, Yellow, PaleVioletRed1)
960 Can be used for visual support of naming conventions, such as highlighting
961 different kinds of signals (e.g. \"Clk_c\", \"Rst_r\") or objects (e.g.
962 \"Signal_s\", \"Variable_v\", \"Constant_c\") by distinguishing them using
963 name suffices.
964 For each entry, a new face is generated with the specified colors and name
965 \"vhdl-font-lock-\" + name + \"-face\".
967 NOTE: Activate a changed regexp in a VHDL buffer by re-fontifying it (menu
968 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking.
969 All other changes require restarting Emacs."
970 :type '(repeat (list :tag "Face" :indent 2
971 (string :tag "Name ")
972 (regexp :tag "Regexp " "\\w+_")
973 (string :tag "Color (light)")
974 (string :tag "Color (dark) ")))
975 :set (lambda (variable value)
976 (vhdl-custom-set variable value 'vhdl-font-lock-init))
977 :group 'vhdl-highlight)
979 (defcustom vhdl-forbidden-words '()
980 "*List of forbidden words to be highlighted.
981 If variable `vhdl-highlight-forbidden-words' is non-nil, these reserved
982 words are highlighted in a warning color to indicate not to use them.
984 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
985 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
986 :type '(repeat (string :format "%v"))
987 :set (lambda (variable value)
988 (vhdl-custom-set variable value
989 'vhdl-words-init 'vhdl-font-lock-init))
990 :group 'vhdl-highlight)
992 (defcustom vhdl-forbidden-syntax ""
993 "*Syntax of forbidden words to be highlighted.
994 If variable `vhdl-highlight-forbidden-words' is non-nil, words with this
995 syntax are highlighted in a warning color to indicate not to use them.
996 Can be used to highlight too long identifiers (e.g. \"\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w+\"
997 highlights identifiers with 10 or more characters).
999 NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
1000 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
1001 :type 'regexp
1002 :set (lambda (variable value)
1003 (vhdl-custom-set variable value
1004 'vhdl-words-init 'vhdl-font-lock-init))
1005 :group 'vhdl-highlight)
1008 (defgroup vhdl-menu nil
1009 "Customizations for speedbar and menues."
1010 :group 'vhdl)
1012 (defcustom vhdl-speedbar nil
1013 "*Non-nil means open the speedbar automatically at startup.
1014 Alternatively, the speedbar can be opened from the VHDL menu."
1015 :type 'boolean
1016 :group 'vhdl-menu)
1018 (defcustom vhdl-speedbar-show-hierarchy nil
1019 "*Non-nil means open the speedbar as hierarchy browser at startup.
1020 Otherwise, the speedbar is opened as normal file browser."
1021 :type 'boolean
1022 :group 'vhdl-menu)
1024 (defcustom vhdl-speedbar-hierarchy-indent 1
1025 "*Amount of indentation in hierarchy display of subcomponent."
1026 :type 'integer
1027 :group 'vhdl-menu)
1029 (defcustom vhdl-index-menu nil
1030 "*Non-nil means add an index menu for a source file when loading.
1031 Alternatively, the speedbar can be used. Note that the index menu scans a file
1032 when it is opened, while speedbar only scans the file upon request.
1033 Does not work under XEmacs."
1034 :type 'boolean
1035 :group 'vhdl-menu)
1037 (defcustom vhdl-source-file-menu nil
1038 "*Non-nil means add a menu of all source files in current directory.
1039 Alternatively, the speedbar can be used."
1040 :type 'boolean
1041 :group 'vhdl-menu)
1043 (defcustom vhdl-hideshow-menu nil
1044 "*Non-nil means add hideshow menu and functionality.
1045 Hideshow allows hiding code of VHDL design units.
1046 Does not work under XEmacs.
1048 NOTE: Activate the new setting in a VHDL buffer using the menu entry
1049 \"Activate New Customizations\""
1050 :type 'boolean
1051 :group 'vhdl-menu)
1053 (defcustom vhdl-hide-all-init nil
1054 "*Non-nil means hide all design units initially after a file is loaded."
1055 :type 'boolean
1056 :group 'vhdl-menu)
1059 (defgroup vhdl-print nil
1060 "Customizations for printing."
1061 :group 'vhdl)
1063 (defcustom vhdl-print-two-column t
1064 "*Non-nil means print code in two columns and landscape format.
1066 NOTE: Activate the new setting by restarting Emacs.
1067 Overrides `ps-print' settings locally."
1068 :type 'boolean
1069 :group 'vhdl-print)
1071 (defcustom vhdl-print-customize-faces t
1072 "*Non-nil means use an optimized set of faces for postscript printing.
1074 NOTE: Activate the new setting by restarting Emacs.
1075 Overrides `ps-print' settings locally."
1076 :type 'boolean
1077 :group 'vhdl-print)
1080 (defgroup vhdl-misc nil
1081 "Miscellaneous customizations."
1082 :group 'vhdl)
1084 (defcustom vhdl-intelligent-tab t
1085 "*Non-nil means `TAB' does indentation, word completion and tab insertion.
1086 That is, if preceeding character is part of a word then complete word,
1087 else if not at beginning of line then insert tab,
1088 else if last command was a `TAB' or `RET' then dedent one step,
1089 else indent current line (i.e. `TAB' is bound to `vhdl-electric-tab').
1090 If nil, TAB always indents current line (i.e. `TAB' is bound to
1091 `vhdl-indent-line').
1093 NOTE: Activate the new setting in a VHDL buffer using the menu entry
1094 \"Activate New Customizations\""
1095 :type 'boolean
1096 :group 'vhdl-misc)
1098 (defcustom vhdl-word-completion-case-sensitive nil
1099 "*Non-nil means word completion using `TAB' is case sensitive.
1100 That is, `TAB' completes words that start with the same letters and case.
1101 Otherwise, case is ignored."
1102 :type 'boolean
1103 :group 'vhdl-misc)
1105 (defcustom vhdl-word-completion-in-minibuffer t
1106 "*Non-nil enables word completion in minibuffer (for template prompts).
1108 NOTE: Activate the new setting by restarting Emacs."
1109 :type 'boolean
1110 :group 'vhdl-misc)
1112 (defcustom vhdl-underscore-is-part-of-word nil
1113 "*Non-nil means consider the underscore character `_' as part of word.
1114 An identifier containing underscores is then treated as a single word in
1115 select and move operations. All parts of an identifier separated by underscore
1116 are treated as single words otherwise.
1118 NOTE: Activate the new setting in a VHDL buffer using the menu entry
1119 \"Activate New Customizations\""
1120 :type 'boolean
1121 :set (lambda (variable value)
1122 (vhdl-custom-set variable value 'vhdl-mode-syntax-table-init))
1123 :group 'vhdl-misc)
1125 ;; add related general customizations
1126 (defgroup vhdl-related
1127 (if (string-match "XEmacs" emacs-version)
1128 '((ps-print custom-group)
1129 (mail-host-address custom-variable)
1130 (user-mail-address custom-variable)
1131 (line-number-mode custom-variable)
1132 (paren-mode custom-variable))
1133 '((ps-print custom-group)
1134 (mail-host-address custom-variable)
1135 (user-mail-address custom-variable)
1136 (line-number-mode custom-variable)
1137 (paren-showing custom-group)
1138 (transient-mark-mode custom-variable)))
1139 "Related general customizations."
1140 :group 'vhdl)
1142 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1143 ;; Internal variables
1145 (defconst vhdl-version "3.29"
1146 "VHDL Mode version number.")
1148 (defvar vhdl-progress-interval 1
1149 "*Interval used to update progress status during long operations.
1150 If a number, percentage complete gets updated after each interval of
1151 that many seconds. To inhibit all messages, set this variable to nil.")
1153 (defvar vhdl-inhibit-startup-warnings-p nil
1154 "*If non-nil, inhibits start up compatibility warnings.")
1156 (defvar vhdl-strict-syntax-p nil
1157 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
1158 If the syntactic symbol for a particular line does not match a symbol
1159 in the offsets alist, an error is generated, otherwise no error is
1160 reported and the syntactic symbol is ignored.")
1162 (defvar vhdl-echo-syntactic-information-p nil
1163 "*If non-nil, syntactic info is echoed when the line is indented.")
1165 (defconst vhdl-offsets-alist-default
1166 '((string . -1000)
1167 (block-open . 0)
1168 (block-close . 0)
1169 (statement . 0)
1170 (statement-cont . vhdl-lineup-statement-cont)
1171 (statement-block-intro . +)
1172 (statement-case-intro . +)
1173 (case-alternative . +)
1174 (comment . vhdl-lineup-comment)
1175 (arglist-intro . +)
1176 (arglist-cont . 0)
1177 (arglist-cont-nonempty . vhdl-lineup-arglist)
1178 (arglist-close . vhdl-lineup-arglist)
1179 (entity . 0)
1180 (configuration . 0)
1181 (package . 0)
1182 (architecture . 0)
1183 (package-body . 0)
1185 "Default settings for offsets of syntactic elements.
1186 Do not change this constant! See the variable `vhdl-offsets-alist' for
1187 more information.")
1189 (defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
1190 "*Association list of syntactic element symbols and indentation offsets.
1191 As described below, each cons cell in this list has the form:
1193 (SYNTACTIC-SYMBOL . OFFSET)
1195 When a line is indented, `vhdl-mode' first determines the syntactic
1196 context of the line by generating a list of symbols called syntactic
1197 elements. This list can contain more than one syntactic element and
1198 the global variable `vhdl-syntactic-context' contains the context list
1199 for the line being indented. Each element in this list is actually a
1200 cons cell of the syntactic symbol and a buffer position. This buffer
1201 position is call the relative indent point for the line. Some
1202 syntactic symbols may not have a relative indent point associated with
1203 them.
1205 After the syntactic context list for a line is generated, `vhdl-mode'
1206 calculates the absolute indentation for the line by looking at each
1207 syntactic element in the list. First, it compares the syntactic
1208 element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
1209 finds a match, it adds the OFFSET to the column of the relative indent
1210 point. The sum of this calculation for each element in the syntactic
1211 list is the absolute offset for line being indented.
1213 If the syntactic element does not match any in the `vhdl-offsets-alist',
1214 an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
1215 the element is ignored.
1217 Actually, OFFSET can be an integer, a function, a variable, or one of
1218 the following symbols: `+', `-', `++', or `--'. These latter
1219 designate positive or negative multiples of `vhdl-basic-offset',
1220 respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
1221 called with a single argument containing the cons of the syntactic
1222 element symbol and the relative indent point. The function should
1223 return an integer offset.
1225 Here is the current list of valid syntactic element symbols:
1227 string -- inside multi-line string
1228 block-open -- statement block open
1229 block-close -- statement block close
1230 statement -- a VHDL statement
1231 statement-cont -- a continuation of a VHDL statement
1232 statement-block-intro -- the first line in a new statement block
1233 statement-case-intro -- the first line in a case alternative block
1234 case-alternative -- a case statement alternative clause
1235 comment -- a line containing only a comment
1236 arglist-intro -- the first line in an argument list
1237 arglist-cont -- subsequent argument list lines when no
1238 arguments follow on the same line as the
1239 the arglist opening paren
1240 arglist-cont-nonempty -- subsequent argument list lines when at
1241 least one argument follows on the same
1242 line as the arglist opening paren
1243 arglist-close -- the solo close paren of an argument list
1244 entity -- inside an entity declaration
1245 configuration -- inside a configuration declaration
1246 package -- inside a package declaration
1247 architecture -- inside an architecture body
1248 package-body -- inside a package body")
1250 (defvar vhdl-comment-only-line-offset 0
1251 "*Extra offset for line which contains only the start of a comment.
1252 Can contain an integer or a cons cell of the form:
1254 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
1256 Where NON-ANCHORED-OFFSET is the amount of offset given to
1257 non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
1258 the amount of offset to give column-zero anchored comment-only lines.
1259 Just an integer as value is equivalent to (<val> . 0)")
1261 (defvar vhdl-special-indent-hook nil
1262 "*Hook for user defined special indentation adjustments.
1263 This hook gets called after a line is indented by the mode.")
1265 (defvar vhdl-style-alist
1266 '(("IEEE"
1267 (vhdl-basic-offset . 4)
1268 (vhdl-offsets-alist . ())
1271 "Styles of Indentation.
1272 Elements of this alist are of the form:
1274 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
1276 where STYLE-STRING is a short descriptive string used to select a
1277 style, VARIABLE is any `vhdl-mode' variable, and VALUE is the intended
1278 value for that variable when using the selected style.
1280 There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
1281 case, the VALUE is a list containing elements of the form:
1283 (SYNTACTIC-SYMBOL . VALUE)
1285 as described in `vhdl-offsets-alist'. These are passed directly to
1286 `vhdl-set-offset' so there is no need to set every syntactic symbol in
1287 your style, only those that are different from the default.")
1289 ;; dynamically append the default value of most variables
1290 (or (assoc "Default" vhdl-style-alist)
1291 (let* ((varlist '(vhdl-inhibit-startup-warnings-p
1292 vhdl-strict-syntax-p
1293 vhdl-echo-syntactic-information-p
1294 vhdl-basic-offset
1295 vhdl-offsets-alist
1296 vhdl-comment-only-line-offset))
1297 (default (cons "Default"
1298 (mapcar
1299 (function
1300 (lambda (var)
1301 (cons var (symbol-value var))))
1302 varlist))))
1303 (setq vhdl-style-alist (cons default vhdl-style-alist))))
1305 (defvar vhdl-mode-hook nil
1306 "*Hook called by `vhdl-mode'.")
1309 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1310 ;; Compatibility
1312 (defvar vhdl-startup-warnings nil
1313 "Warnings to tell the user during start up.")
1315 (defun vhdl-print-warnings ()
1316 "Print out messages in variable `vhdl-startup-warnings'."
1317 (let ((warnings vhdl-startup-warnings))
1318 (while warnings
1319 (message (concat "WARNING: " (car warnings)))
1320 (setq warnings (cdr warnings))))
1321 (when (> (length vhdl-startup-warnings) 1)
1322 (message "WARNING: See warning messages in *Messages* buffer.")))
1324 (defun vhdl-add-warning (string)
1325 "Add STRING to warning list `vhdl-startup-warnings'."
1326 (setq vhdl-startup-warnings (cons string vhdl-startup-warnings)))
1328 ;; Perform compatibility checks.
1329 (when (not (stringp vhdl-compiler)) ; changed format of `vhdl-compiler'
1330 (setq vhdl-compiler "ModelSim")
1331 (vhdl-add-warning "Variable `vhdl-compiler' has changed format; customize again"))
1332 (when (not (listp vhdl-standard)) ; changed format of `vhdl-standard'
1333 (setq vhdl-standard '(87 nil))
1334 (vhdl-add-warning "Variable `vhdl-standard' has changed format; customize again"))
1335 (when (= (length (car vhdl-model-alist)) 3)
1336 (let ((old-alist vhdl-model-alist) ; changed format of `vhdl-model-alist'
1337 new-alist)
1338 (while old-alist
1339 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1340 (setq old-alist (cdr old-alist)))
1341 (setq vhdl-model-alist (nreverse new-alist))))
1342 (when (= (length (car vhdl-project-alist)) 3)
1343 (let ((old-alist vhdl-project-alist) ; changed format of `vhdl-project-alist'
1344 new-alist)
1345 (while old-alist
1346 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1347 (setq old-alist (cdr old-alist)))
1348 (setq vhdl-project-alist (nreverse new-alist))))
1350 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1351 ;; Help functions
1353 (defsubst vhdl-standard-p (standard)
1354 "Check if STANDARD is specified as used standard."
1355 (or (eq standard (car vhdl-standard))
1356 (memq standard (cadr vhdl-standard))))
1358 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1359 ;; Required packages
1361 (require 'assoc)
1364 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1365 ;;; Emacs variant handling
1366 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1368 ;; active regions
1370 (defun vhdl-keep-region-active ()
1371 "Do whatever is necessary to keep the region active in XEmacs.
1372 Ignore byte-compiler warnings you might see."
1373 (and (boundp 'zmacs-region-stays)
1374 (setq zmacs-region-stays t)))
1376 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1377 ;; XEmacs hacks
1379 (unless (fboundp 'wildcard-to-regexp)
1380 (defun wildcard-to-regexp (wildcard)
1381 "Simplified version of `wildcard-to-regexp' from Emacs' `files.el'."
1382 (let* ((i (string-match "[*?]" wildcard))
1383 (result (substring wildcard 0 i))
1384 (len (length wildcard)))
1385 (when i
1386 (while (< i len)
1387 (let ((ch (aref wildcard i)))
1388 (setq result (concat result
1389 (cond ((eq ch ?*) "[^\000]*")
1390 ((eq ch ??) "[^\000]")
1391 (t (char-to-string ch)))))
1392 (setq i (1+ i)))))
1393 (concat "\\`" result "\\'"))))
1396 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1397 ;;; Bindings
1398 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1400 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1401 ;; Key bindings
1403 (defvar vhdl-template-map ()
1404 "Keymap for VHDL templates.")
1406 (defun vhdl-template-map-init ()
1407 "Initialize `vhdl-template-map'."
1408 (setq vhdl-template-map (make-sparse-keymap))
1409 ;; key bindings for VHDL templates
1410 (define-key vhdl-template-map "al" 'vhdl-template-alias)
1411 (define-key vhdl-template-map "ar" 'vhdl-template-architecture)
1412 (define-key vhdl-template-map "at" 'vhdl-template-assert)
1413 (define-key vhdl-template-map "ad" 'vhdl-template-attribute-decl)
1414 (define-key vhdl-template-map "as" 'vhdl-template-attribute-spec)
1415 (define-key vhdl-template-map "bl" 'vhdl-template-block)
1416 (define-key vhdl-template-map "ca" 'vhdl-template-case-is)
1417 (define-key vhdl-template-map "cd" 'vhdl-template-component-decl)
1418 (define-key vhdl-template-map "ci" 'vhdl-template-component-inst)
1419 (define-key vhdl-template-map "cs" 'vhdl-template-conditional-signal-asst)
1420 (define-key vhdl-template-map "Cb" 'vhdl-template-block-configuration)
1421 (define-key vhdl-template-map "Cc" 'vhdl-template-component-conf)
1422 (define-key vhdl-template-map "Cd" 'vhdl-template-configuration-decl)
1423 (define-key vhdl-template-map "Cs" 'vhdl-template-configuration-spec)
1424 (define-key vhdl-template-map "co" 'vhdl-template-constant)
1425 (define-key vhdl-template-map "di" 'vhdl-template-disconnect)
1426 (define-key vhdl-template-map "el" 'vhdl-template-else)
1427 (define-key vhdl-template-map "ei" 'vhdl-template-elsif)
1428 (define-key vhdl-template-map "en" 'vhdl-template-entity)
1429 (define-key vhdl-template-map "ex" 'vhdl-template-exit)
1430 (define-key vhdl-template-map "fi" 'vhdl-template-file)
1431 (define-key vhdl-template-map "fg" 'vhdl-template-for-generate)
1432 (define-key vhdl-template-map "fl" 'vhdl-template-for-loop)
1433 (define-key vhdl-template-map "\C-f" 'vhdl-template-footer)
1434 (define-key vhdl-template-map "fb" 'vhdl-template-function-body)
1435 (define-key vhdl-template-map "fd" 'vhdl-template-function-decl)
1436 (define-key vhdl-template-map "ge" 'vhdl-template-generic)
1437 (define-key vhdl-template-map "gd" 'vhdl-template-group-decl)
1438 (define-key vhdl-template-map "gt" 'vhdl-template-group-template)
1439 (define-key vhdl-template-map "\C-h" 'vhdl-template-header)
1440 (define-key vhdl-template-map "ig" 'vhdl-template-if-generate)
1441 (define-key vhdl-template-map "it" 'vhdl-template-if-then)
1442 (define-key vhdl-template-map "li" 'vhdl-template-library)
1443 (define-key vhdl-template-map "lo" 'vhdl-template-bare-loop)
1444 (define-key vhdl-template-map "\C-m" 'vhdl-template-modify)
1445 (define-key vhdl-template-map "\C-t" 'vhdl-template-insert-date)
1446 (define-key vhdl-template-map "ma" 'vhdl-template-map)
1447 (define-key vhdl-template-map "ne" 'vhdl-template-next)
1448 (define-key vhdl-template-map "ot" 'vhdl-template-others)
1449 (define-key vhdl-template-map "Pd" 'vhdl-template-package-decl)
1450 (define-key vhdl-template-map "Pb" 'vhdl-template-package-body)
1451 (define-key vhdl-template-map "(" 'vhdl-template-paired-parens)
1452 (define-key vhdl-template-map "po" 'vhdl-template-port)
1453 (define-key vhdl-template-map "pb" 'vhdl-template-procedure-body)
1454 (define-key vhdl-template-map "pd" 'vhdl-template-procedure-decl)
1455 (define-key vhdl-template-map "pc" 'vhdl-template-process-comb)
1456 (define-key vhdl-template-map "ps" 'vhdl-template-process-seq)
1457 (define-key vhdl-template-map "rp" 'vhdl-template-report)
1458 (define-key vhdl-template-map "rt" 'vhdl-template-return)
1459 (define-key vhdl-template-map "ss" 'vhdl-template-selected-signal-asst)
1460 (define-key vhdl-template-map "si" 'vhdl-template-signal)
1461 (define-key vhdl-template-map "su" 'vhdl-template-subtype)
1462 (define-key vhdl-template-map "ty" 'vhdl-template-type)
1463 (define-key vhdl-template-map "us" 'vhdl-template-use)
1464 (define-key vhdl-template-map "va" 'vhdl-template-variable)
1465 (define-key vhdl-template-map "wa" 'vhdl-template-wait)
1466 (define-key vhdl-template-map "wl" 'vhdl-template-while-loop)
1467 (define-key vhdl-template-map "wi" 'vhdl-template-with)
1468 (define-key vhdl-template-map "wc" 'vhdl-template-clocked-wait)
1469 (define-key vhdl-template-map "\C-pb" 'vhdl-template-package-numeric-bit)
1470 (define-key vhdl-template-map "\C-pn" 'vhdl-template-package-numeric-std)
1471 (define-key vhdl-template-map "\C-ps" 'vhdl-template-package-std-logic-1164)
1472 (define-key vhdl-template-map "\C-pA" 'vhdl-template-package-std-logic-arith)
1473 (define-key vhdl-template-map "\C-pM" 'vhdl-template-package-std-logic-misc)
1474 (define-key vhdl-template-map "\C-pS" 'vhdl-template-package-std-logic-signed)
1475 (define-key vhdl-template-map "\C-pT" 'vhdl-template-package-std-logic-textio)
1476 (define-key vhdl-template-map "\C-pU" 'vhdl-template-package-std-logic-unsigned)
1477 (define-key vhdl-template-map "\C-pt" 'vhdl-template-package-textio)
1478 (define-key vhdl-template-map "\C-dn" 'vhdl-template-directive-translate-on)
1479 (define-key vhdl-template-map "\C-df" 'vhdl-template-directive-translate-off)
1480 (define-key vhdl-template-map "\C-dN" 'vhdl-template-directive-synthesis-on)
1481 (define-key vhdl-template-map "\C-dF" 'vhdl-template-directive-synthesis-off)
1482 (define-key vhdl-template-map "\C-q" 'vhdl-template-search-prompt)
1483 (when (vhdl-standard-p 'ams)
1484 (define-key vhdl-template-map "br" 'vhdl-template-break)
1485 (define-key vhdl-template-map "cu" 'vhdl-template-case-use)
1486 (define-key vhdl-template-map "iu" 'vhdl-template-if-use)
1487 (define-key vhdl-template-map "lm" 'vhdl-template-limit)
1488 (define-key vhdl-template-map "na" 'vhdl-template-nature)
1489 (define-key vhdl-template-map "pa" 'vhdl-template-procedural)
1490 (define-key vhdl-template-map "qf" 'vhdl-template-quantity-free)
1491 (define-key vhdl-template-map "qb" 'vhdl-template-quantity-branch)
1492 (define-key vhdl-template-map "qs" 'vhdl-template-quantity-source)
1493 (define-key vhdl-template-map "sn" 'vhdl-template-subnature)
1494 (define-key vhdl-template-map "te" 'vhdl-template-terminal)
1496 (when (vhdl-standard-p 'math)
1497 (define-key vhdl-template-map "\C-pc" 'vhdl-template-package-math-complex)
1498 (define-key vhdl-template-map "\C-pr" 'vhdl-template-package-math-real)
1501 ;; initialize template map for VHDL Mode
1502 (vhdl-template-map-init)
1504 (defun vhdl-function-name (prefix string &optional postfix)
1505 "Generate a Lisp function name.
1506 PREFIX, STRING and optional POSTFIX are concatenated by '-' and spaces in
1507 STRING are replaced by `-' and substrings are converted to lower case."
1508 (let ((name prefix))
1509 (while (string-match "\\(\\w+\\)\\s-*\\(.*\\)" string)
1510 (setq name
1511 (concat name "-" (downcase (substring string 0 (match-end 1)))))
1512 (setq string (substring string (match-beginning 2))))
1513 (when postfix (setq name (concat name "-" postfix)))
1514 (intern name)))
1516 (defvar vhdl-model-map ()
1517 "Keymap for VHDL models.")
1519 (defun vhdl-model-map-init ()
1520 "Initialize `vhdl-model-map'."
1521 (setq vhdl-model-map (make-sparse-keymap))
1522 ;; key bindings for VHDL models
1523 (let ((model-alist vhdl-model-alist) model)
1524 (while model-alist
1525 (setq model (car model-alist))
1526 (define-key vhdl-model-map (nth 2 model)
1527 (vhdl-function-name "vhdl-model" (nth 0 model)))
1528 (setq model-alist (cdr model-alist)))))
1530 ;; initialize user model map for VHDL Mode
1531 (vhdl-model-map-init)
1533 (defvar vhdl-mode-map ()
1534 "Keymap for VHDL Mode.")
1536 (defun vhdl-mode-map-init ()
1537 "Initialize `vhdl-mode-map'."
1538 (setq vhdl-mode-map (make-sparse-keymap))
1539 ;; template key bindings
1540 (define-key vhdl-mode-map "\C-c\C-t" vhdl-template-map)
1541 ;; model key bindings
1542 (define-key vhdl-mode-map "\C-c\C-m" vhdl-model-map)
1543 ;; standard key bindings
1544 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
1545 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
1546 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
1547 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
1548 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
1549 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
1550 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
1551 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
1552 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
1553 ;; backspace/delete key bindings
1554 (define-key vhdl-mode-map [backspace] 'backward-delete-char-untabify)
1555 (define-key vhdl-mode-map [delete] 'delete-char)
1556 (unless (string-match "XEmacs" emacs-version)
1557 (define-key vhdl-mode-map [M-delete] 'kill-word))
1558 ;; mode specific key bindings
1559 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
1560 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
1561 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
1562 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
1563 (define-key vhdl-mode-map "\C-c\C-p\C-w" 'vhdl-port-copy)
1564 (define-key vhdl-mode-map "\C-c\C-p\M-w" 'vhdl-port-copy)
1565 (define-key vhdl-mode-map "\C-c\C-p\C-e" 'vhdl-port-paste-entity)
1566 (define-key vhdl-mode-map "\C-c\C-p\C-c" 'vhdl-port-paste-component)
1567 (define-key vhdl-mode-map "\C-c\C-p\C-i" 'vhdl-port-paste-instance)
1568 (define-key vhdl-mode-map "\C-c\C-p\C-s" 'vhdl-port-paste-signals)
1569 (define-key vhdl-mode-map "\C-c\C-p\M-c" 'vhdl-port-paste-constants)
1570 (if (string-match "XEmacs" emacs-version) ; `... C-g' not allowed in XEmacs
1571 (define-key vhdl-mode-map "\C-c\C-p\M-g" 'vhdl-port-paste-generic-map)
1572 (define-key vhdl-mode-map "\C-c\C-p\C-g" 'vhdl-port-paste-generic-map))
1573 (define-key vhdl-mode-map "\C-c\C-p\C-t" 'vhdl-port-paste-testbench)
1574 (define-key vhdl-mode-map "\C-c\C-p\C-f" 'vhdl-port-flatten)
1575 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
1576 (define-key vhdl-mode-map "\C-c-" 'vhdl-comment-append-inline)
1577 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-comment-display-line)
1578 (define-key vhdl-mode-map "\C-c\M-\C-i" 'vhdl-indent-line)
1579 (define-key vhdl-mode-map "\M-\C-\\" 'vhdl-indent-region)
1580 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-group)
1581 (define-key vhdl-mode-map "\C-c\C-r\C-a" 'vhdl-align-noindent-region)
1582 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-inline-comment-group)
1583 (define-key vhdl-mode-map "\C-c\C-r\M-\C-a" 'vhdl-align-inline-comment-region)
1584 (define-key vhdl-mode-map "\C-c\C-w" 'vhdl-fixup-whitespace-region)
1585 (define-key vhdl-mode-map "\C-c\C-l\C-w" 'vhdl-line-kill)
1586 (define-key vhdl-mode-map "\C-c\C-l\M-w" 'vhdl-line-copy)
1587 (define-key vhdl-mode-map "\C-c\C-l\C-y" 'vhdl-line-yank)
1588 (define-key vhdl-mode-map "\C-c\C-l\t" 'vhdl-line-expand)
1589 (define-key vhdl-mode-map "\C-c\C-l\C-n" 'vhdl-line-transpose-next)
1590 (define-key vhdl-mode-map "\C-c\C-l\C-p" 'vhdl-line-transpose-previous)
1591 (define-key vhdl-mode-map "\C-c\C-l\C-o" 'vhdl-line-open)
1592 (define-key vhdl-mode-map "\C-c\C-l\C-g" 'goto-line)
1593 (define-key vhdl-mode-map "\C-c\C-l\C-c" 'vhdl-comment-uncomment-line)
1594 (define-key vhdl-mode-map "\C-c\C-r\C-u" 'vhdl-fix-case-region)
1595 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
1596 (define-key vhdl-mode-map "\C-c\C-f" 'vhdl-fontify-buffer)
1597 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
1598 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-doc-mode)
1599 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
1600 (define-key vhdl-mode-map "\C-c\C-r\C-b" 'vhdl-beautify-region)
1601 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-beautify-buffer)
1602 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
1603 ;; insert commands bindings
1604 (define-key vhdl-mode-map "\C-c\C-i\C-c" 'vhdl-template-insert-construct)
1605 (define-key vhdl-mode-map "\C-c\C-i\C-p" 'vhdl-template-insert-package)
1606 (define-key vhdl-mode-map "\C-c\C-i\C-d" 'vhdl-template-insert-directive)
1607 (define-key vhdl-mode-map "\C-c\C-i\C-m" 'vhdl-model-insert)
1608 ;; electric key bindings
1609 (define-key vhdl-mode-map " " 'vhdl-electric-space)
1610 (if vhdl-intelligent-tab
1611 (define-key vhdl-mode-map "\t" 'vhdl-electric-tab)
1612 (define-key vhdl-mode-map "\t" 'vhdl-indent-line))
1613 (define-key vhdl-mode-map "\r" 'vhdl-electric-return)
1614 (define-key vhdl-mode-map "-" 'vhdl-electric-dash)
1615 (define-key vhdl-mode-map "[" 'vhdl-electric-open-bracket)
1616 (define-key vhdl-mode-map "]" 'vhdl-electric-close-bracket)
1617 (define-key vhdl-mode-map "'" 'vhdl-electric-quote)
1618 (define-key vhdl-mode-map ";" 'vhdl-electric-semicolon)
1619 (define-key vhdl-mode-map "," 'vhdl-electric-comma)
1620 (define-key vhdl-mode-map "." 'vhdl-electric-period)
1621 (when (vhdl-standard-p 'ams)
1622 (define-key vhdl-mode-map "=" 'vhdl-electric-equal)))
1624 ;; initialize mode map for VHDL Mode
1625 (vhdl-mode-map-init)
1627 ;; define special minibuffer keymap for enabling word completion in minibuffer
1628 ;; (useful in template generator prompts)
1629 (defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
1630 "Keymap for minibuffer used in VHDL Mode.")
1632 (when vhdl-word-completion-in-minibuffer
1633 (define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab))
1635 ;; set up electric character functions to work with
1636 ;; `delete-selection-mode' (Emacs) and `pending-delete-mode' (XEmacs)
1637 (mapcar
1638 (function
1639 (lambda (sym)
1640 (put sym 'delete-selection t) ; for `delete-selection-mode' (Emacs)
1641 (put sym 'pending-delete t))) ; for `pending-delete-mode' (XEmacs)
1642 '(vhdl-electric-space
1643 vhdl-electric-tab
1644 vhdl-electric-return
1645 vhdl-electric-dash
1646 vhdl-electric-open-bracket
1647 vhdl-electric-close-bracket
1648 vhdl-electric-quote
1649 vhdl-electric-semicolon
1650 vhdl-electric-comma
1651 vhdl-electric-period
1652 vhdl-electric-equal))
1654 ;; syntax table
1655 (defvar vhdl-mode-syntax-table nil
1656 "Syntax table used in `vhdl-mode' buffers.")
1658 (defun vhdl-mode-syntax-table-init ()
1659 "Initialize `vhdl-mode-syntax-table'."
1660 (setq vhdl-mode-syntax-table (make-syntax-table))
1661 ;; define punctuation
1662 (modify-syntax-entry ?\# "." vhdl-mode-syntax-table)
1663 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
1664 (modify-syntax-entry ?\% "." vhdl-mode-syntax-table)
1665 (modify-syntax-entry ?\& "." vhdl-mode-syntax-table)
1666 (modify-syntax-entry ?\' "." vhdl-mode-syntax-table)
1667 (modify-syntax-entry ?\* "." vhdl-mode-syntax-table)
1668 (modify-syntax-entry ?\+ "." vhdl-mode-syntax-table)
1669 (modify-syntax-entry ?\. "." vhdl-mode-syntax-table)
1670 (modify-syntax-entry ?\/ "." vhdl-mode-syntax-table)
1671 (modify-syntax-entry ?\: "." vhdl-mode-syntax-table)
1672 (modify-syntax-entry ?\; "." vhdl-mode-syntax-table)
1673 (modify-syntax-entry ?\< "." vhdl-mode-syntax-table)
1674 (modify-syntax-entry ?\= "." vhdl-mode-syntax-table)
1675 (modify-syntax-entry ?\> "." vhdl-mode-syntax-table)
1676 (modify-syntax-entry ?\\ "." vhdl-mode-syntax-table)
1677 (modify-syntax-entry ?\| "." vhdl-mode-syntax-table)
1678 ;; define string
1679 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
1680 ;; define underscore
1681 (when vhdl-underscore-is-part-of-word
1682 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
1683 ;; a single hyphen is punctuation, but a double hyphen starts a comment
1684 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
1685 ;; and \n and \^M end a comment
1686 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
1687 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table)
1688 ;; define parentheses to match
1689 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
1690 (modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table)
1691 (modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table)
1692 (modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table)
1693 (modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table)
1694 (modify-syntax-entry ?\} "){" vhdl-mode-syntax-table))
1696 ;; initialize syntax table for VHDL Mode
1697 (vhdl-mode-syntax-table-init)
1699 (defmacro vhdl-ext-syntax-table (&rest body)
1700 "Execute BODY with syntax table that includes `_' in word class."
1701 `(let (result)
1702 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
1703 (setq result (progn ,@body))
1704 (when (not vhdl-underscore-is-part-of-word)
1705 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
1706 result))
1708 (defvar vhdl-syntactic-context nil
1709 "Buffer local variable containing syntactic analysis list.")
1710 (make-variable-buffer-local 'vhdl-syntactic-context)
1712 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1713 ;; Abbrev hook bindings
1715 (defvar vhdl-mode-abbrev-table nil
1716 "Abbrev table to use in `vhdl-mode' buffers.")
1718 (defun vhdl-mode-abbrev-table-init ()
1719 "Initialize `vhdl-mode-abbrev-table'."
1720 (when vhdl-mode-abbrev-table (clear-abbrev-table vhdl-mode-abbrev-table))
1721 (define-abbrev-table 'vhdl-mode-abbrev-table
1722 (append
1723 (when (memq 'vhdl vhdl-electric-keywords)
1724 ;; VHDL'93 keywords
1726 ("--" "" vhdl-template-display-comment-hook 0 t)
1727 ("abs" "" vhdl-template-default-hook 0 t)
1728 ("access" "" vhdl-template-default-hook 0 t)
1729 ("after" "" vhdl-template-default-hook 0 t)
1730 ("alias" "" vhdl-template-alias-hook 0 t)
1731 ("all" "" vhdl-template-default-hook 0 t)
1732 ("and" "" vhdl-template-default-hook 0 t)
1733 ("arch" "" vhdl-template-architecture-hook 0 t)
1734 ("architecture" "" vhdl-template-architecture-hook 0 t)
1735 ("array" "" vhdl-template-default-hook 0 t)
1736 ("assert" "" vhdl-template-assert-hook 0 t)
1737 ("attr" "" vhdl-template-attribute-hook 0 t)
1738 ("attribute" "" vhdl-template-attribute-hook 0 t)
1739 ("begin" "" vhdl-template-default-indent-hook 0 t)
1740 ("block" "" vhdl-template-block-hook 0 t)
1741 ("body" "" vhdl-template-default-hook 0 t)
1742 ("buffer" "" vhdl-template-default-hook 0 t)
1743 ("bus" "" vhdl-template-default-hook 0 t)
1744 ("case" "" vhdl-template-case-hook 0 t)
1745 ("comp" "" vhdl-template-component-hook 0 t)
1746 ("component" "" vhdl-template-component-hook 0 t)
1747 ("cond" "" vhdl-template-conditional-signal-asst-hook 0 t)
1748 ("conditional" "" vhdl-template-conditional-signal-asst-hook 0 t)
1749 ("conf" "" vhdl-template-configuration-hook 0 t)
1750 ("configuration" "" vhdl-template-configuration-hook 0 t)
1751 ("cons" "" vhdl-template-constant-hook 0 t)
1752 ("constant" "" vhdl-template-constant-hook 0 t)
1753 ("disconnect" "" vhdl-template-disconnect-hook 0 t)
1754 ("downto" "" vhdl-template-default-hook 0 t)
1755 ("else" "" vhdl-template-else-hook 0 t)
1756 ("elseif" "" vhdl-template-elsif-hook 0 t)
1757 ("elsif" "" vhdl-template-elsif-hook 0 t)
1758 ("end" "" vhdl-template-default-indent-hook 0 t)
1759 ("entity" "" vhdl-template-entity-hook 0 t)
1760 ("exit" "" vhdl-template-exit-hook 0 t)
1761 ("file" "" vhdl-template-file-hook 0 t)
1762 ("for" "" vhdl-template-for-hook 0 t)
1763 ("func" "" vhdl-template-function-hook 0 t)
1764 ("function" "" vhdl-template-function-hook 0 t)
1765 ("generic" "" vhdl-template-generic-hook 0 t)
1766 ("group" "" vhdl-template-group-hook 0 t)
1767 ("guarded" "" vhdl-template-default-hook 0 t)
1768 ("if" "" vhdl-template-if-hook 0 t)
1769 ("impure" "" vhdl-template-default-hook 0 t)
1770 ("in" "" vhdl-template-default-hook 0 t)
1771 ("inertial" "" vhdl-template-default-hook 0 t)
1772 ("inout" "" vhdl-template-default-hook 0 t)
1773 ("inst" "" vhdl-template-instance-hook 0 t)
1774 ("instance" "" vhdl-template-instance-hook 0 t)
1775 ("is" "" vhdl-template-default-hook 0 t)
1776 ("label" "" vhdl-template-default-hook 0 t)
1777 ("library" "" vhdl-template-library-hook 0 t)
1778 ("linkage" "" vhdl-template-default-hook 0 t)
1779 ("literal" "" vhdl-template-default-hook 0 t)
1780 ("loop" "" vhdl-template-bare-loop-hook 0 t)
1781 ("map" "" vhdl-template-map-hook 0 t)
1782 ("mod" "" vhdl-template-default-hook 0 t)
1783 ("nand" "" vhdl-template-default-hook 0 t)
1784 ("new" "" vhdl-template-default-hook 0 t)
1785 ("next" "" vhdl-template-next-hook 0 t)
1786 ("nor" "" vhdl-template-default-hook 0 t)
1787 ("not" "" vhdl-template-default-hook 0 t)
1788 ("null" "" vhdl-template-default-hook 0 t)
1789 ("of" "" vhdl-template-default-hook 0 t)
1790 ("on" "" vhdl-template-default-hook 0 t)
1791 ("open" "" vhdl-template-default-hook 0 t)
1792 ("or" "" vhdl-template-default-hook 0 t)
1793 ("others" "" vhdl-template-default-hook 0 t)
1794 ("out" "" vhdl-template-default-hook 0 t)
1795 ("pack" "" vhdl-template-package-hook 0 t)
1796 ("package" "" vhdl-template-package-hook 0 t)
1797 ("port" "" vhdl-template-port-hook 0 t)
1798 ("postponed" "" vhdl-template-default-hook 0 t)
1799 ("procedure" "" vhdl-template-procedure-hook 0 t)
1800 ("process" "" vhdl-template-process-hook 0 t)
1801 ("pure" "" vhdl-template-default-hook 0 t)
1802 ("range" "" vhdl-template-default-hook 0 t)
1803 ("record" "" vhdl-template-default-hook 0 t)
1804 ("register" "" vhdl-template-default-hook 0 t)
1805 ("reject" "" vhdl-template-default-hook 0 t)
1806 ("rem" "" vhdl-template-default-hook 0 t)
1807 ("report" "" vhdl-template-report-hook 0 t)
1808 ("return" "" vhdl-template-return-hook 0 t)
1809 ("rol" "" vhdl-template-default-hook 0 t)
1810 ("ror" "" vhdl-template-default-hook 0 t)
1811 ("select" "" vhdl-template-selected-signal-asst-hook 0 t)
1812 ("severity" "" vhdl-template-default-hook 0 t)
1813 ("shared" "" vhdl-template-default-hook 0 t)
1814 ("sig" "" vhdl-template-signal-hook 0 t)
1815 ("signal" "" vhdl-template-signal-hook 0 t)
1816 ("sla" "" vhdl-template-default-hook 0 t)
1817 ("sll" "" vhdl-template-default-hook 0 t)
1818 ("sra" "" vhdl-template-default-hook 0 t)
1819 ("srl" "" vhdl-template-default-hook 0 t)
1820 ("subtype" "" vhdl-template-subtype-hook 0 t)
1821 ("then" "" vhdl-template-default-hook 0 t)
1822 ("to" "" vhdl-template-default-hook 0 t)
1823 ("transport" "" vhdl-template-default-hook 0 t)
1824 ("type" "" vhdl-template-type-hook 0 t)
1825 ("unaffected" "" vhdl-template-default-hook 0 t)
1826 ("units" "" vhdl-template-default-hook 0 t)
1827 ("until" "" vhdl-template-default-hook 0 t)
1828 ("use" "" vhdl-template-use-hook 0 t)
1829 ("var" "" vhdl-template-variable-hook 0 t)
1830 ("variable" "" vhdl-template-variable-hook 0 t)
1831 ("wait" "" vhdl-template-wait-hook 0 t)
1832 ("when" "" vhdl-template-when-hook 0 t)
1833 ("while" "" vhdl-template-while-loop-hook 0 t)
1834 ("with" "" vhdl-template-with-hook 0 t)
1835 ("xnor" "" vhdl-template-default-hook 0 t)
1836 ("xor" "" vhdl-template-default-hook 0 t)
1838 ;; VHDL-AMS keywords
1839 (when (and (memq 'vhdl vhdl-electric-keywords) (vhdl-standard-p 'ams))
1841 ("across" "" vhdl-template-default-hook 0 t)
1842 ("break" "" vhdl-template-break-hook 0 t)
1843 ("limit" "" vhdl-template-limit-hook 0 t)
1844 ("nature" "" vhdl-template-nature-hook 0 t)
1845 ("noise" "" vhdl-template-default-hook 0 t)
1846 ("procedural" "" vhdl-template-procedural-hook 0 t)
1847 ("quantity" "" vhdl-template-quantity-hook 0 t)
1848 ("reference" "" vhdl-template-default-hook 0 t)
1849 ("spectrum" "" vhdl-template-default-hook 0 t)
1850 ("subnature" "" vhdl-template-subnature-hook 0 t)
1851 ("terminal" "" vhdl-template-terminal-hook 0 t)
1852 ("through" "" vhdl-template-default-hook 0 t)
1853 ("tolerance" "" vhdl-template-default-hook 0 t)
1855 ;; user model keywords
1856 (when (memq 'user vhdl-electric-keywords)
1857 (let ((alist vhdl-model-alist)
1858 abbrev-list keyword)
1859 (while alist
1860 (setq keyword (nth 3 (car alist)))
1861 (unless (equal keyword "")
1862 (setq abbrev-list
1863 (cons (list keyword ""
1864 (vhdl-function-name
1865 "vhdl-model" (nth 0 (car alist)) "hook") 0)
1866 abbrev-list)))
1867 (setq alist (cdr alist)))
1868 abbrev-list)))))
1870 ;; initialize abbrev table for VHDL Mode
1871 (vhdl-mode-abbrev-table-init)
1873 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1874 ;; Template completion lists
1876 (defvar vhdl-template-construct-alist nil
1877 "List of built-in construct templates.")
1879 (defun vhdl-template-construct-alist-init ()
1880 "Initialize `vhdl-template-construct-alist'."
1881 (setq
1882 vhdl-template-construct-alist
1883 (append
1885 ("alias declaration" vhdl-template-alias)
1886 ("architecture body" vhdl-template-architecture)
1887 ("assertion" vhdl-template-assert)
1888 ("attribute declaration" vhdl-template-attribute-decl)
1889 ("attribute specification" vhdl-template-attribute-spec)
1890 ("block configuration" vhdl-template-block-configuration)
1891 ("block statement" vhdl-template-block)
1892 ("case statement" vhdl-template-case-is)
1893 ("component configuration" vhdl-template-component-conf)
1894 ("component declaration" vhdl-template-component-decl)
1895 ("component instantiation statement" vhdl-template-component-inst)
1896 ("conditional signal assignment" vhdl-template-conditional-signal-asst)
1897 ("configuration declaration" vhdl-template-configuration-decl)
1898 ("configuration specification" vhdl-template-configuration-spec)
1899 ("constant declaration" vhdl-template-constant)
1900 ("disconnection specification" vhdl-template-disconnect)
1901 ("entity declaration" vhdl-template-entity)
1902 ("exit statement" vhdl-template-exit)
1903 ("file declaration" vhdl-template-file)
1904 ("generate statement" vhdl-template-generate)
1905 ("generic clause" vhdl-template-generic)
1906 ("group declaration" vhdl-template-group-decl)
1907 ("group template declaration" vhdl-template-group-template)
1908 ("if statement" vhdl-template-if-then)
1909 ("library clause" vhdl-template-library)
1910 ("loop statement" vhdl-template-loop)
1911 ("next statement" vhdl-template-next)
1912 ("package declaration" vhdl-template-package-decl)
1913 ("package body" vhdl-template-package-body)
1914 ("port clause" vhdl-template-port)
1915 ("process statement" vhdl-template-process)
1916 ("report statement" vhdl-template-report)
1917 ("return statement" vhdl-template-return)
1918 ("selected signal assignment" vhdl-template-selected-signal-asst)
1919 ("signal declaration" vhdl-template-signal)
1920 ("subprogram declaration" vhdl-template-subprogram-decl)
1921 ("subprogram body" vhdl-template-subprogram-body)
1922 ("subtype declaration" vhdl-template-subtype)
1923 ("type declaration" vhdl-template-type)
1924 ("use clause" vhdl-template-use)
1925 ("variable declaration" vhdl-template-variable)
1926 ("wait statement" vhdl-template-wait)
1928 (when (vhdl-standard-p 'ams)
1930 ("break statement" vhdl-template-break)
1931 ("nature declaration" vhdl-template-nature)
1932 ("quantity declaration" vhdl-template-quantity)
1933 ("simultaneous case statement" vhdl-template-case-use)
1934 ("simultaneous if statement" vhdl-template-if-use)
1935 ("simultaneous procedural statement" vhdl-template-procedural)
1936 ("step limit specification" vhdl-template-limit)
1937 ("subnature declaration" vhdl-template-subnature)
1938 ("terminal declaration" vhdl-template-terminal)
1939 )))))
1941 ;; initialize for VHDL Mode
1942 (vhdl-template-construct-alist-init)
1944 (defvar vhdl-template-package-alist nil
1945 "List of built-in package templates.")
1947 (defun vhdl-template-package-alist-init ()
1948 "Initialize `vhdl-template-package-alist'."
1949 (setq
1950 vhdl-template-package-alist
1951 (append
1953 ("numeric_bit" vhdl-template-package-numeric-bit)
1954 ("numeric_std" vhdl-template-package-numeric-std)
1955 ("std_logic_1164" vhdl-template-package-std-logic-1164)
1956 ("std_logic_arith" vhdl-template-package-std-logic-arith)
1957 ("std_logic_misc" vhdl-template-package-std-logic-misc)
1958 ("std_logic_signed" vhdl-template-package-std-logic-signed)
1959 ("std_logic_textio" vhdl-template-package-std-logic-textio)
1960 ("std_logic_unsigned" vhdl-template-package-std-logic-unsigned)
1961 ("textio" vhdl-template-package-textio)
1963 (when (vhdl-standard-p 'math)
1965 ("math_complex" vhdl-template-package-math-complex)
1966 ("math_real" vhdl-template-package-math-real)
1967 )))))
1969 ;; initialize for VHDL Mode
1970 (vhdl-template-package-alist-init)
1972 (defvar vhdl-template-directive-alist
1973 (append
1975 ("translate_on" vhdl-template-directive-translate-on)
1976 ("translate_off" vhdl-template-directive-translate-off)
1977 ("synthesis_on" vhdl-template-directive-synthesis-on)
1978 ("synthesis_off" vhdl-template-directive-synthesis-off)
1980 "List of built-in directive templates.")
1983 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1984 ;;; Menues
1985 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1987 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1988 ;; VHDL menu (using `easy-menu.el')
1990 (defun vhdl-customize ()
1991 "Call the customize function with `vhdl' as argument."
1992 (interactive)
1993 (customize-browse 'vhdl))
1995 (defun vhdl-create-customize-menu ()
1996 "Create a full customization menu for VHDL, insert it into the menu."
1997 (interactive)
1998 (if (fboundp 'customize-menu-create)
1999 (easy-menu-change
2000 '("VHDL") "Customize"
2001 `(["Browse VHDL Group..." vhdl-customize t]
2002 ,(customize-menu-create 'vhdl)
2003 "--"
2004 ["Activate New Customizations" vhdl-activate-customizations t]))
2005 (error "Cannot expand menu (outdated version of cus-edit.el)")))
2007 (defun vhdl-create-mode-menu ()
2008 "Create VHDL Mode menu."
2009 (list
2010 "VHDL"
2011 '("Mode"
2012 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
2013 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
2015 "--"
2016 (append
2017 '("Project"
2018 ["None" (vhdl-project-switch "")
2019 :style radio :selected (equal vhdl-project "")]
2020 "--"
2022 ;; add menu entries for defined projects
2023 (let ((project-alist vhdl-project-alist) menu-alist name)
2024 (while project-alist
2025 (setq name (car (car project-alist)))
2026 (setq menu-alist (cons (vector name (list 'vhdl-project-switch name)
2027 :style 'radio :selected
2028 (list 'equal 'vhdl-project name))
2029 menu-alist))
2030 (setq project-alist (cdr project-alist)))
2031 (setq menu-alist (cons '["Add Project..."
2032 (customize-variable 'vhdl-project-alist) t]
2033 (cons "--" menu-alist)))
2034 (nreverse menu-alist)))
2035 "--"
2036 (list
2037 "Compile"
2038 ["Compile Buffer" vhdl-compile t]
2039 ["Stop Compilation" kill-compilation t]
2040 "--"
2041 ["Make" vhdl-make t]
2042 ["Generate Makefile" vhdl-generate-makefile t]
2043 "--"
2044 ["Next Error" next-error t]
2045 ["Previous Error" previous-error t]
2046 ["First Error" first-error t]
2047 "--"
2048 (append
2049 '("Compiler")
2050 ;; add menu entries for defined compilers
2051 (let ((comp-alist vhdl-compiler-alist) menu-alist name)
2052 (while comp-alist
2053 (setq name (car (car comp-alist)))
2054 (setq menu-alist (cons (vector name (list 'setq 'vhdl-compiler name)
2055 :style 'radio :selected
2056 (list 'equal 'vhdl-compiler name))
2057 menu-alist))
2058 (setq comp-alist (cdr comp-alist)))
2059 (setq menu-alist (cons '["Add Compiler..."
2060 (customize-variable 'vhdl-compiler-alist) t]
2061 (cons "--" menu-alist)))
2062 (nreverse menu-alist))))
2063 "--"
2064 (append
2065 '("Template"
2066 ("VHDL Construct 1"
2067 ["Alias" vhdl-template-alias t]
2068 ["Architecture" vhdl-template-architecture t]
2069 ["Assert" vhdl-template-assert t]
2070 ["Attribute (Decl)" vhdl-template-attribute-decl t]
2071 ["Attribute (Spec)" vhdl-template-attribute-spec t]
2072 ["Block" vhdl-template-block t]
2073 ["Case" vhdl-template-case-is t]
2074 ["Component (Decl)" vhdl-template-component-decl t]
2075 ["(Component) Instance" vhdl-template-component-inst t]
2076 ["Conditional (Signal Asst)" vhdl-template-conditional-signal-asst t]
2077 ["Configuration (Block)"vhdl-template-block-configuration t]
2078 ["Configuration (Comp)" vhdl-template-component-conf t]
2079 ["Configuration (Decl)" vhdl-template-configuration-decl t]
2080 ["Configuration (Spec)" vhdl-template-configuration-spec t]
2081 ["Constant" vhdl-template-constant t]
2082 ["Disconnect" vhdl-template-disconnect t]
2083 ["Else" vhdl-template-else t]
2084 ["Elsif" vhdl-template-elsif t]
2085 ["Entity" vhdl-template-entity t]
2086 ["Exit" vhdl-template-exit t]
2087 ["File" vhdl-template-file t]
2088 ["For (Generate)" vhdl-template-for-generate t]
2089 ["For (Loop)" vhdl-template-for-loop t]
2090 ["Function (Body)" vhdl-template-function-body t]
2091 ["Function (Decl)" vhdl-template-function-decl t]
2092 ["Generic" vhdl-template-generic t]
2093 ["Group (Decl)" vhdl-template-group-decl t]
2094 ["Group (Template)" vhdl-template-group-template t]
2096 ("VHDL Construct 2"
2097 ["If (Generate)" vhdl-template-if-generate t]
2098 ["If (Then)" vhdl-template-if-then t]
2099 ["Library" vhdl-template-library t]
2100 ["Loop" vhdl-template-bare-loop t]
2101 ["Map" vhdl-template-map t]
2102 ["Next" vhdl-template-next t]
2103 ["(Others)" vhdl-template-others t]
2104 ["Package (Decl)" vhdl-template-package-decl t]
2105 ["Package (Body)" vhdl-template-package-body t]
2106 ["Port" vhdl-template-port t]
2107 ["Procedure (Body)" vhdl-template-procedure-body t]
2108 ["Procedure (Decl)" vhdl-template-procedure-decl t]
2109 ["Process (Comb)" vhdl-template-process-comb t]
2110 ["Process (Seq)" vhdl-template-process-seq t]
2111 ["Report" vhdl-template-report t]
2112 ["Return" vhdl-template-return t]
2113 ["Select" vhdl-template-selected-signal-asst t]
2114 ["Signal" vhdl-template-signal t]
2115 ["Subtype" vhdl-template-subtype t]
2116 ["Type" vhdl-template-type t]
2117 ["Use" vhdl-template-use t]
2118 ["Variable" vhdl-template-variable t]
2119 ["Wait" vhdl-template-wait t]
2120 ["(Clocked Wait)" vhdl-template-clocked-wait t]
2121 ["When" vhdl-template-when t]
2122 ["While (Loop)" vhdl-template-while-loop t]
2123 ["With" vhdl-template-with t]
2125 (when (vhdl-standard-p 'ams)
2126 '(("VHDL-AMS Construct"
2127 ["Break" vhdl-template-break t]
2128 ["Case (Use)" vhdl-template-case-use t]
2129 ["If (Use)" vhdl-template-if-use t]
2130 ["Limit" vhdl-template-limit t]
2131 ["Nature" vhdl-template-nature t]
2132 ["Procedural" vhdl-template-procedural t]
2133 ["Quantity (Free)" vhdl-template-quantity-free t]
2134 ["Quantity (Branch)" vhdl-template-quantity-branch t]
2135 ["Quantity (Source)" vhdl-template-quantity-source t]
2136 ["Subnature" vhdl-template-subnature t]
2137 ["Terminal" vhdl-template-terminal t]
2139 '(["Insert Construct" vhdl-template-insert-construct
2140 :keys "C-c C-i C-c"]
2141 "--")
2142 (list
2143 (append
2144 '("Package")
2145 (when (vhdl-standard-p 'math)
2147 ["math_complex" vhdl-template-package-math-complex t]
2148 ["math_real" vhdl-template-package-math-real t]
2151 ["numeric_bit" vhdl-template-package-numeric-bit t]
2152 ["numeric_std" vhdl-template-package-numeric-std t]
2153 ["std_logic_1164" vhdl-template-package-std-logic-1164 t]
2154 ["textio" vhdl-template-package-textio t]
2155 "--"
2156 ["std_logic_arith" vhdl-template-package-std-logic-arith t]
2157 ["std_logic_signed" vhdl-template-package-std-logic-signed t]
2158 ["std_logic_unsigned" vhdl-template-package-std-logic-unsigned t]
2159 ["std_logic_misc" vhdl-template-package-std-logic-misc t]
2160 ["std_logic_textio" vhdl-template-package-std-logic-textio t]
2161 "--"
2162 ["Insert Package" vhdl-template-insert-package
2163 :keys "C-c C-i C-p"]
2165 '(("Directive"
2166 ["translate_on" vhdl-template-directive-translate-on t]
2167 ["translate_off" vhdl-template-directive-translate-off t]
2168 ["synthesis_on" vhdl-template-directive-synthesis-on t]
2169 ["synthesis_off" vhdl-template-directive-synthesis-off t]
2170 "--"
2171 ["Insert Directive" vhdl-template-insert-directive
2172 :keys "C-c C-i C-d"]
2174 "--"
2175 ["Insert Header" vhdl-template-header :keys "C-c C-t C-h"]
2176 ["Insert Footer" vhdl-template-footer t]
2177 ["Insert Date" vhdl-template-insert-date t]
2178 ["Modify Date" vhdl-template-modify :keys "C-c C-t C-m"]
2179 "--"
2180 ["Query Next Prompt" vhdl-template-search-prompt t]
2182 (append
2183 '("Model")
2184 ;; add menu entries for defined models
2185 (let ((model-alist vhdl-model-alist) menu-alist model)
2186 (while model-alist
2187 (setq model (car model-alist))
2188 (setq menu-alist
2189 (cons (vector
2190 (nth 0 model)
2191 (vhdl-function-name "vhdl-model" (nth 0 model))
2192 :keys (concat "C-c C-m " (key-description (nth 2 model))))
2193 menu-alist))
2194 (setq model-alist (cdr model-alist)))
2195 (setq menu-alist
2196 (append
2197 (nreverse menu-alist)
2198 '("--"
2199 ["Insert Model" vhdl-model-insert :keys "C-c C-i C-m"]
2200 ["Add Model..." (customize-variable 'vhdl-model-alist) t])))
2201 menu-alist))
2202 '("Port"
2203 ["Copy" vhdl-port-copy t]
2204 "--"
2205 ["Paste As Entity" vhdl-port-paste-entity vhdl-port-list]
2206 ["Paste As Component" vhdl-port-paste-component vhdl-port-list]
2207 ["Paste As Instance" vhdl-port-paste-instance
2208 :keys "C-c C-p C-i" :active vhdl-port-list]
2209 ["Paste As Signals" vhdl-port-paste-signals vhdl-port-list]
2210 ["Paste As Constants" vhdl-port-paste-constants vhdl-port-list]
2211 ["Paste As Generic Map" vhdl-port-paste-generic-map vhdl-port-list]
2212 ["Paste As Test Bench" vhdl-port-paste-testbench vhdl-port-list]
2213 "--"
2214 ["Flatten" vhdl-port-flatten vhdl-port-list]
2216 "--"
2217 '("Comment"
2218 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
2219 "--"
2220 ["Insert Inline Comment" vhdl-comment-append-inline t]
2221 ["Insert Horizontal Line" vhdl-comment-display-line t]
2222 ["Insert Display Comment" vhdl-comment-display t]
2223 "--"
2224 ["Fill Comment" fill-paragraph t]
2225 ["Fill Comment Region" fill-region (mark)]
2226 ["Kill Comment Region" vhdl-comment-kill-region (mark)]
2227 ["Kill Inline Comment Region" vhdl-comment-kill-inline-region (mark)]
2229 '("Line"
2230 ["Kill" vhdl-line-kill t]
2231 ["Copy" vhdl-line-copy t]
2232 ["Yank" vhdl-line-yank t]
2233 ["Expand" vhdl-line-expand t]
2234 "--"
2235 ["Transpose Next" vhdl-line-transpose-next t]
2236 ["Transpose Prev" vhdl-line-transpose-previous t]
2237 ["Open" vhdl-line-open t]
2238 ["Join" delete-indentation t]
2239 "--"
2240 ["Goto" goto-line t]
2241 ["(Un)Comment Out" vhdl-comment-uncomment-line t]
2243 '("Move"
2244 ["Forward Statement" vhdl-end-of-statement t]
2245 ["Backward Statement" vhdl-beginning-of-statement t]
2246 ["Forward Expression" vhdl-forward-sexp t]
2247 ["Backward Expression" vhdl-backward-sexp t]
2248 ["Forward Function" vhdl-end-of-defun t]
2249 ["Backward Function" vhdl-beginning-of-defun t]
2250 ["Mark Function" vhdl-mark-defun t]
2252 "--"
2253 '("Indent"
2254 ["Line" vhdl-indent-line t]
2255 ["Region" vhdl-indent-region (mark)]
2256 ["Buffer" vhdl-indent-buffer t]
2258 '("Align"
2259 ["Group" vhdl-align-group t]
2260 ["Region" vhdl-align-noindent-region (mark)]
2261 ["Buffer" vhdl-align-noindent-buffer t]
2262 "--"
2263 ["Inline Comment Group" vhdl-align-inline-comment-group t]
2264 ["Inline Comment Region" vhdl-align-inline-comment-region (mark)]
2265 ["Inline Comment Buffer" vhdl-align-inline-comment-buffer t]
2266 "--"
2267 ["Fixup Whitespace Region" vhdl-fixup-whitespace-region (mark)]
2268 ["Fixup Whitespace Buffer" vhdl-fixup-whitespace-buffer t]
2270 '("Fix Case"
2271 ["Region" vhdl-fix-case-region (mark)]
2272 ["Buffer" vhdl-fix-case-buffer t]
2274 '("Beautify"
2275 ["Beautify Region" vhdl-beautify-region (mark)]
2276 ["Beautify Buffer" vhdl-beautify-buffer t]
2278 "--"
2279 ["Fontify Buffer" vhdl-fontify-buffer t]
2280 ["Syntactic Info" vhdl-show-syntactic-information t]
2281 "--"
2282 '("Documentation"
2283 ["VHDL Mode" vhdl-doc-mode :keys "C-c C-h"]
2284 ["Reserved Words" (vhdl-doc-variable 'vhdl-doc-keywords) t]
2285 ["Coding Style" (vhdl-doc-variable 'vhdl-doc-coding-style) t]
2287 ["Version" vhdl-version t]
2288 ["Bug Report..." vhdl-submit-bug-report t]
2289 "--"
2290 '("Speedbar"
2291 ["Open/Close" vhdl-speedbar t]
2292 "--"
2293 ["Show Hierarchy" vhdl-speedbar-toggle-hierarchy
2294 :style toggle
2295 :selected
2296 (and (boundp 'speedbar-initial-expansion-list-name)
2297 (equal speedbar-initial-expansion-list-name "vhdl hierarchy"))
2298 :active (and (boundp 'speedbar-frame) speedbar-frame)]
2300 "--"
2301 '("Customize"
2302 ["Browse VHDL Group..." vhdl-customize t]
2303 ["Build Customize Menu" vhdl-create-customize-menu
2304 (fboundp 'customize-menu-create)]
2305 "--"
2306 ["Activate New Customizations" vhdl-activate-customizations t])
2309 (defvar vhdl-mode-menu-list (vhdl-create-mode-menu)
2310 "VHDL Mode menu.")
2312 (defun vhdl-update-mode-menu ()
2313 "Update VHDL mode menu."
2314 (interactive)
2315 (easy-menu-remove vhdl-mode-menu-list) ; for XEmacs
2316 (setq vhdl-mode-menu-list (vhdl-create-mode-menu))
2317 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2318 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2319 "Menu keymap for VHDL Mode." vhdl-mode-menu-list))
2321 (require 'easymenu)
2323 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2324 ;; Index menu (using `imenu.el'), also used for speedbar (using `speedbar.el')
2326 (defvar vhdl-imenu-generic-expression
2328 ("Subprogram"
2329 "^\\s-*\\(\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\s-+\\(\"?\\(\\w\\|\\s_\\)+\"?\\)"
2331 ("Instance"
2332 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
2334 ("Component"
2335 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2337 ("Procedural"
2338 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(procedural\\)"
2340 ("Process"
2341 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\(postponed\\s-+\\|\\)process\\)"
2343 ("Block"
2344 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(block\\)"
2346 ("Package"
2347 "^\\s-*\\(package\\( body\\|\\)\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2349 ("Configuration"
2350 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
2352 ("Architecture"
2353 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
2355 ("Entity"
2356 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2359 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
2361 (defun vhdl-index-menu-init ()
2362 "Initialize index menu."
2363 (set (make-local-variable 'imenu-case-fold-search) t)
2364 (set (make-local-variable 'imenu-generic-expression)
2365 vhdl-imenu-generic-expression)
2366 (when (and vhdl-index-menu (not (string-match "XEmacs" emacs-version)))
2367 (if (or (not (boundp 'font-lock-maximum-size))
2368 (> font-lock-maximum-size (buffer-size)))
2369 (imenu-add-to-menubar "Index")
2370 (message "Scanning buffer for index...buffer too big"))))
2372 ;; ############################################################################
2373 ;; Source file menu (using `easy-menu.el')
2375 (defvar vhdl-sources-menu nil)
2377 (defun vhdl-directory-files (directory &optional full match)
2378 "Call `directory-files' if DIRECTORY exists, otherwise generate error
2379 message."
2380 (if (file-directory-p directory)
2381 (directory-files directory full match)
2382 (message "No such directory: \"%s\"" directory)
2383 nil))
2385 (defun vhdl-get-source-files (&optional full directory)
2386 "Get list of VHDL source files in DIRECTORY or current directory."
2387 (let ((mode-alist auto-mode-alist)
2388 filename-regexp)
2389 ;; create regular expressions for matching file names
2390 (setq filename-regexp ".*\\(")
2391 (while mode-alist
2392 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
2393 (setq filename-regexp
2394 (concat filename-regexp (car (car mode-alist)) "\\|")))
2395 (setq mode-alist (cdr mode-alist)))
2396 (setq filename-regexp
2397 (concat (substring filename-regexp 0
2398 (string-match "\\\\|$" filename-regexp)) "\\)"))
2399 ;; find files
2400 (nreverse (vhdl-directory-files
2401 (or directory default-directory) full filename-regexp))))
2403 (defun vhdl-add-source-files-menu ()
2404 "Scan directory for all VHDL source files and generate menu.
2405 The directory of the current source file is scanned."
2406 (interactive)
2407 (message "Scanning directory for source files ...")
2408 (let ((newmap (current-local-map))
2409 (mode-alist auto-mode-alist)
2410 (file-list (vhdl-get-source-files))
2411 menu-list found)
2412 ;; Create list for menu
2413 (setq found nil)
2414 (while file-list
2415 (setq found t)
2416 (setq menu-list (cons (vector (car file-list)
2417 (list 'find-file (car file-list)) t)
2418 menu-list))
2419 (setq file-list (cdr file-list)))
2420 (setq menu-list (vhdl-menu-split menu-list 25))
2421 (when found (setq menu-list (cons "--" menu-list)))
2422 (setq menu-list (cons ["*Rescan*" vhdl-add-source-files-menu t] menu-list))
2423 (setq menu-list (cons "Sources" menu-list))
2424 ;; Create menu
2425 (easy-menu-add menu-list)
2426 (easy-menu-define vhdl-sources-menu newmap
2427 "VHDL source files menu" menu-list))
2428 (message ""))
2430 (defun vhdl-menu-split (list n)
2431 "Split menu LIST into several submenues, if number of elements > N."
2432 (if (> (length list) n)
2433 (let ((remain list)
2434 (result '())
2435 (sublist '())
2436 (menuno 1)
2437 (i 0))
2438 (while remain
2439 (setq sublist (cons (car remain) sublist))
2440 (setq remain (cdr remain))
2441 (setq i (+ i 1))
2442 (if (= i n)
2443 (progn
2444 (setq result (cons (cons (format "Sources %s" menuno)
2445 (nreverse sublist)) result))
2446 (setq i 0)
2447 (setq menuno (+ menuno 1))
2448 (setq sublist '()))))
2449 (and sublist
2450 (setq result (cons (cons (format "Sources %s" menuno)
2451 (nreverse sublist)) result)))
2452 (nreverse result))
2453 list))
2456 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2457 ;;; VHDL Mode definition
2458 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2459 ;; performs all buffer local initializations
2461 ;;;###autoload
2462 (defun vhdl-mode ()
2463 "Major mode for editing VHDL code.
2465 Usage:
2466 ------
2468 - TEMPLATE INSERTION (electrification): After typing a VHDL keyword and
2469 entering `\\[vhdl-electric-space]', you are prompted for arguments while a template is generated
2470 for that VHDL construct. Typing `\\[vhdl-electric-return]' or `\\[keyboard-quit]' at the first (mandatory)
2471 prompt aborts the current template generation. Optional arguments are
2472 indicated by square brackets and removed if the queried string is left empty.
2473 Prompts for mandatory arguments remain in the code if the queried string is
2474 left empty. They can be queried again by `\\[vhdl-template-search-prompt]'.
2475 Typing `\\[just-one-space]' after a keyword inserts a space without calling the template
2476 generator. Automatic template generation (i.e. electrification) can be
2477 disabled (enabled) by typing `\\[vhdl-electric-mode]' or by setting custom variable
2478 `vhdl-electric-mode' (see CUSTOMIZATION).
2479 Enabled electrification is indicated by `/e' in the modeline.
2480 Template generators can be invoked from the VHDL menu, by key bindings, by
2481 typing `C-c C-i C-c' and choosing a construct, or by typing the keyword (i.e.
2482 first word of menu entry not in parenthesis) and `\\[vhdl-electric-space]'.
2483 The following abbreviations can also be used:
2484 arch, attr, cond, conf, comp, cons, func, inst, pack, sig, var.
2485 Template styles can be customized in customization group `vhdl-electric'
2486 \(see CUSTOMIZATION).
2488 - HEADER INSERTION: A file header can be inserted by `\\[vhdl-template-header]'. A
2489 file footer (template at the end of the file) can be inserted by
2490 `\\[vhdl-template-footer]'. See customization group `vhdl-header'.
2492 - STUTTERING: Double striking of some keys inserts cumbersome VHDL syntax
2493 elements. Stuttering can be disabled (enabled) by typing `\\[vhdl-stutter-mode]' or by
2494 variable `vhdl-stutter-mode'. Enabled stuttering is indicated by `/s' in
2495 the modeline. The stuttering keys and their effects are:
2496 ;; --> \" : \" [ --> ( -- --> comment
2497 ;;; --> \" := \" [[ --> [ --CR --> comment-out code
2498 .. --> \" => \" ] --> ) --- --> horizontal line
2499 ,, --> \" <= \" ]] --> ] ---- --> display comment
2500 == --> \" == \" '' --> \\\"
2502 - WORD COMPLETION: Typing `\\[vhdl-electric-tab]' after a (not completed) word looks for a VHDL
2503 keyword or a word in the buffer that starts alike, inserts it and adjusts
2504 case. Re-typing `\\[vhdl-electric-tab]' toggles through alternative word completions.
2505 This also works in the minibuffer (i.e. in template generator prompts).
2506 Typing `\\[vhdl-electric-tab]' after `(' looks for and inserts complete parenthesized
2507 expressions (e.g. for array index ranges). All keywords as well as standard
2508 types and subprograms of VHDL have predefined abbreviations (e.g. type \"std\"
2509 and `\\[vhdl-electric-tab]' will toggle through all standard types beginning with \"std\").
2511 Typing `\\[vhdl-electric-tab]' after a non-word character indents the line if at the beginning
2512 of a line (i.e. no preceding non-blank characters),and inserts a tabulator
2513 stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator stop.
2515 - COMMENTS:
2516 `--' puts a single comment.
2517 `---' draws a horizontal line for separating code segments.
2518 `----' inserts a display comment, i.e. two horizontal lines with a
2519 comment in between.
2520 `--CR' comments out code on that line. Re-hitting CR comments out
2521 following lines.
2522 `\\[vhdl-comment-uncomment-region]' comments out a region if not commented out,
2523 uncomments a region if already commented out.
2525 You are prompted for comments after object definitions (i.e. signals,
2526 variables, constants, ports) and after subprogram and process specifications
2527 if variable `vhdl-prompt-for-comments' is non-nil. Comments are
2528 automatically inserted as additional labels (e.g. after begin statements) and
2529 as help comments if `vhdl-self-insert-comments' is non-nil.
2530 Inline comments (i.e. comments after a piece of code on the same line) are
2531 indented at least to `vhdl-inline-comment-column'. Comments go at maximum to
2532 `vhdl-end-comment-column'. `\\[vhdl-electric-return]' after a space in a comment will open a
2533 new comment line. Typing beyond `vhdl-end-comment-column' in a comment
2534 automatically opens a new comment line. `\\[fill-paragraph]' re-fills
2535 multi-line comments.
2537 - INDENTATION: `\\[vhdl-electric-tab]' indents a line if at the beginning of the line.
2538 The amount of indentation is specified by variable `vhdl-basic-offset'.
2539 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB' if variable
2540 `vhdl-intelligent-tab' is nil). Indentation can be done for an entire region
2541 \(`\\[vhdl-indent-region]') or buffer (menu). Argument and port lists are indented normally
2542 \(nil) or relative to the opening parenthesis (non-nil) according to variable
2543 `vhdl-argument-list-indent'. If variable `vhdl-indent-tabs-mode' is nil,
2544 spaces are used instead of tabs. `\\[tabify]' and `\\[untabify]' allow
2545 to convert spaces to tabs and vice versa.
2547 - ALIGNMENT: The alignment functions align operators, keywords, and inline
2548 comment to beautify argument lists, port maps, etc. `\\[vhdl-align-group]' aligns a group
2549 of consecutive lines separated by blank lines. `\\[vhdl-align-noindent-region]' aligns an
2550 entire region. If variable `vhdl-align-groups' is non-nil, groups of code
2551 lines separated by empty lines are aligned individually. `\\[vhdl-align-inline-comment-group]' aligns
2552 inline comments for a group of lines, and `\\[vhdl-align-inline-comment-region]' for a region.
2553 Some templates are automatically aligned after generation if custom variable
2554 `vhdl-auto-align' is non-nil.
2555 `\\[vhdl-fixup-whitespace-region]' fixes up whitespace in a region. That is, operator symbols
2556 are surrounded by one space, and multiple spaces are eliminated.
2558 - PORT TRANSLATION: Generic and port clauses from entity or component
2559 declarations can be copied (`\\[vhdl-port-copy]') and pasted as entity and
2560 component declarations, as component instantiations and corresponding
2561 internal constants and signals, as a generic map with constants as actual
2562 parameters, and as a test bench (menu).
2563 A clause with several generic/port names on the same line can be flattened
2564 (`\\[vhdl-port-flatten]') so that only one name per line exists. Names for actual
2565 ports, instances, test benches, and design-under-test instances can be
2566 derived from existing names according to variables `vhdl-...-name'.
2567 Variables `vhdl-testbench-...' allow the insertion of additional templates
2568 into a test bench. New files are created for the test bench entity and
2569 architecture according to variable `vhdl-testbench-create-files'.
2570 See customization group `vhdl-port'.
2572 - TEST BENCH GENERATION: See PORT TRANSLATION.
2574 - KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in
2575 menu).
2577 - VHDL MENU: All commands can be invoked from the VHDL menu.
2579 - FILE BROWSER: The speedbar allows browsing of directories and file contents.
2580 It can be accessed from the VHDL menu and is automatically opened if
2581 variable `vhdl-speedbar' is non-nil.
2582 In speedbar, open files and directories with `mouse-2' on the name and
2583 browse/rescan their contents with `mouse-2'/`S-mouse-2' on the `+'.
2585 - DESIGN HIERARCHY BROWSER: The speedbar can also be used for browsing the
2586 hierarchy of design units contained in the source files of the current
2587 directory or in the source files/directories specified for a project (see
2588 variable `vhdl-project-alist').
2589 The speedbar can be switched between file and hierarchy browsing mode in the
2590 VHDL menu or by typing `f' and `h' in speedbar.
2591 In speedbar, open design units with `mouse-2' on the name and browse their
2592 hierarchy with `mouse-2' on the `+'. The hierarchy can be rescanned and
2593 ports directly be copied from entities by using the speedbar menu.
2595 - PROJECTS: Projects can be defined in variable `vhdl-project-alist' and a
2596 current project be selected using variable `vhdl-project' (permanently) or
2597 from the menu (temporarily). For each project, a title string (for the file
2598 headers) and source files/directories (for the hierarchy browser) can be
2599 specified.
2601 - SPECIAL MENUES: As an alternative to the speedbar, an index menu can
2602 be added (set variable `vhdl-index-menu' to non-nil) or made accessible
2603 as a mouse menu (e.g. add \"(global-set-key '[S-down-mouse-3] 'imenu)\" to
2604 your start-up file) for browsing the file contents. Also, a source file menu
2605 can be added (set variable `vhdl-source-file-menu' to non-nil) for browsing
2606 the current directory for VHDL source files.
2608 - SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
2609 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be used is
2610 specified by variable `vhdl-compiler'. The available compilers are listed
2611 in variable `vhdl-compiler-alist' including all required compilation command,
2612 destination directory, and error message syntax information. New compilers
2613 can be added. Additional compile command options can be set in variable
2614 `vhdl-compiler-options'.
2615 An entire hierarchy of source files can be compiled by the `make' command
2616 \(menu, `\\[vhdl-make]'). This only works if an appropriate Makefile exists.
2617 The make command itself as well as a command to generate a Makefile can also
2618 be specified in variable `vhdl-compiler-alist'.
2620 - VHDL STANDARDS: The VHDL standards to be used are specified in variable
2621 `vhdl-standard'. Available standards are: VHDL'87/'93, VHDL-AMS,
2622 Math Packages.
2624 - KEYWORD CASE: Lower and upper case for keywords and standardized types,
2625 attributes, and enumeration values is supported. If the variable
2626 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in lower
2627 case and are converted into upper case automatically (not for types,
2628 attributes, and enumeration values). The case of keywords, types,
2629 attributes,and enumeration values can be fixed for an entire region (menu)
2630 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
2631 `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
2633 - HIGHLIGHTING (fontification): Keywords and standardized types, attributes,
2634 enumeration values, and function names (controlled by variable
2635 `vhdl-highlight-keywords'), as well as comments, strings, and template
2636 prompts are highlighted using different colors. Unit, subprogram, signal,
2637 variable, constant, parameter and generic/port names in declarations as well
2638 as labels are highlighted if variable `vhdl-highlight-names' is non-nil.
2640 Additional reserved words or words with a forbidden syntax (e.g. words that
2641 should be avoided) can be specified in variable `vhdl-forbidden-words' or
2642 `vhdl-forbidden-syntax' and be highlighted in a warning color (variable
2643 `vhdl-highlight-forbidden-words'). Verilog keywords are highlighted as
2644 forbidden words if variable `vhdl-highlight-verilog-keywords' is non-nil.
2646 Words with special syntax can be highlighted by specifying their syntax and
2647 color in variable `vhdl-special-syntax-alist' and by setting variable
2648 `vhdl-highlight-special-words' to non-nil. This allows to establish some
2649 naming conventions (e.g. to distinguish different kinds of signals or other
2650 objects by using name suffices) and to support them visually.
2652 Variable `vhdl-highlight-case-sensitive' can be set to non-nil in order to
2653 support case-sensitive highlighting. However, keywords are then only
2654 highlighted if written in lower case.
2656 Code between \"translate_off\" and \"translate_on\" pragmas is highlighted
2657 using a different background color if variable `vhdl-highlight-translate-off'
2658 is non-nil.
2660 All colors can be customized by command `\\[customize-face]'.
2661 For highlighting of matching parenthesis, see customization group
2662 `paren-showing' (`\\[customize-group]').
2664 - USER MODELS: VHDL models (templates) can be specified by the user and made
2665 accessible in the menu, through key bindings (`C-c C-m ...'), or by keyword
2666 electrification. See custom variable `vhdl-model-alist'.
2668 - HIDE/SHOW: The code of entire VHDL design units can be hidden using the
2669 `Hide/Show' menu or by pressing `S-mouse-2' within the code (variable
2670 `vhdl-hideshow-menu').
2672 - PRINTING: Postscript printing with different faces (an optimized set of
2673 faces is used if `vhdl-print-customize-faces' is non-nil) or colors
2674 \(if `ps-print-color-p' is non-nil) is possible using the standard Emacs
2675 postscript printing commands. Variable `vhdl-print-two-column' defines
2676 appropriate default settings for nice landscape two-column printing. The
2677 paper format can be set by variable `ps-paper-type'. Do not forget to
2678 switch `ps-print-color-p' to nil for printing on black-and-white printers.
2680 - CUSTOMIZATION: All variables can easily be customized using the `Customize'
2681 menu entry or `\\[customize-option]' (`\\[customize-group]' for groups).
2682 Some customizations only take effect after some action (read the NOTE in
2683 the variable documentation). Customization can also be done globally (i.e.
2684 site-wide, read the INSTALL file).
2686 - FILE EXTENSIONS: As default, files with extensions \".vhd\" and \".vhdl\" are
2687 automatically recognized as VHDL source files. To add an extension \".xxx\",
2688 add the following line to your Emacs start-up file (`.emacs'):
2689 \(setq auto-mode-alist (cons '(\"\\\\.xxx\\\\'\" . vhdl-mode) auto-mode-alist))
2691 - HINTS:
2692 - Type `\\[keyboard-quit] \\[keyboard-quit]' to interrupt long operations or if Emacs hangs.
2695 Maintenance:
2696 ------------
2698 To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
2699 Add a description of the problem and include a reproducible test case.
2701 Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
2703 The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
2704 The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
2705 You are kindly invited to participate in beta testing. Subscribe to above
2706 mailing lists by sending an email to <vhdl-mode@geocities.com>.
2708 VHDL Mode is officially distributed on the Emacs VHDL Mode Home Page
2709 <http://www.geocities.com/SiliconValley/Peaks/8287>, where the latest
2710 version and release notes can be found.
2713 Bugs and Limitations:
2714 ---------------------
2716 - Re-indenting large regions or expressions can be slow.
2717 - Indentation bug in simultaneous if- and case-statements (VHDL-AMS).
2718 - Hideshow does not work under XEmacs.
2719 - Index menu and file tagging in speedbar do not work under XEmacs.
2720 - Parsing compilation error messages for Ikos and Viewlogic VHDL compilers
2721 does not work under XEmacs.
2724 The VHDL Mode Maintainers
2725 Reto Zimmermann and Rod Whitby
2727 Key bindings:
2728 -------------
2730 \\{vhdl-mode-map}"
2731 (interactive)
2732 (kill-all-local-variables)
2733 (setq major-mode 'vhdl-mode)
2734 (setq mode-name "VHDL")
2736 ;; set maps and tables
2737 (use-local-map vhdl-mode-map)
2738 (set-syntax-table vhdl-mode-syntax-table)
2739 (setq local-abbrev-table vhdl-mode-abbrev-table)
2741 ;; set local variable values
2742 (set (make-local-variable 'paragraph-start)
2743 "\\s-*\\(--+\\s-*$\\|[^ -]\\|$\\)")
2744 (set (make-local-variable 'paragraph-separate) paragraph-start)
2745 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
2746 (set (make-local-variable 'require-final-newline) t)
2747 (set (make-local-variable 'parse-sexp-ignore-comments) t)
2748 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
2749 (set (make-local-variable 'comment-start) "--")
2750 (set (make-local-variable 'comment-end) "")
2751 (set (make-local-variable 'comment-column) vhdl-inline-comment-column)
2752 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
2753 (set (make-local-variable 'comment-start-skip) "--+\\s-*")
2754 (set (make-local-variable 'comment-multi-line) nil)
2755 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
2756 (set (make-local-variable 'hippie-expand-only-buffers) '(vhdl-mode))
2757 (set (make-local-variable 'hippie-expand-verbose) nil)
2759 ;; setup the comment indent variable in a Emacs version portable way
2760 ;; ignore any byte compiler warnings you might get here
2761 (when (boundp 'comment-indent-function)
2762 (make-local-variable 'comment-indent-function)
2763 (setq comment-indent-function 'vhdl-comment-indent))
2765 ;; initialize font locking
2766 (require 'font-lock)
2767 (set (make-local-variable 'font-lock-defaults)
2768 (list
2769 'vhdl-font-lock-keywords nil
2770 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
2771 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
2772 (set (make-local-variable 'font-lock-support-mode) 'lazy-lock-mode)
2773 (set (make-local-variable 'lazy-lock-defer-contextually) nil)
2774 (set (make-local-variable 'lazy-lock-defer-on-the-fly) t)
2775 ; (set (make-local-variable 'lazy-lock-defer-time) 0.1)
2776 (set (make-local-variable 'lazy-lock-defer-on-scrolling) t)
2777 (turn-on-font-lock)
2779 ;; variables for source file compilation
2780 (require 'compile)
2781 (set (make-local-variable 'compilation-error-regexp-alist) nil)
2782 (set (make-local-variable 'compilation-file-regexp-alist) nil)
2784 ;; add index menu
2785 (vhdl-index-menu-init)
2786 ;; add source file menu
2787 (if vhdl-source-file-menu (vhdl-add-source-files-menu))
2788 ;; add VHDL menu
2789 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2790 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2791 "Menu keymap for VHDL Mode." vhdl-mode-menu-list)
2792 ;; initialize hideshow and add menu
2793 (make-local-variable 'hs-minor-mode-hook)
2794 (vhdl-hideshow-init)
2795 (run-hooks 'menu-bar-update-hook)
2797 ;; add speedbar
2798 (when (fboundp 'speedbar)
2799 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
2800 (progn
2801 (when (and vhdl-speedbar (not (and (boundp 'speedbar-frame)
2802 (frame-live-p speedbar-frame))))
2803 (speedbar-frame-mode 1)
2804 (select-frame speedbar-attached-frame)))
2805 (error (vhdl-add-warning "Before using Speedbar, install included `speedbar.el' patch"))))
2807 ;; miscellaneous
2808 (vhdl-ps-print-init)
2809 (vhdl-modify-date-init)
2810 (vhdl-mode-line-update)
2811 (message "VHDL Mode %s. Type C-c C-h for documentation."
2812 vhdl-version)
2813 (vhdl-print-warnings)
2815 ;; run hooks
2816 (run-hooks 'vhdl-mode-hook))
2818 (defun vhdl-activate-customizations ()
2819 "Activate all customizations on local variables."
2820 (interactive)
2821 (vhdl-mode-map-init)
2822 (use-local-map vhdl-mode-map)
2823 (set-syntax-table vhdl-mode-syntax-table)
2824 (setq comment-column vhdl-inline-comment-column)
2825 (setq end-comment-column vhdl-end-comment-column)
2826 (vhdl-modify-date-init)
2827 (vhdl-update-mode-menu)
2828 (vhdl-hideshow-init)
2829 (run-hooks 'menu-bar-update-hook)
2830 (vhdl-mode-line-update))
2832 (defun vhdl-modify-date-init ()
2833 "Add/remove hook for modifying date when buffer is saved."
2834 (if vhdl-modify-date-on-saving
2835 (add-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)
2836 (remove-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)))
2839 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2840 ;;; Documentation
2841 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2843 (defvar vhdl-doc-keywords nil
2844 "Reserved words in VHDL:
2846 VHDL'93 (IEEE Std 1076-1993):
2847 `vhdl-93-keywords' : keywords
2848 `vhdl-93-types' : standardized types
2849 `vhdl-93-attributes' : standardized attributes
2850 `vhdl-93-enum-values' : standardized enumeration values
2851 `vhdl-93-functions' : standardized functions
2852 `vhdl-93-packages' : standardized packages and libraries
2854 VHDL-AMS (IEEE Std 1076.1):
2855 `vhdl-ams-keywords' : keywords
2856 `vhdl-ams-types' : standardized types
2857 `vhdl-ams-attributes' : standardized attributes
2858 `vhdl-ams-enum-values' : standardized enumeration values
2859 `vhdl-ams-functions' : standardized functions
2861 Math Packages (IEEE Std 1076.2):
2862 `vhdl-math-types' : standardized types
2863 `vhdl-math-constants' : standardized constants
2864 `vhdl-math-functions' : standardized functions
2865 `vhdl-math-packages' : standardized packages
2867 Forbidden words:
2868 `vhdl-verilog-keywords' : Verilog reserved words
2870 NOTE: click `mouse-2' on variable names above (not in XEmacs).")
2872 (defvar vhdl-doc-coding-style nil
2873 "For VHDL coding style and naming convention guidelines, see the following
2874 references:
2876 \[1] Ben Cohen.
2877 \"VHDL Coding Styles and Methodologies\".
2878 Kluwer Academic Publishers, 1999.
2879 http://members.aol.com/vhdlcohen/vhdl/
2881 \[2] Michael Keating and Pierre Bricaud.
2882 \"Reuse Methodology Manual\".
2883 Kluwer Academic Publishers, 1998.
2884 http://www.synopsys.com/products/reuse/rmm.html
2886 \[3] European Space Agency.
2887 \"VHDL Modelling Guidelines\".
2888 ftp://ftp.estec.esa.nl/pub/vhdl/doc/ModelGuide.{pdf,ps}
2890 Use variables `vhdl-highlight-special-words' and `vhdl-special-syntax-alist'
2891 to visually support naming conventions.")
2893 (defun vhdl-doc-variable (variable)
2894 "Display VARIABLE's documentation in *Help* buffer."
2895 (interactive)
2896 (with-output-to-temp-buffer "*Help*"
2897 (princ (documentation-property variable 'variable-documentation))
2898 (unless (string-match "XEmacs" emacs-version)
2899 (help-setup-xref (list #'vhdl-doc-variable variable) (interactive-p)))
2900 (save-excursion
2901 (set-buffer standard-output)
2902 (help-mode))
2903 (print-help-return-message)))
2905 (defun vhdl-doc-mode ()
2906 "Display VHDL mode documentation in *Help* buffer."
2907 (interactive)
2908 (with-output-to-temp-buffer "*Help*"
2909 (princ mode-name)
2910 (princ " mode:\n")
2911 (princ (documentation 'vhdl-mode))
2912 (unless (string-match "XEmacs" emacs-version)
2913 (help-setup-xref (list #'vhdl-doc-mode) (interactive-p)))
2914 (save-excursion
2915 (set-buffer standard-output)
2916 (help-mode))
2917 (print-help-return-message)))
2920 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2921 ;;; Keywords and standardized words
2922 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2924 (defconst vhdl-93-keywords
2926 "abs" "access" "after" "alias" "all" "and" "architecture" "array"
2927 "assert" "attribute"
2928 "begin" "block" "body" "buffer" "bus"
2929 "case" "component" "configuration" "constant"
2930 "disconnect" "downto"
2931 "else" "elsif" "end" "entity" "exit"
2932 "file" "for" "function"
2933 "generate" "generic" "group" "guarded"
2934 "if" "impure" "in" "inertial" "inout" "is"
2935 "label" "library" "linkage" "literal" "loop"
2936 "map" "mod"
2937 "nand" "new" "next" "nor" "not" "null"
2938 "of" "on" "open" "or" "others" "out"
2939 "package" "port" "postponed" "procedure" "process" "pure"
2940 "range" "record" "register" "reject" "rem" "report" "return"
2941 "rol" "ror"
2942 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
2943 "then" "to" "transport" "type"
2944 "unaffected" "units" "until" "use"
2945 "variable"
2946 "wait" "when" "while" "with"
2947 "xnor" "xor"
2949 "List of VHDL'93 keywords.")
2951 (defconst vhdl-ams-keywords
2953 "across" "break" "limit" "nature" "noise" "procedural" "quantity"
2954 "reference" "spectrum" "subnature" "terminal" "through"
2955 "tolerance"
2957 "List of VHDL-AMS keywords.")
2959 (defconst vhdl-verilog-keywords
2961 "`define" "`else" "`endif" "`ifdef" "`include" "`timescale" "`undef"
2962 "always" "and" "assign" "begin" "buf" "bufif0" "bufif1"
2963 "case" "casex" "casez" "cmos" "deassign" "default" "defparam" "disable"
2964 "edge" "else" "end" "endattribute" "endcase" "endfunction" "endmodule"
2965 "endprimitive" "endspecify" "endtable" "endtask" "event"
2966 "for" "force" "forever" "fork" "function"
2967 "highz0" "highz1" "if" "initial" "inout" "input" "integer" "join" "large"
2968 "macromodule" "makefile" "medium" "module"
2969 "nand" "negedge" "nmos" "nor" "not" "notif0" "notif1" "or" "output"
2970 "parameter" "pmos" "posedge" "primitive" "pull0" "pull1" "pulldown"
2971 "pullup"
2972 "rcmos" "real" "realtime" "reg" "release" "repeat" "rnmos" "rpmos" "rtran"
2973 "rtranif0" "rtranif1"
2974 "scalared" "signed" "small" "specify" "specparam" "strength" "strong0"
2975 "strong1" "supply" "supply0" "supply1"
2976 "table" "task" "time" "tran" "tranif0" "tranif1" "tri" "tri0" "tri1"
2977 "triand" "trior" "trireg"
2978 "vectored" "wait" "wand" "weak0" "weak1" "while" "wire" "wor" "xnor" "xor"
2980 "List of Verilog keywords as candidate for additional reserved words.")
2982 (defconst vhdl-93-types
2984 "boolean" "bit" "bit_vector" "character" "severity_level" "integer"
2985 "real" "time" "natural" "positive" "string" "line" "text" "side"
2986 "unsigned" "signed" "delay_length" "file_open_kind" "file_open_status"
2987 "std_logic" "std_logic_vector"
2988 "std_ulogic" "std_ulogic_vector"
2990 "List of VHDL'93 standardized types.")
2992 (defconst vhdl-ams-types
2994 "domain_type" "real_vector"
2996 "List of VHDL-AMS standardized types.")
2998 (defconst vhdl-math-types
3000 "complex" "complex_polar"
3002 "List of Math Packages standardized types.")
3004 (defconst vhdl-93-attributes
3006 "base" "left" "right" "high" "low" "pos" "val" "succ"
3007 "pred" "leftof" "rightof" "range" "reverse_range"
3008 "length" "delayed" "stable" "quiet" "transaction"
3009 "event" "active" "last_event" "last_active" "last_value"
3010 "driving" "driving_value" "ascending" "value" "image"
3011 "simple_name" "instance_name" "path_name"
3012 "foreign"
3014 "List of VHDL'93 standardized attributes.")
3016 (defconst vhdl-ams-attributes
3018 "across" "through"
3019 "reference" "contribution" "tolerance"
3020 "dot" "integ" "delayed" "above" "zoh" "ltf" "ztf"
3021 "ramp" "slew"
3023 "List of VHDL-AMS standardized attributes.")
3025 (defconst vhdl-93-enum-values
3027 "true" "false"
3028 "note" "warning" "error" "failure"
3029 "read_mode" "write_mode" "append_mode"
3030 "open_ok" "status_error" "name_error" "mode_error"
3031 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
3032 "right" "left"
3034 "List of VHDL'93 standardized enumeration values.")
3036 (defconst vhdl-ams-enum-values
3038 "quiescent_domain" "time_domain" "frequency_domain"
3040 "List of VHDL-AMS standardized enumeration values.")
3042 (defconst vhdl-math-constants
3044 "math_e" "math_1_over_e"
3045 "math_pi" "math_two_pi" "math_1_over_pi"
3046 "math_half_pi" "math_q_pi" "math_3_half_pi"
3047 "math_log_of_2" "math_log_of_10" "math_log2_of_e" "math_log10_of_e"
3048 "math_sqrt2" "math_sqrt1_2" "math_sqrt_pi"
3049 "math_deg_to_rad" "math_rad_to_deg"
3050 "cbase_1" "cbase_j" "czero"
3052 "List of Math Packages standardized constants.")
3054 (defconst vhdl-93-functions
3056 "now" "resolved" "rising_edge" "falling_edge"
3057 "read" "readline" "write" "writeline" "endfile"
3058 "resize" "is_X" "std_match"
3059 "shift_left" "shift_right" "rotate_left" "rotate_right"
3060 "to_unsigned" "to_signed" "to_integer"
3061 "to_stdLogicVector" "to_stdULogic" "to_stdULogicVector"
3062 "to_bit" "to_bitVector" "to_X01" "to_X01Z" "to_UX01" "to_01"
3063 "conv_unsigned" "conv_signed" "conv_integer" "conv_std_logic_vector"
3064 "shl" "shr" "ext" "sxt"
3066 "List of VHDL'93 standardized functions.")
3068 (defconst vhdl-ams-functions
3070 "frequency"
3072 "List of VHDL-AMS standardized functions.")
3074 (defconst vhdl-math-functions
3076 "sign" "ceil" "floor" "round" "trunc" "fmax" "fmin" "uniform"
3077 "sqrt" "cbrt" "exp" "log"
3078 "sin" "cos" "tan" "arcsin" "arccos" "arctan"
3079 "sinh" "cosh" "tanh" "arcsinh" "arccosh" "arctanh"
3080 "cmplx" "complex_to_polar" "polar_to_complex" "arg" "conj"
3082 "List of Math Packages standardized functions.")
3084 (defconst vhdl-93-packages
3086 "std_logic_1164" "numeric_std" "numeric_bit"
3087 "standard" "textio"
3088 "std_logic_arith" "std_logic_signed" "std_logic_unsigned"
3089 "std_logic_misc" "std_logic_textio"
3090 "ieee" "std" "work"
3092 "List of VHDL'93 standardized packages and libraries.")
3094 (defconst vhdl-math-packages
3096 "math_real" "math_complex"
3098 "List of Math Packages standardized packages and libraries.")
3100 (defvar vhdl-keywords nil
3101 "List of VHDL keywords.")
3103 (defvar vhdl-types nil
3104 "List of VHDL standardized types.")
3106 (defvar vhdl-attributes nil
3107 "List of VHDL standardized attributes.")
3109 (defvar vhdl-enum-values nil
3110 "List of VHDL standardized enumeration values.")
3112 (defvar vhdl-constants nil
3113 "List of VHDL standardized constants.")
3115 (defvar vhdl-functions nil
3116 "List of VHDL standardized functions.")
3118 (defvar vhdl-packages nil
3119 "List of VHDL standardized packages and libraries.")
3121 (defvar vhdl-reserved-words nil
3122 "List of additional reserved words.")
3124 (defvar vhdl-keywords-regexp nil
3125 "Regexp for VHDL keywords.")
3127 (defvar vhdl-types-regexp nil
3128 "Regexp for VHDL standardized types.")
3130 (defvar vhdl-attributes-regexp nil
3131 "Regexp for VHDL standardized attributes.")
3133 (defvar vhdl-enum-values-regexp nil
3134 "Regexp for VHDL standardized enumeration values.")
3136 (defvar vhdl-functions-regexp nil
3137 "Regexp for VHDL standardized functions.")
3139 (defvar vhdl-packages-regexp nil
3140 "Regexp for VHDL standardized packages and libraries.")
3142 (defvar vhdl-reserved-words-regexp nil
3143 "Regexp for additional reserved words.")
3145 (defun vhdl-words-init ()
3146 "Initialize reserved words."
3147 (setq vhdl-keywords
3148 (append vhdl-93-keywords
3149 (when (vhdl-standard-p 'ams) vhdl-ams-keywords)))
3150 (setq vhdl-types
3151 (append vhdl-93-types
3152 (when (vhdl-standard-p 'ams) vhdl-ams-types)
3153 (when (vhdl-standard-p 'math) vhdl-math-types)))
3154 (setq vhdl-attributes
3155 (append vhdl-93-attributes
3156 (when (vhdl-standard-p 'ams) vhdl-ams-attributes)))
3157 (setq vhdl-enum-values
3158 (append vhdl-93-enum-values
3159 (when (vhdl-standard-p 'ams) vhdl-ams-enum-values)))
3160 (setq vhdl-constants
3161 (append (when (vhdl-standard-p 'math) vhdl-math-constants)))
3162 (setq vhdl-functions
3163 (append vhdl-93-functions
3164 (when (vhdl-standard-p 'ams) vhdl-ams-functions)
3165 (when (vhdl-standard-p 'math) vhdl-math-functions)))
3166 (setq vhdl-packages
3167 (append vhdl-93-packages
3168 (when (vhdl-standard-p 'math) vhdl-math-packages)))
3169 (setq vhdl-reserved-words
3170 (append (when vhdl-highlight-forbidden-words vhdl-forbidden-words)
3171 (when vhdl-highlight-verilog-keywords vhdl-verilog-keywords)
3172 '("")))
3173 (setq vhdl-keywords-regexp
3174 (concat "\\<\\(" (regexp-opt vhdl-keywords) "\\)\\>"))
3175 (setq vhdl-types-regexp
3176 (concat "\\<\\(" (regexp-opt vhdl-types) "\\)\\>"))
3177 (setq vhdl-attributes-regexp
3178 (concat "\\<\\(" (regexp-opt vhdl-attributes) "\\)\\>"))
3179 (setq vhdl-enum-values-regexp
3180 (concat "\\<\\(" (regexp-opt vhdl-enum-values) "\\)\\>"))
3181 (setq vhdl-functions-regexp
3182 (concat "\\<\\(" (regexp-opt vhdl-functions) "\\)\\>"))
3183 (setq vhdl-packages-regexp
3184 (concat "\\<\\(" (regexp-opt vhdl-packages) "\\)\\>"))
3185 (setq vhdl-reserved-words-regexp
3186 (concat "\\<\\("
3187 (unless (equal vhdl-forbidden-syntax "")
3188 (concat vhdl-forbidden-syntax "\\|"))
3189 (regexp-opt vhdl-reserved-words)
3190 "\\)\\>"))
3191 (vhdl-abbrev-list-init))
3193 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3194 ;; Words to expand
3196 (defvar vhdl-abbrev-list nil
3197 "Predefined abbreviations for VHDL.")
3199 (defun vhdl-abbrev-list-init ()
3200 (setq vhdl-abbrev-list
3201 (append
3202 (list vhdl-upper-case-keywords) vhdl-keywords
3203 (list vhdl-upper-case-types) vhdl-types
3204 (list vhdl-upper-case-attributes) vhdl-attributes
3205 (list vhdl-upper-case-enum-values) vhdl-enum-values
3206 (list vhdl-upper-case-constants) vhdl-constants
3207 (list nil) vhdl-functions
3208 (list nil) vhdl-packages)))
3210 ;; initialize reserved words for VHDL Mode
3211 (vhdl-words-init)
3214 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3215 ;;; Syntax analysis and indentation
3216 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3218 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3219 ;; Syntax analysis
3221 ;; constant regular expressions for looking at various constructs
3223 (defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
3224 "Regexp describing a VHDL symbol.
3225 We cannot use just `word' syntax class since `_' cannot be in word
3226 class. Putting underscore in word class breaks forward word movement
3227 behavior that users are familiar with.")
3229 (defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
3230 "Regexp describing a case statement header key.")
3232 (defconst vhdl-label-key
3233 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
3234 "Regexp describing a VHDL label.")
3236 ;; Macro definitions:
3238 (defmacro vhdl-point (position)
3239 "Return the value of point at certain commonly referenced POSITIONs.
3240 POSITION can be one of the following symbols:
3242 bol -- beginning of line
3243 eol -- end of line
3244 bod -- beginning of defun
3245 boi -- back to indentation
3246 eoi -- last whitespace on line
3247 ionl -- indentation of next line
3248 iopl -- indentation of previous line
3249 bonl -- beginning of next line
3250 bopl -- beginning of previous line
3252 This function does not modify point or mark."
3253 (or (and (eq 'quote (car-safe position))
3254 (null (cdr (cdr position))))
3255 (error "Bad buffer position requested: %s" position))
3256 (setq position (nth 1 position))
3257 `(let ((here (point)))
3258 ,@(cond
3259 ((eq position 'bol) '((beginning-of-line)))
3260 ((eq position 'eol) '((end-of-line)))
3261 ((eq position 'bod) '((save-match-data
3262 (vhdl-beginning-of-defun))))
3263 ((eq position 'boi) '((back-to-indentation)))
3264 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
3265 ((eq position 'bonl) '((forward-line 1)))
3266 ((eq position 'bopl) '((forward-line -1)))
3267 ((eq position 'iopl)
3268 '((forward-line -1)
3269 (back-to-indentation)))
3270 ((eq position 'ionl)
3271 '((forward-line 1)
3272 (back-to-indentation)))
3273 (t (error "Unknown buffer position requested: %s" position))
3275 (prog1
3276 (point)
3277 (goto-char here))
3278 ;; workaround for an Emacs18 bug -- blech! Well, at least it
3279 ;; doesn't hurt for v19
3280 ,@nil
3283 (defmacro vhdl-safe (&rest body)
3284 "Safely execute BODY, return nil if an error occurred."
3285 `(condition-case nil
3286 (progn ,@body)
3287 (error nil)))
3289 (defmacro vhdl-add-syntax (symbol &optional relpos)
3290 "A simple macro to append the syntax in SYMBOL to the syntax list.
3291 Try to increase performance by using this macro."
3292 `(setq vhdl-syntactic-context
3293 (cons (cons ,symbol ,relpos) vhdl-syntactic-context)))
3295 (defmacro vhdl-has-syntax (symbol)
3296 "A simple macro to return check the syntax list.
3297 Try to increase performance by using this macro."
3298 `(assoc ,symbol vhdl-syntactic-context))
3300 ;; Syntactic element offset manipulation:
3302 (defun vhdl-read-offset (langelem)
3303 "Read new offset value for LANGELEM from minibuffer.
3304 Return a legal value only."
3305 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
3306 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
3307 (prompt "Offset: ")
3308 offset input interned)
3309 (while (not offset)
3310 (setq input (read-string prompt oldoff)
3311 offset (cond ((string-equal "+" input) '+)
3312 ((string-equal "-" input) '-)
3313 ((string-equal "++" input) '++)
3314 ((string-equal "--" input) '--)
3315 ((string-match "^-?[0-9]+$" input)
3316 (string-to-int input))
3317 ((fboundp (setq interned (intern input)))
3318 interned)
3319 ((boundp interned) interned)
3320 ;; error, but don't signal one, keep trying
3321 ;; to read an input value
3322 (t (ding)
3323 (setq prompt errmsg)
3324 nil))))
3325 offset))
3327 (defun vhdl-set-offset (symbol offset &optional add-p)
3328 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
3329 SYMBOL is the syntactic element symbol to change and OFFSET is the new
3330 offset for that syntactic element. Optional ADD says to add SYMBOL to
3331 `vhdl-offsets-alist' if it doesn't already appear there."
3332 (interactive
3333 (let* ((langelem
3334 (intern (completing-read
3335 (concat "Syntactic symbol to change"
3336 (if current-prefix-arg " or add" "")
3337 ": ")
3338 (mapcar
3339 (function
3340 (lambda (langelem)
3341 (cons (format "%s" (car langelem)) nil)))
3342 vhdl-offsets-alist)
3343 nil (not current-prefix-arg)
3344 ;; initial contents tries to be the last element
3345 ;; on the syntactic analysis list for the current
3346 ;; line
3347 (let* ((syntax (vhdl-get-syntactic-context))
3348 (len (length syntax))
3349 (ic (format "%s" (car (nth (1- len) syntax)))))
3352 (offset (vhdl-read-offset langelem)))
3353 (list langelem offset current-prefix-arg)))
3354 ;; sanity check offset
3355 (or (eq offset '+)
3356 (eq offset '-)
3357 (eq offset '++)
3358 (eq offset '--)
3359 (integerp offset)
3360 (fboundp offset)
3361 (boundp offset)
3362 (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
3363 offset))
3364 (let ((entry (assq symbol vhdl-offsets-alist)))
3365 (if entry
3366 (setcdr entry offset)
3367 (if add-p
3368 (setq vhdl-offsets-alist
3369 (cons (cons symbol offset) vhdl-offsets-alist))
3370 (error "%s is not a valid syntactic symbol" symbol))))
3371 (vhdl-keep-region-active))
3373 (defun vhdl-set-style (style &optional local)
3374 "Set `vhdl-mode' variables to use one of several different indentation styles.
3375 STYLE is a string representing the desired style and optional LOCAL is
3376 a flag which, if non-nil, means to make the style variables being
3377 changed buffer local, instead of the default, which is to set the
3378 global variables. Interactively, the flag comes from the prefix
3379 argument. The styles are chosen from the `vhdl-style-alist' variable."
3380 (interactive (list (completing-read "Use which VHDL indentation style? "
3381 vhdl-style-alist nil t)
3382 current-prefix-arg))
3383 (let ((vars (cdr (assoc style vhdl-style-alist))))
3384 (or vars
3385 (error "Invalid VHDL indentation style `%s'" style))
3386 ;; set all the variables
3387 (mapcar
3388 (function
3389 (lambda (varentry)
3390 (let ((var (car varentry))
3391 (val (cdr varentry)))
3392 (and local
3393 (make-local-variable var))
3394 ;; special case for vhdl-offsets-alist
3395 (if (not (eq var 'vhdl-offsets-alist))
3396 (set var val)
3397 ;; reset vhdl-offsets-alist to the default value first
3398 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
3399 ;; now set the langelems that are different
3400 (mapcar
3401 (function
3402 (lambda (langentry)
3403 (let ((langelem (car langentry))
3404 (offset (cdr langentry)))
3405 (vhdl-set-offset langelem offset)
3407 val))
3409 vars))
3410 (vhdl-keep-region-active))
3412 (defun vhdl-get-offset (langelem)
3413 "Get offset from LANGELEM which is a cons cell of the form:
3414 \(SYMBOL . RELPOS). The symbol is matched against
3415 vhdl-offsets-alist and the offset found there is either returned,
3416 or added to the indentation at RELPOS. If RELPOS is nil, then
3417 the offset is simply returned."
3418 (let* ((symbol (car langelem))
3419 (relpos (cdr langelem))
3420 (match (assq symbol vhdl-offsets-alist))
3421 (offset (cdr-safe match)))
3422 ;; offset can be a number, a function, a variable, or one of the
3423 ;; symbols + or -
3424 (cond
3425 ((not match)
3426 (if vhdl-strict-syntax-p
3427 (error "Don't know how to indent a %s" symbol)
3428 (setq offset 0
3429 relpos 0)))
3430 ((eq offset '+) (setq offset vhdl-basic-offset))
3431 ((eq offset '-) (setq offset (- vhdl-basic-offset)))
3432 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
3433 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
3434 ((and (not (numberp offset))
3435 (fboundp offset))
3436 (setq offset (funcall offset langelem)))
3437 ((not (numberp offset))
3438 (setq offset (eval offset)))
3440 (+ (if (and relpos
3441 (< relpos (vhdl-point 'bol)))
3442 (save-excursion
3443 (goto-char relpos)
3444 (current-column))
3446 offset)))
3448 ;; Syntactic support functions:
3450 ;; Returns `comment' if in a comment, `string' if in a string literal,
3451 ;; or nil if not in a literal at all. Optional LIM is used as the
3452 ;; backward limit of the search. If omitted, or nil, (point-min) is
3453 ;; used.
3455 (defun vhdl-in-literal (&optional lim)
3456 "Determine if point is in a VHDL literal."
3457 (save-excursion
3458 (let ((state (parse-partial-sexp (vhdl-point 'bol) (point))))
3459 (cond
3460 ((nth 3 state) 'string)
3461 ((nth 4 state) 'comment)
3462 (t nil)))))
3464 ;; This is the best we can do in Win-Emacs.
3465 (defun vhdl-win-il (&optional lim)
3466 "Determine if point is in a VHDL literal."
3467 (save-excursion
3468 (let* ((here (point))
3469 (state nil)
3470 (match nil)
3471 (lim (or lim (vhdl-point 'bod))))
3472 (goto-char lim )
3473 (while (< (point) here)
3474 (setq match
3475 (and (re-search-forward "--\\|[\"']"
3476 here 'move)
3477 (buffer-substring (match-beginning 0) (match-end 0))))
3478 (setq state
3479 (cond
3480 ;; no match
3481 ((null match) nil)
3482 ;; looking at the opening of a VHDL style comment
3483 ((string= "--" match)
3484 (if (<= here (progn (end-of-line) (point))) 'comment))
3485 ;; looking at the opening of a double quote string
3486 ((string= "\"" match)
3487 (if (not (save-restriction
3488 ;; this seems to be necessary since the
3489 ;; re-search-forward will not work without it
3490 (narrow-to-region (point) here)
3491 (re-search-forward
3492 ;; this regexp matches a double quote
3493 ;; which is preceded by an even number
3494 ;; of backslashes, including zero
3495 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
3496 'string))
3497 ;; looking at the opening of a single quote string
3498 ((string= "'" match)
3499 (if (not (save-restriction
3500 ;; see comments from above
3501 (narrow-to-region (point) here)
3502 (re-search-forward
3503 ;; this matches a single quote which is
3504 ;; preceded by zero or two backslashes.
3505 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
3506 here 'move)))
3507 'string))
3508 (t nil)))
3509 ) ; end-while
3510 state)))
3512 (and (string-match "Win-Emacs" emacs-version)
3513 (fset 'vhdl-in-literal 'vhdl-win-il))
3515 ;; Skipping of "syntactic whitespace". Syntactic whitespace is
3516 ;; defined as lexical whitespace or comments. Search no farther back
3517 ;; or forward than optional LIM. If LIM is omitted, (point-min) is
3518 ;; used for backward skipping, (point-max) is used for forward
3519 ;; skipping.
3521 (defun vhdl-forward-syntactic-ws (&optional lim)
3522 "Forward skip of syntactic whitespace."
3523 (save-restriction
3524 (let* ((lim (or lim (point-max)))
3525 (here lim)
3526 (hugenum (point-max)))
3527 (narrow-to-region lim (point))
3528 (while (/= here (point))
3529 (setq here (point))
3530 (forward-comment hugenum))
3533 ;; This is the best we can do in Win-Emacs.
3534 (defun vhdl-win-fsws (&optional lim)
3535 "Forward skip syntactic whitespace for Win-Emacs."
3536 (let ((lim (or lim (point-max)))
3537 stop)
3538 (while (not stop)
3539 (skip-chars-forward " \t\n\r\f" lim)
3540 (cond
3541 ;; vhdl comment
3542 ((looking-at "--") (end-of-line))
3543 ;; none of the above
3544 (t (setq stop t))
3545 ))))
3547 (and (string-match "Win-Emacs" emacs-version)
3548 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
3550 (defun vhdl-backward-syntactic-ws (&optional lim)
3551 "Backward skip over syntactic whitespace."
3552 (save-restriction
3553 (let* ((lim (or lim (point-min)))
3554 (here lim)
3555 (hugenum (- (point-max))))
3556 (if (< lim (point))
3557 (progn
3558 (narrow-to-region lim (point))
3559 (while (/= here (point))
3560 (setq here (point))
3561 (forward-comment hugenum)
3565 ;; This is the best we can do in Win-Emacs.
3566 (defun vhdl-win-bsws (&optional lim)
3567 "Backward skip syntactic whitespace for Win-Emacs."
3568 (let ((lim (or lim (vhdl-point 'bod)))
3569 stop)
3570 (while (not stop)
3571 (skip-chars-backward " \t\n\r\f" lim)
3572 (cond
3573 ;; vhdl comment
3574 ((eq (vhdl-in-literal lim) 'comment)
3575 (skip-chars-backward "^-" lim)
3576 (skip-chars-backward "-" lim)
3577 (while (not (or (and (= (following-char) ?-)
3578 (= (char-after (1+ (point))) ?-))
3579 (<= (point) lim)))
3580 (skip-chars-backward "^-" lim)
3581 (skip-chars-backward "-" lim)))
3582 ;; none of the above
3583 (t (setq stop t))
3584 ))))
3586 (and (string-match "Win-Emacs" emacs-version)
3587 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
3589 ;; Functions to help finding the correct indentation column:
3591 (defun vhdl-first-word (point)
3592 "If the keyword at POINT is at boi, then return (current-column) at
3593 that point, else nil."
3594 (save-excursion
3595 (and (goto-char point)
3596 (eq (point) (vhdl-point 'boi))
3597 (current-column))))
3599 (defun vhdl-last-word (point)
3600 "If the keyword at POINT is at eoi, then return (current-column) at
3601 that point, else nil."
3602 (save-excursion
3603 (and (goto-char point)
3604 (save-excursion (or (eq (progn (forward-sexp) (point))
3605 (vhdl-point 'eoi))
3606 (looking-at "\\s-*\\(--\\)?")))
3607 (current-column))))
3609 ;; Core syntactic evaluation functions:
3611 (defconst vhdl-libunit-re
3612 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
3614 (defun vhdl-libunit-p ()
3615 (and
3616 (save-excursion
3617 (forward-sexp)
3618 (skip-chars-forward " \t\n")
3619 (not (looking-at "is\\b[^_]")))
3620 (save-excursion
3621 (backward-sexp)
3622 (and (not (looking-at "use\\b[^_]"))
3623 (progn
3624 (forward-sexp)
3625 (vhdl-forward-syntactic-ws)
3626 (/= (following-char) ?:))))
3629 (defconst vhdl-defun-re
3630 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedural\\|procedure\\|function\\)\\b[^_]")
3632 (defun vhdl-defun-p ()
3633 (save-excursion
3634 (if (looking-at "block\\|process\\|procedural")
3635 ;; "block", "process", "procedural":
3636 (save-excursion
3637 (backward-sexp)
3638 (not (looking-at "end\\s-+\\w")))
3639 ;; "architecture", "configuration", "entity",
3640 ;; "package", "procedure", "function":
3641 t)))
3643 (defun vhdl-corresponding-defun ()
3644 "If the word at the current position corresponds to a \"defun\"
3645 keyword, then return a string that can be used to find the
3646 corresponding \"begin\" keyword, else return nil."
3647 (save-excursion
3648 (and (looking-at vhdl-defun-re)
3649 (vhdl-defun-p)
3650 (if (looking-at "block\\|process\\|procedural")
3651 ;; "block", "process". "procedural:
3652 (buffer-substring (match-beginning 0) (match-end 0))
3653 ;; "architecture", "configuration", "entity", "package",
3654 ;; "procedure", "function":
3655 "is"))))
3657 (defconst vhdl-begin-fwd-re
3658 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
3659 "A regular expression for searching forward that matches all known
3660 \"begin\" keywords.")
3662 (defconst vhdl-begin-bwd-re
3663 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b[^_]"
3664 "A regular expression for searching backward that matches all known
3665 \"begin\" keywords.")
3667 (defun vhdl-begin-p (&optional lim)
3668 "Return t if we are looking at a real \"begin\" keyword.
3669 Assumes that the caller will make sure that we are looking at
3670 vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
3671 the middle of an identifier that just happens to contain a \"begin\"
3672 keyword."
3673 (cond
3674 ;; "[architecture|case|configuration|entity|package|
3675 ;; procedure|function] ... is":
3676 ((and (looking-at "i")
3677 (save-excursion
3678 ;; Skip backward over first sexp (needed to skip over a
3679 ;; procedure interface list, and is harmless in other
3680 ;; situations). Note that we need "return" in the
3681 ;; following search list so that we don't run into
3682 ;; semicolons in the function interface list.
3683 (backward-sexp)
3684 (let (foundp)
3685 (while (and (not foundp)
3686 (re-search-backward
3687 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|procedural\\|block\\)\\b[^_]"
3688 lim 'move))
3689 (if (or (= (preceding-char) ?_)
3690 (vhdl-in-literal lim))
3691 (backward-char)
3692 (setq foundp t))))
3693 (and (/= (following-char) ?\;)
3694 (not (looking-at "is\\|begin\\|process\\|procedural\\|block")))))
3696 ;; "begin", "then":
3697 ((looking-at "be\\|t")
3699 ;; "else":
3700 ((and (looking-at "e")
3701 ;; make sure that the "else" isn't inside a
3702 ;; conditional signal assignment.
3703 (save-excursion
3704 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3705 (or (eq (following-char) ?\;)
3706 (eq (point) lim))))
3708 ;; "block", "generate", "loop", "process", "procedural",
3709 ;; "units", "record":
3710 ((and (looking-at "bl\\|[glpur]")
3711 (save-excursion
3712 (backward-sexp)
3713 (not (looking-at "end\\s-+\\w"))))
3715 ;; "component":
3716 ((and (looking-at "c")
3717 (save-excursion
3718 (backward-sexp)
3719 (not (looking-at "end\\s-+\\w")))
3720 ;; look out for the dreaded entity class in an attribute
3721 (save-excursion
3722 (vhdl-backward-syntactic-ws lim)
3723 (/= (preceding-char) ?:)))
3725 ;; "for" (inside configuration declaration):
3726 ((and (looking-at "f")
3727 (save-excursion
3728 (backward-sexp)
3729 (not (looking-at "end\\s-+\\w")))
3730 (vhdl-has-syntax 'configuration))
3734 (defun vhdl-corresponding-mid (&optional lim)
3735 (cond
3736 ((looking-at "is\\|block\\|generate\\|process\\|procedural")
3737 "begin")
3738 ((looking-at "then")
3739 "<else>")
3741 "end")))
3743 (defun vhdl-corresponding-end (&optional lim)
3744 "If the word at the current position corresponds to a \"begin\"
3745 keyword, then return a vector containing enough information to find
3746 the corresponding \"end\" keyword, else return nil. The keyword to
3747 search forward for is aref 0. The column in which the keyword must
3748 appear is aref 1 or nil if any column is suitable.
3749 Assumes that the caller will make sure that we are not in the middle
3750 of an identifier that just happens to contain a \"begin\" keyword."
3751 (save-excursion
3752 (and (looking-at vhdl-begin-fwd-re)
3753 (/= (preceding-char) ?_)
3754 (not (vhdl-in-literal lim))
3755 (vhdl-begin-p lim)
3756 (cond
3757 ;; "is", "generate", "loop":
3758 ((looking-at "[igl]")
3759 (vector "end"
3760 (and (vhdl-last-word (point))
3761 (or (vhdl-first-word (point))
3762 (save-excursion
3763 (vhdl-beginning-of-statement-1 lim)
3764 (vhdl-backward-skip-label lim)
3765 (vhdl-first-word (point)))))))
3766 ;; "begin", "else", "for":
3767 ((looking-at "be\\|[ef]")
3768 (vector "end"
3769 (and (vhdl-last-word (point))
3770 (or (vhdl-first-word (point))
3771 (save-excursion
3772 (vhdl-beginning-of-statement-1 lim)
3773 (vhdl-backward-skip-label lim)
3774 (vhdl-first-word (point)))))))
3775 ;; "component", "units", "record":
3776 ((looking-at "[cur]")
3777 ;; The first end found will close the block
3778 (vector "end" nil))
3779 ;; "block", "process", "procedural":
3780 ((looking-at "bl\\|p")
3781 (vector "end"
3782 (or (vhdl-first-word (point))
3783 (save-excursion
3784 (vhdl-beginning-of-statement-1 lim)
3785 (vhdl-backward-skip-label lim)
3786 (vhdl-first-word (point))))))
3787 ;; "then":
3788 ((looking-at "t")
3789 (vector "elsif\\|else\\|end\\s-+if"
3790 (and (vhdl-last-word (point))
3791 (or (vhdl-first-word (point))
3792 (save-excursion
3793 (vhdl-beginning-of-statement-1 lim)
3794 (vhdl-backward-skip-label lim)
3795 (vhdl-first-word (point)))))))
3796 ))))
3798 (defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
3800 (defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
3802 (defun vhdl-end-p (&optional lim)
3803 "Return t if we are looking at a real \"end\" keyword.
3804 Assumes that the caller will make sure that we are looking at
3805 vhdl-end-fwd-re, and are not inside a literal, and that we are not in
3806 the middle of an identifier that just happens to contain an \"end\"
3807 keyword."
3808 (or (not (looking-at "else"))
3809 ;; make sure that the "else" isn't inside a conditional signal
3810 ;; assignment.
3811 (save-excursion
3812 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3813 (or (eq (following-char) ?\;)
3814 (eq (point) lim)))))
3816 (defun vhdl-corresponding-begin (&optional lim)
3817 "If the word at the current position corresponds to an \"end\"
3818 keyword, then return a vector containing enough information to find
3819 the corresponding \"begin\" keyword, else return nil. The keyword to
3820 search backward for is aref 0. The column in which the keyword must
3821 appear is aref 1 or nil if any column is suitable. The supplementary
3822 keyword to search forward for is aref 2 or nil if this is not
3823 required. If aref 3 is t, then the \"begin\" keyword may be found in
3824 the middle of a statement.
3825 Assumes that the caller will make sure that we are not in the middle
3826 of an identifier that just happens to contain an \"end\" keyword."
3827 (save-excursion
3828 (let (pos)
3829 (if (and (looking-at vhdl-end-fwd-re)
3830 (not (vhdl-in-literal lim))
3831 (vhdl-end-p lim))
3832 (if (looking-at "el")
3833 ;; "else", "elsif":
3834 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
3835 ;; "end ...":
3836 (setq pos (point))
3837 (forward-sexp)
3838 (skip-chars-forward " \t\n")
3839 (cond
3840 ;; "end if":
3841 ((looking-at "if\\b[^_]")
3842 (vector "else\\|elsif\\|if"
3843 (vhdl-first-word pos)
3844 "else\\|then" nil))
3845 ;; "end component":
3846 ((looking-at "component\\b[^_]")
3847 (vector (buffer-substring (match-beginning 1)
3848 (match-end 1))
3849 (vhdl-first-word pos)
3850 nil nil))
3851 ;; "end units", "end record":
3852 ((looking-at "\\(units\\|record\\)\\b[^_]")
3853 (vector (buffer-substring (match-beginning 1)
3854 (match-end 1))
3855 (vhdl-first-word pos)
3856 nil t))
3857 ;; "end block", "end process", "end procedural":
3858 ((looking-at "\\(block\\|process\\|procedural\\)\\b[^_]")
3859 (vector "begin" (vhdl-first-word pos) nil nil))
3860 ;; "end case":
3861 ((looking-at "case\\b[^_]")
3862 (vector "case" (vhdl-first-word pos) "is" nil))
3863 ;; "end generate":
3864 ((looking-at "generate\\b[^_]")
3865 (vector "generate\\|for\\|if"
3866 (vhdl-first-word pos)
3867 "generate" nil))
3868 ;; "end loop":
3869 ((looking-at "loop\\b[^_]")
3870 (vector "loop\\|while\\|for"
3871 (vhdl-first-word pos)
3872 "loop" nil))
3873 ;; "end for" (inside configuration declaration):
3874 ((looking-at "for\\b[^_]")
3875 (vector "for" (vhdl-first-word pos) nil nil))
3876 ;; "end [id]":
3878 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
3879 (vhdl-first-word pos)
3880 ;; return an alist of (statement . keyword) mappings
3882 ;; "begin ... end [id]":
3883 ("begin" . nil)
3884 ;; "architecture ... is ... begin ... end [id]":
3885 ("architecture" . "is")
3886 ;; "configuration ... is ... end [id]":
3887 ("configuration" . "is")
3888 ;; "entity ... is ... end [id]":
3889 ("entity" . "is")
3890 ;; "package ... is ... end [id]":
3891 ("package" . "is")
3892 ;; "procedure ... is ... begin ... end [id]":
3893 ("procedure" . "is")
3894 ;; "function ... is ... begin ... end [id]":
3895 ("function" . "is")
3897 nil))
3898 ))) ; "end ..."
3901 (defconst vhdl-leader-re
3902 "\\b\\(block\\|component\\|process\\|procedural\\|for\\)\\b[^_]")
3904 (defun vhdl-end-of-leader ()
3905 (save-excursion
3906 (cond ((looking-at "block\\|process\\|procedural")
3907 (if (save-excursion
3908 (forward-sexp)
3909 (skip-chars-forward " \t\n")
3910 (= (following-char) ?\())
3911 (forward-sexp 2)
3912 (forward-sexp))
3913 (point))
3914 ((looking-at "component")
3915 (forward-sexp 2)
3916 (point))
3917 ((looking-at "for")
3918 (forward-sexp 2)
3919 (skip-chars-forward " \t\n")
3920 (while (looking-at "[,:(]")
3921 (forward-sexp)
3922 (skip-chars-forward " \t\n"))
3923 (point))
3924 (t nil)
3927 (defconst vhdl-trailer-re
3928 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
3930 (defconst vhdl-statement-fwd-re
3931 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
3932 "A regular expression for searching forward that matches all known
3933 \"statement\" keywords.")
3935 (defconst vhdl-statement-bwd-re
3936 "\\b\\(if\\|for\\|while\\)\\b[^_]"
3937 "A regular expression for searching backward that matches all known
3938 \"statement\" keywords.")
3940 (defun vhdl-statement-p (&optional lim)
3941 "Return t if we are looking at a real \"statement\" keyword.
3942 Assumes that the caller will make sure that we are looking at
3943 vhdl-statement-fwd-re, and are not inside a literal, and that we are not
3944 in the middle of an identifier that just happens to contain a
3945 \"statement\" keyword."
3946 (cond
3947 ;; "for" ... "generate":
3948 ((and (looking-at "f")
3949 ;; Make sure it's the start of a parameter specification.
3950 (save-excursion
3951 (forward-sexp 2)
3952 (skip-chars-forward " \t\n")
3953 (looking-at "in\\b[^_]"))
3954 ;; Make sure it's not an "end for".
3955 (save-excursion
3956 (backward-sexp)
3957 (not (looking-at "end\\s-+\\w"))))
3959 ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
3960 ((and (looking-at "i")
3961 ;; Make sure it's not an "end if".
3962 (save-excursion
3963 (backward-sexp)
3964 (not (looking-at "end\\s-+\\w"))))
3966 ;; "while" ... "loop":
3967 ((looking-at "w")
3971 (defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
3972 "Regexp describing a case statement alternative key.")
3974 (defun vhdl-case-alternative-p (&optional lim)
3975 "Return t if we are looking at a real case alternative.
3976 Assumes that the caller will make sure that we are looking at
3977 vhdl-case-alternative-re, and are not inside a literal, and that
3978 we are not in the middle of an identifier that just happens to
3979 contain a \"when\" keyword."
3980 (save-excursion
3981 (let (foundp)
3982 (while (and (not foundp)
3983 (re-search-backward ";\\|<=" lim 'move))
3984 (if (or (= (preceding-char) ?_)
3985 (vhdl-in-literal lim))
3986 (backward-char)
3987 (setq foundp t)))
3988 (or (eq (following-char) ?\;)
3989 (eq (point) lim)))
3992 ;; Core syntactic movement functions:
3994 (defconst vhdl-b-t-b-re
3995 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
3997 (defun vhdl-backward-to-block (&optional lim)
3998 "Move backward to the previous \"begin\" or \"end\" keyword."
3999 (let (foundp)
4000 (while (and (not foundp)
4001 (re-search-backward vhdl-b-t-b-re lim 'move))
4002 (if (or (= (preceding-char) ?_)
4003 (vhdl-in-literal lim))
4004 (backward-char)
4005 (cond
4006 ;; "begin" keyword:
4007 ((and (looking-at vhdl-begin-fwd-re)
4008 (/= (preceding-char) ?_)
4009 (vhdl-begin-p lim))
4010 (setq foundp 'begin))
4011 ;; "end" keyword:
4012 ((and (looking-at vhdl-end-fwd-re)
4013 (/= (preceding-char) ?_)
4014 (vhdl-end-p lim))
4015 (setq foundp 'end))
4018 foundp
4021 (defun vhdl-forward-sexp (&optional count lim)
4022 "Move forward across one balanced expression (sexp).
4023 With COUNT, do it that many times."
4024 (interactive "p")
4025 (let ((count (or count 1))
4026 (case-fold-search t)
4027 end-vec target)
4028 (save-excursion
4029 (while (> count 0)
4030 ;; skip whitespace
4031 (skip-chars-forward " \t\n")
4032 ;; Check for an unbalanced "end" keyword
4033 (if (and (looking-at vhdl-end-fwd-re)
4034 (/= (preceding-char) ?_)
4035 (not (vhdl-in-literal lim))
4036 (vhdl-end-p lim)
4037 (not (looking-at "else")))
4038 (error
4039 "Containing expression ends prematurely in vhdl-forward-sexp"))
4040 ;; If the current keyword is a "begin" keyword, then find the
4041 ;; corresponding "end" keyword.
4042 (if (setq end-vec (vhdl-corresponding-end lim))
4043 (let (
4044 ;; end-re is the statement keyword to search for
4045 (end-re
4046 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
4047 ;; column is either the statement keyword target column
4048 ;; or nil
4049 (column (aref end-vec 1))
4050 (eol (vhdl-point 'eol))
4051 foundp literal placeholder)
4052 ;; Look for the statement keyword.
4053 (while (and (not foundp)
4054 (re-search-forward end-re nil t)
4055 (setq placeholder (match-end 1))
4056 (goto-char (match-beginning 0)))
4057 ;; If we are in a literal, or not in the right target
4058 ;; column and not on the same line as the begin, then
4059 ;; try again.
4060 (if (or (and column
4061 (/= (current-indentation) column)
4062 (> (point) eol))
4063 (= (preceding-char) ?_)
4064 (setq literal (vhdl-in-literal lim)))
4065 (if (eq literal 'comment)
4066 (end-of-line)
4067 (forward-char))
4068 ;; An "else" keyword corresponds to both the opening brace
4069 ;; of the following sexp and the closing brace of the
4070 ;; previous sexp.
4071 (if (not (looking-at "else"))
4072 (goto-char placeholder))
4073 (setq foundp t))
4075 (if (not foundp)
4076 (error "Unbalanced keywords in vhdl-forward-sexp"))
4078 ;; If the current keyword is not a "begin" keyword, then just
4079 ;; perform the normal forward-sexp.
4080 (forward-sexp)
4082 (setq count (1- count))
4084 (setq target (point)))
4085 (goto-char target)
4086 nil))
4088 (defun vhdl-backward-sexp (&optional count lim)
4089 "Move backward across one balanced expression (sexp).
4090 With COUNT, do it that many times. LIM bounds any required backward
4091 searches."
4092 (interactive "p")
4093 (let ((count (or count 1))
4094 (case-fold-search t)
4095 begin-vec target)
4096 (save-excursion
4097 (while (> count 0)
4098 ;; Perform the normal backward-sexp, unless we are looking at
4099 ;; "else" - an "else" keyword corresponds to both the opening brace
4100 ;; of the following sexp and the closing brace of the previous sexp.
4101 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
4102 (/= (preceding-char) ?_)
4103 (not (vhdl-in-literal lim)))
4105 (backward-sexp)
4106 (if (and (looking-at vhdl-begin-fwd-re)
4107 (/= (preceding-char) ?_)
4108 (not (vhdl-in-literal lim))
4109 (vhdl-begin-p lim))
4110 (error "Containing expression ends prematurely in vhdl-backward-sexp")))
4111 ;; If the current keyword is an "end" keyword, then find the
4112 ;; corresponding "begin" keyword.
4113 (if (and (setq begin-vec (vhdl-corresponding-begin lim))
4114 (/= (preceding-char) ?_))
4115 (let (
4116 ;; begin-re is the statement keyword to search for
4117 (begin-re
4118 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
4119 ;; column is either the statement keyword target column
4120 ;; or nil
4121 (column (aref begin-vec 1))
4122 ;; internal-p controls where the statement keyword can
4123 ;; be found.
4124 (internal-p (aref begin-vec 3))
4125 (last-backward (point)) last-forward
4126 foundp literal keyword)
4127 ;; Look for the statement keyword.
4128 (while (and (not foundp)
4129 (re-search-backward begin-re lim t)
4130 (setq keyword
4131 (buffer-substring (match-beginning 1)
4132 (match-end 1))))
4133 ;; If we are in a literal or in the wrong column,
4134 ;; then try again.
4135 (if (or (and column
4136 (and (/= (current-indentation) column)
4137 ;; possibly accept current-column as
4138 ;; well as current-indentation.
4139 (or (not internal-p)
4140 (/= (current-column) column))))
4141 (= (preceding-char) ?_)
4142 (vhdl-in-literal lim))
4143 (backward-char)
4144 ;; If there is a supplementary keyword, then
4145 ;; search forward for it.
4146 (if (and (setq begin-re (aref begin-vec 2))
4147 (or (not (listp begin-re))
4148 ;; If begin-re is an alist, then find the
4149 ;; element corresponding to the actual
4150 ;; keyword that we found.
4151 (progn
4152 (setq begin-re
4153 (assoc keyword begin-re))
4154 (and begin-re
4155 (setq begin-re (cdr begin-re))))))
4156 (and
4157 (setq begin-re
4158 (concat "\\b\\(" begin-re "\\)\\b[^_]"))
4159 (save-excursion
4160 (setq last-forward (point))
4161 ;; Look for the supplementary keyword
4162 ;; (bounded by the backward search start
4163 ;; point).
4164 (while (and (not foundp)
4165 (re-search-forward begin-re
4166 last-backward t)
4167 (goto-char (match-beginning 1)))
4168 ;; If we are in a literal, then try again.
4169 (if (or (= (preceding-char) ?_)
4170 (setq literal
4171 (vhdl-in-literal last-forward)))
4172 (if (eq literal 'comment)
4173 (goto-char
4174 (min (vhdl-point 'eol) last-backward))
4175 (forward-char))
4176 ;; We have found the supplementary keyword.
4177 ;; Save the position of the keyword in foundp.
4178 (setq foundp (point)))
4180 foundp)
4181 ;; If the supplementary keyword was found, then
4182 ;; move point to the supplementary keyword.
4183 (goto-char foundp))
4184 ;; If there was no supplementary keyword, then
4185 ;; point is already at the statement keyword.
4186 (setq foundp t)))
4187 ) ; end of the search for the statement keyword
4188 (if (not foundp)
4189 (error "Unbalanced keywords in vhdl-backward-sexp"))
4191 (setq count (1- count))
4193 (setq target (point)))
4194 (goto-char target)
4195 nil))
4197 (defun vhdl-backward-up-list (&optional count limit)
4198 "Move backward out of one level of blocks.
4199 With argument, do this that many times."
4200 (interactive "p")
4201 (let ((count (or count 1))
4202 target)
4203 (save-excursion
4204 (while (> count 0)
4205 (if (looking-at vhdl-defun-re)
4206 (error "Unbalanced blocks"))
4207 (vhdl-backward-to-block limit)
4208 (setq count (1- count)))
4209 (setq target (point)))
4210 (goto-char target)))
4212 (defun vhdl-end-of-defun (&optional count)
4213 "Move forward to the end of a VHDL defun."
4214 (interactive)
4215 (let ((case-fold-search t))
4216 (vhdl-beginning-of-defun)
4217 (if (not (looking-at "block\\|process\\|procedural"))
4218 (re-search-forward "\\bis\\b"))
4219 (vhdl-forward-sexp)))
4221 (defun vhdl-mark-defun ()
4222 "Put mark at end of this \"defun\", point at beginning."
4223 (interactive)
4224 (let ((case-fold-search t))
4225 (push-mark)
4226 (vhdl-beginning-of-defun)
4227 (push-mark)
4228 (if (not (looking-at "block\\|process\\|procedural"))
4229 (re-search-forward "\\bis\\b"))
4230 (vhdl-forward-sexp)
4231 (exchange-point-and-mark)))
4233 (defun vhdl-beginning-of-libunit ()
4234 "Move backward to the beginning of a VHDL library unit.
4235 Returns the location of the corresponding begin keyword, unless search
4236 stops due to beginning or end of buffer.
4237 Note that if point is between the \"libunit\" keyword and the
4238 corresponding \"begin\" keyword, then that libunit will not be
4239 recognised, and the search will continue backwards. If point is
4240 at the \"begin\" keyword, then the defun will be recognised. The
4241 returned point is at the first character of the \"libunit\" keyword."
4242 (let ((last-forward (point))
4243 (last-backward
4244 ;; Just in case we are actually sitting on the "begin"
4245 ;; keyword, allow for the keyword and an extra character,
4246 ;; as this will be used when looking forward for the
4247 ;; "begin" keyword.
4248 (save-excursion (forward-word 1) (1+ (point))))
4249 foundp literal placeholder)
4250 ;; Find the "libunit" keyword.
4251 (while (and (not foundp)
4252 (re-search-backward vhdl-libunit-re nil 'move))
4253 ;; If we are in a literal, or not at a real libunit, then try again.
4254 (if (or (= (preceding-char) ?_)
4255 (vhdl-in-literal (point-min))
4256 (not (vhdl-libunit-p)))
4257 (backward-char)
4258 ;; Find the corresponding "begin" keyword.
4259 (setq last-forward (point))
4260 (while (and (not foundp)
4261 (re-search-forward "\\bis\\b[^_]" last-backward t)
4262 (setq placeholder (match-beginning 0)))
4263 (if (or (= (preceding-char) ?_)
4264 (setq literal (vhdl-in-literal last-forward)))
4265 ;; It wasn't a real keyword, so keep searching.
4266 (if (eq literal 'comment)
4267 (goto-char
4268 (min (vhdl-point 'eol) last-backward))
4269 (forward-char))
4270 ;; We have found the begin keyword, loop will exit.
4271 (setq foundp placeholder)))
4272 ;; Go back to the libunit keyword
4273 (goto-char last-forward)))
4274 foundp))
4276 (defun vhdl-beginning-of-defun (&optional count)
4277 "Move backward to the beginning of a VHDL defun.
4278 With argument, do it that many times.
4279 Returns the location of the corresponding begin keyword, unless search
4280 stops due to beginning or end of buffer."
4281 ;; Note that if point is between the "defun" keyword and the
4282 ;; corresponding "begin" keyword, then that defun will not be
4283 ;; recognised, and the search will continue backwards. If point is
4284 ;; at the "begin" keyword, then the defun will be recognised. The
4285 ;; returned point is at the first character of the "defun" keyword.
4286 (interactive "p")
4287 (let ((count (or count 1))
4288 (case-fold-search t)
4289 (last-forward (point))
4290 foundp)
4291 (while (> count 0)
4292 (setq foundp nil)
4293 (goto-char last-forward)
4294 (let ((last-backward
4295 ;; Just in case we are actually sitting on the "begin"
4296 ;; keyword, allow for the keyword and an extra character,
4297 ;; as this will be used when looking forward for the
4298 ;; "begin" keyword.
4299 (save-excursion (forward-word 1) (1+ (point))))
4300 begin-string literal)
4301 (while (and (not foundp)
4302 (re-search-backward vhdl-defun-re nil 'move))
4303 ;; If we are in a literal, then try again.
4304 (if (or (= (preceding-char) ?_)
4305 (vhdl-in-literal (point-min)))
4306 (backward-char)
4307 (if (setq begin-string (vhdl-corresponding-defun))
4308 ;; This is a real defun keyword.
4309 ;; Find the corresponding "begin" keyword.
4310 ;; Look for the begin keyword.
4311 (progn
4312 ;; Save the search start point.
4313 (setq last-forward (point))
4314 (while (and (not foundp)
4315 (search-forward begin-string last-backward t))
4316 (if (or (= (preceding-char) ?_)
4317 (save-match-data
4318 (setq literal (vhdl-in-literal last-forward))))
4319 ;; It wasn't a real keyword, so keep searching.
4320 (if (eq literal 'comment)
4321 (goto-char
4322 (min (vhdl-point 'eol) last-backward))
4323 (forward-char))
4324 ;; We have found the begin keyword, loop will exit.
4325 (setq foundp (match-beginning 0)))
4327 ;; Go back to the defun keyword
4328 (goto-char last-forward)) ; end search for begin keyword
4330 ) ; end of the search for the defun keyword
4332 (setq count (1- count))
4334 (vhdl-keep-region-active)
4335 foundp))
4337 (defun vhdl-beginning-of-statement (&optional count lim)
4338 "Go to the beginning of the innermost VHDL statement.
4339 With prefix arg, go back N - 1 statements. If already at the
4340 beginning of a statement then go to the beginning of the preceding
4341 one. If within a string or comment, or next to a comment (only
4342 whitespace between), move by sentences instead of statements.
4344 When called from a program, this function takes 2 optional args: the
4345 prefix arg, and a buffer position limit which is the farthest back to
4346 search."
4347 (interactive "p")
4348 (let ((count (or count 1))
4349 (case-fold-search t)
4350 (lim (or lim (point-min)))
4351 (here (point))
4352 state)
4353 (save-excursion
4354 (goto-char lim)
4355 (setq state (parse-partial-sexp (point) here nil nil)))
4356 (if (and (interactive-p)
4357 (or (nth 3 state)
4358 (nth 4 state)
4359 (looking-at (concat "[ \t]*" comment-start-skip))))
4360 (forward-sentence (- count))
4361 (while (> count 0)
4362 (vhdl-beginning-of-statement-1 lim)
4363 (setq count (1- count))))
4364 ;; its possible we've been left up-buf of lim
4365 (goto-char (max (point) lim))
4367 (vhdl-keep-region-active))
4369 (defconst vhdl-e-o-s-re
4370 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
4372 (defun vhdl-end-of-statement ()
4373 "Very simple implementation."
4374 (interactive)
4375 (re-search-forward vhdl-e-o-s-re))
4377 (defconst vhdl-b-o-s-re
4378 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
4379 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
4381 (defun vhdl-beginning-of-statement-1 (&optional lim)
4382 "Move to the start of the current statement, or the previous
4383 statement if already at the beginning of one."
4384 (let ((lim (or lim (point-min)))
4385 (here (point))
4386 (pos (point))
4387 donep)
4388 ;; go backwards one balanced expression, but be careful of
4389 ;; unbalanced paren being reached
4390 (if (not (vhdl-safe (progn (backward-sexp) t)))
4391 (progn
4392 (backward-up-list 1)
4393 (forward-char)
4394 (vhdl-forward-syntactic-ws here)
4395 (setq donep t)))
4396 (while (and (not donep)
4397 (not (bobp))
4398 ;; look backwards for a statement boundary
4399 (re-search-backward vhdl-b-o-s-re lim 'move))
4400 (if (or (= (preceding-char) ?_)
4401 (vhdl-in-literal lim))
4402 (backward-char)
4403 (cond
4404 ;; If we are looking at an open paren, then stop after it
4405 ((eq (following-char) ?\()
4406 (forward-char)
4407 (vhdl-forward-syntactic-ws here)
4408 (setq donep t))
4409 ;; If we are looking at a close paren, then skip it
4410 ((eq (following-char) ?\))
4411 (forward-char)
4412 (setq pos (point))
4413 (backward-sexp)
4414 (if (< (point) lim)
4415 (progn (goto-char pos)
4416 (vhdl-forward-syntactic-ws here)
4417 (setq donep t))))
4418 ;; If we are looking at a semicolon, then stop
4419 ((eq (following-char) ?\;)
4420 (progn
4421 (forward-char)
4422 (vhdl-forward-syntactic-ws here)
4423 (setq donep t)))
4424 ;; If we are looking at a "begin", then stop
4425 ((and (looking-at vhdl-begin-fwd-re)
4426 (/= (preceding-char) ?_)
4427 (vhdl-begin-p nil))
4428 ;; If it's a leader "begin", then find the
4429 ;; right place
4430 (if (looking-at vhdl-leader-re)
4431 (save-excursion
4432 ;; set a default stop point at the begin
4433 (setq pos (point))
4434 ;; is the start point inside the leader area ?
4435 (goto-char (vhdl-end-of-leader))
4436 (vhdl-forward-syntactic-ws here)
4437 (if (< (point) here)
4438 ;; start point was not inside leader area
4439 ;; set stop point at word after leader
4440 (setq pos (point))))
4441 (forward-word 1)
4442 (vhdl-forward-syntactic-ws here)
4443 (setq pos (point)))
4444 (goto-char pos)
4445 (setq donep t))
4446 ;; If we are looking at a "statement", then stop
4447 ((and (looking-at vhdl-statement-fwd-re)
4448 (/= (preceding-char) ?_)
4449 (vhdl-statement-p nil))
4450 (setq donep t))
4451 ;; If we are looking at a case alternative key, then stop
4452 ((and (looking-at vhdl-case-alternative-re)
4453 (vhdl-case-alternative-p lim))
4454 (save-excursion
4455 ;; set a default stop point at the when
4456 (setq pos (point))
4457 ;; is the start point inside the case alternative key ?
4458 (looking-at vhdl-case-alternative-re)
4459 (goto-char (match-end 0))
4460 (vhdl-forward-syntactic-ws here)
4461 (if (< (point) here)
4462 ;; start point was not inside the case alternative key
4463 ;; set stop point at word after case alternative keyleader
4464 (setq pos (point))))
4465 (goto-char pos)
4466 (setq donep t))
4467 ;; Bogus find, continue
4469 (backward-char)))))
4472 ;; Defuns for calculating the current syntactic state:
4474 (defun vhdl-get-library-unit (bod placeholder)
4475 "If there is an enclosing library unit at bod, with it's \"begin\"
4476 keyword at placeholder, then return the library unit type."
4477 (let ((here (vhdl-point 'bol)))
4478 (if (save-excursion
4479 (goto-char placeholder)
4480 (vhdl-safe (vhdl-forward-sexp 1 bod))
4481 (<= here (point)))
4482 (save-excursion
4483 (goto-char bod)
4484 (cond
4485 ((looking-at "e") 'entity)
4486 ((looking-at "a") 'architecture)
4487 ((looking-at "c") 'configuration)
4488 ((looking-at "p")
4489 (save-excursion
4490 (goto-char bod)
4491 (forward-sexp)
4492 (vhdl-forward-syntactic-ws here)
4493 (if (looking-at "body\\b[^_]")
4494 'package-body 'package))))))
4497 (defun vhdl-get-block-state (&optional lim)
4498 "Finds and records all the closest opens.
4499 lim is the furthest back we need to search (it should be the
4500 previous libunit keyword)."
4501 (let ((here (point))
4502 (lim (or lim (point-min)))
4503 keyword sexp-start sexp-mid sexp-end
4504 preceding-sexp containing-sexp
4505 containing-begin containing-mid containing-paren)
4506 (save-excursion
4507 ;; Find the containing-paren, and use that as the limit
4508 (if (setq containing-paren
4509 (save-restriction
4510 (narrow-to-region lim (point))
4511 (vhdl-safe (scan-lists (point) -1 1))))
4512 (setq lim containing-paren))
4513 ;; Look backwards for "begin" and "end" keywords.
4514 (while (and (> (point) lim)
4515 (not containing-sexp))
4516 (setq keyword (vhdl-backward-to-block lim))
4517 (cond
4518 ((eq keyword 'begin)
4519 ;; Found a "begin" keyword
4520 (setq sexp-start (point))
4521 (setq sexp-mid (vhdl-corresponding-mid lim))
4522 (setq sexp-end (vhdl-safe
4523 (save-excursion
4524 (vhdl-forward-sexp 1 lim) (point))))
4525 (if (and sexp-end (<= sexp-end here))
4526 ;; we want to record this sexp, but we only want to
4527 ;; record the last-most of any of them before here
4528 (or preceding-sexp
4529 (setq preceding-sexp sexp-start))
4530 ;; we're contained in this sexp so put sexp-start on
4531 ;; front of list
4532 (setq containing-sexp sexp-start)
4533 (setq containing-mid sexp-mid)
4534 (setq containing-begin t)))
4535 ((eq keyword 'end)
4536 ;; Found an "end" keyword
4537 (forward-sexp)
4538 (setq sexp-end (point))
4539 (setq sexp-mid nil)
4540 (setq sexp-start
4541 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
4542 (progn (backward-sexp) (point))))
4543 ;; we want to record this sexp, but we only want to
4544 ;; record the last-most of any of them before here
4545 (or preceding-sexp
4546 (setq preceding-sexp sexp-start)))
4548 ;; Check if the containing-paren should be the containing-sexp
4549 (if (and containing-paren
4550 (or (null containing-sexp)
4551 (< containing-sexp containing-paren)))
4552 (setq containing-sexp containing-paren
4553 preceding-sexp nil
4554 containing-begin nil
4555 containing-mid nil))
4556 (vector containing-sexp preceding-sexp containing-begin containing-mid)
4560 (defconst vhdl-s-c-a-re
4561 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
4563 (defun vhdl-skip-case-alternative (&optional lim)
4564 "Skip forward over case/when bodies, with optional maximal
4565 limit. If no next case alternative is found, nil is returned and point
4566 is not moved."
4567 (let ((lim (or lim (point-max)))
4568 (here (point))
4569 donep foundp)
4570 (while (and (< (point) lim)
4571 (not donep))
4572 (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
4573 (save-match-data
4574 (not (vhdl-in-literal)))
4575 (/= (match-beginning 0) here))
4576 (progn
4577 (goto-char (match-beginning 0))
4578 (cond
4579 ((and (looking-at "case")
4580 (re-search-forward "\\bis[^_]" lim t))
4581 (backward-sexp)
4582 (vhdl-forward-sexp))
4584 (setq donep t
4585 foundp t))))))
4586 (if (not foundp)
4587 (goto-char here))
4588 foundp))
4590 (defun vhdl-backward-skip-label (&optional lim)
4591 "Skip backward over a label, with optional maximal
4592 limit. If label is not found, nil is returned and point
4593 is not moved."
4594 (let ((lim (or lim (point-min)))
4595 placeholder)
4596 (if (save-excursion
4597 (vhdl-backward-syntactic-ws lim)
4598 (and (eq (preceding-char) ?:)
4599 (progn
4600 (backward-sexp)
4601 (setq placeholder (point))
4602 (looking-at vhdl-label-key))))
4603 (goto-char placeholder))
4606 (defun vhdl-forward-skip-label (&optional lim)
4607 "Skip forward over a label, with optional maximal
4608 limit. If label is not found, nil is returned and point
4609 is not moved."
4610 (let ((lim (or lim (point-max))))
4611 (if (looking-at vhdl-label-key)
4612 (progn
4613 (goto-char (match-end 0))
4614 (vhdl-forward-syntactic-ws lim)))
4617 (defun vhdl-get-syntactic-context ()
4618 "Guess the syntactic description of the current line of VHDL code."
4619 (save-excursion
4620 (save-restriction
4621 (beginning-of-line)
4622 (let* ((indent-point (point))
4623 (case-fold-search t)
4624 vec literal containing-sexp preceding-sexp
4625 containing-begin containing-mid containing-leader
4626 char-before-ip char-after-ip begin-after-ip end-after-ip
4627 placeholder lim library-unit
4630 ;; Reset the syntactic context
4631 (setq vhdl-syntactic-context nil)
4633 (save-excursion
4634 ;; Move to the start of the previous library unit, and
4635 ;; record the position of the "begin" keyword.
4636 (setq placeholder (vhdl-beginning-of-libunit))
4637 ;; The position of the "libunit" keyword gives us a gross
4638 ;; limit point.
4639 (setq lim (point))
4642 ;; If there is a previous library unit, and we are enclosed by
4643 ;; it, then set the syntax accordingly.
4644 (and placeholder
4645 (setq library-unit (vhdl-get-library-unit lim placeholder))
4646 (vhdl-add-syntax library-unit lim))
4648 ;; Find the surrounding state.
4649 (if (setq vec (vhdl-get-block-state lim))
4650 (progn
4651 (setq containing-sexp (aref vec 0))
4652 (setq preceding-sexp (aref vec 1))
4653 (setq containing-begin (aref vec 2))
4654 (setq containing-mid (aref vec 3))
4657 ;; set the limit on the farthest back we need to search
4658 (setq lim (if containing-sexp
4659 (save-excursion
4660 (goto-char containing-sexp)
4661 ;; set containing-leader if required
4662 (if (looking-at vhdl-leader-re)
4663 (setq containing-leader (vhdl-end-of-leader)))
4664 (vhdl-point 'bol))
4665 (point-min)))
4667 ;; cache char before and after indent point, and move point to
4668 ;; the most likely position to perform the majority of tests
4669 (goto-char indent-point)
4670 (skip-chars-forward " \t")
4671 (setq literal (vhdl-in-literal lim))
4672 (setq char-after-ip (following-char))
4673 (setq begin-after-ip (and
4674 (not literal)
4675 (looking-at vhdl-begin-fwd-re)
4676 (vhdl-begin-p)))
4677 (setq end-after-ip (and
4678 (not literal)
4679 (looking-at vhdl-end-fwd-re)
4680 (vhdl-end-p)))
4681 (vhdl-backward-syntactic-ws lim)
4682 (setq char-before-ip (preceding-char))
4683 (goto-char indent-point)
4684 (skip-chars-forward " \t")
4686 ;; now figure out syntactic qualities of the current line
4687 (cond
4688 ;; CASE 1: in a string or comment.
4689 ((memq literal '(string comment))
4690 (vhdl-add-syntax literal (vhdl-point 'bopl)))
4691 ;; CASE 2: Line is at top level.
4692 ((null containing-sexp)
4693 ;; Find the point to which indentation will be relative
4694 (save-excursion
4695 (if (null preceding-sexp)
4696 ;; CASE 2X.1
4697 ;; no preceding-sexp -> use the preceding statement
4698 (vhdl-beginning-of-statement-1 lim)
4699 ;; CASE 2X.2
4700 ;; if there is a preceding-sexp then indent relative to it
4701 (goto-char preceding-sexp)
4702 ;; if not at boi, then the block-opening keyword is
4703 ;; probably following a label, so we need a different
4704 ;; relpos
4705 (if (/= (point) (vhdl-point 'boi))
4706 ;; CASE 2X.3
4707 (vhdl-beginning-of-statement-1 lim)))
4708 ;; v-b-o-s could have left us at point-min
4709 (and (bobp)
4710 ;; CASE 2X.4
4711 (vhdl-forward-syntactic-ws indent-point))
4712 (setq placeholder (point)))
4713 (cond
4714 ;; CASE 2A : we are looking at a block-open
4715 (begin-after-ip
4716 (vhdl-add-syntax 'block-open placeholder))
4717 ;; CASE 2B: we are looking at a block-close
4718 (end-after-ip
4719 (vhdl-add-syntax 'block-close placeholder))
4720 ;; CASE 2C: we are looking at a top-level statement
4721 ((progn
4722 (vhdl-backward-syntactic-ws lim)
4723 (or (bobp)
4724 (= (preceding-char) ?\;)))
4725 (vhdl-add-syntax 'statement placeholder))
4726 ;; CASE 2D: we are looking at a top-level statement-cont
4728 (vhdl-beginning-of-statement-1 lim)
4729 ;; v-b-o-s could have left us at point-min
4730 (and (bobp)
4731 ;; CASE 2D.1
4732 (vhdl-forward-syntactic-ws indent-point))
4733 (vhdl-add-syntax 'statement-cont (point)))
4734 )) ; end CASE 2
4735 ;; CASE 3: line is inside parentheses. Most likely we are
4736 ;; either in a subprogram argument (interface) list, or a
4737 ;; continued expression containing parentheses.
4738 ((null containing-begin)
4739 (vhdl-backward-syntactic-ws containing-sexp)
4740 (cond
4741 ;; CASE 3A: we are looking at the arglist closing paren
4742 ((eq char-after-ip ?\))
4743 (goto-char containing-sexp)
4744 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
4745 ;; CASE 3B: we are looking at the first argument in an empty
4746 ;; argument list.
4747 ((eq char-before-ip ?\()
4748 (goto-char containing-sexp)
4749 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
4750 ;; CASE 3C: we are looking at an arglist continuation line,
4751 ;; but the preceding argument is on the same line as the
4752 ;; opening paren. This case includes multi-line
4753 ;; expression paren groupings.
4754 ((and (save-excursion
4755 (goto-char (1+ containing-sexp))
4756 (skip-chars-forward " \t")
4757 (not (eolp))
4758 (not (looking-at "--")))
4759 (save-excursion
4760 (vhdl-beginning-of-statement-1 containing-sexp)
4761 (skip-chars-backward " \t(")
4762 (<= (point) containing-sexp)))
4763 (goto-char containing-sexp)
4764 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
4765 ;; CASE 3D: we are looking at just a normal arglist
4766 ;; continuation line
4767 (t (vhdl-beginning-of-statement-1 containing-sexp)
4768 (vhdl-forward-syntactic-ws indent-point)
4769 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
4771 ;; CASE 4: A block mid open
4772 ((and begin-after-ip
4773 (looking-at containing-mid))
4774 (goto-char containing-sexp)
4775 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4776 (if (looking-at vhdl-trailer-re)
4777 ;; CASE 4.1
4778 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4779 (vhdl-backward-skip-label (vhdl-point 'boi))
4780 (vhdl-add-syntax 'block-open (point)))
4781 ;; CASE 5: block close brace
4782 (end-after-ip
4783 (goto-char containing-sexp)
4784 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4785 (if (looking-at vhdl-trailer-re)
4786 ;; CASE 5.1
4787 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4788 (vhdl-backward-skip-label (vhdl-point 'boi))
4789 (vhdl-add-syntax 'block-close (point)))
4790 ;; CASE 6: A continued statement
4791 ((and (/= char-before-ip ?\;)
4792 ;; check it's not a trailer begin keyword, or a begin
4793 ;; keyword immediately following a label.
4794 (not (and begin-after-ip
4795 (or (looking-at vhdl-trailer-re)
4796 (save-excursion
4797 (vhdl-backward-skip-label containing-sexp)))))
4798 ;; check it's not a statement keyword
4799 (not (and (looking-at vhdl-statement-fwd-re)
4800 (vhdl-statement-p)))
4801 ;; see if the b-o-s is before the indent point
4802 (> indent-point
4803 (save-excursion
4804 (vhdl-beginning-of-statement-1 containing-sexp)
4805 ;; If we ended up after a leader, then this will
4806 ;; move us forward to the start of the first
4807 ;; statement. Note that a containing sexp here is
4808 ;; always a keyword, not a paren, so this will
4809 ;; have no effect if we hit the containing-sexp.
4810 (vhdl-forward-syntactic-ws indent-point)
4811 (setq placeholder (point))))
4812 ;; check it's not a block-intro
4813 (/= placeholder containing-sexp)
4814 ;; check it's not a case block-intro
4815 (save-excursion
4816 (goto-char placeholder)
4817 (or (not (looking-at vhdl-case-alternative-re))
4818 (> (match-end 0) indent-point))))
4819 ;; Make placeholder skip a label, but only if it puts us
4820 ;; before the indent point at the start of a line.
4821 (let ((new placeholder))
4822 (if (and (> indent-point
4823 (save-excursion
4824 (goto-char placeholder)
4825 (vhdl-forward-skip-label indent-point)
4826 (setq new (point))))
4827 (save-excursion
4828 (goto-char new)
4829 (eq new (progn (back-to-indentation) (point)))))
4830 (setq placeholder new)))
4831 (vhdl-add-syntax 'statement-cont placeholder)
4832 (if begin-after-ip
4833 (vhdl-add-syntax 'block-open)))
4834 ;; Statement. But what kind?
4835 ;; CASE 7: A case alternative key
4836 ((and (looking-at vhdl-case-alternative-re)
4837 (vhdl-case-alternative-p containing-sexp))
4838 ;; for a case alternative key, we set relpos to the first
4839 ;; non-whitespace char on the line containing the "case"
4840 ;; keyword.
4841 (goto-char containing-sexp)
4842 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4843 (if (looking-at vhdl-trailer-re)
4844 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4845 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
4846 ;; CASE 8: statement catchall
4848 ;; we know its a statement, but we need to find out if it is
4849 ;; the first statement in a block
4850 (if containing-leader
4851 (goto-char containing-leader)
4852 (goto-char containing-sexp)
4853 ;; Note that a containing sexp here is always a keyword,
4854 ;; not a paren, so skip over the keyword.
4855 (forward-sexp))
4856 ;; move to the start of the first statement
4857 (vhdl-forward-syntactic-ws indent-point)
4858 (setq placeholder (point))
4859 ;; we want to ignore case alternatives keys when skipping forward
4860 (let (incase-p)
4861 (while (looking-at vhdl-case-alternative-re)
4862 (setq incase-p (point))
4863 ;; we also want to skip over the body of the
4864 ;; case/when statement if that doesn't put us at
4865 ;; after the indent-point
4866 (while (vhdl-skip-case-alternative indent-point))
4867 ;; set up the match end
4868 (looking-at vhdl-case-alternative-re)
4869 (goto-char (match-end 0))
4870 ;; move to the start of the first case alternative statement
4871 (vhdl-forward-syntactic-ws indent-point)
4872 (setq placeholder (point)))
4873 (cond
4874 ;; CASE 8A: we saw a case/when statement so we must be
4875 ;; in a switch statement. find out if we are at the
4876 ;; statement just after a case alternative key
4877 ((and incase-p
4878 (= (point) indent-point))
4879 ;; relpos is the "when" keyword
4880 (vhdl-add-syntax 'statement-case-intro incase-p))
4881 ;; CASE 8B: any old statement
4882 ((< (point) indent-point)
4883 ;; relpos is the first statement of the block
4884 (vhdl-add-syntax 'statement placeholder)
4885 (if begin-after-ip
4886 (vhdl-add-syntax 'block-open)))
4887 ;; CASE 8C: first statement in a block
4889 (goto-char containing-sexp)
4890 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4891 (if (looking-at vhdl-trailer-re)
4892 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4893 (vhdl-backward-skip-label (vhdl-point 'boi))
4894 (vhdl-add-syntax 'statement-block-intro (point))
4895 (if begin-after-ip
4896 (vhdl-add-syntax 'block-open)))
4900 ;; now we need to look at any modifiers
4901 (goto-char indent-point)
4902 (skip-chars-forward " \t")
4903 (if (looking-at "--")
4904 (vhdl-add-syntax 'comment))
4905 ;; return the syntax
4906 vhdl-syntactic-context))))
4908 ;; Standard indentation line-ups:
4910 (defun vhdl-lineup-arglist (langelem)
4911 "Lineup the current arglist line with the arglist appearing just
4912 after the containing paren which starts the arglist."
4913 (save-excursion
4914 (let* ((containing-sexp
4915 (save-excursion
4916 ;; arglist-cont-nonempty gives relpos ==
4917 ;; to boi of containing-sexp paren. This
4918 ;; is good when offset is +, but bad
4919 ;; when it is vhdl-lineup-arglist, so we
4920 ;; have to special case a kludge here.
4921 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
4922 (progn
4923 (beginning-of-line)
4924 (backward-up-list 1)
4925 (skip-chars-forward " \t" (vhdl-point 'eol)))
4926 (goto-char (cdr langelem)))
4927 (point)))
4928 (cs-curcol (save-excursion
4929 (goto-char (cdr langelem))
4930 (current-column))))
4931 (if (save-excursion
4932 (beginning-of-line)
4933 (looking-at "[ \t]*)"))
4934 (progn (goto-char (match-end 0))
4935 (backward-sexp)
4936 (forward-char)
4937 (vhdl-forward-syntactic-ws)
4938 (- (current-column) cs-curcol))
4939 (goto-char containing-sexp)
4940 (or (eolp)
4941 (let ((eol (vhdl-point 'eol))
4942 (here (progn
4943 (forward-char)
4944 (skip-chars-forward " \t")
4945 (point))))
4946 (vhdl-forward-syntactic-ws)
4947 (if (< (point) eol)
4948 (goto-char here))))
4949 (- (current-column) cs-curcol)
4950 ))))
4952 (defun vhdl-lineup-arglist-intro (langelem)
4953 "Lineup an arglist-intro line to just after the open paren."
4954 (save-excursion
4955 (let ((cs-curcol (save-excursion
4956 (goto-char (cdr langelem))
4957 (current-column)))
4958 (ce-curcol (save-excursion
4959 (beginning-of-line)
4960 (backward-up-list 1)
4961 (skip-chars-forward " \t" (vhdl-point 'eol))
4962 (current-column))))
4963 (- ce-curcol cs-curcol -1))))
4965 (defun vhdl-lineup-comment (langelem)
4966 "Support old behavior for comment indentation. We look at
4967 vhdl-comment-only-line-offset to decide how to indent comment
4968 only-lines."
4969 (save-excursion
4970 (back-to-indentation)
4971 ;; at or to the right of comment-column
4972 (if (>= (current-column) comment-column)
4973 (vhdl-comment-indent)
4974 ;; otherwise, indent as specified by vhdl-comment-only-line-offset
4975 (if (not (bolp))
4976 (or (car-safe vhdl-comment-only-line-offset)
4977 vhdl-comment-only-line-offset)
4978 (or (cdr-safe vhdl-comment-only-line-offset)
4979 (car-safe vhdl-comment-only-line-offset)
4980 -1000 ;jam it against the left side
4981 )))))
4983 (defun vhdl-lineup-statement-cont (langelem)
4984 "Line up statement-cont after the assignment operator."
4985 (save-excursion
4986 (let* ((relpos (cdr langelem))
4987 (assignp (save-excursion
4988 (goto-char (vhdl-point 'boi))
4989 (and (re-search-forward "\\(<\\|:\\)="
4990 (vhdl-point 'eol) t)
4991 (- (point) (vhdl-point 'boi)))))
4992 (curcol (progn
4993 (goto-char relpos)
4994 (current-column)))
4995 foundp)
4996 (while (and (not foundp)
4997 (< (point) (vhdl-point 'eol)))
4998 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
4999 (if (vhdl-in-literal (cdr langelem))
5000 (forward-char)
5001 (if (= (preceding-char) ?\()
5002 ;; skip over any parenthesized expressions
5003 (goto-char (min (vhdl-point 'eol)
5004 (scan-lists (point) 1 1)))
5005 ;; found an assignment operator (not at eol)
5006 (setq foundp (not (looking-at "\\s-*$"))))))
5007 (if (not foundp)
5008 ;; there's no assignment operator on the line
5009 vhdl-basic-offset
5010 ;; calculate indentation column after assign and ws, unless
5011 ;; our line contains an assignment operator
5012 (if (not assignp)
5013 (progn
5014 (forward-char)
5015 (skip-chars-forward " \t")
5016 (setq assignp 0)))
5017 (- (current-column) assignp curcol))
5020 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5021 ;; Indentation commands
5023 (defsubst vhdl-in-comment-p ()
5024 "Check if point is to right of beginning comment delimiter."
5025 (let ((position (point)))
5026 (save-excursion ; finds an unquoted comment
5027 (beginning-of-line)
5028 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" position t))))
5030 (defsubst vhdl-in-string-p ()
5031 "Check if point is in a string."
5032 (let ((position (point)))
5033 (save-excursion ; preceeded by odd number of string delimiters?
5034 (beginning-of-line)
5035 (eq position (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*"
5036 position t)))))
5038 (defsubst vhdl-in-comment-or-string-p ()
5039 "Check if point is in a comment or a string."
5040 (and (vhdl-in-comment-p)
5041 (vhdl-in-string-p)))
5043 (defun vhdl-electric-tab (&optional prefix-arg)
5044 "If preceeding character is part of a word or a paren then hippie-expand,
5045 else if right of non whitespace on line then tab-to-tab-stop,
5046 else if last command was a tab or return then dedent one step,
5047 else indent `correctly'."
5048 (interactive "*P")
5049 (vhdl-ext-syntax-table
5050 (cond ((= (char-syntax (preceding-char)) ?w)
5051 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5052 (case-replace nil))
5053 (vhdl-expand-abbrev prefix-arg)))
5054 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
5055 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5056 (case-replace nil))
5057 (vhdl-expand-paren prefix-arg)))
5058 ((> (current-column) (current-indentation))
5059 (tab-to-tab-stop))
5060 ((and (or (eq last-command 'vhdl-electric-tab)
5061 (eq last-command 'vhdl-electric-return))
5062 (/= 0 (current-indentation)))
5063 (backward-delete-char-untabify vhdl-basic-offset nil))
5064 (t (vhdl-indent-line)))
5065 (setq this-command 'vhdl-electric-tab)))
5067 (defun vhdl-electric-return ()
5068 "newline-and-indent or indent-new-comment-line if in comment and preceding
5069 character is a space."
5070 (interactive)
5071 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
5072 (indent-new-comment-line)
5073 (newline-and-indent)))
5075 (defvar vhdl-progress-info nil
5076 "Array variable for progress information: 0 begin, 1 end, 2 time.")
5078 (defun vhdl-indent-line ()
5079 "Indent the current line as VHDL code. Returns the amount of
5080 indentation change."
5081 (interactive)
5082 (let* ((syntax (vhdl-get-syntactic-context))
5083 (pos (- (point-max) (point)))
5084 ;; special case: comments at or right of comment-column
5085 (indent (if (and (eq (car (car syntax)) 'comment)
5086 (>= (vhdl-get-offset (car syntax)) comment-column))
5087 (vhdl-get-offset (car syntax))
5088 (apply '+ (mapcar 'vhdl-get-offset syntax))))
5089 ; (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
5090 (shift-amt (- indent (current-indentation))))
5091 (and vhdl-echo-syntactic-information-p
5092 (message "syntax: %s, indent= %d" syntax indent))
5093 (unless (zerop shift-amt)
5094 (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
5095 (beginning-of-line)
5096 (indent-to indent))
5097 (if (< (point) (vhdl-point 'boi))
5098 (back-to-indentation)
5099 ;; If initial point was within line's indentation, position after
5100 ;; the indentation. Else stay at same point in text.
5101 (when (> (- (point-max) pos) (point))
5102 (goto-char (- (point-max) pos))))
5103 (run-hooks 'vhdl-special-indent-hook)
5104 ;; update progress status
5105 (when vhdl-progress-info
5106 (aset vhdl-progress-info 1 (+ (aref vhdl-progress-info 1)
5107 (if (> -500 shift-amt) 0 shift-amt)))
5108 (when (< vhdl-progress-interval
5109 (- (nth 1 (current-time)) (aref vhdl-progress-info 2)))
5110 (message "Indenting... (%2d%s)"
5111 (/ (* 100 (- (point) (aref vhdl-progress-info 0)))
5112 (- (aref vhdl-progress-info 1)
5113 (aref vhdl-progress-info 0))) "%")
5114 (aset vhdl-progress-info 2 (nth 1 (current-time)))))
5115 shift-amt))
5117 (defun vhdl-indent-buffer ()
5118 "Indent whole buffer as VHDL code.
5119 Calls `indent-region' for whole buffer and adds progress reporting."
5120 (interactive)
5121 (when vhdl-progress-interval
5122 (setq vhdl-progress-info (vector (point-min) (point-max) 0)))
5123 (indent-region (point-min) (point-max) nil)
5124 (when vhdl-progress-interval (message "Indenting...done"))
5125 (setq vhdl-progress-info nil))
5127 (defun vhdl-indent-region (start end column)
5128 "Indent region as VHDL code.
5129 Adds progress reporting to `indent-region'."
5130 (interactive "r\nP")
5131 (when vhdl-progress-interval (setq vhdl-progress-info (vector start end 0)))
5132 (indent-region start end column)
5133 (when vhdl-progress-interval (message "Indenting...done"))
5134 (setq vhdl-progress-info nil))
5136 (defun vhdl-indent-sexp (&optional endpos)
5137 "Indent each line of the list starting just after point.
5138 If optional arg ENDPOS is given, indent each line, stopping when
5139 ENDPOS is encountered."
5140 (interactive)
5141 (save-excursion
5142 (let ((beg (point))
5143 (end (progn (vhdl-forward-sexp nil endpos) (point))))
5144 (indent-region beg end nil))))
5146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5147 ;; Miscellaneous commands
5149 (defun vhdl-show-syntactic-information ()
5150 "Show syntactic information for current line."
5151 (interactive)
5152 (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
5153 (vhdl-keep-region-active))
5155 ;; Verification and regression functions:
5157 (defun vhdl-regress-line (&optional arg)
5158 "Check syntactic information for current line."
5159 (interactive "P")
5160 (let ((expected (save-excursion
5161 (end-of-line)
5162 (when (search-backward " -- ((" (vhdl-point 'bol) t)
5163 (forward-char 4)
5164 (read (current-buffer)))))
5165 (actual (vhdl-get-syntactic-context))
5166 (expurgated))
5167 ;; remove the library unit symbols
5168 (mapcar
5169 (function
5170 (lambda (elt)
5171 (if (memq (car elt) '(entity configuration package
5172 package-body architecture))
5174 (setq expurgated (append expurgated (list elt))))))
5175 actual)
5176 (if (and (not arg) expected (listp expected))
5177 (if (not (equal expected expurgated))
5178 (error "Should be: %s, is: %s" expected expurgated))
5179 (save-excursion
5180 (beginning-of-line)
5181 (when (not (looking-at "^\\s-*\\(--.*\\)?$"))
5182 (end-of-line)
5183 (if (search-backward " -- ((" (vhdl-point 'bol) t)
5184 (kill-line))
5185 (insert " -- ")
5186 (insert (format "%s" expurgated))))))
5187 (vhdl-keep-region-active))
5190 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5191 ;;; Alignment, whitespace fixup, beautifying
5192 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5194 (defvar vhdl-align-alist
5196 ;; after some keywords
5197 (vhdl-mode "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)[ \t]"
5198 "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)\\([ \t]+\\)" 2)
5199 ;; before ':'
5200 (vhdl-mode ":[^=]" "\\([ \t]*\\):[^=]")
5201 ;; after direction specifications
5202 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\>"
5203 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\([ \t]+\\)" 2)
5204 ;; before "==", ":=", "=>", and "<="
5205 (vhdl-mode "==" "\\([ \t]*\\)==" 1)
5206 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since ":= ... =>" can occur
5207 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "<= ... =>" can occur
5208 (vhdl-mode "=>" "\\([ \t]*\\)=>" 1)
5209 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since "=> ... :=" can occur
5210 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "=> ... <=" can occur
5211 ;; before some keywords
5212 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
5213 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
5214 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
5216 "The format of this alist is (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
5217 It is searched in order. If REGEXP is found anywhere in the first
5218 line of a region to be aligned, ALIGN-PATTERN will be used for that
5219 region. ALIGN-PATTERN must include the whitespace to be expanded or
5220 contracted. It may also provide regexps for the text surrounding the
5221 whitespace. SUBEXP specifies which sub-expression of
5222 ALIGN-PATTERN matches the white space to be expanded/contracted.")
5224 (defvar vhdl-align-try-all-clauses t
5225 "If REGEXP is not found on the first line of the region that clause
5226 is ignored. If this variable is non-nil, then the clause is tried anyway.")
5228 (defun vhdl-align-region (begin end &optional spacing alignment-list indent)
5229 "Attempt to align a range of lines based on the content of the
5230 lines. The definition of `alignment-list' determines the matching
5231 order and the manner in which the lines are aligned. If ALIGNMENT-LIST
5232 is not specified `vhdl-align-alist' is used. If INDENT is non-nil,
5233 indentation is done before aligning."
5234 (interactive "r\np")
5235 (setq alignment-list (or alignment-list vhdl-align-alist))
5236 (setq spacing (or spacing 1))
5237 (save-excursion
5238 (let (bol indent)
5239 (goto-char end)
5240 (setq end (point-marker))
5241 (goto-char begin)
5242 (setq bol (setq begin (progn (beginning-of-line) (point))))
5243 ; (untabify bol end)
5244 (when indent
5245 (indent-region bol end nil))))
5246 (let ((case-fold-search t)
5247 (copy (copy-alist alignment-list)))
5248 (vhdl-ext-syntax-table
5249 (while copy
5250 (save-excursion
5251 (goto-char begin)
5252 (let (element
5253 (eol (save-excursion (progn (end-of-line) (point)))))
5254 (setq element (nth 0 copy))
5255 (when (and (or (and (listp (car element))
5256 (memq major-mode (car element)))
5257 (eq major-mode (car element)))
5258 (or vhdl-align-try-all-clauses
5259 (re-search-forward (car (cdr element)) eol t)))
5260 (vhdl-align-region-1 begin end (car (cdr (cdr element)))
5261 (car (cdr (cdr (cdr element)))) spacing))
5262 (setq copy (cdr copy))))))))
5264 (defun vhdl-align-region-1 (begin end match &optional substr spacing)
5265 "Align a range of lines from BEGIN to END. The regular expression
5266 MATCH must match exactly one fields: the whitespace to be
5267 contracted/expanded. The alignment column will equal the
5268 rightmost column of the widest whitespace block. SPACING is
5269 the amount of extra spaces to add to the calculated maximum required.
5270 SPACING defaults to 1 so that at least one space is inserted after
5271 the token in MATCH."
5272 (setq spacing (or spacing 1))
5273 (setq substr (or substr 1))
5274 (save-excursion
5275 (let (distance (max 0) (lines 0) bol eol width)
5276 ;; Determine the greatest whitespace distance to the alignment
5277 ;; character
5278 (goto-char begin)
5279 (setq eol (progn (end-of-line) (point))
5280 bol (setq begin (progn (beginning-of-line) (point))))
5281 (while (< bol end)
5282 (save-excursion
5283 (when (and (re-search-forward match eol t)
5284 (not (vhdl-in-comment-p)))
5285 (setq distance (- (match-beginning substr) bol))
5286 (when (> distance max)
5287 (setq max distance))))
5288 (forward-line)
5289 (setq bol (point)
5290 eol (save-excursion (end-of-line) (point)))
5291 (setq lines (1+ lines)))
5292 ;; Now insert enough maxs to push each assignment operator to
5293 ;; the same column. We need to use 'lines' as a counter, since
5294 ;; the location of the mark may change
5295 (goto-char (setq bol begin))
5296 (setq eol (save-excursion (end-of-line) (point)))
5297 (while (> lines 0)
5298 (when (and (re-search-forward match eol t)
5299 (not (vhdl-in-comment-p)))
5300 (setq width (- (match-end substr) (match-beginning substr)))
5301 (setq distance (- (match-beginning substr) bol))
5302 (goto-char (match-beginning substr))
5303 (delete-char width)
5304 (insert-char ? (+ (- max distance) spacing)))
5305 (beginning-of-line)
5306 (forward-line)
5307 (setq bol (point)
5308 eol (save-excursion (end-of-line) (point)))
5309 (setq lines (1- lines))))))
5311 (defun vhdl-align-inline-comment-region-1 (beg end &optional spacing)
5312 "Align inline comments in region."
5313 (save-excursion
5314 (let ((high-start 0)
5315 (high-length 0)
5316 (case-fold-search t))
5317 (vhdl-ext-syntax-table
5318 (goto-char beg)
5319 ;; search for longest code line and longest inline comment
5320 (while (< (point) end)
5321 (cond
5322 ((and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5323 (looking-at "^\\(.*[^ \t\n-]+\\)\\s-*\\(--\\s-*.*\\)$"))
5324 (setq high-start
5325 (max high-start (- (match-end 1) (match-beginning 1))))
5326 (setq high-length
5327 (max high-length (- (match-end 2) (match-beginning 2)))))
5328 ((and (looking-at "^\\(\\s-*\\))\\(--\\s-*.*\\)$")
5329 (>= (- (match-end 1) (match-beginning 1)) comment-column))
5330 (setq high-length
5331 (max high-length (- (match-end 2) (match-beginning 2))))))
5332 (beginning-of-line 2))
5333 (goto-char beg)
5334 (setq spacing (or spacing 2))
5335 (setq high-start (+ high-start spacing))
5336 ;; align as nice as possible
5337 (while (< (point) end)
5338 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5339 (or (looking-at "^.*[^ \t\n-]+\\(\\s-*\\)--")
5340 (and (looking-at "^\\(\\s-*\\)--")
5341 (>= (- (match-end 1) (match-beginning 1))
5342 comment-column))))
5343 (goto-char (match-end 1))
5344 (delete-region (match-beginning 1) (match-end 1))
5345 (insert-char ? spacing)
5346 (cond ((<= high-start comment-column)
5347 (indent-to comment-column))
5348 ((<= (+ high-start high-length) end-comment-column)
5349 (indent-to high-start))
5350 (t (indent-to comment-column))))
5351 (beginning-of-line 2))))))
5353 (defun vhdl-align-noindent-region (beg end &optional spacing no-message)
5354 "Align region without indentation."
5355 (interactive "r\nP")
5356 (save-excursion
5357 (let (pos)
5358 (goto-char beg)
5359 (beginning-of-line)
5360 (setq beg (point))
5361 (goto-char end)
5362 (setq end (point-marker))
5363 (untabify beg end)
5364 (unless no-message (message "Aligning..."))
5365 (vhdl-fixup-whitespace-region beg end t)
5366 (goto-char beg)
5367 (if (not vhdl-align-groups)
5368 ;; align entire region
5369 (progn (vhdl-align-region beg end spacing)
5370 (vhdl-align-inline-comment-region-1 beg end))
5371 ;; align groups
5372 (while (and (< beg end)
5373 (re-search-forward "^\\s-*$" end t))
5374 (setq pos (point-marker))
5375 (vhdl-align-region beg pos spacing)
5376 (vhdl-align-inline-comment-region-1 beg pos)
5377 (setq beg (1+ pos))
5378 (goto-char beg))
5379 ;; align last group
5380 (when (< beg end)
5381 (vhdl-align-region beg end spacing)
5382 (vhdl-align-inline-comment-region-1 beg end)))))
5383 (unless no-message (message "Aligning...done")))
5385 (defun vhdl-align-group (&optional spacing)
5386 "Align group of lines between empty lines."
5387 (interactive)
5388 (save-excursion
5389 (let ((start (point))
5390 beg end)
5391 (setq end (if (re-search-forward "^\\s-*$" nil t)
5392 (point-marker) (point-max)))
5393 (goto-char start)
5394 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5395 (untabify beg end)
5396 (message "Aligning...")
5397 (vhdl-fixup-whitespace-region beg end t)
5398 (vhdl-align-region beg end spacing)
5399 (vhdl-align-inline-comment-region-1 beg end)
5400 (message "Aligning...done"))))
5402 (defun vhdl-align-noindent-buffer ()
5403 "Align buffer without indentation."
5404 (interactive)
5405 (vhdl-align-noindent-region (point-min) (point-max)))
5407 (defun vhdl-align-inline-comment-region (beg end &optional spacing no-message)
5408 "Align inline comments within a region. Groups of code lines separated by
5409 empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
5410 (interactive "r\nP")
5411 (save-excursion
5412 (let (pos)
5413 (goto-char beg)
5414 (beginning-of-line)
5415 (setq beg (point))
5416 (goto-char end)
5417 (setq end (point-marker))
5418 (untabify beg end)
5419 (unless no-message (message "Aligning inline comments..."))
5420 (goto-char beg)
5421 (if (not vhdl-align-groups)
5422 ;; align entire region
5423 (vhdl-align-inline-comment-region-1 beg end spacing)
5424 ;; align groups
5425 (while (and (< beg end) (re-search-forward "^\\s-*$" end t))
5426 (setq pos (point-marker))
5427 (vhdl-align-inline-comment-region-1 beg pos spacing)
5428 (setq beg (1+ pos))
5429 (goto-char beg))
5430 ;; align last group
5431 (when (< beg end)
5432 (vhdl-align-inline-comment-region-1 beg end spacing))))
5433 (unless no-message (message "Aligning inline comments...done"))))
5435 (defun vhdl-align-inline-comment-group (&optional spacing)
5436 "Align inline comments within a group of lines between empty lines."
5437 (interactive)
5438 (save-excursion
5439 (let ((start (point))
5440 beg end)
5441 (setq end (if (re-search-forward "^\\s-*$" nil t)
5442 (point-marker) (point-max)))
5443 (goto-char start)
5444 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5445 (untabify beg end)
5446 (message "Aligning inline comments...")
5447 (vhdl-align-inline-comment-region-1 beg end)
5448 (message "Aligning inline comments...done"))))
5450 (defun vhdl-align-inline-comment-buffer ()
5451 "Align inline comments within buffer. Groups of code lines separated by
5452 empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
5453 (interactive)
5454 (vhdl-align-inline-comment-region (point-min) (point-max)))
5456 (defun vhdl-fixup-whitespace-region (beg end &optional no-message)
5457 "Fixup whitespace in region. Surround operator symbols by one space,
5458 eliminate multiple spaces (except at beginning of line), eliminate spaces at
5459 end of line, do nothing in comments."
5460 (interactive "r")
5461 (unless no-message (message "Fixing up whitespace..."))
5462 (save-excursion
5463 (goto-char end)
5464 (setq end (point-marker))
5465 ;; surround operator symbols by one space
5466 (goto-char beg)
5467 (while (re-search-forward "\\([^/:<>=]\\|^\\)\\(--\\|:\\|=\\|<\\|>\\|:=\\|<=\\|>=\\|=>\\)\\([^=>]\\|$\\)"
5468 end t)
5469 (if (equal "--" (match-string 2))
5470 (re-search-forward ".*\n" end t)
5471 (replace-match "\\1 \\2 \\3")))
5472 ;; have no space before and one space after `,' and ';'
5473 (goto-char beg)
5474 (while (re-search-forward "\\(--\\|\\s-*\\([,;]\\)\\)" end t)
5475 (if (equal "--" (match-string 1))
5476 (re-search-forward ".*\n" end t)
5477 (replace-match "\\2 " nil nil nil 1)))
5478 ;; eliminate multiple spaces and spaces at end of line
5479 (goto-char beg)
5480 (while (or (and (looking-at "--.*\n") (re-search-forward "--.*\n" end t))
5481 (and (looking-at "\\s-+$") (re-search-forward "\\s-+$" end t)
5482 (progn (replace-match "" nil nil) t))
5483 (and (looking-at "\\s-+;") (re-search-forward "\\s-+;" end t)
5484 (progn (replace-match ";" nil nil) t))
5485 (and (looking-at "^\\s-+") (re-search-forward "^\\s-+" end t))
5486 (and (looking-at "\\s-+--") (re-search-forward "\\s-+" end t)
5487 (progn (replace-match " " nil nil) t ))
5488 (and (looking-at "\\s-+") (re-search-forward "\\s-+" end t)
5489 (progn (replace-match " " nil nil) t ))
5490 (re-search-forward "\\S-+" end t))))
5491 (unless no-message (message "Fixing up whitespace...done")))
5493 (defun vhdl-fixup-whitespace-buffer ()
5494 "Fixup whitespace in buffer. Surround operator symbols by one space,
5495 eliminate multiple spaces (except at beginning of line), eliminate spaces at
5496 end of line, do nothing in comments."
5497 (interactive)
5498 (vhdl-fixup-whitespace-region (point-min) (point-max)))
5500 (defun vhdl-beautify-region (beg end)
5501 "Beautify region by applying indentation, whitespace fixup, alignment, and
5502 case fixing to a resion. Calls functions `vhdl-indent-buffer',
5503 `vhdl-align-noindent-buffer' (variable `vhdl-align-groups' set to non-nil), and
5504 `vhdl-fix-case-buffer'."
5505 (interactive "r")
5506 (vhdl-indent-region beg end nil)
5507 (let ((vhdl-align-groups t))
5508 (vhdl-align-noindent-region beg end))
5509 (vhdl-fix-case-region beg end))
5511 (defun vhdl-beautify-buffer ()
5512 "Beautify buffer by applying indentation, whitespace fixup, alignment, and
5513 case fixing to entire buffer. Calls `vhdl-beautify-region' for the entire
5514 buffer."
5515 (interactive)
5516 (vhdl-beautify-region (point-min) (point-max)))
5519 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5520 ;;; Electrification
5521 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5523 (defconst vhdl-template-prompt-syntax "[^ =<>][^<>@.\n]*[^ =<>]"
5524 "Syntax of prompt inserted by template generators.")
5526 (defvar vhdl-template-invoked-by-hook nil
5527 "Indicates whether a template has been invoked by a hook or by key or menu.
5528 Used for undoing after template abortion.")
5530 ;; correct different behavior of function `unread-command-events' in XEmacs
5531 (defalias 'vhdl-character-to-event
5532 (if (string-match "XEmacs" emacs-version) 'character-to-event 'identity))
5534 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5535 ;; Enabling/disabling
5537 (defun vhdl-mode-line-update ()
5538 "Update the modeline string for VHDL major mode."
5539 (setq mode-name (concat "VHDL"
5540 (and (or vhdl-electric-mode vhdl-stutter-mode) "/")
5541 (and vhdl-electric-mode "e")
5542 (and vhdl-stutter-mode "s")))
5543 (force-mode-line-update))
5545 (defun vhdl-electric-mode (arg)
5546 "Toggle VHDL electric mode.
5547 Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5548 (interactive "P")
5549 (setq vhdl-electric-mode
5550 (cond ((or (not arg) (zerop arg)) (not vhdl-electric-mode))
5551 ((> arg 0) t) (t nil)))
5552 (vhdl-mode-line-update))
5554 (defun vhdl-stutter-mode (arg)
5555 "Toggle VHDL stuttering mode.
5556 Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5557 (interactive "P")
5558 (setq vhdl-stutter-mode
5559 (cond ((or (not arg) (zerop arg)) (not vhdl-stutter-mode))
5560 ((> arg 0) t) (t nil)))
5561 (vhdl-mode-line-update))
5563 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5564 ;; Stuttering
5566 (defun vhdl-electric-dash (count)
5567 "-- starts a comment, --- draws a horizontal line,
5568 ---- starts a display comment"
5569 (interactive "p")
5570 (if vhdl-stutter-mode
5571 (cond
5572 ((and abbrev-start-location (= abbrev-start-location (point)))
5573 (setq abbrev-start-location nil)
5574 (goto-char last-abbrev-location)
5575 (beginning-of-line nil)
5576 (vhdl-comment-display))
5577 ((/= (preceding-char) ?-) ; standard dash (minus)
5578 (self-insert-command count))
5579 (t (self-insert-command count)
5580 (message "Enter '-' for horiz. line, 'CR' for commenting-out code, else enter comment")
5581 (let ((next-input (read-char)))
5582 (if (= next-input ?-) ; triple dash
5583 (progn
5584 (vhdl-comment-display-line)
5585 (message
5586 "Enter '-' for display comment, else continue coding")
5587 (let ((next-input (read-char)))
5588 (if (= next-input ?-) ; four dashes
5589 (vhdl-comment-display t)
5590 (setq unread-command-events ; pushback the char
5591 (list (vhdl-character-to-event next-input))))))
5592 (setq unread-command-events ; pushback the char
5593 (list (vhdl-character-to-event next-input)))
5594 (vhdl-comment-insert)))))
5595 (self-insert-command count)))
5597 (defun vhdl-electric-open-bracket (count) "'[' --> '(', '([' --> '['"
5598 (interactive "p")
5599 (if (and vhdl-stutter-mode (= count 1))
5600 (if (= (preceding-char) ?\()
5601 (progn (delete-char -1) (insert-char ?\[ 1))
5602 (insert-char ?\( 1))
5603 (self-insert-command count)))
5605 (defun vhdl-electric-close-bracket (count) "']' --> ')', ')]' --> ']'"
5606 (interactive "p")
5607 (if (and vhdl-stutter-mode (= count 1))
5608 (progn
5609 (if (= (preceding-char) ?\))
5610 (progn (delete-char -1) (insert-char ?\] 1))
5611 (insert-char ?\) 1))
5612 (blink-matching-open))
5613 (self-insert-command count)))
5615 (defun vhdl-electric-quote (count) "'' --> \""
5616 (interactive "p")
5617 (if (and vhdl-stutter-mode (= count 1))
5618 (if (= (preceding-char) last-input-char)
5619 (progn (delete-backward-char 1) (insert-char ?\" 1))
5620 (insert-char ?\' 1))
5621 (self-insert-command count)))
5623 (defun vhdl-electric-semicolon (count) "';;' --> ' : ', ': ;' --> ' := '"
5624 (interactive "p")
5625 (if (and vhdl-stutter-mode (= count 1))
5626 (cond ((= (preceding-char) last-input-char)
5627 (progn (delete-char -1)
5628 (when (not (eq (preceding-char) ? )) (insert " "))
5629 (insert ": ")
5630 (setq this-command 'vhdl-electric-colon)))
5631 ((and
5632 (eq last-command 'vhdl-electric-colon) (= (preceding-char) ? ))
5633 (progn (delete-char -1) (insert "= ")))
5634 (t (insert-char ?\; 1)))
5635 (self-insert-command count)))
5637 (defun vhdl-electric-comma (count) "',,' --> ' <= '"
5638 (interactive "p")
5639 (if (and vhdl-stutter-mode (= count 1))
5640 (cond ((= (preceding-char) last-input-char)
5641 (progn (delete-char -1)
5642 (when (not (eq (preceding-char) ? )) (insert " "))
5643 (insert "<= ")))
5644 (t (insert-char ?\, 1)))
5645 (self-insert-command count)))
5647 (defun vhdl-electric-period (count) "'..' --> ' => '"
5648 (interactive "p")
5649 (if (and vhdl-stutter-mode (= count 1))
5650 (cond ((= (preceding-char) last-input-char)
5651 (progn (delete-char -1)
5652 (when (not (eq (preceding-char) ? )) (insert " "))
5653 (insert "=> ")))
5654 (t (insert-char ?\. 1)))
5655 (self-insert-command count)))
5657 (defun vhdl-electric-equal (count) "'==' --> ' == '"
5658 (interactive "p")
5659 (if (and vhdl-stutter-mode (= count 1))
5660 (cond ((= (preceding-char) last-input-char)
5661 (progn (delete-char -1)
5662 (when (not (eq (preceding-char) ? )) (insert " "))
5663 (insert "== ")))
5664 (t (insert-char ?\= 1)))
5665 (self-insert-command count)))
5667 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5668 ;; VHDL templates
5670 (defun vhdl-template-paired-parens ()
5671 "Insert a pair of round parentheses, placing point between them."
5672 (interactive)
5673 (insert "()")
5674 (backward-char))
5676 (defun vhdl-template-alias ()
5677 "Insert alias declaration."
5678 (interactive)
5679 (let ((start (point)))
5680 (vhdl-insert-keyword "ALIAS ")
5681 (when (vhdl-template-field "name" nil t start (point))
5682 (insert " : ")
5683 (unless (vhdl-template-field
5684 (concat "[type" (and (vhdl-standard-p 'ams) " or nature") "]")
5685 nil t)
5686 (backward-delete-char 3))
5687 (vhdl-insert-keyword " IS ")
5688 (vhdl-template-field "name" ";")
5689 (vhdl-comment-insert-inline))))
5691 (defun vhdl-template-architecture ()
5692 "Insert architecture."
5693 (interactive)
5694 (let ((margin (current-indentation))
5695 (start (point))
5696 arch-name entity-exists string
5697 (case-fold-search t))
5698 (vhdl-insert-keyword "ARCHITECTURE ")
5699 (when (setq arch-name
5700 (vhdl-template-field "name" nil t start (point)))
5701 (vhdl-insert-keyword " OF ")
5702 (save-excursion
5703 (vhdl-ext-syntax-table
5704 (setq entity-exists (re-search-backward
5705 "\\<entity \\(\\w+\\) is\\>" nil t))
5706 (setq string (match-string 1))))
5707 (if (and entity-exists (not (equal string "")))
5708 (insert string)
5709 (vhdl-template-field "entity name"))
5710 (vhdl-insert-keyword " IS")
5711 (vhdl-template-begin-end
5712 (unless (vhdl-standard-p '87) "ARCHITECTURE") arch-name margin
5713 (memq vhdl-insert-empty-lines '(unit all))))))
5715 (defun vhdl-template-array (kind &optional secondary)
5716 "Insert array type definition."
5717 (interactive)
5718 (let ((start (point)))
5719 (vhdl-insert-keyword "ARRAY (")
5720 (when (or (vhdl-template-field "range" nil (not secondary) start (point))
5721 secondary)
5722 (vhdl-insert-keyword ") OF ")
5723 (vhdl-template-field (if (eq kind 'type) "type" "nature"))
5724 (vhdl-insert-keyword ";"))))
5726 (defun vhdl-template-assert ()
5727 "Insert an assertion statement."
5728 (interactive)
5729 (let ((start (point)))
5730 (vhdl-insert-keyword "ASSERT ")
5731 (when vhdl-conditions-in-parenthesis (insert "("))
5732 (when (vhdl-template-field "condition (negated)" nil t start (point))
5733 (when vhdl-conditions-in-parenthesis (insert ")"))
5734 (setq start (point))
5735 (vhdl-insert-keyword " REPORT ")
5736 (unless (vhdl-template-field "string expression" nil nil nil nil t)
5737 (delete-region start (point)))
5738 (setq start (point))
5739 (vhdl-insert-keyword " SEVERITY ")
5740 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
5741 (delete-region start (point)))
5742 (insert ";"))))
5744 (defun vhdl-template-attribute ()
5745 "Insert an attribute declaration or specification."
5746 (interactive)
5747 (if (eq (vhdl-decision-query
5748 "attribute" "(d)eclaration or (s)pecification?" t) ?s)
5749 (vhdl-template-attribute-spec)
5750 (vhdl-template-attribute-decl)))
5752 (defun vhdl-template-attribute-decl ()
5753 "Insert an attribute declaration."
5754 (interactive)
5755 (let ((start (point)))
5756 (vhdl-insert-keyword "ATTRIBUTE ")
5757 (when (vhdl-template-field "name" " : " t start (point))
5758 (vhdl-template-field "type" ";")
5759 (vhdl-comment-insert-inline))))
5761 (defun vhdl-template-attribute-spec ()
5762 "Insert an attribute specification."
5763 (interactive)
5764 (let ((start (point)))
5765 (vhdl-insert-keyword "ATTRIBUTE ")
5766 (when (vhdl-template-field "name" nil t start (point))
5767 (vhdl-insert-keyword " OF ")
5768 (vhdl-template-field "entity names | OTHERS | ALL" " : ")
5769 (vhdl-template-field "entity class")
5770 (vhdl-insert-keyword " IS ")
5771 (vhdl-template-field "expression" ";"))))
5773 (defun vhdl-template-block ()
5774 "Insert a block."
5775 (interactive)
5776 (let ((margin (current-indentation))
5777 (start (point))
5778 label)
5779 (vhdl-insert-keyword ": BLOCK ")
5780 (goto-char start)
5781 (when (setq label (vhdl-template-field "label" nil t start (+ (point) 8)))
5782 (forward-word 1)
5783 (forward-char 1)
5784 (insert "(")
5785 (if (vhdl-template-field "[guard expression]" nil t)
5786 (insert ")")
5787 (delete-char -2))
5788 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
5789 (vhdl-template-begin-end "BLOCK" label margin)
5790 (vhdl-comment-block))))
5792 (defun vhdl-template-block-configuration ()
5793 "Insert a block configuration statement."
5794 (interactive)
5795 (let ((margin (current-indentation))
5796 (start (point)))
5797 (vhdl-insert-keyword "FOR ")
5798 (when (vhdl-template-field "block name" nil t start (point))
5799 (vhdl-insert-keyword "\n\n")
5800 (indent-to margin)
5801 (vhdl-insert-keyword "END FOR;")
5802 (end-of-line 0)
5803 (indent-to (+ margin vhdl-basic-offset)))))
5805 (defun vhdl-template-break ()
5806 "Insert a break statement."
5807 (interactive)
5808 (let (position)
5809 (vhdl-insert-keyword "BREAK")
5810 (setq position (point))
5811 (insert " ")
5812 (while (or
5813 (progn (vhdl-insert-keyword "FOR ")
5814 (if (vhdl-template-field "[quantity name]" " USE " t)
5815 (progn (vhdl-template-field "quantity name" " => ") t)
5816 (kill-word -1) nil))
5817 (vhdl-template-field "[quantity name]" " => " t))
5818 (vhdl-template-field "expression")
5819 (setq position (point))
5820 (insert ", "))
5821 (delete-region position (point))
5822 (unless (vhdl-sequential-statement-p)
5823 (vhdl-insert-keyword " ON ")
5824 (if (vhdl-template-field "[sensitivity list]" nil t)
5825 (setq position (point))
5826 (delete-region position (point))))
5827 (vhdl-insert-keyword " WHEN ")
5828 (when vhdl-conditions-in-parenthesis (insert "("))
5829 (if (vhdl-template-field "[condition]" nil t)
5830 (when vhdl-conditions-in-parenthesis (insert ")"))
5831 (delete-region position (point)))
5832 (insert ";")))
5834 (defun vhdl-template-case (&optional kind)
5835 "Insert a case statement."
5836 (interactive)
5837 (let ((margin (current-indentation))
5838 (start (point))
5839 label)
5840 (unless kind (setq kind (if (vhdl-sequential-statement-p) 'is 'use)))
5841 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
5842 (vhdl-insert-keyword "CASE ")
5843 (vhdl-insert-keyword ": CASE ")
5844 (goto-char start)
5845 (setq label (vhdl-template-field "[label]" nil t))
5846 (unless label (delete-char 2))
5847 (forward-word 1)
5848 (forward-char 1))
5849 (when (vhdl-template-field "expression" nil t start (point))
5850 (vhdl-insert-keyword (concat " " (if (eq kind 'is) "IS" "USE") "\n\n"))
5851 (indent-to margin)
5852 (vhdl-insert-keyword "END CASE")
5853 (when label (insert " " label))
5854 (insert ";")
5855 (forward-line -1)
5856 (indent-to (+ margin vhdl-basic-offset))
5857 (vhdl-insert-keyword "WHEN ")
5858 (let ((position (point)))
5859 (insert " => ;\n")
5860 (indent-to (+ margin vhdl-basic-offset))
5861 (vhdl-insert-keyword "WHEN OTHERS => null;")
5862 (goto-char position)))))
5864 (defun vhdl-template-case-is ()
5865 "Insert a sequential case statement."
5866 (interactive)
5867 (vhdl-template-case 'is))
5869 (defun vhdl-template-case-use ()
5870 "Insert a simultaneous case statement."
5871 (interactive)
5872 (vhdl-template-case 'use))
5874 (defun vhdl-template-component ()
5875 "Insert a component declaration."
5876 (interactive)
5877 (vhdl-template-component-decl))
5879 (defun vhdl-template-component-conf ()
5880 "Insert a component configuration (uses `vhdl-template-configuration-spec'
5881 since these are almost equivalent)."
5882 (interactive)
5883 (let ((margin (current-indentation))
5884 (result (vhdl-template-configuration-spec t)))
5885 (when result
5886 (insert "\n")
5887 (indent-to margin)
5888 (vhdl-insert-keyword "END FOR;")
5889 (when (eq result 'no-use)
5890 (end-of-line -0)))))
5892 (defun vhdl-template-component-decl ()
5893 "Insert a component declaration."
5894 (interactive)
5895 (let ((margin (current-indentation))
5896 (start (point))
5897 name end-column)
5898 (vhdl-insert-keyword "COMPONENT ")
5899 (when (setq name (vhdl-template-field "name" nil t start (point)))
5900 (insert "\n\n")
5901 (indent-to margin)
5902 (vhdl-insert-keyword "END COMPONENT")
5903 (unless (vhdl-standard-p '87) (insert " " name))
5904 (insert ";")
5905 (setq end-column (current-column))
5906 (end-of-line -0)
5907 (indent-to (+ margin vhdl-basic-offset))
5908 (vhdl-template-generic-list t t)
5909 (insert "\n")
5910 (indent-to (+ margin vhdl-basic-offset))
5911 (vhdl-template-port-list t)
5912 (beginning-of-line 2)
5913 (forward-char end-column))))
5915 (defun vhdl-template-component-inst ()
5916 "Insert a component instantiation statement."
5917 (interactive)
5918 (let ((margin (current-indentation))
5919 (start (point))
5920 unit position)
5921 (when (vhdl-template-field "instance label" nil t start (point))
5922 (insert ": ")
5923 (if (vhdl-standard-p '87)
5924 (vhdl-template-field "component name")
5925 ;; direct instantiation
5926 (setq unit (vhdl-template-field
5927 "[COMPONENT | ENTITY | CONFIGURATION]" " " t))
5928 (setq unit (upcase (or unit "")))
5929 (cond ((equal unit "ENTITY")
5930 (vhdl-template-field "library name" "." nil nil nil nil "work")
5931 (vhdl-template-field "entity name" "(")
5932 (if (vhdl-template-field "[architecture name]" nil t)
5933 (insert ")")
5934 (delete-char -1)))
5935 ((equal unit "CONFIGURATION")
5936 (vhdl-template-field "library name" "." nil nil nil nil "work")
5937 (vhdl-template-field "configuration name"))
5938 (t (vhdl-template-field "component name"))))
5939 (insert "\n")
5940 (indent-to (+ margin vhdl-basic-offset))
5941 (setq position (point))
5942 (vhdl-insert-keyword "GENERIC ")
5943 (when (vhdl-template-map position t t)
5944 (insert "\n")
5945 (indent-to (+ margin vhdl-basic-offset)))
5946 (setq position (point))
5947 (vhdl-insert-keyword "PORT ")
5948 (unless (vhdl-template-map position t t)
5949 (kill-line -0)
5950 (delete-char -1))
5951 (insert ";"))))
5953 (defun vhdl-template-conditional-signal-asst ()
5954 "Insert a conditional signal assignment."
5955 (interactive)
5956 (when (vhdl-template-field "target signal")
5957 (insert " <= ")
5958 ; (if (not (equal (vhdl-template-field "[GUARDED] [TRANSPORT]") ""))
5959 ; (insert " "))
5960 (let ((margin (current-column))
5961 (start (point))
5962 position)
5963 (vhdl-template-field "waveform")
5964 (setq position (point))
5965 (vhdl-insert-keyword " WHEN ")
5966 (when vhdl-conditions-in-parenthesis (insert "("))
5967 (while (and (vhdl-template-field "[condition]" nil t)
5968 (progn
5969 (when vhdl-conditions-in-parenthesis (insert ")"))
5970 (setq position (point))
5971 (vhdl-insert-keyword " ELSE")
5972 (insert "\n")
5973 (indent-to margin)
5974 (vhdl-template-field "[waveform]" nil t)))
5975 (setq position (point))
5976 (vhdl-insert-keyword " WHEN ")
5977 (when vhdl-conditions-in-parenthesis (insert "(")))
5978 (delete-region position (point))
5979 (insert ";")
5980 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
5982 (defun vhdl-template-configuration ()
5983 "Insert a configuration specification if within an architecture,
5984 a block or component configuration if within a configuration declaration,
5985 a configuration declaration if not within a design unit."
5986 (interactive)
5987 (let ((case-fold-search t))
5988 (vhdl-ext-syntax-table
5989 (cond
5990 ((and (save-excursion ; architecture body
5991 (re-search-backward "^\\(architecture\\|end\\)\\>" nil t))
5992 (equal "ARCHITECTURE" (upcase (match-string 1))))
5993 (vhdl-template-configuration-spec))
5994 ((and (save-excursion ; configuration declaration
5995 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
5996 (equal "CONFIGURATION" (upcase (match-string 1))))
5997 (if (eq (vhdl-decision-query
5998 "configuration" "(b)lock or (c)omponent configuration?" t) ?c)
5999 (vhdl-template-component-conf)
6000 (vhdl-template-block-configuration)))
6001 (t (vhdl-template-configuration-decl)))))) ; otherwise
6003 (defun vhdl-template-configuration-spec (&optional optional-use)
6004 "Insert a configuration specification."
6005 (interactive)
6006 (let ((margin (current-indentation))
6007 (start (point))
6008 aspect position)
6009 (vhdl-insert-keyword "FOR ")
6010 (when (vhdl-template-field "component names | OTHERS | ALL" " : "
6011 t start (point))
6012 (vhdl-template-field "component type" "\n")
6013 (indent-to (+ margin vhdl-basic-offset))
6014 (setq start (point))
6015 (vhdl-insert-keyword "USE ")
6016 (if (and optional-use
6017 (not (setq aspect (vhdl-template-field
6018 "[ENTITY | CONFIGURATION | OPEN]" " " t))))
6019 (progn (delete-region start (point)) 'no-use)
6020 (unless optional-use
6021 (setq aspect (vhdl-template-field
6022 "ENTITY | CONFIGURATION | OPEN" " ")))
6023 (setq aspect (upcase (or aspect "")))
6024 (cond ((equal aspect "ENTITY")
6025 (vhdl-template-field "library name" "." nil nil nil nil "work")
6026 (vhdl-template-field "entity name" "(")
6027 (if (vhdl-template-field "[architecture name]" nil t)
6028 (insert ")")
6029 (delete-char -1))
6030 (insert "\n")
6031 (indent-to (+ margin (* 2 vhdl-basic-offset)))
6032 (setq position (point))
6033 (vhdl-insert-keyword "GENERIC ")
6034 (when (vhdl-template-map position t t)
6035 (insert "\n")
6036 (indent-to (+ margin (* 2 vhdl-basic-offset))))
6037 (setq position (point))
6038 (vhdl-insert-keyword "PORT ")
6039 (unless (vhdl-template-map position t t)
6040 (kill-line -0)
6041 (delete-char -1))
6042 (insert ";")
6044 ((equal aspect "CONFIGURATION")
6045 (vhdl-template-field "library name" "." nil nil nil nil "work")
6046 (vhdl-template-field "configuration name" ";"))
6047 (t (backward-delete-char 1) (insert ";") t))))))
6050 (defun vhdl-template-configuration-decl ()
6051 "Insert a configuration declaration."
6052 (interactive)
6053 (let ((margin (current-indentation))
6054 (start (point))
6055 (case-fold-search t)
6056 entity-exists string name position)
6057 (vhdl-insert-keyword "CONFIGURATION ")
6058 (when (setq name (vhdl-template-field "name" nil t start (point)))
6059 (vhdl-insert-keyword " OF ")
6060 (save-excursion
6061 (vhdl-ext-syntax-table
6062 (setq entity-exists (re-search-backward
6063 "\\<entity \\(\\w*\\) is\\>" nil t))
6064 (setq string (match-string 1))))
6065 (if (and entity-exists (not (equal string "")))
6066 (insert string)
6067 (vhdl-template-field "entity name"))
6068 (vhdl-insert-keyword " IS\n")
6069 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6070 (indent-to (+ margin vhdl-basic-offset))
6071 (setq position (point))
6072 (insert "\n")
6073 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6074 (indent-to margin)
6075 (vhdl-insert-keyword "END ")
6076 (unless (vhdl-standard-p '87)
6077 (vhdl-insert-keyword "CONFIGURATION "))
6078 (insert name ";")
6079 (goto-char position))))
6081 (defun vhdl-template-constant ()
6082 "Insert a constant declaration."
6083 (interactive)
6084 (let ((start (point))
6085 (in-arglist (vhdl-in-argument-list-p)))
6086 (vhdl-insert-keyword "CONSTANT ")
6087 (when (vhdl-template-field "name" nil t start (point))
6088 (insert " : ")
6089 (when in-arglist (vhdl-insert-keyword "IN "))
6090 (vhdl-template-field "type")
6091 (if in-arglist
6092 (progn (insert ";")
6093 (vhdl-comment-insert-inline))
6094 (let ((position (point)))
6095 (insert " := ")
6096 (unless (vhdl-template-field "[initialization]" nil t)
6097 (delete-region position (point)))
6098 (insert ";")
6099 (vhdl-comment-insert-inline))))))
6101 (defun vhdl-template-default ()
6102 "Insert nothing."
6103 (interactive)
6104 (insert " ")
6105 (unexpand-abbrev)
6106 (backward-word 1)
6107 (vhdl-case-word 1)
6108 (forward-char 1))
6110 (defun vhdl-template-default-indent ()
6111 "Insert nothing and indent."
6112 (interactive)
6113 (insert " ")
6114 (unexpand-abbrev)
6115 (backward-word 1)
6116 (vhdl-case-word 1)
6117 (forward-char 1)
6118 (vhdl-indent-line))
6120 (defun vhdl-template-disconnect ()
6121 "Insert a disconnect statement."
6122 (interactive)
6123 (let ((start (point)))
6124 (vhdl-insert-keyword "DISCONNECT ")
6125 (when (vhdl-template-field "signal names | OTHERS | ALL"
6126 " : " t start (point))
6127 (vhdl-template-field "type")
6128 (vhdl-insert-keyword " AFTER ")
6129 (vhdl-template-field "time expression" ";"))))
6131 (defun vhdl-template-else ()
6132 "Insert an else statement."
6133 (interactive)
6134 (let ((case-fold-search t)
6135 margin)
6136 (vhdl-ext-syntax-table
6137 (vhdl-insert-keyword "ELSE")
6138 (if (save-excursion
6139 (re-search-backward "\\(\\<when\\>\\|;\\)" nil t)
6140 (equal "WHEN" (upcase (match-string 1))))
6141 (insert " ")
6142 (vhdl-indent-line)
6143 (setq margin (current-indentation))
6144 (insert "\n")
6145 (indent-to (+ margin vhdl-basic-offset))))))
6147 (defun vhdl-template-elsif ()
6148 "Insert an elsif statement."
6149 (interactive)
6150 (let ((start (point))
6151 margin)
6152 (vhdl-insert-keyword "ELSIF ")
6153 (when vhdl-conditions-in-parenthesis (insert "("))
6154 (when (vhdl-template-field "condition" nil t start (point))
6155 (when vhdl-conditions-in-parenthesis (insert ")"))
6156 (vhdl-indent-line)
6157 (setq margin (current-indentation))
6158 (vhdl-insert-keyword
6159 (concat " " (if (vhdl-sequential-statement-p) "THEN" "USE") "\n"))
6160 (indent-to (+ margin vhdl-basic-offset)))))
6162 (defun vhdl-template-entity ()
6163 "Insert an entity."
6164 (interactive)
6165 (let ((margin (current-indentation))
6166 (start (point))
6167 name end-column)
6168 (vhdl-insert-keyword "ENTITY ")
6169 (when (setq name (vhdl-template-field "name" nil t start (point)))
6170 (vhdl-insert-keyword " IS\n\n")
6171 (indent-to margin)
6172 (vhdl-insert-keyword "END ")
6173 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
6174 (insert name ";")
6175 (setq end-column (current-column))
6176 (end-of-line -0)
6177 (indent-to (+ margin vhdl-basic-offset))
6178 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6179 (indent-to (+ margin vhdl-basic-offset))
6180 (when (vhdl-template-generic-list t)
6181 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6182 (insert "\n")
6183 (indent-to (+ margin vhdl-basic-offset))
6184 (when (vhdl-template-port-list t)
6185 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6186 (beginning-of-line 2)
6187 (forward-char end-column))))
6189 (defun vhdl-template-exit ()
6190 "Insert an exit statement."
6191 (interactive)
6192 (let ((start (point)))
6193 (vhdl-insert-keyword "EXIT ")
6194 (unless (vhdl-template-field "[loop label]" nil t)
6195 (delete-char -1))
6196 (let ((position (point)))
6197 (vhdl-insert-keyword " WHEN ")
6198 (when vhdl-conditions-in-parenthesis (insert "("))
6199 (if (vhdl-template-field "[condition]" nil t)
6200 (when vhdl-conditions-in-parenthesis (insert ")"))
6201 (delete-region position (point))))
6202 (insert ";")))
6204 (defun vhdl-template-file ()
6205 "Insert a file declaration."
6206 (interactive)
6207 (let ((start (point)))
6208 (vhdl-insert-keyword "FILE ")
6209 (when (vhdl-template-field "name" nil t start (point))
6210 (insert " : ")
6211 (vhdl-template-field "type")
6212 (unless (vhdl-standard-p '87)
6213 (vhdl-insert-keyword " OPEN ")
6214 (unless (vhdl-template-field "[READ_MODE | WRITE_MODE | APPEND_MODE]"
6215 nil t)
6216 (backward-delete-char 6)))
6217 (vhdl-insert-keyword " IS ")
6218 (when (vhdl-standard-p '87)
6219 (vhdl-template-field "[IN | OUT]" " " t))
6220 (vhdl-template-field "filename-string" nil nil nil nil t)
6221 (insert ";")
6222 (vhdl-comment-insert-inline))))
6224 (defun vhdl-template-for ()
6225 "Insert a block or component configuration if within a configuration
6226 declaration, a configuration specification if within an architecture
6227 declarative part (and not within a subprogram), and a for-loop otherwise."
6228 (interactive)
6229 (let ((case-fold-search t))
6230 (vhdl-ext-syntax-table
6231 (cond
6232 ((and (save-excursion ; configuration declaration
6233 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
6234 (equal "CONFIGURATION" (upcase (match-string 1))))
6235 (if (eq (vhdl-decision-query
6236 "for" "(b)lock or (c)omponent configuration?" t) ?c)
6237 (vhdl-template-component-conf)
6238 (vhdl-template-block-configuration)))
6239 ((and (save-excursion
6240 (re-search-backward ; architecture declarative part
6241 "^\\(architecture\\|entity\\|begin\\|end\\)\\>" nil t))
6242 (equal "ARCHITECTURE" (upcase (match-string 1)))
6243 (not (and (save-excursion ; not subprogram
6244 (re-search-backward
6245 "^\\s-*\\(architecture\\|begin\\|end\\)\\>" nil t))
6246 (equal "BEGIN" (upcase (match-string 1)))
6247 (save-excursion
6248 (re-search-backward
6249 "^\\s-*\\(function\\|procedure\\)\\>" nil t)))))
6250 (vhdl-template-configuration-spec))
6251 ((vhdl-sequential-statement-p) ; sequential statement
6252 (vhdl-template-for-loop))
6253 (t (vhdl-template-for-generate)))))) ; concurrent statement
6255 (defun vhdl-template-for-generate ()
6256 "Insert a for-generate."
6257 (interactive)
6258 (let ((margin (current-indentation))
6259 (start (point))
6260 label string position)
6261 (vhdl-insert-keyword ": FOR ")
6262 (setq position (point-marker))
6263 (goto-char start)
6264 (when (setq label (vhdl-template-field "label" nil t start position))
6265 (goto-char position)
6266 (vhdl-template-field "loop variable")
6267 (vhdl-insert-keyword " IN ")
6268 (vhdl-template-field "range")
6269 (vhdl-template-generate-body margin label))))
6271 (defun vhdl-template-for-loop ()
6272 "Insert a for loop."
6273 (interactive)
6274 (let ((margin (current-indentation))
6275 (start (point))
6276 label index)
6277 (if (not (eq vhdl-optional-labels 'all))
6278 (vhdl-insert-keyword "FOR ")
6279 (vhdl-insert-keyword ": FOR ")
6280 (goto-char start)
6281 (setq label (vhdl-template-field "[label]" nil t))
6282 (unless label (delete-char 2))
6283 (forward-word 1)
6284 (forward-char 1))
6285 (when (setq index (vhdl-template-field "loop variable"
6286 nil t start (point)))
6287 (vhdl-insert-keyword " IN ")
6288 (vhdl-template-field "range")
6289 (vhdl-insert-keyword " LOOP\n\n")
6290 (indent-to margin)
6291 (vhdl-insert-keyword "END LOOP")
6292 (if label
6293 (insert " " label ";")
6294 (insert ";")
6295 (when vhdl-self-insert-comments (insert " -- " index)))
6296 (forward-line -1)
6297 (indent-to (+ margin vhdl-basic-offset)))))
6299 (defun vhdl-template-footer ()
6300 "Insert a VHDL file footer."
6301 (interactive)
6302 (unless (equal vhdl-file-footer "")
6303 (save-excursion
6304 (goto-char (point-max))
6305 (insert "\n")
6306 (vhdl-insert-string-or-file vhdl-file-footer))))
6308 (defun vhdl-template-function (&optional kind)
6309 "Insert a function declaration or body."
6310 (interactive)
6311 (let ((margin (current-indentation))
6312 (start (point))
6313 name)
6314 (vhdl-insert-keyword "FUNCTION ")
6315 (when (setq name (vhdl-template-field "name" nil t start (point)))
6316 (vhdl-template-argument-list t)
6317 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6318 (end-of-line)
6319 (insert "\n")
6320 (indent-to (+ margin vhdl-basic-offset))
6321 (vhdl-insert-keyword "RETURN ")
6322 (vhdl-template-field "type")
6323 (if (if kind (eq kind 'body)
6324 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6325 (progn (vhdl-insert-keyword " IS")
6326 (vhdl-template-begin-end
6327 (unless (vhdl-standard-p '87) "FUNCTION") name margin)
6328 (vhdl-comment-block))
6329 (insert ";")))))
6331 (defun vhdl-template-function-decl ()
6332 "Insert a function declaration."
6333 (interactive)
6334 (vhdl-template-function 'decl))
6336 (defun vhdl-template-function-body ()
6337 "Insert a function declaration."
6338 (interactive)
6339 (vhdl-template-function 'body))
6341 (defun vhdl-template-generate ()
6342 "Insert a generation scheme."
6343 (interactive)
6344 (if (eq (vhdl-decision-query nil "(f)or or (i)f?" t) ?i)
6345 (vhdl-template-if-generate)
6346 (vhdl-template-for-generate)))
6348 (defun vhdl-template-generic ()
6349 "Insert generic declaration, or generic map in instantiation statements."
6350 (interactive)
6351 (let ((start (point))
6352 (case-fold-search t))
6353 (vhdl-ext-syntax-table
6354 (cond
6355 ((and (save-excursion ; entity declaration
6356 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6357 (equal "ENTITY" (upcase (match-string 1))))
6358 (vhdl-template-generic-list nil))
6359 ((or (save-excursion
6360 (or (beginning-of-line)
6361 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6362 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6363 (vhdl-insert-keyword "GENERIC ")
6364 (vhdl-template-map start))
6365 (t (vhdl-template-generic-list nil t))))))
6367 (defun vhdl-template-group ()
6368 "Insert group or group template declaration."
6369 (interactive)
6370 (let ((start (point)))
6371 (if (eq (vhdl-decision-query
6372 "group" "(d)eclaration or (t)emplate declaration?" t) ?t)
6373 (vhdl-template-group-template)
6374 (vhdl-template-group-decl))))
6376 (defun vhdl-template-group-decl ()
6377 "Insert group declaration."
6378 (interactive)
6379 (let ((start (point)))
6380 (vhdl-insert-keyword "GROUP ")
6381 (when (vhdl-template-field "name" " : " t start (point))
6382 (vhdl-template-field "template name" " (")
6383 (vhdl-template-field "constituent list" ");")
6384 (vhdl-comment-insert-inline))))
6386 (defun vhdl-template-group-template ()
6387 "Insert group template declaration."
6388 (interactive)
6389 (let ((start (point)))
6390 (vhdl-insert-keyword "GROUP ")
6391 (when (vhdl-template-field "template name" nil t start (point))
6392 (vhdl-insert-keyword " IS (")
6393 (vhdl-template-field "entity class list" ");")
6394 (vhdl-comment-insert-inline))))
6396 (defun vhdl-template-header ()
6397 "Insert a VHDL file header."
6398 (interactive)
6399 (unless (equal vhdl-file-header "")
6400 (let ((case-fold-search t)
6401 (project-name (or (nth 0 (aget vhdl-project-alist vhdl-project)) ""))
6402 (project-desc (or (nth 2 (aget vhdl-project-alist vhdl-project)) ""))
6403 eot)
6404 (vhdl-ext-syntax-table
6405 (save-excursion
6406 (save-restriction
6407 (widen)
6408 (goto-char (point-min))
6409 (vhdl-insert-string-or-file vhdl-file-header)
6410 (setq eot (point))
6411 (narrow-to-region (point-min) eot)
6412 (goto-char (point-min))
6413 (while (search-forward "<projectdesc>" nil t)
6414 (replace-match project-desc t t))
6415 (goto-char (point-min))
6416 (while (search-forward "<filename>" nil t)
6417 (replace-match (buffer-name) t t))
6418 (goto-char (point-min))
6419 (while (search-forward "<author>" nil t)
6420 (replace-match "" t t)
6421 (insert (user-full-name))
6422 (when user-mail-address (insert " <" user-mail-address ">")))
6423 (goto-char (point-min))
6424 (while (search-forward "<login>" nil t)
6425 (replace-match (user-login-name) t t))
6426 (goto-char (point-min))
6427 (while (search-forward "<project>" nil t)
6428 (replace-match project-name t t))
6429 (goto-char (point-min))
6430 (while (search-forward "<company>" nil t)
6431 (replace-match vhdl-company-name t t))
6432 (goto-char (point-min))
6433 (while (search-forward "<platform>" nil t)
6434 (replace-match vhdl-platform-spec t t))
6435 (goto-char (point-min))
6436 ;; Replace <RCS> with $, so that RCS for the source is
6437 ;; not over-enthusiastic with replacements
6438 (while (search-forward "<RCS>" nil t)
6439 (replace-match "$" nil t))
6440 (goto-char (point-min))
6441 (while (search-forward "<date>" nil t)
6442 (replace-match "" t t)
6443 (vhdl-template-insert-date))
6444 (goto-char (point-min))
6445 (let (string)
6446 (while
6447 (re-search-forward "<\\(\\(\\w\\|\\s_\\)*\\) string>" nil t)
6448 (setq string (read-string (concat (match-string 1) ": ")))
6449 (replace-match string t t)))))
6450 (goto-char (point-min))
6451 (when (search-forward "<cursor>" nil t)
6452 (replace-match "" t t))
6453 (when (or (not project-name) (equal project-name ""))
6454 (message "You can specify a project title in custom variable `vhdl-project-alist'"))
6455 (when (or (not project-desc) (equal project-desc ""))
6456 (message "You can specify a project description in custom variable `vhdl-project-alist'"))
6457 (when (equal vhdl-company-name "")
6458 (message "You can specify a company name in custom variable `vhdl-company-name'"))
6459 (when (equal vhdl-platform-spec "")
6460 (message "You can specify a platform in custom variable `vhdl-platform-spec'"))))))
6462 (defun vhdl-template-if ()
6463 "Insert a sequential if statement or an if-generate statement."
6464 (interactive)
6465 (if (vhdl-sequential-statement-p)
6466 (vhdl-template-if-then)
6467 (if (and (vhdl-standard-p 'ams)
6468 (eq (vhdl-decision-query "if" "(g)enerate or (u)se?" t) ?u))
6469 (vhdl-template-if-use)
6470 (vhdl-template-if-generate))))
6472 (defun vhdl-template-if-generate ()
6473 "Insert an if-generate."
6474 (interactive)
6475 (let ((margin (current-indentation))
6476 (start (point))
6477 label string position)
6478 (vhdl-insert-keyword ": IF ")
6479 (setq position (point-marker))
6480 (goto-char start)
6481 (when (setq label (vhdl-template-field "label" nil t start position))
6482 (goto-char position)
6483 (when vhdl-conditions-in-parenthesis (insert "("))
6484 (vhdl-template-field "condition")
6485 (when vhdl-conditions-in-parenthesis (insert ")"))
6486 (vhdl-template-generate-body margin label))))
6488 (defun vhdl-template-if-then-use (kind)
6489 "Insert a sequential if statement."
6490 (interactive)
6491 (let ((margin (current-indentation))
6492 (start (point))
6493 label)
6494 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
6495 (vhdl-insert-keyword "IF ")
6496 (vhdl-insert-keyword ": IF ")
6497 (goto-char start)
6498 (setq label (vhdl-template-field "[label]" nil t))
6499 (unless label (delete-char 2))
6500 (forward-word 1)
6501 (forward-char 1))
6502 (when vhdl-conditions-in-parenthesis (insert "("))
6503 (when (vhdl-template-field "condition" nil t start (point))
6504 (when vhdl-conditions-in-parenthesis (insert ")"))
6505 (vhdl-insert-keyword
6506 (concat " " (if (eq kind 'then) "THEN" "USE") "\n\n"))
6507 (indent-to margin)
6508 (vhdl-insert-keyword "END IF")
6509 (when label (insert " " label))
6510 (insert ";")
6511 (forward-line -1)
6512 (indent-to (+ margin vhdl-basic-offset)))))
6514 (defun vhdl-template-if-then ()
6515 "Insert a sequential if statement."
6516 (interactive)
6517 (vhdl-template-if-then-use 'then))
6519 (defun vhdl-template-if-use ()
6520 "Insert a simultaneous if statement."
6521 (interactive)
6522 (vhdl-template-if-then-use 'use))
6524 (defun vhdl-template-instance ()
6525 "Insert a component instantiation statement."
6526 (interactive)
6527 (vhdl-template-component-inst))
6529 (defun vhdl-template-library ()
6530 "Insert a library specification."
6531 (interactive)
6532 (let ((margin (current-indentation))
6533 (start (point))
6534 name end-pos)
6535 (vhdl-insert-keyword "LIBRARY ")
6536 (when (setq name (vhdl-template-field "names" nil t start (point)))
6537 (insert ";")
6538 (unless (string-match "," name)
6539 (setq end-pos (point))
6540 (insert "\n")
6541 (indent-to margin)
6542 (vhdl-insert-keyword "USE ")
6543 (insert name)
6544 (vhdl-insert-keyword "..ALL;")
6545 (backward-char 5)
6546 (if (vhdl-template-field "package name")
6547 (forward-char 5)
6548 (delete-region end-pos (+ (point) 5)))))))
6550 (defun vhdl-template-limit ()
6551 "Insert a limit."
6552 (interactive)
6553 (let ((start (point)))
6554 (vhdl-insert-keyword "LIMIT ")
6555 (when (vhdl-template-field "quantity names | OTHERS | ALL" " : "
6556 t start (point))
6557 (vhdl-template-field "type")
6558 (vhdl-insert-keyword " WITH ")
6559 (vhdl-template-field "real expression" ";"))))
6561 (defun vhdl-template-loop ()
6562 "Insert a loop."
6563 (interactive)
6564 (let ((char (vhdl-decision-query nil "(w)hile, (f)or, or (b)are?" t)))
6565 (cond ((eq char ?w)
6566 (vhdl-template-while-loop))
6567 ((eq char ?f)
6568 (vhdl-template-for-loop))
6569 (t (vhdl-template-bare-loop)))))
6571 (defun vhdl-template-bare-loop ()
6572 "Insert a loop."
6573 (interactive)
6574 (let ((margin (current-indentation))
6575 (start (point))
6576 label)
6577 (if (not (eq vhdl-optional-labels 'all))
6578 (vhdl-insert-keyword "LOOP ")
6579 (vhdl-insert-keyword ": LOOP ")
6580 (goto-char start)
6581 (setq label (vhdl-template-field "[label]" nil t))
6582 (unless label (delete-char 2))
6583 (forward-word 1)
6584 (delete-char 1))
6585 (insert "\n\n")
6586 (indent-to margin)
6587 (vhdl-insert-keyword "END LOOP")
6588 (insert (if label (concat " " label ";") ";"))
6589 (forward-line -1)
6590 (indent-to (+ margin vhdl-basic-offset))))
6592 (defun vhdl-template-map (&optional start optional secondary)
6593 "Insert a map specification with association list."
6594 (interactive)
6595 (let ((start (or start (point)))
6596 margin end-pos)
6597 (vhdl-insert-keyword "MAP (")
6598 (if (not vhdl-association-list-with-formals)
6599 (if (vhdl-template-field
6600 (concat (and optional "[") "association list" (and optional "]"))
6601 ")" (or (not secondary) optional)
6602 (and (not secondary) start) (point))
6604 (if (and optional secondary) (delete-region start (point)))
6605 nil)
6606 (if vhdl-argument-list-indent
6607 (setq margin (current-column))
6608 (setq margin (+ (current-indentation) vhdl-basic-offset))
6609 (insert "\n")
6610 (indent-to margin))
6611 (if (vhdl-template-field
6612 (concat (and optional "[") "formal" (and optional "]"))
6613 " => " (or (not secondary) optional)
6614 (and (not secondary) start) (point))
6615 (progn
6616 (vhdl-template-field "actual" ",")
6617 (setq end-pos (point))
6618 (insert "\n")
6619 (indent-to margin)
6620 (while (vhdl-template-field "[formal]" " => " t)
6621 (vhdl-template-field "actual" ",")
6622 (setq end-pos (point))
6623 (insert "\n")
6624 (indent-to margin))
6625 (delete-region end-pos (point))
6626 (backward-delete-char 1)
6627 (insert ")")
6628 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6630 (when (and optional secondary) (delete-region start (point)))
6631 nil))))
6633 (defun vhdl-template-modify (&optional noerror)
6634 "Actualize modification date."
6635 (interactive)
6636 (let ((case-fold-search t))
6637 (vhdl-ext-syntax-table
6638 (save-excursion
6639 (goto-char (point-min))
6640 (if (re-search-forward vhdl-modify-date-prefix-string nil t)
6641 (progn (kill-line)
6642 (vhdl-template-insert-date))
6643 (unless noerror
6644 (error (concat "Modification date prefix string \""
6645 vhdl-modify-date-prefix-string "\" not found"))))))))
6647 (defun vhdl-template-modify-noerror ()
6648 "Call `vhdl-template-modify' with NOERROR non-nil."
6649 (vhdl-template-modify t))
6651 (defun vhdl-template-nature ()
6652 "Insert a nature declaration."
6653 (interactive)
6654 (let ((start (point))
6655 name mid-pos end-pos)
6656 (vhdl-insert-keyword "NATURE ")
6657 (when (setq name (vhdl-template-field "name" nil t start (point)))
6658 (vhdl-insert-keyword " IS ")
6659 (let ((definition
6660 (upcase
6661 (or (vhdl-template-field
6662 "across type | ARRAY | RECORD")
6663 ""))))
6664 (cond ((equal definition "")
6665 (insert ";"))
6666 ((equal definition "ARRAY")
6667 (kill-word -1)
6668 (vhdl-template-array 'nature t))
6669 ((equal definition "RECORD")
6670 (setq mid-pos (point-marker))
6671 (kill-word -1)
6672 (vhdl-template-record 'nature name t))
6674 (vhdl-insert-keyword " ACROSS ")
6675 (vhdl-template-field "through type")
6676 (vhdl-insert-keyword " THROUGH ")
6677 (vhdl-template-field "reference name")
6678 (vhdl-insert-keyword " REFERENCE;")))
6679 (when mid-pos
6680 (setq end-pos (point-marker))
6681 (goto-char mid-pos)
6682 (end-of-line))
6683 (vhdl-comment-insert-inline)
6684 (when end-pos (goto-char end-pos))))))
6686 (defun vhdl-template-next ()
6687 "Insert a next statement."
6688 (interactive)
6689 (vhdl-insert-keyword "NEXT ")
6690 (unless (vhdl-template-field "[loop label]" nil t)
6691 (delete-char -1))
6692 (let ((position (point)))
6693 (vhdl-insert-keyword " WHEN ")
6694 (when vhdl-conditions-in-parenthesis (insert "("))
6695 (if (vhdl-template-field "[condition]" nil t)
6696 (when vhdl-conditions-in-parenthesis (insert ")"))
6697 (delete-region position (point)))
6698 (insert ";")))
6700 (defun vhdl-template-others ()
6701 "Insert an others aggregate."
6702 (interactive)
6703 (vhdl-insert-keyword "(OTHERS => '')")
6704 (backward-char 2))
6706 (defun vhdl-template-package (&optional kind)
6707 "Insert a package specification or body."
6708 (interactive)
6709 (let ((margin (current-indentation))
6710 (start (point))
6711 name body position)
6712 (vhdl-insert-keyword "PACKAGE ")
6713 (setq body (if kind (eq kind 'body)
6714 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b)))
6715 (when body (vhdl-insert-keyword "BODY "))
6716 (when (setq name (vhdl-template-field "name" nil t start (point)))
6717 (vhdl-insert-keyword " IS\n")
6718 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6719 (indent-to (+ margin vhdl-basic-offset))
6720 (setq position (point))
6721 (insert "\n")
6722 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6723 (indent-to margin)
6724 (vhdl-insert-keyword "END ")
6725 (unless (vhdl-standard-p '87)
6726 (vhdl-insert-keyword (concat "PACKAGE " (and body "BODY "))))
6727 (insert (or name "") ";")
6728 (goto-char position))))
6730 (defun vhdl-template-package-decl ()
6731 "Insert a package specification."
6732 (interactive)
6733 (vhdl-template-package 'decl))
6735 (defun vhdl-template-package-body ()
6736 "Insert a package body."
6737 (interactive)
6738 (vhdl-template-package 'body))
6740 (defun vhdl-template-port ()
6741 "Insert a port declaration, or port map in instantiation statements."
6742 (interactive)
6743 (let ((start (point))
6744 (case-fold-search t))
6745 (vhdl-ext-syntax-table
6746 (cond
6747 ((and (save-excursion ; entity declaration
6748 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6749 (equal "ENTITY" (upcase (match-string 1))))
6750 (vhdl-template-port-list nil))
6751 ((or (save-excursion
6752 (or (beginning-of-line)
6753 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6754 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6755 (vhdl-insert-keyword "PORT ")
6756 (vhdl-template-map start))
6757 (t (vhdl-template-port-list nil))))))
6759 (defun vhdl-template-procedural ()
6760 "Insert a procedural."
6761 (interactive)
6762 (let ((margin (current-indentation))
6763 (start (point))
6764 (case-fold-search t)
6765 label)
6766 (vhdl-insert-keyword "PROCEDURAL ")
6767 (when (memq vhdl-optional-labels '(process all))
6768 (goto-char start)
6769 (insert ": ")
6770 (goto-char start)
6771 (setq label (vhdl-template-field "[label]" nil t))
6772 (unless label (delete-char 2))
6773 (forward-word 1)
6774 (forward-char 1))
6775 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "IS"))
6776 (vhdl-template-begin-end "PROCEDURAL" label margin)
6777 (vhdl-comment-block)))
6779 (defun vhdl-template-procedure (&optional kind)
6780 "Insert a procedure declaration or body."
6781 (interactive)
6782 (let ((margin (current-indentation))
6783 (start (point))
6784 name)
6785 (vhdl-insert-keyword "PROCEDURE ")
6786 (when (setq name (vhdl-template-field "name" nil t start (point)))
6787 (vhdl-template-argument-list)
6788 (if (if kind (eq kind 'body)
6789 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6790 (progn (vhdl-insert-keyword " IS")
6791 (when vhdl-auto-align
6792 (vhdl-align-noindent-region start (point) 1))
6793 (end-of-line)
6794 (vhdl-template-begin-end
6795 (unless (vhdl-standard-p '87) "PROCEDURE")
6796 name margin)
6797 (vhdl-comment-block))
6798 (insert ";")
6799 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6800 (end-of-line)))))
6802 (defun vhdl-template-procedure-decl ()
6803 "Insert a procedure declaration."
6804 (interactive)
6805 (vhdl-template-procedure 'decl))
6807 (defun vhdl-template-procedure-body ()
6808 "Insert a procedure body."
6809 (interactive)
6810 (vhdl-template-procedure 'body))
6812 (defun vhdl-template-process (&optional kind)
6813 "Insert a process."
6814 (interactive)
6815 (let ((margin (current-indentation))
6816 (start (point))
6817 (case-fold-search t)
6818 label seq input-signals clock reset final-pos)
6819 (setq seq (if kind (eq kind 'seq)
6820 (eq (vhdl-decision-query
6821 "process" "(c)ombinational or (s)equential?" t) ?s)))
6822 (vhdl-insert-keyword "PROCESS ")
6823 (when (memq vhdl-optional-labels '(process all))
6824 (goto-char start)
6825 (insert ": ")
6826 (goto-char start)
6827 (setq label (vhdl-template-field "[label]" nil t))
6828 (unless label (delete-char 2))
6829 (forward-word 1)
6830 (forward-char 1))
6831 (insert "(")
6832 (if (not seq)
6833 (unless (setq input-signals
6834 (vhdl-template-field "[sensitivity list]" ")" t))
6835 (setq input-signals "")
6836 (delete-char -2))
6837 (setq clock (or (and (not (equal "" vhdl-clock-name))
6838 (progn (insert vhdl-clock-name) vhdl-clock-name))
6839 (vhdl-template-field "clock name") "<clock>"))
6840 (when (eq vhdl-reset-kind 'async)
6841 (insert ", ")
6842 (setq reset (or (and (not (equal "" vhdl-reset-name))
6843 (progn (insert vhdl-reset-name) vhdl-reset-name))
6844 (vhdl-template-field "reset name") "<reset>")))
6845 (insert ")"))
6846 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
6847 (vhdl-template-begin-end "PROCESS" label margin)
6848 (when seq (setq reset (vhdl-template-seq-process clock reset)))
6849 (when vhdl-prompt-for-comments
6850 (setq final-pos (point-marker))
6851 (vhdl-ext-syntax-table
6852 (when (and (re-search-backward "\\<begin\\>" nil t)
6853 (re-search-backward "\\<process\\>" nil t))
6854 (end-of-line -0)
6855 (if (bobp)
6856 (progn (insert "\n") (forward-line -1))
6857 (insert "\n"))
6858 (indent-to margin)
6859 (insert "-- purpose: ")
6860 (if (not (vhdl-template-field "[description]" nil t))
6861 (vhdl-line-kill-entire)
6862 (insert "\n")
6863 (indent-to margin)
6864 (insert "-- type : ")
6865 (insert (if seq "sequential" "combinational") "\n")
6866 (indent-to margin)
6867 (insert "-- inputs : ")
6868 (if (not seq)
6869 (insert input-signals)
6870 (insert clock ", ")
6871 (when reset (insert reset ", "))
6872 (unless (vhdl-template-field "[signal names]" nil t)
6873 (delete-char -2)))
6874 (insert "\n")
6875 (indent-to margin)
6876 (insert "-- outputs: ")
6877 (vhdl-template-field "[signal names]" nil t))))
6878 (goto-char final-pos))))
6880 (defun vhdl-template-process-comb ()
6881 "Insert a combinational process."
6882 (interactive)
6883 (vhdl-template-process 'comb))
6885 (defun vhdl-template-process-seq ()
6886 "Insert a sequential process."
6887 (interactive)
6888 (vhdl-template-process 'seq))
6890 (defun vhdl-template-quantity ()
6891 "Insert a quantity declaration."
6892 (interactive)
6893 (if (vhdl-in-argument-list-p)
6894 (let ((start (point)))
6895 (vhdl-insert-keyword "QUANTITY ")
6896 (when (vhdl-template-field "names" nil t start (point))
6897 (insert " : ")
6898 (vhdl-template-field "[IN | OUT]" " " t)
6899 (vhdl-template-field "type")
6900 (insert ";")
6901 (vhdl-comment-insert-inline)))
6902 (let ((char (vhdl-decision-query
6903 "quantity" "(f)ree, (b)ranch, or (s)ource quantity?" t)))
6904 (cond ((eq char ?f) (vhdl-template-quantity-free))
6905 ((eq char ?b) (vhdl-template-quantity-branch))
6906 ((eq char ?s) (vhdl-template-quantity-source))
6907 (t (vhdl-template-undo (point) (point)))))))
6909 (defun vhdl-template-quantity-free ()
6910 "Insert a free quantity declaration."
6911 (interactive)
6912 (vhdl-insert-keyword "QUANTITY ")
6913 (vhdl-template-field "names")
6914 (insert " : ")
6915 (vhdl-template-field "type")
6916 (let ((position (point)))
6917 (insert " := ")
6918 (unless (vhdl-template-field "[initialization]" nil t)
6919 (delete-region position (point)))
6920 (insert ";")
6921 (vhdl-comment-insert-inline)))
6923 (defun vhdl-template-quantity-branch ()
6924 "Insert a branch quantity declaration."
6925 (interactive)
6926 (let (position)
6927 (vhdl-insert-keyword "QUANTITY ")
6928 (when (vhdl-template-field "[across names]" " " t)
6929 (vhdl-insert-keyword "ACROSS "))
6930 (when (vhdl-template-field "[through names]" " " t)
6931 (vhdl-insert-keyword "THROUGH "))
6932 (vhdl-template-field "plus terminal name")
6933 (setq position (point))
6934 (vhdl-insert-keyword " TO ")
6935 (unless (vhdl-template-field "[minus terminal name]" nil t)
6936 (delete-region position (point)))
6937 (insert ";")
6938 (vhdl-comment-insert-inline)))
6940 (defun vhdl-template-quantity-source ()
6941 "Insert a source quantity declaration."
6942 (interactive)
6943 (vhdl-insert-keyword "QUANTITY ")
6944 (vhdl-template-field "names")
6945 (insert " : ")
6946 (vhdl-template-field "type" " ")
6947 (if (eq (vhdl-decision-query nil "(s)pectrum or (n)oise?") ?n)
6948 (progn (vhdl-insert-keyword "NOISE ")
6949 (vhdl-template-field "power expression"))
6950 (vhdl-insert-keyword "SPECTRUM ")
6951 (vhdl-template-field "magnitude expression" ", ")
6952 (vhdl-template-field "phase expression"))
6953 (insert ";")
6954 (vhdl-comment-insert-inline))
6956 (defun vhdl-template-record (kind &optional name secondary)
6957 "Insert a record type declaration."
6958 (interactive)
6959 (let ((margin (current-column))
6960 (start (point))
6961 (first t))
6962 (vhdl-insert-keyword "RECORD\n")
6963 (indent-to (+ margin vhdl-basic-offset))
6964 (when (or (vhdl-template-field "element names"
6965 nil (not secondary) start (point))
6966 secondary)
6967 (while (or first (vhdl-template-field "[element names]" nil t))
6968 (insert " : ")
6969 (vhdl-template-field (if (eq kind 'type) "type" "nature") ";")
6970 (vhdl-comment-insert-inline)
6971 (insert "\n")
6972 (indent-to (+ margin vhdl-basic-offset))
6973 (setq first nil))
6974 (kill-line -0)
6975 (indent-to margin)
6976 (vhdl-insert-keyword "END RECORD")
6977 (unless (vhdl-standard-p '87) (and name (insert " " name)))
6978 (insert ";")
6979 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
6981 (defun vhdl-template-report ()
6982 "Insert a report statement."
6983 (interactive)
6984 (let ((start (point)))
6985 (vhdl-insert-keyword "REPORT ")
6986 (if (equal "\"\"" (vhdl-template-field
6987 "string expression" nil t start (point) t))
6988 (backward-delete-char 2)
6989 (setq start (point))
6990 (vhdl-insert-keyword " SEVERITY ")
6991 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
6992 (delete-region start (point)))
6993 (insert ";"))))
6995 (defun vhdl-template-return ()
6996 "Insert a return statement."
6997 (interactive)
6998 (vhdl-insert-keyword "RETURN ")
6999 (unless (vhdl-template-field "[expression]" nil t)
7000 (delete-char -1))
7001 (insert ";"))
7003 (defun vhdl-template-selected-signal-asst ()
7004 "Insert a selected signal assignment."
7005 (interactive)
7006 (let ((margin (current-indentation))
7007 (start (point))
7008 (choices t))
7009 (let ((position (point)))
7010 (vhdl-insert-keyword " SELECT ")
7011 (goto-char position))
7012 (vhdl-insert-keyword "WITH ")
7013 (when (vhdl-template-field "selector expression"
7014 nil t start (+ (point) 7))
7015 (forward-word 1)
7016 (delete-char 1)
7017 (insert "\n")
7018 (indent-to (+ margin vhdl-basic-offset))
7019 (vhdl-template-field "target signal" " <= ")
7020 ; (vhdl-template-field "[GUARDED] [TRANSPORT]")
7021 (insert "\n")
7022 (indent-to (+ margin vhdl-basic-offset))
7023 (vhdl-template-field "waveform")
7024 (vhdl-insert-keyword " WHEN ")
7025 (vhdl-template-field "choices" ",")
7026 (insert "\n")
7027 (indent-to (+ margin vhdl-basic-offset))
7028 (while (and choices (vhdl-template-field "[waveform]" nil t))
7029 (vhdl-insert-keyword " WHEN ")
7030 (if (setq choices (vhdl-template-field "[choices]" "," t))
7031 (progn (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
7032 (vhdl-insert-keyword "OTHERS")))
7033 (when choices
7034 (fixup-whitespace)
7035 (delete-char -2))
7036 (insert ";")
7037 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
7039 (defun vhdl-template-signal ()
7040 "Insert a signal declaration."
7041 (interactive)
7042 (let ((start (point))
7043 (in-arglist (vhdl-in-argument-list-p)))
7044 (vhdl-insert-keyword "SIGNAL ")
7045 (when (vhdl-template-field "names" nil t start (point))
7046 (insert " : ")
7047 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7048 (vhdl-template-field "type")
7049 (if in-arglist
7050 (progn (insert ";")
7051 (vhdl-comment-insert-inline))
7052 (let ((position (point)))
7053 (insert " := ")
7054 (unless (vhdl-template-field "[initialization]" nil t)
7055 (delete-region position (point)))
7056 (insert ";")
7057 (vhdl-comment-insert-inline))))))
7059 (defun vhdl-template-subnature ()
7060 "Insert a subnature declaration."
7061 (interactive)
7062 (let ((start (point))
7063 position)
7064 (vhdl-insert-keyword "SUBNATURE ")
7065 (when (vhdl-template-field "name" nil t start (point))
7066 (vhdl-insert-keyword " IS ")
7067 (vhdl-template-field "nature" " (")
7068 (if (vhdl-template-field "[index range]" nil t)
7069 (insert ")")
7070 (delete-char -2))
7071 (setq position (point))
7072 (vhdl-insert-keyword " TOLERANCE ")
7073 (if (equal "\"\"" (vhdl-template-field "[string expression]"
7074 nil t nil nil t))
7075 (delete-region position (point))
7076 (vhdl-insert-keyword " ACROSS ")
7077 (vhdl-template-field "string expression" nil nil nil nil t)
7078 (vhdl-insert-keyword " THROUGH"))
7079 (insert ";")
7080 (vhdl-comment-insert-inline))))
7082 (defun vhdl-template-subprogram-body ()
7083 "Insert a subprogram body."
7084 (interactive)
7085 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7086 (vhdl-template-function-body)
7087 (vhdl-template-procedure-body)))
7089 (defun vhdl-template-subprogram-decl ()
7090 "Insert a subprogram declaration."
7091 (interactive)
7092 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7093 (vhdl-template-function-decl)
7094 (vhdl-template-procedure-decl)))
7096 (defun vhdl-template-subtype ()
7097 "Insert a subtype declaration."
7098 (interactive)
7099 (let ((start (point)))
7100 (vhdl-insert-keyword "SUBTYPE ")
7101 (when (vhdl-template-field "name" nil t start (point))
7102 (vhdl-insert-keyword " IS ")
7103 (vhdl-template-field "type" " ")
7104 (unless
7105 (vhdl-template-field "[RANGE value range | ( index range )]" nil t)
7106 (delete-char -1))
7107 (insert ";")
7108 (vhdl-comment-insert-inline))))
7110 (defun vhdl-template-terminal ()
7111 "Insert a terminal declaration."
7112 (interactive)
7113 (let ((start (point)))
7114 (vhdl-insert-keyword "TERMINAL ")
7115 (when (vhdl-template-field "names" nil t start (point))
7116 (insert " : ")
7117 (vhdl-template-field "nature")
7118 (insert ";")
7119 (vhdl-comment-insert-inline))))
7121 (defun vhdl-template-type ()
7122 "Insert a type declaration."
7123 (interactive)
7124 (let ((start (point))
7125 name mid-pos end-pos)
7126 (vhdl-insert-keyword "TYPE ")
7127 (when (setq name (vhdl-template-field "name" nil t start (point)))
7128 (vhdl-insert-keyword " IS ")
7129 (let ((definition
7130 (upcase
7131 (or (vhdl-template-field
7132 "[scalar type | ARRAY | RECORD | ACCESS | FILE]" nil t)
7133 ""))))
7134 (cond ((equal definition "")
7135 (backward-delete-char 4)
7136 (insert ";"))
7137 ((equal definition "ARRAY")
7138 (kill-word -1)
7139 (vhdl-template-array 'type t))
7140 ((equal definition "RECORD")
7141 (setq mid-pos (point-marker))
7142 (kill-word -1)
7143 (vhdl-template-record 'type name t))
7144 ((equal definition "ACCESS")
7145 (insert " ")
7146 (vhdl-template-field "type" ";"))
7147 ((equal definition "FILE")
7148 (vhdl-insert-keyword " OF ")
7149 (vhdl-template-field "type" ";"))
7150 (t (insert ";")))
7151 (when mid-pos
7152 (setq end-pos (point-marker))
7153 (goto-char mid-pos)
7154 (end-of-line))
7155 (vhdl-comment-insert-inline)
7156 (when end-pos (goto-char end-pos))))))
7158 (defun vhdl-template-use ()
7159 "Insert a use clause."
7160 (interactive)
7161 (let ((start (point))
7162 (case-fold-search t))
7163 (vhdl-ext-syntax-table
7164 (vhdl-insert-keyword "USE ")
7165 (when (save-excursion (beginning-of-line) (looking-at "^\\s-*use\\>"))
7166 (vhdl-insert-keyword "..ALL;")
7167 (backward-char 6)
7168 (when (vhdl-template-field "library name" nil t start (+ (point) 6))
7169 (forward-char 1)
7170 (vhdl-template-field "package name")
7171 (forward-char 5))))))
7173 (defun vhdl-template-variable ()
7174 "Insert a variable declaration."
7175 (interactive)
7176 (let ((start (point))
7177 (case-fold-search t)
7178 (in-arglist (vhdl-in-argument-list-p)))
7179 (vhdl-ext-syntax-table
7180 (if (or (save-excursion
7181 (and (re-search-backward
7182 "\\<function\\|procedure\\|process\\|procedural\\|end\\>"
7183 nil t)
7184 (not (progn (backward-word 1) (looking-at "\\<end\\>")))))
7185 (save-excursion (backward-word 1) (looking-at "\\<shared\\>")))
7186 (vhdl-insert-keyword "VARIABLE ")
7187 (vhdl-insert-keyword "SHARED VARIABLE ")))
7188 (when (vhdl-template-field "names" nil t start (point))
7189 (insert " : ")
7190 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7191 (vhdl-template-field "type")
7192 (if in-arglist
7193 (progn (insert ";")
7194 (vhdl-comment-insert-inline))
7195 (let ((position (point)))
7196 (insert " := ")
7197 (unless (vhdl-template-field "[initialization]" nil t)
7198 (delete-region position (point)))
7199 (insert ";")
7200 (vhdl-comment-insert-inline))))))
7202 (defun vhdl-template-wait ()
7203 "Insert a wait statement."
7204 (interactive)
7205 (vhdl-insert-keyword "WAIT ")
7206 (unless (vhdl-template-field
7207 "[ON sensitivity list] [UNTIL condition] [FOR time expression]"
7208 nil t)
7209 (delete-char -1))
7210 (insert ";"))
7212 (defun vhdl-template-when ()
7213 "Indent correctly if within a case statement."
7214 (interactive)
7215 (let ((position (point))
7216 (case-fold-search t)
7217 margin)
7218 (vhdl-ext-syntax-table
7219 (if (and (= (current-column) (current-indentation))
7220 (re-search-forward "\\<end\\>" nil t)
7221 (looking-at "\\s-*\\<case\\>"))
7222 (progn
7223 (setq margin (current-indentation))
7224 (goto-char position)
7225 (delete-horizontal-space)
7226 (indent-to (+ margin vhdl-basic-offset)))
7227 (goto-char position)))
7228 (vhdl-insert-keyword "WHEN ")))
7230 (defun vhdl-template-while-loop ()
7231 "Insert a while loop."
7232 (interactive)
7233 (let* ((margin (current-indentation))
7234 (start (point))
7235 label)
7236 (if (not (eq vhdl-optional-labels 'all))
7237 (vhdl-insert-keyword "WHILE ")
7238 (vhdl-insert-keyword ": WHILE ")
7239 (goto-char start)
7240 (setq label (vhdl-template-field "[label]" nil t))
7241 (unless label (delete-char 2))
7242 (forward-word 1)
7243 (forward-char 1))
7244 (when vhdl-conditions-in-parenthesis (insert "("))
7245 (when (vhdl-template-field "condition" nil t start (point))
7246 (when vhdl-conditions-in-parenthesis (insert ")"))
7247 (vhdl-insert-keyword " LOOP\n\n")
7248 (indent-to margin)
7249 (vhdl-insert-keyword "END LOOP")
7250 (insert (if label (concat " " label ";") ";"))
7251 (forward-line -1)
7252 (indent-to (+ margin vhdl-basic-offset)))))
7254 (defun vhdl-template-with ()
7255 "Insert a with statement (i.e. selected signal assignment)."
7256 (interactive)
7257 (let ((case-fold-search t))
7258 (vhdl-ext-syntax-table
7259 (if (save-excursion
7260 (re-search-backward "\\(\\<limit\\>\\|;\\)")
7261 (equal ";" (match-string 1)))
7262 (vhdl-template-selected-signal-asst)
7263 (vhdl-insert-keyword "WITH ")))))
7265 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7266 ;; Special templates
7268 (defun vhdl-template-clocked-wait ()
7269 "Insert a wait statement for rising/falling clock edge."
7270 (interactive)
7271 (let ((start (point))
7272 clock)
7273 (vhdl-insert-keyword "WAIT UNTIL ")
7274 (when (setq clock
7275 (or (and (not (equal "" vhdl-clock-name))
7276 (progn (insert vhdl-clock-name) vhdl-clock-name))
7277 (vhdl-template-field "clock name" nil t start (point))))
7278 (insert "'event")
7279 (vhdl-insert-keyword " AND ")
7280 (insert clock)
7281 (insert
7282 " = " (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string) ";")
7283 (vhdl-comment-insert-inline
7284 (concat (if vhdl-clock-rising-edge "rising" "falling")
7285 " clock edge")))))
7287 (defun vhdl-template-seq-process (clock reset)
7288 "Insert a template for the body of a sequential process."
7289 (let ((margin (current-indentation))
7290 position)
7291 (vhdl-insert-keyword "IF ")
7292 (when (eq vhdl-reset-kind 'async)
7293 (insert reset " = "
7294 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7295 (vhdl-insert-keyword " THEN")
7296 (vhdl-comment-insert-inline
7297 (concat "asynchronous reset (active "
7298 (if vhdl-reset-active-high "high" "low") ")"))
7299 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7300 (setq position (point))
7301 (insert "\n") (indent-to margin)
7302 (vhdl-insert-keyword "ELSIF "))
7303 (if (eq vhdl-clock-edge-condition 'function)
7304 (insert (if vhdl-clock-rising-edge "rising" "falling")
7305 "_edge(" clock ")")
7306 (insert clock "'event")
7307 (vhdl-insert-keyword " AND ")
7308 (insert clock " = "
7309 (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string)))
7310 (vhdl-insert-keyword " THEN")
7311 (vhdl-comment-insert-inline
7312 (concat (if vhdl-clock-rising-edge "rising" "falling") " clock edge"))
7313 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7314 (when (eq vhdl-reset-kind 'sync)
7315 (vhdl-insert-keyword "IF ")
7316 (setq reset (or (and (not (equal "" vhdl-reset-name))
7317 (progn (insert vhdl-reset-name) vhdl-reset-name))
7318 (vhdl-template-field "reset name") "<reset>"))
7319 (insert " = "
7320 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7321 (vhdl-insert-keyword " THEN")
7322 (vhdl-comment-insert-inline
7323 (concat "synchronous reset (active "
7324 (if vhdl-reset-active-high "high" "low") ")"))
7325 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7326 (setq position (point))
7327 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7328 (vhdl-insert-keyword "ELSE")
7329 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7330 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7331 (vhdl-insert-keyword "END IF;"))
7332 (when (eq vhdl-reset-kind 'none)
7333 (setq position (point)))
7334 (insert "\n") (indent-to margin)
7335 (vhdl-insert-keyword "END IF;")
7336 (goto-char position)
7337 reset))
7339 (defun vhdl-template-standard-package (library package)
7340 "Insert specification of a standard package. Include a library
7341 specification, if not already there."
7342 (let ((margin (current-indentation))
7343 (case-fold-search t))
7344 (save-excursion
7345 (vhdl-ext-syntax-table
7346 (and (not (bobp))
7347 (re-search-backward
7348 (concat "^\\s-*\\(library\\s-+\\(\\(\\w\\|\\s_\\)+,\\s-+\\)*"
7349 library "\\|end\\)\\>") nil t))))
7350 (unless (and (match-string 1) (string-match "library" (match-string 1)))
7351 (vhdl-insert-keyword "LIBRARY ")
7352 (insert library ";\n")
7353 (indent-to margin))
7354 (vhdl-insert-keyword "USE ")
7355 (insert library "." package)
7356 (vhdl-insert-keyword ".ALL;")))
7358 (defun vhdl-template-package-math-complex ()
7359 "Insert specification of `math_complex' package."
7360 (interactive)
7361 (vhdl-template-standard-package "ieee" "math_complex"))
7363 (defun vhdl-template-package-math-real ()
7364 "Insert specification of `math_real' package."
7365 (interactive)
7366 (vhdl-template-standard-package "ieee" "math_real"))
7368 (defun vhdl-template-package-numeric-bit ()
7369 "Insert specification of `numeric_bit' package."
7370 (interactive)
7371 (vhdl-template-standard-package "ieee" "numeric_bit"))
7373 (defun vhdl-template-package-numeric-std ()
7374 "Insert specification of `numeric_std' package."
7375 (interactive)
7376 (vhdl-template-standard-package "ieee" "numeric_std"))
7378 (defun vhdl-template-package-std-logic-1164 ()
7379 "Insert specification of `std_logic_1164' package."
7380 (interactive)
7381 (vhdl-template-standard-package "ieee" "std_logic_1164"))
7383 (defun vhdl-template-package-std-logic-arith ()
7384 "Insert specification of `std_logic_arith' package."
7385 (interactive)
7386 (vhdl-template-standard-package "ieee" "std_logic_arith"))
7388 (defun vhdl-template-package-std-logic-misc ()
7389 "Insert specification of `std_logic_misc' package."
7390 (interactive)
7391 (vhdl-template-standard-package "ieee" "std_logic_misc"))
7393 (defun vhdl-template-package-std-logic-signed ()
7394 "Insert specification of `std_logic_signed' package."
7395 (interactive)
7396 (vhdl-template-standard-package "ieee" "std_logic_signed"))
7398 (defun vhdl-template-package-std-logic-textio ()
7399 "Insert specification of `std_logic_textio' package."
7400 (interactive)
7401 (vhdl-template-standard-package "ieee" "std_logic_textio"))
7403 (defun vhdl-template-package-std-logic-unsigned ()
7404 "Insert specification of `std_logic_unsigned' package."
7405 (interactive)
7406 (vhdl-template-standard-package "ieee" "std_logic_unsigned"))
7408 (defun vhdl-template-package-textio ()
7409 "Insert specification of `textio' package."
7410 (interactive)
7411 (vhdl-template-standard-package "std" "textio"))
7413 (defun vhdl-template-directive (directive)
7414 "Insert directive."
7415 (unless (= (current-indentation) (current-column))
7416 (delete-horizontal-space)
7417 (insert " "))
7418 (insert "-- pragma " directive))
7420 (defun vhdl-template-directive-translate-on ()
7421 "Insert directive 'translate_on'."
7422 (interactive)
7423 (vhdl-template-directive "translate_on"))
7425 (defun vhdl-template-directive-translate-off ()
7426 "Insert directive 'translate_off'."
7427 (interactive)
7428 (vhdl-template-directive "translate_off"))
7430 (defun vhdl-template-directive-synthesis-on ()
7431 "Insert directive 'synthesis_on'."
7432 (interactive)
7433 (vhdl-template-directive "synthesis_on"))
7435 (defun vhdl-template-directive-synthesis-off ()
7436 "Insert directive 'synthesis_off'."
7437 (interactive)
7438 (vhdl-template-directive "synthesis_off"))
7440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7441 ;; Comment templates and functions
7443 (defun vhdl-comment-indent ()
7444 "Indent comments."
7445 (let* ((position (point))
7446 (col
7447 (progn
7448 (forward-line -1)
7449 (if (re-search-forward "--" position t)
7450 (- (current-column) 2) ; existing comment at bol stays there
7451 (goto-char position)
7452 (skip-chars-backward " \t")
7453 (max comment-column ; else indent to comment column
7454 (1+ (current-column))))))) ; except leave at least one space
7455 (goto-char position)
7456 col))
7458 (defun vhdl-comment-insert ()
7459 "Start a comment at the end of the line.
7460 If on line with code, indent at least `comment-column'.
7461 If starting after end-comment-column, start a new line."
7462 (interactive)
7463 (when (> (current-column) end-comment-column) (newline-and-indent))
7464 (if (or (looking-at "\\s-*$") ; end of line
7465 (and (not unread-command-events) ; called with key binding or menu
7466 (not (end-of-line))))
7467 (let (margin)
7468 (while (= (preceding-char) ?-) (delete-char -1))
7469 (setq margin (current-column))
7470 (delete-horizontal-space)
7471 (if (bolp)
7472 (progn (indent-to margin) (insert "--"))
7473 (insert " ")
7474 (indent-to comment-column)
7475 (insert "--"))
7476 (if (not unread-command-events) (insert " ")))
7477 ;; else code following current point implies commenting out code
7478 (let (next-input code)
7479 (while (= (preceding-char) ?-) (delete-char -2))
7480 (while (= (setq next-input (read-char)) 13) ; CR
7481 (insert "--") ; or have a space after it?
7482 (forward-char -2)
7483 (forward-line 1)
7484 (message "Enter CR if commenting out a line of code.")
7485 (setq code t))
7486 (when (not code)
7487 (insert "--")) ; hardwire to 1 space or use vhdl-basic-offset?
7488 (setq unread-command-events
7489 (list (vhdl-character-to-event next-input)))))) ; pushback the char
7491 (defun vhdl-comment-display (&optional line-exists)
7492 "Add 2 comment lines at the current indent, making a display comment."
7493 (interactive)
7494 (let ((margin (current-indentation)))
7495 (when (not line-exists) (vhdl-comment-display-line))
7496 (insert "\n") (indent-to margin)
7497 (insert "\n") (indent-to margin)
7498 (vhdl-comment-display-line)
7499 (end-of-line -0)
7500 (insert "-- ")))
7502 (defun vhdl-comment-display-line ()
7503 "Displays one line of dashes."
7504 (interactive)
7505 (while (= (preceding-char) ?-) (delete-char -2))
7506 (let* ((col (current-column))
7507 (len (- end-comment-column col)))
7508 (insert-char ?- len)))
7510 (defun vhdl-comment-append-inline ()
7511 "Append empty inline comment to current line."
7512 (interactive)
7513 (end-of-line)
7514 (delete-horizontal-space)
7515 (insert " ")
7516 (indent-to comment-column)
7517 (insert "-- "))
7519 (defun vhdl-comment-insert-inline (&optional string always-insert)
7520 "Insert inline comment."
7521 (when (or (and string (or vhdl-self-insert-comments always-insert))
7522 (and (not string) vhdl-prompt-for-comments))
7523 (let ((position (point)))
7524 (insert " ")
7525 (indent-to comment-column)
7526 (insert "-- ")
7527 (if (or (and string (progn (insert string) t))
7528 (vhdl-template-field "[comment]" nil t))
7529 (when (> (current-column) end-comment-column)
7530 (setq position (point-marker))
7531 (re-search-backward "-- ")
7532 (insert "\n")
7533 (indent-to comment-column)
7534 (goto-char position))
7535 (delete-region position (point))))))
7537 (defun vhdl-comment-block ()
7538 "Insert comment for code block."
7539 (when vhdl-prompt-for-comments
7540 (let ((final-pos (point-marker))
7541 (case-fold-search t))
7542 (vhdl-ext-syntax-table
7543 (when (and (re-search-backward "^\\s-*begin\\>" nil t)
7544 (re-search-backward
7545 "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\|procedural\\)\\>"
7546 nil t))
7547 (let (margin)
7548 (back-to-indentation)
7549 (setq margin (current-column))
7550 (end-of-line -0)
7551 (if (bobp)
7552 (progn (insert "\n") (forward-line -1))
7553 (insert "\n"))
7554 (indent-to margin)
7555 (insert "-- purpose: ")
7556 (unless (vhdl-template-field "[description]" nil t)
7557 (vhdl-line-kill-entire)))))
7558 (goto-char final-pos))))
7560 (defun vhdl-comment-uncomment-region (beg end &optional arg)
7561 "Comment out region if not commented out, uncomment otherwise."
7562 (interactive "r\nP")
7563 (save-excursion
7564 (goto-char (1- end))
7565 (end-of-line)
7566 (setq end (point-marker))
7567 (goto-char beg)
7568 (beginning-of-line)
7569 (setq beg (point))
7570 (if (looking-at comment-start)
7571 (comment-region beg end -1)
7572 (comment-region beg end))))
7574 (defun vhdl-comment-uncomment-line (&optional arg)
7575 "Comment out line if not commented out, uncomment otherwise."
7576 (interactive "p")
7577 (save-excursion
7578 (beginning-of-line)
7579 (let ((position (point)))
7580 (forward-line (or arg 1))
7581 (vhdl-comment-uncomment-region position (point)))))
7583 (defun vhdl-comment-kill-region (beg end)
7584 "Kill comments in region."
7585 (interactive "r")
7586 (save-excursion
7587 (goto-char end)
7588 (setq end (point-marker))
7589 (goto-char beg)
7590 (beginning-of-line)
7591 (while (< (point) end)
7592 (if (looking-at "^\\(\\s-*--.*\n\\)")
7593 (progn (delete-region (match-beginning 1) (match-end 1)))
7594 (beginning-of-line 2)))))
7596 (defun vhdl-comment-kill-inline-region (beg end)
7597 "Kill inline comments in region."
7598 (interactive "r")
7599 (save-excursion
7600 (goto-char end)
7601 (setq end (point-marker))
7602 (goto-char beg)
7603 (beginning-of-line)
7604 (while (< (point) end)
7605 (when (looking-at "^.*[^ \t\n-]+\\(\\s-*--.*\\)$")
7606 (delete-region (match-beginning 1) (match-end 1)))
7607 (beginning-of-line 2))))
7609 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7610 ;; Subtemplates
7612 (defun vhdl-template-begin-end (construct name margin &optional empty-lines)
7613 "Insert a begin ... end pair with optional name after the end.
7614 Point is left between them."
7615 (let (position)
7616 (insert "\n")
7617 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7618 (indent-to margin)
7619 (vhdl-insert-keyword "BEGIN")
7620 (when (and (or construct name) vhdl-self-insert-comments)
7621 (insert " --")
7622 (when construct (insert " ") (vhdl-insert-keyword construct))
7623 (when name (insert " " name)))
7624 (insert "\n")
7625 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7626 (indent-to (+ margin vhdl-basic-offset))
7627 (setq position (point))
7628 (insert "\n")
7629 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7630 (indent-to margin)
7631 (vhdl-insert-keyword "END")
7632 (when construct (insert " ") (vhdl-insert-keyword construct))
7633 (insert (if name (concat " " name) "") ";")
7634 (goto-char position)))
7636 (defun vhdl-template-argument-list (&optional is-function)
7637 "Read from user a procedure or function argument list."
7638 (insert " (")
7639 (let ((margin (current-column))
7640 (start (point))
7641 (end-pos (point))
7642 not-empty interface semicolon-pos)
7643 (when (not vhdl-argument-list-indent)
7644 (setq margin (+ (current-indentation) vhdl-basic-offset))
7645 (insert "\n")
7646 (indent-to margin))
7647 (setq interface (vhdl-template-field
7648 (concat "[CONSTANT | SIGNAL"
7649 (unless is-function " | VARIABLE") "]") " " t))
7650 (while (vhdl-template-field "[names]" nil t)
7651 (setq not-empty t)
7652 (insert " : ")
7653 (when (not is-function)
7654 (if (and interface (equal (upcase interface) "CONSTANT"))
7655 (vhdl-insert-keyword "IN ")
7656 (vhdl-template-field "[IN | OUT | INOUT]" " " t)))
7657 (vhdl-template-field "type")
7658 (setq semicolon-pos (point))
7659 (insert ";")
7660 (vhdl-comment-insert-inline)
7661 (setq end-pos (point))
7662 (insert "\n")
7663 (indent-to margin)
7664 (setq interface (vhdl-template-field
7665 (concat "[CONSTANT | SIGNAL"
7666 (unless is-function " | VARIABLE") "]") " " t)))
7667 (delete-region end-pos (point))
7668 (when semicolon-pos (goto-char semicolon-pos))
7669 (if not-empty
7670 (progn (delete-char 1) (insert ")"))
7671 (backward-delete-char 2))))
7673 (defun vhdl-template-generic-list (optional &optional no-value)
7674 "Read from user a generic spec argument list."
7675 (let (margin
7676 (start (point)))
7677 (vhdl-insert-keyword "GENERIC (")
7678 (setq margin (current-column))
7679 (when (not vhdl-argument-list-indent)
7680 (let ((position (point)))
7681 (back-to-indentation)
7682 (setq margin (+ (current-column) vhdl-basic-offset))
7683 (goto-char position)
7684 (insert "\n")
7685 (indent-to margin)))
7686 (let ((vhdl-generics (vhdl-template-field
7687 (concat (and optional "[") "name"
7688 (and no-value "s") (and optional "]"))
7689 nil optional)))
7690 (if (not vhdl-generics)
7691 (if optional
7692 (progn (vhdl-line-kill-entire) (end-of-line -0)
7693 (when (not vhdl-argument-list-indent)
7694 (vhdl-line-kill-entire) (end-of-line -0)))
7695 (vhdl-template-undo start (point))
7696 nil )
7697 (insert " : ")
7698 (let (semicolon-pos end-pos)
7699 (while vhdl-generics
7700 (vhdl-template-field "type")
7701 (if no-value
7702 (progn (setq semicolon-pos (point))
7703 (insert ";"))
7704 (insert " := ")
7705 (unless (vhdl-template-field "[value]" nil t)
7706 (delete-char -4))
7707 (setq semicolon-pos (point))
7708 (insert ";"))
7709 (vhdl-comment-insert-inline)
7710 (setq end-pos (point))
7711 (insert "\n")
7712 (indent-to margin)
7713 (setq vhdl-generics (vhdl-template-field
7714 (concat "[name" (and no-value "s") "]")
7715 " : " t)))
7716 (delete-region end-pos (point))
7717 (goto-char semicolon-pos)
7718 (insert ")")
7719 (end-of-line)
7720 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
7721 t)))))
7723 (defun vhdl-template-port-list (optional)
7724 "Read from user a port spec argument list."
7725 (let ((start (point))
7726 margin vhdl-ports object)
7727 (vhdl-insert-keyword "PORT (")
7728 (setq margin (current-column))
7729 (when (not vhdl-argument-list-indent)
7730 (let ((position (point)))
7731 (back-to-indentation)
7732 (setq margin (+ (current-column) vhdl-basic-offset))
7733 (goto-char position)
7734 (insert "\n")
7735 (indent-to margin)))
7736 (when (vhdl-standard-p 'ams)
7737 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7738 " " t)))
7739 (setq vhdl-ports (vhdl-template-field
7740 (concat (and optional "[") "names" (and optional "]"))
7741 nil optional))
7742 (if (not vhdl-ports)
7743 (if optional
7744 (progn (vhdl-line-kill-entire) (end-of-line -0)
7745 (when (not vhdl-argument-list-indent)
7746 (vhdl-line-kill-entire) (end-of-line -0)))
7747 (vhdl-template-undo start (point))
7748 nil)
7749 (insert " : ")
7750 (let (semicolon-pos end-pos)
7751 (while vhdl-ports
7752 (cond ((or (null object) (equal "SIGNAL" (upcase object)))
7753 (vhdl-template-field "IN | OUT | INOUT" " "))
7754 ((equal "QUANTITY" (upcase object))
7755 (vhdl-template-field "[IN | OUT]" " " t)))
7756 (vhdl-template-field
7757 (if (and object (equal "TERMINAL" (upcase object)))
7758 "nature" "type"))
7759 (setq semicolon-pos (point))
7760 (insert ";")
7761 (vhdl-comment-insert-inline)
7762 (setq end-pos (point))
7763 (insert "\n")
7764 (indent-to margin)
7765 (when (vhdl-standard-p 'ams)
7766 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7767 " " t)))
7768 (setq vhdl-ports (vhdl-template-field "[names]" " : " t)))
7769 (delete-region end-pos (point))
7770 (goto-char semicolon-pos)
7771 (insert ")")
7772 (end-of-line)
7773 (when vhdl-auto-align (vhdl-align-noindent-region start end-pos 1))
7774 t))))
7776 (defun vhdl-template-generate-body (margin label)
7777 "Insert body for generate template."
7778 (vhdl-insert-keyword " GENERATE")
7779 (if (not (vhdl-standard-p '87))
7780 (vhdl-template-begin-end "GENERATE" label margin)
7781 (insert "\n\n")
7782 (indent-to margin)
7783 (vhdl-insert-keyword "END GENERATE ")
7784 (insert label ";")
7785 (end-of-line 0)
7786 (indent-to (+ margin vhdl-basic-offset))))
7788 (defun vhdl-template-insert-date ()
7789 "Insert date in appropriate format."
7790 (interactive)
7791 (insert
7792 (cond
7793 ;; 'american, 'european', 'scientific kept for backward compatibility
7794 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
7795 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
7796 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
7797 (t (format-time-string vhdl-date-format nil)))))
7799 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7800 ;; Help functions
7802 (defun vhdl-electric-space (count)
7803 "Expand abbreviations and self-insert space(s), do indent-new-comment-line
7804 if in comment and past end-comment-column."
7805 (interactive "p")
7806 (cond ((vhdl-in-comment-p)
7807 (self-insert-command count)
7808 (cond ((>= (current-column) (+ 2 end-comment-column))
7809 (backward-word 1)
7810 (indent-new-comment-line)
7811 (forward-word 1)
7812 (forward-char 1))
7813 ((>= (current-column) end-comment-column)
7814 (indent-new-comment-line))
7815 (t nil)))
7816 ((or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
7817 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
7818 (vhdl-ext-syntax-table
7819 (let ((case-fold-search t))
7820 (expand-abbrev)))
7821 (self-insert-command count))
7822 (t (self-insert-command count))))
7824 (defun vhdl-template-field (prompt &optional follow-string optional
7825 begin end is-string default)
7826 "Prompt for string and insert it in buffer with optional FOLLOW-STRING.
7827 If OPTIONAL is nil, the prompt is left if an empty string is inserted. If
7828 an empty string is inserted, return nil and call `vhdl-template-undo' for
7829 the region between BEGIN and END. IS-STRING indicates whether a string
7830 with double-quotes is to be inserted. DEFAULT specifies a default string."
7831 (let ((position (point))
7832 string)
7833 (insert "<" prompt ">")
7834 (setq string
7835 (condition-case ()
7836 (read-from-minibuffer (concat prompt ": ")
7837 (or (and is-string '("\"\"" . 2)) default)
7838 vhdl-minibuffer-local-map)
7839 (quit (if (and optional begin end)
7840 (progn (beep) "")
7841 (keyboard-quit)))))
7842 (when (or (not (equal string "")) optional)
7843 (delete-region position (point)))
7844 (when (and (equal string "") optional begin end)
7845 (vhdl-template-undo begin end)
7846 (message "Template aborted"))
7847 (when (not (equal string ""))
7848 (insert string)
7849 (vhdl-fix-case-region-1 position (point) vhdl-upper-case-keywords
7850 vhdl-keywords-regexp))
7851 (when (or (not (equal string "")) (not optional))
7852 (insert (or follow-string "")))
7853 (if (equal string "") nil string)))
7855 (defun vhdl-decision-query (string prompt &optional optional)
7856 "Query a decision from the user."
7857 (let ((start (point)))
7858 (when string (vhdl-insert-keyword (concat string " ")))
7859 (message prompt)
7860 (let ((char (read-char)))
7861 (delete-region start (point))
7862 (if (and optional (eq char ?\r))
7863 (progn (insert " ")
7864 (unexpand-abbrev)
7865 (throw 'abort "Template aborted"))
7866 char))))
7868 (defun vhdl-insert-keyword (keyword)
7869 "Insert KEYWORD and adjust case."
7870 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))))
7872 (defun vhdl-case-keyword (keyword)
7873 "Adjust case of KEYWORD."
7874 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
7876 (defun vhdl-case-word (num)
7877 "Adjust case or following NUM words."
7878 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num)))
7880 (defun vhdl-minibuffer-tab (&optional prefix-arg)
7881 "If preceeding character is part of a word or a paren then hippie-expand,
7882 else if right of non whitespace on line then tab-to-tab-stop,
7883 else indent line in proper way for current major mode (used for word
7884 completion in VHDL minibuffer)."
7885 (interactive "P")
7886 (cond ((= (char-syntax (preceding-char)) ?w)
7887 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7888 (case-replace nil))
7889 (vhdl-expand-abbrev prefix-arg)))
7890 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
7891 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7892 (case-replace nil))
7893 (vhdl-expand-paren prefix-arg)))
7894 ((> (current-column) (current-indentation))
7895 (tab-to-tab-stop))
7896 (t (if (eq indent-line-function 'indent-to-left-margin)
7897 (insert-tab prefix-arg)
7898 (if prefix-arg
7899 (funcall indent-line-function prefix-arg)
7900 (funcall indent-line-function))))))
7902 (defun vhdl-template-search-prompt ()
7903 "Search for left out template prompts and query again."
7904 (interactive)
7905 (let ((case-fold-search t))
7906 (vhdl-ext-syntax-table
7907 (when (or (re-search-forward
7908 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t)
7909 (re-search-backward
7910 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t))
7911 (let ((string (match-string 1)))
7912 (replace-match "")
7913 (vhdl-template-field string))))))
7915 (defun vhdl-template-undo (begin end)
7916 "Undo aborted template by deleting region and unexpanding the keyword."
7917 (cond (vhdl-template-invoked-by-hook
7918 (goto-char end)
7919 (insert " ")
7920 (delete-region begin end)
7921 (unexpand-abbrev))
7922 (t (delete-region begin end))))
7924 (defun vhdl-insert-string-or-file (string)
7925 "Insert STRING or file contents if STRING is an existing file name."
7926 (unless (equal string "")
7927 (cond ((file-exists-p string)
7928 (forward-char (cadr (insert-file-contents string))))
7929 (t (insert string)))))
7931 (defun vhdl-sequential-statement-p ()
7932 "Check if point is within sequential statement part."
7933 (save-excursion
7934 (let ((case-fold-search t)
7935 (start (point)))
7936 (vhdl-ext-syntax-table
7937 (set-match-data nil)
7938 (while (and (re-search-backward "^\\s-*\\(begin\\|end\\(\\s-*\\(case\\|if\\|loop\\)\\)?\\)\\>"
7939 nil t)
7940 (match-string 2)))
7941 (and (match-data)
7942 (equal "BEGIN" (upcase (match-string 1)))
7943 (re-search-backward "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(\\w+\\s-+\\)?\\(function\\|procedure\\|process\\|procedural\\|end\\)\\>"
7944 nil t)
7945 (not (equal "END" (upcase (match-string 3)))))))))
7947 (defun vhdl-in-argument-list-p ()
7948 "Check if within an argument list."
7949 (save-excursion
7950 (let ((case-fold-search t))
7951 (vhdl-ext-syntax-table
7952 (or (string-match "arglist"
7953 (format "%s" (car (car (vhdl-get-syntactic-context)))))
7954 (progn (beginning-of-line)
7955 (looking-at "^\\s-*\\(generic\\|port\\|\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\>\\s-*\\(\\w+\\s-*\\)?(")
7956 ))))))
7958 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7959 ;; Abbrev hooks
7961 (defun vhdl-hooked-abbrev (func)
7962 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
7963 but not if inside a comment or quote)."
7964 (if (or (vhdl-in-comment-p)
7965 (vhdl-in-string-p)
7966 (save-excursion
7967 (forward-word -1)
7968 (and (looking-at "\\<end\\>") (not (looking-at "\\<end;")))))
7969 (progn
7970 (insert " ")
7971 (unexpand-abbrev)
7972 (delete-char -1))
7973 (if (not vhdl-electric-mode)
7974 (progn
7975 (insert " ")
7976 (unexpand-abbrev)
7977 (backward-word 1)
7978 (vhdl-case-word 1)
7979 (delete-char 1))
7980 (let ((invoke-char last-command-char)
7981 (abbrev-mode -1)
7982 (vhdl-template-invoked-by-hook t))
7983 (let ((caught (catch 'abort
7984 (funcall func))))
7985 (when (stringp caught) (message caught)))
7986 (when (= invoke-char ?-) (setq abbrev-start-location (point)))
7987 ;; delete CR which is still in event queue
7988 (if (string-match "XEmacs" emacs-version)
7989 (enqueue-eval-event 'delete-char -1)
7990 (setq unread-command-events ; push back a delete char
7991 (list (vhdl-character-to-event ?\177))))))))
7993 (defun vhdl-template-alias-hook ()
7994 (vhdl-hooked-abbrev 'vhdl-template-alias))
7995 (defun vhdl-template-architecture-hook ()
7996 (vhdl-hooked-abbrev 'vhdl-template-architecture))
7997 (defun vhdl-template-assert-hook ()
7998 (vhdl-hooked-abbrev 'vhdl-template-assert))
7999 (defun vhdl-template-attribute-hook ()
8000 (vhdl-hooked-abbrev 'vhdl-template-attribute))
8001 (defun vhdl-template-block-hook ()
8002 (vhdl-hooked-abbrev 'vhdl-template-block))
8003 (defun vhdl-template-break-hook ()
8004 (vhdl-hooked-abbrev 'vhdl-template-break))
8005 (defun vhdl-template-case-hook ()
8006 (vhdl-hooked-abbrev 'vhdl-template-case))
8007 (defun vhdl-template-component-hook ()
8008 (vhdl-hooked-abbrev 'vhdl-template-component))
8009 (defun vhdl-template-instance-hook ()
8010 (vhdl-hooked-abbrev 'vhdl-template-instance))
8011 (defun vhdl-template-conditional-signal-asst-hook ()
8012 (vhdl-hooked-abbrev 'vhdl-template-conditional-signal-asst))
8013 (defun vhdl-template-configuration-hook ()
8014 (vhdl-hooked-abbrev 'vhdl-template-configuration))
8015 (defun vhdl-template-constant-hook ()
8016 (vhdl-hooked-abbrev 'vhdl-template-constant))
8017 (defun vhdl-template-disconnect-hook ()
8018 (vhdl-hooked-abbrev 'vhdl-template-disconnect))
8019 (defun vhdl-template-display-comment-hook ()
8020 (vhdl-hooked-abbrev 'vhdl-comment-display))
8021 (defun vhdl-template-else-hook ()
8022 (vhdl-hooked-abbrev 'vhdl-template-else))
8023 (defun vhdl-template-elsif-hook ()
8024 (vhdl-hooked-abbrev 'vhdl-template-elsif))
8025 (defun vhdl-template-entity-hook ()
8026 (vhdl-hooked-abbrev 'vhdl-template-entity))
8027 (defun vhdl-template-exit-hook ()
8028 (vhdl-hooked-abbrev 'vhdl-template-exit))
8029 (defun vhdl-template-file-hook ()
8030 (vhdl-hooked-abbrev 'vhdl-template-file))
8031 (defun vhdl-template-for-hook ()
8032 (vhdl-hooked-abbrev 'vhdl-template-for))
8033 (defun vhdl-template-function-hook ()
8034 (vhdl-hooked-abbrev 'vhdl-template-function))
8035 (defun vhdl-template-generic-hook ()
8036 (vhdl-hooked-abbrev 'vhdl-template-generic))
8037 (defun vhdl-template-group-hook ()
8038 (vhdl-hooked-abbrev 'vhdl-template-group))
8039 (defun vhdl-template-library-hook ()
8040 (vhdl-hooked-abbrev 'vhdl-template-library))
8041 (defun vhdl-template-limit-hook ()
8042 (vhdl-hooked-abbrev 'vhdl-template-limit))
8043 (defun vhdl-template-if-hook ()
8044 (vhdl-hooked-abbrev 'vhdl-template-if))
8045 (defun vhdl-template-bare-loop-hook ()
8046 (vhdl-hooked-abbrev 'vhdl-template-bare-loop))
8047 (defun vhdl-template-map-hook ()
8048 (vhdl-hooked-abbrev 'vhdl-template-map))
8049 (defun vhdl-template-nature-hook ()
8050 (vhdl-hooked-abbrev 'vhdl-template-nature))
8051 (defun vhdl-template-next-hook ()
8052 (vhdl-hooked-abbrev 'vhdl-template-next))
8053 (defun vhdl-template-package-hook ()
8054 (vhdl-hooked-abbrev 'vhdl-template-package))
8055 (defun vhdl-template-port-hook ()
8056 (vhdl-hooked-abbrev 'vhdl-template-port))
8057 (defun vhdl-template-procedural-hook ()
8058 (vhdl-hooked-abbrev 'vhdl-template-procedural))
8059 (defun vhdl-template-procedure-hook ()
8060 (vhdl-hooked-abbrev 'vhdl-template-procedure))
8061 (defun vhdl-template-process-hook ()
8062 (vhdl-hooked-abbrev 'vhdl-template-process))
8063 (defun vhdl-template-quantity-hook ()
8064 (vhdl-hooked-abbrev 'vhdl-template-quantity))
8065 (defun vhdl-template-report-hook ()
8066 (vhdl-hooked-abbrev 'vhdl-template-report))
8067 (defun vhdl-template-return-hook ()
8068 (vhdl-hooked-abbrev 'vhdl-template-return))
8069 (defun vhdl-template-selected-signal-asst-hook ()
8070 (vhdl-hooked-abbrev 'vhdl-template-selected-signal-asst))
8071 (defun vhdl-template-signal-hook ()
8072 (vhdl-hooked-abbrev 'vhdl-template-signal))
8073 (defun vhdl-template-subnature-hook ()
8074 (vhdl-hooked-abbrev 'vhdl-template-subnature))
8075 (defun vhdl-template-subtype-hook ()
8076 (vhdl-hooked-abbrev 'vhdl-template-subtype))
8077 (defun vhdl-template-terminal-hook ()
8078 (vhdl-hooked-abbrev 'vhdl-template-terminal))
8079 (defun vhdl-template-type-hook ()
8080 (vhdl-hooked-abbrev 'vhdl-template-type))
8081 (defun vhdl-template-use-hook ()
8082 (vhdl-hooked-abbrev 'vhdl-template-use))
8083 (defun vhdl-template-variable-hook ()
8084 (vhdl-hooked-abbrev 'vhdl-template-variable))
8085 (defun vhdl-template-wait-hook ()
8086 (vhdl-hooked-abbrev 'vhdl-template-wait))
8087 (defun vhdl-template-when-hook ()
8088 (vhdl-hooked-abbrev 'vhdl-template-when))
8089 (defun vhdl-template-while-loop-hook ()
8090 (vhdl-hooked-abbrev 'vhdl-template-while-loop))
8091 (defun vhdl-template-with-hook ()
8092 (vhdl-hooked-abbrev 'vhdl-template-with))
8093 (defun vhdl-template-and-hook ()
8094 (vhdl-hooked-abbrev 'vhdl-template-and))
8095 (defun vhdl-template-or-hook ()
8096 (vhdl-hooked-abbrev 'vhdl-template-or))
8097 (defun vhdl-template-nand-hook ()
8098 (vhdl-hooked-abbrev 'vhdl-template-nand))
8099 (defun vhdl-template-nor-hook ()
8100 (vhdl-hooked-abbrev 'vhdl-template-nor))
8101 (defun vhdl-template-xor-hook ()
8102 (vhdl-hooked-abbrev 'vhdl-template-xor))
8103 (defun vhdl-template-xnor-hook ()
8104 (vhdl-hooked-abbrev 'vhdl-template-xnor))
8105 (defun vhdl-template-not-hook ()
8106 (vhdl-hooked-abbrev 'vhdl-template-not))
8108 (defun vhdl-template-default-hook ()
8109 (vhdl-hooked-abbrev 'vhdl-template-default))
8110 (defun vhdl-template-default-indent-hook ()
8111 (vhdl-hooked-abbrev 'vhdl-template-default-indent))
8113 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8114 ;; Template insertion from completion list
8116 (defun vhdl-template-insert-construct (name)
8117 "Insert the built-in construct template with NAME."
8118 (interactive
8119 (list (let ((completion-ignore-case t))
8120 (completing-read "Construct name: "
8121 vhdl-template-construct-alist nil t))))
8122 (vhdl-template-insert-fun
8123 (car (cdr (assoc name vhdl-template-construct-alist)))))
8125 (defun vhdl-template-insert-package (name)
8126 "Insert the built-in package template with NAME."
8127 (interactive
8128 (list (let ((completion-ignore-case t))
8129 (completing-read "Package name: "
8130 vhdl-template-package-alist nil t))))
8131 (vhdl-template-insert-fun
8132 (car (cdr (assoc name vhdl-template-package-alist)))))
8134 (defun vhdl-template-insert-directive (name)
8135 "Insert the built-in directive template with NAME."
8136 (interactive
8137 (list (let ((completion-ignore-case t))
8138 (completing-read "Directive name: "
8139 vhdl-template-directive-alist nil t))))
8140 (vhdl-template-insert-fun
8141 (car (cdr (assoc name vhdl-template-directive-alist)))))
8143 (defun vhdl-template-insert-fun (fun)
8144 "Call FUN to insert a built-in template."
8145 (let ((caught (catch 'abort (when fun (funcall fun)))))
8146 (when (stringp caught) (message caught))))
8149 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8150 ;;; Models
8151 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8153 (defun vhdl-model-insert (model-name)
8154 "Insert the user model with name MODEL-NAME."
8155 (interactive
8156 (let ((completion-ignore-case t))
8157 (list (completing-read "Model name: " vhdl-model-alist))))
8158 (vhdl-indent-line)
8159 (let ((start (point-marker))
8160 (margin (current-indentation))
8161 (case-fold-search t)
8162 model position prompt string end)
8163 (vhdl-ext-syntax-table
8164 (when (setq model (assoc model-name vhdl-model-alist))
8165 ;; insert model
8166 (beginning-of-line)
8167 (delete-horizontal-space)
8168 (goto-char start)
8169 (vhdl-insert-string-or-file (nth 1 model))
8170 (setq end (point-marker))
8171 ;; indent code
8172 (goto-char start)
8173 (beginning-of-line)
8174 (while (< (point) end)
8175 (unless (looking-at "^$")
8176 (insert-char ? margin))
8177 (beginning-of-line 2))
8178 (goto-char start)
8179 ;; insert clock
8180 (unless (equal "" vhdl-clock-name)
8181 (while (re-search-forward "<clock>" end t)
8182 (replace-match vhdl-clock-name)))
8183 (goto-char start)
8184 ;; insert reset
8185 (unless (equal "" vhdl-reset-name)
8186 (while (re-search-forward "<reset>" end t)
8187 (replace-match vhdl-reset-name)))
8188 (goto-char start)
8189 ;; query prompts
8190 (while (re-search-forward
8191 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") end t)
8192 (unless (equal "cursor" (match-string 1))
8193 (setq position (match-beginning 1))
8194 (setq prompt (match-string 1))
8195 (replace-match "")
8196 (setq string (vhdl-template-field prompt nil t))
8197 ;; replace occurrences of same prompt
8198 (while (re-search-forward (concat "<\\(" prompt "\\)>") end t)
8199 (replace-match (or string "")))
8200 (goto-char position)))
8201 (goto-char start)
8202 ;; goto final position
8203 (if (re-search-forward "<cursor>" end t)
8204 (replace-match "")
8205 (goto-char end))))))
8207 (defun vhdl-model-defun ()
8208 "Define help and hook functions for user models."
8209 (let ((model-alist vhdl-model-alist)
8210 model-name model-keyword)
8211 (while model-alist
8212 ;; define functions for user models that can be invoked from menu and key
8213 ;; bindings and which themselves call `vhdl-model-insert' with the model
8214 ;; name as argument
8215 (setq model-name (nth 0 (car model-alist)))
8216 (eval `(defun ,(vhdl-function-name "vhdl-model" model-name) ()
8217 ,(concat "Insert model for \"" model-name "\".")
8218 (interactive)
8219 (vhdl-model-insert ,model-name)))
8220 ;; define hooks for user models that are invoked from keyword abbrevs
8221 (setq model-keyword (nth 3 (car model-alist)))
8222 (unless (equal model-keyword "")
8223 (eval `(defun
8224 ,(vhdl-function-name
8225 "vhdl-model" model-name "hook") ()
8226 (vhdl-hooked-abbrev
8227 ',(vhdl-function-name "vhdl-model" model-name)))))
8228 (setq model-alist (cdr model-alist)))))
8230 (vhdl-model-defun)
8233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8234 ;;; Port translation
8235 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8237 (defvar vhdl-port-list nil
8238 "Variable to hold last PORT map parsed.")
8239 ;; structure: (parenthesised expression means list of such entries)
8240 ;; ((generic-names) generic-type generic-init generic-comment)
8241 ;; ((port-names) port-object port-direct port-type port-comment)
8243 (defun vhdl-parse-string (string &optional optional)
8244 "Check that the text following point matches the regexp in STRING.
8245 END is the point beyond which matching/searching should not go."
8246 (if (looking-at string)
8247 (re-search-forward string nil t)
8248 (unless optional
8249 (throw 'parse (format "Syntax error near line %s" (vhdl-current-line))))
8250 nil))
8252 (defun vhdl-replace-string (regexp-cons string)
8253 "Replace STRING from car of REGEXP-CONS to cdr of REGEXP-CONS."
8254 (vhdl-ext-syntax-table
8255 (if (string-match (car regexp-cons) string)
8256 (replace-match (cdr regexp-cons) t nil string)
8257 string)))
8259 (defun vhdl-port-flatten ()
8260 "Flatten port list so that only one generic/port exists per line."
8261 (interactive)
8262 (if (not vhdl-port-list)
8263 (error "No port read")
8264 (message "Flattening port...")
8265 (let ((new-vhdl-port-list (list (car vhdl-port-list)))
8266 (old-vhdl-port-list (cdr vhdl-port-list))
8267 old-port-list new-port-list old-port new-port names)
8268 ;; traverse port list and flatten entries
8269 (while old-vhdl-port-list
8270 (setq old-port-list (car old-vhdl-port-list))
8271 (setq new-port-list nil)
8272 (while old-port-list
8273 (setq old-port (car old-port-list))
8274 (setq names (car old-port))
8275 (while names
8276 (setq new-port (cons (list (car names)) (cdr old-port)))
8277 (setq new-port-list (append new-port-list (list new-port)))
8278 (setq names (cdr names)))
8279 (setq old-port-list (cdr old-port-list)))
8280 (setq old-vhdl-port-list (cdr old-vhdl-port-list))
8281 (setq new-vhdl-port-list (append new-vhdl-port-list
8282 (list new-port-list))))
8283 (setq vhdl-port-list new-vhdl-port-list)
8284 (message "Flattening port...done"))))
8286 (defun vhdl-port-copy ()
8287 "Get generic and port information from an entity or component declaration."
8288 (interactive)
8289 (message "Reading port...")
8290 (save-excursion
8291 (let ((case-fold-search t)
8292 parse-error end-of-list
8293 name generics ports
8294 object names direct type init comment)
8295 (vhdl-ext-syntax-table
8296 (setq
8297 parse-error
8298 (catch 'parse
8299 ;; check if within entity or component declaration
8300 (when (or (not (re-search-backward
8301 "^\\s-*\\(component\\|entity\\|end\\)\\>" nil t))
8302 (equal "end" (match-string 1)))
8303 (throw 'parse "Not within entity or component declaration"))
8304 (forward-word 1)
8305 (vhdl-parse-string "\\s-*\\(\\w+\\)\\s-*\\(is\\)?\\s-*$")
8306 (setq name (match-string 1))
8307 (vhdl-forward-syntactic-ws)
8308 ;; parse generic clause
8309 (when (vhdl-parse-string "generic[ \t\n]*(" t)
8310 (vhdl-forward-syntactic-ws)
8311 (setq end-of-list (looking-at ")"))
8312 (while (not end-of-list)
8313 ;; parse names
8314 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8315 (setq names (list (match-string 1)))
8316 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8317 (setq names (append names (list (match-string 1)))))
8318 ;; parse type
8319 (vhdl-parse-string ":[ \t\n]*\\([^():;\n]+\\)")
8320 (setq type (match-string 1))
8321 (setq comment nil)
8322 (while (looking-at "(")
8323 (setq type
8324 (concat type
8325 (buffer-substring
8326 (point) (progn (forward-sexp) (point)))
8327 (and (vhdl-parse-string "\\([^():;\n]*\\)" t)
8328 (match-string 1)))))
8329 ;; special case: closing parenthesis is on separate line
8330 (when (and type (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type))
8331 (setq comment (substring type (match-beginning 2)))
8332 (setq type (substring type 0 (match-beginning 1))))
8333 ;; strip of trailing whitespace
8334 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8335 (setq type (substring type 0 (match-end 1)))
8336 ;; parse initialization expression
8337 (setq init nil)
8338 (when (vhdl-parse-string ":=[ \t\n]*" t)
8339 (vhdl-parse-string "\\([^();\n]*\\)")
8340 (setq init (match-string 1))
8341 (while (looking-at "(")
8342 (setq init
8343 (concat init
8344 (buffer-substring
8345 (point) (progn (forward-sexp) (point)))
8346 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8347 (match-string 1))))))
8348 ;; special case: closing parenthesis is on separate line
8349 (when (and init (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" init))
8350 (setq comment (substring init (match-beginning 2)))
8351 (setq init (substring init 0 (match-beginning 1)))
8352 (vhdl-forward-syntactic-ws))
8353 (skip-chars-forward " \t")
8354 ;; parse inline comment, special case: as above, no initial.
8355 (unless comment
8356 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8357 (match-string 1))))
8358 (vhdl-forward-syntactic-ws)
8359 (setq end-of-list (vhdl-parse-string ")" t))
8360 (vhdl-parse-string ";\\s-*")
8361 ;; parse inline comment
8362 (unless comment
8363 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8364 (match-string 1))))
8365 (vhdl-forward-syntactic-ws)
8366 ;; save everything in list
8367 (setq generics (append generics
8368 (list (list names type init comment))))))
8369 ;; parse port clause
8370 (when (vhdl-parse-string "port[ \t\n]*(" t)
8371 (vhdl-forward-syntactic-ws)
8372 (setq end-of-list (looking-at ")"))
8373 (while (not end-of-list)
8374 ;; parse object
8375 (setq object
8376 (and (vhdl-parse-string
8377 "\\(signal\\|quantity\\|terminal\\)[ \t\n]*" t)
8378 (match-string 1)))
8379 ;; parse names
8380 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8381 (setq names (list (match-string 1)))
8382 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8383 (setq names (append names (list (match-string 1)))))
8384 ;; parse direction
8385 (vhdl-parse-string ":[ \t\n]*")
8386 (setq direct
8387 (and (vhdl-parse-string "\\(IN\\|OUT\\|INOUT\\)[ \t\n]+" t)
8388 (match-string 1)))
8389 ;; parse type
8390 (vhdl-parse-string "\\([^();\n]+\\)")
8391 (setq type (match-string 1))
8392 (setq comment nil)
8393 (while (looking-at "(")
8394 (setq type (concat type
8395 (buffer-substring
8396 (point) (progn (forward-sexp) (point)))
8397 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8398 (match-string 1)))))
8399 ;; special case: closing parenthesis is on separate line
8400 (when (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type)
8401 (setq comment (substring type (match-beginning 2)))
8402 (setq type (substring type 0 (match-beginning 1))))
8403 ;; strip of trailing whitespace
8404 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8405 (setq type (substring type 0 (match-end 1)))
8406 (vhdl-forward-syntactic-ws)
8407 (setq end-of-list (vhdl-parse-string ")" t))
8408 (vhdl-parse-string ";\\s-*")
8409 ;; parse inline comment
8410 (unless comment
8411 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8412 (match-string 1))))
8413 (vhdl-forward-syntactic-ws)
8414 ;; save everything in list
8415 (setq ports
8416 (append ports
8417 (list (list names object direct type comment))))))
8418 nil)))
8419 ;; finish parsing
8420 (if parse-error
8421 (error parse-error)
8422 (setq vhdl-port-list (list name generics ports))
8423 (message "Reading port...done")))))
8425 (defun vhdl-port-paste-generic (&optional no-init)
8426 "Paste a generic clause."
8427 (let ((margin (current-indentation))
8428 list-margin start names generic
8429 (generics-list (nth 1 vhdl-port-list)))
8430 ;; paste generic clause
8431 (when generics-list
8432 (setq start (point))
8433 (vhdl-insert-keyword "GENERIC (")
8434 (unless vhdl-argument-list-indent
8435 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8436 (setq list-margin (current-column))
8437 (while generics-list
8438 ;; paste names
8439 (setq generic (car generics-list))
8440 (setq names (nth 0 generic))
8441 (while names
8442 (insert (car names))
8443 (setq names (cdr names))
8444 (when names (insert ", ")))
8445 ;; paste type
8446 (insert " : " (nth 1 generic))
8447 ;; paste initialization
8448 (when (and (not no-init) (nth 2 generic))
8449 (insert " := " (nth 2 generic)))
8450 (unless (cdr generics-list) (insert ")"))
8451 (insert ";")
8452 ;; paste comment
8453 (when (and vhdl-include-port-comments (nth 3 generic))
8454 (vhdl-comment-insert-inline (nth 3 generic) t))
8455 (setq generics-list (cdr generics-list))
8456 (when generics-list (insert "\n") (indent-to list-margin)))
8457 ;; align generic clause
8458 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1 t)))))
8460 (defun vhdl-port-paste-port ()
8461 "Paste a port clause."
8462 (let ((margin (current-indentation))
8463 list-margin start names port
8464 (ports-list (nth 2 vhdl-port-list)))
8465 ;; paste port clause
8466 (when ports-list
8467 (setq start (point))
8468 (vhdl-insert-keyword "PORT (")
8469 (unless vhdl-argument-list-indent
8470 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8471 (setq list-margin (current-column))
8472 (while ports-list
8473 (setq port (car ports-list))
8474 ;; paste object
8475 (when (nth 1 port) (insert (nth 1 port) " "))
8476 ;; paste names
8477 (setq names (nth 0 port))
8478 (while names
8479 (insert (car names))
8480 (setq names (cdr names))
8481 (when names (insert ", ")))
8482 ;; paste direction
8483 (insert " : ")
8484 (when (nth 2 port) (insert (nth 2 port) " "))
8485 ;; paste type
8486 (insert (nth 3 port))
8487 (unless (cdr ports-list) (insert ")"))
8488 (insert ";")
8489 ;; paste comment
8490 (when (and vhdl-include-port-comments (nth 4 port))
8491 (vhdl-comment-insert-inline (nth 4 port) t))
8492 (setq ports-list (cdr ports-list))
8493 (when ports-list (insert "\n") (indent-to list-margin)))
8494 ;; align port clause
8495 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
8497 (defun vhdl-port-paste-declaration (kind)
8498 "Paste as an entity or component declaration."
8499 (vhdl-indent-line)
8500 (let ((margin (current-indentation))
8501 (name (nth 0 vhdl-port-list)))
8502 (vhdl-insert-keyword (if (eq kind 'entity) "ENTITY " "COMPONENT "))
8503 (insert name)
8504 (if (eq kind 'entity) (vhdl-insert-keyword " IS"))
8505 ;; paste generic and port clause
8506 (when (nth 1 vhdl-port-list)
8507 (insert "\n")
8508 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8509 (insert "\n"))
8510 (indent-to (+ margin vhdl-basic-offset))
8511 (vhdl-port-paste-generic (eq kind 'component)))
8512 (when (nth 2 vhdl-port-list)
8513 (insert "\n")
8514 (when (and (memq vhdl-insert-empty-lines '(unit all))
8515 (eq kind 'entity))
8516 (insert "\n"))
8517 (indent-to (+ margin vhdl-basic-offset)))
8518 (vhdl-port-paste-port)
8519 (insert "\n")
8520 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8521 (insert "\n"))
8522 (indent-to margin)
8523 (vhdl-insert-keyword "END")
8524 (if (eq kind 'entity)
8525 (progn
8526 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " ENTITY"))
8527 (insert " " name))
8528 (vhdl-insert-keyword " COMPONENT")
8529 (unless (vhdl-standard-p '87) (insert " " name)))
8530 (insert ";")))
8532 (defun vhdl-port-paste-entity ()
8533 "Paste as an entity declaration."
8534 (interactive)
8535 (if (not vhdl-port-list)
8536 (error "No port read")
8537 (message "Pasting port as entity...")
8538 (vhdl-port-paste-declaration 'entity)
8539 (message "Pasting port as entity...done")))
8541 (defun vhdl-port-paste-component ()
8542 "Paste as a component declaration."
8543 (interactive)
8544 (if (not vhdl-port-list)
8545 (error "No port read")
8546 (message "Pasting port as component...")
8547 (vhdl-port-paste-declaration 'component)
8548 (message "Pasting port as component...done")))
8550 (defun vhdl-port-paste-generic-map (&optional secondary no-constants)
8551 "Paste as a generic map."
8552 (interactive)
8553 (unless secondary (vhdl-indent-line))
8554 (let ((margin (current-indentation))
8555 list-margin start generic
8556 (generics-list (nth 1 vhdl-port-list)))
8557 (when generics-list
8558 (setq start (point))
8559 (vhdl-insert-keyword "GENERIC MAP (")
8560 (if (not vhdl-association-list-with-formals)
8561 ;; paste list of actual generics
8562 (while generics-list
8563 (insert (or (nth 2 (car generics-list)) " "))
8564 (setq generics-list (cdr generics-list))
8565 (insert (if generics-list ", " ")")))
8566 (unless vhdl-argument-list-indent
8567 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
8568 (setq list-margin (current-column))
8569 (while generics-list
8570 (setq generic (car generics-list))
8571 ;; paste formal and actual generic
8572 (insert (car (nth 0 generic)) " => "
8573 (if no-constants
8574 (car (nth 0 generic))
8575 (or (nth 2 generic) "")))
8576 (setq generics-list (cdr generics-list))
8577 (insert (if generics-list "," ")"))
8578 ;; paste comment
8579 (when (and vhdl-include-port-comments (nth 3 generic))
8580 (vhdl-comment-insert-inline (nth 3 generic) t))
8581 (when generics-list (insert "\n") (indent-to list-margin)))
8582 ;; align generic map
8583 (when vhdl-auto-align
8584 (vhdl-align-noindent-region start (point) 1 t))))))
8586 (defun vhdl-port-paste-port-map ()
8587 "Paste as a port map."
8588 (let ((margin (current-indentation))
8589 list-margin start port
8590 (ports-list (nth 2 vhdl-port-list)))
8591 (when ports-list
8592 (setq start (point))
8593 (vhdl-insert-keyword "PORT MAP (")
8594 (if (not vhdl-association-list-with-formals)
8595 ;; paste list of actual ports
8596 (while ports-list
8597 (insert (vhdl-replace-string vhdl-actual-port-name
8598 (car (nth 0 (car ports-list)))))
8599 (setq ports-list (cdr ports-list))
8600 (insert (if ports-list ", " ");")))
8601 (unless vhdl-argument-list-indent
8602 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
8603 (setq list-margin (current-column))
8604 (while ports-list
8605 (setq port (car ports-list))
8606 ;; paste formal and actual port
8607 (insert (car (nth 0 port)) " => ")
8608 (insert (vhdl-replace-string vhdl-actual-port-name
8609 (car (nth 0 port))))
8610 (setq ports-list (cdr ports-list))
8611 (insert (if ports-list "," ");"))
8612 ;; paste comment
8613 (when (or vhdl-include-direction-comments
8614 (and vhdl-include-port-comments (nth 4 port)))
8615 (vhdl-comment-insert-inline
8616 (concat
8617 (if vhdl-include-direction-comments
8618 (format "%-4s" (or (concat (nth 2 port) " ") "")) "")
8619 (if vhdl-include-port-comments (nth 4 port) "")) t))
8620 (when ports-list (insert "\n") (indent-to list-margin)))
8621 ;; align port clause
8622 (when vhdl-auto-align
8623 (vhdl-align-noindent-region start (point) 1))))))
8625 (defun vhdl-port-paste-instance (&optional name)
8626 "Paste as an instantiation."
8627 (interactive)
8628 (if (not vhdl-port-list)
8629 (error "No port read")
8630 (let ((orig-vhdl-port-list vhdl-port-list))
8631 ;; flatten local copy of port list (must be flat for port mapping)
8632 (vhdl-port-flatten)
8633 (vhdl-indent-line)
8634 (let ((margin (current-indentation))
8635 list-margin start generic port
8636 (generics-list (nth 1 vhdl-port-list))
8637 (ports-list (nth 2 vhdl-port-list)))
8638 ;; paste instantiation
8639 (if name
8640 (insert name ": ")
8641 (if (equal (cdr vhdl-instance-name) "")
8642 (vhdl-template-field "instance name" ": ")
8643 (insert (vhdl-replace-string vhdl-instance-name
8644 (nth 0 vhdl-port-list)) ": ")))
8645 (message "Pasting port as instantiation...")
8646 (if (vhdl-standard-p '87)
8647 (insert (nth 0 vhdl-port-list))
8648 (vhdl-insert-keyword "ENTITY ")
8649 (insert "work." (nth 0 vhdl-port-list)))
8650 (when (nth 1 vhdl-port-list)
8651 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8652 (vhdl-port-paste-generic-map t t))
8653 (when (nth 2 vhdl-port-list)
8654 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8655 (vhdl-port-paste-port-map))
8656 (message "Pasting port as instantiation...done"))
8657 (setq vhdl-port-list orig-vhdl-port-list))))
8659 (defun vhdl-port-paste-signals (&optional initialize)
8660 "Paste ports as internal signals."
8661 (interactive)
8662 (if (not vhdl-port-list)
8663 (error "No port read")
8664 (message "Pasting port as signals...")
8665 (vhdl-indent-line)
8666 (let ((margin (current-indentation))
8667 start port names
8668 (ports-list (nth 2 vhdl-port-list)))
8669 (when ports-list
8670 (setq start (point))
8671 (while ports-list
8672 (setq port (car ports-list))
8673 ;; paste object
8674 (if (nth 1 port)
8675 (insert (nth 1 port) " ")
8676 (vhdl-insert-keyword "SIGNAL "))
8677 ;; paste actual port signals
8678 (setq names (nth 0 port))
8679 (while names
8680 (insert (vhdl-replace-string vhdl-actual-port-name (car names)))
8681 (setq names (cdr names))
8682 (when names (insert ", ")))
8683 ;; paste type
8684 (insert " : " (nth 3 port))
8685 ;; paste initialization (inputs only)
8686 (when (and initialize (equal "in" (nth 2 port)))
8687 (insert
8688 " := "
8689 (if (string-match "(.+)" (nth 3 port)) "(others => '0')" "'0'")))
8690 (insert ";")
8691 ;; paste comment
8692 (when (and vhdl-include-port-comments (nth 4 port))
8693 (vhdl-comment-insert-inline (nth 4 port) t))
8694 (setq ports-list (cdr ports-list))
8695 (when ports-list (insert "\n") (indent-to margin)))
8696 ;; align signal list
8697 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))))
8698 (message "Pasting port as signals...done")))
8700 (defun vhdl-port-paste-constants ()
8701 "Paste generics as constants."
8702 (interactive)
8703 (if (not vhdl-port-list)
8704 (error "No port read")
8705 (let ((orig-vhdl-port-list vhdl-port-list))
8706 (message "Pasting port as constants...")
8707 ;; flatten local copy of port list (must be flat for constant initial.)
8708 (vhdl-port-flatten)
8709 (vhdl-indent-line)
8710 (let ((margin (current-indentation))
8711 start generic name
8712 (generics-list (nth 1 vhdl-port-list)))
8713 (when generics-list
8714 (setq start (point))
8715 (while generics-list
8716 (setq generic (car generics-list))
8717 (vhdl-insert-keyword "CONSTANT ")
8718 ;; paste generic constants
8719 (setq name (nth 0 generic))
8720 (when name
8721 (insert (car name))
8722 ;; paste type
8723 (insert " : " (nth 1 generic))
8724 ;; paste initialization
8725 (when (nth 2 generic)
8726 (insert " := " (nth 2 generic)))
8727 (insert ";")
8728 ;; paste comment
8729 (when (and vhdl-include-port-comments (nth 3 generic))
8730 (vhdl-comment-insert-inline (nth 3 generic) t))
8731 (setq generics-list (cdr generics-list))
8732 (when generics-list (insert "\n") (indent-to margin))))
8733 ;; align signal list
8734 (when vhdl-auto-align
8735 (vhdl-align-noindent-region start (point) 1))))
8736 (message "Pasting port as constants...done")
8737 (setq vhdl-port-list orig-vhdl-port-list))))
8739 (defun vhdl-port-paste-testbench ()
8740 "Paste as a bare-bones test bench."
8741 (interactive)
8742 (if (not vhdl-port-list)
8743 (error "No port read")
8744 (message "Pasting port as test bench...")
8745 (let ((case-fold-search t)
8746 (ent-name (vhdl-replace-string vhdl-testbench-entity-name
8747 (nth 0 vhdl-port-list)))
8748 (source-buffer (current-buffer))
8749 arch-name ent-file-name arch-file-name no-entity position)
8750 ;; open entity file
8751 (when (not (eq vhdl-testbench-create-files 'none))
8752 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8753 (setq ent-file-name
8754 (concat ent-name
8755 (substring (buffer-file-name (current-buffer))
8756 (match-beginning 0))))
8757 (when (file-exists-p ent-file-name)
8758 (if (y-or-n-p
8759 (concat "File `" ent-file-name "' exists; overwrite? "))
8760 (progn (delete-file ent-file-name)
8761 (when (get-file-buffer ent-file-name)
8762 (set-buffer ent-file-name)
8763 (set-buffer-modified-p nil)
8764 (kill-buffer ent-file-name)))
8765 (if (eq vhdl-testbench-create-files 'separate)
8766 (setq no-entity t)
8767 (error "Pasting port as test bench...aborted"))))
8768 (unless no-entity
8769 (set-buffer source-buffer)
8770 (find-file ent-file-name)))
8771 (let ((margin 0))
8772 (unless (and (eq vhdl-testbench-create-files 'separate) no-entity)
8773 ;; paste entity header
8774 (unless (equal "" vhdl-testbench-entity-header)
8775 (vhdl-insert-string-or-file vhdl-testbench-entity-header))
8776 (vhdl-comment-display-line) (insert "\n\n") (indent-to margin)
8777 ;; paste std_logic_1164 package
8778 (vhdl-insert-keyword "LIBRARY ")
8779 (insert "ieee;\n") (indent-to margin)
8780 (vhdl-insert-keyword "USE ")
8781 (insert "ieee.std_logic_1164.")
8782 (vhdl-insert-keyword "ALL;")
8783 (insert "\n\n") (indent-to margin) (vhdl-comment-display-line)
8784 (insert "\n\n") (indent-to margin)
8785 ;; paste entity declaration
8786 (vhdl-insert-keyword "ENTITY ")
8787 (insert ent-name)
8788 (vhdl-insert-keyword " IS")
8789 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
8790 (insert "\n") (indent-to margin)
8791 (vhdl-insert-keyword "END ")
8792 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
8793 (insert ent-name ";")
8794 (insert "\n\n") (indent-to margin)
8795 (vhdl-comment-display-line) (insert "\n"))
8796 ;; get architecture name
8797 (setq arch-name
8798 (if (equal (cdr vhdl-testbench-architecture-name) "")
8799 (read-from-minibuffer "architecture name: "
8800 nil vhdl-minibuffer-local-map)
8801 (vhdl-replace-string vhdl-testbench-architecture-name
8802 (nth 0 vhdl-port-list))))
8803 ;; open architecture file
8804 (when (eq vhdl-testbench-create-files 'separate)
8805 (save-buffer)
8806 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8807 (setq arch-file-name
8808 (concat arch-name
8809 (substring (buffer-file-name (current-buffer))
8810 (match-beginning 0))))
8811 (when (file-exists-p arch-file-name)
8812 (if (y-or-n-p
8813 (concat "File `" ent-file-name "' exists; overwrite? "))
8814 (progn (delete-file arch-file-name)
8815 (when (get-file-buffer arch-file-name)
8816 (set-buffer (get-file-buffer arch-file-name))
8817 (set-buffer-modified-p nil)
8818 (kill-buffer arch-file-name)))
8819 (error "Pasting port as test bench...aborted")))
8820 (set-buffer source-buffer)
8821 (find-file arch-file-name)
8822 ;; paste architecture header
8823 (unless (equal "" vhdl-testbench-architecture-header)
8824 (vhdl-insert-string-or-file vhdl-testbench-architecture-header))
8825 (vhdl-comment-display-line)
8826 (insert "\n"))
8827 (insert "\n") (indent-to margin)
8828 ;; paste architecture body
8829 (vhdl-insert-keyword "ARCHITECTURE ")
8830 (insert arch-name)
8831 (vhdl-insert-keyword " OF ")
8832 (insert ent-name)
8833 (vhdl-insert-keyword " IS")
8834 (insert "\n\n") (indent-to margin)
8835 ;; paste component declaration
8836 (when (vhdl-standard-p '87)
8837 (vhdl-port-paste-component)
8838 (insert "\n\n") (indent-to margin))
8839 ;; paste constants
8840 (when (nth 1 vhdl-port-list)
8841 (vhdl-port-paste-constants)
8842 (insert "\n\n") (indent-to margin))
8843 ;; paste internal signals
8844 (vhdl-port-paste-signals vhdl-testbench-initialize-signals)
8845 ;; paste custom declarations
8846 (unless (equal "" vhdl-testbench-declarations)
8847 (insert "\n\n")
8848 (vhdl-insert-string-or-file vhdl-testbench-declarations)
8849 (delete-indentation))
8850 (setq position (point))
8851 (insert "\n\n") (indent-to margin)
8852 (vhdl-comment-display-line) (insert "\n")
8853 (goto-char position)
8854 (vhdl-template-begin-end
8855 (unless (vhdl-standard-p '87) "ARCHITECTURE")
8856 arch-name margin t)
8857 ;; paste instantiation
8858 (vhdl-port-paste-instance
8859 (vhdl-replace-string vhdl-testbench-dut-name
8860 (nth 0 vhdl-port-list)))
8861 (insert "\n")
8862 ;; paste custom statements
8863 (unless (equal "" vhdl-testbench-statements)
8864 (insert "\n")
8865 (vhdl-insert-string-or-file vhdl-testbench-statements))
8866 (insert "\n")
8867 (indent-to (+ margin vhdl-basic-offset))
8868 (when (not (eq vhdl-testbench-create-files 'none))
8869 (save-buffer))
8870 (message "Pasting port as test bench...done")))))
8873 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8874 ;;; Miscellaneous
8875 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8877 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8878 ;; Hippie expand customization
8880 (defvar vhdl-expand-upper-case nil)
8882 (defun vhdl-try-expand-abbrev (old)
8883 "Try expanding abbreviations from `vhdl-abbrev-list'."
8884 (unless old
8885 (he-init-string (he-dabbrev-beg) (point))
8886 (setq he-expand-list
8887 (let ((abbrev-list vhdl-abbrev-list)
8888 (sel-abbrev-list '()))
8889 (while abbrev-list
8890 (when (or (not (stringp (car abbrev-list)))
8891 (string-match
8892 (concat "^" he-search-string) (car abbrev-list)))
8893 (setq sel-abbrev-list
8894 (cons (car abbrev-list) sel-abbrev-list)))
8895 (setq abbrev-list (cdr abbrev-list)))
8896 (nreverse sel-abbrev-list))))
8897 (while (and he-expand-list
8898 (or (not (stringp (car he-expand-list)))
8899 (he-string-member (car he-expand-list) he-tried-table t)))
8900 ; (equal (car he-expand-list) he-search-string)))
8901 (unless (stringp (car he-expand-list))
8902 (setq vhdl-expand-upper-case (car he-expand-list)))
8903 (setq he-expand-list (cdr he-expand-list)))
8904 (if (null he-expand-list)
8905 (progn (when old (he-reset-string))
8906 nil)
8907 (he-substitute-string
8908 (if vhdl-expand-upper-case
8909 (upcase (car he-expand-list))
8910 (car he-expand-list))
8912 (setq he-expand-list (cdr he-expand-list))
8915 (defun vhdl-he-list-beg ()
8916 "Also looks at the word before `(' in order to better match parenthesized
8917 expressions (e.g. for index ranges of types and signals)."
8918 (save-excursion
8919 (condition-case ()
8920 (progn (backward-up-list 1)
8921 (skip-syntax-backward "w_")) ; crashes in `viper-mode'
8922 (error ()))
8923 (point)))
8925 ;; override `he-list-beg' from `hippie-exp'
8926 (unless (and (boundp 'viper-mode) viper-mode)
8927 (require 'hippie-exp)
8928 (defalias 'he-list-beg 'vhdl-he-list-beg))
8930 ;; function for expanding abbrevs and dabbrevs
8931 (fset 'vhdl-expand-abbrev (make-hippie-expand-function
8932 '(try-expand-dabbrev
8933 try-expand-dabbrev-all-buffers
8934 vhdl-try-expand-abbrev)))
8936 ;; function for expanding parenthesis
8937 (fset 'vhdl-expand-paren (make-hippie-expand-function
8938 '(try-expand-list
8939 try-expand-list-all-buffers)))
8941 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8942 ;; Case fixing
8944 (defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
8945 "Convert all words matching word-regexp in region to lower or upper case,
8946 depending on parameter upper-case."
8947 (let ((case-fold-search t)
8948 (case-replace nil)
8949 (last-update 0))
8950 (vhdl-ext-syntax-table
8951 (save-excursion
8952 (goto-char end)
8953 (setq end (point-marker))
8954 (goto-char beg)
8955 (while (re-search-forward word-regexp end t)
8956 (or (vhdl-in-comment-p)
8957 (vhdl-in-string-p)
8958 (if upper-case
8959 (upcase-word -1)
8960 (downcase-word -1)))
8961 (when (and count vhdl-progress-interval
8962 (< vhdl-progress-interval
8963 (- (nth 1 (current-time)) last-update)))
8964 (message "Fixing case... (%2d%s)"
8965 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg)))
8966 "%")
8967 (setq last-update (nth 1 (current-time)))))
8968 (goto-char end)))
8969 (and count vhdl-progress-interval (message "Fixing case...done"))))
8971 (defun vhdl-fix-case-region (beg end &optional arg)
8972 "Convert all VHDL words in region to lower or upper case, depending on
8973 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
8974 (interactive "r\nP")
8975 (vhdl-fix-case-region-1
8976 beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
8977 (vhdl-fix-case-region-1
8978 beg end vhdl-upper-case-types vhdl-types-regexp 1)
8979 (vhdl-fix-case-region-1
8980 beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
8981 (vhdl-fix-case-region-1
8982 beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3))
8984 (defun vhdl-fix-case-buffer ()
8985 "Convert all VHDL words in buffer to lower or upper case, depending on
8986 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
8987 (interactive)
8988 (vhdl-fix-case-region (point-min) (point-max)))
8990 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8991 ;; Line handling functions
8993 (defun vhdl-current-line ()
8994 "Return the line number of the line containing point."
8995 (save-restriction
8996 (widen)
8997 (save-excursion
8998 (beginning-of-line)
8999 (1+ (count-lines 1 (point))))))
9001 (defun vhdl-line-kill-entire (&optional arg)
9002 "Delete entire line."
9003 (interactive "p")
9004 (beginning-of-line)
9005 (kill-line (or arg 1)))
9007 (defun vhdl-line-kill (&optional arg)
9008 "Kill current line."
9009 (interactive "p")
9010 (vhdl-line-kill-entire arg))
9012 (defun vhdl-line-copy (&optional arg)
9013 "Copy current line."
9014 (interactive "p")
9015 (save-excursion
9016 (beginning-of-line)
9017 (let ((position (point)))
9018 (forward-line (or arg 1))
9019 (copy-region-as-kill position (point)))))
9021 (defun vhdl-line-yank ()
9022 "Yank entire line."
9023 (interactive)
9024 (beginning-of-line)
9025 (yank))
9027 (defun vhdl-line-expand (&optional prefix-arg)
9028 "Hippie-expand current line."
9029 (interactive "P")
9030 (let ((case-fold-search t) (case-replace nil)
9031 (hippie-expand-try-functions-list
9032 '(try-expand-line try-expand-line-all-buffers)))
9033 (hippie-expand prefix-arg)))
9035 (defun vhdl-line-transpose-next (&optional arg)
9036 "Interchange this line with next line."
9037 (interactive "p")
9038 (forward-line 1)
9039 (transpose-lines (or arg 1))
9040 (forward-line -1))
9042 (defun vhdl-line-transpose-previous (&optional arg)
9043 "Interchange this line with previous line."
9044 (interactive "p")
9045 (forward-line 1)
9046 (transpose-lines (- 0 (or arg 0)))
9047 (forward-line -1))
9049 (defun vhdl-line-open ()
9050 "Open a new line and indent."
9051 (interactive)
9052 (end-of-line -0)
9053 (newline-and-indent))
9056 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9057 ;;; Project
9058 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9060 (defun vhdl-project-switch (name)
9061 "Switch to project NAME."
9062 (setq vhdl-project name)
9063 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
9064 (speedbar-refresh)))
9067 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9068 ;;; Compilation
9069 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9070 ;; (using `compile.el')
9072 (defun vhdl-compile-init ()
9073 "Initialize for compilation."
9074 (unless compilation-error-regexp-alist
9075 (setq compilation-error-regexp-alist
9076 (let ((commands-alist vhdl-compiler-alist)
9077 regexp-alist sublist)
9078 (while commands-alist
9079 (setq sublist (nth 5 (car commands-alist)))
9080 (unless (equal "" (car sublist))
9081 (setq regexp-alist
9082 (cons (list (nth 0 sublist)
9083 (if (= 0 (nth 1 sublist))
9084 (if (string-match
9085 "XEmacs" emacs-version) 9 nil)
9086 (nth 1 sublist))
9087 (nth 2 sublist))
9088 regexp-alist)))
9089 (setq commands-alist (cdr commands-alist)))
9090 regexp-alist)))
9091 (unless compilation-file-regexp-alist
9092 (setq compilation-file-regexp-alist
9093 (let ((commands-alist vhdl-compiler-alist)
9094 regexp-alist)
9095 (while commands-alist
9096 (unless (equal "" (car (nth 6 (car commands-alist))))
9097 (setq regexp-alist
9098 (append regexp-alist
9099 (list (nth 6 (car commands-alist))))))
9100 (setq commands-alist (cdr commands-alist)))
9101 regexp-alist))))
9103 (defun vhdl-compile ()
9104 "Compile current buffer using the VHDL compiler specified in
9105 `vhdl-compiler'."
9106 (interactive)
9107 (vhdl-compile-init)
9108 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9109 (command (nth 1 command-elem))
9110 (default-directory (expand-file-name (nth 4 command-elem))))
9111 (when command
9112 (compile (concat command " " vhdl-compiler-options
9113 (unless (string-equal vhdl-compiler-options "") " ")
9114 (buffer-file-name))))))
9116 (defun vhdl-make ()
9117 "Call make command for compilation of all updated source files (requires
9118 `Makefile')."
9119 (interactive)
9120 (vhdl-compile-init)
9121 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9122 (command (nth 2 command-elem))
9123 (default-directory (expand-file-name (nth 4 command-elem))))
9124 (if (equal command "")
9125 (compile "make")
9126 (compile command))))
9128 (defun vhdl-generate-makefile ()
9129 "Generate new `Makefile'."
9130 (interactive)
9131 (vhdl-compile-init)
9132 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9133 (command (nth 3 command-elem))
9134 (default-directory (expand-file-name (nth 4 command-elem))))
9135 (if (not (equal command ""))
9136 (compile command)
9137 (error "No such command specified for `%s'" vhdl-compiler))))
9140 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9141 ;;; Hideshow
9142 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9143 ;; (using `hideshow.el')
9145 (defun vhdl-forward-unit (&optional count)
9146 "Find begin and end of VHDL design units (for hideshow)."
9147 (interactive "p")
9148 (let ((case-fold-search t))
9149 (if (< count 0)
9150 (re-search-backward
9151 "^\\(architecture\\|configuration\\|entity\\|package\\)\\>" nil t)
9152 (re-search-forward "^end\\>" nil t))))
9154 (when (string-match "XEmacs" emacs-version)
9155 (require 'hideshow))
9157 (unless (assq 'vhdl-mode hs-special-modes-alist)
9158 (setq hs-special-modes-alist
9159 (cons
9160 '(vhdl-mode
9161 "\\(^\\)\\(architecture\\|ARCHITECTURE\\|configuration\\|CONFIGURATION\\|entity\\|ENTITY\\|package\\|PACKAGE\\)\\>"
9162 "\\(^\\)\\(end\\|END\\)\\>"
9163 "--\\( \\|$\\)"
9164 vhdl-forward-unit)
9165 hs-special-modes-alist)))
9167 (defun vhdl-hideshow-init ()
9168 "Initialize `hideshow'."
9169 (if vhdl-hide-all-init
9170 (add-hook 'hs-minor-mode-hook 'hs-hide-all)
9171 (remove-hook 'hs-minor-mode-hook 'hs-hide-all))
9172 (if vhdl-hideshow-menu
9173 (hs-minor-mode 1)
9174 (when (boundp 'hs-minor-mode) (hs-minor-mode 0))))
9177 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9178 ;;; Font locking
9179 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9180 ;; (using `font-lock.el')
9182 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9183 ;; Help functions for translate-off region highlighting
9185 (defun vhdl-within-translate-off ()
9186 "Return point if within translate-off region, else nil."
9187 (and (save-excursion
9188 (re-search-backward
9189 "^\\s-*--\\s-*pragma\\s-*translate_\\(on\\|off\\)\\s-*\n" nil t))
9190 (equal "off" (match-string 1))
9191 (point)))
9193 (defun vhdl-start-translate-off (limit)
9194 "Return point before translate-off pragma if before LIMIT, else nil."
9195 (when (re-search-forward
9196 "^\\s-*--\\s-*pragma\\s-*translate_off\\s-*\n" limit t)
9197 (match-beginning 0)))
9199 (defun vhdl-end-translate-off (limit)
9200 "Return point after translate-on pragma if before LIMIT, else nil."
9201 (re-search-forward "^\\s-*--\\s-*pragma\\s-*translate_on\\s-*\n" limit t))
9203 (defun vhdl-match-translate-off (limit)
9204 "Match a translate-off block, setting match-data and returning t, else nil."
9205 (when (< (point) limit)
9206 (let ((start (or (vhdl-within-translate-off)
9207 (vhdl-start-translate-off limit)))
9208 (case-fold-search t))
9209 (when start
9210 (let ((end (or (vhdl-end-translate-off limit) limit)))
9211 (set-match-data (list start end))
9212 (goto-char end))))))
9214 (defun vhdl-font-lock-match-item (limit)
9215 "Match, and move over, any declaration item after point. Adapted from
9216 `font-lock-match-c-style-declaration-item-and-skip-to-next'."
9217 (condition-case nil
9218 (save-restriction
9219 (narrow-to-region (point-min) limit)
9220 ;; match item
9221 (when (looking-at "\\s-*\\(\\w+\\)")
9222 (save-match-data
9223 (goto-char (match-end 1))
9224 ;; move to next item
9225 (if (looking-at "\\(\\s-*,\\)")
9226 (goto-char (match-end 1))
9227 (end-of-line) t))))
9228 (error t)))
9230 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9231 ;; Syntax definitions
9233 (defconst vhdl-font-lock-syntactic-keywords
9234 '(("\\(\'\\).\\(\'\\)" (1 (7 . ?\')) (2 (7 . ?\'))))
9235 "Mark single quotes as having string quote syntax in 'c' instances.")
9237 (defvar vhdl-font-lock-keywords nil
9238 "Regular expressions to highlight in VHDL Mode.")
9240 (defconst vhdl-font-lock-keywords-0
9241 (list
9242 ;; highlight template prompts
9243 (list (concat "\\(<" vhdl-template-prompt-syntax ">\\)")
9244 1 'vhdl-font-lock-prompt-face t)
9246 ;; highlight directives
9247 '("--\\s-*pragma\\s-+\\(.*\\)$" 1 vhdl-font-lock-directive-face t)
9249 "For consideration as a value of `vhdl-font-lock-keywords'.
9250 This does highlighting of template prompts and directives (pragmas).")
9252 (defvar vhdl-font-lock-keywords-1 nil
9253 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9254 "For consideration as a value of `vhdl-font-lock-keywords'.
9255 This does highlighting of keywords and standard identifiers.")
9257 (defconst vhdl-font-lock-keywords-2
9258 (list
9259 ;; highlight names of units, subprograms, and components when declared
9260 (list
9261 (concat
9262 "^\\s-*\\("
9263 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
9264 "\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\|component"
9265 "\\)\\s-+\\(\\w+\\)")
9266 5 'font-lock-function-name-face)
9268 ;; highlight entity names of architectures and configurations
9269 (list
9270 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
9271 2 'font-lock-function-name-face)
9273 ;; highlight labels of common constructs
9274 (list
9275 (concat
9276 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\("
9277 "assert\\|block\\|case\\|component\\|configuration\\|entity\\|exit\\|"
9278 "for\\|if\\|loop\\|next\\|null\\|postponed\\|process\\|"
9279 (when (vhdl-standard-p 'ams) "procedural\\|")
9280 "with\\|while"
9281 "\\)\\>\\|[^\n]*<=\\)")
9282 1 'font-lock-function-name-face)
9284 ;; highlight label and component name of component instantiations
9285 (list
9286 (concat
9287 "^\\s-*\\(\\w+\\)\\s-*:[ \t\n]*\\(component\\s-+\\|\\)\\(\\w+\\)"
9288 "\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>")
9289 '(1 font-lock-function-name-face) '(3 font-lock-function-name-face))
9291 ;; highlight names and labels at end of constructs
9292 (list
9293 (concat
9294 "^\\s-*end\\s-+\\(\\("
9295 "architecture\\|block\\|case\\|component\\|configuration\\|entity\\|"
9296 "for\\|function\\|generate\\|if\\|loop\\|package\\(\\s-+body\\|\\)\\|"
9297 "procedure\\|\\(postponed\\s-+\\|\\)process\\|"
9298 (when (vhdl-standard-p 'ams) "procedural\\|")
9299 "units"
9300 "\\)\\>\\|\\)\\s-*\\(\\w*\\)")
9301 5 'font-lock-function-name-face)
9303 ;; highlight labels in exit and next statements
9304 (list
9305 (concat
9306 "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(exit\\|next\\)\\s-+\\(\\w*\\)")
9307 3 'font-lock-function-name-face)
9309 ;; highlight entity name in attribute specifications
9310 (list
9311 (concat
9312 "^\\s-*attribute\\s-+\\w+\\s-+of\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:")
9313 1 'font-lock-function-name-face)
9315 ;; highlight labels in component specifications
9316 (list
9317 (concat
9318 "^\\s-*for\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:"
9319 "\\(\\s-\\|\n\\)*\\(\\w+\\)")
9320 '(1 font-lock-function-name-face) '(4 font-lock-function-name-face))
9322 ;; highlight attribute name in attribute declarations/specifications
9323 (list
9324 (concat
9325 "^\\s-*attribute\\s-+\\(\\w+\\)")
9326 1 'vhdl-font-lock-attribute-face)
9328 ;; highlight type/nature name in (sub)type/(sub)nature declarations
9329 (list
9330 (concat
9331 "^\\s-*\\(sub\\|\\)\\(nature\\|type\\)\\s-+\\(\\w+\\)")
9332 3 'font-lock-type-face)
9334 ;; highlight signal/variable/constant declaration names
9335 (list "\\(:[^=]\\)"
9336 '(vhdl-font-lock-match-item
9337 (progn (goto-char (match-beginning 1))
9338 (skip-syntax-backward " ")
9339 (skip-syntax-backward "w_")
9340 (skip-syntax-backward " ")
9341 (while (= (preceding-char) ?,)
9342 (backward-char 1)
9343 (skip-syntax-backward " ")
9344 (skip-syntax-backward "w_")
9345 (skip-syntax-backward " ")))
9346 ; (skip-chars-backward "^-(\n\";")
9347 (goto-char (match-end 1)) (1 font-lock-variable-name-face)))
9349 ;; highlight alias/group declaration names and for-loop/-generate variables
9350 (list "\\<\\(alias\\|for\\|group\\)\\s-+\\w+\\s-+\\(in\\|is\\)\\>"
9351 '(vhdl-font-lock-match-item
9352 (progn (goto-char (match-end 1)) (match-beginning 2))
9353 nil (1 font-lock-variable-name-face)))
9355 "For consideration as a value of `vhdl-font-lock-keywords'.
9356 This does context sensitive highlighting of names and labels.")
9358 (defvar vhdl-font-lock-keywords-3 nil
9359 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9360 "For consideration as a value of `vhdl-font-lock-keywords'.
9361 This does highlighting of words with special syntax.")
9363 (defvar vhdl-font-lock-keywords-4 nil
9364 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9365 "For consideration as a value of `vhdl-font-lock-keywords'.
9366 This does highlighting of additional reserved words.")
9368 (defconst vhdl-font-lock-keywords-5
9369 ;; background highlight translate-off regions
9370 '((vhdl-match-translate-off (0 vhdl-font-lock-translate-off-face append)))
9371 "For consideration as a value of `vhdl-font-lock-keywords'.
9372 This does background highlighting of translate-off regions.")
9374 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9375 ;; Font and color definitions
9377 (defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
9378 "Face name to use for prompts.")
9380 (defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
9381 "Face name to use for standardized attributes.")
9383 (defvar vhdl-font-lock-enumvalue-face 'vhdl-font-lock-enumvalue-face
9384 "Face name to use for standardized enumeration values.")
9386 (defvar vhdl-font-lock-function-face 'vhdl-font-lock-function-face
9387 "Face name to use for standardized functions and packages.")
9389 (defvar vhdl-font-lock-directive-face 'vhdl-font-lock-directive-face
9390 "Face name to use for directives.")
9392 (defvar vhdl-font-lock-reserved-words-face 'vhdl-font-lock-reserved-words-face
9393 "Face name to use for additional reserved words.")
9395 (defvar vhdl-font-lock-translate-off-face 'vhdl-font-lock-translate-off-face
9396 "Face name to use for translate-off regions.")
9398 ;; face names to use for words with special syntax.
9399 (let ((syntax-alist vhdl-special-syntax-alist)
9400 name)
9401 (while syntax-alist
9402 (setq name (vhdl-function-name
9403 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
9404 (eval `(defvar ,name ',name
9405 ,(concat "Face name to use for "
9406 (nth 0 (car syntax-alist)) ".")))
9407 (setq syntax-alist (cdr syntax-alist))))
9409 ;; add faces used from `font-lock'.
9410 (defgroup vhdl-highlight-faces
9411 '((font-lock-comment-face custom-face)
9412 (font-lock-string-face custom-face)
9413 (font-lock-keyword-face custom-face)
9414 (font-lock-type-face custom-face)
9415 (font-lock-function-name-face custom-face)
9416 (font-lock-variable-name-face custom-face))
9417 "Faces for highlighting."
9418 :group 'vhdl-highlight)
9420 (defface vhdl-font-lock-prompt-face
9421 '((((class color) (background light)) (:foreground "Red" :weight bold))
9422 (((class color) (background dark)) (:foreground "Pink" :weight bold))
9423 (t (:inverse-video t)))
9424 "Font lock mode face used to highlight prompts."
9425 :group 'vhdl-highlight-faces
9426 :group 'font-lock-highlighting-faces)
9428 (defface vhdl-font-lock-attribute-face
9429 '((((class color) (background light)) (:foreground "Orchid"))
9430 (((class color) (background dark)) (:foreground "LightSteelBlue"))
9431 (t (:slant italic :weight bold)))
9432 "Font lock mode face used to highlight standardized attributes."
9433 :group 'vhdl-highlight-faces
9434 :group 'font-lock-highlighting-faces)
9436 (defface vhdl-font-lock-enumvalue-face
9437 '((((class color) (background light)) (:foreground "Gold4"))
9438 (((class color) (background dark)) (:foreground "BurlyWood"))
9439 (t (:slant italic :weight bold)))
9440 "Font lock mode face used to highlight standardized enumeration values."
9441 :group 'vhdl-highlight-faces
9442 :group 'font-lock-highlighting-faces)
9444 (defface vhdl-font-lock-function-face
9445 '((((class color) (background light)) (:foreground "Orchid4"))
9446 (((class color) (background dark)) (:foreground "Orchid1"))
9447 (t (:slant italic :weight bold)))
9448 "Font lock mode face used to highlight standardized functions and packages."
9449 :group 'vhdl-highlight-faces
9450 :group 'font-lock-highlighting-faces)
9452 (defface vhdl-font-lock-directive-face
9453 '((((class color) (background light)) (:foreground "CadetBlue"))
9454 (((class color) (background dark)) (:foreground "Aquamarine"))
9455 (t (:slant italic :weight bold)))
9456 "Font lock mode face used to highlight directives."
9457 :group 'vhdl-highlight-faces
9458 :group 'font-lock-highlighting-faces)
9460 (defface vhdl-font-lock-reserved-words-face
9461 '((((class color) (background light)) (:foreground "Orange" :weight bold))
9462 (((class color) (background dark)) (:foreground "Yellow" :weight bold))
9463 (t ()))
9464 "Font lock mode face used to highlight additional reserved words."
9465 :group 'vhdl-highlight-faces
9466 :group 'font-lock-highlighting-faces)
9468 (defface vhdl-font-lock-translate-off-face
9469 '((((class color) (background light)) (:background "LightGray"))
9470 (((class color) (background dark)) (:background "DimGray"))
9471 (t ()))
9472 "Font lock mode face used to background highlight translate-off regions."
9473 :group 'vhdl-highlight-faces
9474 :group 'font-lock-highlighting-faces)
9476 ;; font lock mode faces used to highlight words with special syntax.
9477 (let ((syntax-alist vhdl-special-syntax-alist))
9478 (while syntax-alist
9479 (eval `(defface ,(vhdl-function-name
9480 "vhdl-font-lock" (car (car syntax-alist)) "face")
9481 '((((class color) (background light))
9482 (:foreground ,(nth 2 (car syntax-alist))))
9483 (((class color) (background dark))
9484 (:foreground ,(nth 3 (car syntax-alist))))
9485 (t ()))
9486 ,(concat "Font lock mode face used to highlight "
9487 (nth 0 (car syntax-alist)) ".")
9488 :group 'vhdl-highlight-faces
9489 :group 'font-lock-highlighting-faces))
9490 (setq syntax-alist (cdr syntax-alist))))
9492 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9493 ;; Font lock initialization
9495 (defun vhdl-font-lock-init ()
9496 "Initialize fontification."
9497 ;; highlight keywords and standardized types, attributes, enumeration
9498 ;; values, and subprograms
9499 (setq vhdl-font-lock-keywords-1
9500 (list
9501 (list (concat "'" vhdl-attributes-regexp)
9502 1 'vhdl-font-lock-attribute-face)
9503 (list vhdl-types-regexp 1 'font-lock-type-face)
9504 (list vhdl-functions-regexp 1 'vhdl-font-lock-function-face)
9505 (list vhdl-packages-regexp 1 'vhdl-font-lock-function-face)
9506 (list vhdl-enum-values-regexp 1 'vhdl-font-lock-enumvalue-face)
9507 (list vhdl-keywords-regexp 1 'font-lock-keyword-face)))
9508 ;; highlight words with special syntax.
9509 (setq vhdl-font-lock-keywords-3
9510 (let ((syntax-alist vhdl-special-syntax-alist)
9511 keywords)
9512 (while syntax-alist
9513 (setq keywords
9514 (cons
9515 (cons (concat "\\<\\(" (nth 1 (car syntax-alist)) "\\)\\>")
9516 (vhdl-function-name
9517 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
9518 keywords))
9519 (setq syntax-alist (cdr syntax-alist)))
9520 keywords))
9521 ;; highlight additional reserved words
9522 (setq vhdl-font-lock-keywords-4
9523 (list (list vhdl-reserved-words-regexp 1
9524 'vhdl-font-lock-reserved-words-face)))
9525 ;; highlight everything together
9526 (setq vhdl-font-lock-keywords
9527 (append
9528 vhdl-font-lock-keywords-0
9529 (when vhdl-highlight-keywords vhdl-font-lock-keywords-1)
9530 (when (or vhdl-highlight-forbidden-words
9531 vhdl-highlight-verilog-keywords) vhdl-font-lock-keywords-4)
9532 (when vhdl-highlight-special-words vhdl-font-lock-keywords-3)
9533 (when vhdl-highlight-names vhdl-font-lock-keywords-2)
9534 (when vhdl-highlight-translate-off vhdl-font-lock-keywords-5))))
9536 ;; initialize fontification for VHDL Mode
9537 (vhdl-font-lock-init)
9539 (defun vhdl-fontify-buffer ()
9540 "Re-initialize fontification and fontify buffer."
9541 (interactive)
9542 (setq font-lock-defaults
9543 (list
9544 'vhdl-font-lock-keywords nil
9545 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
9546 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
9547 (when (fboundp 'font-lock-unset-defaults)
9548 (font-lock-unset-defaults)) ; not implemented in XEmacs
9549 (font-lock-set-defaults)
9550 (font-lock-fontify-buffer))
9552 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9553 ;; Initialization for postscript printing
9555 (defun vhdl-ps-print-settings ()
9556 "Initialize custom face and page settings for postscript printing."
9557 ;; define custom face settings
9558 (unless (or (not vhdl-print-customize-faces)
9559 ps-print-color-p)
9560 (set (make-local-variable 'ps-bold-faces)
9561 '(font-lock-keyword-face
9562 font-lock-type-face
9563 vhdl-font-lock-attribute-face
9564 vhdl-font-lock-enumvalue-face
9565 vhdl-font-lock-directive-face))
9566 (set (make-local-variable 'ps-italic-faces)
9567 '(font-lock-comment-face
9568 font-lock-function-name-face
9569 font-lock-type-face
9570 vhdl-font-lock-attribute-face
9571 vhdl-font-lock-enumvalue-face
9572 vhdl-font-lock-directive-face))
9573 (set (make-local-variable 'ps-underlined-faces)
9574 '(font-lock-string-face))
9575 (setq ps-always-build-face-reference t))
9576 ;; define page settings, so that a line containing 79 characters (default)
9577 ;; fits into one column
9578 (when vhdl-print-two-column
9579 (set (make-local-variable 'ps-landscape-mode) t)
9580 (set (make-local-variable 'ps-number-of-columns) 2)
9581 (set (make-local-variable 'ps-font-size) 7.0)
9582 (set (make-local-variable 'ps-header-title-font-size) 10.0)
9583 (set (make-local-variable 'ps-header-font-size) 9.0)
9584 (set (make-local-variable 'ps-header-offset) 12.0)
9585 (when (eq ps-paper-type 'letter)
9586 (set (make-local-variable 'ps-inter-column) 40.0)
9587 (set (make-local-variable 'ps-left-margin) 40.0)
9588 (set (make-local-variable 'ps-right-margin) 40.0))))
9590 (defun vhdl-ps-print-init ()
9591 "Initialize postscript printing."
9592 (if (string-match "XEmacs" emacs-version)
9593 (vhdl-ps-print-settings)
9594 (make-local-variable 'ps-print-hook)
9595 (add-hook 'ps-print-hook 'vhdl-ps-print-settings)))
9598 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9599 ;;; Hierarchy browser (using `speedbar.el')
9600 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9601 ;; Allows displaying the hierarchy of all VHDL design units contained in a
9602 ;; directory by using the speedbar.
9604 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9605 ;; Variables
9607 (defvar vhdl-entity-alist nil
9608 "Cache with entities and corresponding architectures and configurations for
9609 each visited directory.")
9610 ;; structure: (parenthesised expression means list of such entries)
9611 ;; (directory-name
9612 ;; (ent-name ent-file ent-line
9613 ;; (arch-name arch-file arch-line
9614 ;; (inst-name inst-file inst-line inst-ent-name inst-arch-name))
9615 ;; (conf-name conf-file conf-line))
9617 (defvar vhdl-package-alist nil
9618 "Cache with packages for each visited directory.")
9619 ;; structure: (parenthesised expression means list of such entries)
9620 ;; (directory-name
9621 ;; (pack-name pack-file pack-line pack-body-file pack-body-line))
9623 (defvar vhdl-ent-inst-alist nil
9624 "Cache with instantiated entities for each visited directory.")
9625 ;; structure: (parenthesised expression means list of such entries)
9626 ;; (directory-name (inst-ent-name))
9628 (defvar vhdl-project-entity-alist nil
9629 "Cache with entities and corresponding architectures and configurations for
9630 each visited project.")
9631 ;; same structure as `vhdl-entity-alist'
9633 (defvar vhdl-project-package-alist nil
9634 "Cache with packages for each visited directory.")
9635 ;; same structure as `vhdl-package-alist'
9637 (defvar vhdl-project-ent-inst-list nil
9638 "Cache with instantiated entities for each visited directory.")
9639 ;; same structure as `vhdl-ent-inst-alist'
9641 (defvar vhdl-speedbar-shown-units-alist nil
9642 "Alist of design units simultaneously open in the current speedbar for each
9643 directory and project.")
9645 (defvar vhdl-speedbar-last-file-name nil
9646 "Last file for which design units were highlighted.")
9648 (defvar vhdl-file-alist nil
9649 "Cache with design units in each file.")
9650 ;; structure (parenthesised expression means list of such entries)
9651 ;; (file-name (ent-list) (arch-list) (conf-list) (pack-list) (inst-list))
9653 ;; help function
9654 (defsubst vhdl-speedbar-project-p ()
9655 "Return non-nil if a project is displayed, i.e. directories or files are
9656 specified."
9657 (nth 1 (aget vhdl-project-alist vhdl-project)))
9659 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9660 ;; Scan functions
9662 (defun vhdl-scan-file-contents (name &optional num-string)
9663 "Scan contents of VHDL files in FILE-LIST."
9664 (string-match "\\(.*/\\)\\(.*\\)" name)
9665 ; (unless (file-directory-p (match-string 1 name))
9666 ; (message "No such directory: \"%s\"" (match-string 1 name)))
9667 (let* ((is-directory (= (match-beginning 2) (match-end 2)))
9668 (file-list
9669 (if is-directory
9670 (nreverse (vhdl-get-source-files t name))
9671 (vhdl-directory-files (match-string 1 name) t
9672 (wildcard-to-regexp (match-string 2 name)))))
9673 (case-fold-search t)
9674 (source-buffer (current-buffer))
9675 ent-alist pack-alist ent-inst-list no-files)
9676 (when (and (not is-directory) (null file-list))
9677 (message "No such file: \"%s\"" name))
9678 (save-excursion
9679 (when file-list
9680 (setq no-files (length file-list))
9681 ;; do for all files
9682 (while file-list
9683 (message "Scanning %s %s\"%s\"... (%2d%s)"
9684 (if is-directory "directory" "files")
9685 (or num-string "") name
9686 (/ (* 100 (- no-files (length file-list))) no-files) "%")
9687 (let ((file-name (abbreviate-file-name (car file-list)))
9688 opened arch-name ent-name
9689 ent-list arch-list conf-list pack-list inst-list)
9690 ;; open file
9691 (if (find-buffer-visiting file-name)
9692 (set-buffer (find-buffer-visiting file-name))
9693 (set-buffer (find-file-noselect file-name nil t))
9694 (setq opened t))
9695 (modify-syntax-entry ?_ "w" (syntax-table))
9696 ;; scan for entities
9697 (goto-char (point-min))
9698 (while (re-search-forward "^\\s-*entity\\s-+\\(\\w+\\)" nil t)
9699 (let* ((ent-entry (aget ent-alist (match-string 1)))
9700 (arch-alist (nth 2 ent-entry))
9701 (conf-alist (nth 3 ent-entry)))
9702 (setq ent-list (cons (match-string 1) ent-list))
9703 (aput 'ent-alist (match-string 1)
9704 (list file-name (vhdl-current-line)
9705 arch-alist conf-alist nil))))
9706 ;; scan for architectures and instantiations
9707 (goto-char (point-min))
9708 (while (re-search-forward
9709 (concat
9710 "^\\s-*\\(architecture\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)\\|"
9711 "\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(entity\\s-+\\w+\\.\\)?"
9712 "\\(\\w+\\)\\(\\s-*(\\(\\w+\\))\\)?\\(\\s-\\|\n\\|--.*\n\\)*"
9713 "\\(generic\\|port\\)\\s-+map\\>\\)")
9714 nil t)
9715 (if (match-string 2)
9716 ;; architecture found
9717 (let* ((ent-entry (aget ent-alist (match-string 3)))
9718 (arch-alist (nth 2 ent-entry))
9719 (conf-alist (nth 3 ent-entry)))
9720 (setq arch-name (match-string 2))
9721 (setq ent-name (match-string 3))
9722 (setq arch-list (cons arch-name arch-list))
9723 (vhdl-aappend 'arch-alist arch-name
9724 (list file-name (vhdl-current-line) nil))
9725 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9726 arch-alist conf-alist nil))
9727 (aput 'ent-alist ent-name ent-entry))
9728 ;; instantiation found
9729 (let* ((ent-entry (aget ent-alist ent-name))
9730 (arch-alist (nth 2 ent-entry))
9731 (arch-entry (aget arch-alist arch-name))
9732 (inst-alist (nth 2 arch-entry))
9733 (inst-name (match-string 4))
9734 (inst-ent-name (match-string 7))
9735 (inst-arch-name (match-string 9))
9736 (conf-alist (nth 3 ent-entry)))
9737 (re-search-backward ":" nil t)
9738 (setq inst-list (cons inst-name inst-list))
9739 (vhdl-aappend 'inst-alist inst-name
9740 (list file-name (vhdl-current-line)
9741 inst-ent-name inst-arch-name))
9742 (setq arch-entry
9743 (list (nth 0 arch-entry) (nth 1 arch-entry)
9744 inst-alist))
9745 (vhdl-aappend 'arch-alist arch-name arch-entry)
9746 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9747 arch-alist conf-alist nil))
9748 (aput 'ent-alist ent-name ent-entry)
9749 (unless (member inst-ent-name ent-inst-list)
9750 (setq ent-inst-list
9751 (cons inst-ent-name ent-inst-list))))))
9752 ;; scan for configurations
9753 (goto-char (point-min))
9754 (while (re-search-forward
9755 "^\\s-*configuration\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)"
9756 nil t)
9757 (let* ((ent-entry (aget ent-alist (match-string 2)))
9758 (arch-alist (nth 2 ent-entry))
9759 (conf-alist (nth 3 ent-entry)))
9760 (setq conf-list (cons (match-string 1) conf-list))
9761 (vhdl-aappend 'conf-alist (match-string 1)
9762 (list file-name (vhdl-current-line)))
9763 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9764 arch-alist conf-alist nil))
9765 (aput 'ent-alist (match-string 2) ent-entry)))
9766 ;; scan for packages
9767 (goto-char (point-min))
9768 (while (re-search-forward
9769 "^\\s-*package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" nil t)
9770 (let ((pack-entry (aget pack-alist (match-string 2))))
9771 (setq pack-list (cons (match-string 2) pack-list))
9772 (aput 'pack-alist (match-string 2)
9773 (if (not (match-string 1))
9774 (list file-name (vhdl-current-line)
9775 (nth 2 pack-entry) (nth 3 pack-entry))
9776 (list (nth 0 pack-entry) (nth 1 pack-entry)
9777 file-name (vhdl-current-line))))))
9778 (setq file-list (cdr file-list))
9779 ;; add design units to variable `vhdl-file-alist'
9780 (aput 'vhdl-file-alist file-name
9781 (list ent-list arch-list conf-list pack-list inst-list))
9782 ;; close file
9783 (if opened
9784 (kill-buffer (current-buffer))
9785 (when (not vhdl-underscore-is-part-of-word)
9786 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table)))
9787 (set-buffer source-buffer)))
9788 ;; sort entities and packages
9789 (setq ent-alist
9790 (sort ent-alist
9791 (function (lambda (a b) (string-lessp (car a) (car b))))))
9792 (setq pack-alist
9793 (sort pack-alist
9794 (function (lambda (a b) (string-lessp (car a) (car b))))))
9795 ;; put directory contents into cache
9796 (when ent-alist
9797 (aput 'vhdl-entity-alist name ent-alist))
9798 (when pack-alist
9799 (aput 'vhdl-package-alist name pack-alist))
9800 (when ent-inst-list
9801 (aput 'vhdl-ent-inst-alist name (list ent-inst-list)))
9802 (message "Scanning %s %s\"%s\"...done"
9803 (if is-directory "directory" "files") (or num-string "") name)
9804 t))))
9806 (defun vhdl-scan-project-contents (project &optional rescan)
9807 "Scan the contents of all VHDL files found in the directories and files
9808 of PROJECT."
9809 (let ((dir-list-tmp (nth 1 (aget vhdl-project-alist project)))
9810 dir-list pro-ent-alist pro-pack-alist pro-ent-inst-list
9811 dir name num-dir act-dir)
9812 ;; resolve environment variables and path wildcards
9813 (setq dir-list-tmp (vhdl-resolve-paths dir-list-tmp))
9814 ;; expand directories
9815 (while dir-list-tmp
9816 (setq dir (car dir-list-tmp))
9817 ;; get subdirectories
9818 (if (string-match "-r \\(.*/\\)" dir)
9819 (setq dir-list (append dir-list (vhdl-get-subdirs
9820 (match-string 1 dir))))
9821 (setq dir-list (append dir-list (list dir))))
9822 (setq dir-list-tmp (cdr dir-list-tmp)))
9823 ;; get entities and packages of each directory in DIR-LIST
9824 (setq num-dir (length dir-list)
9825 act-dir 1)
9826 (while dir-list
9827 (setq name (abbreviate-file-name (car dir-list)))
9828 (or (and (not rescan)
9829 (or (assoc name vhdl-entity-alist)
9830 (assoc name vhdl-package-alist)))
9831 (vhdl-scan-file-contents name (format "(%s/%s) " act-dir num-dir)))
9832 ;; merge entities and corresponding architectures and configurations
9833 (let ((ent-alist (aget vhdl-entity-alist name)))
9834 (while ent-alist
9835 (let* ((ent-name (car (car ent-alist)))
9836 (ent-entry (cdr (car ent-alist)))
9837 (pro-ent-entry (aget pro-ent-alist ent-name)))
9838 (aput 'pro-ent-alist ent-name
9839 (list (or (nth 0 pro-ent-entry) (nth 0 ent-entry))
9840 (or (nth 1 pro-ent-entry) (nth 1 ent-entry))
9841 (append (nth 2 pro-ent-entry) (nth 2 ent-entry))
9842 (append (nth 3 pro-ent-entry) (nth 3 ent-entry)))))
9843 (setq ent-alist (cdr ent-alist))))
9844 ;; merge packages and corresponding package bodies
9845 (let ((pack-alist (aget vhdl-package-alist name)))
9846 (while pack-alist
9847 (let* ((pack-name (car (car pack-alist)))
9848 (pack-entry (cdr (car pack-alist)))
9849 (pro-pack-entry (aget pro-pack-alist pack-name)))
9850 (aput 'pro-pack-alist pack-name
9851 (list (or (nth 0 pro-pack-entry) (nth 0 pack-entry))
9852 (or (nth 1 pro-pack-entry) (nth 1 pack-entry))
9853 (or (nth 2 pro-pack-entry) (nth 2 pack-entry))
9854 (or (nth 3 pro-pack-entry) (nth 3 pack-entry)))))
9855 (setq pack-alist (cdr pack-alist))))
9856 ;; merge list of instantiated entities
9857 (setq pro-ent-inst-list
9858 (append pro-ent-inst-list
9859 (copy-alist
9860 (car (aget vhdl-ent-inst-alist name)))))
9861 (setq dir-list (cdr dir-list)
9862 act-dir (1+ act-dir)))
9863 ;; sort lists and put them into the caches
9864 (when pro-ent-alist
9865 (aput 'vhdl-project-entity-alist project
9866 (sort pro-ent-alist
9867 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9868 (when pro-pack-alist
9869 (aput 'vhdl-project-package-alist project
9870 (sort pro-pack-alist
9871 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9872 (when pro-ent-inst-list
9873 (aput 'vhdl-project-ent-inst-list project pro-ent-inst-list))))
9875 (defun vhdl-get-hierarchy (ent-name arch-name level indent &optional ent-hier)
9876 "Get instantiation hierarchy beginning in architecture ARCH-NAME of
9877 entity ENT-NAME."
9878 (let* ((ent-alist (if (vhdl-speedbar-project-p)
9879 (aget vhdl-project-entity-alist vhdl-project)
9880 (aget vhdl-entity-alist
9881 (abbreviate-file-name
9882 (file-name-as-directory
9883 (speedbar-line-path (1- indent)))))))
9884 (ent-entry (aget ent-alist ent-name))
9885 (arch-entry (if arch-name (aget (nth 2 ent-entry) arch-name)
9886 (cdr (car (last (nth 2 ent-entry))))))
9887 (inst-list (nth 2 arch-entry))
9888 inst-entry inst-ent-entry inst-arch-entry hier-list)
9889 (when (= level 0) (message "Extract design hierarchy..."))
9890 (when (member ent-name ent-hier)
9891 (error (format "Instantiation loop detected; component \"%s\" instantiates itself"
9892 ent-name)))
9893 (while inst-list
9894 (setq inst-entry (car inst-list))
9895 (setq inst-ent-entry (aget ent-alist (nth 3 inst-entry)))
9896 (setq inst-arch-entry
9897 (if (nth 4 inst-entry)
9898 (cons (nth 4 inst-entry)
9899 (aget (nth 2 inst-ent-entry) (nth 4 inst-entry)))
9900 (car (last (nth 2 inst-ent-entry)))))
9901 (setq hier-list
9902 (append
9903 hier-list
9904 (cons (list (nth 0 inst-entry)
9905 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9906 (nth 3 inst-entry)
9907 (cons (nth 0 inst-ent-entry) (nth 1 inst-ent-entry))
9908 (nth 0 inst-arch-entry)
9909 (cons (nth 1 inst-arch-entry) (nth 2 inst-arch-entry))
9910 level)
9911 (vhdl-get-hierarchy (nth 3 inst-entry) (nth 4 inst-entry)
9912 (1+ level) indent
9913 (cons ent-name ent-hier)))))
9914 (setq inst-list (cdr inst-list)))
9915 (when (= level 0) (message "Extract design hierarchy...done"))
9916 hier-list))
9918 (defun vhdl-get-instantiations (ent-name indent)
9919 "Get all instantiations of entity ENT-NAME."
9920 (let ((ent-alist (if (vhdl-speedbar-project-p)
9921 (aget vhdl-project-entity-alist vhdl-project)
9922 (aget vhdl-entity-alist
9923 (abbreviate-file-name
9924 (file-name-as-directory
9925 (speedbar-line-path indent))))))
9926 arch-alist inst-alist ent-inst-list
9927 ent-entry arch-entry inst-entry)
9928 (while ent-alist
9929 (setq ent-entry (car ent-alist))
9930 (setq arch-alist (nth 3 ent-entry))
9931 (while arch-alist
9932 (setq arch-entry (car arch-alist))
9933 (setq inst-alist (nth 3 arch-entry))
9934 (while inst-alist
9935 (setq inst-entry (car inst-alist))
9936 (when (equal ent-name (nth 3 inst-entry))
9937 (setq ent-inst-list
9938 (cons (list (nth 0 inst-entry)
9939 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9940 (nth 0 ent-entry)
9941 (cons (nth 1 ent-entry) (nth 2 ent-entry))
9942 (nth 0 arch-entry)
9943 (cons (nth 1 arch-entry) (nth 2 arch-entry)))
9944 ent-inst-list)))
9945 (setq inst-alist (cdr inst-alist)))
9946 (setq arch-alist (cdr arch-alist)))
9947 (setq ent-alist (cdr ent-alist)))
9948 (nreverse ent-inst-list)))
9950 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9951 ;; Add hierarchy browser functionality to speedbar.
9953 (defvar vhdl-speedbar-key-map nil
9954 "Keymap used when in the VHDL hierarchy browser mode.")
9956 (defvar vhdl-speedbar-menu-items
9957 '(["Edit Design Unit" speedbar-edit-line t]
9958 ["Expand Hierarchy" speedbar-expand-line
9959 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.\\+. "))]
9960 ["Contract Hierarchy" speedbar-contract-line
9961 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.-. "))]
9962 ["Rescan Hierarchy" vhdl-speedbar-rescan-hierarchy t]
9963 "--"
9964 ["Copy Port" vhdl-speedbar-port-copy
9965 (save-excursion
9966 (beginning-of-line) (looking-at "[0-9]+: *\\[[-+?]\\] "))])
9967 "Additional menu-items to add to speedbar frame.")
9969 (defun vhdl-speedbar-initialize ()
9970 "Initialize speedbar."
9971 ;; general settings
9972 ; (set (make-local-variable 'speedbar-tag-hierarchy-method) nil)
9973 ;; VHDL file extensions (extracted from `auto-mode-alist')
9974 (let ((mode-alist auto-mode-alist))
9975 (while mode-alist
9976 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
9977 (speedbar-add-supported-extension (car (car mode-alist))))
9978 (setq mode-alist (cdr mode-alist))))
9979 ;; hierarchy browser settings
9980 (when (boundp 'speedbar-mode-functions-list)
9981 (speedbar-add-mode-functions-list
9982 '("vhdl hierarchy"
9983 (speedbar-item-info . vhdl-speedbar-item-info)
9984 (speedbar-line-path . speedbar-files-line-path)))
9985 (unless vhdl-speedbar-key-map
9986 (setq vhdl-speedbar-key-map (speedbar-make-specialized-keymap))
9987 (define-key vhdl-speedbar-key-map "e" 'speedbar-edit-line)
9988 (define-key vhdl-speedbar-key-map "\C-m" 'speedbar-edit-line)
9989 (define-key vhdl-speedbar-key-map "+" 'speedbar-expand-line)
9990 (define-key vhdl-speedbar-key-map "-" 'speedbar-contract-line)
9991 (define-key vhdl-speedbar-key-map "s" 'vhdl-speedbar-rescan-hierarchy)
9992 (define-key vhdl-speedbar-key-map "c" 'vhdl-speedbar-port-copy))
9993 (define-key speedbar-key-map "h"
9994 (lambda () (interactive)
9995 (speedbar-change-initial-expansion-list "vhdl hierarchy")))
9996 (speedbar-add-expansion-list '("vhdl hierarchy" vhdl-speedbar-menu-items
9997 vhdl-speedbar-key-map
9998 vhdl-speedbar-display-hierarchy))
9999 (setq speedbar-stealthy-function-list
10000 (cons '("vhdl hierarchy" vhdl-speedbar-update-current-unit)
10001 speedbar-stealthy-function-list))
10002 (when vhdl-speedbar-show-hierarchy
10003 (setq speedbar-initial-expansion-list-name "vhdl hierarchy"))))
10005 (defun vhdl-speedbar (&optional arg)
10006 "Open/close speedbar."
10007 (interactive)
10008 (if (not (fboundp 'speedbar))
10009 (error "WARNING: Speedbar is only available in newer Emacs versions")
10010 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
10011 (speedbar-frame-mode arg)
10012 (error (error "WARNING: Install included `speedbar.el' patch first")))))
10014 ;; initialize speedbar for VHDL Mode
10015 (if (not (boundp 'speedbar-frame))
10016 (add-hook 'speedbar-load-hook 'vhdl-speedbar-initialize)
10017 (vhdl-speedbar-initialize)
10018 (when speedbar-frame (speedbar-refresh)))
10020 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10021 ;; Display functions
10023 ;; macros must be defined in the file they are used (copied from `speedbar.el')
10024 (defmacro speedbar-with-writable (&rest forms)
10025 "Allow the buffer to be writable and evaluate FORMS."
10026 (list 'let '((inhibit-read-only t))
10027 (cons 'progn forms)))
10028 (put 'speedbar-with-writable 'lisp-indent-function 0)
10030 (defun vhdl-speedbar-display-hierarchy (directory depth &optional rescan)
10031 "Display directory and hierarchy information in speedbar."
10032 (setq directory (abbreviate-file-name (file-name-as-directory directory)))
10033 (setq speedbar-last-selected-file nil)
10034 (speedbar-with-writable
10035 (save-excursion
10036 (if (vhdl-speedbar-project-p)
10037 (progn
10038 ;; insert project title
10039 (vhdl-speedbar-make-title-line "Project:" 0)
10040 (let ((start (point)))
10041 (insert "p:")
10042 (put-text-property start (point) 'invisible t)
10043 (setq start (point))
10044 (insert vhdl-project)
10045 (put-text-property start (point) 'face 'speedbar-directory-face))
10046 (insert-char ?\n 1)
10047 ;; scan and insert hierarchy of project
10048 (vhdl-speedbar-insert-project-hierarchy vhdl-project
10049 speedbar-power-click))
10050 ;; insert directory path
10051 (speedbar-directory-buttons directory depth)
10052 ;; insert subdirectories
10053 (vhdl-speedbar-insert-dirs (speedbar-file-lists directory) depth)
10054 ;; scan and insert hierarchy of current directory
10055 (vhdl-speedbar-insert-dir-hierarchy directory depth
10056 speedbar-power-click)
10057 ;; expand subdirectories
10058 (when (= depth 0) (vhdl-speedbar-expand-dirs directory))))))
10060 (defun vhdl-speedbar-insert-hierarchy (ent-alist pack-alist
10061 ent-inst-list depth)
10062 "Insert hierarchy of ENT-ALIST and PACK-ALIST."
10063 (if (not (or ent-alist pack-alist))
10064 (vhdl-speedbar-make-title-line "No design units!" depth)
10065 (let (ent-entry pack-entry)
10066 ;; insert entities
10067 (when ent-alist (vhdl-speedbar-make-title-line "Entities:" depth))
10068 (while ent-alist
10069 (setq ent-entry (car ent-alist))
10070 (speedbar-make-tag-line
10071 'bracket ?+ 'vhdl-speedbar-expand-entity (nth 0 ent-entry)
10072 (nth 0 ent-entry) 'vhdl-speedbar-find-file
10073 (cons (nth 1 ent-entry) (nth 2 ent-entry))
10074 'vhdl-speedbar-entity-face depth)
10075 (when (not (member (nth 0 ent-entry) ent-inst-list))
10076 (end-of-line 0) (insert " (top)") (forward-char 1))
10077 (setq ent-alist (cdr ent-alist)))
10078 ;; insert packages
10079 (when pack-alist (vhdl-speedbar-make-title-line "Packages:" depth))
10080 (while pack-alist
10081 (setq pack-entry (car pack-alist))
10082 (vhdl-speedbar-make-pack-line
10083 (nth 0 pack-entry)
10084 (cons (nth 1 pack-entry) (nth 2 pack-entry))
10085 (cons (nth 3 pack-entry) (nth 4 pack-entry))
10086 depth)
10087 (setq pack-alist (cdr pack-alist))))))
10089 (defun vhdl-speedbar-insert-project-hierarchy (project &optional rescan)
10090 "Insert hierarchy of project. Rescan directories if RESCAN is non-nil,
10091 otherwise use cached data of directories."
10092 (when (or rescan (and (not (assoc project vhdl-project-entity-alist))
10093 (not (assoc project vhdl-project-package-alist))))
10094 (vhdl-scan-project-contents project rescan))
10095 ;; insert design hierarchy in speedbar
10096 (vhdl-speedbar-insert-hierarchy
10097 (aget vhdl-project-entity-alist project)
10098 (aget vhdl-project-package-alist project)
10099 (aget vhdl-project-ent-inst-list project) 0)
10100 ;; expand design units
10101 (vhdl-speedbar-expand-units project))
10103 (defun vhdl-speedbar-insert-dir-hierarchy (directory depth &optional rescan)
10104 "Insert hierarchy of DIRECTORY. Rescan directory if RESCAN is non-nil,
10105 otherwise use cached data."
10106 (when (or rescan (and (not (assoc directory vhdl-entity-alist))
10107 (not (assoc directory vhdl-package-alist))))
10108 (vhdl-scan-file-contents directory))
10109 (vhdl-speedbar-insert-hierarchy
10110 (aget vhdl-entity-alist directory)
10111 (aget vhdl-package-alist directory)
10112 (car (aget vhdl-ent-inst-alist directory))
10113 depth)
10114 (vhdl-speedbar-expand-units directory))
10116 (defun vhdl-speedbar-rescan-hierarchy ()
10117 "Rescan hierarchy for the directory under the cursor or the current project."
10118 (interactive)
10119 (cond
10120 ;; the current project
10121 ((vhdl-speedbar-project-p)
10122 (vhdl-scan-project-contents vhdl-project t)
10123 (speedbar-refresh))
10124 ;; the top-level directory
10125 ((save-excursion (beginning-of-line) (looking-at "[^0-9]"))
10126 (re-search-forward "[0-9]+:" nil t)
10127 (vhdl-scan-file-contents (abbreviate-file-name (speedbar-line-path)))
10128 (speedbar-refresh))
10129 ;; the current directory
10130 (t (let ((path (speedbar-line-path)))
10131 (string-match "^\\(.+/\\)" path)
10132 (vhdl-scan-file-contents (abbreviate-file-name (match-string 1 path)))
10133 (speedbar-refresh)))))
10135 (defun vhdl-speedbar-expand-dirs (directory)
10136 "Expand subdirectories in DIRECTORY according to
10137 `speedbar-shown-directories'."
10138 ;; (nicked from `speedbar-default-directory-list')
10139 (let ((sf (cdr (reverse speedbar-shown-directories))))
10140 (setq speedbar-shown-directories
10141 (list (expand-file-name default-directory)))
10142 (while sf
10143 (when (speedbar-goto-this-file (car sf))
10144 (beginning-of-line)
10145 (when (looking-at "[0-9]+:\\s-*<")
10146 (goto-char (match-end 0))
10147 (let* ((position (point))
10148 (directory (abbreviate-file-name
10149 (file-name-as-directory (speedbar-line-file)))))
10150 (speedbar-do-function-pointer))))
10151 (setq sf (cdr sf)))))
10153 (defun vhdl-speedbar-expand-units (directory)
10154 "Expand design units in DIRECTORY according to
10155 `vhdl-speedbar-shown-units-alist'."
10156 (let ((ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10157 (adelete 'vhdl-speedbar-shown-units-alist directory)
10158 (while ent-alist ; expand entities
10159 (vhdl-speedbar-goto-this-unit directory (car (car ent-alist)))
10160 (beginning-of-line)
10161 (let ((arch-alist (nth 1 (car ent-alist)))
10162 position)
10163 (when (looking-at "[0-9]+:\\s-*\\[")
10164 (goto-char (match-end 0))
10165 (setq position (point))
10166 (speedbar-do-function-pointer)
10167 (while arch-alist ; expand architectures
10168 (goto-char position)
10169 (when (re-search-forward
10170 (concat "[0-9]+:\\s-*\\(\\[\\|{.}\\s-+"
10171 (car arch-alist) "\\>\\)") nil t)
10172 (beginning-of-line)
10173 (when (looking-at "[0-9]+:\\s-*{")
10174 (goto-char (match-end 0))
10175 (speedbar-do-function-pointer)))
10176 (setq arch-alist (cdr arch-alist))))
10177 (setq ent-alist (cdr ent-alist))))))
10179 (defun vhdl-speedbar-expand-entity (text token indent)
10180 "Expand/contract the entity under the cursor."
10181 (cond
10182 ((string-match "+" text) ; expand entity
10183 (let* ((ent-alist (if (vhdl-speedbar-project-p)
10184 (aget vhdl-project-entity-alist vhdl-project)
10185 (aget vhdl-entity-alist
10186 (abbreviate-file-name
10187 (file-name-as-directory
10188 (speedbar-line-path indent))))))
10189 (arch-alist (nth 2 (aget ent-alist token)))
10190 (conf-alist (nth 3 (aget ent-alist token)))
10191 (inst-alist (vhdl-get-instantiations token indent))
10192 arch-entry conf-entry inst-entry)
10193 (if (not (or arch-alist conf-alist inst-alist))
10194 (speedbar-change-expand-button-char ??)
10195 (speedbar-change-expand-button-char ?-)
10196 ;; add entity to `vhdl-speedbar-shown-units-alist'
10197 (let* ((directory (if (vhdl-speedbar-project-p)
10198 vhdl-project
10199 (abbreviate-file-name
10200 (file-name-as-directory (speedbar-line-path)))))
10201 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10202 (aput 'ent-alist (speedbar-line-text) nil)
10203 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10204 (speedbar-with-writable
10205 (save-excursion
10206 (end-of-line) (forward-char 1)
10207 ;; insert architectures
10208 (when arch-alist
10209 (vhdl-speedbar-make-title-line "Architectures:" (1+ indent)))
10210 (while arch-alist
10211 (setq arch-entry (car arch-alist))
10212 (speedbar-make-tag-line
10213 'curly ?+ 'vhdl-speedbar-expand-architecture
10214 (cons token (nth 0 arch-entry))
10215 (nth 0 arch-entry) 'vhdl-speedbar-find-file
10216 (cons (nth 1 arch-entry) (nth 2 arch-entry))
10217 'vhdl-speedbar-architecture-face (1+ indent))
10218 (setq arch-alist (cdr arch-alist)))
10219 ;; insert configurations
10220 (when conf-alist
10221 (vhdl-speedbar-make-title-line "Configurations:" (1+ indent)))
10222 (while conf-alist
10223 (setq conf-entry (car conf-alist))
10224 (speedbar-make-tag-line
10225 nil nil nil
10226 (cons token (nth 0 conf-entry))
10227 (nth 0 conf-entry) 'vhdl-speedbar-find-file
10228 (cons (nth 1 conf-entry) (nth 2 conf-entry))
10229 'vhdl-speedbar-configuration-face (1+ indent))
10230 (setq conf-alist (cdr conf-alist)))
10231 ;; insert instantiations
10232 (when inst-alist
10233 (vhdl-speedbar-make-title-line "Instantiations:" (1+ indent)))
10234 (while inst-alist
10235 (setq inst-entry (car inst-alist))
10236 (vhdl-speedbar-make-inst-line
10237 (nth 0 inst-entry) (nth 1 inst-entry)
10238 (nth 2 inst-entry) (nth 3 inst-entry)
10239 (nth 4 inst-entry) (nth 5 inst-entry) (1+ indent) 0)
10240 (setq inst-alist (cdr inst-alist)))))
10241 (setq speedbar-last-selected-file nil)
10242 (save-excursion (speedbar-stealthy-updates)))))
10243 ((string-match "-" text) ; contract entity
10244 (speedbar-change-expand-button-char ?+)
10245 ;; remove entity from `vhdl-speedbar-shown-units-alist'
10246 (let* ((directory (if (vhdl-speedbar-project-p)
10247 vhdl-project
10248 (abbreviate-file-name
10249 (file-name-as-directory (speedbar-line-path)))))
10250 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10251 (adelete 'ent-alist (speedbar-line-text))
10252 (if ent-alist
10253 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist)
10254 (adelete 'vhdl-speedbar-shown-units-alist directory)))
10255 (speedbar-delete-subblock indent))
10256 (t (error "No architectures, configurations, nor instantiations exist for this entity")))
10257 (speedbar-center-buffer-smartly))
10259 (defun vhdl-speedbar-expand-architecture (text token indent)
10260 "Expand/contract the architecture under the cursor."
10261 (cond
10262 ((string-match "+" text) ; expand architecture
10263 (let ((hier-alist (vhdl-get-hierarchy (car token) (cdr token) 0 indent)))
10264 (if (not hier-alist)
10265 (speedbar-change-expand-button-char ??)
10266 (speedbar-change-expand-button-char ?-)
10267 ;; add architecture to `vhdl-speedbar-shown-units-alist'
10268 (let* ((path (speedbar-line-path))
10269 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10270 (ent-name (match-string 2 path))
10271 (directory (if (vhdl-speedbar-project-p)
10272 vhdl-project
10273 (abbreviate-file-name (match-string 1 path))))
10274 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10275 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10276 (aput 'ent-alist ent-name
10277 (list (cons (speedbar-line-text) arch-alist)))
10278 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10279 (speedbar-with-writable
10280 (save-excursion
10281 (end-of-line) (forward-char 1)
10282 ;; insert instance hierarchy
10283 (when hier-alist
10284 (vhdl-speedbar-make-title-line "Subcomponents:" (1+ indent)))
10285 (while hier-alist
10286 (let ((entry (car hier-alist)))
10287 (vhdl-speedbar-make-inst-line
10288 (nth 0 entry) (nth 1 entry)
10289 (nth 2 entry) (nth 3 entry)
10290 (nth 4 entry) (nth 5 entry)
10291 (1+ indent) (nth 6 entry))
10292 (setq hier-alist (cdr hier-alist))))))
10293 (setq speedbar-last-selected-file nil)
10294 (save-excursion (speedbar-stealthy-updates)))))
10295 ((string-match "-" text) ; contract architecture
10296 (speedbar-change-expand-button-char ?+)
10297 ;; remove architecture from `vhdl-speedbar-shown-units-alist'
10298 (let* ((path (speedbar-line-path))
10299 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10300 (ent-name (match-string 2 path))
10301 (directory (if (vhdl-speedbar-project-p)
10302 vhdl-project
10303 (abbreviate-file-name (match-string 1 path))))
10304 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10305 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10306 (aput 'ent-alist ent-name
10307 (list (delete (speedbar-line-text) arch-alist)))
10308 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10309 (speedbar-delete-subblock indent))
10310 (t (error "No component instantiations contained in this architecture")))
10311 (speedbar-center-buffer-smartly))
10313 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10314 ;; Display help functions
10316 (defun vhdl-speedbar-update-current-unit (&optional no-position)
10317 "Highlight all design units that are contained in the current file.
10318 NO-POSITION non-nil means do not re-position cursor."
10319 (let ((last-frame (selected-frame))
10320 file-name position)
10321 ;; get current file name
10322 (select-frame speedbar-attached-frame)
10323 (setq file-name (abbreviate-file-name (or (buffer-file-name) "")))
10324 (unless (equal file-name speedbar-last-selected-file)
10325 (select-frame speedbar-frame)
10326 (set-buffer speedbar-buffer)
10327 (speedbar-with-writable
10328 (save-excursion
10329 ;; unhighlight last units
10330 (let* ((file-entry
10331 (aget vhdl-file-alist speedbar-last-selected-file)))
10332 (vhdl-speedbar-update-units
10333 "\\[.\\]" (nth 0 file-entry)
10334 speedbar-last-selected-file 'vhdl-speedbar-entity-face)
10335 (vhdl-speedbar-update-units
10336 "{.}" (nth 1 file-entry)
10337 speedbar-last-selected-file 'vhdl-speedbar-architecture-face)
10338 (vhdl-speedbar-update-units
10339 ">" (nth 2 file-entry)
10340 speedbar-last-selected-file 'vhdl-speedbar-configuration-face)
10341 (vhdl-speedbar-update-units
10342 ">" (nth 3 file-entry)
10343 speedbar-last-selected-file 'vhdl-speedbar-package-face)
10344 (vhdl-speedbar-update-units
10345 ">" (nth 4 file-entry)
10346 speedbar-last-selected-file 'vhdl-speedbar-instantiation-face))
10347 ;; highlight current units
10348 (let* ((file-entry (aget vhdl-file-alist file-name)))
10349 (vhdl-speedbar-update-units
10350 "\\[.\\]" (nth 0 file-entry)
10351 file-name 'vhdl-speedbar-entity-selected-face)
10352 (setq position (or position (point-marker)))
10353 (vhdl-speedbar-update-units
10354 "{.}" (nth 1 file-entry)
10355 file-name 'vhdl-speedbar-architecture-selected-face)
10356 (setq position (or position (point-marker)))
10357 (vhdl-speedbar-update-units
10358 ">" (nth 2 file-entry)
10359 file-name 'vhdl-speedbar-configuration-selected-face)
10360 (setq position (or position (point-marker)))
10361 (vhdl-speedbar-update-units
10362 ">" (nth 3 file-entry)
10363 file-name 'vhdl-speedbar-package-selected-face)
10364 (setq position (or position (point-marker)))
10365 (vhdl-speedbar-update-units
10366 ">" (nth 4 file-entry)
10367 file-name 'vhdl-speedbar-instantiation-selected-face))))
10368 (setq position (or position (point-marker)))
10369 ;; move speedbar so the first highlighted unit is visible
10370 (when (and position (not no-position))
10371 (goto-char position)
10372 (speedbar-center-buffer-smartly)
10373 (speedbar-position-cursor-on-line))
10374 (setq speedbar-last-selected-file file-name))
10375 (select-frame last-frame)
10378 (defun vhdl-speedbar-update-units (text unit-list file-name face)
10379 "Help function to highlight design units."
10380 (let (position)
10381 (while unit-list
10382 (goto-char (point-min))
10383 (while (re-search-forward
10384 (concat text " \\(" (car unit-list) "\\)\\>") nil t)
10385 (when (equal file-name (car (get-text-property
10386 (match-beginning 1) 'speedbar-token)))
10387 (setq position (or position (point-marker)))
10388 (put-text-property (match-beginning 1) (match-end 1) 'face face)))
10389 (setq unit-list (cdr unit-list)))
10390 (when position (goto-char position))))
10392 (defun vhdl-speedbar-make-inst-line (inst-name inst-file-marker
10393 ent-name ent-file-marker
10394 arch-name arch-file-marker
10395 depth offset)
10396 "Insert instantiation entry."
10397 (let ((start (point)))
10398 (insert (int-to-string depth) ":")
10399 (put-text-property start (point) 'invisible t)
10400 (setq start (point))
10401 (insert-char ? (+ depth (* offset vhdl-speedbar-hierarchy-indent)))
10402 (insert "> ")
10403 (put-text-property start (point) 'invisible nil)
10404 (setq start (point))
10405 (insert inst-name)
10406 (speedbar-make-button
10407 start (point) 'vhdl-speedbar-instantiation-face 'speedbar-highlight-face
10408 'vhdl-speedbar-find-file inst-file-marker)
10409 (setq start (point))
10410 (insert ": ")
10411 (put-text-property start (point) 'invisible nil)
10412 (setq start (point))
10413 (insert ent-name)
10414 (speedbar-make-button
10415 start (point) 'vhdl-speedbar-entity-face 'speedbar-highlight-face
10416 'vhdl-speedbar-find-file ent-file-marker)
10417 (setq start (point))
10418 (when arch-name
10419 (insert " (")
10420 (put-text-property start (point) 'invisible nil)
10421 (setq start (point))
10422 (insert arch-name)
10423 (speedbar-make-button
10424 start (point) 'vhdl-speedbar-architecture-face 'speedbar-highlight-face
10425 'vhdl-speedbar-find-file arch-file-marker)
10426 (setq start (point))
10427 (insert ")"))
10428 (put-text-property start (point) 'invisible nil)
10429 (insert-char ?\n 1)
10430 (put-text-property (1- (point)) (point) 'invisible nil)))
10432 (defun vhdl-speedbar-make-pack-line (pack-name pack-file-marker
10433 body-file-marker depth)
10434 "Insert package entry."
10435 (let ((start (point)))
10436 (insert (int-to-string depth) ":")
10437 (put-text-property start (point) 'invisible t)
10438 (setq start (point))
10439 (insert-char ? depth)
10440 (insert "> ")
10441 (put-text-property start (point) 'invisible nil)
10442 (setq start (point))
10443 (insert pack-name)
10444 (speedbar-make-button
10445 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10446 'vhdl-speedbar-find-file pack-file-marker)
10447 (when (car body-file-marker)
10448 (setq start (point))
10449 (insert " (")
10450 (put-text-property start (point) 'invisible nil)
10451 (setq start (point))
10452 (insert "body")
10453 (speedbar-make-button
10454 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10455 'vhdl-speedbar-find-file body-file-marker)
10456 (setq start (point))
10457 (insert ")")
10458 (put-text-property start (point) 'invisible nil))
10459 (insert-char ?\n 1)
10460 (put-text-property (1- (point)) (point) 'invisible nil)))
10462 (defun vhdl-speedbar-make-title-line (text depth)
10463 "Insert design unit title entry."
10464 (let ((start (point)))
10465 (insert (int-to-string depth) ":")
10466 (put-text-property start (point) 'invisible t)
10467 (setq start (point))
10468 (insert-char ? depth)
10469 (put-text-property start (point) 'invisible nil)
10470 (setq start (point))
10471 (insert text)
10472 (speedbar-make-button start (point) nil nil nil nil)
10473 (insert-char ?\n 1)
10474 (put-text-property start (point) 'invisible nil)))
10476 (defun vhdl-speedbar-insert-dirs (files level)
10477 "Insert subdirectories."
10478 (let ((dirs (car files)))
10479 (while dirs
10480 (speedbar-make-tag-line 'angle ?+ 'vhdl-speedbar-dired (car dirs)
10481 (car dirs) 'speedbar-dir-follow nil
10482 'speedbar-directory-face level)
10483 (setq dirs (cdr dirs)))))
10485 (defun vhdl-speedbar-dired (text token indent)
10486 "Speedbar click handler for directory expand button in hierarchy mode."
10487 (cond ((string-match "+" text) ; we have to expand this dir
10488 (setq speedbar-shown-directories
10489 (cons (expand-file-name
10490 (concat (speedbar-line-path indent) token "/"))
10491 speedbar-shown-directories))
10492 (speedbar-change-expand-button-char ?-)
10493 (speedbar-reset-scanners)
10494 (speedbar-with-writable
10495 (save-excursion
10496 (end-of-line) (forward-char 1)
10497 (vhdl-speedbar-insert-dirs
10498 (speedbar-file-lists
10499 (concat (speedbar-line-path indent) token "/"))
10500 (1+ indent))
10501 (speedbar-reset-scanners)
10502 (vhdl-speedbar-insert-dir-hierarchy
10503 (abbreviate-file-name
10504 (concat (speedbar-line-path indent) token "/"))
10505 (1+ indent) speedbar-power-click)))
10506 (setq speedbar-last-selected-file nil)
10507 (save-excursion (speedbar-stealthy-updates)))
10508 ((string-match "-" text) ; we have to contract this node
10509 (speedbar-reset-scanners)
10510 (let ((oldl speedbar-shown-directories)
10511 (newl nil)
10512 (td (expand-file-name
10513 (concat (speedbar-line-path indent) token))))
10514 (while oldl
10515 (if (not (string-match (concat "^" (regexp-quote td)) (car oldl)))
10516 (setq newl (cons (car oldl) newl)))
10517 (setq oldl (cdr oldl)))
10518 (setq speedbar-shown-directories (nreverse newl)))
10519 (speedbar-change-expand-button-char ?+)
10520 (speedbar-delete-subblock indent))
10521 (t (error "Ooops... not sure what to do")))
10522 (speedbar-center-buffer-smartly))
10524 (defun vhdl-speedbar-item-info ()
10525 "Derive and display information about this line item."
10526 (save-excursion
10527 (beginning-of-line)
10528 ;; skip invisible number info
10529 (when (looking-at "[0-9]+:") (goto-char (match-end 0)))
10530 (when (looking-at "p:")
10531 (message "Project \"%s\""
10532 (nth 0 (aget vhdl-project-alist vhdl-project))))
10533 (cond
10534 ;; directory entry
10535 ((looking-at "\\s-*<[-+?]> ") (speedbar-files-item-info))
10536 ;; design unit entry
10537 ((looking-at "\\s-*\\([[{][-+?][]}]\\|>\\) ")
10538 (goto-char (match-end 0))
10539 (let ((face (get-text-property (point) 'face)))
10540 (message
10541 "%s \"%s\" in \"%s\""
10542 ;; design unit kind
10543 (cond ((or (eq face 'vhdl-speedbar-entity-face)
10544 (eq face 'vhdl-speedbar-entity-selected-face))
10545 "Entity")
10546 ((or (eq face 'vhdl-speedbar-architecture-face)
10547 (eq face 'vhdl-speedbar-architecture-selected-face))
10548 "Architecture")
10549 ((or (eq face 'vhdl-speedbar-configuration-face)
10550 (eq face 'vhdl-speedbar-configuration-selected-face))
10551 "Configuration")
10552 ((or (eq face 'vhdl-speedbar-package-face)
10553 (eq face 'vhdl-speedbar-package-selected-face))
10554 "Package")
10555 ((or (eq face 'vhdl-speedbar-instantiation-face)
10556 (eq face 'vhdl-speedbar-instantiation-selected-face))
10557 "Instantiation")
10558 (t ""))
10559 ;; design unit name
10560 (buffer-substring-no-properties
10561 (point) (progn (looking-at"\\(\\w\\|_\\)+") (match-end 0)))
10562 ;; file name
10563 (abbreviate-file-name
10564 (or (car (get-text-property (point) 'speedbar-token)) "?"))))))))
10566 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10567 ;; Help functions
10569 (defun vhdl-get-subdirs (directory)
10570 "Recursively get subdirectories of DIRECTORY."
10571 (let ((dir-list (list (file-name-as-directory directory)))
10572 subdir-list file-list)
10573 (setq file-list (vhdl-directory-files directory t "\\w.*"))
10574 (while file-list
10575 (when (file-directory-p (car file-list))
10576 (setq dir-list (append dir-list (vhdl-get-subdirs (car file-list)))))
10577 (setq file-list (cdr file-list)))
10578 dir-list))
10580 (defun vhdl-resolve-paths (path-list)
10581 "Resolve environment variables and path wildcards in PATH-LIST."
10582 (let (path-list-1 path-list-2 path-list-3 path-beg path-end dir)
10583 ;; resolve environment variables
10584 (while path-list
10585 (setq dir (car path-list))
10586 (while (string-match "\\(.*\\)${?\\(\\(\\w\\|_\\)+\\)}?\\(.*\\)" dir)
10587 (setq dir (concat (match-string 1 dir) (getenv (match-string 2 dir))
10588 (match-string 4 dir))))
10589 (setq path-list-1 (cons dir path-list-1))
10590 (setq path-list (cdr path-list)))
10591 ;; eliminate non-existent directories
10592 (while path-list-1
10593 (setq dir (car path-list-1))
10594 (string-match "\\(-r \\)?\\(\\([^?*]*/\\)*\\)" dir)
10595 (if (file-directory-p (match-string 2 dir))
10596 (setq path-list-2 (cons dir path-list-2))
10597 (message "No such directory: \"%s\"" (match-string 2 dir)))
10598 (setq path-list-1 (cdr path-list-1)))
10599 ;; resolve path wildcards
10600 (while path-list-2
10601 (setq dir (car path-list-2))
10602 (if (string-match
10603 "\\(-r \\)?\\(\\([^?*]*/\\)*\\)\\([^/]*[?*][^/]*\\)\\(/.*\\)" dir)
10604 (progn
10605 (setq path-beg (match-string 1 dir)
10606 path-end (match-string 5 dir))
10607 (setq path-list-2
10608 (append
10609 (mapcar
10610 (function
10611 (lambda (var) (concat path-beg var path-end)))
10612 (let ((all-list (vhdl-directory-files
10613 (match-string 2 dir) t
10614 (concat "\\<" (wildcard-to-regexp
10615 (match-string 4 dir)))))
10616 dir-list)
10617 (while all-list
10618 (when (file-directory-p (car all-list))
10619 (setq dir-list (cons (car all-list) dir-list)))
10620 (setq all-list (cdr all-list)))
10621 dir-list))
10622 (cdr path-list-2))))
10623 (string-match "\\(-r \\)?\\(.*\\)/.*" dir)
10624 (when (file-directory-p (match-string 2 dir))
10625 (setq path-list-3 (cons dir path-list-3)))
10626 (setq path-list-2 (cdr path-list-2))))
10627 path-list-3))
10629 (defun vhdl-aappend (alist-symbol key value)
10630 "Append a key-value pair to an alist.
10631 Similar to `aput' but moves the key-value pair to the tail of the alist."
10632 (let ((elem (aelement key value))
10633 (alist (adelete alist-symbol key)))
10634 (set alist-symbol (append alist elem))))
10636 (defun vhdl-speedbar-goto-this-unit (directory unit)
10637 "If UNIT is displayed in DIRECTORY, goto this line and return t, else nil."
10638 (let ((dest (point)))
10639 (if (and (if (vhdl-speedbar-project-p)
10640 (progn (goto-char (point-min)) t)
10641 (speedbar-goto-this-file directory))
10642 (re-search-forward (concat "[]}] " unit "\\>") nil t))
10643 (progn (speedbar-position-cursor-on-line)
10645 (goto-char dest)
10646 nil)))
10648 (defun vhdl-speedbar-find-file (text token indent)
10649 "When user clicks on TEXT, load file with name and position in TOKEN."
10650 (if (not (car token))
10651 (error "Design unit does not exist")
10652 (speedbar-find-file-in-frame (car token))
10653 (goto-line (cdr token))
10654 (recenter)
10655 (vhdl-speedbar-update-current-unit t)
10656 (speedbar-set-timer speedbar-update-speed)
10657 (speedbar-maybee-jump-to-attached-frame)))
10659 (defun vhdl-speedbar-toggle-hierarchy ()
10660 "Toggle between hierarchy and file browsing mode."
10661 (interactive)
10662 (if (not (boundp 'speedbar-mode-functions-list))
10663 (error "WARNING: Install included `speedbar.el' patch first")
10664 (if (equal speedbar-initial-expansion-list-name "vhdl hierarchy")
10665 (speedbar-change-initial-expansion-list "files")
10666 (speedbar-change-initial-expansion-list "vhdl hierarchy"))))
10668 (defun vhdl-speedbar-port-copy ()
10669 "Copy the port of the entity under the cursor."
10670 (interactive)
10671 (beginning-of-line)
10672 (if (re-search-forward "\\([0-9]\\)+:\\s-*\\[[-+?]\\] \\(\\(\\w\\|\\s_\\)+\\)"
10673 (save-excursion (end-of-line) (point)) t)
10674 (condition-case ()
10675 (let* ((indent (string-to-number (match-string 1)))
10676 (ent-name (match-string 2))
10677 (ent-alist (if (vhdl-speedbar-project-p)
10678 (aget vhdl-project-entity-alist vhdl-project)
10679 (aget vhdl-entity-alist
10680 (abbreviate-file-name
10681 (file-name-as-directory
10682 (speedbar-line-path indent))))))
10683 (ent-entry (aget ent-alist ent-name))
10684 (file-name (nth 0 ent-entry))
10685 opened)
10686 ;; open file
10687 (if (find-buffer-visiting file-name)
10688 (set-buffer (file-name-nondirectory file-name))
10689 (set-buffer (find-file-noselect file-name nil t))
10690 (modify-syntax-entry ?\- ". 12" (syntax-table))
10691 (modify-syntax-entry ?\n ">" (syntax-table))
10692 (modify-syntax-entry ?\^M ">" (syntax-table))
10693 (setq opened t))
10694 ;; scan port
10695 (goto-line (nth 1 ent-entry))
10696 (end-of-line)
10697 (vhdl-port-copy)
10698 ;; close file
10699 (when opened (kill-buffer (current-buffer))))
10700 (error (error "Port not scanned successfully")))
10701 (error "No entity on current line")))
10703 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10704 ;; Fontification
10706 (defface vhdl-speedbar-entity-face
10707 '((((class color) (background light)) (:foreground "ForestGreen"))
10708 (((class color) (background dark)) (:foreground "PaleGreen")))
10709 "Face used for displaying entity names."
10710 :group 'speedbar-faces)
10712 (defface vhdl-speedbar-architecture-face
10713 '((((class color) (background light)) (:foreground "Blue"))
10714 (((class color) (background dark)) (:foreground "LightSkyBlue")))
10715 "Face used for displaying architecture names."
10716 :group 'speedbar-faces)
10718 (defface vhdl-speedbar-configuration-face
10719 '((((class color) (background light)) (:foreground "DarkGoldenrod"))
10720 (((class color) (background dark)) (:foreground "Salmon")))
10721 "Face used for displaying configuration names."
10722 :group 'speedbar-faces)
10724 (defface vhdl-speedbar-package-face
10725 '((((class color) (background light)) (:foreground "Grey50"))
10726 (((class color) (background dark)) (:foreground "Grey80")))
10727 "Face used for displaying package names."
10728 :group 'speedbar-faces)
10730 (defface vhdl-speedbar-instantiation-face
10731 '((((class color) (background light)) (:foreground "Brown"))
10732 (((class color) (background dark)) (:foreground "Yellow")))
10733 "Face used for displaying instantiation names."
10734 :group 'speedbar-faces)
10736 (defface vhdl-speedbar-entity-selected-face
10737 '((((class color) (background light)) (:foreground "ForestGreen" :underline t))
10738 (((class color) (background dark)) (:foreground "PaleGreen" :underline t)))
10739 "Face used for displaying entity names."
10740 :group 'speedbar-faces)
10742 (defface vhdl-speedbar-architecture-selected-face
10743 '((((class color) (background light)) (:foreground "Blue" :underline t))
10744 (((class color) (background dark)) (:foreground "LightSkyBlue" :underline t)))
10745 "Face used for displaying architecture names."
10746 :group 'speedbar-faces)
10748 (defface vhdl-speedbar-configuration-selected-face
10749 '((((class color) (background light)) (:foreground "DarkGoldenrod" :underline t))
10750 (((class color) (background dark)) (:foreground "Salmon" :underline t)))
10751 "Face used for displaying configuration names."
10752 :group 'speedbar-faces)
10754 (defface vhdl-speedbar-package-selected-face
10755 '((((class color) (background light)) (:foreground "Grey50" :underline t))
10756 (((class color) (background dark)) (:foreground "Grey80" :underline t)))
10757 "Face used for displaying package names."
10758 :group 'speedbar-faces)
10760 (defface vhdl-speedbar-instantiation-selected-face
10761 '((((class color) (background light)) (:foreground "Brown" :underline t))
10762 (((class color) (background dark)) (:foreground "Yellow" :underline t)))
10763 "Face used for displaying instantiation names."
10764 :group 'speedbar-faces)
10767 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10768 ;;; Bug reports
10769 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10770 ;; (using `reporter.el')
10772 (defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
10773 "Address for VHDL Mode bug reports.")
10775 (defun vhdl-version ()
10776 "Echo the current version of VHDL Mode in the minibuffer."
10777 (interactive)
10778 (message "Using VHDL Mode version %s" vhdl-version)
10779 (vhdl-keep-region-active))
10781 ;; get reporter-submit-bug-report when byte-compiling
10782 (eval-when-compile
10783 (require 'reporter))
10785 (defun vhdl-submit-bug-report ()
10786 "Submit via mail a bug report on VHDL Mode."
10787 (interactive)
10788 ;; load in reporter
10789 (and
10790 (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
10791 (require 'reporter)
10792 (reporter-submit-bug-report
10793 vhdl-mode-help-address
10794 (concat "VHDL Mode " vhdl-version)
10795 (list
10796 ;; report all important variables
10797 'vhdl-offsets-alist
10798 'vhdl-comment-only-line-offset
10799 'tab-width
10800 'vhdl-electric-mode
10801 'vhdl-stutter-mode
10802 'vhdl-indent-tabs-mode
10803 'vhdl-project-alist
10804 'vhdl-project
10805 'vhdl-compiler-alist
10806 'vhdl-compiler
10807 'vhdl-compiler-options
10808 'vhdl-standard
10809 'vhdl-basic-offset
10810 'vhdl-upper-case-keywords
10811 'vhdl-upper-case-types
10812 'vhdl-upper-case-attributes
10813 'vhdl-upper-case-enum-values
10814 'vhdl-upper-case-constants
10815 'vhdl-electric-keywords
10816 'vhdl-optional-labels
10817 'vhdl-insert-empty-lines
10818 'vhdl-argument-list-indent
10819 'vhdl-association-list-with-formals
10820 'vhdl-conditions-in-parenthesis
10821 'vhdl-zero-string
10822 'vhdl-one-string
10823 'vhdl-file-header
10824 'vhdl-file-footer
10825 'vhdl-company-name
10826 'vhdl-platform-spec
10827 'vhdl-date-format
10828 'vhdl-modify-date-prefix-string
10829 'vhdl-modify-date-on-saving
10830 'vhdl-reset-kind
10831 'vhdl-reset-active-high
10832 'vhdl-clock-rising-edge
10833 'vhdl-clock-edge-condition
10834 'vhdl-clock-name
10835 'vhdl-reset-name
10836 'vhdl-model-alist
10837 'vhdl-include-port-comments
10838 'vhdl-include-direction-comments
10839 'vhdl-actual-port-name
10840 'vhdl-instance-name
10841 'vhdl-testbench-entity-name
10842 'vhdl-testbench-architecture-name
10843 'vhdl-testbench-dut-name
10844 'vhdl-testbench-entity-header
10845 'vhdl-testbench-architecture-header
10846 'vhdl-testbench-declarations
10847 'vhdl-testbench-statements
10848 'vhdl-testbench-initialize-signals
10849 'vhdl-testbench-create-files
10850 'vhdl-self-insert-comments
10851 'vhdl-prompt-for-comments
10852 'vhdl-inline-comment-column
10853 'vhdl-end-comment-column
10854 'vhdl-auto-align
10855 'vhdl-align-groups
10856 'vhdl-highlight-keywords
10857 'vhdl-highlight-names
10858 'vhdl-highlight-special-words
10859 'vhdl-highlight-forbidden-words
10860 'vhdl-highlight-verilog-keywords
10861 'vhdl-highlight-translate-off
10862 'vhdl-highlight-case-sensitive
10863 'vhdl-special-syntax-alist
10864 'vhdl-forbidden-words
10865 'vhdl-forbidden-syntax
10866 'vhdl-speedbar
10867 'vhdl-speedbar-show-hierarchy
10868 'vhdl-speedbar-hierarchy-indent
10869 'vhdl-index-menu
10870 'vhdl-source-file-menu
10871 'vhdl-hideshow-menu
10872 'vhdl-hide-all-init
10873 'vhdl-print-two-column
10874 'vhdl-print-customize-faces
10875 'vhdl-intelligent-tab
10876 'vhdl-word-completion-case-sensitive
10877 'vhdl-word-completion-in-minibuffer
10878 'vhdl-underscore-is-part-of-word
10879 'vhdl-mode-hook
10880 'vhdl-startup-warnings)
10881 (function
10882 (lambda ()
10883 (insert
10884 (if vhdl-special-indent-hook
10885 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
10886 "vhdl-special-indent-hook is set to '"
10887 (format "%s" vhdl-special-indent-hook)
10888 ".\nPerhaps this is your problem?\n"
10889 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
10890 "\n"))))
10892 "Dear VHDL Mode maintainers,")))
10895 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10897 (provide 'vhdl-mode)
10899 ;;; vhdl-mode.el ends here