Doc fixes.
[bpt/emacs.git] / lisp / progmodes / vhdl-mode.el
1 ;;; vhdl-mode.el --- major mode for editing VHDL code
2
3 ;; Copyright (C) 1992,93,94,95,96,97,98,99 Free Software Foundation, Inc.
4
5 ;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch>
6 ;; <http://www.iis.ee.ethz.ch/~zimmi/>
7 ;; Rodney J. Whitby <mailto:rwhitby@geocities.com>
8 ;; <http://www.geocities.com/SiliconValley/Park/8287/>
9 ;; Maintainer: VHDL Mode Maintainers <vhdl-mode@geocities.com>
10 ;; <http://www.geocities.com/SiliconValley/Peaks/8287/>
11 ;; Version: 3.29
12 ;; Keywords: languages vhdl
13
14 ;; This file is part of GNU Emacs.
15
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.
20
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.
25
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.
30
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;; Commentary:
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
35 ;; This package provides an Emacs major mode for editing VHDL code.
36 ;; It includes the following features:
37
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)
57
58 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
59 ;; Usage
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61
62 ;; see below (comment in `vhdl-mode' function) or type `C-c C-h' in Emacs.
63
64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65 ;; Emacs Versions
66 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67
68 ;; supported: Emacs 20.X (Unix and Windows NT/95), XEmacs 20.X
69 ;; tested on: Emacs 20.3, XEmacs 20.4 (marginally)
70
71 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72 ;; Acknowledgements
73 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
74
75 ;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
76 ;; and Steve Grout.
77
78 ;; Fontification approach suggested by Ken Wood <ken@eda.com.au>.
79 ;; Ideas about alignment from John Wiegley <johnw@borland.com>.
80
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.
85
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.
91
92
93 ;;; Code:
94
95 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 ;;; Variables
97 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
98
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))))
108
109 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 ;; User variables
111
112 (defgroup vhdl nil
113 "Customizations for VHDL Mode."
114 :prefix "vhdl-"
115 :group 'languages
116 :version "20.4" ; comment out for XEmacs
117 )
118
119 (defgroup vhdl-mode nil
120 "Customizations for modes."
121 :group 'vhdl)
122
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)
130
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)
137
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)
143
144
145 (defgroup vhdl-project nil
146 "Customizations for projects."
147 :group 'vhdl)
148
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.
155 ")
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)
167
168 Project name and description are used to insert into the file header (see
169 variable `vhdl-file-header').
170
171 Path and file name can contain wildcards `*' and `?'. Environment variables
172 \(e.g. \"$EXAMPLE2\") are resolved.
173
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.
177
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)
190
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)
205
206
207 (defgroup vhdl-compile nil
208 "Customizations for compilation."
209 :group 'vhdl)
210
211 (defcustom vhdl-compiler-alist
212 '(
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))
249 )
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
265
266 See also variable `vhdl-compiler-options' to add options to the compile
267 command.
268
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.
272
273 A compiler is selected for syntax analysis (`\\[vhdl-compile]') by
274 assigning its name to variable `vhdl-compiler'.
275
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)
294
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)
305
306 (defcustom vhdl-compiler-options ""
307 "*Options to be added to the compile command."
308 :type 'string
309 :group 'vhdl-compile)
310
311
312 (defgroup vhdl-style nil
313 "Customizations for code styles."
314 :group 'vhdl)
315
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')
324
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)
342
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)
348
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)
356
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)
364
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)
372
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)
380
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)
388
389
390 (defgroup vhdl-electric nil
391 "Customizations for electrification."
392 :group 'vhdl)
393
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)
403
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)
414
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
421
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)
427
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)
435
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)
442
443 (defcustom vhdl-conditions-in-parenthesis nil
444 "*Non-nil means place parenthesis around condition expressions."
445 :type 'boolean
446 :group 'vhdl-electric)
447
448 (defcustom vhdl-zero-string "'0'"
449 "*String to use for a logic zero."
450 :type 'string
451 :group 'vhdl-electric)
452
453 (defcustom vhdl-one-string "'1'"
454 "*String to use for a logic one."
455 :type 'string
456 :group 'vhdl-electric)
457
458
459 (defgroup vhdl-header nil
460 "Customizations for file header."
461 :group 'vhdl-electric)
462
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 -------------------------------------------------------------------------------
480
481 "
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.
488
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
501
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)
506
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)
515
516 (defcustom vhdl-company-name ""
517 "*Name of company to insert in file header."
518 :type 'string
519 :group 'vhdl-header)
520
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)
527
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)
535
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)
543
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]').
547
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)
552
553
554 (defgroup vhdl-sequential-process nil
555 "Customizations for sequential processes."
556 :group 'vhdl-electric)
557
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)
564
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)
570
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)
576
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)
584
585 (defcustom vhdl-clock-name ""
586 "*Name of clock signal to use in templates."
587 :type 'string
588 :group 'vhdl-sequential-process)
589
590 (defcustom vhdl-reset-name ""
591 "*Name of reset signal to use in templates."
592 :type 'string
593 :group 'vhdl-sequential-process)
594
595
596 (defgroup vhdl-model nil
597 "Customizations for user models."
598 :group 'vhdl)
599
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
608
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
623
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
630
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.
635
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)
651
652 (defgroup vhdl-port nil
653 "Customizations for port transformation functions."
654 :group 'vhdl)
655
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)
660
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)
665
666 (defconst vhdl-name-doc-string "
667
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")
679
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)
689
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)
700
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)
710
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)
721
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)
732
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)
741
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)
751
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)
760
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)
769
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)
774
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)
786
787
788 (defgroup vhdl-comment nil
789 "Customizations for comments."
790 :group 'vhdl)
791
792 (defcustom vhdl-self-insert-comments t
793 "*Non-nil means various templates automatically insert help comments."
794 :type 'boolean
795 :group 'vhdl-comment)
796
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)
801
802 (defcustom vhdl-inline-comment-column 40
803 "*Column to indent inline comments to.
804 Overrides local variable `comment-column'.
805
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)
810
811 (defcustom vhdl-end-comment-column 79
812 "*End of comment column.
813 Comments that exceed this column number are wrapped.
814
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)
819
820 (defvar end-comment-column)
821
822
823 (defgroup vhdl-align nil
824 "Customizations for alignment."
825 :group 'vhdl)
826
827 (defcustom vhdl-auto-align t
828 "*Non-nil means align some templates automatically after generation."
829 :type 'boolean
830 :group 'vhdl-align)
831
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)
837
838
839 (defgroup vhdl-highlight nil
840 "Customizations for highlighting."
841 :group 'vhdl)
842
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
851
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)
858
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
868
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)
875
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.
881
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)
888
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.
895
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)
903
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.
908
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)
916
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).
923
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)
930
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'.
939
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)
944
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.
949
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)
959
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\".
966
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)
978
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.
983
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)
991
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).
998
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)
1006
1007
1008 (defgroup vhdl-menu nil
1009 "Customizations for speedbar and menues."
1010 :group 'vhdl)
1011
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)
1017
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)
1023
1024 (defcustom vhdl-speedbar-hierarchy-indent 1
1025 "*Amount of indentation in hierarchy display of subcomponent."
1026 :type 'integer
1027 :group 'vhdl-menu)
1028
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)
1036
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)
1042
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.
1047
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)
1052
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)
1057
1058
1059 (defgroup vhdl-print nil
1060 "Customizations for printing."
1061 :group 'vhdl)
1062
1063 (defcustom vhdl-print-two-column t
1064 "*Non-nil means print code in two columns and landscape format.
1065
1066 NOTE: Activate the new setting by restarting Emacs.
1067 Overrides `ps-print' settings locally."
1068 :type 'boolean
1069 :group 'vhdl-print)
1070
1071 (defcustom vhdl-print-customize-faces t
1072 "*Non-nil means use an optimized set of faces for postscript printing.
1073
1074 NOTE: Activate the new setting by restarting Emacs.
1075 Overrides `ps-print' settings locally."
1076 :type 'boolean
1077 :group 'vhdl-print)
1078
1079
1080 (defgroup vhdl-misc nil
1081 "Miscellaneous customizations."
1082 :group 'vhdl)
1083
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').
1092
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)
1097
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)
1104
1105 (defcustom vhdl-word-completion-in-minibuffer t
1106 "*Non-nil enables word completion in minibuffer (for template prompts).
1107
1108 NOTE: Activate the new setting by restarting Emacs."
1109 :type 'boolean
1110 :group 'vhdl-misc)
1111
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.
1117
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)
1124
1125
1126 (defgroup vhdl-related nil
1127 "Related general customizations."
1128 :group 'vhdl)
1129
1130 ;; add related general customizations
1131 (custom-add-to-group 'vhdl-related 'line-number-mode 'custom-variable)
1132 (if (string-match "XEmacs" emacs-version)
1133 (custom-add-to-group 'vhdl-related 'paren-mode 'custom-variable)
1134 (custom-add-to-group 'vhdl-related 'paren-showing 'custom-group))
1135 (unless (string-match "XEmacs" emacs-version)
1136 (custom-add-to-group 'vhdl-related 'transient-mark-mode 'custom-variable))
1137 (custom-add-to-group 'vhdl-related 'ps-print 'custom-group)
1138 (custom-add-to-group 'vhdl-related 'mail-host-address 'custom-variable)
1139 (custom-add-to-group 'vhdl-related 'user-mail-address 'custom-variable)
1140
1141 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1142 ;; Internal variables
1143
1144 (defconst vhdl-version "3.29"
1145 "VHDL Mode version number.")
1146
1147 (defvar vhdl-progress-interval 1
1148 "*Interval used to update progress status during long operations.
1149 If a number, percentage complete gets updated after each interval of
1150 that many seconds. To inhibit all messages, set this variable to nil.")
1151
1152 (defvar vhdl-inhibit-startup-warnings-p nil
1153 "*If non-nil, inhibits start up compatibility warnings.")
1154
1155 (defvar vhdl-strict-syntax-p nil
1156 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
1157 If the syntactic symbol for a particular line does not match a symbol
1158 in the offsets alist, an error is generated, otherwise no error is
1159 reported and the syntactic symbol is ignored.")
1160
1161 (defvar vhdl-echo-syntactic-information-p nil
1162 "*If non-nil, syntactic info is echoed when the line is indented.")
1163
1164 (defconst vhdl-offsets-alist-default
1165 '((string . -1000)
1166 (block-open . 0)
1167 (block-close . 0)
1168 (statement . 0)
1169 (statement-cont . vhdl-lineup-statement-cont)
1170 (statement-block-intro . +)
1171 (statement-case-intro . +)
1172 (case-alternative . +)
1173 (comment . vhdl-lineup-comment)
1174 (arglist-intro . +)
1175 (arglist-cont . 0)
1176 (arglist-cont-nonempty . vhdl-lineup-arglist)
1177 (arglist-close . vhdl-lineup-arglist)
1178 (entity . 0)
1179 (configuration . 0)
1180 (package . 0)
1181 (architecture . 0)
1182 (package-body . 0)
1183 )
1184 "Default settings for offsets of syntactic elements.
1185 Do not change this constant! See the variable `vhdl-offsets-alist' for
1186 more information.")
1187
1188 (defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
1189 "*Association list of syntactic element symbols and indentation offsets.
1190 As described below, each cons cell in this list has the form:
1191
1192 (SYNTACTIC-SYMBOL . OFFSET)
1193
1194 When a line is indented, `vhdl-mode' first determines the syntactic
1195 context of the line by generating a list of symbols called syntactic
1196 elements. This list can contain more than one syntactic element and
1197 the global variable `vhdl-syntactic-context' contains the context list
1198 for the line being indented. Each element in this list is actually a
1199 cons cell of the syntactic symbol and a buffer position. This buffer
1200 position is call the relative indent point for the line. Some
1201 syntactic symbols may not have a relative indent point associated with
1202 them.
1203
1204 After the syntactic context list for a line is generated, `vhdl-mode'
1205 calculates the absolute indentation for the line by looking at each
1206 syntactic element in the list. First, it compares the syntactic
1207 element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
1208 finds a match, it adds the OFFSET to the column of the relative indent
1209 point. The sum of this calculation for each element in the syntactic
1210 list is the absolute offset for line being indented.
1211
1212 If the syntactic element does not match any in the `vhdl-offsets-alist',
1213 an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
1214 the element is ignored.
1215
1216 Actually, OFFSET can be an integer, a function, a variable, or one of
1217 the following symbols: `+', `-', `++', or `--'. These latter
1218 designate positive or negative multiples of `vhdl-basic-offset',
1219 respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
1220 called with a single argument containing the cons of the syntactic
1221 element symbol and the relative indent point. The function should
1222 return an integer offset.
1223
1224 Here is the current list of valid syntactic element symbols:
1225
1226 string -- inside multi-line string
1227 block-open -- statement block open
1228 block-close -- statement block close
1229 statement -- a VHDL statement
1230 statement-cont -- a continuation of a VHDL statement
1231 statement-block-intro -- the first line in a new statement block
1232 statement-case-intro -- the first line in a case alternative block
1233 case-alternative -- a case statement alternative clause
1234 comment -- a line containing only a comment
1235 arglist-intro -- the first line in an argument list
1236 arglist-cont -- subsequent argument list lines when no
1237 arguments follow on the same line as the
1238 the arglist opening paren
1239 arglist-cont-nonempty -- subsequent argument list lines when at
1240 least one argument follows on the same
1241 line as the arglist opening paren
1242 arglist-close -- the solo close paren of an argument list
1243 entity -- inside an entity declaration
1244 configuration -- inside a configuration declaration
1245 package -- inside a package declaration
1246 architecture -- inside an architecture body
1247 package-body -- inside a package body")
1248
1249 (defvar vhdl-comment-only-line-offset 0
1250 "*Extra offset for line which contains only the start of a comment.
1251 Can contain an integer or a cons cell of the form:
1252
1253 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
1254
1255 Where NON-ANCHORED-OFFSET is the amount of offset given to
1256 non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
1257 the amount of offset to give column-zero anchored comment-only lines.
1258 Just an integer as value is equivalent to (<val> . 0)")
1259
1260 (defvar vhdl-special-indent-hook nil
1261 "*Hook for user defined special indentation adjustments.
1262 This hook gets called after a line is indented by the mode.")
1263
1264 (defvar vhdl-style-alist
1265 '(("IEEE"
1266 (vhdl-basic-offset . 4)
1267 (vhdl-offsets-alist . ())
1268 )
1269 )
1270 "Styles of Indentation.
1271 Elements of this alist are of the form:
1272
1273 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
1274
1275 where STYLE-STRING is a short descriptive string used to select a
1276 style, VARIABLE is any `vhdl-mode' variable, and VALUE is the intended
1277 value for that variable when using the selected style.
1278
1279 There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
1280 case, the VALUE is a list containing elements of the form:
1281
1282 (SYNTACTIC-SYMBOL . VALUE)
1283
1284 as described in `vhdl-offsets-alist'. These are passed directly to
1285 `vhdl-set-offset' so there is no need to set every syntactic symbol in
1286 your style, only those that are different from the default.")
1287
1288 ;; dynamically append the default value of most variables
1289 (or (assoc "Default" vhdl-style-alist)
1290 (let* ((varlist '(vhdl-inhibit-startup-warnings-p
1291 vhdl-strict-syntax-p
1292 vhdl-echo-syntactic-information-p
1293 vhdl-basic-offset
1294 vhdl-offsets-alist
1295 vhdl-comment-only-line-offset))
1296 (default (cons "Default"
1297 (mapcar
1298 (function
1299 (lambda (var)
1300 (cons var (symbol-value var))))
1301 varlist))))
1302 (setq vhdl-style-alist (cons default vhdl-style-alist))))
1303
1304 (defvar vhdl-mode-hook nil
1305 "*Hook called by `vhdl-mode'.")
1306
1307
1308 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1309 ;; Compatibility
1310
1311 (defvar vhdl-startup-warnings nil
1312 "Warnings to tell the user during start up.")
1313
1314 (defun vhdl-print-warnings ()
1315 "Print out messages in variable `vhdl-startup-warnings'."
1316 (let ((warnings vhdl-startup-warnings))
1317 (while warnings
1318 (message (concat "WARNING: " (car warnings)))
1319 (setq warnings (cdr warnings))))
1320 (when (> (length vhdl-startup-warnings) 1)
1321 (message "WARNING: See warning messages in *Messages* buffer.")))
1322
1323 (defun vhdl-add-warning (string)
1324 "Add STRING to warning list `vhdl-startup-warnings'."
1325 (setq vhdl-startup-warnings (cons string vhdl-startup-warnings)))
1326
1327 ;; Perform compatibility checks.
1328 (when (not (stringp vhdl-compiler)) ; changed format of `vhdl-compiler'
1329 (setq vhdl-compiler "ModelSim")
1330 (vhdl-add-warning "Variable `vhdl-compiler' has changed format; customize again"))
1331 (when (not (listp vhdl-standard)) ; changed format of `vhdl-standard'
1332 (setq vhdl-standard '(87 nil))
1333 (vhdl-add-warning "Variable `vhdl-standard' has changed format; customize again"))
1334 (when (= (length (car vhdl-model-alist)) 3)
1335 (let ((old-alist vhdl-model-alist) ; changed format of `vhdl-model-alist'
1336 new-alist)
1337 (while old-alist
1338 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1339 (setq old-alist (cdr old-alist)))
1340 (setq vhdl-model-alist (nreverse new-alist))))
1341 (when (= (length (car vhdl-project-alist)) 3)
1342 (let ((old-alist vhdl-project-alist) ; changed format of `vhdl-project-alist'
1343 new-alist)
1344 (while old-alist
1345 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1346 (setq old-alist (cdr old-alist)))
1347 (setq vhdl-project-alist (nreverse new-alist))))
1348
1349 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1350 ;; Help functions
1351
1352 (defsubst vhdl-standard-p (standard)
1353 "Check if STANDARD is specified as used standard."
1354 (or (eq standard (car vhdl-standard))
1355 (memq standard (cadr vhdl-standard))))
1356
1357 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1358 ;; Required packages
1359
1360 (require 'assoc)
1361
1362
1363 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1364 ;;; Emacs variant handling
1365 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1366
1367 ;; active regions
1368
1369 (defun vhdl-keep-region-active ()
1370 "Do whatever is necessary to keep the region active in XEmacs.
1371 Ignore byte-compiler warnings you might see."
1372 (and (boundp 'zmacs-region-stays)
1373 (setq zmacs-region-stays t)))
1374
1375 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1376 ;; XEmacs hacks
1377
1378 (unless (fboundp 'wildcard-to-regexp)
1379 (defun wildcard-to-regexp (wildcard)
1380 "Simplified version of `wildcard-to-regexp' from Emacs' `files.el'."
1381 (let* ((i (string-match "[*?]" wildcard))
1382 (result (substring wildcard 0 i))
1383 (len (length wildcard)))
1384 (when i
1385 (while (< i len)
1386 (let ((ch (aref wildcard i)))
1387 (setq result (concat result
1388 (cond ((eq ch ?*) "[^\000]*")
1389 ((eq ch ??) "[^\000]")
1390 (t (char-to-string ch)))))
1391 (setq i (1+ i)))))
1392 (concat "\\`" result "\\'"))))
1393
1394
1395 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1396 ;;; Bindings
1397 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1398
1399 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1400 ;; Key bindings
1401
1402 (defvar vhdl-template-map ()
1403 "Keymap for VHDL templates.")
1404
1405 (defun vhdl-template-map-init ()
1406 "Initialize `vhdl-template-map'."
1407 (setq vhdl-template-map (make-sparse-keymap))
1408 ;; key bindings for VHDL templates
1409 (define-key vhdl-template-map "al" 'vhdl-template-alias)
1410 (define-key vhdl-template-map "ar" 'vhdl-template-architecture)
1411 (define-key vhdl-template-map "at" 'vhdl-template-assert)
1412 (define-key vhdl-template-map "ad" 'vhdl-template-attribute-decl)
1413 (define-key vhdl-template-map "as" 'vhdl-template-attribute-spec)
1414 (define-key vhdl-template-map "bl" 'vhdl-template-block)
1415 (define-key vhdl-template-map "ca" 'vhdl-template-case-is)
1416 (define-key vhdl-template-map "cd" 'vhdl-template-component-decl)
1417 (define-key vhdl-template-map "ci" 'vhdl-template-component-inst)
1418 (define-key vhdl-template-map "cs" 'vhdl-template-conditional-signal-asst)
1419 (define-key vhdl-template-map "Cb" 'vhdl-template-block-configuration)
1420 (define-key vhdl-template-map "Cc" 'vhdl-template-component-conf)
1421 (define-key vhdl-template-map "Cd" 'vhdl-template-configuration-decl)
1422 (define-key vhdl-template-map "Cs" 'vhdl-template-configuration-spec)
1423 (define-key vhdl-template-map "co" 'vhdl-template-constant)
1424 (define-key vhdl-template-map "di" 'vhdl-template-disconnect)
1425 (define-key vhdl-template-map "el" 'vhdl-template-else)
1426 (define-key vhdl-template-map "ei" 'vhdl-template-elsif)
1427 (define-key vhdl-template-map "en" 'vhdl-template-entity)
1428 (define-key vhdl-template-map "ex" 'vhdl-template-exit)
1429 (define-key vhdl-template-map "fi" 'vhdl-template-file)
1430 (define-key vhdl-template-map "fg" 'vhdl-template-for-generate)
1431 (define-key vhdl-template-map "fl" 'vhdl-template-for-loop)
1432 (define-key vhdl-template-map "\C-f" 'vhdl-template-footer)
1433 (define-key vhdl-template-map "fb" 'vhdl-template-function-body)
1434 (define-key vhdl-template-map "fd" 'vhdl-template-function-decl)
1435 (define-key vhdl-template-map "ge" 'vhdl-template-generic)
1436 (define-key vhdl-template-map "gd" 'vhdl-template-group-decl)
1437 (define-key vhdl-template-map "gt" 'vhdl-template-group-template)
1438 (define-key vhdl-template-map "\C-h" 'vhdl-template-header)
1439 (define-key vhdl-template-map "ig" 'vhdl-template-if-generate)
1440 (define-key vhdl-template-map "it" 'vhdl-template-if-then)
1441 (define-key vhdl-template-map "li" 'vhdl-template-library)
1442 (define-key vhdl-template-map "lo" 'vhdl-template-bare-loop)
1443 (define-key vhdl-template-map "\C-m" 'vhdl-template-modify)
1444 (define-key vhdl-template-map "\C-t" 'vhdl-template-insert-date)
1445 (define-key vhdl-template-map "ma" 'vhdl-template-map)
1446 (define-key vhdl-template-map "ne" 'vhdl-template-next)
1447 (define-key vhdl-template-map "ot" 'vhdl-template-others)
1448 (define-key vhdl-template-map "Pd" 'vhdl-template-package-decl)
1449 (define-key vhdl-template-map "Pb" 'vhdl-template-package-body)
1450 (define-key vhdl-template-map "(" 'vhdl-template-paired-parens)
1451 (define-key vhdl-template-map "po" 'vhdl-template-port)
1452 (define-key vhdl-template-map "pb" 'vhdl-template-procedure-body)
1453 (define-key vhdl-template-map "pd" 'vhdl-template-procedure-decl)
1454 (define-key vhdl-template-map "pc" 'vhdl-template-process-comb)
1455 (define-key vhdl-template-map "ps" 'vhdl-template-process-seq)
1456 (define-key vhdl-template-map "rp" 'vhdl-template-report)
1457 (define-key vhdl-template-map "rt" 'vhdl-template-return)
1458 (define-key vhdl-template-map "ss" 'vhdl-template-selected-signal-asst)
1459 (define-key vhdl-template-map "si" 'vhdl-template-signal)
1460 (define-key vhdl-template-map "su" 'vhdl-template-subtype)
1461 (define-key vhdl-template-map "ty" 'vhdl-template-type)
1462 (define-key vhdl-template-map "us" 'vhdl-template-use)
1463 (define-key vhdl-template-map "va" 'vhdl-template-variable)
1464 (define-key vhdl-template-map "wa" 'vhdl-template-wait)
1465 (define-key vhdl-template-map "wl" 'vhdl-template-while-loop)
1466 (define-key vhdl-template-map "wi" 'vhdl-template-with)
1467 (define-key vhdl-template-map "wc" 'vhdl-template-clocked-wait)
1468 (define-key vhdl-template-map "\C-pb" 'vhdl-template-package-numeric-bit)
1469 (define-key vhdl-template-map "\C-pn" 'vhdl-template-package-numeric-std)
1470 (define-key vhdl-template-map "\C-ps" 'vhdl-template-package-std-logic-1164)
1471 (define-key vhdl-template-map "\C-pA" 'vhdl-template-package-std-logic-arith)
1472 (define-key vhdl-template-map "\C-pM" 'vhdl-template-package-std-logic-misc)
1473 (define-key vhdl-template-map "\C-pS" 'vhdl-template-package-std-logic-signed)
1474 (define-key vhdl-template-map "\C-pT" 'vhdl-template-package-std-logic-textio)
1475 (define-key vhdl-template-map "\C-pU" 'vhdl-template-package-std-logic-unsigned)
1476 (define-key vhdl-template-map "\C-pt" 'vhdl-template-package-textio)
1477 (define-key vhdl-template-map "\C-dn" 'vhdl-template-directive-translate-on)
1478 (define-key vhdl-template-map "\C-df" 'vhdl-template-directive-translate-off)
1479 (define-key vhdl-template-map "\C-dN" 'vhdl-template-directive-synthesis-on)
1480 (define-key vhdl-template-map "\C-dF" 'vhdl-template-directive-synthesis-off)
1481 (define-key vhdl-template-map "\C-q" 'vhdl-template-search-prompt)
1482 (when (vhdl-standard-p 'ams)
1483 (define-key vhdl-template-map "br" 'vhdl-template-break)
1484 (define-key vhdl-template-map "cu" 'vhdl-template-case-use)
1485 (define-key vhdl-template-map "iu" 'vhdl-template-if-use)
1486 (define-key vhdl-template-map "lm" 'vhdl-template-limit)
1487 (define-key vhdl-template-map "na" 'vhdl-template-nature)
1488 (define-key vhdl-template-map "pa" 'vhdl-template-procedural)
1489 (define-key vhdl-template-map "qf" 'vhdl-template-quantity-free)
1490 (define-key vhdl-template-map "qb" 'vhdl-template-quantity-branch)
1491 (define-key vhdl-template-map "qs" 'vhdl-template-quantity-source)
1492 (define-key vhdl-template-map "sn" 'vhdl-template-subnature)
1493 (define-key vhdl-template-map "te" 'vhdl-template-terminal)
1494 )
1495 (when (vhdl-standard-p 'math)
1496 (define-key vhdl-template-map "\C-pc" 'vhdl-template-package-math-complex)
1497 (define-key vhdl-template-map "\C-pr" 'vhdl-template-package-math-real)
1498 ))
1499
1500 ;; initialize template map for VHDL Mode
1501 (vhdl-template-map-init)
1502
1503 (defun vhdl-function-name (prefix string &optional postfix)
1504 "Generate a Lisp function name.
1505 PREFIX, STRING and optional POSTFIX are concatenated by '-' and spaces in
1506 STRING are replaced by `-' and substrings are converted to lower case."
1507 (let ((name prefix))
1508 (while (string-match "\\(\\w+\\)\\s-*\\(.*\\)" string)
1509 (setq name
1510 (concat name "-" (downcase (substring string 0 (match-end 1)))))
1511 (setq string (substring string (match-beginning 2))))
1512 (when postfix (setq name (concat name "-" postfix)))
1513 (intern name)))
1514
1515 (defvar vhdl-model-map ()
1516 "Keymap for VHDL models.")
1517
1518 (defun vhdl-model-map-init ()
1519 "Initialize `vhdl-model-map'."
1520 (setq vhdl-model-map (make-sparse-keymap))
1521 ;; key bindings for VHDL models
1522 (let ((model-alist vhdl-model-alist) model)
1523 (while model-alist
1524 (setq model (car model-alist))
1525 (define-key vhdl-model-map (nth 2 model)
1526 (vhdl-function-name "vhdl-model" (nth 0 model)))
1527 (setq model-alist (cdr model-alist)))))
1528
1529 ;; initialize user model map for VHDL Mode
1530 (vhdl-model-map-init)
1531
1532 (defvar vhdl-mode-map ()
1533 "Keymap for VHDL Mode.")
1534
1535 (defun vhdl-mode-map-init ()
1536 "Initialize `vhdl-mode-map'."
1537 (setq vhdl-mode-map (make-sparse-keymap))
1538 ;; template key bindings
1539 (define-key vhdl-mode-map "\C-c\C-t" vhdl-template-map)
1540 ;; model key bindings
1541 (define-key vhdl-mode-map "\C-c\C-m" vhdl-model-map)
1542 ;; standard key bindings
1543 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
1544 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
1545 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
1546 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
1547 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
1548 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
1549 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
1550 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
1551 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
1552 ;; backspace/delete key bindings
1553 (define-key vhdl-mode-map [backspace] 'backward-delete-char-untabify)
1554 (define-key vhdl-mode-map [delete] 'delete-char)
1555 (unless (string-match "XEmacs" emacs-version)
1556 (define-key vhdl-mode-map [M-delete] 'kill-word))
1557 ;; mode specific key bindings
1558 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
1559 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
1560 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
1561 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
1562 (define-key vhdl-mode-map "\C-c\C-p\C-w" 'vhdl-port-copy)
1563 (define-key vhdl-mode-map "\C-c\C-p\M-w" 'vhdl-port-copy)
1564 (define-key vhdl-mode-map "\C-c\C-p\C-e" 'vhdl-port-paste-entity)
1565 (define-key vhdl-mode-map "\C-c\C-p\C-c" 'vhdl-port-paste-component)
1566 (define-key vhdl-mode-map "\C-c\C-p\C-i" 'vhdl-port-paste-instance)
1567 (define-key vhdl-mode-map "\C-c\C-p\C-s" 'vhdl-port-paste-signals)
1568 (define-key vhdl-mode-map "\C-c\C-p\M-c" 'vhdl-port-paste-constants)
1569 (if (string-match "XEmacs" emacs-version) ; `... C-g' not allowed in XEmacs
1570 (define-key vhdl-mode-map "\C-c\C-p\M-g" 'vhdl-port-paste-generic-map)
1571 (define-key vhdl-mode-map "\C-c\C-p\C-g" 'vhdl-port-paste-generic-map))
1572 (define-key vhdl-mode-map "\C-c\C-p\C-t" 'vhdl-port-paste-testbench)
1573 (define-key vhdl-mode-map "\C-c\C-p\C-f" 'vhdl-port-flatten)
1574 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
1575 (define-key vhdl-mode-map "\C-c-" 'vhdl-comment-append-inline)
1576 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-comment-display-line)
1577 (define-key vhdl-mode-map "\C-c\M-\C-i" 'vhdl-indent-line)
1578 (define-key vhdl-mode-map "\M-\C-\\" 'vhdl-indent-region)
1579 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-group)
1580 (define-key vhdl-mode-map "\C-c\C-r\C-a" 'vhdl-align-noindent-region)
1581 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-inline-comment-group)
1582 (define-key vhdl-mode-map "\C-c\C-r\M-\C-a" 'vhdl-align-inline-comment-region)
1583 (define-key vhdl-mode-map "\C-c\C-w" 'vhdl-fixup-whitespace-region)
1584 (define-key vhdl-mode-map "\C-c\C-l\C-w" 'vhdl-line-kill)
1585 (define-key vhdl-mode-map "\C-c\C-l\M-w" 'vhdl-line-copy)
1586 (define-key vhdl-mode-map "\C-c\C-l\C-y" 'vhdl-line-yank)
1587 (define-key vhdl-mode-map "\C-c\C-l\t" 'vhdl-line-expand)
1588 (define-key vhdl-mode-map "\C-c\C-l\C-n" 'vhdl-line-transpose-next)
1589 (define-key vhdl-mode-map "\C-c\C-l\C-p" 'vhdl-line-transpose-previous)
1590 (define-key vhdl-mode-map "\C-c\C-l\C-o" 'vhdl-line-open)
1591 (define-key vhdl-mode-map "\C-c\C-l\C-g" 'goto-line)
1592 (define-key vhdl-mode-map "\C-c\C-l\C-c" 'vhdl-comment-uncomment-line)
1593 (define-key vhdl-mode-map "\C-c\C-r\C-u" 'vhdl-fix-case-region)
1594 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
1595 (define-key vhdl-mode-map "\C-c\C-f" 'vhdl-fontify-buffer)
1596 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
1597 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-doc-mode)
1598 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
1599 (define-key vhdl-mode-map "\C-c\C-r\C-b" 'vhdl-beautify-region)
1600 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-beautify-buffer)
1601 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
1602 ;; insert commands bindings
1603 (define-key vhdl-mode-map "\C-c\C-i\C-c" 'vhdl-template-insert-construct)
1604 (define-key vhdl-mode-map "\C-c\C-i\C-p" 'vhdl-template-insert-package)
1605 (define-key vhdl-mode-map "\C-c\C-i\C-d" 'vhdl-template-insert-directive)
1606 (define-key vhdl-mode-map "\C-c\C-i\C-m" 'vhdl-model-insert)
1607 ;; electric key bindings
1608 (define-key vhdl-mode-map " " 'vhdl-electric-space)
1609 (if vhdl-intelligent-tab
1610 (define-key vhdl-mode-map "\t" 'vhdl-electric-tab)
1611 (define-key vhdl-mode-map "\t" 'vhdl-indent-line))
1612 (define-key vhdl-mode-map "\r" 'vhdl-electric-return)
1613 (define-key vhdl-mode-map "-" 'vhdl-electric-dash)
1614 (define-key vhdl-mode-map "[" 'vhdl-electric-open-bracket)
1615 (define-key vhdl-mode-map "]" 'vhdl-electric-close-bracket)
1616 (define-key vhdl-mode-map "'" 'vhdl-electric-quote)
1617 (define-key vhdl-mode-map ";" 'vhdl-electric-semicolon)
1618 (define-key vhdl-mode-map "," 'vhdl-electric-comma)
1619 (define-key vhdl-mode-map "." 'vhdl-electric-period)
1620 (when (vhdl-standard-p 'ams)
1621 (define-key vhdl-mode-map "=" 'vhdl-electric-equal)))
1622
1623 ;; initialize mode map for VHDL Mode
1624 (vhdl-mode-map-init)
1625
1626 ;; define special minibuffer keymap for enabling word completion in minibuffer
1627 ;; (useful in template generator prompts)
1628 (defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
1629 "Keymap for minibuffer used in VHDL Mode.")
1630
1631 (when vhdl-word-completion-in-minibuffer
1632 (define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab))
1633
1634 ;; set up electric character functions to work with
1635 ;; `delete-selection-mode' (Emacs) and `pending-delete-mode' (XEmacs)
1636 (mapcar
1637 (function
1638 (lambda (sym)
1639 (put sym 'delete-selection t) ; for `delete-selection-mode' (Emacs)
1640 (put sym 'pending-delete t))) ; for `pending-delete-mode' (XEmacs)
1641 '(vhdl-electric-space
1642 vhdl-electric-tab
1643 vhdl-electric-return
1644 vhdl-electric-dash
1645 vhdl-electric-open-bracket
1646 vhdl-electric-close-bracket
1647 vhdl-electric-quote
1648 vhdl-electric-semicolon
1649 vhdl-electric-comma
1650 vhdl-electric-period
1651 vhdl-electric-equal))
1652
1653 ;; syntax table
1654 (defvar vhdl-mode-syntax-table nil
1655 "Syntax table used in `vhdl-mode' buffers.")
1656
1657 (defun vhdl-mode-syntax-table-init ()
1658 "Initialize `vhdl-mode-syntax-table'."
1659 (setq vhdl-mode-syntax-table (make-syntax-table))
1660 ;; define punctuation
1661 (modify-syntax-entry ?\# "." vhdl-mode-syntax-table)
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 ;; define string
1678 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
1679 ;; define underscore
1680 (when vhdl-underscore-is-part-of-word
1681 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
1682 ;; a single hyphen is punctuation, but a double hyphen starts a comment
1683 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
1684 ;; and \n and \^M end a comment
1685 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
1686 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table)
1687 ;; define parentheses to match
1688 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
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
1695 ;; initialize syntax table for VHDL Mode
1696 (vhdl-mode-syntax-table-init)
1697
1698 (defmacro vhdl-ext-syntax-table (&rest body)
1699 "Execute BODY with syntax table that includes `_' in word class."
1700 `(let (result)
1701 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
1702 (setq result (progn ,@body))
1703 (when (not vhdl-underscore-is-part-of-word)
1704 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
1705 result))
1706
1707 (defvar vhdl-syntactic-context nil
1708 "Buffer local variable containing syntactic analysis list.")
1709 (make-variable-buffer-local 'vhdl-syntactic-context)
1710
1711 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1712 ;; Abbrev hook bindings
1713
1714 (defvar vhdl-mode-abbrev-table nil
1715 "Abbrev table to use in `vhdl-mode' buffers.")
1716
1717 (defun vhdl-mode-abbrev-table-init ()
1718 "Initialize `vhdl-mode-abbrev-table'."
1719 (when vhdl-mode-abbrev-table (clear-abbrev-table vhdl-mode-abbrev-table))
1720 (define-abbrev-table 'vhdl-mode-abbrev-table
1721 (append
1722 (when (memq 'vhdl vhdl-electric-keywords)
1723 ;; VHDL'93 keywords
1724 '(
1725 ("--" "" vhdl-template-display-comment-hook 0)
1726 ("abs" "" vhdl-template-default-hook 0)
1727 ("access" "" vhdl-template-default-hook 0)
1728 ("after" "" vhdl-template-default-hook 0)
1729 ("alias" "" vhdl-template-alias-hook 0)
1730 ("all" "" vhdl-template-default-hook 0)
1731 ("and" "" vhdl-template-default-hook 0)
1732 ("arch" "" vhdl-template-architecture-hook 0)
1733 ("architecture" "" vhdl-template-architecture-hook 0)
1734 ("array" "" vhdl-template-default-hook 0)
1735 ("assert" "" vhdl-template-assert-hook 0)
1736 ("attr" "" vhdl-template-attribute-hook 0)
1737 ("attribute" "" vhdl-template-attribute-hook 0)
1738 ("begin" "" vhdl-template-default-indent-hook 0)
1739 ("block" "" vhdl-template-block-hook 0)
1740 ("body" "" vhdl-template-default-hook 0)
1741 ("buffer" "" vhdl-template-default-hook 0)
1742 ("bus" "" vhdl-template-default-hook 0)
1743 ("case" "" vhdl-template-case-hook 0)
1744 ("comp" "" vhdl-template-component-hook 0)
1745 ("component" "" vhdl-template-component-hook 0)
1746 ("cond" "" vhdl-template-conditional-signal-asst-hook 0)
1747 ("conditional" "" vhdl-template-conditional-signal-asst-hook 0)
1748 ("conf" "" vhdl-template-configuration-hook 0)
1749 ("configuration" "" vhdl-template-configuration-hook 0)
1750 ("cons" "" vhdl-template-constant-hook 0)
1751 ("constant" "" vhdl-template-constant-hook 0)
1752 ("disconnect" "" vhdl-template-disconnect-hook 0)
1753 ("downto" "" vhdl-template-default-hook 0)
1754 ("else" "" vhdl-template-else-hook 0)
1755 ("elseif" "" vhdl-template-elsif-hook 0)
1756 ("elsif" "" vhdl-template-elsif-hook 0)
1757 ("end" "" vhdl-template-default-indent-hook 0)
1758 ("entity" "" vhdl-template-entity-hook 0)
1759 ("exit" "" vhdl-template-exit-hook 0)
1760 ("file" "" vhdl-template-file-hook 0)
1761 ("for" "" vhdl-template-for-hook 0)
1762 ("func" "" vhdl-template-function-hook 0)
1763 ("function" "" vhdl-template-function-hook 0)
1764 ("generic" "" vhdl-template-generic-hook 0)
1765 ("group" "" vhdl-template-group-hook 0)
1766 ("guarded" "" vhdl-template-default-hook 0)
1767 ("if" "" vhdl-template-if-hook 0)
1768 ("impure" "" vhdl-template-default-hook 0)
1769 ("in" "" vhdl-template-default-hook 0)
1770 ("inertial" "" vhdl-template-default-hook 0)
1771 ("inout" "" vhdl-template-default-hook 0)
1772 ("inst" "" vhdl-template-instance-hook 0)
1773 ("instance" "" vhdl-template-instance-hook 0)
1774 ("is" "" vhdl-template-default-hook 0)
1775 ("label" "" vhdl-template-default-hook 0)
1776 ("library" "" vhdl-template-library-hook 0)
1777 ("linkage" "" vhdl-template-default-hook 0)
1778 ("literal" "" vhdl-template-default-hook 0)
1779 ("loop" "" vhdl-template-bare-loop-hook 0)
1780 ("map" "" vhdl-template-map-hook 0)
1781 ("mod" "" vhdl-template-default-hook 0)
1782 ("nand" "" vhdl-template-default-hook 0)
1783 ("new" "" vhdl-template-default-hook 0)
1784 ("next" "" vhdl-template-next-hook 0)
1785 ("nor" "" vhdl-template-default-hook 0)
1786 ("not" "" vhdl-template-default-hook 0)
1787 ("null" "" vhdl-template-default-hook 0)
1788 ("of" "" vhdl-template-default-hook 0)
1789 ("on" "" vhdl-template-default-hook 0)
1790 ("open" "" vhdl-template-default-hook 0)
1791 ("or" "" vhdl-template-default-hook 0)
1792 ("others" "" vhdl-template-default-hook 0)
1793 ("out" "" vhdl-template-default-hook 0)
1794 ("pack" "" vhdl-template-package-hook 0)
1795 ("package" "" vhdl-template-package-hook 0)
1796 ("port" "" vhdl-template-port-hook 0)
1797 ("postponed" "" vhdl-template-default-hook 0)
1798 ("procedure" "" vhdl-template-procedure-hook 0)
1799 ("process" "" vhdl-template-process-hook 0)
1800 ("pure" "" vhdl-template-default-hook 0)
1801 ("range" "" vhdl-template-default-hook 0)
1802 ("record" "" vhdl-template-default-hook 0)
1803 ("register" "" vhdl-template-default-hook 0)
1804 ("reject" "" vhdl-template-default-hook 0)
1805 ("rem" "" vhdl-template-default-hook 0)
1806 ("report" "" vhdl-template-report-hook 0)
1807 ("return" "" vhdl-template-return-hook 0)
1808 ("rol" "" vhdl-template-default-hook 0)
1809 ("ror" "" vhdl-template-default-hook 0)
1810 ("select" "" vhdl-template-selected-signal-asst-hook 0)
1811 ("severity" "" vhdl-template-default-hook 0)
1812 ("shared" "" vhdl-template-default-hook 0)
1813 ("sig" "" vhdl-template-signal-hook 0)
1814 ("signal" "" vhdl-template-signal-hook 0)
1815 ("sla" "" vhdl-template-default-hook 0)
1816 ("sll" "" vhdl-template-default-hook 0)
1817 ("sra" "" vhdl-template-default-hook 0)
1818 ("srl" "" vhdl-template-default-hook 0)
1819 ("subtype" "" vhdl-template-subtype-hook 0)
1820 ("then" "" vhdl-template-default-hook 0)
1821 ("to" "" vhdl-template-default-hook 0)
1822 ("transport" "" vhdl-template-default-hook 0)
1823 ("type" "" vhdl-template-type-hook 0)
1824 ("unaffected" "" vhdl-template-default-hook 0)
1825 ("units" "" vhdl-template-default-hook 0)
1826 ("until" "" vhdl-template-default-hook 0)
1827 ("use" "" vhdl-template-use-hook 0)
1828 ("var" "" vhdl-template-variable-hook 0)
1829 ("variable" "" vhdl-template-variable-hook 0)
1830 ("wait" "" vhdl-template-wait-hook 0)
1831 ("when" "" vhdl-template-when-hook 0)
1832 ("while" "" vhdl-template-while-loop-hook 0)
1833 ("with" "" vhdl-template-with-hook 0)
1834 ("xnor" "" vhdl-template-default-hook 0)
1835 ("xor" "" vhdl-template-default-hook 0)
1836 ))
1837 ;; VHDL-AMS keywords
1838 (when (and (memq 'vhdl vhdl-electric-keywords) (vhdl-standard-p 'ams))
1839 '(
1840 ("across" "" vhdl-template-default-hook 0)
1841 ("break" "" vhdl-template-break-hook 0)
1842 ("limit" "" vhdl-template-limit-hook 0)
1843 ("nature" "" vhdl-template-nature-hook 0)
1844 ("noise" "" vhdl-template-default-hook 0)
1845 ("procedural" "" vhdl-template-procedural-hook 0)
1846 ("quantity" "" vhdl-template-quantity-hook 0)
1847 ("reference" "" vhdl-template-default-hook 0)
1848 ("spectrum" "" vhdl-template-default-hook 0)
1849 ("subnature" "" vhdl-template-subnature-hook 0)
1850 ("terminal" "" vhdl-template-terminal-hook 0)
1851 ("through" "" vhdl-template-default-hook 0)
1852 ("tolerance" "" vhdl-template-default-hook 0)
1853 ))
1854 ;; user model keywords
1855 (when (memq 'user vhdl-electric-keywords)
1856 (let ((alist vhdl-model-alist)
1857 abbrev-list keyword)
1858 (while alist
1859 (setq keyword (nth 3 (car alist)))
1860 (unless (equal keyword "")
1861 (setq abbrev-list
1862 (cons (list keyword ""
1863 (vhdl-function-name
1864 "vhdl-model" (nth 0 (car alist)) "hook") 0)
1865 abbrev-list)))
1866 (setq alist (cdr alist)))
1867 abbrev-list)))))
1868
1869 ;; initialize abbrev table for VHDL Mode
1870 (vhdl-mode-abbrev-table-init)
1871
1872 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1873 ;; Template completion lists
1874
1875 (defvar vhdl-template-construct-alist nil
1876 "List of built-in construct templates.")
1877
1878 (defun vhdl-template-construct-alist-init ()
1879 "Initialize `vhdl-template-construct-alist'."
1880 (setq
1881 vhdl-template-construct-alist
1882 (append
1883 '(
1884 ("alias declaration" vhdl-template-alias)
1885 ("architecture body" vhdl-template-architecture)
1886 ("assertion" vhdl-template-assert)
1887 ("attribute declaration" vhdl-template-attribute-decl)
1888 ("attribute specification" vhdl-template-attribute-spec)
1889 ("block configuration" vhdl-template-block-configuration)
1890 ("block statement" vhdl-template-block)
1891 ("case statement" vhdl-template-case-is)
1892 ("component configuration" vhdl-template-component-conf)
1893 ("component declaration" vhdl-template-component-decl)
1894 ("component instantiation statement" vhdl-template-component-inst)
1895 ("conditional signal assignment" vhdl-template-conditional-signal-asst)
1896 ("configuration declaration" vhdl-template-configuration-decl)
1897 ("configuration specification" vhdl-template-configuration-spec)
1898 ("constant declaration" vhdl-template-constant)
1899 ("disconnection specification" vhdl-template-disconnect)
1900 ("entity declaration" vhdl-template-entity)
1901 ("exit statement" vhdl-template-exit)
1902 ("file declaration" vhdl-template-file)
1903 ("generate statement" vhdl-template-generate)
1904 ("generic clause" vhdl-template-generic)
1905 ("group declaration" vhdl-template-group-decl)
1906 ("group template declaration" vhdl-template-group-template)
1907 ("if statement" vhdl-template-if-then)
1908 ("library clause" vhdl-template-library)
1909 ("loop statement" vhdl-template-loop)
1910 ("next statement" vhdl-template-next)
1911 ("package declaration" vhdl-template-package-decl)
1912 ("package body" vhdl-template-package-body)
1913 ("port clause" vhdl-template-port)
1914 ("process statement" vhdl-template-process)
1915 ("report statement" vhdl-template-report)
1916 ("return statement" vhdl-template-return)
1917 ("selected signal assignment" vhdl-template-selected-signal-asst)
1918 ("signal declaration" vhdl-template-signal)
1919 ("subprogram declaration" vhdl-template-subprogram-decl)
1920 ("subprogram body" vhdl-template-subprogram-body)
1921 ("subtype declaration" vhdl-template-subtype)
1922 ("type declaration" vhdl-template-type)
1923 ("use clause" vhdl-template-use)
1924 ("variable declaration" vhdl-template-variable)
1925 ("wait statement" vhdl-template-wait)
1926 )
1927 (when (vhdl-standard-p 'ams)
1928 '(
1929 ("break statement" vhdl-template-break)
1930 ("nature declaration" vhdl-template-nature)
1931 ("quantity declaration" vhdl-template-quantity)
1932 ("simultaneous case statement" vhdl-template-case-use)
1933 ("simultaneous if statement" vhdl-template-if-use)
1934 ("simultaneous procedural statement" vhdl-template-procedural)
1935 ("step limit specification" vhdl-template-limit)
1936 ("subnature declaration" vhdl-template-subnature)
1937 ("terminal declaration" vhdl-template-terminal)
1938 )))))
1939
1940 ;; initialize for VHDL Mode
1941 (vhdl-template-construct-alist-init)
1942
1943 (defvar vhdl-template-package-alist nil
1944 "List of built-in package templates.")
1945
1946 (defun vhdl-template-package-alist-init ()
1947 "Initialize `vhdl-template-package-alist'."
1948 (setq
1949 vhdl-template-package-alist
1950 (append
1951 '(
1952 ("numeric_bit" vhdl-template-package-numeric-bit)
1953 ("numeric_std" vhdl-template-package-numeric-std)
1954 ("std_logic_1164" vhdl-template-package-std-logic-1164)
1955 ("std_logic_arith" vhdl-template-package-std-logic-arith)
1956 ("std_logic_misc" vhdl-template-package-std-logic-misc)
1957 ("std_logic_signed" vhdl-template-package-std-logic-signed)
1958 ("std_logic_textio" vhdl-template-package-std-logic-textio)
1959 ("std_logic_unsigned" vhdl-template-package-std-logic-unsigned)
1960 ("textio" vhdl-template-package-textio)
1961 )
1962 (when (vhdl-standard-p 'math)
1963 '(
1964 ("math_complex" vhdl-template-package-math-complex)
1965 ("math_real" vhdl-template-package-math-real)
1966 )))))
1967
1968 ;; initialize for VHDL Mode
1969 (vhdl-template-package-alist-init)
1970
1971 (defvar vhdl-template-directive-alist
1972 (append
1973 '(
1974 ("translate_on" vhdl-template-directive-translate-on)
1975 ("translate_off" vhdl-template-directive-translate-off)
1976 ("synthesis_on" vhdl-template-directive-synthesis-on)
1977 ("synthesis_off" vhdl-template-directive-synthesis-off)
1978 ))
1979 "List of built-in directive templates.")
1980
1981
1982 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1983 ;;; Menues
1984 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1985
1986 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1987 ;; VHDL menu (using `easy-menu.el')
1988
1989 (defun vhdl-customize ()
1990 "Call the customize function with `vhdl' as argument."
1991 (interactive)
1992 (customize-browse 'vhdl))
1993
1994 (defun vhdl-create-customize-menu ()
1995 "Create a full customization menu for VHDL, insert it into the menu."
1996 (interactive)
1997 (if (fboundp 'customize-menu-create)
1998 (easy-menu-change
1999 '("VHDL") "Customize"
2000 `(["Browse VHDL Group..." vhdl-customize t]
2001 ,(customize-menu-create 'vhdl)
2002 "--"
2003 ["Activate New Customizations" vhdl-activate-customizations t]))
2004 (error "Cannot expand menu (outdated version of cus-edit.el)")))
2005
2006 (defun vhdl-create-mode-menu ()
2007 "Create VHDL Mode menu."
2008 (list
2009 "VHDL"
2010 '("Mode"
2011 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
2012 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
2013 )
2014 "--"
2015 (append
2016 '("Project"
2017 ["None" (vhdl-project-switch "")
2018 :style radio :selected (equal vhdl-project "")]
2019 "--"
2020 )
2021 ;; add menu entries for defined projects
2022 (let ((project-alist vhdl-project-alist) menu-alist name)
2023 (while project-alist
2024 (setq name (car (car project-alist)))
2025 (setq menu-alist (cons (vector name (list 'vhdl-project-switch name)
2026 :style 'radio :selected
2027 (list 'equal 'vhdl-project name))
2028 menu-alist))
2029 (setq project-alist (cdr project-alist)))
2030 (setq menu-alist (cons '["Add Project..."
2031 (customize-variable 'vhdl-project-alist) t]
2032 (cons "--" menu-alist)))
2033 (nreverse menu-alist)))
2034 "--"
2035 (list
2036 "Compile"
2037 ["Compile Buffer" vhdl-compile t]
2038 ["Stop Compilation" kill-compilation t]
2039 "--"
2040 ["Make" vhdl-make t]
2041 ["Generate Makefile" vhdl-generate-makefile t]
2042 "--"
2043 ["Next Error" next-error t]
2044 ["Previous Error" previous-error t]
2045 ["First Error" first-error t]
2046 "--"
2047 (append
2048 '("Compiler")
2049 ;; add menu entries for defined compilers
2050 (let ((comp-alist vhdl-compiler-alist) menu-alist name)
2051 (while comp-alist
2052 (setq name (car (car comp-alist)))
2053 (setq menu-alist (cons (vector name (list 'setq 'vhdl-compiler name)
2054 :style 'radio :selected
2055 (list 'equal 'vhdl-compiler name))
2056 menu-alist))
2057 (setq comp-alist (cdr comp-alist)))
2058 (setq menu-alist (cons '["Add Compiler..."
2059 (customize-variable 'vhdl-compiler-alist) t]
2060 (cons "--" menu-alist)))
2061 (nreverse menu-alist))))
2062 "--"
2063 (append
2064 '("Template"
2065 ("VHDL Construct 1"
2066 ["Alias" vhdl-template-alias t]
2067 ["Architecture" vhdl-template-architecture t]
2068 ["Assert" vhdl-template-assert t]
2069 ["Attribute (Decl)" vhdl-template-attribute-decl t]
2070 ["Attribute (Spec)" vhdl-template-attribute-spec t]
2071 ["Block" vhdl-template-block t]
2072 ["Case" vhdl-template-case-is t]
2073 ["Component (Decl)" vhdl-template-component-decl t]
2074 ["(Component) Instance" vhdl-template-component-inst t]
2075 ["Conditional (Signal Asst)" vhdl-template-conditional-signal-asst t]
2076 ["Configuration (Block)"vhdl-template-block-configuration t]
2077 ["Configuration (Comp)" vhdl-template-component-conf t]
2078 ["Configuration (Decl)" vhdl-template-configuration-decl t]
2079 ["Configuration (Spec)" vhdl-template-configuration-spec t]
2080 ["Constant" vhdl-template-constant t]
2081 ["Disconnect" vhdl-template-disconnect t]
2082 ["Else" vhdl-template-else t]
2083 ["Elsif" vhdl-template-elsif t]
2084 ["Entity" vhdl-template-entity t]
2085 ["Exit" vhdl-template-exit t]
2086 ["File" vhdl-template-file t]
2087 ["For (Generate)" vhdl-template-for-generate t]
2088 ["For (Loop)" vhdl-template-for-loop t]
2089 ["Function (Body)" vhdl-template-function-body t]
2090 ["Function (Decl)" vhdl-template-function-decl t]
2091 ["Generic" vhdl-template-generic t]
2092 ["Group (Decl)" vhdl-template-group-decl t]
2093 ["Group (Template)" vhdl-template-group-template t]
2094 )
2095 ("VHDL Construct 2"
2096 ["If (Generate)" vhdl-template-if-generate t]
2097 ["If (Then)" vhdl-template-if-then t]
2098 ["Library" vhdl-template-library t]
2099 ["Loop" vhdl-template-bare-loop t]
2100 ["Map" vhdl-template-map t]
2101 ["Next" vhdl-template-next t]
2102 ["(Others)" vhdl-template-others t]
2103 ["Package (Decl)" vhdl-template-package-decl t]
2104 ["Package (Body)" vhdl-template-package-body t]
2105 ["Port" vhdl-template-port t]
2106 ["Procedure (Body)" vhdl-template-procedure-body t]
2107 ["Procedure (Decl)" vhdl-template-procedure-decl t]
2108 ["Process (Comb)" vhdl-template-process-comb t]
2109 ["Process (Seq)" vhdl-template-process-seq t]
2110 ["Report" vhdl-template-report t]
2111 ["Return" vhdl-template-return t]
2112 ["Select" vhdl-template-selected-signal-asst t]
2113 ["Signal" vhdl-template-signal t]
2114 ["Subtype" vhdl-template-subtype t]
2115 ["Type" vhdl-template-type t]
2116 ["Use" vhdl-template-use t]
2117 ["Variable" vhdl-template-variable t]
2118 ["Wait" vhdl-template-wait t]
2119 ["(Clocked Wait)" vhdl-template-clocked-wait t]
2120 ["When" vhdl-template-when t]
2121 ["While (Loop)" vhdl-template-while-loop t]
2122 ["With" vhdl-template-with t]
2123 ))
2124 (when (vhdl-standard-p 'ams)
2125 '(("VHDL-AMS Construct"
2126 ["Break" vhdl-template-break t]
2127 ["Case (Use)" vhdl-template-case-use t]
2128 ["If (Use)" vhdl-template-if-use t]
2129 ["Limit" vhdl-template-limit t]
2130 ["Nature" vhdl-template-nature t]
2131 ["Procedural" vhdl-template-procedural t]
2132 ["Quantity (Free)" vhdl-template-quantity-free t]
2133 ["Quantity (Branch)" vhdl-template-quantity-branch t]
2134 ["Quantity (Source)" vhdl-template-quantity-source t]
2135 ["Subnature" vhdl-template-subnature t]
2136 ["Terminal" vhdl-template-terminal t]
2137 )))
2138 '(["Insert Construct" vhdl-template-insert-construct
2139 :keys "C-c C-i C-c"]
2140 "--")
2141 (list
2142 (append
2143 '("Package")
2144 (when (vhdl-standard-p 'math)
2145 '(
2146 ["math_complex" vhdl-template-package-math-complex t]
2147 ["math_real" vhdl-template-package-math-real t]
2148 ))
2149 '(
2150 ["numeric_bit" vhdl-template-package-numeric-bit t]
2151 ["numeric_std" vhdl-template-package-numeric-std t]
2152 ["std_logic_1164" vhdl-template-package-std-logic-1164 t]
2153 ["textio" vhdl-template-package-textio t]
2154 "--"
2155 ["std_logic_arith" vhdl-template-package-std-logic-arith t]
2156 ["std_logic_signed" vhdl-template-package-std-logic-signed t]
2157 ["std_logic_unsigned" vhdl-template-package-std-logic-unsigned t]
2158 ["std_logic_misc" vhdl-template-package-std-logic-misc t]
2159 ["std_logic_textio" vhdl-template-package-std-logic-textio t]
2160 "--"
2161 ["Insert Package" vhdl-template-insert-package
2162 :keys "C-c C-i C-p"]
2163 )))
2164 '(("Directive"
2165 ["translate_on" vhdl-template-directive-translate-on t]
2166 ["translate_off" vhdl-template-directive-translate-off t]
2167 ["synthesis_on" vhdl-template-directive-synthesis-on t]
2168 ["synthesis_off" vhdl-template-directive-synthesis-off t]
2169 "--"
2170 ["Insert Directive" vhdl-template-insert-directive
2171 :keys "C-c C-i C-d"]
2172 )
2173 "--"
2174 ["Insert Header" vhdl-template-header :keys "C-c C-t C-h"]
2175 ["Insert Footer" vhdl-template-footer t]
2176 ["Insert Date" vhdl-template-insert-date t]
2177 ["Modify Date" vhdl-template-modify :keys "C-c C-t C-m"]
2178 "--"
2179 ["Query Next Prompt" vhdl-template-search-prompt t]
2180 ))
2181 (append
2182 '("Model")
2183 ;; add menu entries for defined models
2184 (let ((model-alist vhdl-model-alist) menu-alist model)
2185 (while model-alist
2186 (setq model (car model-alist))
2187 (setq menu-alist
2188 (cons (vector
2189 (nth 0 model)
2190 (vhdl-function-name "vhdl-model" (nth 0 model))
2191 :keys (concat "C-c C-m " (key-description (nth 2 model))))
2192 menu-alist))
2193 (setq model-alist (cdr model-alist)))
2194 (setq menu-alist
2195 (append
2196 (nreverse menu-alist)
2197 '("--"
2198 ["Insert Model" vhdl-model-insert :keys "C-c C-i C-m"]
2199 ["Add Model..." (customize-variable 'vhdl-model-alist) t])))
2200 menu-alist))
2201 '("Port"
2202 ["Copy" vhdl-port-copy t]
2203 "--"
2204 ["Paste As Entity" vhdl-port-paste-entity vhdl-port-list]
2205 ["Paste As Component" vhdl-port-paste-component vhdl-port-list]
2206 ["Paste As Instance" vhdl-port-paste-instance
2207 :keys "C-c C-p C-i" :active vhdl-port-list]
2208 ["Paste As Signals" vhdl-port-paste-signals vhdl-port-list]
2209 ["Paste As Constants" vhdl-port-paste-constants vhdl-port-list]
2210 ["Paste As Generic Map" vhdl-port-paste-generic-map vhdl-port-list]
2211 ["Paste As Test Bench" vhdl-port-paste-testbench vhdl-port-list]
2212 "--"
2213 ["Flatten" vhdl-port-flatten vhdl-port-list]
2214 )
2215 "--"
2216 '("Comment"
2217 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
2218 "--"
2219 ["Insert Inline Comment" vhdl-comment-append-inline t]
2220 ["Insert Horizontal Line" vhdl-comment-display-line t]
2221 ["Insert Display Comment" vhdl-comment-display t]
2222 "--"
2223 ["Fill Comment" fill-paragraph t]
2224 ["Fill Comment Region" fill-region (mark)]
2225 ["Kill Comment Region" vhdl-comment-kill-region (mark)]
2226 ["Kill Inline Comment Region" vhdl-comment-kill-inline-region (mark)]
2227 )
2228 '("Line"
2229 ["Kill" vhdl-line-kill t]
2230 ["Copy" vhdl-line-copy t]
2231 ["Yank" vhdl-line-yank t]
2232 ["Expand" vhdl-line-expand t]
2233 "--"
2234 ["Transpose Next" vhdl-line-transpose-next t]
2235 ["Transpose Prev" vhdl-line-transpose-previous t]
2236 ["Open" vhdl-line-open t]
2237 ["Join" delete-indentation t]
2238 "--"
2239 ["Goto" goto-line t]
2240 ["(Un)Comment Out" vhdl-comment-uncomment-line t]
2241 )
2242 '("Move"
2243 ["Forward Statement" vhdl-end-of-statement t]
2244 ["Backward Statement" vhdl-beginning-of-statement t]
2245 ["Forward Expression" vhdl-forward-sexp t]
2246 ["Backward Expression" vhdl-backward-sexp t]
2247 ["Forward Function" vhdl-end-of-defun t]
2248 ["Backward Function" vhdl-beginning-of-defun t]
2249 ["Mark Function" vhdl-mark-defun t]
2250 )
2251 "--"
2252 '("Indent"
2253 ["Line" vhdl-indent-line t]
2254 ["Region" vhdl-indent-region (mark)]
2255 ["Buffer" vhdl-indent-buffer t]
2256 )
2257 '("Align"
2258 ["Group" vhdl-align-group t]
2259 ["Region" vhdl-align-noindent-region (mark)]
2260 ["Buffer" vhdl-align-noindent-buffer t]
2261 "--"
2262 ["Inline Comment Group" vhdl-align-inline-comment-group t]
2263 ["Inline Comment Region" vhdl-align-inline-comment-region (mark)]
2264 ["Inline Comment Buffer" vhdl-align-inline-comment-buffer t]
2265 "--"
2266 ["Fixup Whitespace Region" vhdl-fixup-whitespace-region (mark)]
2267 ["Fixup Whitespace Buffer" vhdl-fixup-whitespace-buffer t]
2268 )
2269 '("Fix Case"
2270 ["Region" vhdl-fix-case-region (mark)]
2271 ["Buffer" vhdl-fix-case-buffer t]
2272 )
2273 '("Beautify"
2274 ["Beautify Region" vhdl-beautify-region (mark)]
2275 ["Beautify Buffer" vhdl-beautify-buffer t]
2276 )
2277 "--"
2278 ["Fontify Buffer" vhdl-fontify-buffer t]
2279 ["Syntactic Info" vhdl-show-syntactic-information t]
2280 "--"
2281 '("Documentation"
2282 ["VHDL Mode" vhdl-doc-mode :keys "C-c C-h"]
2283 ["Reserved Words" (vhdl-doc-variable 'vhdl-doc-keywords) t]
2284 ["Coding Style" (vhdl-doc-variable 'vhdl-doc-coding-style) t]
2285 )
2286 ["Version" vhdl-version t]
2287 ["Bug Report..." vhdl-submit-bug-report t]
2288 "--"
2289 '("Speedbar"
2290 ["Open/Close" vhdl-speedbar t]
2291 "--"
2292 ["Show Hierarchy" vhdl-speedbar-toggle-hierarchy
2293 :style toggle
2294 :selected
2295 (and (boundp 'speedbar-initial-expansion-list-name)
2296 (equal speedbar-initial-expansion-list-name "vhdl hierarchy"))
2297 :active (and (boundp 'speedbar-frame) speedbar-frame)]
2298 )
2299 "--"
2300 '("Customize"
2301 ["Browse VHDL Group..." vhdl-customize t]
2302 ["Build Customize Menu" vhdl-create-customize-menu
2303 (fboundp 'customize-menu-create)]
2304 "--"
2305 ["Activate New Customizations" vhdl-activate-customizations t])
2306 ))
2307
2308 (defvar vhdl-mode-menu-list (vhdl-create-mode-menu)
2309 "VHDL Mode menu.")
2310
2311 (defun vhdl-update-mode-menu ()
2312 "Update VHDL mode menu."
2313 (interactive)
2314 (easy-menu-remove vhdl-mode-menu-list) ; for XEmacs
2315 (setq vhdl-mode-menu-list (vhdl-create-mode-menu))
2316 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2317 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2318 "Menu keymap for VHDL Mode." vhdl-mode-menu-list))
2319
2320 (require 'easymenu)
2321
2322 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2323 ;; Index menu (using `imenu.el'), also used for speedbar (using `speedbar.el')
2324
2325 (defvar vhdl-imenu-generic-expression
2326 '(
2327 ("Subprogram"
2328 "^\\s-*\\(\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\s-+\\(\"?\\(\\w\\|\\s_\\)+\"?\\)"
2329 4)
2330 ("Instance"
2331 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
2332 1)
2333 ("Component"
2334 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2335 2)
2336 ("Procedural"
2337 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(procedural\\)"
2338 1)
2339 ("Process"
2340 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\(postponed\\s-+\\|\\)process\\)"
2341 1)
2342 ("Block"
2343 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(block\\)"
2344 1)
2345 ("Package"
2346 "^\\s-*\\(package\\( body\\|\\)\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2347 3)
2348 ("Configuration"
2349 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
2350 2)
2351 ("Architecture"
2352 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
2353 2)
2354 ("Entity"
2355 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2356 2)
2357 )
2358 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
2359
2360 (defun vhdl-index-menu-init ()
2361 "Initialize index menu."
2362 (set (make-local-variable 'imenu-case-fold-search) t)
2363 (set (make-local-variable 'imenu-generic-expression)
2364 vhdl-imenu-generic-expression)
2365 (when (and vhdl-index-menu (not (string-match "XEmacs" emacs-version)))
2366 (if (or (not (boundp 'font-lock-maximum-size))
2367 (> font-lock-maximum-size (buffer-size)))
2368 (imenu-add-to-menubar "Index")
2369 (message "Scanning buffer for index...buffer too big"))))
2370
2371 ;; ############################################################################
2372 ;; Source file menu (using `easy-menu.el')
2373
2374 (defvar vhdl-sources-menu nil)
2375
2376 (defun vhdl-directory-files (directory &optional full match)
2377 "Call `directory-files' if DIRECTORY exists, otherwise generate error
2378 message."
2379 (if (file-directory-p directory)
2380 (directory-files directory full match)
2381 (message "No such directory: \"%s\"" directory)
2382 nil))
2383
2384 (defun vhdl-get-source-files (&optional full directory)
2385 "Get list of VHDL source files in DIRECTORY or current directory."
2386 (let ((mode-alist auto-mode-alist)
2387 filename-regexp)
2388 ;; create regular expressions for matching file names
2389 (setq filename-regexp ".*\\(")
2390 (while mode-alist
2391 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
2392 (setq filename-regexp
2393 (concat filename-regexp (car (car mode-alist)) "\\|")))
2394 (setq mode-alist (cdr mode-alist)))
2395 (setq filename-regexp
2396 (concat (substring filename-regexp 0
2397 (string-match "\\\\|$" filename-regexp)) "\\)"))
2398 ;; find files
2399 (nreverse (vhdl-directory-files
2400 (or directory default-directory) full filename-regexp))))
2401
2402 (defun vhdl-add-source-files-menu ()
2403 "Scan directory for all VHDL source files and generate menu.
2404 The directory of the current source file is scanned."
2405 (interactive)
2406 (message "Scanning directory for source files ...")
2407 (let ((newmap (current-local-map))
2408 (mode-alist auto-mode-alist)
2409 (file-list (vhdl-get-source-files))
2410 menu-list found)
2411 ;; Create list for menu
2412 (setq found nil)
2413 (while file-list
2414 (setq found t)
2415 (setq menu-list (cons (vector (car file-list)
2416 (list 'find-file (car file-list)) t)
2417 menu-list))
2418 (setq file-list (cdr file-list)))
2419 (setq menu-list (vhdl-menu-split menu-list 25))
2420 (when found (setq menu-list (cons "--" menu-list)))
2421 (setq menu-list (cons ["*Rescan*" vhdl-add-source-files-menu t] menu-list))
2422 (setq menu-list (cons "Sources" menu-list))
2423 ;; Create menu
2424 (easy-menu-add menu-list)
2425 (easy-menu-define vhdl-sources-menu newmap
2426 "VHDL source files menu" menu-list))
2427 (message ""))
2428
2429 (defun vhdl-menu-split (list n)
2430 "Split menu LIST into several submenues, if number of elements > N."
2431 (if (> (length list) n)
2432 (let ((remain list)
2433 (result '())
2434 (sublist '())
2435 (menuno 1)
2436 (i 0))
2437 (while remain
2438 (setq sublist (cons (car remain) sublist))
2439 (setq remain (cdr remain))
2440 (setq i (+ i 1))
2441 (if (= i n)
2442 (progn
2443 (setq result (cons (cons (format "Sources %s" menuno)
2444 (nreverse sublist)) result))
2445 (setq i 0)
2446 (setq menuno (+ menuno 1))
2447 (setq sublist '()))))
2448 (and sublist
2449 (setq result (cons (cons (format "Sources %s" menuno)
2450 (nreverse sublist)) result)))
2451 (nreverse result))
2452 list))
2453
2454
2455 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2456 ;;; VHDL Mode definition
2457 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2458 ;; performs all buffer local initializations
2459
2460 ;;;###autoload
2461 (defun vhdl-mode ()
2462 "Major mode for editing VHDL code.
2463
2464 Usage:
2465 ------
2466
2467 - TEMPLATE INSERTION (electrification): After typing a VHDL keyword and
2468 entering `\\[vhdl-electric-space]', you are prompted for arguments while a template is generated
2469 for that VHDL construct. Typing `\\[vhdl-electric-return]' or `\\[keyboard-quit]' at the first (mandatory)
2470 prompt aborts the current template generation. Optional arguments are
2471 indicated by square brackets and removed if the queried string is left empty.
2472 Prompts for mandatory arguments remain in the code if the queried string is
2473 left empty. They can be queried again by `\\[vhdl-template-search-prompt]'.
2474 Typing `\\[just-one-space]' after a keyword inserts a space without calling the template
2475 generator. Automatic template generation (i.e. electrification) can be
2476 disabled (enabled) by typing `\\[vhdl-electric-mode]' or by setting custom variable
2477 `vhdl-electric-mode' (see CUSTOMIZATION).
2478 Enabled electrification is indicated by `/e' in the modeline.
2479 Template generators can be invoked from the VHDL menu, by key bindings, by
2480 typing `C-c C-i C-c' and choosing a construct, or by typing the keyword (i.e.
2481 first word of menu entry not in parenthesis) and `\\[vhdl-electric-space]'.
2482 The following abbreviations can also be used:
2483 arch, attr, cond, conf, comp, cons, func, inst, pack, sig, var.
2484 Template styles can be customized in customization group `vhdl-electric'
2485 \(see CUSTOMIZATION).
2486
2487 - HEADER INSERTION: A file header can be inserted by `\\[vhdl-template-header]'. A
2488 file footer (template at the end of the file) can be inserted by
2489 `\\[vhdl-template-footer]'. See customization group `vhdl-header'.
2490
2491 - STUTTERING: Double striking of some keys inserts cumbersome VHDL syntax
2492 elements. Stuttering can be disabled (enabled) by typing `\\[vhdl-stutter-mode]' or by
2493 variable `vhdl-stutter-mode'. Enabled stuttering is indicated by `/s' in
2494 the modeline. The stuttering keys and their effects are:
2495 ;; --> \" : \" [ --> ( -- --> comment
2496 ;;; --> \" := \" [[ --> [ --CR --> comment-out code
2497 .. --> \" => \" ] --> ) --- --> horizontal line
2498 ,, --> \" <= \" ]] --> ] ---- --> display comment
2499 == --> \" == \" '' --> \\\"
2500
2501 - WORD COMPLETION: Typing `\\[vhdl-electric-tab]' after a (not completed) word looks for a VHDL
2502 keyword or a word in the buffer that starts alike, inserts it and adjusts
2503 case. Re-typing `\\[vhdl-electric-tab]' toggles through alternative word completions.
2504 This also works in the minibuffer (i.e. in template generator prompts).
2505 Typing `\\[vhdl-electric-tab]' after `(' looks for and inserts complete parenthesized
2506 expressions (e.g. for array index ranges). All keywords as well as standard
2507 types and subprograms of VHDL have predefined abbreviations (e.g. type \"std\"
2508 and `\\[vhdl-electric-tab]' will toggle through all standard types beginning with \"std\").
2509
2510 Typing `\\[vhdl-electric-tab]' after a non-word character indents the line if at the beginning
2511 of a line (i.e. no preceding non-blank characters),and inserts a tabulator
2512 stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator stop.
2513
2514 - COMMENTS:
2515 `--' puts a single comment.
2516 `---' draws a horizontal line for separating code segments.
2517 `----' inserts a display comment, i.e. two horizontal lines with a
2518 comment in between.
2519 `--CR' comments out code on that line. Re-hitting CR comments out
2520 following lines.
2521 `\\[vhdl-comment-uncomment-region]' comments out a region if not commented out,
2522 uncomments a region if already commented out.
2523
2524 You are prompted for comments after object definitions (i.e. signals,
2525 variables, constants, ports) and after subprogram and process specifications
2526 if variable `vhdl-prompt-for-comments' is non-nil. Comments are
2527 automatically inserted as additional labels (e.g. after begin statements) and
2528 as help comments if `vhdl-self-insert-comments' is non-nil.
2529 Inline comments (i.e. comments after a piece of code on the same line) are
2530 indented at least to `vhdl-inline-comment-column'. Comments go at maximum to
2531 `vhdl-end-comment-column'. `\\[vhdl-electric-return]' after a space in a comment will open a
2532 new comment line. Typing beyond `vhdl-end-comment-column' in a comment
2533 automatically opens a new comment line. `\\[fill-paragraph]' re-fills
2534 multi-line comments.
2535
2536 - INDENTATION: `\\[vhdl-electric-tab]' indents a line if at the beginning of the line.
2537 The amount of indentation is specified by variable `vhdl-basic-offset'.
2538 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB' if variable
2539 `vhdl-intelligent-tab' is nil). Indentation can be done for an entire region
2540 \(`\\[vhdl-indent-region]') or buffer (menu). Argument and port lists are indented normally
2541 \(nil) or relative to the opening parenthesis (non-nil) according to variable
2542 `vhdl-argument-list-indent'. If variable `vhdl-indent-tabs-mode' is nil,
2543 spaces are used instead of tabs. `\\[tabify]' and `\\[untabify]' allow
2544 to convert spaces to tabs and vice versa.
2545
2546 - ALIGNMENT: The alignment functions align operators, keywords, and inline
2547 comment to beautify argument lists, port maps, etc. `\\[vhdl-align-group]' aligns a group
2548 of consecutive lines separated by blank lines. `\\[vhdl-align-noindent-region]' aligns an
2549 entire region. If variable `vhdl-align-groups' is non-nil, groups of code
2550 lines separated by empty lines are aligned individually. `\\[vhdl-align-inline-comment-group]' aligns
2551 inline comments for a group of lines, and `\\[vhdl-align-inline-comment-region]' for a region.
2552 Some templates are automatically aligned after generation if custom variable
2553 `vhdl-auto-align' is non-nil.
2554 `\\[vhdl-fixup-whitespace-region]' fixes up whitespace in a region. That is, operator symbols
2555 are surrounded by one space, and multiple spaces are eliminated.
2556
2557 - PORT TRANSLATION: Generic and port clauses from entity or component
2558 declarations can be copied (`\\[vhdl-port-copy]') and pasted as entity and
2559 component declarations, as component instantiations and corresponding
2560 internal constants and signals, as a generic map with constants as actual
2561 parameters, and as a test bench (menu).
2562 A clause with several generic/port names on the same line can be flattened
2563 (`\\[vhdl-port-flatten]') so that only one name per line exists. Names for actual
2564 ports, instances, test benches, and design-under-test instances can be
2565 derived from existing names according to variables `vhdl-...-name'.
2566 Variables `vhdl-testbench-...' allow the insertion of additional templates
2567 into a test bench. New files are created for the test bench entity and
2568 architecture according to variable `vhdl-testbench-create-files'.
2569 See customization group `vhdl-port'.
2570
2571 - TEST BENCH GENERATION: See PORT TRANSLATION.
2572
2573 - KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in
2574 menu).
2575
2576 - VHDL MENU: All commands can be invoked from the VHDL menu.
2577
2578 - FILE BROWSER: The speedbar allows browsing of directories and file contents.
2579 It can be accessed from the VHDL menu and is automatically opened if
2580 variable `vhdl-speedbar' is non-nil.
2581 In speedbar, open files and directories with `mouse-2' on the name and
2582 browse/rescan their contents with `mouse-2'/`S-mouse-2' on the `+'.
2583
2584 - DESIGN HIERARCHY BROWSER: The speedbar can also be used for browsing the
2585 hierarchy of design units contained in the source files of the current
2586 directory or in the source files/directories specified for a project (see
2587 variable `vhdl-project-alist').
2588 The speedbar can be switched between file and hierarchy browsing mode in the
2589 VHDL menu or by typing `f' and `h' in speedbar.
2590 In speedbar, open design units with `mouse-2' on the name and browse their
2591 hierarchy with `mouse-2' on the `+'. The hierarchy can be rescanned and
2592 ports directly be copied from entities by using the speedbar menu.
2593
2594 - PROJECTS: Projects can be defined in variable `vhdl-project-alist' and a
2595 current project be selected using variable `vhdl-project' (permanently) or
2596 from the menu (temporarily). For each project, a title string (for the file
2597 headers) and source files/directories (for the hierarchy browser) can be
2598 specified.
2599
2600 - SPECIAL MENUES: As an alternative to the speedbar, an index menu can
2601 be added (set variable `vhdl-index-menu' to non-nil) or made accessible
2602 as a mouse menu (e.g. add \"(global-set-key '[S-down-mouse-3] 'imenu)\" to
2603 your start-up file) for browsing the file contents. Also, a source file menu
2604 can be added (set variable `vhdl-source-file-menu' to non-nil) for browsing
2605 the current directory for VHDL source files.
2606
2607 - SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
2608 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be used is
2609 specified by variable `vhdl-compiler'. The available compilers are listed
2610 in variable `vhdl-compiler-alist' including all required compilation command,
2611 destination directory, and error message syntax information. New compilers
2612 can be added. Additional compile command options can be set in variable
2613 `vhdl-compiler-options'.
2614 An entire hierarchy of source files can be compiled by the `make' command
2615 \(menu, `\\[vhdl-make]'). This only works if an appropriate Makefile exists.
2616 The make command itself as well as a command to generate a Makefile can also
2617 be specified in variable `vhdl-compiler-alist'.
2618
2619 - VHDL STANDARDS: The VHDL standards to be used are specified in variable
2620 `vhdl-standard'. Available standards are: VHDL'87/'93, VHDL-AMS,
2621 Math Packages.
2622
2623 - KEYWORD CASE: Lower and upper case for keywords and standardized types,
2624 attributes, and enumeration values is supported. If the variable
2625 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in lower
2626 case and are converted into upper case automatically (not for types,
2627 attributes, and enumeration values). The case of keywords, types,
2628 attributes,and enumeration values can be fixed for an entire region (menu)
2629 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
2630 `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
2631
2632 - HIGHLIGHTING (fontification): Keywords and standardized types, attributes,
2633 enumeration values, and function names (controlled by variable
2634 `vhdl-highlight-keywords'), as well as comments, strings, and template
2635 prompts are highlighted using different colors. Unit, subprogram, signal,
2636 variable, constant, parameter and generic/port names in declarations as well
2637 as labels are highlighted if variable `vhdl-highlight-names' is non-nil.
2638
2639 Additional reserved words or words with a forbidden syntax (e.g. words that
2640 should be avoided) can be specified in variable `vhdl-forbidden-words' or
2641 `vhdl-forbidden-syntax' and be highlighted in a warning color (variable
2642 `vhdl-highlight-forbidden-words'). Verilog keywords are highlighted as
2643 forbidden words if variable `vhdl-highlight-verilog-keywords' is non-nil.
2644
2645 Words with special syntax can be highlighted by specifying their syntax and
2646 color in variable `vhdl-special-syntax-alist' and by setting variable
2647 `vhdl-highlight-special-words' to non-nil. This allows to establish some
2648 naming conventions (e.g. to distinguish different kinds of signals or other
2649 objects by using name suffices) and to support them visually.
2650
2651 Variable `vhdl-highlight-case-sensitive' can be set to non-nil in order to
2652 support case-sensitive highlighting. However, keywords are then only
2653 highlighted if written in lower case.
2654
2655 Code between \"translate_off\" and \"translate_on\" pragmas is highlighted
2656 using a different background color if variable `vhdl-highlight-translate-off'
2657 is non-nil.
2658
2659 All colors can be customized by command `\\[customize-face]'.
2660 For highlighting of matching parenthesis, see customization group
2661 `paren-showing' (`\\[customize-group]').
2662
2663 - USER MODELS: VHDL models (templates) can be specified by the user and made
2664 accessible in the menu, through key bindings (`C-c C-m ...'), or by keyword
2665 electrification. See custom variable `vhdl-model-alist'.
2666
2667 - HIDE/SHOW: The code of entire VHDL design units can be hidden using the
2668 `Hide/Show' menu or by pressing `S-mouse-2' within the code (variable
2669 `vhdl-hideshow-menu').
2670
2671 - PRINTING: Postscript printing with different faces (an optimized set of
2672 faces is used if `vhdl-print-customize-faces' is non-nil) or colors
2673 \(if `ps-print-color-p' is non-nil) is possible using the standard Emacs
2674 postscript printing commands. Variable `vhdl-print-two-column' defines
2675 appropriate default settings for nice landscape two-column printing. The
2676 paper format can be set by variable `ps-paper-type'. Do not forget to
2677 switch `ps-print-color-p' to nil for printing on black-and-white printers.
2678
2679 - CUSTOMIZATION: All variables can easily be customized using the `Customize'
2680 menu entry or `\\[customize-option]' (`\\[customize-group]' for groups).
2681 Some customizations only take effect after some action (read the NOTE in
2682 the variable documentation). Customization can also be done globally (i.e.
2683 site-wide, read the INSTALL file).
2684
2685 - FILE EXTENSIONS: As default, files with extensions \".vhd\" and \".vhdl\" are
2686 automatically recognized as VHDL source files. To add an extension \".xxx\",
2687 add the following line to your Emacs start-up file (`.emacs'):
2688 \(setq auto-mode-alist (cons '(\"\\\\.xxx\\\\'\" . vhdl-mode) auto-mode-alist))
2689
2690 - HINTS:
2691 - Type `\\[keyboard-quit] \\[keyboard-quit]' to interrupt long operations or if Emacs hangs.
2692
2693
2694 Maintenance:
2695 ------------
2696
2697 To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
2698 Add a description of the problem and include a reproducible test case.
2699
2700 Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
2701
2702 The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
2703 The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
2704 You are kindly invited to participate in beta testing. Subscribe to above
2705 mailing lists by sending an email to <vhdl-mode@geocities.com>.
2706
2707 VHDL Mode is officially distributed on the Emacs VHDL Mode Home Page
2708 <http://www.geocities.com/SiliconValley/Peaks/8287>, where the latest
2709 version and release notes can be found.
2710
2711
2712 Bugs and Limitations:
2713 ---------------------
2714
2715 - Re-indenting large regions or expressions can be slow.
2716 - Indentation bug in simultaneous if- and case-statements (VHDL-AMS).
2717 - Hideshow does not work under XEmacs.
2718 - Index menu and file tagging in speedbar do not work under XEmacs.
2719 - Parsing compilation error messages for Ikos and Viewlogic VHDL compilers
2720 does not work under XEmacs.
2721
2722
2723 The VHDL Mode Maintainers
2724 Reto Zimmermann and Rod Whitby
2725
2726 Key bindings:
2727 -------------
2728
2729 \\{vhdl-mode-map}"
2730 (interactive)
2731 (kill-all-local-variables)
2732 (setq major-mode 'vhdl-mode)
2733 (setq mode-name "VHDL")
2734
2735 ;; set maps and tables
2736 (use-local-map vhdl-mode-map)
2737 (set-syntax-table vhdl-mode-syntax-table)
2738 (setq local-abbrev-table vhdl-mode-abbrev-table)
2739
2740 ;; set local variable values
2741 (set (make-local-variable 'paragraph-start)
2742 "\\s-*\\(--+\\s-*$\\|[^ -]\\|$\\)")
2743 (set (make-local-variable 'paragraph-separate) paragraph-start)
2744 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
2745 (set (make-local-variable 'require-final-newline) t)
2746 (set (make-local-variable 'parse-sexp-ignore-comments) t)
2747 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
2748 (set (make-local-variable 'comment-start) "--")
2749 (set (make-local-variable 'comment-end) "")
2750 (set (make-local-variable 'comment-column) vhdl-inline-comment-column)
2751 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
2752 (set (make-local-variable 'comment-start-skip) "--+\\s-*")
2753 (set (make-local-variable 'comment-multi-line) nil)
2754 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
2755 (set (make-local-variable 'hippie-expand-only-buffers) '(vhdl-mode))
2756 (set (make-local-variable 'hippie-expand-verbose) nil)
2757
2758 ;; setup the comment indent variable in a Emacs version portable way
2759 ;; ignore any byte compiler warnings you might get here
2760 (when (boundp 'comment-indent-function)
2761 (make-local-variable 'comment-indent-function)
2762 (setq comment-indent-function 'vhdl-comment-indent))
2763
2764 ;; initialize font locking
2765 (require 'font-lock)
2766 (set (make-local-variable 'font-lock-defaults)
2767 (list
2768 'vhdl-font-lock-keywords nil
2769 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
2770 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
2771 (set (make-local-variable 'font-lock-support-mode) 'lazy-lock-mode)
2772 (set (make-local-variable 'lazy-lock-defer-contextually) nil)
2773 (set (make-local-variable 'lazy-lock-defer-on-the-fly) t)
2774 ; (set (make-local-variable 'lazy-lock-defer-time) 0.1)
2775 (set (make-local-variable 'lazy-lock-defer-on-scrolling) t)
2776 (turn-on-font-lock)
2777
2778 ;; variables for source file compilation
2779 (require 'compile)
2780 (set (make-local-variable 'compilation-error-regexp-alist) nil)
2781 (set (make-local-variable 'compilation-file-regexp-alist) nil)
2782
2783 ;; add index menu
2784 (vhdl-index-menu-init)
2785 ;; add source file menu
2786 (if vhdl-source-file-menu (vhdl-add-source-files-menu))
2787 ;; add VHDL menu
2788 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2789 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2790 "Menu keymap for VHDL Mode." vhdl-mode-menu-list)
2791 ;; initialize hideshow and add menu
2792 (make-local-variable 'hs-minor-mode-hook)
2793 (vhdl-hideshow-init)
2794 (run-hooks 'menu-bar-update-hook)
2795
2796 ;; add speedbar
2797 (when (fboundp 'speedbar)
2798 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
2799 (progn
2800 (when (and vhdl-speedbar (not (and (boundp 'speedbar-frame)
2801 (frame-live-p speedbar-frame))))
2802 (speedbar-frame-mode 1)
2803 (select-frame speedbar-attached-frame)))
2804 (error (vhdl-add-warning "Before using Speedbar, install included `speedbar.el' patch"))))
2805
2806 ;; miscellaneous
2807 (vhdl-ps-print-init)
2808 (vhdl-modify-date-init)
2809 (vhdl-mode-line-update)
2810 (message "VHDL Mode %s. Type C-c C-h for documentation."
2811 vhdl-version)
2812 (vhdl-print-warnings)
2813
2814 ;; run hooks
2815 (run-hooks 'vhdl-mode-hook))
2816
2817 (defun vhdl-activate-customizations ()
2818 "Activate all customizations on local variables."
2819 (interactive)
2820 (vhdl-mode-map-init)
2821 (use-local-map vhdl-mode-map)
2822 (set-syntax-table vhdl-mode-syntax-table)
2823 (setq comment-column vhdl-inline-comment-column)
2824 (setq end-comment-column vhdl-end-comment-column)
2825 (vhdl-modify-date-init)
2826 (vhdl-update-mode-menu)
2827 (vhdl-hideshow-init)
2828 (run-hooks 'menu-bar-update-hook)
2829 (vhdl-mode-line-update))
2830
2831 (defun vhdl-modify-date-init ()
2832 "Add/remove hook for modifying date when buffer is saved."
2833 (if vhdl-modify-date-on-saving
2834 (add-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)
2835 (remove-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)))
2836
2837
2838 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2839 ;;; Documentation
2840 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2841
2842 (defvar vhdl-doc-keywords nil
2843 "Reserved words in VHDL:
2844
2845 VHDL'93 (IEEE Std 1076-1993):
2846 `vhdl-93-keywords' : keywords
2847 `vhdl-93-types' : standardized types
2848 `vhdl-93-attributes' : standardized attributes
2849 `vhdl-93-enum-values' : standardized enumeration values
2850 `vhdl-93-functions' : standardized functions
2851 `vhdl-93-packages' : standardized packages and libraries
2852
2853 VHDL-AMS (IEEE Std 1076.1):
2854 `vhdl-ams-keywords' : keywords
2855 `vhdl-ams-types' : standardized types
2856 `vhdl-ams-attributes' : standardized attributes
2857 `vhdl-ams-enum-values' : standardized enumeration values
2858 `vhdl-ams-functions' : standardized functions
2859
2860 Math Packages (IEEE Std 1076.2):
2861 `vhdl-math-types' : standardized types
2862 `vhdl-math-constants' : standardized constants
2863 `vhdl-math-functions' : standardized functions
2864 `vhdl-math-packages' : standardized packages
2865
2866 Forbidden words:
2867 `vhdl-verilog-keywords' : Verilog reserved words
2868
2869 NOTE: click `mouse-2' on variable names above (not in XEmacs).")
2870
2871 (defvar vhdl-doc-coding-style nil
2872 "For VHDL coding style and naming convention guidelines, see the following
2873 references:
2874
2875 \[1] Ben Cohen.
2876 \"VHDL Coding Styles and Methodologies\".
2877 Kluwer Academic Publishers, 1999.
2878 http://members.aol.com/vhdlcohen/vhdl/
2879
2880 \[2] Michael Keating and Pierre Bricaud.
2881 \"Reuse Methodology Manual\".
2882 Kluwer Academic Publishers, 1998.
2883 http://www.synopsys.com/products/reuse/rmm.html
2884
2885 \[3] European Space Agency.
2886 \"VHDL Modelling Guidelines\".
2887 ftp://ftp.estec.esa.nl/pub/vhdl/doc/ModelGuide.{pdf,ps}
2888
2889 Use variables `vhdl-highlight-special-words' and `vhdl-special-syntax-alist'
2890 to visually support naming conventions.")
2891
2892 (defun vhdl-doc-variable (variable)
2893 "Display VARIABLE's documentation in *Help* buffer."
2894 (interactive)
2895 (with-output-to-temp-buffer "*Help*"
2896 (princ (documentation-property variable 'variable-documentation))
2897 (unless (string-match "XEmacs" emacs-version)
2898 (help-setup-xref (list #'vhdl-doc-variable variable) (interactive-p)))
2899 (save-excursion
2900 (set-buffer standard-output)
2901 (help-mode))
2902 (print-help-return-message)))
2903
2904 (defun vhdl-doc-mode ()
2905 "Display VHDL mode documentation in *Help* buffer."
2906 (interactive)
2907 (with-output-to-temp-buffer "*Help*"
2908 (princ mode-name)
2909 (princ " mode:\n")
2910 (princ (documentation 'vhdl-mode))
2911 (unless (string-match "XEmacs" emacs-version)
2912 (help-setup-xref (list #'vhdl-doc-mode) (interactive-p)))
2913 (save-excursion
2914 (set-buffer standard-output)
2915 (help-mode))
2916 (print-help-return-message)))
2917
2918
2919 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2920 ;;; Keywords and standardized words
2921 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2922
2923 (defconst vhdl-93-keywords
2924 '(
2925 "abs" "access" "after" "alias" "all" "and" "architecture" "array"
2926 "assert" "attribute"
2927 "begin" "block" "body" "buffer" "bus"
2928 "case" "component" "configuration" "constant"
2929 "disconnect" "downto"
2930 "else" "elsif" "end" "entity" "exit"
2931 "file" "for" "function"
2932 "generate" "generic" "group" "guarded"
2933 "if" "impure" "in" "inertial" "inout" "is"
2934 "label" "library" "linkage" "literal" "loop"
2935 "map" "mod"
2936 "nand" "new" "next" "nor" "not" "null"
2937 "of" "on" "open" "or" "others" "out"
2938 "package" "port" "postponed" "procedure" "process" "pure"
2939 "range" "record" "register" "reject" "rem" "report" "return"
2940 "rol" "ror"
2941 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
2942 "then" "to" "transport" "type"
2943 "unaffected" "units" "until" "use"
2944 "variable"
2945 "wait" "when" "while" "with"
2946 "xnor" "xor"
2947 )
2948 "List of VHDL'93 keywords.")
2949
2950 (defconst vhdl-ams-keywords
2951 '(
2952 "across" "break" "limit" "nature" "noise" "procedural" "quantity"
2953 "reference" "spectrum" "subnature" "terminal" "through"
2954 "tolerance"
2955 )
2956 "List of VHDL-AMS keywords.")
2957
2958 (defconst vhdl-verilog-keywords
2959 '(
2960 "`define" "`else" "`endif" "`ifdef" "`include" "`timescale" "`undef"
2961 "always" "and" "assign" "begin" "buf" "bufif0" "bufif1"
2962 "case" "casex" "casez" "cmos" "deassign" "default" "defparam" "disable"
2963 "edge" "else" "end" "endattribute" "endcase" "endfunction" "endmodule"
2964 "endprimitive" "endspecify" "endtable" "endtask" "event"
2965 "for" "force" "forever" "fork" "function"
2966 "highz0" "highz1" "if" "initial" "inout" "input" "integer" "join" "large"
2967 "macromodule" "makefile" "medium" "module"
2968 "nand" "negedge" "nmos" "nor" "not" "notif0" "notif1" "or" "output"
2969 "parameter" "pmos" "posedge" "primitive" "pull0" "pull1" "pulldown"
2970 "pullup"
2971 "rcmos" "real" "realtime" "reg" "release" "repeat" "rnmos" "rpmos" "rtran"
2972 "rtranif0" "rtranif1"
2973 "scalared" "signed" "small" "specify" "specparam" "strength" "strong0"
2974 "strong1" "supply" "supply0" "supply1"
2975 "table" "task" "time" "tran" "tranif0" "tranif1" "tri" "tri0" "tri1"
2976 "triand" "trior" "trireg"
2977 "vectored" "wait" "wand" "weak0" "weak1" "while" "wire" "wor" "xnor" "xor"
2978 )
2979 "List of Verilog keywords as candidate for additional reserved words.")
2980
2981 (defconst vhdl-93-types
2982 '(
2983 "boolean" "bit" "bit_vector" "character" "severity_level" "integer"
2984 "real" "time" "natural" "positive" "string" "line" "text" "side"
2985 "unsigned" "signed" "delay_length" "file_open_kind" "file_open_status"
2986 "std_logic" "std_logic_vector"
2987 "std_ulogic" "std_ulogic_vector"
2988 )
2989 "List of VHDL'93 standardized types.")
2990
2991 (defconst vhdl-ams-types
2992 '(
2993 "domain_type" "real_vector"
2994 )
2995 "List of VHDL-AMS standardized types.")
2996
2997 (defconst vhdl-math-types
2998 '(
2999 "complex" "complex_polar"
3000 )
3001 "List of Math Packages standardized types.")
3002
3003 (defconst vhdl-93-attributes
3004 '(
3005 "base" "left" "right" "high" "low" "pos" "val" "succ"
3006 "pred" "leftof" "rightof" "range" "reverse_range"
3007 "length" "delayed" "stable" "quiet" "transaction"
3008 "event" "active" "last_event" "last_active" "last_value"
3009 "driving" "driving_value" "ascending" "value" "image"
3010 "simple_name" "instance_name" "path_name"
3011 "foreign"
3012 )
3013 "List of VHDL'93 standardized attributes.")
3014
3015 (defconst vhdl-ams-attributes
3016 '(
3017 "across" "through"
3018 "reference" "contribution" "tolerance"
3019 "dot" "integ" "delayed" "above" "zoh" "ltf" "ztf"
3020 "ramp" "slew"
3021 )
3022 "List of VHDL-AMS standardized attributes.")
3023
3024 (defconst vhdl-93-enum-values
3025 '(
3026 "true" "false"
3027 "note" "warning" "error" "failure"
3028 "read_mode" "write_mode" "append_mode"
3029 "open_ok" "status_error" "name_error" "mode_error"
3030 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
3031 "right" "left"
3032 )
3033 "List of VHDL'93 standardized enumeration values.")
3034
3035 (defconst vhdl-ams-enum-values
3036 '(
3037 "quiescent_domain" "time_domain" "frequency_domain"
3038 )
3039 "List of VHDL-AMS standardized enumeration values.")
3040
3041 (defconst vhdl-math-constants
3042 '(
3043 "math_e" "math_1_over_e"
3044 "math_pi" "math_two_pi" "math_1_over_pi"
3045 "math_half_pi" "math_q_pi" "math_3_half_pi"
3046 "math_log_of_2" "math_log_of_10" "math_log2_of_e" "math_log10_of_e"
3047 "math_sqrt2" "math_sqrt1_2" "math_sqrt_pi"
3048 "math_deg_to_rad" "math_rad_to_deg"
3049 "cbase_1" "cbase_j" "czero"
3050 )
3051 "List of Math Packages standardized constants.")
3052
3053 (defconst vhdl-93-functions
3054 '(
3055 "now" "resolved" "rising_edge" "falling_edge"
3056 "read" "readline" "write" "writeline" "endfile"
3057 "resize" "is_X" "std_match"
3058 "shift_left" "shift_right" "rotate_left" "rotate_right"
3059 "to_unsigned" "to_signed" "to_integer"
3060 "to_stdLogicVector" "to_stdULogic" "to_stdULogicVector"
3061 "to_bit" "to_bitVector" "to_X01" "to_X01Z" "to_UX01" "to_01"
3062 "conv_unsigned" "conv_signed" "conv_integer" "conv_std_logic_vector"
3063 "shl" "shr" "ext" "sxt"
3064 )
3065 "List of VHDL'93 standardized functions.")
3066
3067 (defconst vhdl-ams-functions
3068 '(
3069 "frequency"
3070 )
3071 "List of VHDL-AMS standardized functions.")
3072
3073 (defconst vhdl-math-functions
3074 '(
3075 "sign" "ceil" "floor" "round" "trunc" "fmax" "fmin" "uniform"
3076 "sqrt" "cbrt" "exp" "log"
3077 "sin" "cos" "tan" "arcsin" "arccos" "arctan"
3078 "sinh" "cosh" "tanh" "arcsinh" "arccosh" "arctanh"
3079 "cmplx" "complex_to_polar" "polar_to_complex" "arg" "conj"
3080 )
3081 "List of Math Packages standardized functions.")
3082
3083 (defconst vhdl-93-packages
3084 '(
3085 "std_logic_1164" "numeric_std" "numeric_bit"
3086 "standard" "textio"
3087 "std_logic_arith" "std_logic_signed" "std_logic_unsigned"
3088 "std_logic_misc" "std_logic_textio"
3089 "ieee" "std" "work"
3090 )
3091 "List of VHDL'93 standardized packages and libraries.")
3092
3093 (defconst vhdl-math-packages
3094 '(
3095 "math_real" "math_complex"
3096 )
3097 "List of Math Packages standardized packages and libraries.")
3098
3099 (defvar vhdl-keywords nil
3100 "List of VHDL keywords.")
3101
3102 (defvar vhdl-types nil
3103 "List of VHDL standardized types.")
3104
3105 (defvar vhdl-attributes nil
3106 "List of VHDL standardized attributes.")
3107
3108 (defvar vhdl-enum-values nil
3109 "List of VHDL standardized enumeration values.")
3110
3111 (defvar vhdl-constants nil
3112 "List of VHDL standardized constants.")
3113
3114 (defvar vhdl-functions nil
3115 "List of VHDL standardized functions.")
3116
3117 (defvar vhdl-packages nil
3118 "List of VHDL standardized packages and libraries.")
3119
3120 (defvar vhdl-reserved-words nil
3121 "List of additional reserved words.")
3122
3123 (defvar vhdl-keywords-regexp nil
3124 "Regexp for VHDL keywords.")
3125
3126 (defvar vhdl-types-regexp nil
3127 "Regexp for VHDL standardized types.")
3128
3129 (defvar vhdl-attributes-regexp nil
3130 "Regexp for VHDL standardized attributes.")
3131
3132 (defvar vhdl-enum-values-regexp nil
3133 "Regexp for VHDL standardized enumeration values.")
3134
3135 (defvar vhdl-functions-regexp nil
3136 "Regexp for VHDL standardized functions.")
3137
3138 (defvar vhdl-packages-regexp nil
3139 "Regexp for VHDL standardized packages and libraries.")
3140
3141 (defvar vhdl-reserved-words-regexp nil
3142 "Regexp for additional reserved words.")
3143
3144 (defun vhdl-words-init ()
3145 "Initialize reserved words."
3146 (setq vhdl-keywords
3147 (append vhdl-93-keywords
3148 (when (vhdl-standard-p 'ams) vhdl-ams-keywords)))
3149 (setq vhdl-types
3150 (append vhdl-93-types
3151 (when (vhdl-standard-p 'ams) vhdl-ams-types)
3152 (when (vhdl-standard-p 'math) vhdl-math-types)))
3153 (setq vhdl-attributes
3154 (append vhdl-93-attributes
3155 (when (vhdl-standard-p 'ams) vhdl-ams-attributes)))
3156 (setq vhdl-enum-values
3157 (append vhdl-93-enum-values
3158 (when (vhdl-standard-p 'ams) vhdl-ams-enum-values)))
3159 (setq vhdl-constants
3160 (append (when (vhdl-standard-p 'math) vhdl-math-constants)))
3161 (setq vhdl-functions
3162 (append vhdl-93-functions
3163 (when (vhdl-standard-p 'ams) vhdl-ams-functions)
3164 (when (vhdl-standard-p 'math) vhdl-math-functions)))
3165 (setq vhdl-packages
3166 (append vhdl-93-packages
3167 (when (vhdl-standard-p 'math) vhdl-math-packages)))
3168 (setq vhdl-reserved-words
3169 (append (when vhdl-highlight-forbidden-words vhdl-forbidden-words)
3170 (when vhdl-highlight-verilog-keywords vhdl-verilog-keywords)
3171 '("")))
3172 (setq vhdl-keywords-regexp
3173 (concat "\\<\\(" (regexp-opt vhdl-keywords) "\\)\\>"))
3174 (setq vhdl-types-regexp
3175 (concat "\\<\\(" (regexp-opt vhdl-types) "\\)\\>"))
3176 (setq vhdl-attributes-regexp
3177 (concat "\\<\\(" (regexp-opt vhdl-attributes) "\\)\\>"))
3178 (setq vhdl-enum-values-regexp
3179 (concat "\\<\\(" (regexp-opt vhdl-enum-values) "\\)\\>"))
3180 (setq vhdl-functions-regexp
3181 (concat "\\<\\(" (regexp-opt vhdl-functions) "\\)\\>"))
3182 (setq vhdl-packages-regexp
3183 (concat "\\<\\(" (regexp-opt vhdl-packages) "\\)\\>"))
3184 (setq vhdl-reserved-words-regexp
3185 (concat "\\<\\("
3186 (unless (equal vhdl-forbidden-syntax "")
3187 (concat vhdl-forbidden-syntax "\\|"))
3188 (regexp-opt vhdl-reserved-words)
3189 "\\)\\>"))
3190 (vhdl-abbrev-list-init))
3191
3192 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3193 ;; Words to expand
3194
3195 (defvar vhdl-abbrev-list nil
3196 "Predefined abbreviations for VHDL.")
3197
3198 (defun vhdl-abbrev-list-init ()
3199 (setq vhdl-abbrev-list
3200 (append
3201 (list vhdl-upper-case-keywords) vhdl-keywords
3202 (list vhdl-upper-case-types) vhdl-types
3203 (list vhdl-upper-case-attributes) vhdl-attributes
3204 (list vhdl-upper-case-enum-values) vhdl-enum-values
3205 (list vhdl-upper-case-constants) vhdl-constants
3206 (list nil) vhdl-functions
3207 (list nil) vhdl-packages)))
3208
3209 ;; initialize reserved words for VHDL Mode
3210 (vhdl-words-init)
3211
3212
3213 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3214 ;;; Syntax analysis and indentation
3215 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3216
3217 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3218 ;; Syntax analysis
3219
3220 ;; constant regular expressions for looking at various constructs
3221
3222 (defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
3223 "Regexp describing a VHDL symbol.
3224 We cannot use just `word' syntax class since `_' cannot be in word
3225 class. Putting underscore in word class breaks forward word movement
3226 behavior that users are familiar with.")
3227
3228 (defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
3229 "Regexp describing a case statement header key.")
3230
3231 (defconst vhdl-label-key
3232 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
3233 "Regexp describing a VHDL label.")
3234
3235 ;; Macro definitions:
3236
3237 (defmacro vhdl-point (position)
3238 "Return the value of point at certain commonly referenced POSITIONs.
3239 POSITION can be one of the following symbols:
3240
3241 bol -- beginning of line
3242 eol -- end of line
3243 bod -- beginning of defun
3244 boi -- back to indentation
3245 eoi -- last whitespace on line
3246 ionl -- indentation of next line
3247 iopl -- indentation of previous line
3248 bonl -- beginning of next line
3249 bopl -- beginning of previous line
3250
3251 This function does not modify point or mark."
3252 (or (and (eq 'quote (car-safe position))
3253 (null (cdr (cdr position))))
3254 (error "Bad buffer position requested: %s" position))
3255 (setq position (nth 1 position))
3256 `(let ((here (point)))
3257 ,@(cond
3258 ((eq position 'bol) '((beginning-of-line)))
3259 ((eq position 'eol) '((end-of-line)))
3260 ((eq position 'bod) '((save-match-data
3261 (vhdl-beginning-of-defun))))
3262 ((eq position 'boi) '((back-to-indentation)))
3263 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
3264 ((eq position 'bonl) '((forward-line 1)))
3265 ((eq position 'bopl) '((forward-line -1)))
3266 ((eq position 'iopl)
3267 '((forward-line -1)
3268 (back-to-indentation)))
3269 ((eq position 'ionl)
3270 '((forward-line 1)
3271 (back-to-indentation)))
3272 (t (error "Unknown buffer position requested: %s" position))
3273 )
3274 (prog1
3275 (point)
3276 (goto-char here))
3277 ;; workaround for an Emacs18 bug -- blech! Well, at least it
3278 ;; doesn't hurt for v19
3279 ,@nil
3280 ))
3281
3282 (defmacro vhdl-safe (&rest body)
3283 "Safely execute BODY, return nil if an error occurred."
3284 `(condition-case nil
3285 (progn ,@body)
3286 (error nil)))
3287
3288 (defmacro vhdl-add-syntax (symbol &optional relpos)
3289 "A simple macro to append the syntax in SYMBOL to the syntax list.
3290 Try to increase performance by using this macro."
3291 `(setq vhdl-syntactic-context
3292 (cons (cons ,symbol ,relpos) vhdl-syntactic-context)))
3293
3294 (defmacro vhdl-has-syntax (symbol)
3295 "A simple macro to return check the syntax list.
3296 Try to increase performance by using this macro."
3297 `(assoc ,symbol vhdl-syntactic-context))
3298
3299 ;; Syntactic element offset manipulation:
3300
3301 (defun vhdl-read-offset (langelem)
3302 "Read new offset value for LANGELEM from minibuffer.
3303 Return a legal value only."
3304 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
3305 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
3306 (prompt "Offset: ")
3307 offset input interned)
3308 (while (not offset)
3309 (setq input (read-string prompt oldoff)
3310 offset (cond ((string-equal "+" input) '+)
3311 ((string-equal "-" input) '-)
3312 ((string-equal "++" input) '++)
3313 ((string-equal "--" input) '--)
3314 ((string-match "^-?[0-9]+$" input)
3315 (string-to-int input))
3316 ((fboundp (setq interned (intern input)))
3317 interned)
3318 ((boundp interned) interned)
3319 ;; error, but don't signal one, keep trying
3320 ;; to read an input value
3321 (t (ding)
3322 (setq prompt errmsg)
3323 nil))))
3324 offset))
3325
3326 (defun vhdl-set-offset (symbol offset &optional add-p)
3327 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
3328 SYMBOL is the syntactic element symbol to change and OFFSET is the new
3329 offset for that syntactic element. Optional ADD says to add SYMBOL to
3330 `vhdl-offsets-alist' if it doesn't already appear there."
3331 (interactive
3332 (let* ((langelem
3333 (intern (completing-read
3334 (concat "Syntactic symbol to change"
3335 (if current-prefix-arg " or add" "")
3336 ": ")
3337 (mapcar
3338 (function
3339 (lambda (langelem)
3340 (cons (format "%s" (car langelem)) nil)))
3341 vhdl-offsets-alist)
3342 nil (not current-prefix-arg)
3343 ;; initial contents tries to be the last element
3344 ;; on the syntactic analysis list for the current
3345 ;; line
3346 (let* ((syntax (vhdl-get-syntactic-context))
3347 (len (length syntax))
3348 (ic (format "%s" (car (nth (1- len) syntax)))))
3349 ic)
3350 )))
3351 (offset (vhdl-read-offset langelem)))
3352 (list langelem offset current-prefix-arg)))
3353 ;; sanity check offset
3354 (or (eq offset '+)
3355 (eq offset '-)
3356 (eq offset '++)
3357 (eq offset '--)
3358 (integerp offset)
3359 (fboundp offset)
3360 (boundp offset)
3361 (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
3362 offset))
3363 (let ((entry (assq symbol vhdl-offsets-alist)))
3364 (if entry
3365 (setcdr entry offset)
3366 (if add-p
3367 (setq vhdl-offsets-alist
3368 (cons (cons symbol offset) vhdl-offsets-alist))
3369 (error "%s is not a valid syntactic symbol" symbol))))
3370 (vhdl-keep-region-active))
3371
3372 (defun vhdl-set-style (style &optional local)
3373 "Set `vhdl-mode' variables to use one of several different indentation styles.
3374 STYLE is a string representing the desired style and optional LOCAL is
3375 a flag which, if non-nil, means to make the style variables being
3376 changed buffer local, instead of the default, which is to set the
3377 global variables. Interactively, the flag comes from the prefix
3378 argument. The styles are chosen from the `vhdl-style-alist' variable."
3379 (interactive (list (completing-read "Use which VHDL indentation style? "
3380 vhdl-style-alist nil t)
3381 current-prefix-arg))
3382 (let ((vars (cdr (assoc style vhdl-style-alist))))
3383 (or vars
3384 (error "Invalid VHDL indentation style `%s'" style))
3385 ;; set all the variables
3386 (mapcar
3387 (function
3388 (lambda (varentry)
3389 (let ((var (car varentry))
3390 (val (cdr varentry)))
3391 (and local
3392 (make-local-variable var))
3393 ;; special case for vhdl-offsets-alist
3394 (if (not (eq var 'vhdl-offsets-alist))
3395 (set var val)
3396 ;; reset vhdl-offsets-alist to the default value first
3397 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
3398 ;; now set the langelems that are different
3399 (mapcar
3400 (function
3401 (lambda (langentry)
3402 (let ((langelem (car langentry))
3403 (offset (cdr langentry)))
3404 (vhdl-set-offset langelem offset)
3405 )))
3406 val))
3407 )))
3408 vars))
3409 (vhdl-keep-region-active))
3410
3411 (defun vhdl-get-offset (langelem)
3412 "Get offset from LANGELEM which is a cons cell of the form:
3413 \(SYMBOL . RELPOS). The symbol is matched against
3414 vhdl-offsets-alist and the offset found there is either returned,
3415 or added to the indentation at RELPOS. If RELPOS is nil, then
3416 the offset is simply returned."
3417 (let* ((symbol (car langelem))
3418 (relpos (cdr langelem))
3419 (match (assq symbol vhdl-offsets-alist))
3420 (offset (cdr-safe match)))
3421 ;; offset can be a number, a function, a variable, or one of the
3422 ;; symbols + or -
3423 (cond
3424 ((not match)
3425 (if vhdl-strict-syntax-p
3426 (error "Don't know how to indent a %s" symbol)
3427 (setq offset 0
3428 relpos 0)))
3429 ((eq offset '+) (setq offset vhdl-basic-offset))
3430 ((eq offset '-) (setq offset (- vhdl-basic-offset)))
3431 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
3432 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
3433 ((and (not (numberp offset))
3434 (fboundp offset))
3435 (setq offset (funcall offset langelem)))
3436 ((not (numberp offset))
3437 (setq offset (eval offset)))
3438 )
3439 (+ (if (and relpos
3440 (< relpos (vhdl-point 'bol)))
3441 (save-excursion
3442 (goto-char relpos)
3443 (current-column))
3444 0)
3445 offset)))
3446
3447 ;; Syntactic support functions:
3448
3449 ;; Returns `comment' if in a comment, `string' if in a string literal,
3450 ;; or nil if not in a literal at all. Optional LIM is used as the
3451 ;; backward limit of the search. If omitted, or nil, (point-min) is
3452 ;; used.
3453
3454 (defun vhdl-in-literal (&optional lim)
3455 "Determine if point is in a VHDL literal."
3456 (save-excursion
3457 (let ((state (parse-partial-sexp (vhdl-point 'bol) (point))))
3458 (cond
3459 ((nth 3 state) 'string)
3460 ((nth 4 state) 'comment)
3461 (t nil)))))
3462
3463 ;; This is the best we can do in Win-Emacs.
3464 (defun vhdl-win-il (&optional lim)
3465 "Determine if point is in a VHDL literal."
3466 (save-excursion
3467 (let* ((here (point))
3468 (state nil)
3469 (match nil)
3470 (lim (or lim (vhdl-point 'bod))))
3471 (goto-char lim )
3472 (while (< (point) here)
3473 (setq match
3474 (and (re-search-forward "--\\|[\"']"
3475 here 'move)
3476 (buffer-substring (match-beginning 0) (match-end 0))))
3477 (setq state
3478 (cond
3479 ;; no match
3480 ((null match) nil)
3481 ;; looking at the opening of a VHDL style comment
3482 ((string= "--" match)
3483 (if (<= here (progn (end-of-line) (point))) 'comment))
3484 ;; looking at the opening of a double quote string
3485 ((string= "\"" match)
3486 (if (not (save-restriction
3487 ;; this seems to be necessary since the
3488 ;; re-search-forward will not work without it
3489 (narrow-to-region (point) here)
3490 (re-search-forward
3491 ;; this regexp matches a double quote
3492 ;; which is preceded by an even number
3493 ;; of backslashes, including zero
3494 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
3495 'string))
3496 ;; looking at the opening of a single quote string
3497 ((string= "'" match)
3498 (if (not (save-restriction
3499 ;; see comments from above
3500 (narrow-to-region (point) here)
3501 (re-search-forward
3502 ;; this matches a single quote which is
3503 ;; preceded by zero or two backslashes.
3504 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
3505 here 'move)))
3506 'string))
3507 (t nil)))
3508 ) ; end-while
3509 state)))
3510
3511 (and (string-match "Win-Emacs" emacs-version)
3512 (fset 'vhdl-in-literal 'vhdl-win-il))
3513
3514 ;; Skipping of "syntactic whitespace". Syntactic whitespace is
3515 ;; defined as lexical whitespace or comments. Search no farther back
3516 ;; or forward than optional LIM. If LIM is omitted, (point-min) is
3517 ;; used for backward skipping, (point-max) is used for forward
3518 ;; skipping.
3519
3520 (defun vhdl-forward-syntactic-ws (&optional lim)
3521 "Forward skip of syntactic whitespace."
3522 (save-restriction
3523 (let* ((lim (or lim (point-max)))
3524 (here lim)
3525 (hugenum (point-max)))
3526 (narrow-to-region lim (point))
3527 (while (/= here (point))
3528 (setq here (point))
3529 (forward-comment hugenum))
3530 )))
3531
3532 ;; This is the best we can do in Win-Emacs.
3533 (defun vhdl-win-fsws (&optional lim)
3534 "Forward skip syntactic whitespace for Win-Emacs."
3535 (let ((lim (or lim (point-max)))
3536 stop)
3537 (while (not stop)
3538 (skip-chars-forward " \t\n\r\f" lim)
3539 (cond
3540 ;; vhdl comment
3541 ((looking-at "--") (end-of-line))
3542 ;; none of the above
3543 (t (setq stop t))
3544 ))))
3545
3546 (and (string-match "Win-Emacs" emacs-version)
3547 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
3548
3549 (defun vhdl-backward-syntactic-ws (&optional lim)
3550 "Backward skip over syntactic whitespace."
3551 (save-restriction
3552 (let* ((lim (or lim (point-min)))
3553 (here lim)
3554 (hugenum (- (point-max))))
3555 (if (< lim (point))
3556 (progn
3557 (narrow-to-region lim (point))
3558 (while (/= here (point))
3559 (setq here (point))
3560 (forward-comment hugenum)
3561 )))
3562 )))
3563
3564 ;; This is the best we can do in Win-Emacs.
3565 (defun vhdl-win-bsws (&optional lim)
3566 "Backward skip syntactic whitespace for Win-Emacs."
3567 (let ((lim (or lim (vhdl-point 'bod)))
3568 stop)
3569 (while (not stop)
3570 (skip-chars-backward " \t\n\r\f" lim)
3571 (cond
3572 ;; vhdl comment
3573 ((eq (vhdl-in-literal lim) 'comment)
3574 (skip-chars-backward "^-" lim)
3575 (skip-chars-backward "-" lim)
3576 (while (not (or (and (= (following-char) ?-)
3577 (= (char-after (1+ (point))) ?-))
3578 (<= (point) lim)))
3579 (skip-chars-backward "^-" lim)
3580 (skip-chars-backward "-" lim)))
3581 ;; none of the above
3582 (t (setq stop t))
3583 ))))
3584
3585 (and (string-match "Win-Emacs" emacs-version)
3586 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
3587
3588 ;; Functions to help finding the correct indentation column:
3589
3590 (defun vhdl-first-word (point)
3591 "If the keyword at POINT is at boi, then return (current-column) at
3592 that point, else nil."
3593 (save-excursion
3594 (and (goto-char point)
3595 (eq (point) (vhdl-point 'boi))
3596 (current-column))))
3597
3598 (defun vhdl-last-word (point)
3599 "If the keyword at POINT is at eoi, then return (current-column) at
3600 that point, else nil."
3601 (save-excursion
3602 (and (goto-char point)
3603 (save-excursion (or (eq (progn (forward-sexp) (point))
3604 (vhdl-point 'eoi))
3605 (looking-at "\\s-*\\(--\\)?")))
3606 (current-column))))
3607
3608 ;; Core syntactic evaluation functions:
3609
3610 (defconst vhdl-libunit-re
3611 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
3612
3613 (defun vhdl-libunit-p ()
3614 (and
3615 (save-excursion
3616 (forward-sexp)
3617 (skip-chars-forward " \t\n")
3618 (not (looking-at "is\\b[^_]")))
3619 (save-excursion
3620 (backward-sexp)
3621 (and (not (looking-at "use\\b[^_]"))
3622 (progn
3623 (forward-sexp)
3624 (vhdl-forward-syntactic-ws)
3625 (/= (following-char) ?:))))
3626 ))
3627
3628 (defconst vhdl-defun-re
3629 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedural\\|procedure\\|function\\)\\b[^_]")
3630
3631 (defun vhdl-defun-p ()
3632 (save-excursion
3633 (if (looking-at "block\\|process\\|procedural")
3634 ;; "block", "process", "procedural":
3635 (save-excursion
3636 (backward-sexp)
3637 (not (looking-at "end\\s-+\\w")))
3638 ;; "architecture", "configuration", "entity",
3639 ;; "package", "procedure", "function":
3640 t)))
3641
3642 (defun vhdl-corresponding-defun ()
3643 "If the word at the current position corresponds to a \"defun\"
3644 keyword, then return a string that can be used to find the
3645 corresponding \"begin\" keyword, else return nil."
3646 (save-excursion
3647 (and (looking-at vhdl-defun-re)
3648 (vhdl-defun-p)
3649 (if (looking-at "block\\|process\\|procedural")
3650 ;; "block", "process". "procedural:
3651 (buffer-substring (match-beginning 0) (match-end 0))
3652 ;; "architecture", "configuration", "entity", "package",
3653 ;; "procedure", "function":
3654 "is"))))
3655
3656 (defconst vhdl-begin-fwd-re
3657 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
3658 "A regular expression for searching forward that matches all known
3659 \"begin\" keywords.")
3660
3661 (defconst vhdl-begin-bwd-re
3662 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b[^_]"
3663 "A regular expression for searching backward that matches all known
3664 \"begin\" keywords.")
3665
3666 (defun vhdl-begin-p (&optional lim)
3667 "Return t if we are looking at a real \"begin\" keyword.
3668 Assumes that the caller will make sure that we are looking at
3669 vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
3670 the middle of an identifier that just happens to contain a \"begin\"
3671 keyword."
3672 (cond
3673 ;; "[architecture|case|configuration|entity|package|
3674 ;; procedure|function] ... is":
3675 ((and (looking-at "i")
3676 (save-excursion
3677 ;; Skip backward over first sexp (needed to skip over a
3678 ;; procedure interface list, and is harmless in other
3679 ;; situations). Note that we need "return" in the
3680 ;; following search list so that we don't run into
3681 ;; semicolons in the function interface list.
3682 (backward-sexp)
3683 (let (foundp)
3684 (while (and (not foundp)
3685 (re-search-backward
3686 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|procedural\\|block\\)\\b[^_]"
3687 lim 'move))
3688 (if (or (= (preceding-char) ?_)
3689 (vhdl-in-literal lim))
3690 (backward-char)
3691 (setq foundp t))))
3692 (and (/= (following-char) ?\;)
3693 (not (looking-at "is\\|begin\\|process\\|procedural\\|block")))))
3694 t)
3695 ;; "begin", "then":
3696 ((looking-at "be\\|t")
3697 t)
3698 ;; "else":
3699 ((and (looking-at "e")
3700 ;; make sure that the "else" isn't inside a
3701 ;; conditional signal assignment.
3702 (save-excursion
3703 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3704 (or (eq (following-char) ?\;)
3705 (eq (point) lim))))
3706 t)
3707 ;; "block", "generate", "loop", "process", "procedural",
3708 ;; "units", "record":
3709 ((and (looking-at "bl\\|[glpur]")
3710 (save-excursion
3711 (backward-sexp)
3712 (not (looking-at "end\\s-+\\w"))))
3713 t)
3714 ;; "component":
3715 ((and (looking-at "c")
3716 (save-excursion
3717 (backward-sexp)
3718 (not (looking-at "end\\s-+\\w")))
3719 ;; look out for the dreaded entity class in an attribute
3720 (save-excursion
3721 (vhdl-backward-syntactic-ws lim)
3722 (/= (preceding-char) ?:)))
3723 t)
3724 ;; "for" (inside configuration declaration):
3725 ((and (looking-at "f")
3726 (save-excursion
3727 (backward-sexp)
3728 (not (looking-at "end\\s-+\\w")))
3729 (vhdl-has-syntax 'configuration))
3730 t)
3731 ))
3732
3733 (defun vhdl-corresponding-mid (&optional lim)
3734 (cond
3735 ((looking-at "is\\|block\\|generate\\|process\\|procedural")
3736 "begin")
3737 ((looking-at "then")
3738 "<else>")
3739 (t
3740 "end")))
3741
3742 (defun vhdl-corresponding-end (&optional lim)
3743 "If the word at the current position corresponds to a \"begin\"
3744 keyword, then return a vector containing enough information to find
3745 the corresponding \"end\" keyword, else return nil. The keyword to
3746 search forward for is aref 0. The column in which the keyword must
3747 appear is aref 1 or nil if any column is suitable.
3748 Assumes that the caller will make sure that we are not in the middle
3749 of an identifier that just happens to contain a \"begin\" keyword."
3750 (save-excursion
3751 (and (looking-at vhdl-begin-fwd-re)
3752 (/= (preceding-char) ?_)
3753 (not (vhdl-in-literal lim))
3754 (vhdl-begin-p lim)
3755 (cond
3756 ;; "is", "generate", "loop":
3757 ((looking-at "[igl]")
3758 (vector "end"
3759 (and (vhdl-last-word (point))
3760 (or (vhdl-first-word (point))
3761 (save-excursion
3762 (vhdl-beginning-of-statement-1 lim)
3763 (vhdl-backward-skip-label lim)
3764 (vhdl-first-word (point)))))))
3765 ;; "begin", "else", "for":
3766 ((looking-at "be\\|[ef]")
3767 (vector "end"
3768 (and (vhdl-last-word (point))
3769 (or (vhdl-first-word (point))
3770 (save-excursion
3771 (vhdl-beginning-of-statement-1 lim)
3772 (vhdl-backward-skip-label lim)
3773 (vhdl-first-word (point)))))))
3774 ;; "component", "units", "record":
3775 ((looking-at "[cur]")
3776 ;; The first end found will close the block
3777 (vector "end" nil))
3778 ;; "block", "process", "procedural":
3779 ((looking-at "bl\\|p")
3780 (vector "end"
3781 (or (vhdl-first-word (point))
3782 (save-excursion
3783 (vhdl-beginning-of-statement-1 lim)
3784 (vhdl-backward-skip-label lim)
3785 (vhdl-first-word (point))))))
3786 ;; "then":
3787 ((looking-at "t")
3788 (vector "elsif\\|else\\|end\\s-+if"
3789 (and (vhdl-last-word (point))
3790 (or (vhdl-first-word (point))
3791 (save-excursion
3792 (vhdl-beginning-of-statement-1 lim)
3793 (vhdl-backward-skip-label lim)
3794 (vhdl-first-word (point)))))))
3795 ))))
3796
3797 (defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
3798
3799 (defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
3800
3801 (defun vhdl-end-p (&optional lim)
3802 "Return t if we are looking at a real \"end\" keyword.
3803 Assumes that the caller will make sure that we are looking at
3804 vhdl-end-fwd-re, and are not inside a literal, and that we are not in
3805 the middle of an identifier that just happens to contain an \"end\"
3806 keyword."
3807 (or (not (looking-at "else"))
3808 ;; make sure that the "else" isn't inside a conditional signal
3809 ;; assignment.
3810 (save-excursion
3811 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3812 (or (eq (following-char) ?\;)
3813 (eq (point) lim)))))
3814
3815 (defun vhdl-corresponding-begin (&optional lim)
3816 "If the word at the current position corresponds to an \"end\"
3817 keyword, then return a vector containing enough information to find
3818 the corresponding \"begin\" keyword, else return nil. The keyword to
3819 search backward for is aref 0. The column in which the keyword must
3820 appear is aref 1 or nil if any column is suitable. The supplementary
3821 keyword to search forward for is aref 2 or nil if this is not
3822 required. If aref 3 is t, then the \"begin\" keyword may be found in
3823 the middle of a statement.
3824 Assumes that the caller will make sure that we are not in the middle
3825 of an identifier that just happens to contain an \"end\" keyword."
3826 (save-excursion
3827 (let (pos)
3828 (if (and (looking-at vhdl-end-fwd-re)
3829 (not (vhdl-in-literal lim))
3830 (vhdl-end-p lim))
3831 (if (looking-at "el")
3832 ;; "else", "elsif":
3833 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
3834 ;; "end ...":
3835 (setq pos (point))
3836 (forward-sexp)
3837 (skip-chars-forward " \t\n")
3838 (cond
3839 ;; "end if":
3840 ((looking-at "if\\b[^_]")
3841 (vector "else\\|elsif\\|if"
3842 (vhdl-first-word pos)
3843 "else\\|then" nil))
3844 ;; "end component":
3845 ((looking-at "component\\b[^_]")
3846 (vector (buffer-substring (match-beginning 1)
3847 (match-end 1))
3848 (vhdl-first-word pos)
3849 nil nil))
3850 ;; "end units", "end record":
3851 ((looking-at "\\(units\\|record\\)\\b[^_]")
3852 (vector (buffer-substring (match-beginning 1)
3853 (match-end 1))
3854 (vhdl-first-word pos)
3855 nil t))
3856 ;; "end block", "end process", "end procedural":
3857 ((looking-at "\\(block\\|process\\|procedural\\)\\b[^_]")
3858 (vector "begin" (vhdl-first-word pos) nil nil))
3859 ;; "end case":
3860 ((looking-at "case\\b[^_]")
3861 (vector "case" (vhdl-first-word pos) "is" nil))
3862 ;; "end generate":
3863 ((looking-at "generate\\b[^_]")
3864 (vector "generate\\|for\\|if"
3865 (vhdl-first-word pos)
3866 "generate" nil))
3867 ;; "end loop":
3868 ((looking-at "loop\\b[^_]")
3869 (vector "loop\\|while\\|for"
3870 (vhdl-first-word pos)
3871 "loop" nil))
3872 ;; "end for" (inside configuration declaration):
3873 ((looking-at "for\\b[^_]")
3874 (vector "for" (vhdl-first-word pos) nil nil))
3875 ;; "end [id]":
3876 (t
3877 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
3878 (vhdl-first-word pos)
3879 ;; return an alist of (statement . keyword) mappings
3880 '(
3881 ;; "begin ... end [id]":
3882 ("begin" . nil)
3883 ;; "architecture ... is ... begin ... end [id]":
3884 ("architecture" . "is")
3885 ;; "configuration ... is ... end [id]":
3886 ("configuration" . "is")
3887 ;; "entity ... is ... end [id]":
3888 ("entity" . "is")
3889 ;; "package ... is ... end [id]":
3890 ("package" . "is")
3891 ;; "procedure ... is ... begin ... end [id]":
3892 ("procedure" . "is")
3893 ;; "function ... is ... begin ... end [id]":
3894 ("function" . "is")
3895 )
3896 nil))
3897 ))) ; "end ..."
3898 )))
3899
3900 (defconst vhdl-leader-re
3901 "\\b\\(block\\|component\\|process\\|procedural\\|for\\)\\b[^_]")
3902
3903 (defun vhdl-end-of-leader ()
3904 (save-excursion
3905 (cond ((looking-at "block\\|process\\|procedural")
3906 (if (save-excursion
3907 (forward-sexp)
3908 (skip-chars-forward " \t\n")
3909 (= (following-char) ?\())
3910 (forward-sexp 2)
3911 (forward-sexp))
3912 (point))
3913 ((looking-at "component")
3914 (forward-sexp 2)
3915 (point))
3916 ((looking-at "for")
3917 (forward-sexp 2)
3918 (skip-chars-forward " \t\n")
3919 (while (looking-at "[,:(]")
3920 (forward-sexp)
3921 (skip-chars-forward " \t\n"))
3922 (point))
3923 (t nil)
3924 )))
3925
3926 (defconst vhdl-trailer-re
3927 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
3928
3929 (defconst vhdl-statement-fwd-re
3930 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
3931 "A regular expression for searching forward that matches all known
3932 \"statement\" keywords.")
3933
3934 (defconst vhdl-statement-bwd-re
3935 "\\b\\(if\\|for\\|while\\)\\b[^_]"
3936 "A regular expression for searching backward that matches all known
3937 \"statement\" keywords.")
3938
3939 (defun vhdl-statement-p (&optional lim)
3940 "Return t if we are looking at a real \"statement\" keyword.
3941 Assumes that the caller will make sure that we are looking at
3942 vhdl-statement-fwd-re, and are not inside a literal, and that we are not
3943 in the middle of an identifier that just happens to contain a
3944 \"statement\" keyword."
3945 (cond
3946 ;; "for" ... "generate":
3947 ((and (looking-at "f")
3948 ;; Make sure it's the start of a parameter specification.
3949 (save-excursion
3950 (forward-sexp 2)
3951 (skip-chars-forward " \t\n")
3952 (looking-at "in\\b[^_]"))
3953 ;; Make sure it's not an "end for".
3954 (save-excursion
3955 (backward-sexp)
3956 (not (looking-at "end\\s-+\\w"))))
3957 t)
3958 ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
3959 ((and (looking-at "i")
3960 ;; Make sure it's not an "end if".
3961 (save-excursion
3962 (backward-sexp)
3963 (not (looking-at "end\\s-+\\w"))))
3964 t)
3965 ;; "while" ... "loop":
3966 ((looking-at "w")
3967 t)
3968 ))
3969
3970 (defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
3971 "Regexp describing a case statement alternative key.")
3972
3973 (defun vhdl-case-alternative-p (&optional lim)
3974 "Return t if we are looking at a real case alternative.
3975 Assumes that the caller will make sure that we are looking at
3976 vhdl-case-alternative-re, and are not inside a literal, and that
3977 we are not in the middle of an identifier that just happens to
3978 contain a \"when\" keyword."
3979 (save-excursion
3980 (let (foundp)
3981 (while (and (not foundp)
3982 (re-search-backward ";\\|<=" lim 'move))
3983 (if (or (= (preceding-char) ?_)
3984 (vhdl-in-literal lim))
3985 (backward-char)
3986 (setq foundp t)))
3987 (or (eq (following-char) ?\;)
3988 (eq (point) lim)))
3989 ))
3990
3991 ;; Core syntactic movement functions:
3992
3993 (defconst vhdl-b-t-b-re
3994 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
3995
3996 (defun vhdl-backward-to-block (&optional lim)
3997 "Move backward to the previous \"begin\" or \"end\" keyword."
3998 (let (foundp)
3999 (while (and (not foundp)
4000 (re-search-backward vhdl-b-t-b-re lim 'move))
4001 (if (or (= (preceding-char) ?_)
4002 (vhdl-in-literal lim))
4003 (backward-char)
4004 (cond
4005 ;; "begin" keyword:
4006 ((and (looking-at vhdl-begin-fwd-re)
4007 (/= (preceding-char) ?_)
4008 (vhdl-begin-p lim))
4009 (setq foundp 'begin))
4010 ;; "end" keyword:
4011 ((and (looking-at vhdl-end-fwd-re)
4012 (/= (preceding-char) ?_)
4013 (vhdl-end-p lim))
4014 (setq foundp 'end))
4015 ))
4016 )
4017 foundp
4018 ))
4019
4020 (defun vhdl-forward-sexp (&optional count lim)
4021 "Move forward across one balanced expression (sexp).
4022 With COUNT, do it that many times."
4023 (interactive "p")
4024 (let ((count (or count 1))
4025 (case-fold-search t)
4026 end-vec target)
4027 (save-excursion
4028 (while (> count 0)
4029 ;; skip whitespace
4030 (skip-chars-forward " \t\n")
4031 ;; Check for an unbalanced "end" keyword
4032 (if (and (looking-at vhdl-end-fwd-re)
4033 (/= (preceding-char) ?_)
4034 (not (vhdl-in-literal lim))
4035 (vhdl-end-p lim)
4036 (not (looking-at "else")))
4037 (error
4038 "Containing expression ends prematurely in vhdl-forward-sexp"))
4039 ;; If the current keyword is a "begin" keyword, then find the
4040 ;; corresponding "end" keyword.
4041 (if (setq end-vec (vhdl-corresponding-end lim))
4042 (let (
4043 ;; end-re is the statement keyword to search for
4044 (end-re
4045 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
4046 ;; column is either the statement keyword target column
4047 ;; or nil
4048 (column (aref end-vec 1))
4049 (eol (vhdl-point 'eol))
4050 foundp literal placeholder)
4051 ;; Look for the statement keyword.
4052 (while (and (not foundp)
4053 (re-search-forward end-re nil t)
4054 (setq placeholder (match-end 1))
4055 (goto-char (match-beginning 0)))
4056 ;; If we are in a literal, or not in the right target
4057 ;; column and not on the same line as the begin, then
4058 ;; try again.
4059 (if (or (and column
4060 (/= (current-indentation) column)
4061 (> (point) eol))
4062 (= (preceding-char) ?_)
4063 (setq literal (vhdl-in-literal lim)))
4064 (if (eq literal 'comment)
4065 (end-of-line)
4066 (forward-char))
4067 ;; An "else" keyword corresponds to both the opening brace
4068 ;; of the following sexp and the closing brace of the
4069 ;; previous sexp.
4070 (if (not (looking-at "else"))
4071 (goto-char placeholder))
4072 (setq foundp t))
4073 )
4074 (if (not foundp)
4075 (error "Unbalanced keywords in vhdl-forward-sexp"))
4076 )
4077 ;; If the current keyword is not a "begin" keyword, then just
4078 ;; perform the normal forward-sexp.
4079 (forward-sexp)
4080 )
4081 (setq count (1- count))
4082 )
4083 (setq target (point)))
4084 (goto-char target)
4085 nil))
4086
4087 (defun vhdl-backward-sexp (&optional count lim)
4088 "Move backward across one balanced expression (sexp).
4089 With COUNT, do it that many times. LIM bounds any required backward
4090 searches."
4091 (interactive "p")
4092 (let ((count (or count 1))
4093 (case-fold-search t)
4094 begin-vec target)
4095 (save-excursion
4096 (while (> count 0)
4097 ;; Perform the normal backward-sexp, unless we are looking at
4098 ;; "else" - an "else" keyword corresponds to both the opening brace
4099 ;; of the following sexp and the closing brace of the previous sexp.
4100 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
4101 (/= (preceding-char) ?_)
4102 (not (vhdl-in-literal lim)))
4103 nil
4104 (backward-sexp)
4105 (if (and (looking-at vhdl-begin-fwd-re)
4106 (/= (preceding-char) ?_)
4107 (not (vhdl-in-literal lim))
4108 (vhdl-begin-p lim))
4109 (error "Containing expression ends prematurely in vhdl-backward-sexp")))
4110 ;; If the current keyword is an "end" keyword, then find the
4111 ;; corresponding "begin" keyword.
4112 (if (and (setq begin-vec (vhdl-corresponding-begin lim))
4113 (/= (preceding-char) ?_))
4114 (let (
4115 ;; begin-re is the statement keyword to search for
4116 (begin-re
4117 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
4118 ;; column is either the statement keyword target column
4119 ;; or nil
4120 (column (aref begin-vec 1))
4121 ;; internal-p controls where the statement keyword can
4122 ;; be found.
4123 (internal-p (aref begin-vec 3))
4124 (last-backward (point)) last-forward
4125 foundp literal keyword)
4126 ;; Look for the statement keyword.
4127 (while (and (not foundp)
4128 (re-search-backward begin-re lim t)
4129 (setq keyword
4130 (buffer-substring (match-beginning 1)
4131 (match-end 1))))
4132 ;; If we are in a literal or in the wrong column,
4133 ;; then try again.
4134 (if (or (and column
4135 (and (/= (current-indentation) column)
4136 ;; possibly accept current-column as
4137 ;; well as current-indentation.
4138 (or (not internal-p)
4139 (/= (current-column) column))))
4140 (= (preceding-char) ?_)
4141 (vhdl-in-literal lim))
4142 (backward-char)
4143 ;; If there is a supplementary keyword, then
4144 ;; search forward for it.
4145 (if (and (setq begin-re (aref begin-vec 2))
4146 (or (not (listp begin-re))
4147 ;; If begin-re is an alist, then find the
4148 ;; element corresponding to the actual
4149 ;; keyword that we found.
4150 (progn
4151 (setq begin-re
4152 (assoc keyword begin-re))
4153 (and begin-re
4154 (setq begin-re (cdr begin-re))))))
4155 (and
4156 (setq begin-re
4157 (concat "\\b\\(" begin-re "\\)\\b[^_]"))
4158 (save-excursion
4159 (setq last-forward (point))
4160 ;; Look for the supplementary keyword
4161 ;; (bounded by the backward search start
4162 ;; point).
4163 (while (and (not foundp)
4164 (re-search-forward begin-re
4165 last-backward t)
4166 (goto-char (match-beginning 1)))
4167 ;; If we are in a literal, then try again.
4168 (if (or (= (preceding-char) ?_)
4169 (setq literal
4170 (vhdl-in-literal last-forward)))
4171 (if (eq literal 'comment)
4172 (goto-char
4173 (min (vhdl-point 'eol) last-backward))
4174 (forward-char))
4175 ;; We have found the supplementary keyword.
4176 ;; Save the position of the keyword in foundp.
4177 (setq foundp (point)))
4178 )
4179 foundp)
4180 ;; If the supplementary keyword was found, then
4181 ;; move point to the supplementary keyword.
4182 (goto-char foundp))
4183 ;; If there was no supplementary keyword, then
4184 ;; point is already at the statement keyword.
4185 (setq foundp t)))
4186 ) ; end of the search for the statement keyword
4187 (if (not foundp)
4188 (error "Unbalanced keywords in vhdl-backward-sexp"))
4189 ))
4190 (setq count (1- count))
4191 )
4192 (setq target (point)))
4193 (goto-char target)
4194 nil))
4195
4196 (defun vhdl-backward-up-list (&optional count limit)
4197 "Move backward out of one level of blocks.
4198 With argument, do this that many times."
4199 (interactive "p")
4200 (let ((count (or count 1))
4201 target)
4202 (save-excursion
4203 (while (> count 0)
4204 (if (looking-at vhdl-defun-re)
4205 (error "Unbalanced blocks"))
4206 (vhdl-backward-to-block limit)
4207 (setq count (1- count)))
4208 (setq target (point)))
4209 (goto-char target)))
4210
4211 (defun vhdl-end-of-defun (&optional count)
4212 "Move forward to the end of a VHDL defun."
4213 (interactive)
4214 (let ((case-fold-search t))
4215 (vhdl-beginning-of-defun)
4216 (if (not (looking-at "block\\|process\\|procedural"))
4217 (re-search-forward "\\bis\\b"))
4218 (vhdl-forward-sexp)))
4219
4220 (defun vhdl-mark-defun ()
4221 "Put mark at end of this \"defun\", point at beginning."
4222 (interactive)
4223 (let ((case-fold-search t))
4224 (push-mark)
4225 (vhdl-beginning-of-defun)
4226 (push-mark)
4227 (if (not (looking-at "block\\|process\\|procedural"))
4228 (re-search-forward "\\bis\\b"))
4229 (vhdl-forward-sexp)
4230 (exchange-point-and-mark)))
4231
4232 (defun vhdl-beginning-of-libunit ()
4233 "Move backward to the beginning of a VHDL library unit.
4234 Returns the location of the corresponding begin keyword, unless search
4235 stops due to beginning or end of buffer.
4236 Note that if point is between the \"libunit\" keyword and the
4237 corresponding \"begin\" keyword, then that libunit will not be
4238 recognised, and the search will continue backwards. If point is
4239 at the \"begin\" keyword, then the defun will be recognised. The
4240 returned point is at the first character of the \"libunit\" keyword."
4241 (let ((last-forward (point))
4242 (last-backward
4243 ;; Just in case we are actually sitting on the "begin"
4244 ;; keyword, allow for the keyword and an extra character,
4245 ;; as this will be used when looking forward for the
4246 ;; "begin" keyword.
4247 (save-excursion (forward-word 1) (1+ (point))))
4248 foundp literal placeholder)
4249 ;; Find the "libunit" keyword.
4250 (while (and (not foundp)
4251 (re-search-backward vhdl-libunit-re nil 'move))
4252 ;; If we are in a literal, or not at a real libunit, then try again.
4253 (if (or (= (preceding-char) ?_)
4254 (vhdl-in-literal (point-min))
4255 (not (vhdl-libunit-p)))
4256 (backward-char)
4257 ;; Find the corresponding "begin" keyword.
4258 (setq last-forward (point))
4259 (while (and (not foundp)
4260 (re-search-forward "\\bis\\b[^_]" last-backward t)
4261 (setq placeholder (match-beginning 0)))
4262 (if (or (= (preceding-char) ?_)
4263 (setq literal (vhdl-in-literal last-forward)))
4264 ;; It wasn't a real keyword, so keep searching.
4265 (if (eq literal 'comment)
4266 (goto-char
4267 (min (vhdl-point 'eol) last-backward))
4268 (forward-char))
4269 ;; We have found the begin keyword, loop will exit.
4270 (setq foundp placeholder)))
4271 ;; Go back to the libunit keyword
4272 (goto-char last-forward)))
4273 foundp))
4274
4275 (defun vhdl-beginning-of-defun (&optional count)
4276 "Move backward to the beginning of a VHDL defun.
4277 With argument, do it that many times.
4278 Returns the location of the corresponding begin keyword, unless search
4279 stops due to beginning or end of buffer."
4280 ;; Note that if point is between the "defun" keyword and the
4281 ;; corresponding "begin" keyword, then that defun will not be
4282 ;; recognised, and the search will continue backwards. If point is
4283 ;; at the "begin" keyword, then the defun will be recognised. The
4284 ;; returned point is at the first character of the "defun" keyword.
4285 (interactive "p")
4286 (let ((count (or count 1))
4287 (case-fold-search t)
4288 (last-forward (point))
4289 foundp)
4290 (while (> count 0)
4291 (setq foundp nil)
4292 (goto-char last-forward)
4293 (let ((last-backward
4294 ;; Just in case we are actually sitting on the "begin"
4295 ;; keyword, allow for the keyword and an extra character,
4296 ;; as this will be used when looking forward for the
4297 ;; "begin" keyword.
4298 (save-excursion (forward-word 1) (1+ (point))))
4299 begin-string literal)
4300 (while (and (not foundp)
4301 (re-search-backward vhdl-defun-re nil 'move))
4302 ;; If we are in a literal, then try again.
4303 (if (or (= (preceding-char) ?_)
4304 (vhdl-in-literal (point-min)))
4305 (backward-char)
4306 (if (setq begin-string (vhdl-corresponding-defun))
4307 ;; This is a real defun keyword.
4308 ;; Find the corresponding "begin" keyword.
4309 ;; Look for the begin keyword.
4310 (progn
4311 ;; Save the search start point.
4312 (setq last-forward (point))
4313 (while (and (not foundp)
4314 (search-forward begin-string last-backward t))
4315 (if (or (= (preceding-char) ?_)
4316 (save-match-data
4317 (setq literal (vhdl-in-literal last-forward))))
4318 ;; It wasn't a real keyword, so keep searching.
4319 (if (eq literal 'comment)
4320 (goto-char
4321 (min (vhdl-point 'eol) last-backward))
4322 (forward-char))
4323 ;; We have found the begin keyword, loop will exit.
4324 (setq foundp (match-beginning 0)))
4325 )
4326 ;; Go back to the defun keyword
4327 (goto-char last-forward)) ; end search for begin keyword
4328 ))
4329 ) ; end of the search for the defun keyword
4330 )
4331 (setq count (1- count))
4332 )
4333 (vhdl-keep-region-active)
4334 foundp))
4335
4336 (defun vhdl-beginning-of-statement (&optional count lim)
4337 "Go to the beginning of the innermost VHDL statement.
4338 With prefix arg, go back N - 1 statements. If already at the
4339 beginning of a statement then go to the beginning of the preceding
4340 one. If within a string or comment, or next to a comment (only
4341 whitespace between), move by sentences instead of statements.
4342
4343 When called from a program, this function takes 2 optional args: the
4344 prefix arg, and a buffer position limit which is the farthest back to
4345 search."
4346 (interactive "p")
4347 (let ((count (or count 1))
4348 (case-fold-search t)
4349 (lim (or lim (point-min)))
4350 (here (point))
4351 state)
4352 (save-excursion
4353 (goto-char lim)
4354 (setq state (parse-partial-sexp (point) here nil nil)))
4355 (if (and (interactive-p)
4356 (or (nth 3 state)
4357 (nth 4 state)
4358 (looking-at (concat "[ \t]*" comment-start-skip))))
4359 (forward-sentence (- count))
4360 (while (> count 0)
4361 (vhdl-beginning-of-statement-1 lim)
4362 (setq count (1- count))))
4363 ;; its possible we've been left up-buf of lim
4364 (goto-char (max (point) lim))
4365 )
4366 (vhdl-keep-region-active))
4367
4368 (defconst vhdl-e-o-s-re
4369 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
4370
4371 (defun vhdl-end-of-statement ()
4372 "Very simple implementation."
4373 (interactive)
4374 (re-search-forward vhdl-e-o-s-re))
4375
4376 (defconst vhdl-b-o-s-re
4377 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
4378 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
4379
4380 (defun vhdl-beginning-of-statement-1 (&optional lim)
4381 "Move to the start of the current statement, or the previous
4382 statement if already at the beginning of one."
4383 (let ((lim (or lim (point-min)))
4384 (here (point))
4385 (pos (point))
4386 donep)
4387 ;; go backwards one balanced expression, but be careful of
4388 ;; unbalanced paren being reached
4389 (if (not (vhdl-safe (progn (backward-sexp) t)))
4390 (progn
4391 (backward-up-list 1)
4392 (forward-char)
4393 (vhdl-forward-syntactic-ws here)
4394 (setq donep t)))
4395 (while (and (not donep)
4396 (not (bobp))
4397 ;; look backwards for a statement boundary
4398 (re-search-backward vhdl-b-o-s-re lim 'move))
4399 (if (or (= (preceding-char) ?_)
4400 (vhdl-in-literal lim))
4401 (backward-char)
4402 (cond
4403 ;; If we are looking at an open paren, then stop after it
4404 ((eq (following-char) ?\()
4405 (forward-char)
4406 (vhdl-forward-syntactic-ws here)
4407 (setq donep t))
4408 ;; If we are looking at a close paren, then skip it
4409 ((eq (following-char) ?\))
4410 (forward-char)
4411 (setq pos (point))
4412 (backward-sexp)
4413 (if (< (point) lim)
4414 (progn (goto-char pos)
4415 (vhdl-forward-syntactic-ws here)
4416 (setq donep t))))
4417 ;; If we are looking at a semicolon, then stop
4418 ((eq (following-char) ?\;)
4419 (progn
4420 (forward-char)
4421 (vhdl-forward-syntactic-ws here)
4422 (setq donep t)))
4423 ;; If we are looking at a "begin", then stop
4424 ((and (looking-at vhdl-begin-fwd-re)
4425 (/= (preceding-char) ?_)
4426 (vhdl-begin-p nil))
4427 ;; If it's a leader "begin", then find the
4428 ;; right place
4429 (if (looking-at vhdl-leader-re)
4430 (save-excursion
4431 ;; set a default stop point at the begin
4432 (setq pos (point))
4433 ;; is the start point inside the leader area ?
4434 (goto-char (vhdl-end-of-leader))
4435 (vhdl-forward-syntactic-ws here)
4436 (if (< (point) here)
4437 ;; start point was not inside leader area
4438 ;; set stop point at word after leader
4439 (setq pos (point))))
4440 (forward-word 1)
4441 (vhdl-forward-syntactic-ws here)
4442 (setq pos (point)))
4443 (goto-char pos)
4444 (setq donep t))
4445 ;; If we are looking at a "statement", then stop
4446 ((and (looking-at vhdl-statement-fwd-re)
4447 (/= (preceding-char) ?_)
4448 (vhdl-statement-p nil))
4449 (setq donep t))
4450 ;; If we are looking at a case alternative key, then stop
4451 ((and (looking-at vhdl-case-alternative-re)
4452 (vhdl-case-alternative-p lim))
4453 (save-excursion
4454 ;; set a default stop point at the when
4455 (setq pos (point))
4456 ;; is the start point inside the case alternative key ?
4457 (looking-at vhdl-case-alternative-re)
4458 (goto-char (match-end 0))
4459 (vhdl-forward-syntactic-ws here)
4460 (if (< (point) here)
4461 ;; start point was not inside the case alternative key
4462 ;; set stop point at word after case alternative keyleader
4463 (setq pos (point))))
4464 (goto-char pos)
4465 (setq donep t))
4466 ;; Bogus find, continue
4467 (t
4468 (backward-char)))))
4469 ))
4470
4471 ;; Defuns for calculating the current syntactic state:
4472
4473 (defun vhdl-get-library-unit (bod placeholder)
4474 "If there is an enclosing library unit at bod, with it's \"begin\"
4475 keyword at placeholder, then return the library unit type."
4476 (let ((here (vhdl-point 'bol)))
4477 (if (save-excursion
4478 (goto-char placeholder)
4479 (vhdl-safe (vhdl-forward-sexp 1 bod))
4480 (<= here (point)))
4481 (save-excursion
4482 (goto-char bod)
4483 (cond
4484 ((looking-at "e") 'entity)
4485 ((looking-at "a") 'architecture)
4486 ((looking-at "c") 'configuration)
4487 ((looking-at "p")
4488 (save-excursion
4489 (goto-char bod)
4490 (forward-sexp)
4491 (vhdl-forward-syntactic-ws here)
4492 (if (looking-at "body\\b[^_]")
4493 'package-body 'package))))))
4494 ))
4495
4496 (defun vhdl-get-block-state (&optional lim)
4497 "Finds and records all the closest opens.
4498 lim is the furthest back we need to search (it should be the
4499 previous libunit keyword)."
4500 (let ((here (point))
4501 (lim (or lim (point-min)))
4502 keyword sexp-start sexp-mid sexp-end
4503 preceding-sexp containing-sexp
4504 containing-begin containing-mid containing-paren)
4505 (save-excursion
4506 ;; Find the containing-paren, and use that as the limit
4507 (if (setq containing-paren
4508 (save-restriction
4509 (narrow-to-region lim (point))
4510 (vhdl-safe (scan-lists (point) -1 1))))
4511 (setq lim containing-paren))
4512 ;; Look backwards for "begin" and "end" keywords.
4513 (while (and (> (point) lim)
4514 (not containing-sexp))
4515 (setq keyword (vhdl-backward-to-block lim))
4516 (cond
4517 ((eq keyword 'begin)
4518 ;; Found a "begin" keyword
4519 (setq sexp-start (point))
4520 (setq sexp-mid (vhdl-corresponding-mid lim))
4521 (setq sexp-end (vhdl-safe
4522 (save-excursion
4523 (vhdl-forward-sexp 1 lim) (point))))
4524 (if (and sexp-end (<= sexp-end here))
4525 ;; we want to record this sexp, but we only want to
4526 ;; record the last-most of any of them before here
4527 (or preceding-sexp
4528 (setq preceding-sexp sexp-start))
4529 ;; we're contained in this sexp so put sexp-start on
4530 ;; front of list
4531 (setq containing-sexp sexp-start)
4532 (setq containing-mid sexp-mid)
4533 (setq containing-begin t)))
4534 ((eq keyword 'end)
4535 ;; Found an "end" keyword
4536 (forward-sexp)
4537 (setq sexp-end (point))
4538 (setq sexp-mid nil)
4539 (setq sexp-start
4540 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
4541 (progn (backward-sexp) (point))))
4542 ;; we want to record this sexp, but we only want to
4543 ;; record the last-most of any of them before here
4544 (or preceding-sexp
4545 (setq preceding-sexp sexp-start)))
4546 )))
4547 ;; Check if the containing-paren should be the containing-sexp
4548 (if (and containing-paren
4549 (or (null containing-sexp)
4550 (< containing-sexp containing-paren)))
4551 (setq containing-sexp containing-paren
4552 preceding-sexp nil
4553 containing-begin nil
4554 containing-mid nil))
4555 (vector containing-sexp preceding-sexp containing-begin containing-mid)
4556 ))
4557
4558
4559 (defconst vhdl-s-c-a-re
4560 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
4561
4562 (defun vhdl-skip-case-alternative (&optional lim)
4563 "Skip forward over case/when bodies, with optional maximal
4564 limit. If no next case alternative is found, nil is returned and point
4565 is not moved."
4566 (let ((lim (or lim (point-max)))
4567 (here (point))
4568 donep foundp)
4569 (while (and (< (point) lim)
4570 (not donep))
4571 (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
4572 (save-match-data
4573 (not (vhdl-in-literal)))
4574 (/= (match-beginning 0) here))
4575 (progn
4576 (goto-char (match-beginning 0))
4577 (cond
4578 ((and (looking-at "case")
4579 (re-search-forward "\\bis[^_]" lim t))
4580 (backward-sexp)
4581 (vhdl-forward-sexp))
4582 (t
4583 (setq donep t
4584 foundp t))))))
4585 (if (not foundp)
4586 (goto-char here))
4587 foundp))
4588
4589 (defun vhdl-backward-skip-label (&optional lim)
4590 "Skip backward over a label, with optional maximal
4591 limit. If label is not found, nil is returned and point
4592 is not moved."
4593 (let ((lim (or lim (point-min)))
4594 placeholder)
4595 (if (save-excursion
4596 (vhdl-backward-syntactic-ws lim)
4597 (and (eq (preceding-char) ?:)
4598 (progn
4599 (backward-sexp)
4600 (setq placeholder (point))
4601 (looking-at vhdl-label-key))))
4602 (goto-char placeholder))
4603 ))
4604
4605 (defun vhdl-forward-skip-label (&optional lim)
4606 "Skip forward over a label, with optional maximal
4607 limit. If label is not found, nil is returned and point
4608 is not moved."
4609 (let ((lim (or lim (point-max))))
4610 (if (looking-at vhdl-label-key)
4611 (progn
4612 (goto-char (match-end 0))
4613 (vhdl-forward-syntactic-ws lim)))
4614 ))
4615
4616 (defun vhdl-get-syntactic-context ()
4617 "Guess the syntactic description of the current line of VHDL code."
4618 (save-excursion
4619 (save-restriction
4620 (beginning-of-line)
4621 (let* ((indent-point (point))
4622 (case-fold-search t)
4623 vec literal containing-sexp preceding-sexp
4624 containing-begin containing-mid containing-leader
4625 char-before-ip char-after-ip begin-after-ip end-after-ip
4626 placeholder lim library-unit
4627 )
4628
4629 ;; Reset the syntactic context
4630 (setq vhdl-syntactic-context nil)
4631
4632 (save-excursion
4633 ;; Move to the start of the previous library unit, and
4634 ;; record the position of the "begin" keyword.
4635 (setq placeholder (vhdl-beginning-of-libunit))
4636 ;; The position of the "libunit" keyword gives us a gross
4637 ;; limit point.
4638 (setq lim (point))
4639 )
4640
4641 ;; If there is a previous library unit, and we are enclosed by
4642 ;; it, then set the syntax accordingly.
4643 (and placeholder
4644 (setq library-unit (vhdl-get-library-unit lim placeholder))
4645 (vhdl-add-syntax library-unit lim))
4646
4647 ;; Find the surrounding state.
4648 (if (setq vec (vhdl-get-block-state lim))
4649 (progn
4650 (setq containing-sexp (aref vec 0))
4651 (setq preceding-sexp (aref vec 1))
4652 (setq containing-begin (aref vec 2))
4653 (setq containing-mid (aref vec 3))
4654 ))
4655
4656 ;; set the limit on the farthest back we need to search
4657 (setq lim (if containing-sexp
4658 (save-excursion
4659 (goto-char containing-sexp)
4660 ;; set containing-leader if required
4661 (if (looking-at vhdl-leader-re)
4662 (setq containing-leader (vhdl-end-of-leader)))
4663 (vhdl-point 'bol))
4664 (point-min)))
4665
4666 ;; cache char before and after indent point, and move point to
4667 ;; the most likely position to perform the majority of tests
4668 (goto-char indent-point)
4669 (skip-chars-forward " \t")
4670 (setq literal (vhdl-in-literal lim))
4671 (setq char-after-ip (following-char))
4672 (setq begin-after-ip (and
4673 (not literal)
4674 (looking-at vhdl-begin-fwd-re)
4675 (vhdl-begin-p)))
4676 (setq end-after-ip (and
4677 (not literal)
4678 (looking-at vhdl-end-fwd-re)
4679 (vhdl-end-p)))
4680 (vhdl-backward-syntactic-ws lim)
4681 (setq char-before-ip (preceding-char))
4682 (goto-char indent-point)
4683 (skip-chars-forward " \t")
4684
4685 ;; now figure out syntactic qualities of the current line
4686 (cond
4687 ;; CASE 1: in a string or comment.
4688 ((memq literal '(string comment))
4689 (vhdl-add-syntax literal (vhdl-point 'bopl)))
4690 ;; CASE 2: Line is at top level.
4691 ((null containing-sexp)
4692 ;; Find the point to which indentation will be relative
4693 (save-excursion
4694 (if (null preceding-sexp)
4695 ;; CASE 2X.1
4696 ;; no preceding-sexp -> use the preceding statement
4697 (vhdl-beginning-of-statement-1 lim)
4698 ;; CASE 2X.2
4699 ;; if there is a preceding-sexp then indent relative to it
4700 (goto-char preceding-sexp)
4701 ;; if not at boi, then the block-opening keyword is
4702 ;; probably following a label, so we need a different
4703 ;; relpos
4704 (if (/= (point) (vhdl-point 'boi))
4705 ;; CASE 2X.3
4706 (vhdl-beginning-of-statement-1 lim)))
4707 ;; v-b-o-s could have left us at point-min
4708 (and (bobp)
4709 ;; CASE 2X.4
4710 (vhdl-forward-syntactic-ws indent-point))
4711 (setq placeholder (point)))
4712 (cond
4713 ;; CASE 2A : we are looking at a block-open
4714 (begin-after-ip
4715 (vhdl-add-syntax 'block-open placeholder))
4716 ;; CASE 2B: we are looking at a block-close
4717 (end-after-ip
4718 (vhdl-add-syntax 'block-close placeholder))
4719 ;; CASE 2C: we are looking at a top-level statement
4720 ((progn
4721 (vhdl-backward-syntactic-ws lim)
4722 (or (bobp)
4723 (= (preceding-char) ?\;)))
4724 (vhdl-add-syntax 'statement placeholder))
4725 ;; CASE 2D: we are looking at a top-level statement-cont
4726 (t
4727 (vhdl-beginning-of-statement-1 lim)
4728 ;; v-b-o-s could have left us at point-min
4729 (and (bobp)
4730 ;; CASE 2D.1
4731 (vhdl-forward-syntactic-ws indent-point))
4732 (vhdl-add-syntax 'statement-cont (point)))
4733 )) ; end CASE 2
4734 ;; CASE 3: line is inside parentheses. Most likely we are
4735 ;; either in a subprogram argument (interface) list, or a
4736 ;; continued expression containing parentheses.
4737 ((null containing-begin)
4738 (vhdl-backward-syntactic-ws containing-sexp)
4739 (cond
4740 ;; CASE 3A: we are looking at the arglist closing paren
4741 ((eq char-after-ip ?\))
4742 (goto-char containing-sexp)
4743 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
4744 ;; CASE 3B: we are looking at the first argument in an empty
4745 ;; argument list.
4746 ((eq char-before-ip ?\()
4747 (goto-char containing-sexp)
4748 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
4749 ;; CASE 3C: we are looking at an arglist continuation line,
4750 ;; but the preceding argument is on the same line as the
4751 ;; opening paren. This case includes multi-line
4752 ;; expression paren groupings.
4753 ((and (save-excursion
4754 (goto-char (1+ containing-sexp))
4755 (skip-chars-forward " \t")
4756 (not (eolp))
4757 (not (looking-at "--")))
4758 (save-excursion
4759 (vhdl-beginning-of-statement-1 containing-sexp)
4760 (skip-chars-backward " \t(")
4761 (<= (point) containing-sexp)))
4762 (goto-char containing-sexp)
4763 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
4764 ;; CASE 3D: we are looking at just a normal arglist
4765 ;; continuation line
4766 (t (vhdl-beginning-of-statement-1 containing-sexp)
4767 (vhdl-forward-syntactic-ws indent-point)
4768 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
4769 ))
4770 ;; CASE 4: A block mid open
4771 ((and begin-after-ip
4772 (looking-at containing-mid))
4773 (goto-char containing-sexp)
4774 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4775 (if (looking-at vhdl-trailer-re)
4776 ;; CASE 4.1
4777 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4778 (vhdl-backward-skip-label (vhdl-point 'boi))
4779 (vhdl-add-syntax 'block-open (point)))
4780 ;; CASE 5: block close brace
4781 (end-after-ip
4782 (goto-char containing-sexp)
4783 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4784 (if (looking-at vhdl-trailer-re)
4785 ;; CASE 5.1
4786 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4787 (vhdl-backward-skip-label (vhdl-point 'boi))
4788 (vhdl-add-syntax 'block-close (point)))
4789 ;; CASE 6: A continued statement
4790 ((and (/= char-before-ip ?\;)
4791 ;; check it's not a trailer begin keyword, or a begin
4792 ;; keyword immediately following a label.
4793 (not (and begin-after-ip
4794 (or (looking-at vhdl-trailer-re)
4795 (save-excursion
4796 (vhdl-backward-skip-label containing-sexp)))))
4797 ;; check it's not a statement keyword
4798 (not (and (looking-at vhdl-statement-fwd-re)
4799 (vhdl-statement-p)))
4800 ;; see if the b-o-s is before the indent point
4801 (> indent-point
4802 (save-excursion
4803 (vhdl-beginning-of-statement-1 containing-sexp)
4804 ;; If we ended up after a leader, then this will
4805 ;; move us forward to the start of the first
4806 ;; statement. Note that a containing sexp here is
4807 ;; always a keyword, not a paren, so this will
4808 ;; have no effect if we hit the containing-sexp.
4809 (vhdl-forward-syntactic-ws indent-point)
4810 (setq placeholder (point))))
4811 ;; check it's not a block-intro
4812 (/= placeholder containing-sexp)
4813 ;; check it's not a case block-intro
4814 (save-excursion
4815 (goto-char placeholder)
4816 (or (not (looking-at vhdl-case-alternative-re))
4817 (> (match-end 0) indent-point))))
4818 ;; Make placeholder skip a label, but only if it puts us
4819 ;; before the indent point at the start of a line.
4820 (let ((new placeholder))
4821 (if (and (> indent-point
4822 (save-excursion
4823 (goto-char placeholder)
4824 (vhdl-forward-skip-label indent-point)
4825 (setq new (point))))
4826 (save-excursion
4827 (goto-char new)
4828 (eq new (progn (back-to-indentation) (point)))))
4829 (setq placeholder new)))
4830 (vhdl-add-syntax 'statement-cont placeholder)
4831 (if begin-after-ip
4832 (vhdl-add-syntax 'block-open)))
4833 ;; Statement. But what kind?
4834 ;; CASE 7: A case alternative key
4835 ((and (looking-at vhdl-case-alternative-re)
4836 (vhdl-case-alternative-p containing-sexp))
4837 ;; for a case alternative key, we set relpos to the first
4838 ;; non-whitespace char on the line containing the "case"
4839 ;; keyword.
4840 (goto-char containing-sexp)
4841 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4842 (if (looking-at vhdl-trailer-re)
4843 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4844 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
4845 ;; CASE 8: statement catchall
4846 (t
4847 ;; we know its a statement, but we need to find out if it is
4848 ;; the first statement in a block
4849 (if containing-leader
4850 (goto-char containing-leader)
4851 (goto-char containing-sexp)
4852 ;; Note that a containing sexp here is always a keyword,
4853 ;; not a paren, so skip over the keyword.
4854 (forward-sexp))
4855 ;; move to the start of the first statement
4856 (vhdl-forward-syntactic-ws indent-point)
4857 (setq placeholder (point))
4858 ;; we want to ignore case alternatives keys when skipping forward
4859 (let (incase-p)
4860 (while (looking-at vhdl-case-alternative-re)
4861 (setq incase-p (point))
4862 ;; we also want to skip over the body of the
4863 ;; case/when statement if that doesn't put us at
4864 ;; after the indent-point
4865 (while (vhdl-skip-case-alternative indent-point))
4866 ;; set up the match end
4867 (looking-at vhdl-case-alternative-re)
4868 (goto-char (match-end 0))
4869 ;; move to the start of the first case alternative statement
4870 (vhdl-forward-syntactic-ws indent-point)
4871 (setq placeholder (point)))
4872 (cond
4873 ;; CASE 8A: we saw a case/when statement so we must be
4874 ;; in a switch statement. find out if we are at the
4875 ;; statement just after a case alternative key
4876 ((and incase-p
4877 (= (point) indent-point))
4878 ;; relpos is the "when" keyword
4879 (vhdl-add-syntax 'statement-case-intro incase-p))
4880 ;; CASE 8B: any old statement
4881 ((< (point) indent-point)
4882 ;; relpos is the first statement of the block
4883 (vhdl-add-syntax 'statement placeholder)
4884 (if begin-after-ip
4885 (vhdl-add-syntax 'block-open)))
4886 ;; CASE 8C: first statement in a block
4887 (t
4888 (goto-char containing-sexp)
4889 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4890 (if (looking-at vhdl-trailer-re)
4891 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4892 (vhdl-backward-skip-label (vhdl-point 'boi))
4893 (vhdl-add-syntax 'statement-block-intro (point))
4894 (if begin-after-ip
4895 (vhdl-add-syntax 'block-open)))
4896 )))
4897 )
4898
4899 ;; now we need to look at any modifiers
4900 (goto-char indent-point)
4901 (skip-chars-forward " \t")
4902 (if (looking-at "--")
4903 (vhdl-add-syntax 'comment))
4904 ;; return the syntax
4905 vhdl-syntactic-context))))
4906
4907 ;; Standard indentation line-ups:
4908
4909 (defun vhdl-lineup-arglist (langelem)
4910 "Lineup the current arglist line with the arglist appearing just
4911 after the containing paren which starts the arglist."
4912 (save-excursion
4913 (let* ((containing-sexp
4914 (save-excursion
4915 ;; arglist-cont-nonempty gives relpos ==
4916 ;; to boi of containing-sexp paren. This
4917 ;; is good when offset is +, but bad
4918 ;; when it is vhdl-lineup-arglist, so we
4919 ;; have to special case a kludge here.
4920 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
4921 (progn
4922 (beginning-of-line)
4923 (backward-up-list 1)
4924 (skip-chars-forward " \t" (vhdl-point 'eol)))
4925 (goto-char (cdr langelem)))
4926 (point)))
4927 (cs-curcol (save-excursion
4928 (goto-char (cdr langelem))
4929 (current-column))))
4930 (if (save-excursion
4931 (beginning-of-line)
4932 (looking-at "[ \t]*)"))
4933 (progn (goto-char (match-end 0))
4934 (backward-sexp)
4935 (forward-char)
4936 (vhdl-forward-syntactic-ws)
4937 (- (current-column) cs-curcol))
4938 (goto-char containing-sexp)
4939 (or (eolp)
4940 (let ((eol (vhdl-point 'eol))
4941 (here (progn
4942 (forward-char)
4943 (skip-chars-forward " \t")
4944 (point))))
4945 (vhdl-forward-syntactic-ws)
4946 (if (< (point) eol)
4947 (goto-char here))))
4948 (- (current-column) cs-curcol)
4949 ))))
4950
4951 (defun vhdl-lineup-arglist-intro (langelem)
4952 "Lineup an arglist-intro line to just after the open paren."
4953 (save-excursion
4954 (let ((cs-curcol (save-excursion
4955 (goto-char (cdr langelem))
4956 (current-column)))
4957 (ce-curcol (save-excursion
4958 (beginning-of-line)
4959 (backward-up-list 1)
4960 (skip-chars-forward " \t" (vhdl-point 'eol))
4961 (current-column))))
4962 (- ce-curcol cs-curcol -1))))
4963
4964 (defun vhdl-lineup-comment (langelem)
4965 "Support old behavior for comment indentation. We look at
4966 vhdl-comment-only-line-offset to decide how to indent comment
4967 only-lines."
4968 (save-excursion
4969 (back-to-indentation)
4970 ;; at or to the right of comment-column
4971 (if (>= (current-column) comment-column)
4972 (vhdl-comment-indent)
4973 ;; otherwise, indent as specified by vhdl-comment-only-line-offset
4974 (if (not (bolp))
4975 (or (car-safe vhdl-comment-only-line-offset)
4976 vhdl-comment-only-line-offset)
4977 (or (cdr-safe vhdl-comment-only-line-offset)
4978 (car-safe vhdl-comment-only-line-offset)
4979 -1000 ;jam it against the left side
4980 )))))
4981
4982 (defun vhdl-lineup-statement-cont (langelem)
4983 "Line up statement-cont after the assignment operator."
4984 (save-excursion
4985 (let* ((relpos (cdr langelem))
4986 (assignp (save-excursion
4987 (goto-char (vhdl-point 'boi))
4988 (and (re-search-forward "\\(<\\|:\\)="
4989 (vhdl-point 'eol) t)
4990 (- (point) (vhdl-point 'boi)))))
4991 (curcol (progn
4992 (goto-char relpos)
4993 (current-column)))
4994 foundp)
4995 (while (and (not foundp)
4996 (< (point) (vhdl-point 'eol)))
4997 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
4998 (if (vhdl-in-literal (cdr langelem))
4999 (forward-char)
5000 (if (= (preceding-char) ?\()
5001 ;; skip over any parenthesized expressions
5002 (goto-char (min (vhdl-point 'eol)
5003 (scan-lists (point) 1 1)))
5004 ;; found an assignment operator (not at eol)
5005 (setq foundp (not (looking-at "\\s-*$"))))))
5006 (if (not foundp)
5007 ;; there's no assignment operator on the line
5008 vhdl-basic-offset
5009 ;; calculate indentation column after assign and ws, unless
5010 ;; our line contains an assignment operator
5011 (if (not assignp)
5012 (progn
5013 (forward-char)
5014 (skip-chars-forward " \t")
5015 (setq assignp 0)))
5016 (- (current-column) assignp curcol))
5017 )))
5018
5019 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5020 ;; Indentation commands
5021
5022 (defsubst vhdl-in-comment-p ()
5023 "Check if point is to right of beginning comment delimiter."
5024 (let ((position (point)))
5025 (save-excursion ; finds an unquoted comment
5026 (beginning-of-line)
5027 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" position t))))
5028
5029 (defsubst vhdl-in-string-p ()
5030 "Check if point is in a string."
5031 (let ((position (point)))
5032 (save-excursion ; preceeded by odd number of string delimiters?
5033 (beginning-of-line)
5034 (eq position (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*"
5035 position t)))))
5036
5037 (defsubst vhdl-in-comment-or-string-p ()
5038 "Check if point is in a comment or a string."
5039 (and (vhdl-in-comment-p)
5040 (vhdl-in-string-p)))
5041
5042 (defun vhdl-electric-tab (&optional prefix-arg)
5043 "If preceeding character is part of a word or a paren then hippie-expand,
5044 else if right of non whitespace on line then tab-to-tab-stop,
5045 else if last command was a tab or return then dedent one step,
5046 else indent `correctly'."
5047 (interactive "*P")
5048 (vhdl-ext-syntax-table
5049 (cond ((= (char-syntax (preceding-char)) ?w)
5050 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5051 (case-replace nil))
5052 (vhdl-expand-abbrev prefix-arg)))
5053 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
5054 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5055 (case-replace nil))
5056 (vhdl-expand-paren prefix-arg)))
5057 ((> (current-column) (current-indentation))
5058 (tab-to-tab-stop))
5059 ((and (or (eq last-command 'vhdl-electric-tab)
5060 (eq last-command 'vhdl-electric-return))
5061 (/= 0 (current-indentation)))
5062 (backward-delete-char-untabify vhdl-basic-offset nil))
5063 (t (vhdl-indent-line)))
5064 (setq this-command 'vhdl-electric-tab)))
5065
5066 (defun vhdl-electric-return ()
5067 "newline-and-indent or indent-new-comment-line if in comment and preceding
5068 character is a space."
5069 (interactive)
5070 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
5071 (indent-new-comment-line)
5072 (newline-and-indent)))
5073
5074 (defvar vhdl-progress-info nil
5075 "Array variable for progress information: 0 begin, 1 end, 2 time.")
5076
5077 (defun vhdl-indent-line ()
5078 "Indent the current line as VHDL code. Returns the amount of
5079 indentation change."
5080 (interactive)
5081 (let* ((syntax (vhdl-get-syntactic-context))
5082 (pos (- (point-max) (point)))
5083 ;; special case: comments at or right of comment-column
5084 (indent (if (and (eq (car (car syntax)) 'comment)
5085 (>= (vhdl-get-offset (car syntax)) comment-column))
5086 (vhdl-get-offset (car syntax))
5087 (apply '+ (mapcar 'vhdl-get-offset syntax))))
5088 ; (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
5089 (shift-amt (- indent (current-indentation))))
5090 (and vhdl-echo-syntactic-information-p
5091 (message "syntax: %s, indent= %d" syntax indent))
5092 (unless (zerop shift-amt)
5093 (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
5094 (beginning-of-line)
5095 (indent-to indent))
5096 (if (< (point) (vhdl-point 'boi))
5097 (back-to-indentation)
5098 ;; If initial point was within line's indentation, position after
5099 ;; the indentation. Else stay at same point in text.
5100 (when (> (- (point-max) pos) (point))
5101 (goto-char (- (point-max) pos))))
5102 (run-hooks 'vhdl-special-indent-hook)
5103 ;; update progress status
5104 (when vhdl-progress-info
5105 (aset vhdl-progress-info 1 (+ (aref vhdl-progress-info 1)
5106 (if (> -500 shift-amt) 0 shift-amt)))
5107 (when (< vhdl-progress-interval
5108 (- (nth 1 (current-time)) (aref vhdl-progress-info 2)))
5109 (message "Indenting... (%2d%s)"
5110 (/ (* 100 (- (point) (aref vhdl-progress-info 0)))
5111 (- (aref vhdl-progress-info 1)
5112 (aref vhdl-progress-info 0))) "%")
5113 (aset vhdl-progress-info 2 (nth 1 (current-time)))))
5114 shift-amt))
5115
5116 (defun vhdl-indent-buffer ()
5117 "Indent whole buffer as VHDL code.
5118 Calls `indent-region' for whole buffer and adds progress reporting."
5119 (interactive)
5120 (when vhdl-progress-interval
5121 (setq vhdl-progress-info (vector (point-min) (point-max) 0)))
5122 (indent-region (point-min) (point-max) nil)
5123 (when vhdl-progress-interval (message "Indenting...done"))
5124 (setq vhdl-progress-info nil))
5125
5126 (defun vhdl-indent-region (start end column)
5127 "Indent region as VHDL code.
5128 Adds progress reporting to `indent-region'."
5129 (interactive "r\nP")
5130 (when vhdl-progress-interval (setq vhdl-progress-info (vector start end 0)))
5131 (indent-region start end column)
5132 (when vhdl-progress-interval (message "Indenting...done"))
5133 (setq vhdl-progress-info nil))
5134
5135 (defun vhdl-indent-sexp (&optional endpos)
5136 "Indent each line of the list starting just after point.
5137 If optional arg ENDPOS is given, indent each line, stopping when
5138 ENDPOS is encountered."
5139 (interactive)
5140 (save-excursion
5141 (let ((beg (point))
5142 (end (progn (vhdl-forward-sexp nil endpos) (point))))
5143 (indent-region beg end nil))))
5144
5145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5146 ;; Miscellaneous commands
5147
5148 (defun vhdl-show-syntactic-information ()
5149 "Show syntactic information for current line."
5150 (interactive)
5151 (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
5152 (vhdl-keep-region-active))
5153
5154 ;; Verification and regression functions:
5155
5156 (defun vhdl-regress-line (&optional arg)
5157 "Check syntactic information for current line."
5158 (interactive "P")
5159 (let ((expected (save-excursion
5160 (end-of-line)
5161 (when (search-backward " -- ((" (vhdl-point 'bol) t)
5162 (forward-char 4)
5163 (read (current-buffer)))))
5164 (actual (vhdl-get-syntactic-context))
5165 (expurgated))
5166 ;; remove the library unit symbols
5167 (mapcar
5168 (function
5169 (lambda (elt)
5170 (if (memq (car elt) '(entity configuration package
5171 package-body architecture))
5172 nil
5173 (setq expurgated (append expurgated (list elt))))))
5174 actual)
5175 (if (and (not arg) expected (listp expected))
5176 (if (not (equal expected expurgated))
5177 (error "Should be: %s, is: %s" expected expurgated))
5178 (save-excursion
5179 (beginning-of-line)
5180 (when (not (looking-at "^\\s-*\\(--.*\\)?$"))
5181 (end-of-line)
5182 (if (search-backward " -- ((" (vhdl-point 'bol) t)
5183 (kill-line))
5184 (insert " -- ")
5185 (insert (format "%s" expurgated))))))
5186 (vhdl-keep-region-active))
5187
5188
5189 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5190 ;;; Alignment, whitespace fixup, beautifying
5191 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5192
5193 (defvar vhdl-align-alist
5194 '(
5195 ;; after some keywords
5196 (vhdl-mode "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)[ \t]"
5197 "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)\\([ \t]+\\)" 2)
5198 ;; before ':'
5199 (vhdl-mode ":[^=]" "\\([ \t]*\\):[^=]")
5200 ;; after direction specifications
5201 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\>"
5202 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\([ \t]+\\)" 2)
5203 ;; before "==", ":=", "=>", and "<="
5204 (vhdl-mode "==" "\\([ \t]*\\)==" 1)
5205 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since ":= ... =>" can occur
5206 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "<= ... =>" can occur
5207 (vhdl-mode "=>" "\\([ \t]*\\)=>" 1)
5208 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since "=> ... :=" can occur
5209 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "=> ... <=" can occur
5210 ;; before some keywords
5211 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
5212 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
5213 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
5214 )
5215 "The format of this alist is (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
5216 It is searched in order. If REGEXP is found anywhere in the first
5217 line of a region to be aligned, ALIGN-PATTERN will be used for that
5218 region. ALIGN-PATTERN must include the whitespace to be expanded or
5219 contracted. It may also provide regexps for the text surrounding the
5220 whitespace. SUBEXP specifies which sub-expression of
5221 ALIGN-PATTERN matches the white space to be expanded/contracted.")
5222
5223 (defvar vhdl-align-try-all-clauses t
5224 "If REGEXP is not found on the first line of the region that clause
5225 is ignored. If this variable is non-nil, then the clause is tried anyway.")
5226
5227 (defun vhdl-align-region (begin end &optional spacing alignment-list indent)
5228 "Attempt to align a range of lines based on the content of the
5229 lines. The definition of `alignment-list' determines the matching
5230 order and the manner in which the lines are aligned. If ALIGNMENT-LIST
5231 is not specified `vhdl-align-alist' is used. If INDENT is non-nil,
5232 indentation is done before aligning."
5233 (interactive "r\np")
5234 (setq alignment-list (or alignment-list vhdl-align-alist))
5235 (setq spacing (or spacing 1))
5236 (save-excursion
5237 (let (bol indent)
5238 (goto-char end)
5239 (setq end (point-marker))
5240 (goto-char begin)
5241 (setq bol (setq begin (progn (beginning-of-line) (point))))
5242 ; (untabify bol end)
5243 (when indent
5244 (indent-region bol end nil))))
5245 (let ((case-fold-search t)
5246 (copy (copy-alist alignment-list)))
5247 (vhdl-ext-syntax-table
5248 (while copy
5249 (save-excursion
5250 (goto-char begin)
5251 (let (element
5252 (eol (save-excursion (progn (end-of-line) (point)))))
5253 (setq element (nth 0 copy))
5254 (when (and (or (and (listp (car element))
5255 (memq major-mode (car element)))
5256 (eq major-mode (car element)))
5257 (or vhdl-align-try-all-clauses
5258 (re-search-forward (car (cdr element)) eol t)))
5259 (vhdl-align-region-1 begin end (car (cdr (cdr element)))
5260 (car (cdr (cdr (cdr element)))) spacing))
5261 (setq copy (cdr copy))))))))
5262
5263 (defun vhdl-align-region-1 (begin end match &optional substr spacing)
5264 "Align a range of lines from BEGIN to END. The regular expression
5265 MATCH must match exactly one fields: the whitespace to be
5266 contracted/expanded. The alignment column will equal the
5267 rightmost column of the widest whitespace block. SPACING is
5268 the amount of extra spaces to add to the calculated maximum required.
5269 SPACING defaults to 1 so that at least one space is inserted after
5270 the token in MATCH."
5271 (setq spacing (or spacing 1))
5272 (setq substr (or substr 1))
5273 (save-excursion
5274 (let (distance (max 0) (lines 0) bol eol width)
5275 ;; Determine the greatest whitespace distance to the alignment
5276 ;; character
5277 (goto-char begin)
5278 (setq eol (progn (end-of-line) (point))
5279 bol (setq begin (progn (beginning-of-line) (point))))
5280 (while (< bol end)
5281 (save-excursion
5282 (when (and (re-search-forward match eol t)
5283 (not (vhdl-in-comment-p)))
5284 (setq distance (- (match-beginning substr) bol))
5285 (when (> distance max)
5286 (setq max distance))))
5287 (forward-line)
5288 (setq bol (point)
5289 eol (save-excursion (end-of-line) (point)))
5290 (setq lines (1+ lines)))
5291 ;; Now insert enough maxs to push each assignment operator to
5292 ;; the same column. We need to use 'lines' as a counter, since
5293 ;; the location of the mark may change
5294 (goto-char (setq bol begin))
5295 (setq eol (save-excursion (end-of-line) (point)))
5296 (while (> lines 0)
5297 (when (and (re-search-forward match eol t)
5298 (not (vhdl-in-comment-p)))
5299 (setq width (- (match-end substr) (match-beginning substr)))
5300 (setq distance (- (match-beginning substr) bol))
5301 (goto-char (match-beginning substr))
5302 (delete-char width)
5303 (insert-char ? (+ (- max distance) spacing)))
5304 (beginning-of-line)
5305 (forward-line)
5306 (setq bol (point)
5307 eol (save-excursion (end-of-line) (point)))
5308 (setq lines (1- lines))))))
5309
5310 (defun vhdl-align-inline-comment-region-1 (beg end &optional spacing)
5311 "Align inline comments in region."
5312 (save-excursion
5313 (let ((high-start 0)
5314 (high-length 0)
5315 (case-fold-search t))
5316 (vhdl-ext-syntax-table
5317 (goto-char beg)
5318 ;; search for longest code line and longest inline comment
5319 (while (< (point) end)
5320 (cond
5321 ((and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5322 (looking-at "^\\(.*[^ \t\n-]+\\)\\s-*\\(--\\s-*.*\\)$"))
5323 (setq high-start
5324 (max high-start (- (match-end 1) (match-beginning 1))))
5325 (setq high-length
5326 (max high-length (- (match-end 2) (match-beginning 2)))))
5327 ((and (looking-at "^\\(\\s-*\\))\\(--\\s-*.*\\)$")
5328 (>= (- (match-end 1) (match-beginning 1)) comment-column))
5329 (setq high-length
5330 (max high-length (- (match-end 2) (match-beginning 2))))))
5331 (beginning-of-line 2))
5332 (goto-char beg)
5333 (setq spacing (or spacing 2))
5334 (setq high-start (+ high-start spacing))
5335 ;; align as nice as possible
5336 (while (< (point) end)
5337 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5338 (or (looking-at "^.*[^ \t\n-]+\\(\\s-*\\)--")
5339 (and (looking-at "^\\(\\s-*\\)--")
5340 (>= (- (match-end 1) (match-beginning 1))
5341 comment-column))))
5342 (goto-char (match-end 1))
5343 (delete-region (match-beginning 1) (match-end 1))
5344 (insert-char ? spacing)
5345 (cond ((<= high-start comment-column)
5346 (indent-to comment-column))
5347 ((<= (+ high-start high-length) end-comment-column)
5348 (indent-to high-start))
5349 (t (indent-to comment-column))))
5350 (beginning-of-line 2))))))
5351
5352 (defun vhdl-align-noindent-region (beg end &optional spacing no-message)
5353 "Align region without indentation."
5354 (interactive "r\nP")
5355 (save-excursion
5356 (let (pos)
5357 (goto-char beg)
5358 (beginning-of-line)
5359 (setq beg (point))
5360 (goto-char end)
5361 (setq end (point-marker))
5362 (untabify beg end)
5363 (unless no-message (message "Aligning..."))
5364 (vhdl-fixup-whitespace-region beg end t)
5365 (goto-char beg)
5366 (if (not vhdl-align-groups)
5367 ;; align entire region
5368 (progn (vhdl-align-region beg end spacing)
5369 (vhdl-align-inline-comment-region-1 beg end))
5370 ;; align groups
5371 (while (and (< beg end)
5372 (re-search-forward "^\\s-*$" end t))
5373 (setq pos (point-marker))
5374 (vhdl-align-region beg pos spacing)
5375 (vhdl-align-inline-comment-region-1 beg pos)
5376 (setq beg (1+ pos))
5377 (goto-char beg))
5378 ;; align last group
5379 (when (< beg end)
5380 (vhdl-align-region beg end spacing)
5381 (vhdl-align-inline-comment-region-1 beg end)))))
5382 (unless no-message (message "Aligning...done")))
5383
5384 (defun vhdl-align-group (&optional spacing)
5385 "Align group of lines between empty lines."
5386 (interactive)
5387 (save-excursion
5388 (let ((start (point))
5389 beg end)
5390 (setq end (if (re-search-forward "^\\s-*$" nil t)
5391 (point-marker) (point-max)))
5392 (goto-char start)
5393 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5394 (untabify beg end)
5395 (message "Aligning...")
5396 (vhdl-fixup-whitespace-region beg end t)
5397 (vhdl-align-region beg end spacing)
5398 (vhdl-align-inline-comment-region-1 beg end)
5399 (message "Aligning...done"))))
5400
5401 (defun vhdl-align-noindent-buffer ()
5402 "Align buffer without indentation."
5403 (interactive)
5404 (vhdl-align-noindent-region (point-min) (point-max)))
5405
5406 (defun vhdl-align-inline-comment-region (beg end &optional spacing no-message)
5407 "Align inline comments within a region. Groups of code lines separated by
5408 empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
5409 (interactive "r\nP")
5410 (save-excursion
5411 (let (pos)
5412 (goto-char beg)
5413 (beginning-of-line)
5414 (setq beg (point))
5415 (goto-char end)
5416 (setq end (point-marker))
5417 (untabify beg end)
5418 (unless no-message (message "Aligning inline comments..."))
5419 (goto-char beg)
5420 (if (not vhdl-align-groups)
5421 ;; align entire region
5422 (vhdl-align-inline-comment-region-1 beg end spacing)
5423 ;; align groups
5424 (while (and (< beg end) (re-search-forward "^\\s-*$" end t))
5425 (setq pos (point-marker))
5426 (vhdl-align-inline-comment-region-1 beg pos spacing)
5427 (setq beg (1+ pos))
5428 (goto-char beg))
5429 ;; align last group
5430 (when (< beg end)
5431 (vhdl-align-inline-comment-region-1 beg end spacing))))
5432 (unless no-message (message "Aligning inline comments...done"))))
5433
5434 (defun vhdl-align-inline-comment-group (&optional spacing)
5435 "Align inline comments within a group of lines between empty lines."
5436 (interactive)
5437 (save-excursion
5438 (let ((start (point))
5439 beg end)
5440 (setq end (if (re-search-forward "^\\s-*$" nil t)
5441 (point-marker) (point-max)))
5442 (goto-char start)
5443 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5444 (untabify beg end)
5445 (message "Aligning inline comments...")
5446 (vhdl-align-inline-comment-region-1 beg end)
5447 (message "Aligning inline comments...done"))))
5448
5449 (defun vhdl-align-inline-comment-buffer ()
5450 "Align inline comments within buffer. Groups of code lines separated by
5451 empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
5452 (interactive)
5453 (vhdl-align-inline-comment-region (point-min) (point-max)))
5454
5455 (defun vhdl-fixup-whitespace-region (beg end &optional no-message)
5456 "Fixup whitespace in region. Surround operator symbols by one space,
5457 eliminate multiple spaces (except at beginning of line), eliminate spaces at
5458 end of line, do nothing in comments."
5459 (interactive "r")
5460 (unless no-message (message "Fixing up whitespace..."))
5461 (save-excursion
5462 (goto-char end)
5463 (setq end (point-marker))
5464 ;; surround operator symbols by one space
5465 (goto-char beg)
5466 (while (re-search-forward "\\([^/:<>=]\\|^\\)\\(--\\|:\\|=\\|<\\|>\\|:=\\|<=\\|>=\\|=>\\)\\([^=>]\\|$\\)"
5467 end t)
5468 (if (equal "--" (match-string 2))
5469 (re-search-forward ".*\n" end t)
5470 (replace-match "\\1 \\2 \\3")))
5471 ;; have no space before and one space after `,' and ';'
5472 (goto-char beg)
5473 (while (re-search-forward "\\(--\\|\\s-*\\([,;]\\)\\)" end t)
5474 (if (equal "--" (match-string 1))
5475 (re-search-forward ".*\n" end t)
5476 (replace-match "\\2 " nil nil nil 1)))
5477 ;; eliminate multiple spaces and spaces at end of line
5478 (goto-char beg)
5479 (while (or (and (looking-at "--.*\n") (re-search-forward "--.*\n" end t))
5480 (and (looking-at "\\s-+$") (re-search-forward "\\s-+$" end t)
5481 (progn (replace-match "" nil nil) t))
5482 (and (looking-at "\\s-+;") (re-search-forward "\\s-+;" end t)
5483 (progn (replace-match ";" nil nil) t))
5484 (and (looking-at "^\\s-+") (re-search-forward "^\\s-+" end t))
5485 (and (looking-at "\\s-+--") (re-search-forward "\\s-+" end t)
5486 (progn (replace-match " " nil nil) t ))
5487 (and (looking-at "\\s-+") (re-search-forward "\\s-+" end t)
5488 (progn (replace-match " " nil nil) t ))
5489 (re-search-forward "\\S-+" end t))))
5490 (unless no-message (message "Fixing up whitespace...done")))
5491
5492 (defun vhdl-fixup-whitespace-buffer ()
5493 "Fixup whitespace in buffer. Surround operator symbols by one space,
5494 eliminate multiple spaces (except at beginning of line), eliminate spaces at
5495 end of line, do nothing in comments."
5496 (interactive)
5497 (vhdl-fixup-whitespace-region (point-min) (point-max)))
5498
5499 (defun vhdl-beautify-region (beg end)
5500 "Beautify region by applying indentation, whitespace fixup, alignment, and
5501 case fixing to a resion. Calls functions `vhdl-indent-buffer',
5502 `vhdl-align-noindent-buffer' (variable `vhdl-align-groups' set to non-nil), and
5503 `vhdl-fix-case-buffer'."
5504 (interactive "r")
5505 (vhdl-indent-region beg end nil)
5506 (let ((vhdl-align-groups t))
5507 (vhdl-align-noindent-region beg end))
5508 (vhdl-fix-case-region beg end))
5509
5510 (defun vhdl-beautify-buffer ()
5511 "Beautify buffer by applying indentation, whitespace fixup, alignment, and
5512 case fixing to entire buffer. Calls `vhdl-beautify-region' for the entire
5513 buffer."
5514 (interactive)
5515 (vhdl-beautify-region (point-min) (point-max)))
5516
5517
5518 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5519 ;;; Electrification
5520 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5521
5522 (defconst vhdl-template-prompt-syntax "[^ =<>][^<>@.\n]*[^ =<>]"
5523 "Syntax of prompt inserted by template generators.")
5524
5525 (defvar vhdl-template-invoked-by-hook nil
5526 "Indicates whether a template has been invoked by a hook or by key or menu.
5527 Used for undoing after template abortion.")
5528
5529 ;; correct different behavior of function `unread-command-events' in XEmacs
5530 (defalias 'vhdl-character-to-event
5531 (if (string-match "XEmacs" emacs-version) 'character-to-event 'identity))
5532
5533 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5534 ;; Enabling/disabling
5535
5536 (defun vhdl-mode-line-update ()
5537 "Update the modeline string for VHDL major mode."
5538 (setq mode-name (concat "VHDL"
5539 (and (or vhdl-electric-mode vhdl-stutter-mode) "/")
5540 (and vhdl-electric-mode "e")
5541 (and vhdl-stutter-mode "s")))
5542 (force-mode-line-update))
5543
5544 (defun vhdl-electric-mode (arg)
5545 "Toggle VHDL electric mode.
5546 Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5547 (interactive "P")
5548 (setq vhdl-electric-mode
5549 (cond ((or (not arg) (zerop arg)) (not vhdl-electric-mode))
5550 ((> arg 0) t) (t nil)))
5551 (vhdl-mode-line-update))
5552
5553 (defun vhdl-stutter-mode (arg)
5554 "Toggle VHDL stuttering mode.
5555 Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5556 (interactive "P")
5557 (setq vhdl-stutter-mode
5558 (cond ((or (not arg) (zerop arg)) (not vhdl-stutter-mode))
5559 ((> arg 0) t) (t nil)))
5560 (vhdl-mode-line-update))
5561
5562 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5563 ;; Stuttering
5564
5565 (defun vhdl-electric-dash (count)
5566 "-- starts a comment, --- draws a horizontal line,
5567 ---- starts a display comment"
5568 (interactive "p")
5569 (if vhdl-stutter-mode
5570 (cond
5571 ((and abbrev-start-location (= abbrev-start-location (point)))
5572 (setq abbrev-start-location nil)
5573 (goto-char last-abbrev-location)
5574 (beginning-of-line nil)
5575 (vhdl-comment-display))
5576 ((/= (preceding-char) ?-) ; standard dash (minus)
5577 (self-insert-command count))
5578 (t (self-insert-command count)
5579 (message "Enter '-' for horiz. line, 'CR' for commenting-out code, else enter comment")
5580 (let ((next-input (read-char)))
5581 (if (= next-input ?-) ; triple dash
5582 (progn
5583 (vhdl-comment-display-line)
5584 (message
5585 "Enter '-' for display comment, else continue coding")
5586 (let ((next-input (read-char)))
5587 (if (= next-input ?-) ; four dashes
5588 (vhdl-comment-display t)
5589 (setq unread-command-events ; pushback the char
5590 (list (vhdl-character-to-event next-input))))))
5591 (setq unread-command-events ; pushback the char
5592 (list (vhdl-character-to-event next-input)))
5593 (vhdl-comment-insert)))))
5594 (self-insert-command count)))
5595
5596 (defun vhdl-electric-open-bracket (count) "'[' --> '(', '([' --> '['"
5597 (interactive "p")
5598 (if (and vhdl-stutter-mode (= count 1))
5599 (if (= (preceding-char) ?\()
5600 (progn (delete-char -1) (insert-char ?\[ 1))
5601 (insert-char ?\( 1))
5602 (self-insert-command count)))
5603
5604 (defun vhdl-electric-close-bracket (count) "']' --> ')', ')]' --> ']'"
5605 (interactive "p")
5606 (if (and vhdl-stutter-mode (= count 1))
5607 (progn
5608 (if (= (preceding-char) ?\))
5609 (progn (delete-char -1) (insert-char ?\] 1))
5610 (insert-char ?\) 1))
5611 (blink-matching-open))
5612 (self-insert-command count)))
5613
5614 (defun vhdl-electric-quote (count) "'' --> \""
5615 (interactive "p")
5616 (if (and vhdl-stutter-mode (= count 1))
5617 (if (= (preceding-char) last-input-char)
5618 (progn (delete-backward-char 1) (insert-char ?\" 1))
5619 (insert-char ?\' 1))
5620 (self-insert-command count)))
5621
5622 (defun vhdl-electric-semicolon (count) "';;' --> ' : ', ': ;' --> ' := '"
5623 (interactive "p")
5624 (if (and vhdl-stutter-mode (= count 1))
5625 (cond ((= (preceding-char) last-input-char)
5626 (progn (delete-char -1)
5627 (when (not (eq (preceding-char) ? )) (insert " "))
5628 (insert ": ")
5629 (setq this-command 'vhdl-electric-colon)))
5630 ((and
5631 (eq last-command 'vhdl-electric-colon) (= (preceding-char) ? ))
5632 (progn (delete-char -1) (insert "= ")))
5633 (t (insert-char ?\; 1)))
5634 (self-insert-command count)))
5635
5636 (defun vhdl-electric-comma (count) "',,' --> ' <= '"
5637 (interactive "p")
5638 (if (and vhdl-stutter-mode (= count 1))
5639 (cond ((= (preceding-char) last-input-char)
5640 (progn (delete-char -1)
5641 (when (not (eq (preceding-char) ? )) (insert " "))
5642 (insert "<= ")))
5643 (t (insert-char ?\, 1)))
5644 (self-insert-command count)))
5645
5646 (defun vhdl-electric-period (count) "'..' --> ' => '"
5647 (interactive "p")
5648 (if (and vhdl-stutter-mode (= count 1))
5649 (cond ((= (preceding-char) last-input-char)
5650 (progn (delete-char -1)
5651 (when (not (eq (preceding-char) ? )) (insert " "))
5652 (insert "=> ")))
5653 (t (insert-char ?\. 1)))
5654 (self-insert-command count)))
5655
5656 (defun vhdl-electric-equal (count) "'==' --> ' == '"
5657 (interactive "p")
5658 (if (and vhdl-stutter-mode (= count 1))
5659 (cond ((= (preceding-char) last-input-char)
5660 (progn (delete-char -1)
5661 (when (not (eq (preceding-char) ? )) (insert " "))
5662 (insert "== ")))
5663 (t (insert-char ?\= 1)))
5664 (self-insert-command count)))
5665
5666 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5667 ;; VHDL templates
5668
5669 (defun vhdl-template-paired-parens ()
5670 "Insert a pair of round parentheses, placing point between them."
5671 (interactive)
5672 (insert "()")
5673 (backward-char))
5674
5675 (defun vhdl-template-alias ()
5676 "Insert alias declaration."
5677 (interactive)
5678 (let ((start (point)))
5679 (vhdl-insert-keyword "ALIAS ")
5680 (when (vhdl-template-field "name" nil t start (point))
5681 (insert " : ")
5682 (unless (vhdl-template-field
5683 (concat "[type" (and (vhdl-standard-p 'ams) " or nature") "]")
5684 nil t)
5685 (backward-delete-char 3))
5686 (vhdl-insert-keyword " IS ")
5687 (vhdl-template-field "name" ";")
5688 (vhdl-comment-insert-inline))))
5689
5690 (defun vhdl-template-architecture ()
5691 "Insert architecture."
5692 (interactive)
5693 (let ((margin (current-indentation))
5694 (start (point))
5695 arch-name entity-exists string
5696 (case-fold-search t))
5697 (vhdl-insert-keyword "ARCHITECTURE ")
5698 (when (setq arch-name
5699 (vhdl-template-field "name" nil t start (point)))
5700 (vhdl-insert-keyword " OF ")
5701 (save-excursion
5702 (vhdl-ext-syntax-table
5703 (setq entity-exists (re-search-backward
5704 "\\<entity \\(\\w+\\) is\\>" nil t))
5705 (setq string (match-string 1))))
5706 (if (and entity-exists (not (equal string "")))
5707 (insert string)
5708 (vhdl-template-field "entity name"))
5709 (vhdl-insert-keyword " IS")
5710 (vhdl-template-begin-end
5711 (unless (vhdl-standard-p '87) "ARCHITECTURE") arch-name margin
5712 (memq vhdl-insert-empty-lines '(unit all))))))
5713
5714 (defun vhdl-template-array (kind &optional secondary)
5715 "Insert array type definition."
5716 (interactive)
5717 (let ((start (point)))
5718 (vhdl-insert-keyword "ARRAY (")
5719 (when (or (vhdl-template-field "range" nil (not secondary) start (point))
5720 secondary)
5721 (vhdl-insert-keyword ") OF ")
5722 (vhdl-template-field (if (eq kind 'type) "type" "nature"))
5723 (vhdl-insert-keyword ";"))))
5724
5725 (defun vhdl-template-assert ()
5726 "Insert an assertion statement."
5727 (interactive)
5728 (let ((start (point)))
5729 (vhdl-insert-keyword "ASSERT ")
5730 (when vhdl-conditions-in-parenthesis (insert "("))
5731 (when (vhdl-template-field "condition (negated)" nil t start (point))
5732 (when vhdl-conditions-in-parenthesis (insert ")"))
5733 (setq start (point))
5734 (vhdl-insert-keyword " REPORT ")
5735 (unless (vhdl-template-field "string expression" nil nil nil nil t)
5736 (delete-region start (point)))
5737 (setq start (point))
5738 (vhdl-insert-keyword " SEVERITY ")
5739 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
5740 (delete-region start (point)))
5741 (insert ";"))))
5742
5743 (defun vhdl-template-attribute ()
5744 "Insert an attribute declaration or specification."
5745 (interactive)
5746 (if (eq (vhdl-decision-query
5747 "attribute" "(d)eclaration or (s)pecification?" t) ?s)
5748 (vhdl-template-attribute-spec)
5749 (vhdl-template-attribute-decl)))
5750
5751 (defun vhdl-template-attribute-decl ()
5752 "Insert an attribute declaration."
5753 (interactive)
5754 (let ((start (point)))
5755 (vhdl-insert-keyword "ATTRIBUTE ")
5756 (when (vhdl-template-field "name" " : " t start (point))
5757 (vhdl-template-field "type" ";")
5758 (vhdl-comment-insert-inline))))
5759
5760 (defun vhdl-template-attribute-spec ()
5761 "Insert an attribute specification."
5762 (interactive)
5763 (let ((start (point)))
5764 (vhdl-insert-keyword "ATTRIBUTE ")
5765 (when (vhdl-template-field "name" nil t start (point))
5766 (vhdl-insert-keyword " OF ")
5767 (vhdl-template-field "entity names | OTHERS | ALL" " : ")
5768 (vhdl-template-field "entity class")
5769 (vhdl-insert-keyword " IS ")
5770 (vhdl-template-field "expression" ";"))))
5771
5772 (defun vhdl-template-block ()
5773 "Insert a block."
5774 (interactive)
5775 (let ((margin (current-indentation))
5776 (start (point))
5777 label)
5778 (vhdl-insert-keyword ": BLOCK ")
5779 (goto-char start)
5780 (when (setq label (vhdl-template-field "label" nil t start (+ (point) 8)))
5781 (forward-word 1)
5782 (forward-char 1)
5783 (insert "(")
5784 (if (vhdl-template-field "[guard expression]" nil t)
5785 (insert ")")
5786 (delete-char -2))
5787 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
5788 (vhdl-template-begin-end "BLOCK" label margin)
5789 (vhdl-comment-block))))
5790
5791 (defun vhdl-template-block-configuration ()
5792 "Insert a block configuration statement."
5793 (interactive)
5794 (let ((margin (current-indentation))
5795 (start (point)))
5796 (vhdl-insert-keyword "FOR ")
5797 (when (vhdl-template-field "block name" nil t start (point))
5798 (vhdl-insert-keyword "\n\n")
5799 (indent-to margin)
5800 (vhdl-insert-keyword "END FOR;")
5801 (end-of-line 0)
5802 (indent-to (+ margin vhdl-basic-offset)))))
5803
5804 (defun vhdl-template-break ()
5805 "Insert a break statement."
5806 (interactive)
5807 (let (position)
5808 (vhdl-insert-keyword "BREAK")
5809 (setq position (point))
5810 (insert " ")
5811 (while (or
5812 (progn (vhdl-insert-keyword "FOR ")
5813 (if (vhdl-template-field "[quantity name]" " USE " t)
5814 (progn (vhdl-template-field "quantity name" " => ") t)
5815 (kill-word -1) nil))
5816 (vhdl-template-field "[quantity name]" " => " t))
5817 (vhdl-template-field "expression")
5818 (setq position (point))
5819 (insert ", "))
5820 (delete-region position (point))
5821 (unless (vhdl-sequential-statement-p)
5822 (vhdl-insert-keyword " ON ")
5823 (if (vhdl-template-field "[sensitivity list]" nil t)
5824 (setq position (point))
5825 (delete-region position (point))))
5826 (vhdl-insert-keyword " WHEN ")
5827 (when vhdl-conditions-in-parenthesis (insert "("))
5828 (if (vhdl-template-field "[condition]" nil t)
5829 (when vhdl-conditions-in-parenthesis (insert ")"))
5830 (delete-region position (point)))
5831 (insert ";")))
5832
5833 (defun vhdl-template-case (&optional kind)
5834 "Insert a case statement."
5835 (interactive)
5836 (let ((margin (current-indentation))
5837 (start (point))
5838 label)
5839 (unless kind (setq kind (if (vhdl-sequential-statement-p) 'is 'use)))
5840 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
5841 (vhdl-insert-keyword "CASE ")
5842 (vhdl-insert-keyword ": CASE ")
5843 (goto-char start)
5844 (setq label (vhdl-template-field "[label]" nil t))
5845 (unless label (delete-char 2))
5846 (forward-word 1)
5847 (forward-char 1))
5848 (when (vhdl-template-field "expression" nil t start (point))
5849 (vhdl-insert-keyword (concat " " (if (eq kind 'is) "IS" "USE") "\n\n"))
5850 (indent-to margin)
5851 (vhdl-insert-keyword "END CASE")
5852 (when label (insert " " label))
5853 (insert ";")
5854 (forward-line -1)
5855 (indent-to (+ margin vhdl-basic-offset))
5856 (vhdl-insert-keyword "WHEN ")
5857 (let ((position (point)))
5858 (insert " => ;\n")
5859 (indent-to (+ margin vhdl-basic-offset))
5860 (vhdl-insert-keyword "WHEN OTHERS => null;")
5861 (goto-char position)))))
5862
5863 (defun vhdl-template-case-is ()
5864 "Insert a sequential case statement."
5865 (interactive)
5866 (vhdl-template-case 'is))
5867
5868 (defun vhdl-template-case-use ()
5869 "Insert a simultaneous case statement."
5870 (interactive)
5871 (vhdl-template-case 'use))
5872
5873 (defun vhdl-template-component ()
5874 "Insert a component declaration."
5875 (interactive)
5876 (vhdl-template-component-decl))
5877
5878 (defun vhdl-template-component-conf ()
5879 "Insert a component configuration (uses `vhdl-template-configuration-spec'
5880 since these are almost equivalent)."
5881 (interactive)
5882 (let ((margin (current-indentation))
5883 (result (vhdl-template-configuration-spec t)))
5884 (when result
5885 (insert "\n")
5886 (indent-to margin)
5887 (vhdl-insert-keyword "END FOR;")
5888 (when (eq result 'no-use)
5889 (end-of-line -0)))))
5890
5891 (defun vhdl-template-component-decl ()
5892 "Insert a component declaration."
5893 (interactive)
5894 (let ((margin (current-indentation))
5895 (start (point))
5896 name end-column)
5897 (vhdl-insert-keyword "COMPONENT ")
5898 (when (setq name (vhdl-template-field "name" nil t start (point)))
5899 (insert "\n\n")
5900 (indent-to margin)
5901 (vhdl-insert-keyword "END COMPONENT")
5902 (unless (vhdl-standard-p '87) (insert " " name))
5903 (insert ";")
5904 (setq end-column (current-column))
5905 (end-of-line -0)
5906 (indent-to (+ margin vhdl-basic-offset))
5907 (vhdl-template-generic-list t t)
5908 (insert "\n")
5909 (indent-to (+ margin vhdl-basic-offset))
5910 (vhdl-template-port-list t)
5911 (beginning-of-line 2)
5912 (forward-char end-column))))
5913
5914 (defun vhdl-template-component-inst ()
5915 "Insert a component instantiation statement."
5916 (interactive)
5917 (let ((margin (current-indentation))
5918 (start (point))
5919 unit position)
5920 (when (vhdl-template-field "instance label" nil t start (point))
5921 (insert ": ")
5922 (if (vhdl-standard-p '87)
5923 (vhdl-template-field "component name")
5924 ;; direct instantiation
5925 (setq unit (vhdl-template-field
5926 "[COMPONENT | ENTITY | CONFIGURATION]" " " t))
5927 (setq unit (upcase (or unit "")))
5928 (cond ((equal unit "ENTITY")
5929 (vhdl-template-field "library name" "." nil nil nil nil "work")
5930 (vhdl-template-field "entity name" "(")
5931 (if (vhdl-template-field "[architecture name]" nil t)
5932 (insert ")")
5933 (delete-char -1)))
5934 ((equal unit "CONFIGURATION")
5935 (vhdl-template-field "library name" "." nil nil nil nil "work")
5936 (vhdl-template-field "configuration name"))
5937 (t (vhdl-template-field "component name"))))
5938 (insert "\n")
5939 (indent-to (+ margin vhdl-basic-offset))
5940 (setq position (point))
5941 (vhdl-insert-keyword "GENERIC ")
5942 (when (vhdl-template-map position t t)
5943 (insert "\n")
5944 (indent-to (+ margin vhdl-basic-offset)))
5945 (setq position (point))
5946 (vhdl-insert-keyword "PORT ")
5947 (unless (vhdl-template-map position t t)
5948 (kill-line -0)
5949 (delete-char -1))
5950 (insert ";"))))
5951
5952 (defun vhdl-template-conditional-signal-asst ()
5953 "Insert a conditional signal assignment."
5954 (interactive)
5955 (when (vhdl-template-field "target signal")
5956 (insert " <= ")
5957 ; (if (not (equal (vhdl-template-field "[GUARDED] [TRANSPORT]") ""))
5958 ; (insert " "))
5959 (let ((margin (current-column))
5960 (start (point))
5961 position)
5962 (vhdl-template-field "waveform")
5963 (setq position (point))
5964 (vhdl-insert-keyword " WHEN ")
5965 (when vhdl-conditions-in-parenthesis (insert "("))
5966 (while (and (vhdl-template-field "[condition]" nil t)
5967 (progn
5968 (when vhdl-conditions-in-parenthesis (insert ")"))
5969 (setq position (point))
5970 (vhdl-insert-keyword " ELSE")
5971 (insert "\n")
5972 (indent-to margin)
5973 (vhdl-template-field "[waveform]" nil t)))
5974 (setq position (point))
5975 (vhdl-insert-keyword " WHEN ")
5976 (when vhdl-conditions-in-parenthesis (insert "(")))
5977 (delete-region position (point))
5978 (insert ";")
5979 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
5980
5981 (defun vhdl-template-configuration ()
5982 "Insert a configuration specification if within an architecture,
5983 a block or component configuration if within a configuration declaration,
5984 a configuration declaration if not within a design unit."
5985 (interactive)
5986 (let ((case-fold-search t))
5987 (vhdl-ext-syntax-table
5988 (cond
5989 ((and (save-excursion ; architecture body
5990 (re-search-backward "^\\(architecture\\|end\\)\\>" nil t))
5991 (equal "ARCHITECTURE" (upcase (match-string 1))))
5992 (vhdl-template-configuration-spec))
5993 ((and (save-excursion ; configuration declaration
5994 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
5995 (equal "CONFIGURATION" (upcase (match-string 1))))
5996 (if (eq (vhdl-decision-query
5997 "configuration" "(b)lock or (c)omponent configuration?" t) ?c)
5998 (vhdl-template-component-conf)
5999 (vhdl-template-block-configuration)))
6000 (t (vhdl-template-configuration-decl)))))) ; otherwise
6001
6002 (defun vhdl-template-configuration-spec (&optional optional-use)
6003 "Insert a configuration specification."
6004 (interactive)
6005 (let ((margin (current-indentation))
6006 (start (point))
6007 aspect position)
6008 (vhdl-insert-keyword "FOR ")
6009 (when (vhdl-template-field "component names | OTHERS | ALL" " : "
6010 t start (point))
6011 (vhdl-template-field "component type" "\n")
6012 (indent-to (+ margin vhdl-basic-offset))
6013 (setq start (point))
6014 (vhdl-insert-keyword "USE ")
6015 (if (and optional-use
6016 (not (setq aspect (vhdl-template-field
6017 "[ENTITY | CONFIGURATION | OPEN]" " " t))))
6018 (progn (delete-region start (point)) 'no-use)
6019 (unless optional-use
6020 (setq aspect (vhdl-template-field
6021 "ENTITY | CONFIGURATION | OPEN" " ")))
6022 (setq aspect (upcase (or aspect "")))
6023 (cond ((equal aspect "ENTITY")
6024 (vhdl-template-field "library name" "." nil nil nil nil "work")
6025 (vhdl-template-field "entity name" "(")
6026 (if (vhdl-template-field "[architecture name]" nil t)
6027 (insert ")")
6028 (delete-char -1))
6029 (insert "\n")
6030 (indent-to (+ margin (* 2 vhdl-basic-offset)))
6031 (setq position (point))
6032 (vhdl-insert-keyword "GENERIC ")
6033 (when (vhdl-template-map position t t)
6034 (insert "\n")
6035 (indent-to (+ margin (* 2 vhdl-basic-offset))))
6036 (setq position (point))
6037 (vhdl-insert-keyword "PORT ")
6038 (unless (vhdl-template-map position t t)
6039 (kill-line -0)
6040 (delete-char -1))
6041 (insert ";")
6042 t)
6043 ((equal aspect "CONFIGURATION")
6044 (vhdl-template-field "library name" "." nil nil nil nil "work")
6045 (vhdl-template-field "configuration name" ";"))
6046 (t (backward-delete-char 1) (insert ";") t))))))
6047
6048
6049 (defun vhdl-template-configuration-decl ()
6050 "Insert a configuration declaration."
6051 (interactive)
6052 (let ((margin (current-indentation))
6053 (start (point))
6054 (case-fold-search t)
6055 entity-exists string name position)
6056 (vhdl-insert-keyword "CONFIGURATION ")
6057 (when (setq name (vhdl-template-field "name" nil t start (point)))
6058 (vhdl-insert-keyword " OF ")
6059 (save-excursion
6060 (vhdl-ext-syntax-table
6061 (setq entity-exists (re-search-backward
6062 "\\<entity \\(\\w*\\) is\\>" nil t))
6063 (setq string (match-string 1))))
6064 (if (and entity-exists (not (equal string "")))
6065 (insert string)
6066 (vhdl-template-field "entity name"))
6067 (vhdl-insert-keyword " IS\n")
6068 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6069 (indent-to (+ margin vhdl-basic-offset))
6070 (setq position (point))
6071 (insert "\n")
6072 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6073 (indent-to margin)
6074 (vhdl-insert-keyword "END ")
6075 (unless (vhdl-standard-p '87)
6076 (vhdl-insert-keyword "CONFIGURATION "))
6077 (insert name ";")
6078 (goto-char position))))
6079
6080 (defun vhdl-template-constant ()
6081 "Insert a constant declaration."
6082 (interactive)
6083 (let ((start (point))
6084 (in-arglist (vhdl-in-argument-list-p)))
6085 (vhdl-insert-keyword "CONSTANT ")
6086 (when (vhdl-template-field "name" nil t start (point))
6087 (insert " : ")
6088 (when in-arglist (vhdl-insert-keyword "IN "))
6089 (vhdl-template-field "type")
6090 (if in-arglist
6091 (progn (insert ";")
6092 (vhdl-comment-insert-inline))
6093 (let ((position (point)))
6094 (insert " := ")
6095 (unless (vhdl-template-field "[initialization]" nil t)
6096 (delete-region position (point)))
6097 (insert ";")
6098 (vhdl-comment-insert-inline))))))
6099
6100 (defun vhdl-template-default ()
6101 "Insert nothing."
6102 (interactive)
6103 (insert " ")
6104 (unexpand-abbrev)
6105 (backward-word 1)
6106 (vhdl-case-word 1)
6107 (forward-char 1))
6108
6109 (defun vhdl-template-default-indent ()
6110 "Insert nothing and indent."
6111 (interactive)
6112 (insert " ")
6113 (unexpand-abbrev)
6114 (backward-word 1)
6115 (vhdl-case-word 1)
6116 (forward-char 1)
6117 (vhdl-indent-line))
6118
6119 (defun vhdl-template-disconnect ()
6120 "Insert a disconnect statement."
6121 (interactive)
6122 (let ((start (point)))
6123 (vhdl-insert-keyword "DISCONNECT ")
6124 (when (vhdl-template-field "signal names | OTHERS | ALL"
6125 " : " t start (point))
6126 (vhdl-template-field "type")
6127 (vhdl-insert-keyword " AFTER ")
6128 (vhdl-template-field "time expression" ";"))))
6129
6130 (defun vhdl-template-else ()
6131 "Insert an else statement."
6132 (interactive)
6133 (let ((case-fold-search t)
6134 margin)
6135 (vhdl-ext-syntax-table
6136 (vhdl-insert-keyword "ELSE")
6137 (if (save-excursion
6138 (re-search-backward "\\(\\<when\\>\\|;\\)" nil t)
6139 (equal "WHEN" (upcase (match-string 1))))
6140 (insert " ")
6141 (vhdl-indent-line)
6142 (setq margin (current-indentation))
6143 (insert "\n")
6144 (indent-to (+ margin vhdl-basic-offset))))))
6145
6146 (defun vhdl-template-elsif ()
6147 "Insert an elsif statement."
6148 (interactive)
6149 (let ((start (point))
6150 margin)
6151 (vhdl-insert-keyword "ELSIF ")
6152 (when vhdl-conditions-in-parenthesis (insert "("))
6153 (when (vhdl-template-field "condition" nil t start (point))
6154 (when vhdl-conditions-in-parenthesis (insert ")"))
6155 (vhdl-indent-line)
6156 (setq margin (current-indentation))
6157 (vhdl-insert-keyword
6158 (concat " " (if (vhdl-sequential-statement-p) "THEN" "USE") "\n"))
6159 (indent-to (+ margin vhdl-basic-offset)))))
6160
6161 (defun vhdl-template-entity ()
6162 "Insert an entity."
6163 (interactive)
6164 (let ((margin (current-indentation))
6165 (start (point))
6166 name end-column)
6167 (vhdl-insert-keyword "ENTITY ")
6168 (when (setq name (vhdl-template-field "name" nil t start (point)))
6169 (vhdl-insert-keyword " IS\n\n")
6170 (indent-to margin)
6171 (vhdl-insert-keyword "END ")
6172 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
6173 (insert name ";")
6174 (setq end-column (current-column))
6175 (end-of-line -0)
6176 (indent-to (+ margin vhdl-basic-offset))
6177 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6178 (indent-to (+ margin vhdl-basic-offset))
6179 (when (vhdl-template-generic-list t)
6180 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6181 (insert "\n")
6182 (indent-to (+ margin vhdl-basic-offset))
6183 (when (vhdl-template-port-list t)
6184 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6185 (beginning-of-line 2)
6186 (forward-char end-column))))
6187
6188 (defun vhdl-template-exit ()
6189 "Insert an exit statement."
6190 (interactive)
6191 (let ((start (point)))
6192 (vhdl-insert-keyword "EXIT ")
6193 (unless (vhdl-template-field "[loop label]" nil t)
6194 (delete-char -1))
6195 (let ((position (point)))
6196 (vhdl-insert-keyword " WHEN ")
6197 (when vhdl-conditions-in-parenthesis (insert "("))
6198 (if (vhdl-template-field "[condition]" nil t)
6199 (when vhdl-conditions-in-parenthesis (insert ")"))
6200 (delete-region position (point))))
6201 (insert ";")))
6202
6203 (defun vhdl-template-file ()
6204 "Insert a file declaration."
6205 (interactive)
6206 (let ((start (point)))
6207 (vhdl-insert-keyword "FILE ")
6208 (when (vhdl-template-field "name" nil t start (point))
6209 (insert " : ")
6210 (vhdl-template-field "type")
6211 (unless (vhdl-standard-p '87)
6212 (vhdl-insert-keyword " OPEN ")
6213 (unless (vhdl-template-field "[READ_MODE | WRITE_MODE | APPEND_MODE]"
6214 nil t)
6215 (backward-delete-char 6)))
6216 (vhdl-insert-keyword " IS ")
6217 (when (vhdl-standard-p '87)
6218 (vhdl-template-field "[IN | OUT]" " " t))
6219 (vhdl-template-field "filename-string" nil nil nil nil t)
6220 (insert ";")
6221 (vhdl-comment-insert-inline))))
6222
6223 (defun vhdl-template-for ()
6224 "Insert a block or component configuration if within a configuration
6225 declaration, a configuration specification if within an architecture
6226 declarative part (and not within a subprogram), and a for-loop otherwise."
6227 (interactive)
6228 (let ((case-fold-search t))
6229 (vhdl-ext-syntax-table
6230 (cond
6231 ((and (save-excursion ; configuration declaration
6232 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
6233 (equal "CONFIGURATION" (upcase (match-string 1))))
6234 (if (eq (vhdl-decision-query
6235 "for" "(b)lock or (c)omponent configuration?" t) ?c)
6236 (vhdl-template-component-conf)
6237 (vhdl-template-block-configuration)))
6238 ((and (save-excursion
6239 (re-search-backward ; architecture declarative part
6240 "^\\(architecture\\|entity\\|begin\\|end\\)\\>" nil t))
6241 (equal "ARCHITECTURE" (upcase (match-string 1)))
6242 (not (and (save-excursion ; not subprogram
6243 (re-search-backward
6244 "^\\s-*\\(architecture\\|begin\\|end\\)\\>" nil t))
6245 (equal "BEGIN" (upcase (match-string 1)))
6246 (save-excursion
6247 (re-search-backward
6248 "^\\s-*\\(function\\|procedure\\)\\>" nil t)))))
6249 (vhdl-template-configuration-spec))
6250 ((vhdl-sequential-statement-p) ; sequential statement
6251 (vhdl-template-for-loop))
6252 (t (vhdl-template-for-generate)))))) ; concurrent statement
6253
6254 (defun vhdl-template-for-generate ()
6255 "Insert a for-generate."
6256 (interactive)
6257 (let ((margin (current-indentation))
6258 (start (point))
6259 label string position)
6260 (vhdl-insert-keyword ": FOR ")
6261 (setq position (point-marker))
6262 (goto-char start)
6263 (when (setq label (vhdl-template-field "label" nil t start position))
6264 (goto-char position)
6265 (vhdl-template-field "loop variable")
6266 (vhdl-insert-keyword " IN ")
6267 (vhdl-template-field "range")
6268 (vhdl-template-generate-body margin label))))
6269
6270 (defun vhdl-template-for-loop ()
6271 "Insert a for loop."
6272 (interactive)
6273 (let ((margin (current-indentation))
6274 (start (point))
6275 label index)
6276 (if (not (eq vhdl-optional-labels 'all))
6277 (vhdl-insert-keyword "FOR ")
6278 (vhdl-insert-keyword ": FOR ")
6279 (goto-char start)
6280 (setq label (vhdl-template-field "[label]" nil t))
6281 (unless label (delete-char 2))
6282 (forward-word 1)
6283 (forward-char 1))
6284 (when (setq index (vhdl-template-field "loop variable"
6285 nil t start (point)))
6286 (vhdl-insert-keyword " IN ")
6287 (vhdl-template-field "range")
6288 (vhdl-insert-keyword " LOOP\n\n")
6289 (indent-to margin)
6290 (vhdl-insert-keyword "END LOOP")
6291 (if label
6292 (insert " " label ";")
6293 (insert ";")
6294 (when vhdl-self-insert-comments (insert " -- " index)))
6295 (forward-line -1)
6296 (indent-to (+ margin vhdl-basic-offset)))))
6297
6298 (defun vhdl-template-footer ()
6299 "Insert a VHDL file footer."
6300 (interactive)
6301 (unless (equal vhdl-file-footer "")
6302 (save-excursion
6303 (goto-char (point-max))
6304 (insert "\n")
6305 (vhdl-insert-string-or-file vhdl-file-footer))))
6306
6307 (defun vhdl-template-function (&optional kind)
6308 "Insert a function declaration or body."
6309 (interactive)
6310 (let ((margin (current-indentation))
6311 (start (point))
6312 name)
6313 (vhdl-insert-keyword "FUNCTION ")
6314 (when (setq name (vhdl-template-field "name" nil t start (point)))
6315 (vhdl-template-argument-list t)
6316 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6317 (end-of-line)
6318 (insert "\n")
6319 (indent-to (+ margin vhdl-basic-offset))
6320 (vhdl-insert-keyword "RETURN ")
6321 (vhdl-template-field "type")
6322 (if (if kind (eq kind 'body)
6323 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6324 (progn (vhdl-insert-keyword " IS")
6325 (vhdl-template-begin-end
6326 (unless (vhdl-standard-p '87) "FUNCTION") name margin)
6327 (vhdl-comment-block))
6328 (insert ";")))))
6329
6330 (defun vhdl-template-function-decl ()
6331 "Insert a function declaration."
6332 (interactive)
6333 (vhdl-template-function 'decl))
6334
6335 (defun vhdl-template-function-body ()
6336 "Insert a function declaration."
6337 (interactive)
6338 (vhdl-template-function 'body))
6339
6340 (defun vhdl-template-generate ()
6341 "Insert a generation scheme."
6342 (interactive)
6343 (if (eq (vhdl-decision-query nil "(f)or or (i)f?" t) ?i)
6344 (vhdl-template-if-generate)
6345 (vhdl-template-for-generate)))
6346
6347 (defun vhdl-template-generic ()
6348 "Insert generic declaration, or generic map in instantiation statements."
6349 (interactive)
6350 (let ((start (point))
6351 (case-fold-search t))
6352 (vhdl-ext-syntax-table
6353 (cond
6354 ((and (save-excursion ; entity declaration
6355 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6356 (equal "ENTITY" (upcase (match-string 1))))
6357 (vhdl-template-generic-list nil))
6358 ((or (save-excursion
6359 (or (beginning-of-line)
6360 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6361 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6362 (vhdl-insert-keyword "GENERIC ")
6363 (vhdl-template-map start))
6364 (t (vhdl-template-generic-list nil t))))))
6365
6366 (defun vhdl-template-group ()
6367 "Insert group or group template declaration."
6368 (interactive)
6369 (let ((start (point)))
6370 (if (eq (vhdl-decision-query
6371 "group" "(d)eclaration or (t)emplate declaration?" t) ?t)
6372 (vhdl-template-group-template)
6373 (vhdl-template-group-decl))))
6374
6375 (defun vhdl-template-group-decl ()
6376 "Insert group declaration."
6377 (interactive)
6378 (let ((start (point)))
6379 (vhdl-insert-keyword "GROUP ")
6380 (when (vhdl-template-field "name" " : " t start (point))
6381 (vhdl-template-field "template name" " (")
6382 (vhdl-template-field "constituent list" ");")
6383 (vhdl-comment-insert-inline))))
6384
6385 (defun vhdl-template-group-template ()
6386 "Insert group template declaration."
6387 (interactive)
6388 (let ((start (point)))
6389 (vhdl-insert-keyword "GROUP ")
6390 (when (vhdl-template-field "template name" nil t start (point))
6391 (vhdl-insert-keyword " IS (")
6392 (vhdl-template-field "entity class list" ");")
6393 (vhdl-comment-insert-inline))))
6394
6395 (defun vhdl-template-header ()
6396 "Insert a VHDL file header."
6397 (interactive)
6398 (unless (equal vhdl-file-header "")
6399 (let ((case-fold-search t)
6400 (project-name (or (nth 0 (aget vhdl-project-alist vhdl-project)) ""))
6401 (project-desc (or (nth 2 (aget vhdl-project-alist vhdl-project)) ""))
6402 eot)
6403 (vhdl-ext-syntax-table
6404 (save-excursion
6405 (save-restriction
6406 (widen)
6407 (goto-char (point-min))
6408 (vhdl-insert-string-or-file vhdl-file-header)
6409 (setq eot (point))
6410 (narrow-to-region (point-min) eot)
6411 (goto-char (point-min))
6412 (while (search-forward "<projectdesc>" nil t)
6413 (replace-match project-desc t t))
6414 (goto-char (point-min))
6415 (while (search-forward "<filename>" nil t)
6416 (replace-match (buffer-name) t t))
6417 (goto-char (point-min))
6418 (while (search-forward "<author>" nil t)
6419 (replace-match "" t t)
6420 (insert (user-full-name))
6421 (when user-mail-address (insert " <" user-mail-address ">")))
6422 (goto-char (point-min))
6423 (while (search-forward "<login>" nil t)
6424 (replace-match (user-login-name) t t))
6425 (goto-char (point-min))
6426 (while (search-forward "<project>" nil t)
6427 (replace-match project-name t t))
6428 (goto-char (point-min))
6429 (while (search-forward "<company>" nil t)
6430 (replace-match vhdl-company-name t t))
6431 (goto-char (point-min))
6432 (while (search-forward "<platform>" nil t)
6433 (replace-match vhdl-platform-spec t t))
6434 (goto-char (point-min))
6435 ;; Replace <RCS> with $, so that RCS for the source is
6436 ;; not over-enthusiastic with replacements
6437 (while (search-forward "<RCS>" nil t)
6438 (replace-match "$" nil t))
6439 (goto-char (point-min))
6440 (while (search-forward "<date>" nil t)
6441 (replace-match "" t t)
6442 (vhdl-template-insert-date))
6443 (goto-char (point-min))
6444 (let (string)
6445 (while
6446 (re-search-forward "<\\(\\(\\w\\|\\s_\\)*\\) string>" nil t)
6447 (setq string (read-string (concat (match-string 1) ": ")))
6448 (replace-match string t t)))))
6449 (goto-char (point-min))
6450 (when (search-forward "<cursor>" nil t)
6451 (replace-match "" t t))
6452 (when (or (not project-name) (equal project-name ""))
6453 (message "You can specify a project title in custom variable `vhdl-project-alist'"))
6454 (when (or (not project-desc) (equal project-desc ""))
6455 (message "You can specify a project description in custom variable `vhdl-project-alist'"))
6456 (when (equal vhdl-company-name "")
6457 (message "You can specify a company name in custom variable `vhdl-company-name'"))
6458 (when (equal vhdl-platform-spec "")
6459 (message "You can specify a platform in custom variable `vhdl-platform-spec'"))))))
6460
6461 (defun vhdl-template-if ()
6462 "Insert a sequential if statement or an if-generate statement."
6463 (interactive)
6464 (if (vhdl-sequential-statement-p)
6465 (vhdl-template-if-then)
6466 (if (and (vhdl-standard-p 'ams)
6467 (eq (vhdl-decision-query "if" "(g)enerate or (u)se?" t) ?u))
6468 (vhdl-template-if-use)
6469 (vhdl-template-if-generate))))
6470
6471 (defun vhdl-template-if-generate ()
6472 "Insert an if-generate."
6473 (interactive)
6474 (let ((margin (current-indentation))
6475 (start (point))
6476 label string position)
6477 (vhdl-insert-keyword ": IF ")
6478 (setq position (point-marker))
6479 (goto-char start)
6480 (when (setq label (vhdl-template-field "label" nil t start position))
6481 (goto-char position)
6482 (when vhdl-conditions-in-parenthesis (insert "("))
6483 (vhdl-template-field "condition")
6484 (when vhdl-conditions-in-parenthesis (insert ")"))
6485 (vhdl-template-generate-body margin label))))
6486
6487 (defun vhdl-template-if-then-use (kind)
6488 "Insert a sequential if statement."
6489 (interactive)
6490 (let ((margin (current-indentation))
6491 (start (point))
6492 label)
6493 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
6494 (vhdl-insert-keyword "IF ")
6495 (vhdl-insert-keyword ": IF ")
6496 (goto-char start)
6497 (setq label (vhdl-template-field "[label]" nil t))
6498 (unless label (delete-char 2))
6499 (forward-word 1)
6500 (forward-char 1))
6501 (when vhdl-conditions-in-parenthesis (insert "("))
6502 (when (vhdl-template-field "condition" nil t start (point))
6503 (when vhdl-conditions-in-parenthesis (insert ")"))
6504 (vhdl-insert-keyword
6505 (concat " " (if (eq kind 'then) "THEN" "USE") "\n\n"))
6506 (indent-to margin)
6507 (vhdl-insert-keyword "END IF")
6508 (when label (insert " " label))
6509 (insert ";")
6510 (forward-line -1)
6511 (indent-to (+ margin vhdl-basic-offset)))))
6512
6513 (defun vhdl-template-if-then ()
6514 "Insert a sequential if statement."
6515 (interactive)
6516 (vhdl-template-if-then-use 'then))
6517
6518 (defun vhdl-template-if-use ()
6519 "Insert a simultaneous if statement."
6520 (interactive)
6521 (vhdl-template-if-then-use 'use))
6522
6523 (defun vhdl-template-instance ()
6524 "Insert a component instantiation statement."
6525 (interactive)
6526 (vhdl-template-component-inst))
6527
6528 (defun vhdl-template-library ()
6529 "Insert a library specification."
6530 (interactive)
6531 (let ((margin (current-indentation))
6532 (start (point))
6533 name end-pos)
6534 (vhdl-insert-keyword "LIBRARY ")
6535 (when (setq name (vhdl-template-field "names" nil t start (point)))
6536 (insert ";")
6537 (unless (string-match "," name)
6538 (setq end-pos (point))
6539 (insert "\n")
6540 (indent-to margin)
6541 (vhdl-insert-keyword "USE ")
6542 (insert name)
6543 (vhdl-insert-keyword "..ALL;")
6544 (backward-char 5)
6545 (if (vhdl-template-field "package name")
6546 (forward-char 5)
6547 (delete-region end-pos (+ (point) 5)))))))
6548
6549 (defun vhdl-template-limit ()
6550 "Insert a limit."
6551 (interactive)
6552 (let ((start (point)))
6553 (vhdl-insert-keyword "LIMIT ")
6554 (when (vhdl-template-field "quantity names | OTHERS | ALL" " : "
6555 t start (point))
6556 (vhdl-template-field "type")
6557 (vhdl-insert-keyword " WITH ")
6558 (vhdl-template-field "real expression" ";"))))
6559
6560 (defun vhdl-template-loop ()
6561 "Insert a loop."
6562 (interactive)
6563 (let ((char (vhdl-decision-query nil "(w)hile, (f)or, or (b)are?" t)))
6564 (cond ((eq char ?w)
6565 (vhdl-template-while-loop))
6566 ((eq char ?f)
6567 (vhdl-template-for-loop))
6568 (t (vhdl-template-bare-loop)))))
6569
6570 (defun vhdl-template-bare-loop ()
6571 "Insert a loop."
6572 (interactive)
6573 (let ((margin (current-indentation))
6574 (start (point))
6575 label)
6576 (if (not (eq vhdl-optional-labels 'all))
6577 (vhdl-insert-keyword "LOOP ")
6578 (vhdl-insert-keyword ": LOOP ")
6579 (goto-char start)
6580 (setq label (vhdl-template-field "[label]" nil t))
6581 (unless label (delete-char 2))
6582 (forward-word 1)
6583 (delete-char 1))
6584 (insert "\n\n")
6585 (indent-to margin)
6586 (vhdl-insert-keyword "END LOOP")
6587 (insert (if label (concat " " label ";") ";"))
6588 (forward-line -1)
6589 (indent-to (+ margin vhdl-basic-offset))))
6590
6591 (defun vhdl-template-map (&optional start optional secondary)
6592 "Insert a map specification with association list."
6593 (interactive)
6594 (let ((start (or start (point)))
6595 margin end-pos)
6596 (vhdl-insert-keyword "MAP (")
6597 (if (not vhdl-association-list-with-formals)
6598 (if (vhdl-template-field
6599 (concat (and optional "[") "association list" (and optional "]"))
6600 ")" (or (not secondary) optional)
6601 (and (not secondary) start) (point))
6602 t
6603 (if (and optional secondary) (delete-region start (point)))
6604 nil)
6605 (if vhdl-argument-list-indent
6606 (setq margin (current-column))
6607 (setq margin (+ (current-indentation) vhdl-basic-offset))
6608 (insert "\n")
6609 (indent-to margin))
6610 (if (vhdl-template-field
6611 (concat (and optional "[") "formal" (and optional "]"))
6612 " => " (or (not secondary) optional)
6613 (and (not secondary) start) (point))
6614 (progn
6615 (vhdl-template-field "actual" ",")
6616 (setq end-pos (point))
6617 (insert "\n")
6618 (indent-to margin)
6619 (while (vhdl-template-field "[formal]" " => " t)
6620 (vhdl-template-field "actual" ",")
6621 (setq end-pos (point))
6622 (insert "\n")
6623 (indent-to margin))
6624 (delete-region end-pos (point))
6625 (backward-delete-char 1)
6626 (insert ")")
6627 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6628 t)
6629 (when (and optional secondary) (delete-region start (point)))
6630 nil))))
6631
6632 (defun vhdl-template-modify (&optional noerror)
6633 "Actualize modification date."
6634 (interactive)
6635 (let ((case-fold-search t))
6636 (vhdl-ext-syntax-table
6637 (save-excursion
6638 (goto-char (point-min))
6639 (if (re-search-forward vhdl-modify-date-prefix-string nil t)
6640 (progn (kill-line)
6641 (vhdl-template-insert-date))
6642 (unless noerror
6643 (error (concat "Modification date prefix string \""
6644 vhdl-modify-date-prefix-string "\" not found"))))))))
6645
6646 (defun vhdl-template-modify-noerror ()
6647 "Call `vhdl-template-modify' with NOERROR non-nil."
6648 (vhdl-template-modify t))
6649
6650 (defun vhdl-template-nature ()
6651 "Insert a nature declaration."
6652 (interactive)
6653 (let ((start (point))
6654 name mid-pos end-pos)
6655 (vhdl-insert-keyword "NATURE ")
6656 (when (setq name (vhdl-template-field "name" nil t start (point)))
6657 (vhdl-insert-keyword " IS ")
6658 (let ((definition
6659 (upcase
6660 (or (vhdl-template-field
6661 "across type | ARRAY | RECORD")
6662 ""))))
6663 (cond ((equal definition "")
6664 (insert ";"))
6665 ((equal definition "ARRAY")
6666 (kill-word -1)
6667 (vhdl-template-array 'nature t))
6668 ((equal definition "RECORD")
6669 (setq mid-pos (point-marker))
6670 (kill-word -1)
6671 (vhdl-template-record 'nature name t))
6672 (t
6673 (vhdl-insert-keyword " ACROSS ")
6674 (vhdl-template-field "through type")
6675 (vhdl-insert-keyword " THROUGH ")
6676 (vhdl-template-field "reference name")
6677 (vhdl-insert-keyword " REFERENCE;")))
6678 (when mid-pos
6679 (setq end-pos (point-marker))
6680 (goto-char mid-pos)
6681 (end-of-line))
6682 (vhdl-comment-insert-inline)
6683 (when end-pos (goto-char end-pos))))))
6684
6685 (defun vhdl-template-next ()
6686 "Insert a next statement."
6687 (interactive)
6688 (vhdl-insert-keyword "NEXT ")
6689 (unless (vhdl-template-field "[loop label]" nil t)
6690 (delete-char -1))
6691 (let ((position (point)))
6692 (vhdl-insert-keyword " WHEN ")
6693 (when vhdl-conditions-in-parenthesis (insert "("))
6694 (if (vhdl-template-field "[condition]" nil t)
6695 (when vhdl-conditions-in-parenthesis (insert ")"))
6696 (delete-region position (point)))
6697 (insert ";")))
6698
6699 (defun vhdl-template-others ()
6700 "Insert an others aggregate."
6701 (interactive)
6702 (vhdl-insert-keyword "(OTHERS => '')")
6703 (backward-char 2))
6704
6705 (defun vhdl-template-package (&optional kind)
6706 "Insert a package specification or body."
6707 (interactive)
6708 (let ((margin (current-indentation))
6709 (start (point))
6710 name body position)
6711 (vhdl-insert-keyword "PACKAGE ")
6712 (setq body (if kind (eq kind 'body)
6713 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b)))
6714 (when body (vhdl-insert-keyword "BODY "))
6715 (when (setq name (vhdl-template-field "name" nil t start (point)))
6716 (vhdl-insert-keyword " IS\n")
6717 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6718 (indent-to (+ margin vhdl-basic-offset))
6719 (setq position (point))
6720 (insert "\n")
6721 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6722 (indent-to margin)
6723 (vhdl-insert-keyword "END ")
6724 (unless (vhdl-standard-p '87)
6725 (vhdl-insert-keyword (concat "PACKAGE " (and body "BODY "))))
6726 (insert (or name "") ";")
6727 (goto-char position))))
6728
6729 (defun vhdl-template-package-decl ()
6730 "Insert a package specification."
6731 (interactive)
6732 (vhdl-template-package 'decl))
6733
6734 (defun vhdl-template-package-body ()
6735 "Insert a package body."
6736 (interactive)
6737 (vhdl-template-package 'body))
6738
6739 (defun vhdl-template-port ()
6740 "Insert a port declaration, or port map in instantiation statements."
6741 (interactive)
6742 (let ((start (point))
6743 (case-fold-search t))
6744 (vhdl-ext-syntax-table
6745 (cond
6746 ((and (save-excursion ; entity declaration
6747 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6748 (equal "ENTITY" (upcase (match-string 1))))
6749 (vhdl-template-port-list nil))
6750 ((or (save-excursion
6751 (or (beginning-of-line)
6752 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6753 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6754 (vhdl-insert-keyword "PORT ")
6755 (vhdl-template-map start))
6756 (t (vhdl-template-port-list nil))))))
6757
6758 (defun vhdl-template-procedural ()
6759 "Insert a procedural."
6760 (interactive)
6761 (let ((margin (current-indentation))
6762 (start (point))
6763 (case-fold-search t)
6764 label)
6765 (vhdl-insert-keyword "PROCEDURAL ")
6766 (when (memq vhdl-optional-labels '(process all))
6767 (goto-char start)
6768 (insert ": ")
6769 (goto-char start)
6770 (setq label (vhdl-template-field "[label]" nil t))
6771 (unless label (delete-char 2))
6772 (forward-word 1)
6773 (forward-char 1))
6774 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "IS"))
6775 (vhdl-template-begin-end "PROCEDURAL" label margin)
6776 (vhdl-comment-block)))
6777
6778 (defun vhdl-template-procedure (&optional kind)
6779 "Insert a procedure declaration or body."
6780 (interactive)
6781 (let ((margin (current-indentation))
6782 (start (point))
6783 name)
6784 (vhdl-insert-keyword "PROCEDURE ")
6785 (when (setq name (vhdl-template-field "name" nil t start (point)))
6786 (vhdl-template-argument-list)
6787 (if (if kind (eq kind 'body)
6788 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6789 (progn (vhdl-insert-keyword " IS")
6790 (when vhdl-auto-align
6791 (vhdl-align-noindent-region start (point) 1))
6792 (end-of-line)
6793 (vhdl-template-begin-end
6794 (unless (vhdl-standard-p '87) "PROCEDURE")
6795 name margin)
6796 (vhdl-comment-block))
6797 (insert ";")
6798 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6799 (end-of-line)))))
6800
6801 (defun vhdl-template-procedure-decl ()
6802 "Insert a procedure declaration."
6803 (interactive)
6804 (vhdl-template-procedure 'decl))
6805
6806 (defun vhdl-template-procedure-body ()
6807 "Insert a procedure body."
6808 (interactive)
6809 (vhdl-template-procedure 'body))
6810
6811 (defun vhdl-template-process (&optional kind)
6812 "Insert a process."
6813 (interactive)
6814 (let ((margin (current-indentation))
6815 (start (point))
6816 (case-fold-search t)
6817 label seq input-signals clock reset final-pos)
6818 (setq seq (if kind (eq kind 'seq)
6819 (eq (vhdl-decision-query
6820 "process" "(c)ombinational or (s)equential?" t) ?s)))
6821 (vhdl-insert-keyword "PROCESS ")
6822 (when (memq vhdl-optional-labels '(process all))
6823 (goto-char start)
6824 (insert ": ")
6825 (goto-char start)
6826 (setq label (vhdl-template-field "[label]" nil t))
6827 (unless label (delete-char 2))
6828 (forward-word 1)
6829 (forward-char 1))
6830 (insert "(")
6831 (if (not seq)
6832 (unless (setq input-signals
6833 (vhdl-template-field "[sensitivity list]" ")" t))
6834 (setq input-signals "")
6835 (delete-char -2))
6836 (setq clock (or (and (not (equal "" vhdl-clock-name))
6837 (progn (insert vhdl-clock-name) vhdl-clock-name))
6838 (vhdl-template-field "clock name") "<clock>"))
6839 (when (eq vhdl-reset-kind 'async)
6840 (insert ", ")
6841 (setq reset (or (and (not (equal "" vhdl-reset-name))
6842 (progn (insert vhdl-reset-name) vhdl-reset-name))
6843 (vhdl-template-field "reset name") "<reset>")))
6844 (insert ")"))
6845 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
6846 (vhdl-template-begin-end "PROCESS" label margin)
6847 (when seq (setq reset (vhdl-template-seq-process clock reset)))
6848 (when vhdl-prompt-for-comments
6849 (setq final-pos (point-marker))
6850 (vhdl-ext-syntax-table
6851 (when (and (re-search-backward "\\<begin\\>" nil t)
6852 (re-search-backward "\\<process\\>" nil t))
6853 (end-of-line -0)
6854 (if (bobp)
6855 (progn (insert "\n") (forward-line -1))
6856 (insert "\n"))
6857 (indent-to margin)
6858 (insert "-- purpose: ")
6859 (if (not (vhdl-template-field "[description]" nil t))
6860 (vhdl-line-kill-entire)
6861 (insert "\n")
6862 (indent-to margin)
6863 (insert "-- type : ")
6864 (insert (if seq "sequential" "combinational") "\n")
6865 (indent-to margin)
6866 (insert "-- inputs : ")
6867 (if (not seq)
6868 (insert input-signals)
6869 (insert clock ", ")
6870 (when reset (insert reset ", "))
6871 (unless (vhdl-template-field "[signal names]" nil t)
6872 (delete-char -2)))
6873 (insert "\n")
6874 (indent-to margin)
6875 (insert "-- outputs: ")
6876 (vhdl-template-field "[signal names]" nil t))))
6877 (goto-char final-pos))))
6878
6879 (defun vhdl-template-process-comb ()
6880 "Insert a combinational process."
6881 (interactive)
6882 (vhdl-template-process 'comb))
6883
6884 (defun vhdl-template-process-seq ()
6885 "Insert a sequential process."
6886 (interactive)
6887 (vhdl-template-process 'seq))
6888
6889 (defun vhdl-template-quantity ()
6890 "Insert a quantity declaration."
6891 (interactive)
6892 (if (vhdl-in-argument-list-p)
6893 (let ((start (point)))
6894 (vhdl-insert-keyword "QUANTITY ")
6895 (when (vhdl-template-field "names" nil t start (point))
6896 (insert " : ")
6897 (vhdl-template-field "[IN | OUT]" " " t)
6898 (vhdl-template-field "type")
6899 (insert ";")
6900 (vhdl-comment-insert-inline)))
6901 (let ((char (vhdl-decision-query
6902 "quantity" "(f)ree, (b)ranch, or (s)ource quantity?" t)))
6903 (cond ((eq char ?f) (vhdl-template-quantity-free))
6904 ((eq char ?b) (vhdl-template-quantity-branch))
6905 ((eq char ?s) (vhdl-template-quantity-source))
6906 (t (vhdl-template-undo (point) (point)))))))
6907
6908 (defun vhdl-template-quantity-free ()
6909 "Insert a free quantity declaration."
6910 (interactive)
6911 (vhdl-insert-keyword "QUANTITY ")
6912 (vhdl-template-field "names")
6913 (insert " : ")
6914 (vhdl-template-field "type")
6915 (let ((position (point)))
6916 (insert " := ")
6917 (unless (vhdl-template-field "[initialization]" nil t)
6918 (delete-region position (point)))
6919 (insert ";")
6920 (vhdl-comment-insert-inline)))
6921
6922 (defun vhdl-template-quantity-branch ()
6923 "Insert a branch quantity declaration."
6924 (interactive)
6925 (let (position)
6926 (vhdl-insert-keyword "QUANTITY ")
6927 (when (vhdl-template-field "[across names]" " " t)
6928 (vhdl-insert-keyword "ACROSS "))
6929 (when (vhdl-template-field "[through names]" " " t)
6930 (vhdl-insert-keyword "THROUGH "))
6931 (vhdl-template-field "plus terminal name")
6932 (setq position (point))
6933 (vhdl-insert-keyword " TO ")
6934 (unless (vhdl-template-field "[minus terminal name]" nil t)
6935 (delete-region position (point)))
6936 (insert ";")
6937 (vhdl-comment-insert-inline)))
6938
6939 (defun vhdl-template-quantity-source ()
6940 "Insert a source quantity declaration."
6941 (interactive)
6942 (vhdl-insert-keyword "QUANTITY ")
6943 (vhdl-template-field "names")
6944 (insert " : ")
6945 (vhdl-template-field "type" " ")
6946 (if (eq (vhdl-decision-query nil "(s)pectrum or (n)oise?") ?n)
6947 (progn (vhdl-insert-keyword "NOISE ")
6948 (vhdl-template-field "power expression"))
6949 (vhdl-insert-keyword "SPECTRUM ")
6950 (vhdl-template-field "magnitude expression" ", ")
6951 (vhdl-template-field "phase expression"))
6952 (insert ";")
6953 (vhdl-comment-insert-inline))
6954
6955 (defun vhdl-template-record (kind &optional name secondary)
6956 "Insert a record type declaration."
6957 (interactive)
6958 (let ((margin (current-column))
6959 (start (point))
6960 (first t))
6961 (vhdl-insert-keyword "RECORD\n")
6962 (indent-to (+ margin vhdl-basic-offset))
6963 (when (or (vhdl-template-field "element names"
6964 nil (not secondary) start (point))
6965 secondary)
6966 (while (or first (vhdl-template-field "[element names]" nil t))
6967 (insert " : ")
6968 (vhdl-template-field (if (eq kind 'type) "type" "nature") ";")
6969 (vhdl-comment-insert-inline)
6970 (insert "\n")
6971 (indent-to (+ margin vhdl-basic-offset))
6972 (setq first nil))
6973 (kill-line -0)
6974 (indent-to margin)
6975 (vhdl-insert-keyword "END RECORD")
6976 (unless (vhdl-standard-p '87) (and name (insert " " name)))
6977 (insert ";")
6978 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
6979
6980 (defun vhdl-template-report ()
6981 "Insert a report statement."
6982 (interactive)
6983 (let ((start (point)))
6984 (vhdl-insert-keyword "REPORT ")
6985 (if (equal "\"\"" (vhdl-template-field
6986 "string expression" nil t start (point) t))
6987 (backward-delete-char 2)
6988 (setq start (point))
6989 (vhdl-insert-keyword " SEVERITY ")
6990 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
6991 (delete-region start (point)))
6992 (insert ";"))))
6993
6994 (defun vhdl-template-return ()
6995 "Insert a return statement."
6996 (interactive)
6997 (vhdl-insert-keyword "RETURN ")
6998 (unless (vhdl-template-field "[expression]" nil t)
6999 (delete-char -1))
7000 (insert ";"))
7001
7002 (defun vhdl-template-selected-signal-asst ()
7003 "Insert a selected signal assignment."
7004 (interactive)
7005 (let ((margin (current-indentation))
7006 (start (point))
7007 (choices t))
7008 (let ((position (point)))
7009 (vhdl-insert-keyword " SELECT ")
7010 (goto-char position))
7011 (vhdl-insert-keyword "WITH ")
7012 (when (vhdl-template-field "selector expression"
7013 nil t start (+ (point) 7))
7014 (forward-word 1)
7015 (delete-char 1)
7016 (insert "\n")
7017 (indent-to (+ margin vhdl-basic-offset))
7018 (vhdl-template-field "target signal" " <= ")
7019 ; (vhdl-template-field "[GUARDED] [TRANSPORT]")
7020 (insert "\n")
7021 (indent-to (+ margin vhdl-basic-offset))
7022 (vhdl-template-field "waveform")
7023 (vhdl-insert-keyword " WHEN ")
7024 (vhdl-template-field "choices" ",")
7025 (insert "\n")
7026 (indent-to (+ margin vhdl-basic-offset))
7027 (while (and choices (vhdl-template-field "[waveform]" nil t))
7028 (vhdl-insert-keyword " WHEN ")
7029 (if (setq choices (vhdl-template-field "[choices]" "," t))
7030 (progn (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
7031 (vhdl-insert-keyword "OTHERS")))
7032 (when choices
7033 (fixup-whitespace)
7034 (delete-char -2))
7035 (insert ";")
7036 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
7037
7038 (defun vhdl-template-signal ()
7039 "Insert a signal declaration."
7040 (interactive)
7041 (let ((start (point))
7042 (in-arglist (vhdl-in-argument-list-p)))
7043 (vhdl-insert-keyword "SIGNAL ")
7044 (when (vhdl-template-field "names" nil t start (point))
7045 (insert " : ")
7046 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7047 (vhdl-template-field "type")
7048 (if in-arglist
7049 (progn (insert ";")
7050 (vhdl-comment-insert-inline))
7051 (let ((position (point)))
7052 (insert " := ")
7053 (unless (vhdl-template-field "[initialization]" nil t)
7054 (delete-region position (point)))
7055 (insert ";")
7056 (vhdl-comment-insert-inline))))))
7057
7058 (defun vhdl-template-subnature ()
7059 "Insert a subnature declaration."
7060 (interactive)
7061 (let ((start (point))
7062 position)
7063 (vhdl-insert-keyword "SUBNATURE ")
7064 (when (vhdl-template-field "name" nil t start (point))
7065 (vhdl-insert-keyword " IS ")
7066 (vhdl-template-field "nature" " (")
7067 (if (vhdl-template-field "[index range]" nil t)
7068 (insert ")")
7069 (delete-char -2))
7070 (setq position (point))
7071 (vhdl-insert-keyword " TOLERANCE ")
7072 (if (equal "\"\"" (vhdl-template-field "[string expression]"
7073 nil t nil nil t))
7074 (delete-region position (point))
7075 (vhdl-insert-keyword " ACROSS ")
7076 (vhdl-template-field "string expression" nil nil nil nil t)
7077 (vhdl-insert-keyword " THROUGH"))
7078 (insert ";")
7079 (vhdl-comment-insert-inline))))
7080
7081 (defun vhdl-template-subprogram-body ()
7082 "Insert a subprogram body."
7083 (interactive)
7084 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7085 (vhdl-template-function-body)
7086 (vhdl-template-procedure-body)))
7087
7088 (defun vhdl-template-subprogram-decl ()
7089 "Insert a subprogram declaration."
7090 (interactive)
7091 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7092 (vhdl-template-function-decl)
7093 (vhdl-template-procedure-decl)))
7094
7095 (defun vhdl-template-subtype ()
7096 "Insert a subtype declaration."
7097 (interactive)
7098 (let ((start (point)))
7099 (vhdl-insert-keyword "SUBTYPE ")
7100 (when (vhdl-template-field "name" nil t start (point))
7101 (vhdl-insert-keyword " IS ")
7102 (vhdl-template-field "type" " ")
7103 (unless
7104 (vhdl-template-field "[RANGE value range | ( index range )]" nil t)
7105 (delete-char -1))
7106 (insert ";")
7107 (vhdl-comment-insert-inline))))
7108
7109 (defun vhdl-template-terminal ()
7110 "Insert a terminal declaration."
7111 (interactive)
7112 (let ((start (point)))
7113 (vhdl-insert-keyword "TERMINAL ")
7114 (when (vhdl-template-field "names" nil t start (point))
7115 (insert " : ")
7116 (vhdl-template-field "nature")
7117 (insert ";")
7118 (vhdl-comment-insert-inline))))
7119
7120 (defun vhdl-template-type ()
7121 "Insert a type declaration."
7122 (interactive)
7123 (let ((start (point))
7124 name mid-pos end-pos)
7125 (vhdl-insert-keyword "TYPE ")
7126 (when (setq name (vhdl-template-field "name" nil t start (point)))
7127 (vhdl-insert-keyword " IS ")
7128 (let ((definition
7129 (upcase
7130 (or (vhdl-template-field
7131 "[scalar type | ARRAY | RECORD | ACCESS | FILE]" nil t)
7132 ""))))
7133 (cond ((equal definition "")
7134 (backward-delete-char 4)
7135 (insert ";"))
7136 ((equal definition "ARRAY")
7137 (kill-word -1)
7138 (vhdl-template-array 'type t))
7139 ((equal definition "RECORD")
7140 (setq mid-pos (point-marker))
7141 (kill-word -1)
7142 (vhdl-template-record 'type name t))
7143 ((equal definition "ACCESS")
7144 (insert " ")
7145 (vhdl-template-field "type" ";"))
7146 ((equal definition "FILE")
7147 (vhdl-insert-keyword " OF ")
7148 (vhdl-template-field "type" ";"))
7149 (t (insert ";")))
7150 (when mid-pos
7151 (setq end-pos (point-marker))
7152 (goto-char mid-pos)
7153 (end-of-line))
7154 (vhdl-comment-insert-inline)
7155 (when end-pos (goto-char end-pos))))))
7156
7157 (defun vhdl-template-use ()
7158 "Insert a use clause."
7159 (interactive)
7160 (let ((start (point))
7161 (case-fold-search t))
7162 (vhdl-ext-syntax-table
7163 (vhdl-insert-keyword "USE ")
7164 (when (save-excursion (beginning-of-line) (looking-at "^\\s-*use\\>"))
7165 (vhdl-insert-keyword "..ALL;")
7166 (backward-char 6)
7167 (when (vhdl-template-field "library name" nil t start (+ (point) 6))
7168 (forward-char 1)
7169 (vhdl-template-field "package name")
7170 (forward-char 5))))))
7171
7172 (defun vhdl-template-variable ()
7173 "Insert a variable declaration."
7174 (interactive)
7175 (let ((start (point))
7176 (case-fold-search t)
7177 (in-arglist (vhdl-in-argument-list-p)))
7178 (vhdl-ext-syntax-table
7179 (if (or (save-excursion
7180 (and (re-search-backward
7181 "\\<function\\|procedure\\|process\\|procedural\\|end\\>"
7182 nil t)
7183 (not (progn (backward-word 1) (looking-at "\\<end\\>")))))
7184 (save-excursion (backward-word 1) (looking-at "\\<shared\\>")))
7185 (vhdl-insert-keyword "VARIABLE ")
7186 (vhdl-insert-keyword "SHARED VARIABLE ")))
7187 (when (vhdl-template-field "names" nil t start (point))
7188 (insert " : ")
7189 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7190 (vhdl-template-field "type")
7191 (if in-arglist
7192 (progn (insert ";")
7193 (vhdl-comment-insert-inline))
7194 (let ((position (point)))
7195 (insert " := ")
7196 (unless (vhdl-template-field "[initialization]" nil t)
7197 (delete-region position (point)))
7198 (insert ";")
7199 (vhdl-comment-insert-inline))))))
7200
7201 (defun vhdl-template-wait ()
7202 "Insert a wait statement."
7203 (interactive)
7204 (vhdl-insert-keyword "WAIT ")
7205 (unless (vhdl-template-field
7206 "[ON sensitivity list] [UNTIL condition] [FOR time expression]"
7207 nil t)
7208 (delete-char -1))
7209 (insert ";"))
7210
7211 (defun vhdl-template-when ()
7212 "Indent correctly if within a case statement."
7213 (interactive)
7214 (let ((position (point))
7215 (case-fold-search t)
7216 margin)
7217 (vhdl-ext-syntax-table
7218 (if (and (= (current-column) (current-indentation))
7219 (re-search-forward "\\<end\\>" nil t)
7220 (looking-at "\\s-*\\<case\\>"))
7221 (progn
7222 (setq margin (current-indentation))
7223 (goto-char position)
7224 (delete-horizontal-space)
7225 (indent-to (+ margin vhdl-basic-offset)))
7226 (goto-char position)))
7227 (vhdl-insert-keyword "WHEN ")))
7228
7229 (defun vhdl-template-while-loop ()
7230 "Insert a while loop."
7231 (interactive)
7232 (let* ((margin (current-indentation))
7233 (start (point))
7234 label)
7235 (if (not (eq vhdl-optional-labels 'all))
7236 (vhdl-insert-keyword "WHILE ")
7237 (vhdl-insert-keyword ": WHILE ")
7238 (goto-char start)
7239 (setq label (vhdl-template-field "[label]" nil t))
7240 (unless label (delete-char 2))
7241 (forward-word 1)
7242 (forward-char 1))
7243 (when vhdl-conditions-in-parenthesis (insert "("))
7244 (when (vhdl-template-field "condition" nil t start (point))
7245 (when vhdl-conditions-in-parenthesis (insert ")"))
7246 (vhdl-insert-keyword " LOOP\n\n")
7247 (indent-to margin)
7248 (vhdl-insert-keyword "END LOOP")
7249 (insert (if label (concat " " label ";") ";"))
7250 (forward-line -1)
7251 (indent-to (+ margin vhdl-basic-offset)))))
7252
7253 (defun vhdl-template-with ()
7254 "Insert a with statement (i.e. selected signal assignment)."
7255 (interactive)
7256 (let ((case-fold-search t))
7257 (vhdl-ext-syntax-table
7258 (if (save-excursion
7259 (re-search-backward "\\(\\<limit\\>\\|;\\)")
7260 (equal ";" (match-string 1)))
7261 (vhdl-template-selected-signal-asst)
7262 (vhdl-insert-keyword "WITH ")))))
7263
7264 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7265 ;; Special templates
7266
7267 (defun vhdl-template-clocked-wait ()
7268 "Insert a wait statement for rising/falling clock edge."
7269 (interactive)
7270 (let ((start (point))
7271 clock)
7272 (vhdl-insert-keyword "WAIT UNTIL ")
7273 (when (setq clock
7274 (or (and (not (equal "" vhdl-clock-name))
7275 (progn (insert vhdl-clock-name) vhdl-clock-name))
7276 (vhdl-template-field "clock name" nil t start (point))))
7277 (insert "'event")
7278 (vhdl-insert-keyword " AND ")
7279 (insert clock)
7280 (insert
7281 " = " (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string) ";")
7282 (vhdl-comment-insert-inline
7283 (concat (if vhdl-clock-rising-edge "rising" "falling")
7284 " clock edge")))))
7285
7286 (defun vhdl-template-seq-process (clock reset)
7287 "Insert a template for the body of a sequential process."
7288 (let ((margin (current-indentation))
7289 position)
7290 (vhdl-insert-keyword "IF ")
7291 (when (eq vhdl-reset-kind 'async)
7292 (insert reset " = "
7293 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7294 (vhdl-insert-keyword " THEN")
7295 (vhdl-comment-insert-inline
7296 (concat "asynchronous reset (active "
7297 (if vhdl-reset-active-high "high" "low") ")"))
7298 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7299 (setq position (point))
7300 (insert "\n") (indent-to margin)
7301 (vhdl-insert-keyword "ELSIF "))
7302 (if (eq vhdl-clock-edge-condition 'function)
7303 (insert (if vhdl-clock-rising-edge "rising" "falling")
7304 "_edge(" clock ")")
7305 (insert clock "'event")
7306 (vhdl-insert-keyword " AND ")
7307 (insert clock " = "
7308 (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string)))
7309 (vhdl-insert-keyword " THEN")
7310 (vhdl-comment-insert-inline
7311 (concat (if vhdl-clock-rising-edge "rising" "falling") " clock edge"))
7312 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7313 (when (eq vhdl-reset-kind 'sync)
7314 (vhdl-insert-keyword "IF ")
7315 (setq reset (or (and (not (equal "" vhdl-reset-name))
7316 (progn (insert vhdl-reset-name) vhdl-reset-name))
7317 (vhdl-template-field "reset name") "<reset>"))
7318 (insert " = "
7319 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7320 (vhdl-insert-keyword " THEN")
7321 (vhdl-comment-insert-inline
7322 (concat "synchronous reset (active "
7323 (if vhdl-reset-active-high "high" "low") ")"))
7324 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7325 (setq position (point))
7326 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7327 (vhdl-insert-keyword "ELSE")
7328 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7329 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7330 (vhdl-insert-keyword "END IF;"))
7331 (when (eq vhdl-reset-kind 'none)
7332 (setq position (point)))
7333 (insert "\n") (indent-to margin)
7334 (vhdl-insert-keyword "END IF;")
7335 (goto-char position)
7336 reset))
7337
7338 (defun vhdl-template-standard-package (library package)
7339 "Insert specification of a standard package. Include a library
7340 specification, if not already there."
7341 (let ((margin (current-indentation))
7342 (case-fold-search t))
7343 (save-excursion
7344 (vhdl-ext-syntax-table
7345 (and (not (bobp))
7346 (re-search-backward
7347 (concat "^\\s-*\\(library\\s-+\\(\\(\\w\\|\\s_\\)+,\\s-+\\)*"
7348 library "\\|end\\)\\>") nil t))))
7349 (unless (and (match-string 1) (string-match "library" (match-string 1)))
7350 (vhdl-insert-keyword "LIBRARY ")
7351 (insert library ";\n")
7352 (indent-to margin))
7353 (vhdl-insert-keyword "USE ")
7354 (insert library "." package)
7355 (vhdl-insert-keyword ".ALL;")))
7356
7357 (defun vhdl-template-package-math-complex ()
7358 "Insert specification of `math_complex' package."
7359 (interactive)
7360 (vhdl-template-standard-package "ieee" "math_complex"))
7361
7362 (defun vhdl-template-package-math-real ()
7363 "Insert specification of `math_real' package."
7364 (interactive)
7365 (vhdl-template-standard-package "ieee" "math_real"))
7366
7367 (defun vhdl-template-package-numeric-bit ()
7368 "Insert specification of `numeric_bit' package."
7369 (interactive)
7370 (vhdl-template-standard-package "ieee" "numeric_bit"))
7371
7372 (defun vhdl-template-package-numeric-std ()
7373 "Insert specification of `numeric_std' package."
7374 (interactive)
7375 (vhdl-template-standard-package "ieee" "numeric_std"))
7376
7377 (defun vhdl-template-package-std-logic-1164 ()
7378 "Insert specification of `std_logic_1164' package."
7379 (interactive)
7380 (vhdl-template-standard-package "ieee" "std_logic_1164"))
7381
7382 (defun vhdl-template-package-std-logic-arith ()
7383 "Insert specification of `std_logic_arith' package."
7384 (interactive)
7385 (vhdl-template-standard-package "ieee" "std_logic_arith"))
7386
7387 (defun vhdl-template-package-std-logic-misc ()
7388 "Insert specification of `std_logic_misc' package."
7389 (interactive)
7390 (vhdl-template-standard-package "ieee" "std_logic_misc"))
7391
7392 (defun vhdl-template-package-std-logic-signed ()
7393 "Insert specification of `std_logic_signed' package."
7394 (interactive)
7395 (vhdl-template-standard-package "ieee" "std_logic_signed"))
7396
7397 (defun vhdl-template-package-std-logic-textio ()
7398 "Insert specification of `std_logic_textio' package."
7399 (interactive)
7400 (vhdl-template-standard-package "ieee" "std_logic_textio"))
7401
7402 (defun vhdl-template-package-std-logic-unsigned ()
7403 "Insert specification of `std_logic_unsigned' package."
7404 (interactive)
7405 (vhdl-template-standard-package "ieee" "std_logic_unsigned"))
7406
7407 (defun vhdl-template-package-textio ()
7408 "Insert specification of `textio' package."
7409 (interactive)
7410 (vhdl-template-standard-package "std" "textio"))
7411
7412 (defun vhdl-template-directive (directive)
7413 "Insert directive."
7414 (unless (= (current-indentation) (current-column))
7415 (delete-horizontal-space)
7416 (insert " "))
7417 (insert "-- pragma " directive))
7418
7419 (defun vhdl-template-directive-translate-on ()
7420 "Insert directive 'translate_on'."
7421 (interactive)
7422 (vhdl-template-directive "translate_on"))
7423
7424 (defun vhdl-template-directive-translate-off ()
7425 "Insert directive 'translate_off'."
7426 (interactive)
7427 (vhdl-template-directive "translate_off"))
7428
7429 (defun vhdl-template-directive-synthesis-on ()
7430 "Insert directive 'synthesis_on'."
7431 (interactive)
7432 (vhdl-template-directive "synthesis_on"))
7433
7434 (defun vhdl-template-directive-synthesis-off ()
7435 "Insert directive 'synthesis_off'."
7436 (interactive)
7437 (vhdl-template-directive "synthesis_off"))
7438
7439 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7440 ;; Comment templates and functions
7441
7442 (defun vhdl-comment-indent ()
7443 "Indent comments."
7444 (let* ((position (point))
7445 (col
7446 (progn
7447 (forward-line -1)
7448 (if (re-search-forward "--" position t)
7449 (- (current-column) 2) ; existing comment at bol stays there
7450 (goto-char position)
7451 (skip-chars-backward " \t")
7452 (max comment-column ; else indent to comment column
7453 (1+ (current-column))))))) ; except leave at least one space
7454 (goto-char position)
7455 col))
7456
7457 (defun vhdl-comment-insert ()
7458 "Start a comment at the end of the line.
7459 If on line with code, indent at least `comment-column'.
7460 If starting after end-comment-column, start a new line."
7461 (interactive)
7462 (when (> (current-column) end-comment-column) (newline-and-indent))
7463 (if (or (looking-at "\\s-*$") ; end of line
7464 (and (not unread-command-events) ; called with key binding or menu
7465 (not (end-of-line))))
7466 (let (margin)
7467 (while (= (preceding-char) ?-) (delete-char -1))
7468 (setq margin (current-column))
7469 (delete-horizontal-space)
7470 (if (bolp)
7471 (progn (indent-to margin) (insert "--"))
7472 (insert " ")
7473 (indent-to comment-column)
7474 (insert "--"))
7475 (if (not unread-command-events) (insert " ")))
7476 ;; else code following current point implies commenting out code
7477 (let (next-input code)
7478 (while (= (preceding-char) ?-) (delete-char -2))
7479 (while (= (setq next-input (read-char)) 13) ; CR
7480 (insert "--") ; or have a space after it?
7481 (forward-char -2)
7482 (forward-line 1)
7483 (message "Enter CR if commenting out a line of code.")
7484 (setq code t))
7485 (when (not code)
7486 (insert "--")) ; hardwire to 1 space or use vhdl-basic-offset?
7487 (setq unread-command-events
7488 (list (vhdl-character-to-event next-input)))))) ; pushback the char
7489
7490 (defun vhdl-comment-display (&optional line-exists)
7491 "Add 2 comment lines at the current indent, making a display comment."
7492 (interactive)
7493 (let ((margin (current-indentation)))
7494 (when (not line-exists) (vhdl-comment-display-line))
7495 (insert "\n") (indent-to margin)
7496 (insert "\n") (indent-to margin)
7497 (vhdl-comment-display-line)
7498 (end-of-line -0)
7499 (insert "-- ")))
7500
7501 (defun vhdl-comment-display-line ()
7502 "Displays one line of dashes."
7503 (interactive)
7504 (while (= (preceding-char) ?-) (delete-char -2))
7505 (let* ((col (current-column))
7506 (len (- end-comment-column col)))
7507 (insert-char ?- len)))
7508
7509 (defun vhdl-comment-append-inline ()
7510 "Append empty inline comment to current line."
7511 (interactive)
7512 (end-of-line)
7513 (delete-horizontal-space)
7514 (insert " ")
7515 (indent-to comment-column)
7516 (insert "-- "))
7517
7518 (defun vhdl-comment-insert-inline (&optional string always-insert)
7519 "Insert inline comment."
7520 (when (or (and string (or vhdl-self-insert-comments always-insert))
7521 (and (not string) vhdl-prompt-for-comments))
7522 (let ((position (point)))
7523 (insert " ")
7524 (indent-to comment-column)
7525 (insert "-- ")
7526 (if (or (and string (progn (insert string) t))
7527 (vhdl-template-field "[comment]" nil t))
7528 (when (> (current-column) end-comment-column)
7529 (setq position (point-marker))
7530 (re-search-backward "-- ")
7531 (insert "\n")
7532 (indent-to comment-column)
7533 (goto-char position))
7534 (delete-region position (point))))))
7535
7536 (defun vhdl-comment-block ()
7537 "Insert comment for code block."
7538 (when vhdl-prompt-for-comments
7539 (let ((final-pos (point-marker))
7540 (case-fold-search t))
7541 (vhdl-ext-syntax-table
7542 (when (and (re-search-backward "^\\s-*begin\\>" nil t)
7543 (re-search-backward
7544 "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\|procedural\\)\\>"
7545 nil t))
7546 (let (margin)
7547 (back-to-indentation)
7548 (setq margin (current-column))
7549 (end-of-line -0)
7550 (if (bobp)
7551 (progn (insert "\n") (forward-line -1))
7552 (insert "\n"))
7553 (indent-to margin)
7554 (insert "-- purpose: ")
7555 (unless (vhdl-template-field "[description]" nil t)
7556 (vhdl-line-kill-entire)))))
7557 (goto-char final-pos))))
7558
7559 (defun vhdl-comment-uncomment-region (beg end &optional arg)
7560 "Comment out region if not commented out, uncomment otherwise."
7561 (interactive "r\nP")
7562 (save-excursion
7563 (goto-char (1- end))
7564 (end-of-line)
7565 (setq end (point-marker))
7566 (goto-char beg)
7567 (beginning-of-line)
7568 (setq beg (point))
7569 (if (looking-at comment-start)
7570 (comment-region beg end -1)
7571 (comment-region beg end))))
7572
7573 (defun vhdl-comment-uncomment-line (&optional arg)
7574 "Comment out line if not commented out, uncomment otherwise."
7575 (interactive "p")
7576 (save-excursion
7577 (beginning-of-line)
7578 (let ((position (point)))
7579 (forward-line (or arg 1))
7580 (vhdl-comment-uncomment-region position (point)))))
7581
7582 (defun vhdl-comment-kill-region (beg end)
7583 "Kill comments in region."
7584 (interactive "r")
7585 (save-excursion
7586 (goto-char end)
7587 (setq end (point-marker))
7588 (goto-char beg)
7589 (beginning-of-line)
7590 (while (< (point) end)
7591 (if (looking-at "^\\(\\s-*--.*\n\\)")
7592 (progn (delete-region (match-beginning 1) (match-end 1)))
7593 (beginning-of-line 2)))))
7594
7595 (defun vhdl-comment-kill-inline-region (beg end)
7596 "Kill inline comments in region."
7597 (interactive "r")
7598 (save-excursion
7599 (goto-char end)
7600 (setq end (point-marker))
7601 (goto-char beg)
7602 (beginning-of-line)
7603 (while (< (point) end)
7604 (when (looking-at "^.*[^ \t\n-]+\\(\\s-*--.*\\)$")
7605 (delete-region (match-beginning 1) (match-end 1)))
7606 (beginning-of-line 2))))
7607
7608 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7609 ;; Subtemplates
7610
7611 (defun vhdl-template-begin-end (construct name margin &optional empty-lines)
7612 "Insert a begin ... end pair with optional name after the end.
7613 Point is left between them."
7614 (let (position)
7615 (insert "\n")
7616 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7617 (indent-to margin)
7618 (vhdl-insert-keyword "BEGIN")
7619 (when (and (or construct name) vhdl-self-insert-comments)
7620 (insert " --")
7621 (when construct (insert " ") (vhdl-insert-keyword construct))
7622 (when name (insert " " name)))
7623 (insert "\n")
7624 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7625 (indent-to (+ margin vhdl-basic-offset))
7626 (setq position (point))
7627 (insert "\n")
7628 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
7629 (indent-to margin)
7630 (vhdl-insert-keyword "END")
7631 (when construct (insert " ") (vhdl-insert-keyword construct))
7632 (insert (if name (concat " " name) "") ";")
7633 (goto-char position)))
7634
7635 (defun vhdl-template-argument-list (&optional is-function)
7636 "Read from user a procedure or function argument list."
7637 (insert " (")
7638 (let ((margin (current-column))
7639 (start (point))
7640 (end-pos (point))
7641 not-empty interface semicolon-pos)
7642 (when (not vhdl-argument-list-indent)
7643 (setq margin (+ (current-indentation) vhdl-basic-offset))
7644 (insert "\n")
7645 (indent-to margin))
7646 (setq interface (vhdl-template-field
7647 (concat "[CONSTANT | SIGNAL"
7648 (unless is-function " | VARIABLE") "]") " " t))
7649 (while (vhdl-template-field "[names]" nil t)
7650 (setq not-empty t)
7651 (insert " : ")
7652 (when (not is-function)
7653 (if (and interface (equal (upcase interface) "CONSTANT"))
7654 (vhdl-insert-keyword "IN ")
7655 (vhdl-template-field "[IN | OUT | INOUT]" " " t)))
7656 (vhdl-template-field "type")
7657 (setq semicolon-pos (point))
7658 (insert ";")
7659 (vhdl-comment-insert-inline)
7660 (setq end-pos (point))
7661 (insert "\n")
7662 (indent-to margin)
7663 (setq interface (vhdl-template-field
7664 (concat "[CONSTANT | SIGNAL"
7665 (unless is-function " | VARIABLE") "]") " " t)))
7666 (delete-region end-pos (point))
7667 (when semicolon-pos (goto-char semicolon-pos))
7668 (if not-empty
7669 (progn (delete-char 1) (insert ")"))
7670 (backward-delete-char 2))))
7671
7672 (defun vhdl-template-generic-list (optional &optional no-value)
7673 "Read from user a generic spec argument list."
7674 (let (margin
7675 (start (point)))
7676 (vhdl-insert-keyword "GENERIC (")
7677 (setq margin (current-column))
7678 (when (not vhdl-argument-list-indent)
7679 (let ((position (point)))
7680 (back-to-indentation)
7681 (setq margin (+ (current-column) vhdl-basic-offset))
7682 (goto-char position)
7683 (insert "\n")
7684 (indent-to margin)))
7685 (let ((vhdl-generics (vhdl-template-field
7686 (concat (and optional "[") "name"
7687 (and no-value "s") (and optional "]"))
7688 nil optional)))
7689 (if (not vhdl-generics)
7690 (if optional
7691 (progn (vhdl-line-kill-entire) (end-of-line -0)
7692 (when (not vhdl-argument-list-indent)
7693 (vhdl-line-kill-entire) (end-of-line -0)))
7694 (vhdl-template-undo start (point))
7695 nil )
7696 (insert " : ")
7697 (let (semicolon-pos end-pos)
7698 (while vhdl-generics
7699 (vhdl-template-field "type")
7700 (if no-value
7701 (progn (setq semicolon-pos (point))
7702 (insert ";"))
7703 (insert " := ")
7704 (unless (vhdl-template-field "[value]" nil t)
7705 (delete-char -4))
7706 (setq semicolon-pos (point))
7707 (insert ";"))
7708 (vhdl-comment-insert-inline)
7709 (setq end-pos (point))
7710 (insert "\n")
7711 (indent-to margin)
7712 (setq vhdl-generics (vhdl-template-field
7713 (concat "[name" (and no-value "s") "]")
7714 " : " t)))
7715 (delete-region end-pos (point))
7716 (goto-char semicolon-pos)
7717 (insert ")")
7718 (end-of-line)
7719 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
7720 t)))))
7721
7722 (defun vhdl-template-port-list (optional)
7723 "Read from user a port spec argument list."
7724 (let ((start (point))
7725 margin vhdl-ports object)
7726 (vhdl-insert-keyword "PORT (")
7727 (setq margin (current-column))
7728 (when (not vhdl-argument-list-indent)
7729 (let ((position (point)))
7730 (back-to-indentation)
7731 (setq margin (+ (current-column) vhdl-basic-offset))
7732 (goto-char position)
7733 (insert "\n")
7734 (indent-to margin)))
7735 (when (vhdl-standard-p 'ams)
7736 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7737 " " t)))
7738 (setq vhdl-ports (vhdl-template-field
7739 (concat (and optional "[") "names" (and optional "]"))
7740 nil optional))
7741 (if (not vhdl-ports)
7742 (if optional
7743 (progn (vhdl-line-kill-entire) (end-of-line -0)
7744 (when (not vhdl-argument-list-indent)
7745 (vhdl-line-kill-entire) (end-of-line -0)))
7746 (vhdl-template-undo start (point))
7747 nil)
7748 (insert " : ")
7749 (let (semicolon-pos end-pos)
7750 (while vhdl-ports
7751 (cond ((or (null object) (equal "SIGNAL" (upcase object)))
7752 (vhdl-template-field "IN | OUT | INOUT" " "))
7753 ((equal "QUANTITY" (upcase object))
7754 (vhdl-template-field "[IN | OUT]" " " t)))
7755 (vhdl-template-field
7756 (if (and object (equal "TERMINAL" (upcase object)))
7757 "nature" "type"))
7758 (setq semicolon-pos (point))
7759 (insert ";")
7760 (vhdl-comment-insert-inline)
7761 (setq end-pos (point))
7762 (insert "\n")
7763 (indent-to margin)
7764 (when (vhdl-standard-p 'ams)
7765 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7766 " " t)))
7767 (setq vhdl-ports (vhdl-template-field "[names]" " : " t)))
7768 (delete-region end-pos (point))
7769 (goto-char semicolon-pos)
7770 (insert ")")
7771 (end-of-line)
7772 (when vhdl-auto-align (vhdl-align-noindent-region start end-pos 1))
7773 t))))
7774
7775 (defun vhdl-template-generate-body (margin label)
7776 "Insert body for generate template."
7777 (vhdl-insert-keyword " GENERATE")
7778 (if (not (vhdl-standard-p '87))
7779 (vhdl-template-begin-end "GENERATE" label margin)
7780 (insert "\n\n")
7781 (indent-to margin)
7782 (vhdl-insert-keyword "END GENERATE ")
7783 (insert label ";")
7784 (end-of-line 0)
7785 (indent-to (+ margin vhdl-basic-offset))))
7786
7787 (defun vhdl-template-insert-date ()
7788 "Insert date in appropriate format."
7789 (interactive)
7790 (insert
7791 (cond
7792 ;; 'american, 'european', 'scientific kept for backward compatibility
7793 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
7794 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
7795 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
7796 (t (format-time-string vhdl-date-format nil)))))
7797
7798 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7799 ;; Help functions
7800
7801 (defun vhdl-electric-space (count)
7802 "Expand abbreviations and self-insert space(s), do indent-new-comment-line
7803 if in comment and past end-comment-column."
7804 (interactive "p")
7805 (cond ((vhdl-in-comment-p)
7806 (self-insert-command count)
7807 (cond ((>= (current-column) (+ 2 end-comment-column))
7808 (backward-word 1)
7809 (indent-new-comment-line)
7810 (forward-word 1)
7811 (forward-char 1))
7812 ((>= (current-column) end-comment-column)
7813 (indent-new-comment-line))
7814 (t nil)))
7815 ((or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
7816 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
7817 (vhdl-ext-syntax-table
7818 (let ((case-fold-search t))
7819 (expand-abbrev)))
7820 (self-insert-command count))
7821 (t (self-insert-command count))))
7822
7823 (defun vhdl-template-field (prompt &optional follow-string optional
7824 begin end is-string default)
7825 "Prompt for string and insert it in buffer with optional FOLLOW-STRING.
7826 If OPTIONAL is nil, the prompt is left if an empty string is inserted. If
7827 an empty string is inserted, return nil and call `vhdl-template-undo' for
7828 the region between BEGIN and END. IS-STRING indicates whether a string
7829 with double-quotes is to be inserted. DEFAULT specifies a default string."
7830 (let ((position (point))
7831 string)
7832 (insert "<" prompt ">")
7833 (setq string
7834 (condition-case ()
7835 (read-from-minibuffer (concat prompt ": ")
7836 (or (and is-string '("\"\"" . 2)) default)
7837 vhdl-minibuffer-local-map)
7838 (quit (if (and optional begin end)
7839 (progn (beep) "")
7840 (keyboard-quit)))))
7841 (when (or (not (equal string "")) optional)
7842 (delete-region position (point)))
7843 (when (and (equal string "") optional begin end)
7844 (vhdl-template-undo begin end)
7845 (message "Template aborted"))
7846 (when (not (equal string ""))
7847 (insert string)
7848 (vhdl-fix-case-region-1 position (point) vhdl-upper-case-keywords
7849 vhdl-keywords-regexp))
7850 (when (or (not (equal string "")) (not optional))
7851 (insert (or follow-string "")))
7852 (if (equal string "") nil string)))
7853
7854 (defun vhdl-decision-query (string prompt &optional optional)
7855 "Query a decision from the user."
7856 (let ((start (point)))
7857 (when string (vhdl-insert-keyword (concat string " ")))
7858 (message prompt)
7859 (let ((char (read-char)))
7860 (delete-region start (point))
7861 (if (and optional (eq char ?\r))
7862 (progn (insert " ")
7863 (unexpand-abbrev)
7864 (throw 'abort "Template aborted"))
7865 char))))
7866
7867 (defun vhdl-insert-keyword (keyword)
7868 "Insert KEYWORD and adjust case."
7869 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))))
7870
7871 (defun vhdl-case-keyword (keyword)
7872 "Adjust case of KEYWORD."
7873 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
7874
7875 (defun vhdl-case-word (num)
7876 "Adjust case or following NUM words."
7877 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num)))
7878
7879 (defun vhdl-minibuffer-tab (&optional prefix-arg)
7880 "If preceeding character is part of a word or a paren then hippie-expand,
7881 else if right of non whitespace on line then tab-to-tab-stop,
7882 else indent line in proper way for current major mode (used for word
7883 completion in VHDL minibuffer)."
7884 (interactive "P")
7885 (cond ((= (char-syntax (preceding-char)) ?w)
7886 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7887 (case-replace nil))
7888 (vhdl-expand-abbrev prefix-arg)))
7889 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
7890 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7891 (case-replace nil))
7892 (vhdl-expand-paren prefix-arg)))
7893 ((> (current-column) (current-indentation))
7894 (tab-to-tab-stop))
7895 (t (if (eq indent-line-function 'indent-to-left-margin)
7896 (insert-tab prefix-arg)
7897 (if prefix-arg
7898 (funcall indent-line-function prefix-arg)
7899 (funcall indent-line-function))))))
7900
7901 (defun vhdl-template-search-prompt ()
7902 "Search for left out template prompts and query again."
7903 (interactive)
7904 (let ((case-fold-search t))
7905 (vhdl-ext-syntax-table
7906 (when (or (re-search-forward
7907 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t)
7908 (re-search-backward
7909 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t))
7910 (let ((string (match-string 1)))
7911 (replace-match "")
7912 (vhdl-template-field string))))))
7913
7914 (defun vhdl-template-undo (begin end)
7915 "Undo aborted template by deleting region and unexpanding the keyword."
7916 (cond (vhdl-template-invoked-by-hook
7917 (goto-char end)
7918 (insert " ")
7919 (delete-region begin end)
7920 (unexpand-abbrev))
7921 (t (delete-region begin end))))
7922
7923 (defun vhdl-insert-string-or-file (string)
7924 "Insert STRING or file contents if STRING is an existing file name."
7925 (unless (equal string "")
7926 (cond ((file-exists-p string)
7927 (forward-char (cadr (insert-file-contents string))))
7928 (t (insert string)))))
7929
7930 (defun vhdl-sequential-statement-p ()
7931 "Check if point is within sequential statement part."
7932 (save-excursion
7933 (let ((case-fold-search t)
7934 (start (point)))
7935 (vhdl-ext-syntax-table
7936 (set-match-data nil)
7937 (while (and (re-search-backward "^\\s-*\\(begin\\|end\\(\\s-*\\(case\\|if\\|loop\\)\\)?\\)\\>"
7938 nil t)
7939 (match-string 2)))
7940 (and (match-data)
7941 (equal "BEGIN" (upcase (match-string 1)))
7942 (re-search-backward "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(\\w+\\s-+\\)?\\(function\\|procedure\\|process\\|procedural\\|end\\)\\>"
7943 nil t)
7944 (not (equal "END" (upcase (match-string 3)))))))))
7945
7946 (defun vhdl-in-argument-list-p ()
7947 "Check if within an argument list."
7948 (save-excursion
7949 (let ((case-fold-search t))
7950 (vhdl-ext-syntax-table
7951 (or (string-match "arglist"
7952 (format "%s" (car (car (vhdl-get-syntactic-context)))))
7953 (progn (beginning-of-line)
7954 (looking-at "^\\s-*\\(generic\\|port\\|\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\>\\s-*\\(\\w+\\s-*\\)?(")
7955 ))))))
7956
7957 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7958 ;; Abbrev hooks
7959
7960 (defun vhdl-hooked-abbrev (func)
7961 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
7962 but not if inside a comment or quote)."
7963 (if (or (vhdl-in-comment-p)
7964 (vhdl-in-string-p)
7965 (save-excursion
7966 (forward-word -1)
7967 (and (looking-at "\\<end\\>") (not (looking-at "\\<end;")))))
7968 (progn
7969 (insert " ")
7970 (unexpand-abbrev)
7971 (delete-char -1))
7972 (if (not vhdl-electric-mode)
7973 (progn
7974 (insert " ")
7975 (unexpand-abbrev)
7976 (backward-word 1)
7977 (vhdl-case-word 1)
7978 (delete-char 1))
7979 (let ((invoke-char last-command-char)
7980 (abbrev-mode -1)
7981 (vhdl-template-invoked-by-hook t))
7982 (let ((caught (catch 'abort
7983 (funcall func))))
7984 (when (stringp caught) (message caught)))
7985 (when (= invoke-char ?-) (setq abbrev-start-location (point)))
7986 ;; delete CR which is still in event queue
7987 (if (string-match "XEmacs" emacs-version)
7988 (enqueue-eval-event 'delete-char -1)
7989 (setq unread-command-events ; push back a delete char
7990 (list (vhdl-character-to-event ?\177))))))))
7991
7992 (defun vhdl-template-alias-hook ()
7993 (vhdl-hooked-abbrev 'vhdl-template-alias))
7994 (defun vhdl-template-architecture-hook ()
7995 (vhdl-hooked-abbrev 'vhdl-template-architecture))
7996 (defun vhdl-template-assert-hook ()
7997 (vhdl-hooked-abbrev 'vhdl-template-assert))
7998 (defun vhdl-template-attribute-hook ()
7999 (vhdl-hooked-abbrev 'vhdl-template-attribute))
8000 (defun vhdl-template-block-hook ()
8001 (vhdl-hooked-abbrev 'vhdl-template-block))
8002 (defun vhdl-template-break-hook ()
8003 (vhdl-hooked-abbrev 'vhdl-template-break))
8004 (defun vhdl-template-case-hook ()
8005 (vhdl-hooked-abbrev 'vhdl-template-case))
8006 (defun vhdl-template-component-hook ()
8007 (vhdl-hooked-abbrev 'vhdl-template-component))
8008 (defun vhdl-template-instance-hook ()
8009 (vhdl-hooked-abbrev 'vhdl-template-instance))
8010 (defun vhdl-template-conditional-signal-asst-hook ()
8011 (vhdl-hooked-abbrev 'vhdl-template-conditional-signal-asst))
8012 (defun vhdl-template-configuration-hook ()
8013 (vhdl-hooked-abbrev 'vhdl-template-configuration))
8014 (defun vhdl-template-constant-hook ()
8015 (vhdl-hooked-abbrev 'vhdl-template-constant))
8016 (defun vhdl-template-disconnect-hook ()
8017 (vhdl-hooked-abbrev 'vhdl-template-disconnect))
8018 (defun vhdl-template-display-comment-hook ()
8019 (vhdl-hooked-abbrev 'vhdl-comment-display))
8020 (defun vhdl-template-else-hook ()
8021 (vhdl-hooked-abbrev 'vhdl-template-else))
8022 (defun vhdl-template-elsif-hook ()
8023 (vhdl-hooked-abbrev 'vhdl-template-elsif))
8024 (defun vhdl-template-entity-hook ()
8025 (vhdl-hooked-abbrev 'vhdl-template-entity))
8026 (defun vhdl-template-exit-hook ()
8027 (vhdl-hooked-abbrev 'vhdl-template-exit))
8028 (defun vhdl-template-file-hook ()
8029 (vhdl-hooked-abbrev 'vhdl-template-file))
8030 (defun vhdl-template-for-hook ()
8031 (vhdl-hooked-abbrev 'vhdl-template-for))
8032 (defun vhdl-template-function-hook ()
8033 (vhdl-hooked-abbrev 'vhdl-template-function))
8034 (defun vhdl-template-generic-hook ()
8035 (vhdl-hooked-abbrev 'vhdl-template-generic))
8036 (defun vhdl-template-group-hook ()
8037 (vhdl-hooked-abbrev 'vhdl-template-group))
8038 (defun vhdl-template-library-hook ()
8039 (vhdl-hooked-abbrev 'vhdl-template-library))
8040 (defun vhdl-template-limit-hook ()
8041 (vhdl-hooked-abbrev 'vhdl-template-limit))
8042 (defun vhdl-template-if-hook ()
8043 (vhdl-hooked-abbrev 'vhdl-template-if))
8044 (defun vhdl-template-bare-loop-hook ()
8045 (vhdl-hooked-abbrev 'vhdl-template-bare-loop))
8046 (defun vhdl-template-map-hook ()
8047 (vhdl-hooked-abbrev 'vhdl-template-map))
8048 (defun vhdl-template-nature-hook ()
8049 (vhdl-hooked-abbrev 'vhdl-template-nature))
8050 (defun vhdl-template-next-hook ()
8051 (vhdl-hooked-abbrev 'vhdl-template-next))
8052 (defun vhdl-template-package-hook ()
8053 (vhdl-hooked-abbrev 'vhdl-template-package))
8054 (defun vhdl-template-port-hook ()
8055 (vhdl-hooked-abbrev 'vhdl-template-port))
8056 (defun vhdl-template-procedural-hook ()
8057 (vhdl-hooked-abbrev 'vhdl-template-procedural))
8058 (defun vhdl-template-procedure-hook ()
8059 (vhdl-hooked-abbrev 'vhdl-template-procedure))
8060 (defun vhdl-template-process-hook ()
8061 (vhdl-hooked-abbrev 'vhdl-template-process))
8062 (defun vhdl-template-quantity-hook ()
8063 (vhdl-hooked-abbrev 'vhdl-template-quantity))
8064 (defun vhdl-template-report-hook ()
8065 (vhdl-hooked-abbrev 'vhdl-template-report))
8066 (defun vhdl-template-return-hook ()
8067 (vhdl-hooked-abbrev 'vhdl-template-return))
8068 (defun vhdl-template-selected-signal-asst-hook ()
8069 (vhdl-hooked-abbrev 'vhdl-template-selected-signal-asst))
8070 (defun vhdl-template-signal-hook ()
8071 (vhdl-hooked-abbrev 'vhdl-template-signal))
8072 (defun vhdl-template-subnature-hook ()
8073 (vhdl-hooked-abbrev 'vhdl-template-subnature))
8074 (defun vhdl-template-subtype-hook ()
8075 (vhdl-hooked-abbrev 'vhdl-template-subtype))
8076 (defun vhdl-template-terminal-hook ()
8077 (vhdl-hooked-abbrev 'vhdl-template-terminal))
8078 (defun vhdl-template-type-hook ()
8079 (vhdl-hooked-abbrev 'vhdl-template-type))
8080 (defun vhdl-template-use-hook ()
8081 (vhdl-hooked-abbrev 'vhdl-template-use))
8082 (defun vhdl-template-variable-hook ()
8083 (vhdl-hooked-abbrev 'vhdl-template-variable))
8084 (defun vhdl-template-wait-hook ()
8085 (vhdl-hooked-abbrev 'vhdl-template-wait))
8086 (defun vhdl-template-when-hook ()
8087 (vhdl-hooked-abbrev 'vhdl-template-when))
8088 (defun vhdl-template-while-loop-hook ()
8089 (vhdl-hooked-abbrev 'vhdl-template-while-loop))
8090 (defun vhdl-template-with-hook ()
8091 (vhdl-hooked-abbrev 'vhdl-template-with))
8092 (defun vhdl-template-and-hook ()
8093 (vhdl-hooked-abbrev 'vhdl-template-and))
8094 (defun vhdl-template-or-hook ()
8095 (vhdl-hooked-abbrev 'vhdl-template-or))
8096 (defun vhdl-template-nand-hook ()
8097 (vhdl-hooked-abbrev 'vhdl-template-nand))
8098 (defun vhdl-template-nor-hook ()
8099 (vhdl-hooked-abbrev 'vhdl-template-nor))
8100 (defun vhdl-template-xor-hook ()
8101 (vhdl-hooked-abbrev 'vhdl-template-xor))
8102 (defun vhdl-template-xnor-hook ()
8103 (vhdl-hooked-abbrev 'vhdl-template-xnor))
8104 (defun vhdl-template-not-hook ()
8105 (vhdl-hooked-abbrev 'vhdl-template-not))
8106
8107 (defun vhdl-template-default-hook ()
8108 (vhdl-hooked-abbrev 'vhdl-template-default))
8109 (defun vhdl-template-default-indent-hook ()
8110 (vhdl-hooked-abbrev 'vhdl-template-default-indent))
8111
8112 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8113 ;; Template insertion from completion list
8114
8115 (defun vhdl-template-insert-construct (name)
8116 "Insert the built-in construct template with NAME."
8117 (interactive
8118 (list (let ((completion-ignore-case t))
8119 (completing-read "Construct name: "
8120 vhdl-template-construct-alist nil t))))
8121 (vhdl-template-insert-fun
8122 (car (cdr (assoc name vhdl-template-construct-alist)))))
8123
8124 (defun vhdl-template-insert-package (name)
8125 "Insert the built-in package template with NAME."
8126 (interactive
8127 (list (let ((completion-ignore-case t))
8128 (completing-read "Package name: "
8129 vhdl-template-package-alist nil t))))
8130 (vhdl-template-insert-fun
8131 (car (cdr (assoc name vhdl-template-package-alist)))))
8132
8133 (defun vhdl-template-insert-directive (name)
8134 "Insert the built-in directive template with NAME."
8135 (interactive
8136 (list (let ((completion-ignore-case t))
8137 (completing-read "Directive name: "
8138 vhdl-template-directive-alist nil t))))
8139 (vhdl-template-insert-fun
8140 (car (cdr (assoc name vhdl-template-directive-alist)))))
8141
8142 (defun vhdl-template-insert-fun (fun)
8143 "Call FUN to insert a built-in template."
8144 (let ((caught (catch 'abort (when fun (funcall fun)))))
8145 (when (stringp caught) (message caught))))
8146
8147
8148 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8149 ;;; Models
8150 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8151
8152 (defun vhdl-model-insert (model-name)
8153 "Insert the user model with name MODEL-NAME."
8154 (interactive
8155 (let ((completion-ignore-case t))
8156 (list (completing-read "Model name: " vhdl-model-alist))))
8157 (vhdl-indent-line)
8158 (let ((start (point-marker))
8159 (margin (current-indentation))
8160 (case-fold-search t)
8161 model position prompt string end)
8162 (vhdl-ext-syntax-table
8163 (when (setq model (assoc model-name vhdl-model-alist))
8164 ;; insert model
8165 (beginning-of-line)
8166 (delete-horizontal-space)
8167 (goto-char start)
8168 (vhdl-insert-string-or-file (nth 1 model))
8169 (setq end (point-marker))
8170 ;; indent code
8171 (goto-char start)
8172 (beginning-of-line)
8173 (while (< (point) end)
8174 (unless (looking-at "^$")
8175 (insert-char ? margin))
8176 (beginning-of-line 2))
8177 (goto-char start)
8178 ;; insert clock
8179 (unless (equal "" vhdl-clock-name)
8180 (while (re-search-forward "<clock>" end t)
8181 (replace-match vhdl-clock-name)))
8182 (goto-char start)
8183 ;; insert reset
8184 (unless (equal "" vhdl-reset-name)
8185 (while (re-search-forward "<reset>" end t)
8186 (replace-match vhdl-reset-name)))
8187 (goto-char start)
8188 ;; query prompts
8189 (while (re-search-forward
8190 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") end t)
8191 (unless (equal "cursor" (match-string 1))
8192 (setq position (match-beginning 1))
8193 (setq prompt (match-string 1))
8194 (replace-match "")
8195 (setq string (vhdl-template-field prompt nil t))
8196 ;; replace occurences of same prompt
8197 (while (re-search-forward (concat "<\\(" prompt "\\)>") end t)
8198 (replace-match (or string "")))
8199 (goto-char position)))
8200 (goto-char start)
8201 ;; goto final position
8202 (if (re-search-forward "<cursor>" end t)
8203 (replace-match "")
8204 (goto-char end))))))
8205
8206 (defun vhdl-model-defun ()
8207 "Define help and hook functions for user models."
8208 (let ((model-alist vhdl-model-alist)
8209 model-name model-keyword)
8210 (while model-alist
8211 ;; define functions for user models that can be invoked from menu and key
8212 ;; bindings and which themselves call `vhdl-model-insert' with the model
8213 ;; name as argument
8214 (setq model-name (nth 0 (car model-alist)))
8215 (eval `(defun ,(vhdl-function-name "vhdl-model" model-name) ()
8216 ,(concat "Insert model for \"" model-name "\".")
8217 (interactive)
8218 (vhdl-model-insert ,model-name)))
8219 ;; define hooks for user models that are invoked from keyword abbrevs
8220 (setq model-keyword (nth 3 (car model-alist)))
8221 (unless (equal model-keyword "")
8222 (eval `(defun
8223 ,(vhdl-function-name
8224 "vhdl-model" model-name "hook") ()
8225 (vhdl-hooked-abbrev
8226 ',(vhdl-function-name "vhdl-model" model-name)))))
8227 (setq model-alist (cdr model-alist)))))
8228
8229 (vhdl-model-defun)
8230
8231
8232 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8233 ;;; Port translation
8234 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8235
8236 (defvar vhdl-port-list nil
8237 "Variable to hold last PORT map parsed.")
8238 ;; structure: (parenthesised expression means list of such entries)
8239 ;; ((generic-names) generic-type generic-init generic-comment)
8240 ;; ((port-names) port-object port-direct port-type port-comment)
8241
8242 (defun vhdl-parse-string (string &optional optional)
8243 "Check that the text following point matches the regexp in STRING.
8244 END is the point beyond which matching/searching should not go."
8245 (if (looking-at string)
8246 (re-search-forward string nil t)
8247 (unless optional
8248 (throw 'parse (format "Syntax error near line %s" (vhdl-current-line))))
8249 nil))
8250
8251 (defun vhdl-replace-string (regexp-cons string)
8252 "Replace STRING from car of REGEXP-CONS to cdr of REGEXP-CONS."
8253 (vhdl-ext-syntax-table
8254 (if (string-match (car regexp-cons) string)
8255 (replace-match (cdr regexp-cons) t nil string)
8256 string)))
8257
8258 (defun vhdl-port-flatten ()
8259 "Flatten port list so that only one generic/port exists per line."
8260 (interactive)
8261 (if (not vhdl-port-list)
8262 (error "No port read")
8263 (message "Flattening port...")
8264 (let ((new-vhdl-port-list (list (car vhdl-port-list)))
8265 (old-vhdl-port-list (cdr vhdl-port-list))
8266 old-port-list new-port-list old-port new-port names)
8267 ;; traverse port list and flatten entries
8268 (while old-vhdl-port-list
8269 (setq old-port-list (car old-vhdl-port-list))
8270 (setq new-port-list nil)
8271 (while old-port-list
8272 (setq old-port (car old-port-list))
8273 (setq names (car old-port))
8274 (while names
8275 (setq new-port (cons (list (car names)) (cdr old-port)))
8276 (setq new-port-list (append new-port-list (list new-port)))
8277 (setq names (cdr names)))
8278 (setq old-port-list (cdr old-port-list)))
8279 (setq old-vhdl-port-list (cdr old-vhdl-port-list))
8280 (setq new-vhdl-port-list (append new-vhdl-port-list
8281 (list new-port-list))))
8282 (setq vhdl-port-list new-vhdl-port-list)
8283 (message "Flattening port...done"))))
8284
8285 (defun vhdl-port-copy ()
8286 "Get generic and port information from an entity or component declaration."
8287 (interactive)
8288 (message "Reading port...")
8289 (save-excursion
8290 (let ((case-fold-search t)
8291 parse-error end-of-list
8292 name generics ports
8293 object names direct type init comment)
8294 (vhdl-ext-syntax-table
8295 (setq
8296 parse-error
8297 (catch 'parse
8298 ;; check if within entity or component declaration
8299 (when (or (not (re-search-backward
8300 "^\\s-*\\(component\\|entity\\|end\\)\\>" nil t))
8301 (equal "end" (match-string 1)))
8302 (throw 'parse "Not within entity or component declaration"))
8303 (forward-word 1)
8304 (vhdl-parse-string "\\s-*\\(\\w+\\)\\s-*\\(is\\)?\\s-*$")
8305 (setq name (match-string 1))
8306 (vhdl-forward-syntactic-ws)
8307 ;; parse generic clause
8308 (when (vhdl-parse-string "generic[ \t\n]*(" t)
8309 (vhdl-forward-syntactic-ws)
8310 (setq end-of-list (looking-at ")"))
8311 (while (not end-of-list)
8312 ;; parse names
8313 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8314 (setq names (list (match-string 1)))
8315 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8316 (setq names (append names (list (match-string 1)))))
8317 ;; parse type
8318 (vhdl-parse-string ":[ \t\n]*\\([^():;\n]+\\)")
8319 (setq type (match-string 1))
8320 (setq comment nil)
8321 (while (looking-at "(")
8322 (setq type
8323 (concat type
8324 (buffer-substring
8325 (point) (progn (forward-sexp) (point)))
8326 (and (vhdl-parse-string "\\([^():;\n]*\\)" t)
8327 (match-string 1)))))
8328 ;; special case: closing parenthesis is on separate line
8329 (when (and type (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type))
8330 (setq comment (substring type (match-beginning 2)))
8331 (setq type (substring type 0 (match-beginning 1))))
8332 ;; strip of trailing whitespace
8333 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8334 (setq type (substring type 0 (match-end 1)))
8335 ;; parse initialization expression
8336 (setq init nil)
8337 (when (vhdl-parse-string ":=[ \t\n]*" t)
8338 (vhdl-parse-string "\\([^();\n]*\\)")
8339 (setq init (match-string 1))
8340 (while (looking-at "(")
8341 (setq init
8342 (concat init
8343 (buffer-substring
8344 (point) (progn (forward-sexp) (point)))
8345 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8346 (match-string 1))))))
8347 ;; special case: closing parenthesis is on separate line
8348 (when (and init (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" init))
8349 (setq comment (substring init (match-beginning 2)))
8350 (setq init (substring init 0 (match-beginning 1)))
8351 (vhdl-forward-syntactic-ws))
8352 (skip-chars-forward " \t")
8353 ;; parse inline comment, special case: as above, no initial.
8354 (unless comment
8355 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8356 (match-string 1))))
8357 (vhdl-forward-syntactic-ws)
8358 (setq end-of-list (vhdl-parse-string ")" t))
8359 (vhdl-parse-string ";\\s-*")
8360 ;; parse inline comment
8361 (unless comment
8362 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8363 (match-string 1))))
8364 (vhdl-forward-syntactic-ws)
8365 ;; save everything in list
8366 (setq generics (append generics
8367 (list (list names type init comment))))))
8368 ;; parse port clause
8369 (when (vhdl-parse-string "port[ \t\n]*(" t)
8370 (vhdl-forward-syntactic-ws)
8371 (setq end-of-list (looking-at ")"))
8372 (while (not end-of-list)
8373 ;; parse object
8374 (setq object
8375 (and (vhdl-parse-string
8376 "\\(signal\\|quantity\\|terminal\\)[ \t\n]*" t)
8377 (match-string 1)))
8378 ;; parse names
8379 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8380 (setq names (list (match-string 1)))
8381 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8382 (setq names (append names (list (match-string 1)))))
8383 ;; parse direction
8384 (vhdl-parse-string ":[ \t\n]*")
8385 (setq direct
8386 (and (vhdl-parse-string "\\(IN\\|OUT\\|INOUT\\)[ \t\n]+" t)
8387 (match-string 1)))
8388 ;; parse type
8389 (vhdl-parse-string "\\([^();\n]+\\)")
8390 (setq type (match-string 1))
8391 (setq comment nil)
8392 (while (looking-at "(")
8393 (setq type (concat type
8394 (buffer-substring
8395 (point) (progn (forward-sexp) (point)))
8396 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8397 (match-string 1)))))
8398 ;; special case: closing parenthesis is on separate line
8399 (when (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type)
8400 (setq comment (substring type (match-beginning 2)))
8401 (setq type (substring type 0 (match-beginning 1))))
8402 ;; strip of trailing whitespace
8403 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8404 (setq type (substring type 0 (match-end 1)))
8405 (vhdl-forward-syntactic-ws)
8406 (setq end-of-list (vhdl-parse-string ")" t))
8407 (vhdl-parse-string ";\\s-*")
8408 ;; parse inline comment
8409 (unless comment
8410 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8411 (match-string 1))))
8412 (vhdl-forward-syntactic-ws)
8413 ;; save everything in list
8414 (setq ports
8415 (append ports
8416 (list (list names object direct type comment))))))
8417 nil)))
8418 ;; finish parsing
8419 (if parse-error
8420 (error parse-error)
8421 (setq vhdl-port-list (list name generics ports))
8422 (message "Reading port...done")))))
8423
8424 (defun vhdl-port-paste-generic (&optional no-init)
8425 "Paste a generic clause."
8426 (let ((margin (current-indentation))
8427 list-margin start names generic
8428 (generics-list (nth 1 vhdl-port-list)))
8429 ;; paste generic clause
8430 (when generics-list
8431 (setq start (point))
8432 (vhdl-insert-keyword "GENERIC (")
8433 (unless vhdl-argument-list-indent
8434 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8435 (setq list-margin (current-column))
8436 (while generics-list
8437 ;; paste names
8438 (setq generic (car generics-list))
8439 (setq names (nth 0 generic))
8440 (while names
8441 (insert (car names))
8442 (setq names (cdr names))
8443 (when names (insert ", ")))
8444 ;; paste type
8445 (insert " : " (nth 1 generic))
8446 ;; paste initialization
8447 (when (and (not no-init) (nth 2 generic))
8448 (insert " := " (nth 2 generic)))
8449 (unless (cdr generics-list) (insert ")"))
8450 (insert ";")
8451 ;; paste comment
8452 (when (and vhdl-include-port-comments (nth 3 generic))
8453 (vhdl-comment-insert-inline (nth 3 generic) t))
8454 (setq generics-list (cdr generics-list))
8455 (when generics-list (insert "\n") (indent-to list-margin)))
8456 ;; align generic clause
8457 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1 t)))))
8458
8459 (defun vhdl-port-paste-port ()
8460 "Paste a port clause."
8461 (let ((margin (current-indentation))
8462 list-margin start names port
8463 (ports-list (nth 2 vhdl-port-list)))
8464 ;; paste port clause
8465 (when ports-list
8466 (setq start (point))
8467 (vhdl-insert-keyword "PORT (")
8468 (unless vhdl-argument-list-indent
8469 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8470 (setq list-margin (current-column))
8471 (while ports-list
8472 (setq port (car ports-list))
8473 ;; paste object
8474 (when (nth 1 port) (insert (nth 1 port) " "))
8475 ;; paste names
8476 (setq names (nth 0 port))
8477 (while names
8478 (insert (car names))
8479 (setq names (cdr names))
8480 (when names (insert ", ")))
8481 ;; paste direction
8482 (insert " : ")
8483 (when (nth 2 port) (insert (nth 2 port) " "))
8484 ;; paste type
8485 (insert (nth 3 port))
8486 (unless (cdr ports-list) (insert ")"))
8487 (insert ";")
8488 ;; paste comment
8489 (when (and vhdl-include-port-comments (nth 4 port))
8490 (vhdl-comment-insert-inline (nth 4 port) t))
8491 (setq ports-list (cdr ports-list))
8492 (when ports-list (insert "\n") (indent-to list-margin)))
8493 ;; align port clause
8494 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
8495
8496 (defun vhdl-port-paste-declaration (kind)
8497 "Paste as an entity or component declaration."
8498 (vhdl-indent-line)
8499 (let ((margin (current-indentation))
8500 (name (nth 0 vhdl-port-list)))
8501 (vhdl-insert-keyword (if (eq kind 'entity) "ENTITY " "COMPONENT "))
8502 (insert name)
8503 (if (eq kind 'entity) (vhdl-insert-keyword " IS"))
8504 ;; paste generic and port clause
8505 (when (nth 1 vhdl-port-list)
8506 (insert "\n")
8507 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8508 (insert "\n"))
8509 (indent-to (+ margin vhdl-basic-offset))
8510 (vhdl-port-paste-generic (eq kind 'component)))
8511 (when (nth 2 vhdl-port-list)
8512 (insert "\n")
8513 (when (and (memq vhdl-insert-empty-lines '(unit all))
8514 (eq kind 'entity))
8515 (insert "\n"))
8516 (indent-to (+ margin vhdl-basic-offset)))
8517 (vhdl-port-paste-port)
8518 (insert "\n")
8519 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8520 (insert "\n"))
8521 (indent-to margin)
8522 (vhdl-insert-keyword "END")
8523 (if (eq kind 'entity)
8524 (progn
8525 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " ENTITY"))
8526 (insert " " name))
8527 (vhdl-insert-keyword " COMPONENT")
8528 (unless (vhdl-standard-p '87) (insert " " name)))
8529 (insert ";")))
8530
8531 (defun vhdl-port-paste-entity ()
8532 "Paste as an entity declaration."
8533 (interactive)
8534 (if (not vhdl-port-list)
8535 (error "No port read")
8536 (message "Pasting port as entity...")
8537 (vhdl-port-paste-declaration 'entity)
8538 (message "Pasting port as entity...done")))
8539
8540 (defun vhdl-port-paste-component ()
8541 "Paste as a component declaration."
8542 (interactive)
8543 (if (not vhdl-port-list)
8544 (error "No port read")
8545 (message "Pasting port as component...")
8546 (vhdl-port-paste-declaration 'component)
8547 (message "Pasting port as component...done")))
8548
8549 (defun vhdl-port-paste-generic-map (&optional secondary no-constants)
8550 "Paste as a generic map."
8551 (interactive)
8552 (unless secondary (vhdl-indent-line))
8553 (let ((margin (current-indentation))
8554 list-margin start generic
8555 (generics-list (nth 1 vhdl-port-list)))
8556 (when generics-list
8557 (setq start (point))
8558 (vhdl-insert-keyword "GENERIC MAP (")
8559 (if (not vhdl-association-list-with-formals)
8560 ;; paste list of actual generics
8561 (while generics-list
8562 (insert (or (nth 2 (car generics-list)) " "))
8563 (setq generics-list (cdr generics-list))
8564 (insert (if generics-list ", " ")")))
8565 (unless vhdl-argument-list-indent
8566 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
8567 (setq list-margin (current-column))
8568 (while generics-list
8569 (setq generic (car generics-list))
8570 ;; paste formal and actual generic
8571 (insert (car (nth 0 generic)) " => "
8572 (if no-constants
8573 (car (nth 0 generic))
8574 (or (nth 2 generic) "")))
8575 (setq generics-list (cdr generics-list))
8576 (insert (if generics-list "," ")"))
8577 ;; paste comment
8578 (when (and vhdl-include-port-comments (nth 3 generic))
8579 (vhdl-comment-insert-inline (nth 3 generic) t))
8580 (when generics-list (insert "\n") (indent-to list-margin)))
8581 ;; align generic map
8582 (when vhdl-auto-align
8583 (vhdl-align-noindent-region start (point) 1 t))))))
8584
8585 (defun vhdl-port-paste-port-map ()
8586 "Paste as a port map."
8587 (let ((margin (current-indentation))
8588 list-margin start port
8589 (ports-list (nth 2 vhdl-port-list)))
8590 (when ports-list
8591 (setq start (point))
8592 (vhdl-insert-keyword "PORT MAP (")
8593 (if (not vhdl-association-list-with-formals)
8594 ;; paste list of actual ports
8595 (while ports-list
8596 (insert (vhdl-replace-string vhdl-actual-port-name
8597 (car (nth 0 (car ports-list)))))
8598 (setq ports-list (cdr ports-list))
8599 (insert (if ports-list ", " ");")))
8600 (unless vhdl-argument-list-indent
8601 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
8602 (setq list-margin (current-column))
8603 (while ports-list
8604 (setq port (car ports-list))
8605 ;; paste formal and actual port
8606 (insert (car (nth 0 port)) " => ")
8607 (insert (vhdl-replace-string vhdl-actual-port-name
8608 (car (nth 0 port))))
8609 (setq ports-list (cdr ports-list))
8610 (insert (if ports-list "," ");"))
8611 ;; paste comment
8612 (when (or vhdl-include-direction-comments
8613 (and vhdl-include-port-comments (nth 4 port)))
8614 (vhdl-comment-insert-inline
8615 (concat
8616 (if vhdl-include-direction-comments
8617 (format "%-4s" (or (concat (nth 2 port) " ") "")) "")
8618 (if vhdl-include-port-comments (nth 4 port) "")) t))
8619 (when ports-list (insert "\n") (indent-to list-margin)))
8620 ;; align port clause
8621 (when vhdl-auto-align
8622 (vhdl-align-noindent-region start (point) 1))))))
8623
8624 (defun vhdl-port-paste-instance (&optional name)
8625 "Paste as an instantiation."
8626 (interactive)
8627 (if (not vhdl-port-list)
8628 (error "No port read")
8629 (let ((orig-vhdl-port-list vhdl-port-list))
8630 ;; flatten local copy of port list (must be flat for port mapping)
8631 (vhdl-port-flatten)
8632 (vhdl-indent-line)
8633 (let ((margin (current-indentation))
8634 list-margin start generic port
8635 (generics-list (nth 1 vhdl-port-list))
8636 (ports-list (nth 2 vhdl-port-list)))
8637 ;; paste instantiation
8638 (if name
8639 (insert name ": ")
8640 (if (equal (cdr vhdl-instance-name) "")
8641 (vhdl-template-field "instance name" ": ")
8642 (insert (vhdl-replace-string vhdl-instance-name
8643 (nth 0 vhdl-port-list)) ": ")))
8644 (message "Pasting port as instantiation...")
8645 (if (vhdl-standard-p '87)
8646 (insert (nth 0 vhdl-port-list))
8647 (vhdl-insert-keyword "ENTITY ")
8648 (insert "work." (nth 0 vhdl-port-list)))
8649 (when (nth 1 vhdl-port-list)
8650 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8651 (vhdl-port-paste-generic-map t t))
8652 (when (nth 2 vhdl-port-list)
8653 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8654 (vhdl-port-paste-port-map))
8655 (message "Pasting port as instantiation...done"))
8656 (setq vhdl-port-list orig-vhdl-port-list))))
8657
8658 (defun vhdl-port-paste-signals (&optional initialize)
8659 "Paste ports as internal signals."
8660 (interactive)
8661 (if (not vhdl-port-list)
8662 (error "No port read")
8663 (message "Pasting port as signals...")
8664 (vhdl-indent-line)
8665 (let ((margin (current-indentation))
8666 start port names
8667 (ports-list (nth 2 vhdl-port-list)))
8668 (when ports-list
8669 (setq start (point))
8670 (while ports-list
8671 (setq port (car ports-list))
8672 ;; paste object
8673 (if (nth 1 port)
8674 (insert (nth 1 port) " ")
8675 (vhdl-insert-keyword "SIGNAL "))
8676 ;; paste actual port signals
8677 (setq names (nth 0 port))
8678 (while names
8679 (insert (vhdl-replace-string vhdl-actual-port-name (car names)))
8680 (setq names (cdr names))
8681 (when names (insert ", ")))
8682 ;; paste type
8683 (insert " : " (nth 3 port))
8684 ;; paste initialization (inputs only)
8685 (when (and initialize (equal "in" (nth 2 port)))
8686 (insert
8687 " := "
8688 (if (string-match "(.+)" (nth 3 port)) "(others => '0')" "'0'")))
8689 (insert ";")
8690 ;; paste comment
8691 (when (and vhdl-include-port-comments (nth 4 port))
8692 (vhdl-comment-insert-inline (nth 4 port) t))
8693 (setq ports-list (cdr ports-list))
8694 (when ports-list (insert "\n") (indent-to margin)))
8695 ;; align signal list
8696 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))))
8697 (message "Pasting port as signals...done")))
8698
8699 (defun vhdl-port-paste-constants ()
8700 "Paste generics as constants."
8701 (interactive)
8702 (if (not vhdl-port-list)
8703 (error "No port read")
8704 (let ((orig-vhdl-port-list vhdl-port-list))
8705 (message "Pasting port as constants...")
8706 ;; flatten local copy of port list (must be flat for constant initial.)
8707 (vhdl-port-flatten)
8708 (vhdl-indent-line)
8709 (let ((margin (current-indentation))
8710 start generic name
8711 (generics-list (nth 1 vhdl-port-list)))
8712 (when generics-list
8713 (setq start (point))
8714 (while generics-list
8715 (setq generic (car generics-list))
8716 (vhdl-insert-keyword "CONSTANT ")
8717 ;; paste generic constants
8718 (setq name (nth 0 generic))
8719 (when name
8720 (insert (car name))
8721 ;; paste type
8722 (insert " : " (nth 1 generic))
8723 ;; paste initialization
8724 (when (nth 2 generic)
8725 (insert " := " (nth 2 generic)))
8726 (insert ";")
8727 ;; paste comment
8728 (when (and vhdl-include-port-comments (nth 3 generic))
8729 (vhdl-comment-insert-inline (nth 3 generic) t))
8730 (setq generics-list (cdr generics-list))
8731 (when generics-list (insert "\n") (indent-to margin))))
8732 ;; align signal list
8733 (when vhdl-auto-align
8734 (vhdl-align-noindent-region start (point) 1))))
8735 (message "Pasting port as constants...done")
8736 (setq vhdl-port-list orig-vhdl-port-list))))
8737
8738 (defun vhdl-port-paste-testbench ()
8739 "Paste as a bare-bones test bench."
8740 (interactive)
8741 (if (not vhdl-port-list)
8742 (error "No port read")
8743 (message "Pasting port as test bench...")
8744 (let ((case-fold-search t)
8745 (ent-name (vhdl-replace-string vhdl-testbench-entity-name
8746 (nth 0 vhdl-port-list)))
8747 (source-buffer (current-buffer))
8748 arch-name ent-file-name arch-file-name no-entity position)
8749 ;; open entity file
8750 (when (not (eq vhdl-testbench-create-files 'none))
8751 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8752 (setq ent-file-name
8753 (concat ent-name
8754 (substring (buffer-file-name (current-buffer))
8755 (match-beginning 0))))
8756 (when (file-exists-p ent-file-name)
8757 (if (y-or-n-p
8758 (concat "File `" ent-file-name "' exists; overwrite? "))
8759 (progn (delete-file ent-file-name)
8760 (when (get-file-buffer ent-file-name)
8761 (set-buffer ent-file-name)
8762 (set-buffer-modified-p nil)
8763 (kill-buffer ent-file-name)))
8764 (if (eq vhdl-testbench-create-files 'separate)
8765 (setq no-entity t)
8766 (error "Pasting port as test bench...aborted"))))
8767 (unless no-entity
8768 (set-buffer source-buffer)
8769 (find-file ent-file-name)))
8770 (let ((margin 0))
8771 (unless (and (eq vhdl-testbench-create-files 'separate) no-entity)
8772 ;; paste entity header
8773 (unless (equal "" vhdl-testbench-entity-header)
8774 (vhdl-insert-string-or-file vhdl-testbench-entity-header))
8775 (vhdl-comment-display-line) (insert "\n\n") (indent-to margin)
8776 ;; paste std_logic_1164 package
8777 (vhdl-insert-keyword "LIBRARY ")
8778 (insert "ieee;\n") (indent-to margin)
8779 (vhdl-insert-keyword "USE ")
8780 (insert "ieee.std_logic_1164.")
8781 (vhdl-insert-keyword "ALL;")
8782 (insert "\n\n") (indent-to margin) (vhdl-comment-display-line)
8783 (insert "\n\n") (indent-to margin)
8784 ;; paste entity declaration
8785 (vhdl-insert-keyword "ENTITY ")
8786 (insert ent-name)
8787 (vhdl-insert-keyword " IS")
8788 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
8789 (insert "\n") (indent-to margin)
8790 (vhdl-insert-keyword "END ")
8791 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
8792 (insert ent-name ";")
8793 (insert "\n\n") (indent-to margin)
8794 (vhdl-comment-display-line) (insert "\n"))
8795 ;; get architecture name
8796 (setq arch-name
8797 (if (equal (cdr vhdl-testbench-architecture-name) "")
8798 (read-from-minibuffer "architecture name: "
8799 nil vhdl-minibuffer-local-map)
8800 (vhdl-replace-string vhdl-testbench-architecture-name
8801 (nth 0 vhdl-port-list))))
8802 ;; open architecture file
8803 (when (eq vhdl-testbench-create-files 'separate)
8804 (save-buffer)
8805 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8806 (setq arch-file-name
8807 (concat arch-name
8808 (substring (buffer-file-name (current-buffer))
8809 (match-beginning 0))))
8810 (when (file-exists-p arch-file-name)
8811 (if (y-or-n-p
8812 (concat "File `" ent-file-name "' exists; overwrite? "))
8813 (progn (delete-file arch-file-name)
8814 (when (get-file-buffer arch-file-name)
8815 (set-buffer (get-file-buffer arch-file-name))
8816 (set-buffer-modified-p nil)
8817 (kill-buffer arch-file-name)))
8818 (error "Pasting port as test bench...aborted")))
8819 (set-buffer source-buffer)
8820 (find-file arch-file-name)
8821 ;; paste architecture header
8822 (unless (equal "" vhdl-testbench-architecture-header)
8823 (vhdl-insert-string-or-file vhdl-testbench-architecture-header))
8824 (vhdl-comment-display-line)
8825 (insert "\n"))
8826 (insert "\n") (indent-to margin)
8827 ;; paste architecture body
8828 (vhdl-insert-keyword "ARCHITECTURE ")
8829 (insert arch-name)
8830 (vhdl-insert-keyword " OF ")
8831 (insert ent-name)
8832 (vhdl-insert-keyword " IS")
8833 (insert "\n\n") (indent-to margin)
8834 ;; paste component declaration
8835 (when (vhdl-standard-p '87)
8836 (vhdl-port-paste-component)
8837 (insert "\n\n") (indent-to margin))
8838 ;; paste constants
8839 (when (nth 1 vhdl-port-list)
8840 (vhdl-port-paste-constants)
8841 (insert "\n\n") (indent-to margin))
8842 ;; paste internal signals
8843 (vhdl-port-paste-signals vhdl-testbench-initialize-signals)
8844 ;; paste custom declarations
8845 (unless (equal "" vhdl-testbench-declarations)
8846 (insert "\n\n")
8847 (vhdl-insert-string-or-file vhdl-testbench-declarations)
8848 (delete-indentation))
8849 (setq position (point))
8850 (insert "\n\n") (indent-to margin)
8851 (vhdl-comment-display-line) (insert "\n")
8852 (goto-char position)
8853 (vhdl-template-begin-end
8854 (unless (vhdl-standard-p '87) "ARCHITECTURE")
8855 arch-name margin t)
8856 ;; paste instantiation
8857 (vhdl-port-paste-instance
8858 (vhdl-replace-string vhdl-testbench-dut-name
8859 (nth 0 vhdl-port-list)))
8860 (insert "\n")
8861 ;; paste custom statements
8862 (unless (equal "" vhdl-testbench-statements)
8863 (insert "\n")
8864 (vhdl-insert-string-or-file vhdl-testbench-statements))
8865 (insert "\n")
8866 (indent-to (+ margin vhdl-basic-offset))
8867 (when (not (eq vhdl-testbench-create-files 'none))
8868 (save-buffer))
8869 (message "Pasting port as test bench...done")))))
8870
8871
8872 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8873 ;;; Miscellaneous
8874 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8875
8876 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8877 ;; Hippie expand customization
8878
8879 (defvar vhdl-expand-upper-case nil)
8880
8881 (defun vhdl-try-expand-abbrev (old)
8882 "Try expanding abbreviations from `vhdl-abbrev-list'."
8883 (unless old
8884 (he-init-string (he-dabbrev-beg) (point))
8885 (setq he-expand-list
8886 (let ((abbrev-list vhdl-abbrev-list)
8887 (sel-abbrev-list '()))
8888 (while abbrev-list
8889 (when (or (not (stringp (car abbrev-list)))
8890 (string-match
8891 (concat "^" he-search-string) (car abbrev-list)))
8892 (setq sel-abbrev-list
8893 (cons (car abbrev-list) sel-abbrev-list)))
8894 (setq abbrev-list (cdr abbrev-list)))
8895 (nreverse sel-abbrev-list))))
8896 (while (and he-expand-list
8897 (or (not (stringp (car he-expand-list)))
8898 (he-string-member (car he-expand-list) he-tried-table t)))
8899 ; (equal (car he-expand-list) he-search-string)))
8900 (unless (stringp (car he-expand-list))
8901 (setq vhdl-expand-upper-case (car he-expand-list)))
8902 (setq he-expand-list (cdr he-expand-list)))
8903 (if (null he-expand-list)
8904 (progn (when old (he-reset-string))
8905 nil)
8906 (he-substitute-string
8907 (if vhdl-expand-upper-case
8908 (upcase (car he-expand-list))
8909 (car he-expand-list))
8910 t)
8911 (setq he-expand-list (cdr he-expand-list))
8912 t))
8913
8914 (defun vhdl-he-list-beg ()
8915 "Also looks at the word before `(' in order to better match parenthesized
8916 expressions (e.g. for index ranges of types and signals)."
8917 (save-excursion
8918 (condition-case ()
8919 (progn (backward-up-list 1)
8920 (skip-syntax-backward "w_")) ; crashes in `viper-mode'
8921 (error ()))
8922 (point)))
8923
8924 ;; override `he-list-beg' from `hippie-exp'
8925 (unless (and (boundp 'viper-mode) viper-mode)
8926 (require 'hippie-exp)
8927 (defalias 'he-list-beg 'vhdl-he-list-beg))
8928
8929 ;; function for expanding abbrevs and dabbrevs
8930 (fset 'vhdl-expand-abbrev (make-hippie-expand-function
8931 '(try-expand-dabbrev
8932 try-expand-dabbrev-all-buffers
8933 vhdl-try-expand-abbrev)))
8934
8935 ;; function for expanding parenthesis
8936 (fset 'vhdl-expand-paren (make-hippie-expand-function
8937 '(try-expand-list
8938 try-expand-list-all-buffers)))
8939
8940 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8941 ;; Case fixing
8942
8943 (defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
8944 "Convert all words matching word-regexp in region to lower or upper case,
8945 depending on parameter upper-case."
8946 (let ((case-fold-search t)
8947 (case-replace nil)
8948 (last-update 0))
8949 (vhdl-ext-syntax-table
8950 (save-excursion
8951 (goto-char end)
8952 (setq end (point-marker))
8953 (goto-char beg)
8954 (while (re-search-forward word-regexp end t)
8955 (or (vhdl-in-comment-p)
8956 (vhdl-in-string-p)
8957 (if upper-case
8958 (upcase-word -1)
8959 (downcase-word -1)))
8960 (when (and count vhdl-progress-interval
8961 (< vhdl-progress-interval
8962 (- (nth 1 (current-time)) last-update)))
8963 (message "Fixing case... (%2d%s)"
8964 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg)))
8965 "%")
8966 (setq last-update (nth 1 (current-time)))))
8967 (goto-char end)))
8968 (and count vhdl-progress-interval (message "Fixing case...done"))))
8969
8970 (defun vhdl-fix-case-region (beg end &optional arg)
8971 "Convert all VHDL words in region to lower or upper case, depending on
8972 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
8973 (interactive "r\nP")
8974 (vhdl-fix-case-region-1
8975 beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
8976 (vhdl-fix-case-region-1
8977 beg end vhdl-upper-case-types vhdl-types-regexp 1)
8978 (vhdl-fix-case-region-1
8979 beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
8980 (vhdl-fix-case-region-1
8981 beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3))
8982
8983 (defun vhdl-fix-case-buffer ()
8984 "Convert all VHDL words in buffer to lower or upper case, depending on
8985 variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
8986 (interactive)
8987 (vhdl-fix-case-region (point-min) (point-max)))
8988
8989 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8990 ;; Line handling functions
8991
8992 (defun vhdl-current-line ()
8993 "Return the line number of the line containing point."
8994 (save-restriction
8995 (widen)
8996 (save-excursion
8997 (beginning-of-line)
8998 (1+ (count-lines 1 (point))))))
8999
9000 (defun vhdl-line-kill-entire (&optional arg)
9001 "Delete entire line."
9002 (interactive "p")
9003 (beginning-of-line)
9004 (kill-line (or arg 1)))
9005
9006 (defun vhdl-line-kill (&optional arg)
9007 "Kill current line."
9008 (interactive "p")
9009 (vhdl-line-kill-entire arg))
9010
9011 (defun vhdl-line-copy (&optional arg)
9012 "Copy current line."
9013 (interactive "p")
9014 (save-excursion
9015 (beginning-of-line)
9016 (let ((position (point)))
9017 (forward-line (or arg 1))
9018 (copy-region-as-kill position (point)))))
9019
9020 (defun vhdl-line-yank ()
9021 "Yank entire line."
9022 (interactive)
9023 (beginning-of-line)
9024 (yank))
9025
9026 (defun vhdl-line-expand (&optional prefix-arg)
9027 "Hippie-expand current line."
9028 (interactive "P")
9029 (let ((case-fold-search t) (case-replace nil)
9030 (hippie-expand-try-functions-list
9031 '(try-expand-line try-expand-line-all-buffers)))
9032 (hippie-expand prefix-arg)))
9033
9034 (defun vhdl-line-transpose-next (&optional arg)
9035 "Interchange this line with next line."
9036 (interactive "p")
9037 (forward-line 1)
9038 (transpose-lines (or arg 1))
9039 (forward-line -1))
9040
9041 (defun vhdl-line-transpose-previous (&optional arg)
9042 "Interchange this line with previous line."
9043 (interactive "p")
9044 (forward-line 1)
9045 (transpose-lines (- 0 (or arg 0)))
9046 (forward-line -1))
9047
9048 (defun vhdl-line-open ()
9049 "Open a new line and indent."
9050 (interactive)
9051 (end-of-line -0)
9052 (newline-and-indent))
9053
9054
9055 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9056 ;;; Project
9057 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9058
9059 (defun vhdl-project-switch (name)
9060 "Switch to project NAME."
9061 (setq vhdl-project name)
9062 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
9063 (speedbar-refresh)))
9064
9065
9066 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9067 ;;; Compilation
9068 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9069 ;; (using `compile.el')
9070
9071 (defun vhdl-compile-init ()
9072 "Initialize for compilation."
9073 (unless compilation-error-regexp-alist
9074 (setq compilation-error-regexp-alist
9075 (let ((commands-alist vhdl-compiler-alist)
9076 regexp-alist sublist)
9077 (while commands-alist
9078 (setq sublist (nth 5 (car commands-alist)))
9079 (unless (equal "" (car sublist))
9080 (setq regexp-alist
9081 (cons (list (nth 0 sublist)
9082 (if (= 0 (nth 1 sublist))
9083 (if (string-match
9084 "XEmacs" emacs-version) 9 nil)
9085 (nth 1 sublist))
9086 (nth 2 sublist))
9087 regexp-alist)))
9088 (setq commands-alist (cdr commands-alist)))
9089 regexp-alist)))
9090 (unless compilation-file-regexp-alist
9091 (setq compilation-file-regexp-alist
9092 (let ((commands-alist vhdl-compiler-alist)
9093 regexp-alist)
9094 (while commands-alist
9095 (unless (equal "" (car (nth 6 (car commands-alist))))
9096 (setq regexp-alist
9097 (append regexp-alist
9098 (list (nth 6 (car commands-alist))))))
9099 (setq commands-alist (cdr commands-alist)))
9100 regexp-alist))))
9101
9102 (defun vhdl-compile ()
9103 "Compile current buffer using the VHDL compiler specified in
9104 `vhdl-compiler'."
9105 (interactive)
9106 (vhdl-compile-init)
9107 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9108 (command (nth 1 command-elem))
9109 (default-directory (expand-file-name (nth 4 command-elem))))
9110 (when command
9111 (compile (concat command " " vhdl-compiler-options
9112 (unless (string-equal vhdl-compiler-options "") " ")
9113 (buffer-file-name))))))
9114
9115 (defun vhdl-make ()
9116 "Call make command for compilation of all updated source files (requires
9117 `Makefile')."
9118 (interactive)
9119 (vhdl-compile-init)
9120 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9121 (command (nth 2 command-elem))
9122 (default-directory (expand-file-name (nth 4 command-elem))))
9123 (if (equal command "")
9124 (compile "make")
9125 (compile command))))
9126
9127 (defun vhdl-generate-makefile ()
9128 "Generate new `Makefile'."
9129 (interactive)
9130 (vhdl-compile-init)
9131 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9132 (command (nth 3 command-elem))
9133 (default-directory (expand-file-name (nth 4 command-elem))))
9134 (if (not (equal command ""))
9135 (compile command)
9136 (error "No such command specified for `%s'" vhdl-compiler))))
9137
9138
9139 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9140 ;;; Hideshow
9141 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9142 ;; (using `hideshow.el')
9143
9144 (defun vhdl-forward-unit (&optional count)
9145 "Find begin and end of VHDL design units (for hideshow)."
9146 (interactive "p")
9147 (let ((case-fold-search t))
9148 (if (< count 0)
9149 (re-search-backward
9150 "^\\(architecture\\|configuration\\|entity\\|package\\)\\>" nil t)
9151 (re-search-forward "^end\\>" nil t))))
9152
9153 (when (string-match "XEmacs" emacs-version)
9154 (require 'hideshow))
9155
9156 (unless (assq 'vhdl-mode hs-special-modes-alist)
9157 (setq hs-special-modes-alist
9158 (cons
9159 '(vhdl-mode
9160 "\\(^\\)\\(architecture\\|ARCHITECTURE\\|configuration\\|CONFIGURATION\\|entity\\|ENTITY\\|package\\|PACKAGE\\)\\>"
9161 "\\(^\\)\\(end\\|END\\)\\>"
9162 "--\\( \\|$\\)"
9163 vhdl-forward-unit)
9164 hs-special-modes-alist)))
9165
9166 (defun vhdl-hideshow-init ()
9167 "Initialize `hideshow'."
9168 (if vhdl-hide-all-init
9169 (add-hook 'hs-minor-mode-hook 'hs-hide-all)
9170 (remove-hook 'hs-minor-mode-hook 'hs-hide-all))
9171 (if vhdl-hideshow-menu
9172 (hs-minor-mode 1)
9173 (when (boundp 'hs-minor-mode) (hs-minor-mode 0))))
9174
9175
9176 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9177 ;;; Font locking
9178 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9179 ;; (using `font-lock.el')
9180
9181 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9182 ;; Help functions for translate-off region highlighting
9183
9184 (defun vhdl-within-translate-off ()
9185 "Return point if within translate-off region, else nil."
9186 (and (save-excursion
9187 (re-search-backward
9188 "^\\s-*--\\s-*pragma\\s-*translate_\\(on\\|off\\)\\s-*\n" nil t))
9189 (equal "off" (match-string 1))
9190 (point)))
9191
9192 (defun vhdl-start-translate-off (limit)
9193 "Return point before translate-off pragma if before LIMIT, else nil."
9194 (when (re-search-forward
9195 "^\\s-*--\\s-*pragma\\s-*translate_off\\s-*\n" limit t)
9196 (match-beginning 0)))
9197
9198 (defun vhdl-end-translate-off (limit)
9199 "Return point after translate-on pragma if before LIMIT, else nil."
9200 (re-search-forward "^\\s-*--\\s-*pragma\\s-*translate_on\\s-*\n" limit t))
9201
9202 (defun vhdl-match-translate-off (limit)
9203 "Match a translate-off block, setting match-data and returning t, else nil."
9204 (when (< (point) limit)
9205 (let ((start (or (vhdl-within-translate-off)
9206 (vhdl-start-translate-off limit)))
9207 (case-fold-search t))
9208 (when start
9209 (let ((end (or (vhdl-end-translate-off limit) limit)))
9210 (set-match-data (list start end))
9211 (goto-char end))))))
9212
9213 (defun vhdl-font-lock-match-item (limit)
9214 "Match, and move over, any declaration item after point. Adapted from
9215 `font-lock-match-c-style-declaration-item-and-skip-to-next'."
9216 (condition-case nil
9217 (save-restriction
9218 (narrow-to-region (point-min) limit)
9219 ;; match item
9220 (when (looking-at "\\s-*\\(\\w+\\)")
9221 (save-match-data
9222 (goto-char (match-end 1))
9223 ;; move to next item
9224 (if (looking-at "\\(\\s-*,\\)")
9225 (goto-char (match-end 1))
9226 (end-of-line) t))))
9227 (error t)))
9228
9229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9230 ;; Syntax definitions
9231
9232 (defconst vhdl-font-lock-syntactic-keywords
9233 '(("\\(\'\\).\\(\'\\)" (1 (7 . ?\')) (2 (7 . ?\'))))
9234 "Mark single quotes as having string quote syntax in 'c' instances.")
9235
9236 (defvar vhdl-font-lock-keywords nil
9237 "Regular expressions to highlight in VHDL Mode.")
9238
9239 (defconst vhdl-font-lock-keywords-0
9240 (list
9241 ;; highlight template prompts
9242 (list (concat "\\(<" vhdl-template-prompt-syntax ">\\)")
9243 1 'vhdl-font-lock-prompt-face t)
9244
9245 ;; highlight directives
9246 '("--\\s-*pragma\\s-+\\(.*\\)$" 1 vhdl-font-lock-directive-face t)
9247 )
9248 "For consideration as a value of `vhdl-font-lock-keywords'.
9249 This does highlighting of template prompts and directives (pragmas).")
9250
9251 (defvar vhdl-font-lock-keywords-1 nil
9252 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9253 "For consideration as a value of `vhdl-font-lock-keywords'.
9254 This does highlighting of keywords and standard identifiers.")
9255
9256 (defconst vhdl-font-lock-keywords-2
9257 (list
9258 ;; highlight names of units, subprograms, and components when declared
9259 (list
9260 (concat
9261 "^\\s-*\\("
9262 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
9263 "\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\|component"
9264 "\\)\\s-+\\(\\w+\\)")
9265 5 'font-lock-function-name-face)
9266
9267 ;; highlight entity names of architectures and configurations
9268 (list
9269 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
9270 2 'font-lock-function-name-face)
9271
9272 ;; highlight labels of common constructs
9273 (list
9274 (concat
9275 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\("
9276 "assert\\|block\\|case\\|component\\|configuration\\|entity\\|exit\\|"
9277 "for\\|if\\|loop\\|next\\|null\\|postponed\\|process\\|"
9278 (when (vhdl-standard-p 'ams) "procedural\\|")
9279 "with\\|while"
9280 "\\)\\>\\|[^\n]*<=\\)")
9281 1 'font-lock-function-name-face)
9282
9283 ;; highlight label and component name of component instantiations
9284 (list
9285 (concat
9286 "^\\s-*\\(\\w+\\)\\s-*:[ \t\n]*\\(component\\s-+\\|\\)\\(\\w+\\)"
9287 "\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>")
9288 '(1 font-lock-function-name-face) '(3 font-lock-function-name-face))
9289
9290 ;; highlight names and labels at end of constructs
9291 (list
9292 (concat
9293 "^\\s-*end\\s-+\\(\\("
9294 "architecture\\|block\\|case\\|component\\|configuration\\|entity\\|"
9295 "for\\|function\\|generate\\|if\\|loop\\|package\\(\\s-+body\\|\\)\\|"
9296 "procedure\\|\\(postponed\\s-+\\|\\)process\\|"
9297 (when (vhdl-standard-p 'ams) "procedural\\|")
9298 "units"
9299 "\\)\\>\\|\\)\\s-*\\(\\w*\\)")
9300 5 'font-lock-function-name-face)
9301
9302 ;; highlight labels in exit and next statements
9303 (list
9304 (concat
9305 "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(exit\\|next\\)\\s-+\\(\\w*\\)")
9306 3 'font-lock-function-name-face)
9307
9308 ;; highlight entity name in attribute specifications
9309 (list
9310 (concat
9311 "^\\s-*attribute\\s-+\\w+\\s-+of\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:")
9312 1 'font-lock-function-name-face)
9313
9314 ;; highlight labels in component specifications
9315 (list
9316 (concat
9317 "^\\s-*for\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:"
9318 "\\(\\s-\\|\n\\)*\\(\\w+\\)")
9319 '(1 font-lock-function-name-face) '(4 font-lock-function-name-face))
9320
9321 ;; highlight attribute name in attribute declarations/specifications
9322 (list
9323 (concat
9324 "^\\s-*attribute\\s-+\\(\\w+\\)")
9325 1 'vhdl-font-lock-attribute-face)
9326
9327 ;; highlight type/nature name in (sub)type/(sub)nature declarations
9328 (list
9329 (concat
9330 "^\\s-*\\(sub\\|\\)\\(nature\\|type\\)\\s-+\\(\\w+\\)")
9331 3 'font-lock-type-face)
9332
9333 ;; highlight signal/variable/constant declaration names
9334 (list "\\(:[^=]\\)"
9335 '(vhdl-font-lock-match-item
9336 (progn (goto-char (match-beginning 1))
9337 (skip-syntax-backward " ")
9338 (skip-syntax-backward "w_")
9339 (skip-syntax-backward " ")
9340 (while (= (preceding-char) ?,)
9341 (backward-char 1)
9342 (skip-syntax-backward " ")
9343 (skip-syntax-backward "w_")
9344 (skip-syntax-backward " ")))
9345 ; (skip-chars-backward "^-(\n\";")
9346 (goto-char (match-end 1)) (1 font-lock-variable-name-face)))
9347
9348 ;; highlight alias/group declaration names and for-loop/-generate variables
9349 (list "\\<\\(alias\\|for\\|group\\)\\s-+\\w+\\s-+\\(in\\|is\\)\\>"
9350 '(vhdl-font-lock-match-item
9351 (progn (goto-char (match-end 1)) (match-beginning 2))
9352 nil (1 font-lock-variable-name-face)))
9353 )
9354 "For consideration as a value of `vhdl-font-lock-keywords'.
9355 This does context sensitive highlighting of names and labels.")
9356
9357 (defvar vhdl-font-lock-keywords-3 nil
9358 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9359 "For consideration as a value of `vhdl-font-lock-keywords'.
9360 This does highlighting of words with special syntax.")
9361
9362 (defvar vhdl-font-lock-keywords-4 nil
9363 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9364 "For consideration as a value of `vhdl-font-lock-keywords'.
9365 This does highlighting of additional reserved words.")
9366
9367 (defconst vhdl-font-lock-keywords-5
9368 ;; background highlight translate-off regions
9369 '((vhdl-match-translate-off (0 vhdl-font-lock-translate-off-face append)))
9370 "For consideration as a value of `vhdl-font-lock-keywords'.
9371 This does background highlighting of translate-off regions.")
9372
9373 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9374 ;; Font and color definitions
9375
9376 (defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
9377 "Face name to use for prompts.")
9378
9379 (defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
9380 "Face name to use for standardized attributes.")
9381
9382 (defvar vhdl-font-lock-enumvalue-face 'vhdl-font-lock-enumvalue-face
9383 "Face name to use for standardized enumeration values.")
9384
9385 (defvar vhdl-font-lock-function-face 'vhdl-font-lock-function-face
9386 "Face name to use for standardized functions and packages.")
9387
9388 (defvar vhdl-font-lock-directive-face 'vhdl-font-lock-directive-face
9389 "Face name to use for directives.")
9390
9391 (defvar vhdl-font-lock-reserved-words-face 'vhdl-font-lock-reserved-words-face
9392 "Face name to use for additional reserved words.")
9393
9394 (defvar vhdl-font-lock-translate-off-face 'vhdl-font-lock-translate-off-face
9395 "Face name to use for translate-off regions.")
9396
9397 ;; face names to use for words with special syntax.
9398 (let ((syntax-alist vhdl-special-syntax-alist)
9399 name)
9400 (while syntax-alist
9401 (setq name (vhdl-function-name
9402 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
9403 (eval `(defvar ,name ',name
9404 ,(concat "Face name to use for "
9405 (nth 0 (car syntax-alist)) ".")))
9406 (setq syntax-alist (cdr syntax-alist))))
9407
9408 (defgroup vhdl-highlight-faces nil
9409 "Faces for highlighting."
9410 :group 'vhdl-highlight)
9411
9412 ;; add faces used from `font-lock'
9413 (custom-add-to-group
9414 'vhdl-highlight-faces 'font-lock-comment-face 'custom-face)
9415 (custom-add-to-group
9416 'vhdl-highlight-faces 'font-lock-string-face 'custom-face)
9417 (custom-add-to-group
9418 'vhdl-highlight-faces 'font-lock-keyword-face 'custom-face)
9419 (custom-add-to-group
9420 'vhdl-highlight-faces 'font-lock-type-face 'custom-face)
9421 (custom-add-to-group
9422 'vhdl-highlight-faces 'font-lock-function-name-face 'custom-face)
9423 (custom-add-to-group
9424 'vhdl-highlight-faces 'font-lock-variable-name-face 'custom-face)
9425
9426 (defface vhdl-font-lock-prompt-face
9427 '((((class color) (background light)) (:foreground "Red" :bold t))
9428 (((class color) (background dark)) (:foreground "Pink" :bold t))
9429 (t (:inverse-video t)))
9430 "Font lock mode face used to highlight prompts."
9431 :group 'vhdl-highlight-faces
9432 :group 'font-lock-highlighting-faces)
9433
9434 (defface vhdl-font-lock-attribute-face
9435 '((((class color) (background light)) (:foreground "Orchid"))
9436 (((class color) (background dark)) (:foreground "LightSteelBlue"))
9437 (t (:italic t :bold t)))
9438 "Font lock mode face used to highlight standardized attributes."
9439 :group 'vhdl-highlight-faces
9440 :group 'font-lock-highlighting-faces)
9441
9442 (defface vhdl-font-lock-enumvalue-face
9443 '((((class color) (background light)) (:foreground "Gold4"))
9444 (((class color) (background dark)) (:foreground "BurlyWood"))
9445 (t (:italic t :bold t)))
9446 "Font lock mode face used to highlight standardized enumeration values."
9447 :group 'vhdl-highlight-faces
9448 :group 'font-lock-highlighting-faces)
9449
9450 (defface vhdl-font-lock-function-face
9451 '((((class color) (background light)) (:foreground "Orchid4"))
9452 (((class color) (background dark)) (:foreground "Orchid1"))
9453 (t (:italic t :bold t)))
9454 "Font lock mode face used to highlight standardized functions and packages."
9455 :group 'vhdl-highlight-faces
9456 :group 'font-lock-highlighting-faces)
9457
9458 (defface vhdl-font-lock-directive-face
9459 '((((class color) (background light)) (:foreground "CadetBlue"))
9460 (((class color) (background dark)) (:foreground "Aquamarine"))
9461 (t (:italic t :bold t)))
9462 "Font lock mode face used to highlight directives."
9463 :group 'vhdl-highlight-faces
9464 :group 'font-lock-highlighting-faces)
9465
9466 (defface vhdl-font-lock-reserved-words-face
9467 '((((class color) (background light)) (:foreground "Orange" :bold t))
9468 (((class color) (background dark)) (:foreground "Yellow" :bold t))
9469 (t ()))
9470 "Font lock mode face used to highlight additional reserved words."
9471 :group 'vhdl-highlight-faces
9472 :group 'font-lock-highlighting-faces)
9473
9474 (defface vhdl-font-lock-translate-off-face
9475 '((((class color) (background light)) (:background "LightGray"))
9476 (((class color) (background dark)) (:background "DimGray"))
9477 (t ()))
9478 "Font lock mode face used to background highlight translate-off regions."
9479 :group 'vhdl-highlight-faces
9480 :group 'font-lock-highlighting-faces)
9481
9482 ;; font lock mode faces used to highlight words with special syntax.
9483 (let ((syntax-alist vhdl-special-syntax-alist))
9484 (while syntax-alist
9485 (eval `(defface ,(vhdl-function-name
9486 "vhdl-font-lock" (car (car syntax-alist)) "face")
9487 '((((class color) (background light))
9488 (:foreground ,(nth 2 (car syntax-alist))))
9489 (((class color) (background dark))
9490 (:foreground ,(nth 3 (car syntax-alist))))
9491 (t ()))
9492 ,(concat "Font lock mode face used to highlight "
9493 (nth 0 (car syntax-alist)) ".")
9494 :group 'vhdl-highlight-faces
9495 :group 'font-lock-highlighting-faces))
9496 (setq syntax-alist (cdr syntax-alist))))
9497
9498 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9499 ;; Font lock initialization
9500
9501 (defun vhdl-font-lock-init ()
9502 "Initialize fontification."
9503 ;; highlight keywords and standardized types, attributes, enumeration
9504 ;; values, and subprograms
9505 (setq vhdl-font-lock-keywords-1
9506 (list
9507 (list (concat "'" vhdl-attributes-regexp)
9508 1 'vhdl-font-lock-attribute-face)
9509 (list vhdl-types-regexp 1 'font-lock-type-face)
9510 (list vhdl-functions-regexp 1 'vhdl-font-lock-function-face)
9511 (list vhdl-packages-regexp 1 'vhdl-font-lock-function-face)
9512 (list vhdl-enum-values-regexp 1 'vhdl-font-lock-enumvalue-face)
9513 (list vhdl-keywords-regexp 1 'font-lock-keyword-face)))
9514 ;; highlight words with special syntax.
9515 (setq vhdl-font-lock-keywords-3
9516 (let ((syntax-alist vhdl-special-syntax-alist)
9517 keywords)
9518 (while syntax-alist
9519 (setq keywords
9520 (cons
9521 (cons (concat "\\<\\(" (nth 1 (car syntax-alist)) "\\)\\>")
9522 (vhdl-function-name
9523 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
9524 keywords))
9525 (setq syntax-alist (cdr syntax-alist)))
9526 keywords))
9527 ;; highlight additional reserved words
9528 (setq vhdl-font-lock-keywords-4
9529 (list (list vhdl-reserved-words-regexp 1
9530 'vhdl-font-lock-reserved-words-face)))
9531 ;; highlight everything together
9532 (setq vhdl-font-lock-keywords
9533 (append
9534 vhdl-font-lock-keywords-0
9535 (when vhdl-highlight-keywords vhdl-font-lock-keywords-1)
9536 (when (or vhdl-highlight-forbidden-words
9537 vhdl-highlight-verilog-keywords) vhdl-font-lock-keywords-4)
9538 (when vhdl-highlight-special-words vhdl-font-lock-keywords-3)
9539 (when vhdl-highlight-names vhdl-font-lock-keywords-2)
9540 (when vhdl-highlight-translate-off vhdl-font-lock-keywords-5))))
9541
9542 ;; initialize fontification for VHDL Mode
9543 (vhdl-font-lock-init)
9544
9545 (defun vhdl-fontify-buffer ()
9546 "Re-initialize fontification and fontify buffer."
9547 (interactive)
9548 (setq font-lock-defaults
9549 (list
9550 'vhdl-font-lock-keywords nil
9551 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
9552 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
9553 (when (fboundp 'font-lock-unset-defaults)
9554 (font-lock-unset-defaults)) ; not implemented in XEmacs
9555 (font-lock-set-defaults)
9556 (font-lock-fontify-buffer))
9557
9558 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9559 ;; Initialization for postscript printing
9560
9561 (defun vhdl-ps-print-settings ()
9562 "Initialize custom face and page settings for postscript printing."
9563 ;; define custom face settings
9564 (unless (or (not vhdl-print-customize-faces)
9565 ps-print-color-p)
9566 (set (make-local-variable 'ps-bold-faces)
9567 '(font-lock-keyword-face
9568 font-lock-type-face
9569 vhdl-font-lock-attribute-face
9570 vhdl-font-lock-enumvalue-face
9571 vhdl-font-lock-directive-face))
9572 (set (make-local-variable 'ps-italic-faces)
9573 '(font-lock-comment-face
9574 font-lock-function-name-face
9575 font-lock-type-face
9576 vhdl-font-lock-attribute-face
9577 vhdl-font-lock-enumvalue-face
9578 vhdl-font-lock-directive-face))
9579 (set (make-local-variable 'ps-underlined-faces)
9580 '(font-lock-string-face))
9581 (setq ps-always-build-face-reference t))
9582 ;; define page settings, so that a line containing 79 characters (default)
9583 ;; fits into one column
9584 (when vhdl-print-two-column
9585 (set (make-local-variable 'ps-landscape-mode) t)
9586 (set (make-local-variable 'ps-number-of-columns) 2)
9587 (set (make-local-variable 'ps-font-size) 7.0)
9588 (set (make-local-variable 'ps-header-title-font-size) 10.0)
9589 (set (make-local-variable 'ps-header-font-size) 9.0)
9590 (set (make-local-variable 'ps-header-offset) 12.0)
9591 (when (eq ps-paper-type 'letter)
9592 (set (make-local-variable 'ps-inter-column) 40.0)
9593 (set (make-local-variable 'ps-left-margin) 40.0)
9594 (set (make-local-variable 'ps-right-margin) 40.0))))
9595
9596 (defun vhdl-ps-print-init ()
9597 "Initialize postscript printing."
9598 (if (string-match "XEmacs" emacs-version)
9599 (vhdl-ps-print-settings)
9600 (make-local-variable 'ps-print-hook)
9601 (add-hook 'ps-print-hook 'vhdl-ps-print-settings)))
9602
9603
9604 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9605 ;;; Hierarchy browser (using `speedbar.el')
9606 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9607 ;; Allows displaying the hierarchy of all VHDL design units contained in a
9608 ;; directory by using the speedbar.
9609
9610 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9611 ;; Variables
9612
9613 (defvar vhdl-entity-alist nil
9614 "Cache with entities and corresponding architectures and configurations for
9615 each visited directory.")
9616 ;; structure: (parenthesised expression means list of such entries)
9617 ;; (directory-name
9618 ;; (ent-name ent-file ent-line
9619 ;; (arch-name arch-file arch-line
9620 ;; (inst-name inst-file inst-line inst-ent-name inst-arch-name))
9621 ;; (conf-name conf-file conf-line))
9622
9623 (defvar vhdl-package-alist nil
9624 "Cache with packages for each visited directory.")
9625 ;; structure: (parenthesised expression means list of such entries)
9626 ;; (directory-name
9627 ;; (pack-name pack-file pack-line pack-body-file pack-body-line))
9628
9629 (defvar vhdl-ent-inst-alist nil
9630 "Cache with instantiated entities for each visited directory.")
9631 ;; structure: (parenthesised expression means list of such entries)
9632 ;; (directory-name (inst-ent-name))
9633
9634 (defvar vhdl-project-entity-alist nil
9635 "Cache with entities and corresponding architectures and configurations for
9636 each visited project.")
9637 ;; same structure as `vhdl-entity-alist'
9638
9639 (defvar vhdl-project-package-alist nil
9640 "Cache with packages for each visited directory.")
9641 ;; same structure as `vhdl-package-alist'
9642
9643 (defvar vhdl-project-ent-inst-list nil
9644 "Cache with instantiated entities for each visited directory.")
9645 ;; same structure as `vhdl-ent-inst-alist'
9646
9647 (defvar vhdl-speedbar-shown-units-alist nil
9648 "Alist of design units simultaneously open in the current speedbar for each
9649 directory and project.")
9650
9651 (defvar vhdl-speedbar-last-file-name nil
9652 "Last file for which design units were highlighted.")
9653
9654 (defvar vhdl-file-alist nil
9655 "Cache with design units in each file.")
9656 ;; structure (parenthesised expression means list of such entries)
9657 ;; (file-name (ent-list) (arch-list) (conf-list) (pack-list) (inst-list))
9658
9659 ;; help function
9660 (defsubst vhdl-speedbar-project-p ()
9661 "Return non-nil if a project is displayed, i.e. directories or files are
9662 specified."
9663 (nth 1 (aget vhdl-project-alist vhdl-project)))
9664
9665 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9666 ;; Scan functions
9667
9668 (defun vhdl-scan-file-contents (name &optional num-string)
9669 "Scan contents of VHDL files in FILE-LIST."
9670 (string-match "\\(.*/\\)\\(.*\\)" name)
9671 ; (unless (file-directory-p (match-string 1 name))
9672 ; (message "No such directory: \"%s\"" (match-string 1 name)))
9673 (let* ((is-directory (= (match-beginning 2) (match-end 2)))
9674 (file-list
9675 (if is-directory
9676 (nreverse (vhdl-get-source-files t name))
9677 (vhdl-directory-files (match-string 1 name) t
9678 (wildcard-to-regexp (match-string 2 name)))))
9679 (case-fold-search t)
9680 (source-buffer (current-buffer))
9681 ent-alist pack-alist ent-inst-list no-files)
9682 (when (and (not is-directory) (null file-list))
9683 (message "No such file: \"%s\"" name))
9684 (save-excursion
9685 (when file-list
9686 (setq no-files (length file-list))
9687 ;; do for all files
9688 (while file-list
9689 (message "Scanning %s %s\"%s\"... (%2d%s)"
9690 (if is-directory "directory" "files")
9691 (or num-string "") name
9692 (/ (* 100 (- no-files (length file-list))) no-files) "%")
9693 (let ((file-name (abbreviate-file-name (car file-list)))
9694 opened arch-name ent-name
9695 ent-list arch-list conf-list pack-list inst-list)
9696 ;; open file
9697 (if (find-buffer-visiting file-name)
9698 (set-buffer (find-buffer-visiting file-name))
9699 (set-buffer (find-file-noselect file-name nil t))
9700 (setq opened t))
9701 (modify-syntax-entry ?_ "w" (syntax-table))
9702 ;; scan for entities
9703 (goto-char (point-min))
9704 (while (re-search-forward "^\\s-*entity\\s-+\\(\\w+\\)" nil t)
9705 (let* ((ent-entry (aget ent-alist (match-string 1)))
9706 (arch-alist (nth 2 ent-entry))
9707 (conf-alist (nth 3 ent-entry)))
9708 (setq ent-list (cons (match-string 1) ent-list))
9709 (aput 'ent-alist (match-string 1)
9710 (list file-name (vhdl-current-line)
9711 arch-alist conf-alist nil))))
9712 ;; scan for architectures and instantiations
9713 (goto-char (point-min))
9714 (while (re-search-forward
9715 (concat
9716 "^\\s-*\\(architecture\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)\\|"
9717 "\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(entity\\s-+\\w+\\.\\)?"
9718 "\\(\\w+\\)\\(\\s-*(\\(\\w+\\))\\)?\\(\\s-\\|\n\\|--.*\n\\)*"
9719 "\\(generic\\|port\\)\\s-+map\\>\\)")
9720 nil t)
9721 (if (match-string 2)
9722 ;; architecture found
9723 (let* ((ent-entry (aget ent-alist (match-string 3)))
9724 (arch-alist (nth 2 ent-entry))
9725 (conf-alist (nth 3 ent-entry)))
9726 (setq arch-name (match-string 2))
9727 (setq ent-name (match-string 3))
9728 (setq arch-list (cons arch-name arch-list))
9729 (vhdl-aappend 'arch-alist arch-name
9730 (list file-name (vhdl-current-line) nil))
9731 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9732 arch-alist conf-alist nil))
9733 (aput 'ent-alist ent-name ent-entry))
9734 ;; instantiation found
9735 (let* ((ent-entry (aget ent-alist ent-name))
9736 (arch-alist (nth 2 ent-entry))
9737 (arch-entry (aget arch-alist arch-name))
9738 (inst-alist (nth 2 arch-entry))
9739 (inst-name (match-string 4))
9740 (inst-ent-name (match-string 7))
9741 (inst-arch-name (match-string 9))
9742 (conf-alist (nth 3 ent-entry)))
9743 (re-search-backward ":" nil t)
9744 (setq inst-list (cons inst-name inst-list))
9745 (vhdl-aappend 'inst-alist inst-name
9746 (list file-name (vhdl-current-line)
9747 inst-ent-name inst-arch-name))
9748 (setq arch-entry
9749 (list (nth 0 arch-entry) (nth 1 arch-entry)
9750 inst-alist))
9751 (vhdl-aappend 'arch-alist arch-name arch-entry)
9752 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9753 arch-alist conf-alist nil))
9754 (aput 'ent-alist ent-name ent-entry)
9755 (unless (member inst-ent-name ent-inst-list)
9756 (setq ent-inst-list
9757 (cons inst-ent-name ent-inst-list))))))
9758 ;; scan for configurations
9759 (goto-char (point-min))
9760 (while (re-search-forward
9761 "^\\s-*configuration\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)"
9762 nil t)
9763 (let* ((ent-entry (aget ent-alist (match-string 2)))
9764 (arch-alist (nth 2 ent-entry))
9765 (conf-alist (nth 3 ent-entry)))
9766 (setq conf-list (cons (match-string 1) conf-list))
9767 (vhdl-aappend 'conf-alist (match-string 1)
9768 (list file-name (vhdl-current-line)))
9769 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9770 arch-alist conf-alist nil))
9771 (aput 'ent-alist (match-string 2) ent-entry)))
9772 ;; scan for packages
9773 (goto-char (point-min))
9774 (while (re-search-forward
9775 "^\\s-*package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" nil t)
9776 (let ((pack-entry (aget pack-alist (match-string 2))))
9777 (setq pack-list (cons (match-string 2) pack-list))
9778 (aput 'pack-alist (match-string 2)
9779 (if (not (match-string 1))
9780 (list file-name (vhdl-current-line)
9781 (nth 2 pack-entry) (nth 3 pack-entry))
9782 (list (nth 0 pack-entry) (nth 1 pack-entry)
9783 file-name (vhdl-current-line))))))
9784 (setq file-list (cdr file-list))
9785 ;; add design units to variable `vhdl-file-alist'
9786 (aput 'vhdl-file-alist file-name
9787 (list ent-list arch-list conf-list pack-list inst-list))
9788 ;; close file
9789 (if opened
9790 (kill-buffer (current-buffer))
9791 (when (not vhdl-underscore-is-part-of-word)
9792 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table)))
9793 (set-buffer source-buffer)))
9794 ;; sort entities and packages
9795 (setq ent-alist
9796 (sort ent-alist
9797 (function (lambda (a b) (string-lessp (car a) (car b))))))
9798 (setq pack-alist
9799 (sort pack-alist
9800 (function (lambda (a b) (string-lessp (car a) (car b))))))
9801 ;; put directory contents into cache
9802 (when ent-alist
9803 (aput 'vhdl-entity-alist name ent-alist))
9804 (when pack-alist
9805 (aput 'vhdl-package-alist name pack-alist))
9806 (when ent-inst-list
9807 (aput 'vhdl-ent-inst-alist name (list ent-inst-list)))
9808 (message "Scanning %s %s\"%s\"...done"
9809 (if is-directory "directory" "files") (or num-string "") name)
9810 t))))
9811
9812 (defun vhdl-scan-project-contents (project &optional rescan)
9813 "Scan the contents of all VHDL files found in the directories and files
9814 of PROJECT."
9815 (let ((dir-list-tmp (nth 1 (aget vhdl-project-alist project)))
9816 dir-list pro-ent-alist pro-pack-alist pro-ent-inst-list
9817 dir name num-dir act-dir)
9818 ;; resolve environment variables and path wildcards
9819 (setq dir-list-tmp (vhdl-resolve-paths dir-list-tmp))
9820 ;; expand directories
9821 (while dir-list-tmp
9822 (setq dir (car dir-list-tmp))
9823 ;; get subdirectories
9824 (if (string-match "-r \\(.*/\\)" dir)
9825 (setq dir-list (append dir-list (vhdl-get-subdirs
9826 (match-string 1 dir))))
9827 (setq dir-list (append dir-list (list dir))))
9828 (setq dir-list-tmp (cdr dir-list-tmp)))
9829 ;; get entities and packages of each directory in DIR-LIST
9830 (setq num-dir (length dir-list)
9831 act-dir 1)
9832 (while dir-list
9833 (setq name (abbreviate-file-name (car dir-list)))
9834 (or (and (not rescan)
9835 (or (assoc name vhdl-entity-alist)
9836 (assoc name vhdl-package-alist)))
9837 (vhdl-scan-file-contents name (format "(%s/%s) " act-dir num-dir)))
9838 ;; merge entities and corresponding architectures and configurations
9839 (let ((ent-alist (aget vhdl-entity-alist name)))
9840 (while ent-alist
9841 (let* ((ent-name (car (car ent-alist)))
9842 (ent-entry (cdr (car ent-alist)))
9843 (pro-ent-entry (aget pro-ent-alist ent-name)))
9844 (aput 'pro-ent-alist ent-name
9845 (list (or (nth 0 pro-ent-entry) (nth 0 ent-entry))
9846 (or (nth 1 pro-ent-entry) (nth 1 ent-entry))
9847 (append (nth 2 pro-ent-entry) (nth 2 ent-entry))
9848 (append (nth 3 pro-ent-entry) (nth 3 ent-entry)))))
9849 (setq ent-alist (cdr ent-alist))))
9850 ;; merge packages and corresponding package bodies
9851 (let ((pack-alist (aget vhdl-package-alist name)))
9852 (while pack-alist
9853 (let* ((pack-name (car (car pack-alist)))
9854 (pack-entry (cdr (car pack-alist)))
9855 (pro-pack-entry (aget pro-pack-alist pack-name)))
9856 (aput 'pro-pack-alist pack-name
9857 (list (or (nth 0 pro-pack-entry) (nth 0 pack-entry))
9858 (or (nth 1 pro-pack-entry) (nth 1 pack-entry))
9859 (or (nth 2 pro-pack-entry) (nth 2 pack-entry))
9860 (or (nth 3 pro-pack-entry) (nth 3 pack-entry)))))
9861 (setq pack-alist (cdr pack-alist))))
9862 ;; merge list of instantiated entities
9863 (setq pro-ent-inst-list
9864 (append pro-ent-inst-list
9865 (copy-alist
9866 (car (aget vhdl-ent-inst-alist name)))))
9867 (setq dir-list (cdr dir-list)
9868 act-dir (1+ act-dir)))
9869 ;; sort lists and put them into the caches
9870 (when pro-ent-alist
9871 (aput 'vhdl-project-entity-alist project
9872 (sort pro-ent-alist
9873 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9874 (when pro-pack-alist
9875 (aput 'vhdl-project-package-alist project
9876 (sort pro-pack-alist
9877 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9878 (when pro-ent-inst-list
9879 (aput 'vhdl-project-ent-inst-list project pro-ent-inst-list))))
9880
9881 (defun vhdl-get-hierarchy (ent-name arch-name level indent &optional ent-hier)
9882 "Get instantiation hierarchy beginning in architecture ARCH-NAME of
9883 entity ENT-NAME."
9884 (let* ((ent-alist (if (vhdl-speedbar-project-p)
9885 (aget vhdl-project-entity-alist vhdl-project)
9886 (aget vhdl-entity-alist
9887 (abbreviate-file-name
9888 (file-name-as-directory
9889 (speedbar-line-path (1- indent)))))))
9890 (ent-entry (aget ent-alist ent-name))
9891 (arch-entry (if arch-name (aget (nth 2 ent-entry) arch-name)
9892 (cdr (car (last (nth 2 ent-entry))))))
9893 (inst-list (nth 2 arch-entry))
9894 inst-entry inst-ent-entry inst-arch-entry hier-list)
9895 (when (= level 0) (message "Extract design hierarchy..."))
9896 (when (member ent-name ent-hier)
9897 (error (format "Instantiation loop detected; component \"%s\" instantiates itself"
9898 ent-name)))
9899 (while inst-list
9900 (setq inst-entry (car inst-list))
9901 (setq inst-ent-entry (aget ent-alist (nth 3 inst-entry)))
9902 (setq inst-arch-entry
9903 (if (nth 4 inst-entry)
9904 (cons (nth 4 inst-entry)
9905 (aget (nth 2 inst-ent-entry) (nth 4 inst-entry)))
9906 (car (last (nth 2 inst-ent-entry)))))
9907 (setq hier-list
9908 (append
9909 hier-list
9910 (cons (list (nth 0 inst-entry)
9911 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9912 (nth 3 inst-entry)
9913 (cons (nth 0 inst-ent-entry) (nth 1 inst-ent-entry))
9914 (nth 0 inst-arch-entry)
9915 (cons (nth 1 inst-arch-entry) (nth 2 inst-arch-entry))
9916 level)
9917 (vhdl-get-hierarchy (nth 3 inst-entry) (nth 4 inst-entry)
9918 (1+ level) indent
9919 (cons ent-name ent-hier)))))
9920 (setq inst-list (cdr inst-list)))
9921 (when (= level 0) (message "Extract design hierarchy...done"))
9922 hier-list))
9923
9924 (defun vhdl-get-instantiations (ent-name indent)
9925 "Get all instantiations of entity ENT-NAME."
9926 (let ((ent-alist (if (vhdl-speedbar-project-p)
9927 (aget vhdl-project-entity-alist vhdl-project)
9928 (aget vhdl-entity-alist
9929 (abbreviate-file-name
9930 (file-name-as-directory
9931 (speedbar-line-path indent))))))
9932 arch-alist inst-alist ent-inst-list
9933 ent-entry arch-entry inst-entry)
9934 (while ent-alist
9935 (setq ent-entry (car ent-alist))
9936 (setq arch-alist (nth 3 ent-entry))
9937 (while arch-alist
9938 (setq arch-entry (car arch-alist))
9939 (setq inst-alist (nth 3 arch-entry))
9940 (while inst-alist
9941 (setq inst-entry (car inst-alist))
9942 (when (equal ent-name (nth 3 inst-entry))
9943 (setq ent-inst-list
9944 (cons (list (nth 0 inst-entry)
9945 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9946 (nth 0 ent-entry)
9947 (cons (nth 1 ent-entry) (nth 2 ent-entry))
9948 (nth 0 arch-entry)
9949 (cons (nth 1 arch-entry) (nth 2 arch-entry)))
9950 ent-inst-list)))
9951 (setq inst-alist (cdr inst-alist)))
9952 (setq arch-alist (cdr arch-alist)))
9953 (setq ent-alist (cdr ent-alist)))
9954 (nreverse ent-inst-list)))
9955
9956 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9957 ;; Add hierarchy browser functionality to speedbar.
9958
9959 (defvar vhdl-speedbar-key-map nil
9960 "Keymap used when in the VHDL hierarchy browser mode.")
9961
9962 (defvar vhdl-speedbar-menu-items
9963 '(["Edit Design Unit" speedbar-edit-line t]
9964 ["Expand Hierarchy" speedbar-expand-line
9965 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.\\+. "))]
9966 ["Contract Hierarchy" speedbar-contract-line
9967 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.-. "))]
9968 ["Rescan Hierarchy" vhdl-speedbar-rescan-hierarchy t]
9969 "--"
9970 ["Copy Port" vhdl-speedbar-port-copy
9971 (save-excursion
9972 (beginning-of-line) (looking-at "[0-9]+: *\\[[-+?]\\] "))])
9973 "Additional menu-items to add to speedbar frame.")
9974
9975 (defun vhdl-speedbar-initialize ()
9976 "Initialize speedbar."
9977 ;; general settings
9978 ; (set (make-local-variable 'speedbar-tag-hierarchy-method) nil)
9979 ;; VHDL file extensions (extracted from `auto-mode-alist')
9980 (let ((mode-alist auto-mode-alist))
9981 (while mode-alist
9982 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
9983 (speedbar-add-supported-extension (car (car mode-alist))))
9984 (setq mode-alist (cdr mode-alist))))
9985 ;; hierarchy browser settings
9986 (when (boundp 'speedbar-mode-functions-list)
9987 (speedbar-add-mode-functions-list
9988 '("vhdl hierarchy"
9989 (speedbar-item-info . vhdl-speedbar-item-info)
9990 (speedbar-line-path . speedbar-files-line-path)))
9991 (unless vhdl-speedbar-key-map
9992 (setq vhdl-speedbar-key-map (speedbar-make-specialized-keymap))
9993 (define-key vhdl-speedbar-key-map "e" 'speedbar-edit-line)
9994 (define-key vhdl-speedbar-key-map "\C-m" 'speedbar-edit-line)
9995 (define-key vhdl-speedbar-key-map "+" 'speedbar-expand-line)
9996 (define-key vhdl-speedbar-key-map "-" 'speedbar-contract-line)
9997 (define-key vhdl-speedbar-key-map "s" 'vhdl-speedbar-rescan-hierarchy)
9998 (define-key vhdl-speedbar-key-map "c" 'vhdl-speedbar-port-copy))
9999 (define-key speedbar-key-map "h"
10000 (lambda () (interactive)
10001 (speedbar-change-initial-expansion-list "vhdl hierarchy")))
10002 (speedbar-add-expansion-list '("vhdl hierarchy" vhdl-speedbar-menu-items
10003 vhdl-speedbar-key-map
10004 vhdl-speedbar-display-hierarchy))
10005 (setq speedbar-stealthy-function-list
10006 (cons '("vhdl hierarchy" vhdl-speedbar-update-current-unit)
10007 speedbar-stealthy-function-list))
10008 (when vhdl-speedbar-show-hierarchy
10009 (setq speedbar-initial-expansion-list-name "vhdl hierarchy"))))
10010
10011 (defun vhdl-speedbar (&optional arg)
10012 "Open/close speedbar."
10013 (interactive)
10014 (if (not (fboundp 'speedbar))
10015 (error "WARNING: Speedbar is only available in newer Emacs versions")
10016 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
10017 (speedbar-frame-mode arg)
10018 (error (error "WARNING: Install included `speedbar.el' patch first")))))
10019
10020 ;; initialize speedbar for VHDL Mode
10021 (if (not (boundp 'speedbar-frame))
10022 (add-hook 'speedbar-load-hook 'vhdl-speedbar-initialize)
10023 (vhdl-speedbar-initialize)
10024 (when speedbar-frame (speedbar-refresh)))
10025
10026 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10027 ;; Display functions
10028
10029 ;; macros must be defined in the file they are used (copied from `speedbar.el')
10030 (defmacro speedbar-with-writable (&rest forms)
10031 "Allow the buffer to be writable and evaluate FORMS."
10032 (list 'let '((inhibit-read-only t))
10033 (cons 'progn forms)))
10034 (put 'speedbar-with-writable 'lisp-indent-function 0)
10035
10036 (defun vhdl-speedbar-display-hierarchy (directory depth &optional rescan)
10037 "Display directory and hierarchy information in speedbar."
10038 (setq directory (abbreviate-file-name (file-name-as-directory directory)))
10039 (setq speedbar-last-selected-file nil)
10040 (speedbar-with-writable
10041 (save-excursion
10042 (if (vhdl-speedbar-project-p)
10043 (progn
10044 ;; insert project title
10045 (vhdl-speedbar-make-title-line "Project:" 0)
10046 (let ((start (point)))
10047 (insert "p:")
10048 (put-text-property start (point) 'invisible t)
10049 (setq start (point))
10050 (insert vhdl-project)
10051 (put-text-property start (point) 'face 'speedbar-directory-face))
10052 (insert-char ?\n 1)
10053 ;; scan and insert hierarchy of project
10054 (vhdl-speedbar-insert-project-hierarchy vhdl-project
10055 speedbar-power-click))
10056 ;; insert directory path
10057 (speedbar-directory-buttons directory depth)
10058 ;; insert subdirectories
10059 (vhdl-speedbar-insert-dirs (speedbar-file-lists directory) depth)
10060 ;; scan and insert hierarchy of current directory
10061 (vhdl-speedbar-insert-dir-hierarchy directory depth
10062 speedbar-power-click)
10063 ;; expand subdirectories
10064 (when (= depth 0) (vhdl-speedbar-expand-dirs directory))))))
10065
10066 (defun vhdl-speedbar-insert-hierarchy (ent-alist pack-alist
10067 ent-inst-list depth)
10068 "Insert hierarchy of ENT-ALIST and PACK-ALIST."
10069 (if (not (or ent-alist pack-alist))
10070 (vhdl-speedbar-make-title-line "No design units!" depth)
10071 (let (ent-entry pack-entry)
10072 ;; insert entities
10073 (when ent-alist (vhdl-speedbar-make-title-line "Entities:" depth))
10074 (while ent-alist
10075 (setq ent-entry (car ent-alist))
10076 (speedbar-make-tag-line
10077 'bracket ?+ 'vhdl-speedbar-expand-entity (nth 0 ent-entry)
10078 (nth 0 ent-entry) 'vhdl-speedbar-find-file
10079 (cons (nth 1 ent-entry) (nth 2 ent-entry))
10080 'vhdl-speedbar-entity-face depth)
10081 (when (not (member (nth 0 ent-entry) ent-inst-list))
10082 (end-of-line 0) (insert " (top)") (forward-char 1))
10083 (setq ent-alist (cdr ent-alist)))
10084 ;; insert packages
10085 (when pack-alist (vhdl-speedbar-make-title-line "Packages:" depth))
10086 (while pack-alist
10087 (setq pack-entry (car pack-alist))
10088 (vhdl-speedbar-make-pack-line
10089 (nth 0 pack-entry)
10090 (cons (nth 1 pack-entry) (nth 2 pack-entry))
10091 (cons (nth 3 pack-entry) (nth 4 pack-entry))
10092 depth)
10093 (setq pack-alist (cdr pack-alist))))))
10094
10095 (defun vhdl-speedbar-insert-project-hierarchy (project &optional rescan)
10096 "Insert hierarchy of project. Rescan directories if RESCAN is non-nil,
10097 otherwise use cached data of directories."
10098 (when (or rescan (and (not (assoc project vhdl-project-entity-alist))
10099 (not (assoc project vhdl-project-package-alist))))
10100 (vhdl-scan-project-contents project rescan))
10101 ;; insert design hierarchy in speedbar
10102 (vhdl-speedbar-insert-hierarchy
10103 (aget vhdl-project-entity-alist project)
10104 (aget vhdl-project-package-alist project)
10105 (aget vhdl-project-ent-inst-list project) 0)
10106 ;; expand design units
10107 (vhdl-speedbar-expand-units project))
10108
10109 (defun vhdl-speedbar-insert-dir-hierarchy (directory depth &optional rescan)
10110 "Insert hierarchy of DIRECTORY. Rescan directory if RESCAN is non-nil,
10111 otherwise use cached data."
10112 (when (or rescan (and (not (assoc directory vhdl-entity-alist))
10113 (not (assoc directory vhdl-package-alist))))
10114 (vhdl-scan-file-contents directory))
10115 (vhdl-speedbar-insert-hierarchy
10116 (aget vhdl-entity-alist directory)
10117 (aget vhdl-package-alist directory)
10118 (car (aget vhdl-ent-inst-alist directory))
10119 depth)
10120 (vhdl-speedbar-expand-units directory))
10121
10122 (defun vhdl-speedbar-rescan-hierarchy ()
10123 "Rescan hierarchy for the directory under the cursor or the current project."
10124 (interactive)
10125 (cond
10126 ;; the current project
10127 ((vhdl-speedbar-project-p)
10128 (vhdl-scan-project-contents vhdl-project t)
10129 (speedbar-refresh))
10130 ;; the top-level directory
10131 ((save-excursion (beginning-of-line) (looking-at "[^0-9]"))
10132 (re-search-forward "[0-9]+:" nil t)
10133 (vhdl-scan-file-contents (abbreviate-file-name (speedbar-line-path)))
10134 (speedbar-refresh))
10135 ;; the current directory
10136 (t (let ((path (speedbar-line-path)))
10137 (string-match "^\\(.+/\\)" path)
10138 (vhdl-scan-file-contents (abbreviate-file-name (match-string 1 path)))
10139 (speedbar-refresh)))))
10140
10141 (defun vhdl-speedbar-expand-dirs (directory)
10142 "Expand subdirectories in DIRECTORY according to
10143 `speedbar-shown-directories'."
10144 ;; (nicked from `speedbar-default-directory-list')
10145 (let ((sf (cdr (reverse speedbar-shown-directories))))
10146 (setq speedbar-shown-directories
10147 (list (expand-file-name default-directory)))
10148 (while sf
10149 (when (speedbar-goto-this-file (car sf))
10150 (beginning-of-line)
10151 (when (looking-at "[0-9]+:\\s-*<")
10152 (goto-char (match-end 0))
10153 (let* ((position (point))
10154 (directory (abbreviate-file-name
10155 (file-name-as-directory (speedbar-line-file)))))
10156 (speedbar-do-function-pointer))))
10157 (setq sf (cdr sf)))))
10158
10159 (defun vhdl-speedbar-expand-units (directory)
10160 "Expand design units in DIRECTORY according to
10161 `vhdl-speedbar-shown-units-alist'."
10162 (let ((ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10163 (adelete 'vhdl-speedbar-shown-units-alist directory)
10164 (while ent-alist ; expand entities
10165 (vhdl-speedbar-goto-this-unit directory (car (car ent-alist)))
10166 (beginning-of-line)
10167 (let ((arch-alist (nth 1 (car ent-alist)))
10168 position)
10169 (when (looking-at "[0-9]+:\\s-*\\[")
10170 (goto-char (match-end 0))
10171 (setq position (point))
10172 (speedbar-do-function-pointer)
10173 (while arch-alist ; expand architectures
10174 (goto-char position)
10175 (when (re-search-forward
10176 (concat "[0-9]+:\\s-*\\(\\[\\|{.}\\s-+"
10177 (car arch-alist) "\\>\\)") nil t)
10178 (beginning-of-line)
10179 (when (looking-at "[0-9]+:\\s-*{")
10180 (goto-char (match-end 0))
10181 (speedbar-do-function-pointer)))
10182 (setq arch-alist (cdr arch-alist))))
10183 (setq ent-alist (cdr ent-alist))))))
10184
10185 (defun vhdl-speedbar-expand-entity (text token indent)
10186 "Expand/contract the entity under the cursor."
10187 (cond
10188 ((string-match "+" text) ; expand entity
10189 (let* ((ent-alist (if (vhdl-speedbar-project-p)
10190 (aget vhdl-project-entity-alist vhdl-project)
10191 (aget vhdl-entity-alist
10192 (abbreviate-file-name
10193 (file-name-as-directory
10194 (speedbar-line-path indent))))))
10195 (arch-alist (nth 2 (aget ent-alist token)))
10196 (conf-alist (nth 3 (aget ent-alist token)))
10197 (inst-alist (vhdl-get-instantiations token indent))
10198 arch-entry conf-entry inst-entry)
10199 (if (not (or arch-alist conf-alist inst-alist))
10200 (speedbar-change-expand-button-char ??)
10201 (speedbar-change-expand-button-char ?-)
10202 ;; add entity to `vhdl-speedbar-shown-units-alist'
10203 (let* ((directory (if (vhdl-speedbar-project-p)
10204 vhdl-project
10205 (abbreviate-file-name
10206 (file-name-as-directory (speedbar-line-path)))))
10207 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10208 (aput 'ent-alist (speedbar-line-text) nil)
10209 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10210 (speedbar-with-writable
10211 (save-excursion
10212 (end-of-line) (forward-char 1)
10213 ;; insert architectures
10214 (when arch-alist
10215 (vhdl-speedbar-make-title-line "Architectures:" (1+ indent)))
10216 (while arch-alist
10217 (setq arch-entry (car arch-alist))
10218 (speedbar-make-tag-line
10219 'curly ?+ 'vhdl-speedbar-expand-architecture
10220 (cons token (nth 0 arch-entry))
10221 (nth 0 arch-entry) 'vhdl-speedbar-find-file
10222 (cons (nth 1 arch-entry) (nth 2 arch-entry))
10223 'vhdl-speedbar-architecture-face (1+ indent))
10224 (setq arch-alist (cdr arch-alist)))
10225 ;; insert configurations
10226 (when conf-alist
10227 (vhdl-speedbar-make-title-line "Configurations:" (1+ indent)))
10228 (while conf-alist
10229 (setq conf-entry (car conf-alist))
10230 (speedbar-make-tag-line
10231 nil nil nil
10232 (cons token (nth 0 conf-entry))
10233 (nth 0 conf-entry) 'vhdl-speedbar-find-file
10234 (cons (nth 1 conf-entry) (nth 2 conf-entry))
10235 'vhdl-speedbar-configuration-face (1+ indent))
10236 (setq conf-alist (cdr conf-alist)))
10237 ;; insert instantiations
10238 (when inst-alist
10239 (vhdl-speedbar-make-title-line "Instantiations:" (1+ indent)))
10240 (while inst-alist
10241 (setq inst-entry (car inst-alist))
10242 (vhdl-speedbar-make-inst-line
10243 (nth 0 inst-entry) (nth 1 inst-entry)
10244 (nth 2 inst-entry) (nth 3 inst-entry)
10245 (nth 4 inst-entry) (nth 5 inst-entry) (1+ indent) 0)
10246 (setq inst-alist (cdr inst-alist)))))
10247 (setq speedbar-last-selected-file nil)
10248 (save-excursion (speedbar-stealthy-updates)))))
10249 ((string-match "-" text) ; contract entity
10250 (speedbar-change-expand-button-char ?+)
10251 ;; remove entity from `vhdl-speedbar-shown-units-alist'
10252 (let* ((directory (if (vhdl-speedbar-project-p)
10253 vhdl-project
10254 (abbreviate-file-name
10255 (file-name-as-directory (speedbar-line-path)))))
10256 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10257 (adelete 'ent-alist (speedbar-line-text))
10258 (if ent-alist
10259 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist)
10260 (adelete 'vhdl-speedbar-shown-units-alist directory)))
10261 (speedbar-delete-subblock indent))
10262 (t (error "No architectures, configurations, nor instantiations exist for this entity")))
10263 (speedbar-center-buffer-smartly))
10264
10265 (defun vhdl-speedbar-expand-architecture (text token indent)
10266 "Expand/contract the architecture under the cursor."
10267 (cond
10268 ((string-match "+" text) ; expand architecture
10269 (let ((hier-alist (vhdl-get-hierarchy (car token) (cdr token) 0 indent)))
10270 (if (not hier-alist)
10271 (speedbar-change-expand-button-char ??)
10272 (speedbar-change-expand-button-char ?-)
10273 ;; add architecture to `vhdl-speedbar-shown-units-alist'
10274 (let* ((path (speedbar-line-path))
10275 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10276 (ent-name (match-string 2 path))
10277 (directory (if (vhdl-speedbar-project-p)
10278 vhdl-project
10279 (abbreviate-file-name (match-string 1 path))))
10280 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10281 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10282 (aput 'ent-alist ent-name
10283 (list (cons (speedbar-line-text) arch-alist)))
10284 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10285 (speedbar-with-writable
10286 (save-excursion
10287 (end-of-line) (forward-char 1)
10288 ;; insert instance hierarchy
10289 (when hier-alist
10290 (vhdl-speedbar-make-title-line "Subcomponents:" (1+ indent)))
10291 (while hier-alist
10292 (let ((entry (car hier-alist)))
10293 (vhdl-speedbar-make-inst-line
10294 (nth 0 entry) (nth 1 entry)
10295 (nth 2 entry) (nth 3 entry)
10296 (nth 4 entry) (nth 5 entry)
10297 (1+ indent) (nth 6 entry))
10298 (setq hier-alist (cdr hier-alist))))))
10299 (setq speedbar-last-selected-file nil)
10300 (save-excursion (speedbar-stealthy-updates)))))
10301 ((string-match "-" text) ; contract architecture
10302 (speedbar-change-expand-button-char ?+)
10303 ;; remove architecture from `vhdl-speedbar-shown-units-alist'
10304 (let* ((path (speedbar-line-path))
10305 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10306 (ent-name (match-string 2 path))
10307 (directory (if (vhdl-speedbar-project-p)
10308 vhdl-project
10309 (abbreviate-file-name (match-string 1 path))))
10310 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10311 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10312 (aput 'ent-alist ent-name
10313 (list (delete (speedbar-line-text) arch-alist)))
10314 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10315 (speedbar-delete-subblock indent))
10316 (t (error "No component instantiations contained in this architecture")))
10317 (speedbar-center-buffer-smartly))
10318
10319 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10320 ;; Display help functions
10321
10322 (defun vhdl-speedbar-update-current-unit (&optional no-position)
10323 "Highlight all design units that are contained in the current file.
10324 NO-POSITION non-nil means do not re-position cursor."
10325 (let ((last-frame (selected-frame))
10326 file-name position)
10327 ;; get current file name
10328 (select-frame speedbar-attached-frame)
10329 (setq file-name (abbreviate-file-name (or (buffer-file-name) "")))
10330 (unless (equal file-name speedbar-last-selected-file)
10331 (select-frame speedbar-frame)
10332 (set-buffer speedbar-buffer)
10333 (speedbar-with-writable
10334 (save-excursion
10335 ;; unhighlight last units
10336 (let* ((file-entry
10337 (aget vhdl-file-alist speedbar-last-selected-file)))
10338 (vhdl-speedbar-update-units
10339 "\\[.\\]" (nth 0 file-entry)
10340 speedbar-last-selected-file 'vhdl-speedbar-entity-face)
10341 (vhdl-speedbar-update-units
10342 "{.}" (nth 1 file-entry)
10343 speedbar-last-selected-file 'vhdl-speedbar-architecture-face)
10344 (vhdl-speedbar-update-units
10345 ">" (nth 2 file-entry)
10346 speedbar-last-selected-file 'vhdl-speedbar-configuration-face)
10347 (vhdl-speedbar-update-units
10348 ">" (nth 3 file-entry)
10349 speedbar-last-selected-file 'vhdl-speedbar-package-face)
10350 (vhdl-speedbar-update-units
10351 ">" (nth 4 file-entry)
10352 speedbar-last-selected-file 'vhdl-speedbar-instantiation-face))
10353 ;; highlight current units
10354 (let* ((file-entry (aget vhdl-file-alist file-name)))
10355 (vhdl-speedbar-update-units
10356 "\\[.\\]" (nth 0 file-entry)
10357 file-name 'vhdl-speedbar-entity-selected-face)
10358 (setq position (or position (point-marker)))
10359 (vhdl-speedbar-update-units
10360 "{.}" (nth 1 file-entry)
10361 file-name 'vhdl-speedbar-architecture-selected-face)
10362 (setq position (or position (point-marker)))
10363 (vhdl-speedbar-update-units
10364 ">" (nth 2 file-entry)
10365 file-name 'vhdl-speedbar-configuration-selected-face)
10366 (setq position (or position (point-marker)))
10367 (vhdl-speedbar-update-units
10368 ">" (nth 3 file-entry)
10369 file-name 'vhdl-speedbar-package-selected-face)
10370 (setq position (or position (point-marker)))
10371 (vhdl-speedbar-update-units
10372 ">" (nth 4 file-entry)
10373 file-name 'vhdl-speedbar-instantiation-selected-face))))
10374 (setq position (or position (point-marker)))
10375 ;; move speedbar so the first highlighted unit is visible
10376 (when (and position (not no-position))
10377 (goto-char position)
10378 (speedbar-center-buffer-smartly)
10379 (speedbar-position-cursor-on-line))
10380 (setq speedbar-last-selected-file file-name))
10381 (select-frame last-frame)
10382 t))
10383
10384 (defun vhdl-speedbar-update-units (text unit-list file-name face)
10385 "Help function to highlight design units."
10386 (let (position)
10387 (while unit-list
10388 (goto-char (point-min))
10389 (while (re-search-forward
10390 (concat text " \\(" (car unit-list) "\\)\\>") nil t)
10391 (when (equal file-name (car (get-text-property
10392 (match-beginning 1) 'speedbar-token)))
10393 (setq position (or position (point-marker)))
10394 (put-text-property (match-beginning 1) (match-end 1) 'face face)))
10395 (setq unit-list (cdr unit-list)))
10396 (when position (goto-char position))))
10397
10398 (defun vhdl-speedbar-make-inst-line (inst-name inst-file-marker
10399 ent-name ent-file-marker
10400 arch-name arch-file-marker
10401 depth offset)
10402 "Insert instantiation entry."
10403 (let ((start (point)))
10404 (insert (int-to-string depth) ":")
10405 (put-text-property start (point) 'invisible t)
10406 (setq start (point))
10407 (insert-char ? (+ depth (* offset vhdl-speedbar-hierarchy-indent)))
10408 (insert "> ")
10409 (put-text-property start (point) 'invisible nil)
10410 (setq start (point))
10411 (insert inst-name)
10412 (speedbar-make-button
10413 start (point) 'vhdl-speedbar-instantiation-face 'speedbar-highlight-face
10414 'vhdl-speedbar-find-file inst-file-marker)
10415 (setq start (point))
10416 (insert ": ")
10417 (put-text-property start (point) 'invisible nil)
10418 (setq start (point))
10419 (insert ent-name)
10420 (speedbar-make-button
10421 start (point) 'vhdl-speedbar-entity-face 'speedbar-highlight-face
10422 'vhdl-speedbar-find-file ent-file-marker)
10423 (setq start (point))
10424 (when arch-name
10425 (insert " (")
10426 (put-text-property start (point) 'invisible nil)
10427 (setq start (point))
10428 (insert arch-name)
10429 (speedbar-make-button
10430 start (point) 'vhdl-speedbar-architecture-face 'speedbar-highlight-face
10431 'vhdl-speedbar-find-file arch-file-marker)
10432 (setq start (point))
10433 (insert ")"))
10434 (put-text-property start (point) 'invisible nil)
10435 (insert-char ?\n 1)
10436 (put-text-property (1- (point)) (point) 'invisible nil)))
10437
10438 (defun vhdl-speedbar-make-pack-line (pack-name pack-file-marker
10439 body-file-marker depth)
10440 "Insert package entry."
10441 (let ((start (point)))
10442 (insert (int-to-string depth) ":")
10443 (put-text-property start (point) 'invisible t)
10444 (setq start (point))
10445 (insert-char ? depth)
10446 (insert "> ")
10447 (put-text-property start (point) 'invisible nil)
10448 (setq start (point))
10449 (insert pack-name)
10450 (speedbar-make-button
10451 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10452 'vhdl-speedbar-find-file pack-file-marker)
10453 (when (car body-file-marker)
10454 (setq start (point))
10455 (insert " (")
10456 (put-text-property start (point) 'invisible nil)
10457 (setq start (point))
10458 (insert "body")
10459 (speedbar-make-button
10460 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10461 'vhdl-speedbar-find-file body-file-marker)
10462 (setq start (point))
10463 (insert ")")
10464 (put-text-property start (point) 'invisible nil))
10465 (insert-char ?\n 1)
10466 (put-text-property (1- (point)) (point) 'invisible nil)))
10467
10468 (defun vhdl-speedbar-make-title-line (text depth)
10469 "Insert design unit title entry."
10470 (let ((start (point)))
10471 (insert (int-to-string depth) ":")
10472 (put-text-property start (point) 'invisible t)
10473 (setq start (point))
10474 (insert-char ? depth)
10475 (put-text-property start (point) 'invisible nil)
10476 (setq start (point))
10477 (insert text)
10478 (speedbar-make-button start (point) nil nil nil nil)
10479 (insert-char ?\n 1)
10480 (put-text-property start (point) 'invisible nil)))
10481
10482 (defun vhdl-speedbar-insert-dirs (files level)
10483 "Insert subdirectories."
10484 (let ((dirs (car files)))
10485 (while dirs
10486 (speedbar-make-tag-line 'angle ?+ 'vhdl-speedbar-dired (car dirs)
10487 (car dirs) 'speedbar-dir-follow nil
10488 'speedbar-directory-face level)
10489 (setq dirs (cdr dirs)))))
10490
10491 (defun vhdl-speedbar-dired (text token indent)
10492 "Speedbar click handler for directory expand button in hierarchy mode."
10493 (cond ((string-match "+" text) ; we have to expand this dir
10494 (setq speedbar-shown-directories
10495 (cons (expand-file-name
10496 (concat (speedbar-line-path indent) token "/"))
10497 speedbar-shown-directories))
10498 (speedbar-change-expand-button-char ?-)
10499 (speedbar-reset-scanners)
10500 (speedbar-with-writable
10501 (save-excursion
10502 (end-of-line) (forward-char 1)
10503 (vhdl-speedbar-insert-dirs
10504 (speedbar-file-lists
10505 (concat (speedbar-line-path indent) token "/"))
10506 (1+ indent))
10507 (speedbar-reset-scanners)
10508 (vhdl-speedbar-insert-dir-hierarchy
10509 (abbreviate-file-name
10510 (concat (speedbar-line-path indent) token "/"))
10511 (1+ indent) speedbar-power-click)))
10512 (setq speedbar-last-selected-file nil)
10513 (save-excursion (speedbar-stealthy-updates)))
10514 ((string-match "-" text) ; we have to contract this node
10515 (speedbar-reset-scanners)
10516 (let ((oldl speedbar-shown-directories)
10517 (newl nil)
10518 (td (expand-file-name
10519 (concat (speedbar-line-path indent) token))))
10520 (while oldl
10521 (if (not (string-match (concat "^" (regexp-quote td)) (car oldl)))
10522 (setq newl (cons (car oldl) newl)))
10523 (setq oldl (cdr oldl)))
10524 (setq speedbar-shown-directories (nreverse newl)))
10525 (speedbar-change-expand-button-char ?+)
10526 (speedbar-delete-subblock indent))
10527 (t (error "Ooops... not sure what to do")))
10528 (speedbar-center-buffer-smartly))
10529
10530 (defun vhdl-speedbar-item-info ()
10531 "Derive and display information about this line item."
10532 (save-excursion
10533 (beginning-of-line)
10534 ;; skip invisible number info
10535 (when (looking-at "[0-9]+:") (goto-char (match-end 0)))
10536 (when (looking-at "p:")
10537 (message "Project \"%s\""
10538 (nth 0 (aget vhdl-project-alist vhdl-project))))
10539 (cond
10540 ;; directory entry
10541 ((looking-at "\\s-*<[-+?]> ") (speedbar-files-item-info))
10542 ;; design unit entry
10543 ((looking-at "\\s-*\\([[{][-+?][]}]\\|>\\) ")
10544 (goto-char (match-end 0))
10545 (let ((face (get-text-property (point) 'face)))
10546 (message
10547 "%s \"%s\" in \"%s\""
10548 ;; design unit kind
10549 (cond ((or (eq face 'vhdl-speedbar-entity-face)
10550 (eq face 'vhdl-speedbar-entity-selected-face))
10551 "Entity")
10552 ((or (eq face 'vhdl-speedbar-architecture-face)
10553 (eq face 'vhdl-speedbar-architecture-selected-face))
10554 "Architecture")
10555 ((or (eq face 'vhdl-speedbar-configuration-face)
10556 (eq face 'vhdl-speedbar-configuration-selected-face))
10557 "Configuration")
10558 ((or (eq face 'vhdl-speedbar-package-face)
10559 (eq face 'vhdl-speedbar-package-selected-face))
10560 "Package")
10561 ((or (eq face 'vhdl-speedbar-instantiation-face)
10562 (eq face 'vhdl-speedbar-instantiation-selected-face))
10563 "Instantiation")
10564 (t ""))
10565 ;; design unit name
10566 (buffer-substring-no-properties
10567 (point) (progn (looking-at"\\(\\w\\|_\\)+") (match-end 0)))
10568 ;; file name
10569 (abbreviate-file-name
10570 (or (car (get-text-property (point) 'speedbar-token)) "?"))))))))
10571
10572 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10573 ;; Help functions
10574
10575 (defun vhdl-get-subdirs (directory)
10576 "Recursively get subdirectories of DIRECTORY."
10577 (let ((dir-list (list (file-name-as-directory directory)))
10578 subdir-list file-list)
10579 (setq file-list (vhdl-directory-files directory t "\\w.*"))
10580 (while file-list
10581 (when (file-directory-p (car file-list))
10582 (setq dir-list (append dir-list (vhdl-get-subdirs (car file-list)))))
10583 (setq file-list (cdr file-list)))
10584 dir-list))
10585
10586 (defun vhdl-resolve-paths (path-list)
10587 "Resolve environment variables and path wildcards in PATH-LIST."
10588 (let (path-list-1 path-list-2 path-list-3 path-beg path-end dir)
10589 ;; resolve environment variables
10590 (while path-list
10591 (setq dir (car path-list))
10592 (while (string-match "\\(.*\\)${?\\(\\(\\w\\|_\\)+\\)}?\\(.*\\)" dir)
10593 (setq dir (concat (match-string 1 dir) (getenv (match-string 2 dir))
10594 (match-string 4 dir))))
10595 (setq path-list-1 (cons dir path-list-1))
10596 (setq path-list (cdr path-list)))
10597 ;; eliminate non-existent directories
10598 (while path-list-1
10599 (setq dir (car path-list-1))
10600 (string-match "\\(-r \\)?\\(\\([^?*]*/\\)*\\)" dir)
10601 (if (file-directory-p (match-string 2 dir))
10602 (setq path-list-2 (cons dir path-list-2))
10603 (message "No such directory: \"%s\"" (match-string 2 dir)))
10604 (setq path-list-1 (cdr path-list-1)))
10605 ;; resolve path wildcards
10606 (while path-list-2
10607 (setq dir (car path-list-2))
10608 (if (string-match
10609 "\\(-r \\)?\\(\\([^?*]*/\\)*\\)\\([^/]*[?*][^/]*\\)\\(/.*\\)" dir)
10610 (progn
10611 (setq path-beg (match-string 1 dir)
10612 path-end (match-string 5 dir))
10613 (setq path-list-2
10614 (append
10615 (mapcar
10616 (function
10617 (lambda (var) (concat path-beg var path-end)))
10618 (let ((all-list (vhdl-directory-files
10619 (match-string 2 dir) t
10620 (concat "\\<" (wildcard-to-regexp
10621 (match-string 4 dir)))))
10622 dir-list)
10623 (while all-list
10624 (when (file-directory-p (car all-list))
10625 (setq dir-list (cons (car all-list) dir-list)))
10626 (setq all-list (cdr all-list)))
10627 dir-list))
10628 (cdr path-list-2))))
10629 (string-match "\\(-r \\)?\\(.*\\)/.*" dir)
10630 (when (file-directory-p (match-string 2 dir))
10631 (setq path-list-3 (cons dir path-list-3)))
10632 (setq path-list-2 (cdr path-list-2))))
10633 path-list-3))
10634
10635 (defun vhdl-aappend (alist-symbol key value)
10636 "Append a key-value pair to an alist.
10637 Similar to `aput' but moves the key-value pair to the tail of the alist."
10638 (let ((elem (aelement key value))
10639 (alist (adelete alist-symbol key)))
10640 (set alist-symbol (append alist elem))))
10641
10642 (defun vhdl-speedbar-goto-this-unit (directory unit)
10643 "If UNIT is displayed in DIRECTORY, goto this line and return t, else nil."
10644 (let ((dest (point)))
10645 (if (and (if (vhdl-speedbar-project-p)
10646 (progn (goto-char (point-min)) t)
10647 (speedbar-goto-this-file directory))
10648 (re-search-forward (concat "[]}] " unit "\\>") nil t))
10649 (progn (speedbar-position-cursor-on-line)
10650 t)
10651 (goto-char dest)
10652 nil)))
10653
10654 (defun vhdl-speedbar-find-file (text token indent)
10655 "When user clicks on TEXT, load file with name and position in TOKEN."
10656 (if (not (car token))
10657 (error "Design unit does not exist")
10658 (speedbar-find-file-in-frame (car token))
10659 (goto-line (cdr token))
10660 (recenter)
10661 (vhdl-speedbar-update-current-unit t)
10662 (speedbar-set-timer speedbar-update-speed)
10663 (speedbar-maybee-jump-to-attached-frame)))
10664
10665 (defun vhdl-speedbar-toggle-hierarchy ()
10666 "Toggle between hierarchy and file browsing mode."
10667 (interactive)
10668 (if (not (boundp 'speedbar-mode-functions-list))
10669 (error "WARNING: Install included `speedbar.el' patch first")
10670 (if (equal speedbar-initial-expansion-list-name "vhdl hierarchy")
10671 (speedbar-change-initial-expansion-list "files")
10672 (speedbar-change-initial-expansion-list "vhdl hierarchy"))))
10673
10674 (defun vhdl-speedbar-port-copy ()
10675 "Copy the port of the entity under the cursor."
10676 (interactive)
10677 (beginning-of-line)
10678 (if (re-search-forward "\\([0-9]\\)+:\\s-*\\[[-+?]\\] \\(\\(\\w\\|\\s_\\)+\\)"
10679 (save-excursion (end-of-line) (point)) t)
10680 (condition-case ()
10681 (let* ((indent (string-to-number (match-string 1)))
10682 (ent-name (match-string 2))
10683 (ent-alist (if (vhdl-speedbar-project-p)
10684 (aget vhdl-project-entity-alist vhdl-project)
10685 (aget vhdl-entity-alist
10686 (abbreviate-file-name
10687 (file-name-as-directory
10688 (speedbar-line-path indent))))))
10689 (ent-entry (aget ent-alist ent-name))
10690 (file-name (nth 0 ent-entry))
10691 opened)
10692 ;; open file
10693 (if (find-buffer-visiting file-name)
10694 (set-buffer (file-name-nondirectory file-name))
10695 (set-buffer (find-file-noselect file-name nil t))
10696 (modify-syntax-entry ?\- ". 12" (syntax-table))
10697 (modify-syntax-entry ?\n ">" (syntax-table))
10698 (modify-syntax-entry ?\^M ">" (syntax-table))
10699 (setq opened t))
10700 ;; scan port
10701 (goto-line (nth 1 ent-entry))
10702 (end-of-line)
10703 (vhdl-port-copy)
10704 ;; close file
10705 (when opened (kill-buffer (current-buffer))))
10706 (error (error "Port not scanned successfully")))
10707 (error "No entity on current line")))
10708
10709 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10710 ;; Fontification
10711
10712 (defface vhdl-speedbar-entity-face
10713 '((((class color) (background light)) (:foreground "ForestGreen"))
10714 (((class color) (background dark)) (:foreground "PaleGreen")))
10715 "Face used for displaying entity names."
10716 :group 'speedbar-faces)
10717
10718 (defface vhdl-speedbar-architecture-face
10719 '((((class color) (background light)) (:foreground "Blue"))
10720 (((class color) (background dark)) (:foreground "LightSkyBlue")))
10721 "Face used for displaying architecture names."
10722 :group 'speedbar-faces)
10723
10724 (defface vhdl-speedbar-configuration-face
10725 '((((class color) (background light)) (:foreground "DarkGoldenrod"))
10726 (((class color) (background dark)) (:foreground "Salmon")))
10727 "Face used for displaying configuration names."
10728 :group 'speedbar-faces)
10729
10730 (defface vhdl-speedbar-package-face
10731 '((((class color) (background light)) (:foreground "Grey50"))
10732 (((class color) (background dark)) (:foreground "Grey80")))
10733 "Face used for displaying package names."
10734 :group 'speedbar-faces)
10735
10736 (defface vhdl-speedbar-instantiation-face
10737 '((((class color) (background light)) (:foreground "Brown"))
10738 (((class color) (background dark)) (:foreground "Yellow")))
10739 "Face used for displaying instantiation names."
10740 :group 'speedbar-faces)
10741
10742 (defface vhdl-speedbar-entity-selected-face
10743 '((((class color) (background light)) (:foreground "ForestGreen" :underline t))
10744 (((class color) (background dark)) (:foreground "PaleGreen" :underline t)))
10745 "Face used for displaying entity names."
10746 :group 'speedbar-faces)
10747
10748 (defface vhdl-speedbar-architecture-selected-face
10749 '((((class color) (background light)) (:foreground "Blue" :underline t))
10750 (((class color) (background dark)) (:foreground "LightSkyBlue" :underline t)))
10751 "Face used for displaying architecture names."
10752 :group 'speedbar-faces)
10753
10754 (defface vhdl-speedbar-configuration-selected-face
10755 '((((class color) (background light)) (:foreground "DarkGoldenrod" :underline t))
10756 (((class color) (background dark)) (:foreground "Salmon" :underline t)))
10757 "Face used for displaying configuration names."
10758 :group 'speedbar-faces)
10759
10760 (defface vhdl-speedbar-package-selected-face
10761 '((((class color) (background light)) (:foreground "Grey50" :underline t))
10762 (((class color) (background dark)) (:foreground "Grey80" :underline t)))
10763 "Face used for displaying package names."
10764 :group 'speedbar-faces)
10765
10766 (defface vhdl-speedbar-instantiation-selected-face
10767 '((((class color) (background light)) (:foreground "Brown" :underline t))
10768 (((class color) (background dark)) (:foreground "Yellow" :underline t)))
10769 "Face used for displaying instantiation names."
10770 :group 'speedbar-faces)
10771
10772
10773 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10774 ;;; Bug reports
10775 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10776 ;; (using `reporter.el')
10777
10778 (defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
10779 "Address for VHDL Mode bug reports.")
10780
10781 (defun vhdl-version ()
10782 "Echo the current version of VHDL Mode in the minibuffer."
10783 (interactive)
10784 (message "Using VHDL Mode version %s" vhdl-version)
10785 (vhdl-keep-region-active))
10786
10787 ;; get reporter-submit-bug-report when byte-compiling
10788 (eval-when-compile
10789 (require 'reporter))
10790
10791 (defun vhdl-submit-bug-report ()
10792 "Submit via mail a bug report on VHDL Mode."
10793 (interactive)
10794 ;; load in reporter
10795 (and
10796 (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
10797 (require 'reporter)
10798 (reporter-submit-bug-report
10799 vhdl-mode-help-address
10800 (concat "VHDL Mode " vhdl-version)
10801 (list
10802 ;; report all important variables
10803 'vhdl-offsets-alist
10804 'vhdl-comment-only-line-offset
10805 'tab-width
10806 'vhdl-electric-mode
10807 'vhdl-stutter-mode
10808 'vhdl-indent-tabs-mode
10809 'vhdl-project-alist
10810 'vhdl-project
10811 'vhdl-compiler-alist
10812 'vhdl-compiler
10813 'vhdl-compiler-options
10814 'vhdl-standard
10815 'vhdl-basic-offset
10816 'vhdl-upper-case-keywords
10817 'vhdl-upper-case-types
10818 'vhdl-upper-case-attributes
10819 'vhdl-upper-case-enum-values
10820 'vhdl-upper-case-constants
10821 'vhdl-electric-keywords
10822 'vhdl-optional-labels
10823 'vhdl-insert-empty-lines
10824 'vhdl-argument-list-indent
10825 'vhdl-association-list-with-formals
10826 'vhdl-conditions-in-parenthesis
10827 'vhdl-zero-string
10828 'vhdl-one-string
10829 'vhdl-file-header
10830 'vhdl-file-footer
10831 'vhdl-company-name
10832 'vhdl-platform-spec
10833 'vhdl-date-format
10834 'vhdl-modify-date-prefix-string
10835 'vhdl-modify-date-on-saving
10836 'vhdl-reset-kind
10837 'vhdl-reset-active-high
10838 'vhdl-clock-rising-edge
10839 'vhdl-clock-edge-condition
10840 'vhdl-clock-name
10841 'vhdl-reset-name
10842 'vhdl-model-alist
10843 'vhdl-include-port-comments
10844 'vhdl-include-direction-comments
10845 'vhdl-actual-port-name
10846 'vhdl-instance-name
10847 'vhdl-testbench-entity-name
10848 'vhdl-testbench-architecture-name
10849 'vhdl-testbench-dut-name
10850 'vhdl-testbench-entity-header
10851 'vhdl-testbench-architecture-header
10852 'vhdl-testbench-declarations
10853 'vhdl-testbench-statements
10854 'vhdl-testbench-initialize-signals
10855 'vhdl-testbench-create-files
10856 'vhdl-self-insert-comments
10857 'vhdl-prompt-for-comments
10858 'vhdl-inline-comment-column
10859 'vhdl-end-comment-column
10860 'vhdl-auto-align
10861 'vhdl-align-groups
10862 'vhdl-highlight-keywords
10863 'vhdl-highlight-names
10864 'vhdl-highlight-special-words
10865 'vhdl-highlight-forbidden-words
10866 'vhdl-highlight-verilog-keywords
10867 'vhdl-highlight-translate-off
10868 'vhdl-highlight-case-sensitive
10869 'vhdl-special-syntax-alist
10870 'vhdl-forbidden-words
10871 'vhdl-forbidden-syntax
10872 'vhdl-speedbar
10873 'vhdl-speedbar-show-hierarchy
10874 'vhdl-speedbar-hierarchy-indent
10875 'vhdl-index-menu
10876 'vhdl-source-file-menu
10877 'vhdl-hideshow-menu
10878 'vhdl-hide-all-init
10879 'vhdl-print-two-column
10880 'vhdl-print-customize-faces
10881 'vhdl-intelligent-tab
10882 'vhdl-word-completion-case-sensitive
10883 'vhdl-word-completion-in-minibuffer
10884 'vhdl-underscore-is-part-of-word
10885 'vhdl-mode-hook
10886 'vhdl-startup-warnings)
10887 (function
10888 (lambda ()
10889 (insert
10890 (if vhdl-special-indent-hook
10891 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
10892 "vhdl-special-indent-hook is set to '"
10893 (format "%s" vhdl-special-indent-hook)
10894 ".\nPerhaps this is your problem?\n"
10895 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
10896 "\n"))))
10897 nil
10898 "Dear VHDL Mode maintainers,")))
10899
10900
10901 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10902
10903 (provide 'vhdl-mode)
10904
10905 ;;; vhdl-mode.el ends here