Restore iso-2022-7bit
[bpt/emacs.git] / lisp / progmodes / vhdl-mode.el
CommitLineData
d2ddb974
KH
1;;; vhdl-mode.el --- major mode for editing VHDL code
2
5eabfe72 3;; Copyright (C) 1992,93,94,95,96,97,98,99 Free Software Foundation, Inc.
d2ddb974 4
5eabfe72 5;; Authors: Reto Zimmermann <mailto:Reto.Zimmermann@iaeth.ch>
d2ddb974 6;; <http://www.iis.ee.ethz.ch/~zimmi/>
5eabfe72 7;; Rodney J. Whitby <mailto:rwhitby@geocities.com>
d2ddb974 8;; <http://www.geocities.com/SiliconValley/Park/8287/>
5eabfe72
KH
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
d2ddb974
KH
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
5eabfe72 31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 32;;; Commentary:
5eabfe72 33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
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
5eabfe72 42;; - Insertion of user-specified models
d2ddb974 43;; - Word completion (dynamic abbreviations)
5eabfe72
KH
44;; - Comprehensive menu
45;; - File browser (using Speedbar or index/sources menu)
46;; - Design hierarchy browser (using Speedbar)
d2ddb974
KH
47;; - Source file compilation (syntax analysis)
48;; - Postscript printing with fontification
49;; - Lower and upper case keywords
5eabfe72
KH
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 59;; Usage
5eabfe72 60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 61
5eabfe72 62;; see below (comment in `vhdl-mode' function) or type `C-c C-h' in Emacs.
d2ddb974 63
5eabfe72 64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 65;; Emacs Versions
5eabfe72 66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 67
5eabfe72
KH
68;; supported: Emacs 20.X (Unix and Windows NT/95), XEmacs 20.X
69;; tested on: Emacs 20.3, XEmacs 20.4 (marginally)
d2ddb974 70
5eabfe72 71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 72;; Acknowledgements
5eabfe72 73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
74
75;; Electrification ideas by Bob Pack <rlpst@cislabs.pitt.edu>
5eabfe72 76;; and Steve Grout.
d2ddb974 77
5eabfe72
KH
78;; Fontification approach suggested by Ken Wood <ken@eda.com.au>.
79;; Ideas about alignment from John Wiegley <johnw@borland.com>.
d2ddb974
KH
80
81;; Many thanks to all the users who sent me bug reports and enhancement
5eabfe72
KH
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
d2ddb974
KH
92
93;;; Code:
94
5eabfe72
KH
95;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96;;; Variables
97;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 98
5eabfe72
KH
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
d2ddb974
KH
111
112(defgroup vhdl nil
113 "Customizations for VHDL Mode."
114 :prefix "vhdl-"
42dfe0ad 115 :group 'languages
5eabfe72
KH
116 :version "20.4" ; comment out for XEmacs
117 )
d2ddb974
KH
118
119(defgroup vhdl-mode nil
120 "Customizations for modes."
121 :group 'vhdl)
122
123(defcustom vhdl-electric-mode t
5eabfe72
KH
124 "*Non-nil enables electrification (automatic template generation).
125If nil, template generators can still be invoked through key bindings and
126menu. Is indicated in the modeline by `/e' after the mode name and can be
127toggled by `\\[vhdl-electric-mode]'."
d2ddb974
KH
128 :type 'boolean
129 :group 'vhdl-mode)
130
131(defcustom vhdl-stutter-mode t
5eabfe72
KH
132 "*Non-nil enables stuttering.
133Is indicated in the modeline by `/s' after the mode name and can be toggled
134by `\\[vhdl-stutter-mode]'."
d2ddb974
KH
135 :type 'boolean
136 :group 'vhdl-mode)
137
5eabfe72
KH
138(defcustom vhdl-indent-tabs-mode nil
139 "*Non-nil means indentation can insert tabs.
d2ddb974
KH
140Overrides local variable `indent-tabs-mode'."
141 :type 'boolean
142 :group 'vhdl-mode)
143
144
5eabfe72
KH
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
168Project name and description are used to insert into the file header (see
169variable `vhdl-file-header').
170
171Path and file name can contain wildcards `*' and `?'. Environment variables
172\(e.g. \"$EXAMPLE2\") are resolved.
173
174The hierarchy browser shows the hierarchy of the design units found in
175`Sources'. If no directories or files are specified, the current directory is
176shown.
177
178NOTE: 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.
193Select a project name from the ones defined in variable `vhdl-project-alist'.
194Is used to determine the project title and description to be inserted in file
195headers and the source files/directories to be scanned in the hierarchy
196browser. 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
d2ddb974
KH
207(defgroup vhdl-compile nil
208 "Customizations for compilation."
209 :group 'vhdl)
210
5eabfe72
KH
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.
251Each list entry specifies the following items for a compiler:
252Compiler:
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 '/')
258Error 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
262File Message:
263 Regexp : regular expression to match a file name message
264 File Subexp Index: index of subexpression that matches the file name
265
266See also variable `vhdl-compiler-options' to add options to the compile
267command.
268
269Some compilers do not include the file name in the error message, but print
270out a file name message in advance. In this case, set \"File Subexp Index\"
271to 0 and fill out the \"File Message\" entries.
272
273A compiler is selected for syntax analysis (`\\[vhdl-compile]') by
274assigning its name to variable `vhdl-compiler'.
275
276NOTE: 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.
297Select 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)))
d2ddb974
KH
304 :group 'vhdl-compile)
305
306(defcustom vhdl-compiler-options ""
5eabfe72 307 "*Options to be added to the compile command."
d2ddb974
KH
308 :type 'string
309 :group 'vhdl-compile)
310
311
312(defgroup vhdl-style nil
313 "Customizations for code styles."
314 :group 'vhdl)
315
5eabfe72
KH
316(defcustom vhdl-standard '(87 nil)
317 "*VHDL standards used.
318Basic standard:
319 VHDL'87 : IEEE Std 1076-1987
320 VHDL'93 : IEEE Std 1076-1993
321Additional standards:
322 VHDL-AMS : IEEE Std 1076.1 (analog-mixed-signal)
323 Math Packages: IEEE Std 1076.2 (`math_real', `math_complex')
324
325NOTE: 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
d2ddb974
KH
344 "*Amount of basic offset used for indentation.
345This value is used by + and - symbols in `vhdl-offsets-alist'."
346 :type 'integer
347 :group 'vhdl-style)
348
d2ddb974 349(defcustom vhdl-upper-case-keywords nil
5eabfe72
KH
350 "*Non-nil means convert keywords to upper case.
351This is done when typed or expanded or by the fix case functions."
d2ddb974 352 :type 'boolean
5eabfe72
KH
353 :set (lambda (variable value)
354 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
355 :group 'vhdl-style)
d2ddb974
KH
356
357(defcustom vhdl-upper-case-types nil
5eabfe72
KH
358 "*Non-nil means convert standardized types to upper case.
359This is done when expanded or by the fix case functions."
d2ddb974 360 :type 'boolean
5eabfe72
KH
361 :set (lambda (variable value)
362 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
363 :group 'vhdl-style)
d2ddb974
KH
364
365(defcustom vhdl-upper-case-attributes nil
5eabfe72
KH
366 "*Non-nil means convert standardized attributes to upper case.
367This is done when expanded or by the fix case functions."
d2ddb974 368 :type 'boolean
5eabfe72
KH
369 :set (lambda (variable value)
370 (vhdl-custom-set variable value 'vhdl-abbrev-list-init))
371 :group 'vhdl-style)
d2ddb974
KH
372
373(defcustom vhdl-upper-case-enum-values nil
5eabfe72
KH
374 "*Non-nil means convert standardized enumeration values to upper case.
375This is done when expanded or by the fix case functions."
d2ddb974 376 :type 'boolean
5eabfe72
KH
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.
383This 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)
d2ddb974
KH
388
389
390(defgroup vhdl-electric nil
5eabfe72 391 "Customizations for electrification."
d2ddb974
KH
392 :group 'vhdl)
393
5eabfe72
KH
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.
406Template 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))
d2ddb974
KH
413 :group 'vhdl-electric)
414
5eabfe72
KH
415(defcustom vhdl-insert-empty-lines 'unit
416 "*Specifies whether to insert empty lines in some templates.
417This 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
422Replaces 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.
430That is, argument, association, and port lists start on the same line as the
431opening parenthesis and subsequent lines are indented accordingly.
432Otherwise, lists start on a new line and are indented as normal code."
d2ddb974
KH
433 :type 'boolean
434 :group 'vhdl-electric)
435
5eabfe72
KH
436(defcustom vhdl-association-list-with-formals t
437 "*Non-nil means write association lists with formal parameters.
438In templates, you are prompted for formal and actual parameters.
439If nil, only a list of actual parameters is entered."
d2ddb974
KH
440 :type 'boolean
441 :group 'vhdl-electric)
442
443(defcustom vhdl-conditions-in-parenthesis nil
5eabfe72 444 "*Non-nil means place parenthesis around condition expressions."
d2ddb974
KH
445 :type 'boolean
446 :group 'vhdl-electric)
447
5eabfe72
KH
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."
d2ddb974
KH
461 :group 'vhdl-electric)
462
5eabfe72
KH
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.
483If the string specifies an existing file name, the contents of the file is
484inserted, otherwise the string itself is inserted as file header.
485Type `C-j' for newlines.
d2ddb974
KH
486If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
487if the header needs to be version controlled.
488
489The following keywords for template generation are supported:
490 <filename> : replaced by the name of the buffer
5eabfe72
KH
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'
d2ddb974 495 <date> : replaced by the current date
5eabfe72
KH
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)
d2ddb974
KH
500 <cursor> : final cursor position
501
5eabfe72
KH
502The (multi-line) project description <projectdesc> can be used as a project
503dependent 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.
509If the string specifies an existing file name, the contents of the file is
510inserted, otherwise the string itself is inserted as file footer (i.e. at
511the end of the file).
512Type `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.
523The platform specification should contain names and versions of the
524simulation 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.
530This string is passed as argument to the command `format-time-string'.
531For 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)
d2ddb974 535
5eabfe72 536(defcustom vhdl-modify-date-prefix-string "-- Last update: "
d2ddb974 537 "*Prefix string of modification date in VHDL file header.
5eabfe72
KH
538If actualization of the modification date is called (menu,
539`\\[vhdl-template-modify]'), this string is searched and the rest
540of the line replaced by the current date."
d2ddb974 541 :type 'string
5eabfe72
KH
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.
546Calls function `\\[vhdl-template-modify]').
547
548NOTE: 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."
d2ddb974
KH
556 :group 'vhdl-electric)
557
5eabfe72
KH
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.
0ff9b955 567nil means active low."
5eabfe72
KH
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.
0ff9b955 573nil means falling edge."
5eabfe72
KH
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."
d2ddb974 587 :type 'string
5eabfe72 588 :group 'vhdl-sequential-process)
d2ddb974 589
5eabfe72
KH
590(defcustom vhdl-reset-name ""
591 "*Name of reset signal to use in templates."
d2ddb974 592 :type 'string
5eabfe72
KH
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>)
603begin -- 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
a1506d29 608
5eabfe72
KH
609 end if;
610 end if;
611end process <label>;"
612 "e" ""))
613 "*List of user models.
614VHDL models (templates) can be specified by the user in this list. They can be
615invoked from the menu, through key bindings (`C-c C-m ...'), or by keyword
616electrification (i.e. overriding existing or creating new keywords, see
617variable `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
624The models can contain prompts to be queried. A prompt is of the form \"<...>\".
625A prompt that appears several times is queried once and replaced throughout
626the 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
631If the string specifies an existing file name, the contents of the file is
632inserted, otherwise the string itself is inserted.
633The code within the models should be correctly indented.
634Type `C-j' for newlines.
635
636NOTE: 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
668FROM REGEXP is a regular expression matching the formal port name:
669 `.*' matches the entire name
670 `\\(...\\)' matches a substring
671TO 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 `\\(...\\)'
674Examples:
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.
683In a component instantiation, an actual port name can be obtained by
684modifying 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.
693The instance name can be obtained by modifying the name of the component to be
694instantiated (e.g. attaching or stripping off a substring).
695If 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.
704The entity name of a test bench can be obtained by modifying the name of
705the 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.
714The test bench architecture name can be obtained by modifying the name of
715the component to be tested (e.g. attaching or stripping off a substring).
716If 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.
725The design-under-test instance name (i.e. the component instantiated in the
726test bench) can be obtained by modifying the component name (e.g. attaching
727or 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.
735If the string specifies an existing file name, the contents of the file is
736inserted, otherwise the string itself is inserted at the beginning of the test
737bench entity template.
738Type `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.
744If the string specifies an existing file name, the contents of the file is
745inserted, otherwise the string itself is inserted at the beginning of the test
746bench architecture template, if a separate file is created for the
747architecture.
748Type `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.
754If the string specifies an existing file name, the contents of the file is
755inserted, otherwise the string itself is inserted in the test bench
756architecture before the BEGIN keyword.
757Type `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.
763If the string specifies an existing file name, the contents of the file is
764inserted, otherwise the string itself is inserted in the test bench
765architecture before the END keyword.
766Type `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.
777Test 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
781Note 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)
d2ddb974
KH
786
787
788(defgroup vhdl-comment nil
789 "Customizations for comments."
5eabfe72 790 :group 'vhdl)
d2ddb974
KH
791
792(defcustom vhdl-self-insert-comments t
5eabfe72 793 "*Non-nil means various templates automatically insert help comments."
d2ddb974
KH
794 :type 'boolean
795 :group 'vhdl-comment)
796
797(defcustom vhdl-prompt-for-comments t
5eabfe72 798 "*Non-nil means various templates prompt for user definable comments."
d2ddb974
KH
799 :type 'boolean
800 :group 'vhdl-comment)
801
5eabfe72
KH
802(defcustom vhdl-inline-comment-column 40
803 "*Column to indent inline comments to.
804Overrides local variable `comment-column'.
805
806NOTE: Activate the new setting in a VHDL buffer using the menu entry
807 \"Activate New Customizations\""
d2ddb974
KH
808 :type 'integer
809 :group 'vhdl-comment)
810
811(defcustom vhdl-end-comment-column 79
5eabfe72
KH
812 "*End of comment column.
813Comments that exceed this column number are wrapped.
814
815NOTE: Activate the new setting in a VHDL buffer using the menu entry
816 \"Activate New Customizations\""
d2ddb974
KH
817 :type 'integer
818 :group 'vhdl-comment)
819
5eabfe72 820(defvar end-comment-column)
d2ddb974
KH
821
822
5eabfe72
KH
823(defgroup vhdl-align nil
824 "Customizations for alignment."
d2ddb974
KH
825 :group 'vhdl)
826
5eabfe72
KH
827(defcustom vhdl-auto-align t
828 "*Non-nil means align some templates automatically after generation."
d2ddb974 829 :type 'boolean
5eabfe72
KH
830 :group 'vhdl-align)
831
832(defcustom vhdl-align-groups t
833 "*Non-nil means align groups of code lines separately.
834A 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)
d2ddb974
KH
842
843(defcustom vhdl-highlight-keywords t
5eabfe72
KH
844 "*Non-nil means highlight VHDL keywords and other standardized words.
845The 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
852NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
853 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 854 :type 'boolean
5eabfe72
KH
855 :set (lambda (variable value)
856 (vhdl-custom-set variable value 'vhdl-font-lock-init))
d2ddb974
KH
857 :group 'vhdl-highlight)
858
5eabfe72
KH
859(defcustom vhdl-highlight-names t
860 "*Non-nil means highlight declaration names and construct labels.
861The 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
869NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
870 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 871 :type 'boolean
5eabfe72
KH
872 :set (lambda (variable value)
873 (vhdl-custom-set variable value 'vhdl-font-lock-init))
d2ddb974
KH
874 :group 'vhdl-highlight)
875
5eabfe72
KH
876(defcustom vhdl-highlight-special-words nil
877 "*Non-nil means highlight words with special syntax.
878The words with syntax and color specified in variable
879`vhdl-special-syntax-alist' are highlighted accordingly.
880Can be used for visual support of naming conventions.
881
882NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
883 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 884 :type 'boolean
5eabfe72
KH
885 :set (lambda (variable value)
886 (vhdl-custom-set variable value 'vhdl-font-lock-init))
d2ddb974
KH
887 :group 'vhdl-highlight)
888
5eabfe72
KH
889(defcustom vhdl-highlight-forbidden-words nil
890 "*Non-nil means highlight forbidden words.
891The reserved words specified in variable `vhdl-forbidden-words' or having the
892syntax specified in variable `vhdl-forbidden-syntax' are highlighted in a
893warning color (face `vhdl-font-lock-reserved-words-face') to indicate not to
894use them.
895
896NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
897 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 898 :type 'boolean
5eabfe72
KH
899 :set (lambda (variable value)
900 (vhdl-custom-set variable value
901 'vhdl-words-init 'vhdl-font-lock-init))
d2ddb974
KH
902 :group 'vhdl-highlight)
903
5eabfe72
KH
904(defcustom vhdl-highlight-verilog-keywords nil
905 "*Non-nil means highlight Verilog keywords as reserved words.
906Verilog keywords are highlighted in a warning color (face
907`vhdl-font-lock-reserved-words-face') to indicate not to use them.
2f402702 908
5eabfe72
KH
909NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
910 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 911 :type 'boolean
5eabfe72
KH
912 :set (lambda (variable value)
913 (vhdl-custom-set variable value
914 'vhdl-words-init 'vhdl-font-lock-init))
d2ddb974
KH
915 :group 'vhdl-highlight)
916
5eabfe72
KH
917(defcustom vhdl-highlight-translate-off nil
918 "*Non-nil means background-highlight code excluded from translation.
919That 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').
922Note: this might slow down on-the-fly fontification (and thus editing).
d2ddb974 923
5eabfe72
KH
924NOTE: 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))
d2ddb974
KH
929 :group 'vhdl-highlight)
930
5eabfe72
KH
931(defcustom vhdl-highlight-case-sensitive nil
932 "*Non-nil means consider case for highlighting.
933Possible 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
938Overrides local variable `font-lock-keywords-case-fold-search'.
939
940NOTE: 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)
d2ddb974 944
5eabfe72
KH
945(defcustom vhdl-special-syntax-alist nil
946 "*List of special syntax to be highlighted.
947If variable `vhdl-highlight-special-words' is non-nil, words with the specified
948syntax (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
960Can be used for visual support of naming conventions, such as highlighting
961different kinds of signals (e.g. \"Clk_c\", \"Rst_r\") or objects (e.g.
962\"Signal_s\", \"Variable_v\", \"Constant_c\") by distinguishing them using
963name suffices.
964For each entry, a new face is generated with the specified colors and name
965\"vhdl-font-lock-\" + name + \"-face\".
966
967NOTE: 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)
d2ddb974 978
5eabfe72
KH
979(defcustom vhdl-forbidden-words '()
980 "*List of forbidden words to be highlighted.
981If variable `vhdl-highlight-forbidden-words' is non-nil, these reserved
982words are highlighted in a warning color to indicate not to use them.
983
984NOTE: 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)
d2ddb974 991
5eabfe72
KH
992(defcustom vhdl-forbidden-syntax ""
993 "*Syntax of forbidden words to be highlighted.
994If variable `vhdl-highlight-forbidden-words' is non-nil, words with this
995syntax are highlighted in a warning color to indicate not to use them.
996Can be used to highlight too long identifiers (e.g. \"\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w+\"
997highlights identifiers with 10 or more characters).
d2ddb974 998
5eabfe72
KH
999NOTE: Activate the new setting in a VHDL buffer by re-fontifying it (menu
1000 entry \"Fontify Buffer\"). XEmacs: turn off and on font locking."
d2ddb974 1001 :type 'regexp
5eabfe72
KH
1002 :set (lambda (variable value)
1003 (vhdl-custom-set variable value
1004 'vhdl-words-init 'vhdl-font-lock-init))
1005 :group 'vhdl-highlight)
d2ddb974
KH
1006
1007
1008(defgroup vhdl-menu nil
5eabfe72 1009 "Customizations for speedbar and menues."
d2ddb974
KH
1010 :group 'vhdl)
1011
5eabfe72
KH
1012(defcustom vhdl-speedbar nil
1013 "*Non-nil means open the speedbar automatically at startup.
1014Alternatively, the speedbar can be opened from the VHDL menu."
d2ddb974
KH
1015 :type 'boolean
1016 :group 'vhdl-menu)
1017
5eabfe72
KH
1018(defcustom vhdl-speedbar-show-hierarchy nil
1019 "*Non-nil means open the speedbar as hierarchy browser at startup.
1020Otherwise, the speedbar is opened as normal file browser."
d2ddb974
KH
1021 :type 'boolean
1022 :group 'vhdl-menu)
1023
5eabfe72
KH
1024(defcustom vhdl-speedbar-hierarchy-indent 1
1025 "*Amount of indentation in hierarchy display of subcomponent."
1026 :type 'integer
5eabfe72
KH
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.
1031Alternatively, the speedbar can be used. Note that the index menu scans a file
1032when it is opened, while speedbar only scans the file upon request.
1033Does 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.
1039Alternatively, 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.
1045Hideshow allows hiding code of VHDL design units.
1046Does not work under XEmacs.
1047
1048NOTE: 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."
d2ddb974
KH
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
5eabfe72
KH
1064 "*Non-nil means print code in two columns and landscape format.
1065
1066NOTE: 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
1074NOTE: Activate the new setting by restarting Emacs.
1075 Overrides `ps-print' settings locally."
d2ddb974
KH
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
5eabfe72 1085 "*Non-nil means `TAB' does indentation, word completion and tab insertion.
d2ddb974
KH
1086That is, if preceeding character is part of a word then complete word,
1087else if not at beginning of line then insert tab,
1088else if last command was a `TAB' or `RET' then dedent one step,
5eabfe72 1089else indent current line (i.e. `TAB' is bound to `vhdl-electric-tab').
d2ddb974 1090If nil, TAB always indents current line (i.e. `TAB' is bound to
5eabfe72
KH
1091`vhdl-indent-line').
1092
1093NOTE: Activate the new setting in a VHDL buffer using the menu entry
1094 \"Activate New Customizations\""
d2ddb974
KH
1095 :type 'boolean
1096 :group 'vhdl-misc)
1097
5eabfe72
KH
1098(defcustom vhdl-word-completion-case-sensitive nil
1099 "*Non-nil means word completion using `TAB' is case sensitive.
1100That is, `TAB' completes words that start with the same letters and case.
1101Otherwise, case is ignored."
1102 :type 'boolean
d2ddb974
KH
1103 :group 'vhdl-misc)
1104
1105(defcustom vhdl-word-completion-in-minibuffer t
5eabfe72
KH
1106 "*Non-nil enables word completion in minibuffer (for template prompts).
1107
1108NOTE: Activate the new setting by restarting Emacs."
d2ddb974
KH
1109 :type 'boolean
1110 :group 'vhdl-misc)
1111
1112(defcustom vhdl-underscore-is-part-of-word nil
5eabfe72 1113 "*Non-nil means consider the underscore character `_' as part of word.
d2ddb974 1114An identifier containing underscores is then treated as a single word in
5eabfe72
KH
1115select and move operations. All parts of an identifier separated by underscore
1116are treated as single words otherwise.
1117
1118NOTE: Activate the new setting in a VHDL buffer using the menu entry
1119 \"Activate New Customizations\""
d2ddb974 1120 :type 'boolean
5eabfe72
KH
1121 :set (lambda (variable value)
1122 (vhdl-custom-set variable value 'vhdl-mode-syntax-table-init))
d2ddb974
KH
1123 :group 'vhdl-misc)
1124
a152344b
MR
1125;; add related general customizations
1126(defgroup vhdl-related
1127 (if (string-match "XEmacs" emacs-version)
1128 '((ps-print custom-group)
1129 (mail-host-address custom-variable)
1130 (user-mail-address custom-variable)
1131 (line-number-mode custom-variable)
1132 (paren-mode custom-variable))
1133 '((ps-print custom-group)
1134 (mail-host-address custom-variable)
1135 (user-mail-address custom-variable)
1136 (line-number-mode custom-variable)
1137 (paren-showing custom-group)
1138 (transient-mark-mode custom-variable)))
5eabfe72
KH
1139 "Related general customizations."
1140 :group 'vhdl)
1141
5eabfe72
KH
1142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1143;; Internal variables
1144
1145(defconst vhdl-version "3.29"
1146 "VHDL Mode version number.")
1147
1148(defvar vhdl-progress-interval 1
1149 "*Interval used to update progress status during long operations.
1150If a number, percentage complete gets updated after each interval of
9b61eea1 1151that many seconds. To inhibit all messages, set this variable to nil.")
d2ddb974
KH
1152
1153(defvar vhdl-inhibit-startup-warnings-p nil
1154 "*If non-nil, inhibits start up compatibility warnings.")
1155
1156(defvar vhdl-strict-syntax-p nil
1157 "*If non-nil, all syntactic symbols must be found in `vhdl-offsets-alist'.
1158If the syntactic symbol for a particular line does not match a symbol
1159in the offsets alist, an error is generated, otherwise no error is
1160reported and the syntactic symbol is ignored.")
1161
1162(defvar vhdl-echo-syntactic-information-p nil
1163 "*If non-nil, syntactic info is echoed when the line is indented.")
1164
1165(defconst vhdl-offsets-alist-default
1166 '((string . -1000)
1167 (block-open . 0)
1168 (block-close . 0)
1169 (statement . 0)
1170 (statement-cont . vhdl-lineup-statement-cont)
1171 (statement-block-intro . +)
1172 (statement-case-intro . +)
1173 (case-alternative . +)
1174 (comment . vhdl-lineup-comment)
1175 (arglist-intro . +)
1176 (arglist-cont . 0)
1177 (arglist-cont-nonempty . vhdl-lineup-arglist)
1178 (arglist-close . vhdl-lineup-arglist)
1179 (entity . 0)
1180 (configuration . 0)
1181 (package . 0)
1182 (architecture . 0)
1183 (package-body . 0)
1184 )
1185 "Default settings for offsets of syntactic elements.
1186Do not change this constant! See the variable `vhdl-offsets-alist' for
1187more information.")
1188
1189(defvar vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default)
1190 "*Association list of syntactic element symbols and indentation offsets.
1191As described below, each cons cell in this list has the form:
1192
1193 (SYNTACTIC-SYMBOL . OFFSET)
1194
5eabfe72 1195When a line is indented, `vhdl-mode' first determines the syntactic
d2ddb974
KH
1196context of the line by generating a list of symbols called syntactic
1197elements. This list can contain more than one syntactic element and
1198the global variable `vhdl-syntactic-context' contains the context list
1199for the line being indented. Each element in this list is actually a
1200cons cell of the syntactic symbol and a buffer position. This buffer
1201position is call the relative indent point for the line. Some
1202syntactic symbols may not have a relative indent point associated with
1203them.
1204
5eabfe72 1205After the syntactic context list for a line is generated, `vhdl-mode'
d2ddb974
KH
1206calculates the absolute indentation for the line by looking at each
1207syntactic element in the list. First, it compares the syntactic
1208element against the SYNTACTIC-SYMBOL's in `vhdl-offsets-alist'. When it
1209finds a match, it adds the OFFSET to the column of the relative indent
1210point. The sum of this calculation for each element in the syntactic
1211list is the absolute offset for line being indented.
1212
1213If the syntactic element does not match any in the `vhdl-offsets-alist',
1214an error is generated if `vhdl-strict-syntax-p' is non-nil, otherwise
1215the element is ignored.
1216
1217Actually, OFFSET can be an integer, a function, a variable, or one of
1218the following symbols: `+', `-', `++', or `--'. These latter
1219designate positive or negative multiples of `vhdl-basic-offset',
5eabfe72 1220respectively: *1, *-1, *2, and *-2. If OFFSET is a function, it is
d2ddb974
KH
1221called with a single argument containing the cons of the syntactic
1222element symbol and the relative indent point. The function should
1223return an integer offset.
1224
1225Here is the current list of valid syntactic element symbols:
1226
1227 string -- inside multi-line string
1228 block-open -- statement block open
1229 block-close -- statement block close
1230 statement -- a VHDL statement
1231 statement-cont -- a continuation of a VHDL statement
1232 statement-block-intro -- the first line in a new statement block
1233 statement-case-intro -- the first line in a case alternative block
1234 case-alternative -- a case statement alternative clause
1235 comment -- a line containing only a comment
1236 arglist-intro -- the first line in an argument list
1237 arglist-cont -- subsequent argument list lines when no
1238 arguments follow on the same line as the
1239 the arglist opening paren
1240 arglist-cont-nonempty -- subsequent argument list lines when at
1241 least one argument follows on the same
1242 line as the arglist opening paren
1243 arglist-close -- the solo close paren of an argument list
1244 entity -- inside an entity declaration
1245 configuration -- inside a configuration declaration
1246 package -- inside a package declaration
1247 architecture -- inside an architecture body
5eabfe72 1248 package-body -- inside a package body")
d2ddb974
KH
1249
1250(defvar vhdl-comment-only-line-offset 0
1251 "*Extra offset for line which contains only the start of a comment.
1252Can contain an integer or a cons cell of the form:
1253
1254 (NON-ANCHORED-OFFSET . ANCHORED-OFFSET)
1255
1256Where NON-ANCHORED-OFFSET is the amount of offset given to
1257non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is
1258the amount of offset to give column-zero anchored comment-only lines.
1259Just an integer as value is equivalent to (<val> . 0)")
1260
1261(defvar vhdl-special-indent-hook nil
1262 "*Hook for user defined special indentation adjustments.
1263This hook gets called after a line is indented by the mode.")
1264
1265(defvar vhdl-style-alist
1266 '(("IEEE"
1267 (vhdl-basic-offset . 4)
1268 (vhdl-offsets-alist . ())
1269 )
1270 )
1271 "Styles of Indentation.
1272Elements of this alist are of the form:
1273
1274 (STYLE-STRING (VARIABLE . VALUE) [(VARIABLE . VALUE) ...])
1275
1276where STYLE-STRING is a short descriptive string used to select a
5eabfe72 1277style, VARIABLE is any `vhdl-mode' variable, and VALUE is the intended
d2ddb974
KH
1278value for that variable when using the selected style.
1279
1280There is one special case when VARIABLE is `vhdl-offsets-alist'. In this
1281case, the VALUE is a list containing elements of the form:
1282
1283 (SYNTACTIC-SYMBOL . VALUE)
1284
1285as described in `vhdl-offsets-alist'. These are passed directly to
1286`vhdl-set-offset' so there is no need to set every syntactic symbol in
1287your style, only those that are different from the default.")
1288
1289;; dynamically append the default value of most variables
1290(or (assoc "Default" vhdl-style-alist)
1291 (let* ((varlist '(vhdl-inhibit-startup-warnings-p
1292 vhdl-strict-syntax-p
1293 vhdl-echo-syntactic-information-p
1294 vhdl-basic-offset
1295 vhdl-offsets-alist
1296 vhdl-comment-only-line-offset))
1297 (default (cons "Default"
1298 (mapcar
1299 (function
1300 (lambda (var)
5eabfe72 1301 (cons var (symbol-value var))))
d2ddb974
KH
1302 varlist))))
1303 (setq vhdl-style-alist (cons default vhdl-style-alist))))
1304
1305(defvar vhdl-mode-hook nil
1306 "*Hook called by `vhdl-mode'.")
1307
1308
5eabfe72
KH
1309;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1310;; Compatibility
1311
1312(defvar vhdl-startup-warnings nil
1313 "Warnings to tell the user during start up.")
1314
1315(defun vhdl-print-warnings ()
1316 "Print out messages in variable `vhdl-startup-warnings'."
1317 (let ((warnings vhdl-startup-warnings))
1318 (while warnings
1319 (message (concat "WARNING: " (car warnings)))
1320 (setq warnings (cdr warnings))))
1321 (when (> (length vhdl-startup-warnings) 1)
1322 (message "WARNING: See warning messages in *Messages* buffer.")))
1323
1324(defun vhdl-add-warning (string)
1325 "Add STRING to warning list `vhdl-startup-warnings'."
1326 (setq vhdl-startup-warnings (cons string vhdl-startup-warnings)))
1327
1328;; Perform compatibility checks.
1329(when (not (stringp vhdl-compiler)) ; changed format of `vhdl-compiler'
1330 (setq vhdl-compiler "ModelSim")
1331 (vhdl-add-warning "Variable `vhdl-compiler' has changed format; customize again"))
1332(when (not (listp vhdl-standard)) ; changed format of `vhdl-standard'
1333 (setq vhdl-standard '(87 nil))
1334 (vhdl-add-warning "Variable `vhdl-standard' has changed format; customize again"))
1335(when (= (length (car vhdl-model-alist)) 3)
1336 (let ((old-alist vhdl-model-alist) ; changed format of `vhdl-model-alist'
1337 new-alist)
1338 (while old-alist
1339 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1340 (setq old-alist (cdr old-alist)))
1341 (setq vhdl-model-alist (nreverse new-alist))))
1342(when (= (length (car vhdl-project-alist)) 3)
1343 (let ((old-alist vhdl-project-alist) ; changed format of `vhdl-project-alist'
1344 new-alist)
1345 (while old-alist
1346 (setq new-alist (cons (append (car old-alist) '("")) new-alist))
1347 (setq old-alist (cdr old-alist)))
1348 (setq vhdl-project-alist (nreverse new-alist))))
1349
1350;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1351;; Help functions
1352
1353(defsubst vhdl-standard-p (standard)
1354 "Check if STANDARD is specified as used standard."
1355 (or (eq standard (car vhdl-standard))
1356 (memq standard (cadr vhdl-standard))))
1357
1358;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1359;; Required packages
1360
1361(require 'assoc)
1362
1363
1364;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1365;;; Emacs variant handling
1366;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
1367
1368;; active regions
1369
1370(defun vhdl-keep-region-active ()
5eabfe72
KH
1371 "Do whatever is necessary to keep the region active in XEmacs.
1372Ignore byte-compiler warnings you might see."
d2ddb974
KH
1373 (and (boundp 'zmacs-region-stays)
1374 (setq zmacs-region-stays t)))
1375
5eabfe72
KH
1376;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1377;; XEmacs hacks
1378
1379(unless (fboundp 'wildcard-to-regexp)
1380 (defun wildcard-to-regexp (wildcard)
1381 "Simplified version of `wildcard-to-regexp' from Emacs' `files.el'."
1382 (let* ((i (string-match "[*?]" wildcard))
1383 (result (substring wildcard 0 i))
1384 (len (length wildcard)))
1385 (when i
1386 (while (< i len)
1387 (let ((ch (aref wildcard i)))
1388 (setq result (concat result
1389 (cond ((eq ch ?*) "[^\000]*")
1390 ((eq ch ??) "[^\000]")
1391 (t (char-to-string ch)))))
1392 (setq i (1+ i)))))
1393 (concat "\\`" result "\\'"))))
1394
1395
1396;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1397;;; Bindings
1398;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1399
1400;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
1401;; Key bindings
1402
1403(defvar vhdl-template-map ()
1404 "Keymap for VHDL templates.")
1405
5eabfe72
KH
1406(defun vhdl-template-map-init ()
1407 "Initialize `vhdl-template-map'."
d2ddb974
KH
1408 (setq vhdl-template-map (make-sparse-keymap))
1409 ;; key bindings for VHDL templates
5eabfe72
KH
1410 (define-key vhdl-template-map "al" 'vhdl-template-alias)
1411 (define-key vhdl-template-map "ar" 'vhdl-template-architecture)
1412 (define-key vhdl-template-map "at" 'vhdl-template-assert)
1413 (define-key vhdl-template-map "ad" 'vhdl-template-attribute-decl)
1414 (define-key vhdl-template-map "as" 'vhdl-template-attribute-spec)
1415 (define-key vhdl-template-map "bl" 'vhdl-template-block)
1416 (define-key vhdl-template-map "ca" 'vhdl-template-case-is)
1417 (define-key vhdl-template-map "cd" 'vhdl-template-component-decl)
1418 (define-key vhdl-template-map "ci" 'vhdl-template-component-inst)
1419 (define-key vhdl-template-map "cs" 'vhdl-template-conditional-signal-asst)
1420 (define-key vhdl-template-map "Cb" 'vhdl-template-block-configuration)
1421 (define-key vhdl-template-map "Cc" 'vhdl-template-component-conf)
1422 (define-key vhdl-template-map "Cd" 'vhdl-template-configuration-decl)
1423 (define-key vhdl-template-map "Cs" 'vhdl-template-configuration-spec)
1424 (define-key vhdl-template-map "co" 'vhdl-template-constant)
1425 (define-key vhdl-template-map "di" 'vhdl-template-disconnect)
1426 (define-key vhdl-template-map "el" 'vhdl-template-else)
1427 (define-key vhdl-template-map "ei" 'vhdl-template-elsif)
1428 (define-key vhdl-template-map "en" 'vhdl-template-entity)
1429 (define-key vhdl-template-map "ex" 'vhdl-template-exit)
1430 (define-key vhdl-template-map "fi" 'vhdl-template-file)
1431 (define-key vhdl-template-map "fg" 'vhdl-template-for-generate)
1432 (define-key vhdl-template-map "fl" 'vhdl-template-for-loop)
1433 (define-key vhdl-template-map "\C-f" 'vhdl-template-footer)
1434 (define-key vhdl-template-map "fb" 'vhdl-template-function-body)
1435 (define-key vhdl-template-map "fd" 'vhdl-template-function-decl)
1436 (define-key vhdl-template-map "ge" 'vhdl-template-generic)
1437 (define-key vhdl-template-map "gd" 'vhdl-template-group-decl)
1438 (define-key vhdl-template-map "gt" 'vhdl-template-group-template)
1439 (define-key vhdl-template-map "\C-h" 'vhdl-template-header)
1440 (define-key vhdl-template-map "ig" 'vhdl-template-if-generate)
1441 (define-key vhdl-template-map "it" 'vhdl-template-if-then)
1442 (define-key vhdl-template-map "li" 'vhdl-template-library)
1443 (define-key vhdl-template-map "lo" 'vhdl-template-bare-loop)
1444 (define-key vhdl-template-map "\C-m" 'vhdl-template-modify)
1445 (define-key vhdl-template-map "\C-t" 'vhdl-template-insert-date)
1446 (define-key vhdl-template-map "ma" 'vhdl-template-map)
1447 (define-key vhdl-template-map "ne" 'vhdl-template-next)
1448 (define-key vhdl-template-map "ot" 'vhdl-template-others)
1449 (define-key vhdl-template-map "Pd" 'vhdl-template-package-decl)
1450 (define-key vhdl-template-map "Pb" 'vhdl-template-package-body)
1451 (define-key vhdl-template-map "(" 'vhdl-template-paired-parens)
1452 (define-key vhdl-template-map "po" 'vhdl-template-port)
1453 (define-key vhdl-template-map "pb" 'vhdl-template-procedure-body)
1454 (define-key vhdl-template-map "pd" 'vhdl-template-procedure-decl)
1455 (define-key vhdl-template-map "pc" 'vhdl-template-process-comb)
1456 (define-key vhdl-template-map "ps" 'vhdl-template-process-seq)
1457 (define-key vhdl-template-map "rp" 'vhdl-template-report)
1458 (define-key vhdl-template-map "rt" 'vhdl-template-return)
1459 (define-key vhdl-template-map "ss" 'vhdl-template-selected-signal-asst)
1460 (define-key vhdl-template-map "si" 'vhdl-template-signal)
1461 (define-key vhdl-template-map "su" 'vhdl-template-subtype)
1462 (define-key vhdl-template-map "ty" 'vhdl-template-type)
1463 (define-key vhdl-template-map "us" 'vhdl-template-use)
1464 (define-key vhdl-template-map "va" 'vhdl-template-variable)
1465 (define-key vhdl-template-map "wa" 'vhdl-template-wait)
1466 (define-key vhdl-template-map "wl" 'vhdl-template-while-loop)
1467 (define-key vhdl-template-map "wi" 'vhdl-template-with)
1468 (define-key vhdl-template-map "wc" 'vhdl-template-clocked-wait)
1469 (define-key vhdl-template-map "\C-pb" 'vhdl-template-package-numeric-bit)
1470 (define-key vhdl-template-map "\C-pn" 'vhdl-template-package-numeric-std)
1471 (define-key vhdl-template-map "\C-ps" 'vhdl-template-package-std-logic-1164)
1472 (define-key vhdl-template-map "\C-pA" 'vhdl-template-package-std-logic-arith)
1473 (define-key vhdl-template-map "\C-pM" 'vhdl-template-package-std-logic-misc)
1474 (define-key vhdl-template-map "\C-pS" 'vhdl-template-package-std-logic-signed)
1475 (define-key vhdl-template-map "\C-pT" 'vhdl-template-package-std-logic-textio)
1476 (define-key vhdl-template-map "\C-pU" 'vhdl-template-package-std-logic-unsigned)
1477 (define-key vhdl-template-map "\C-pt" 'vhdl-template-package-textio)
1478 (define-key vhdl-template-map "\C-dn" 'vhdl-template-directive-translate-on)
1479 (define-key vhdl-template-map "\C-df" 'vhdl-template-directive-translate-off)
1480 (define-key vhdl-template-map "\C-dN" 'vhdl-template-directive-synthesis-on)
1481 (define-key vhdl-template-map "\C-dF" 'vhdl-template-directive-synthesis-off)
1482 (define-key vhdl-template-map "\C-q" 'vhdl-template-search-prompt)
1483 (when (vhdl-standard-p 'ams)
1484 (define-key vhdl-template-map "br" 'vhdl-template-break)
1485 (define-key vhdl-template-map "cu" 'vhdl-template-case-use)
1486 (define-key vhdl-template-map "iu" 'vhdl-template-if-use)
1487 (define-key vhdl-template-map "lm" 'vhdl-template-limit)
1488 (define-key vhdl-template-map "na" 'vhdl-template-nature)
1489 (define-key vhdl-template-map "pa" 'vhdl-template-procedural)
1490 (define-key vhdl-template-map "qf" 'vhdl-template-quantity-free)
1491 (define-key vhdl-template-map "qb" 'vhdl-template-quantity-branch)
1492 (define-key vhdl-template-map "qs" 'vhdl-template-quantity-source)
1493 (define-key vhdl-template-map "sn" 'vhdl-template-subnature)
1494 (define-key vhdl-template-map "te" 'vhdl-template-terminal)
1495 )
1496 (when (vhdl-standard-p 'math)
1497 (define-key vhdl-template-map "\C-pc" 'vhdl-template-package-math-complex)
1498 (define-key vhdl-template-map "\C-pr" 'vhdl-template-package-math-real)
1499 ))
1500
1501;; initialize template map for VHDL Mode
1502(vhdl-template-map-init)
1503
1504(defun vhdl-function-name (prefix string &optional postfix)
1505 "Generate a Lisp function name.
1506PREFIX, STRING and optional POSTFIX are concatenated by '-' and spaces in
1507STRING are replaced by `-' and substrings are converted to lower case."
1508 (let ((name prefix))
1509 (while (string-match "\\(\\w+\\)\\s-*\\(.*\\)" string)
1510 (setq name
1511 (concat name "-" (downcase (substring string 0 (match-end 1)))))
1512 (setq string (substring string (match-beginning 2))))
1513 (when postfix (setq name (concat name "-" postfix)))
1514 (intern name)))
1515
1516(defvar vhdl-model-map ()
1517 "Keymap for VHDL models.")
1518
1519(defun vhdl-model-map-init ()
1520 "Initialize `vhdl-model-map'."
1521 (setq vhdl-model-map (make-sparse-keymap))
1522 ;; key bindings for VHDL models
1523 (let ((model-alist vhdl-model-alist) model)
1524 (while model-alist
1525 (setq model (car model-alist))
1526 (define-key vhdl-model-map (nth 2 model)
1527 (vhdl-function-name "vhdl-model" (nth 0 model)))
1528 (setq model-alist (cdr model-alist)))))
1529
1530;; initialize user model map for VHDL Mode
1531(vhdl-model-map-init)
d2ddb974
KH
1532
1533(defvar vhdl-mode-map ()
1534 "Keymap for VHDL Mode.")
1535
5eabfe72
KH
1536(defun vhdl-mode-map-init ()
1537 "Initialize `vhdl-mode-map'."
d2ddb974 1538 (setq vhdl-mode-map (make-sparse-keymap))
5eabfe72
KH
1539 ;; template key bindings
1540 (define-key vhdl-mode-map "\C-c\C-t" vhdl-template-map)
1541 ;; model key bindings
1542 (define-key vhdl-mode-map "\C-c\C-m" vhdl-model-map)
d2ddb974 1543 ;; standard key bindings
5eabfe72
KH
1544 (define-key vhdl-mode-map "\M-a" 'vhdl-beginning-of-statement)
1545 (define-key vhdl-mode-map "\M-e" 'vhdl-end-of-statement)
1546 (define-key vhdl-mode-map "\M-\C-f" 'vhdl-forward-sexp)
1547 (define-key vhdl-mode-map "\M-\C-b" 'vhdl-backward-sexp)
1548 (define-key vhdl-mode-map "\M-\C-u" 'vhdl-backward-up-list)
1549 (define-key vhdl-mode-map "\M-\C-a" 'vhdl-beginning-of-defun)
1550 (define-key vhdl-mode-map "\M-\C-e" 'vhdl-end-of-defun)
1551 (define-key vhdl-mode-map "\M-\C-h" 'vhdl-mark-defun)
1552 (define-key vhdl-mode-map "\M-\C-q" 'vhdl-indent-sexp)
1553 ;; backspace/delete key bindings
1554 (define-key vhdl-mode-map [backspace] 'backward-delete-char-untabify)
1555 (define-key vhdl-mode-map [delete] 'delete-char)
1556 (unless (string-match "XEmacs" emacs-version)
1557 (define-key vhdl-mode-map [M-delete] 'kill-word))
1558 ;; mode specific key bindings
1559 (define-key vhdl-mode-map "\C-c\C-e" 'vhdl-electric-mode)
1560 (define-key vhdl-mode-map "\C-c\C-s" 'vhdl-stutter-mode)
1561 (define-key vhdl-mode-map "\C-c\C-k" 'vhdl-compile)
1562 (define-key vhdl-mode-map "\C-c\M-\C-k" 'vhdl-make)
1563 (define-key vhdl-mode-map "\C-c\C-p\C-w" 'vhdl-port-copy)
1564 (define-key vhdl-mode-map "\C-c\C-p\M-w" 'vhdl-port-copy)
1565 (define-key vhdl-mode-map "\C-c\C-p\C-e" 'vhdl-port-paste-entity)
1566 (define-key vhdl-mode-map "\C-c\C-p\C-c" 'vhdl-port-paste-component)
1567 (define-key vhdl-mode-map "\C-c\C-p\C-i" 'vhdl-port-paste-instance)
1568 (define-key vhdl-mode-map "\C-c\C-p\C-s" 'vhdl-port-paste-signals)
1569 (define-key vhdl-mode-map "\C-c\C-p\M-c" 'vhdl-port-paste-constants)
1570 (if (string-match "XEmacs" emacs-version) ; `... C-g' not allowed in XEmacs
1571 (define-key vhdl-mode-map "\C-c\C-p\M-g" 'vhdl-port-paste-generic-map)
1572 (define-key vhdl-mode-map "\C-c\C-p\C-g" 'vhdl-port-paste-generic-map))
1573 (define-key vhdl-mode-map "\C-c\C-p\C-t" 'vhdl-port-paste-testbench)
1574 (define-key vhdl-mode-map "\C-c\C-p\C-f" 'vhdl-port-flatten)
1575 (define-key vhdl-mode-map "\C-c\C-c" 'vhdl-comment-uncomment-region)
1576 (define-key vhdl-mode-map "\C-c-" 'vhdl-comment-append-inline)
1577 (define-key vhdl-mode-map "\C-c\M--" 'vhdl-comment-display-line)
1578 (define-key vhdl-mode-map "\C-c\M-\C-i" 'vhdl-indent-line)
1579 (define-key vhdl-mode-map "\M-\C-\\" 'vhdl-indent-region)
1580 (define-key vhdl-mode-map "\C-c\C-a" 'vhdl-align-group)
1581 (define-key vhdl-mode-map "\C-c\C-r\C-a" 'vhdl-align-noindent-region)
1582 (define-key vhdl-mode-map "\C-c\M-\C-a" 'vhdl-align-inline-comment-group)
1583 (define-key vhdl-mode-map "\C-c\C-r\M-\C-a" 'vhdl-align-inline-comment-region)
1584 (define-key vhdl-mode-map "\C-c\C-w" 'vhdl-fixup-whitespace-region)
1585 (define-key vhdl-mode-map "\C-c\C-l\C-w" 'vhdl-line-kill)
1586 (define-key vhdl-mode-map "\C-c\C-l\M-w" 'vhdl-line-copy)
1587 (define-key vhdl-mode-map "\C-c\C-l\C-y" 'vhdl-line-yank)
1588 (define-key vhdl-mode-map "\C-c\C-l\t" 'vhdl-line-expand)
1589 (define-key vhdl-mode-map "\C-c\C-l\C-n" 'vhdl-line-transpose-next)
1590 (define-key vhdl-mode-map "\C-c\C-l\C-p" 'vhdl-line-transpose-previous)
1591 (define-key vhdl-mode-map "\C-c\C-l\C-o" 'vhdl-line-open)
1592 (define-key vhdl-mode-map "\C-c\C-l\C-g" 'goto-line)
1593 (define-key vhdl-mode-map "\C-c\C-l\C-c" 'vhdl-comment-uncomment-line)
1594 (define-key vhdl-mode-map "\C-c\C-r\C-u" 'vhdl-fix-case-region)
1595 (define-key vhdl-mode-map "\C-c\C-u" 'vhdl-fix-case-buffer)
1596 (define-key vhdl-mode-map "\C-c\C-f" 'vhdl-fontify-buffer)
1597 (define-key vhdl-mode-map "\C-c\C-x" 'vhdl-show-syntactic-information)
1598 (define-key vhdl-mode-map "\C-c\C-h" 'vhdl-doc-mode)
1599 (define-key vhdl-mode-map "\C-c\C-v" 'vhdl-version)
1600 (define-key vhdl-mode-map "\C-c\C-r\C-b" 'vhdl-beautify-region)
1601 (define-key vhdl-mode-map "\C-c\C-b" 'vhdl-beautify-buffer)
1602 (define-key vhdl-mode-map "\M-\t" 'tab-to-tab-stop)
1603 ;; insert commands bindings
1604 (define-key vhdl-mode-map "\C-c\C-i\C-c" 'vhdl-template-insert-construct)
1605 (define-key vhdl-mode-map "\C-c\C-i\C-p" 'vhdl-template-insert-package)
1606 (define-key vhdl-mode-map "\C-c\C-i\C-d" 'vhdl-template-insert-directive)
1607 (define-key vhdl-mode-map "\C-c\C-i\C-m" 'vhdl-model-insert)
1608 ;; electric key bindings
1609 (define-key vhdl-mode-map " " 'vhdl-electric-space)
d2ddb974 1610 (if vhdl-intelligent-tab
5eabfe72
KH
1611 (define-key vhdl-mode-map "\t" 'vhdl-electric-tab)
1612 (define-key vhdl-mode-map "\t" 'vhdl-indent-line))
1613 (define-key vhdl-mode-map "\r" 'vhdl-electric-return)
1614 (define-key vhdl-mode-map "-" 'vhdl-electric-dash)
1615 (define-key vhdl-mode-map "[" 'vhdl-electric-open-bracket)
1616 (define-key vhdl-mode-map "]" 'vhdl-electric-close-bracket)
1617 (define-key vhdl-mode-map "'" 'vhdl-electric-quote)
1618 (define-key vhdl-mode-map ";" 'vhdl-electric-semicolon)
1619 (define-key vhdl-mode-map "," 'vhdl-electric-comma)
1620 (define-key vhdl-mode-map "." 'vhdl-electric-period)
1621 (when (vhdl-standard-p 'ams)
1622 (define-key vhdl-mode-map "=" 'vhdl-electric-equal)))
1623
1624;; initialize mode map for VHDL Mode
1625(vhdl-mode-map-init)
d2ddb974
KH
1626
1627;; define special minibuffer keymap for enabling word completion in minibuffer
1628;; (useful in template generator prompts)
1629(defvar vhdl-minibuffer-local-map (copy-keymap minibuffer-local-map)
1630 "Keymap for minibuffer used in VHDL Mode.")
1631
5eabfe72
KH
1632(when vhdl-word-completion-in-minibuffer
1633 (define-key vhdl-minibuffer-local-map "\t" 'vhdl-minibuffer-tab))
1634
1635;; set up electric character functions to work with
1636;; `delete-selection-mode' (Emacs) and `pending-delete-mode' (XEmacs)
1637(mapcar
1638 (function
1639 (lambda (sym)
1640 (put sym 'delete-selection t) ; for `delete-selection-mode' (Emacs)
1641 (put sym 'pending-delete t))) ; for `pending-delete-mode' (XEmacs)
1642 '(vhdl-electric-space
1643 vhdl-electric-tab
1644 vhdl-electric-return
1645 vhdl-electric-dash
1646 vhdl-electric-open-bracket
1647 vhdl-electric-close-bracket
1648 vhdl-electric-quote
1649 vhdl-electric-semicolon
1650 vhdl-electric-comma
1651 vhdl-electric-period
1652 vhdl-electric-equal))
1653
1654;; syntax table
d2ddb974 1655(defvar vhdl-mode-syntax-table nil
5eabfe72 1656 "Syntax table used in `vhdl-mode' buffers.")
d2ddb974 1657
5eabfe72
KH
1658(defun vhdl-mode-syntax-table-init ()
1659 "Initialize `vhdl-mode-syntax-table'."
d2ddb974 1660 (setq vhdl-mode-syntax-table (make-syntax-table))
5eabfe72
KH
1661 ;; define punctuation
1662 (modify-syntax-entry ?\# "." vhdl-mode-syntax-table)
1663 (modify-syntax-entry ?\$ "." vhdl-mode-syntax-table)
1664 (modify-syntax-entry ?\% "." vhdl-mode-syntax-table)
1665 (modify-syntax-entry ?\& "." vhdl-mode-syntax-table)
1666 (modify-syntax-entry ?\' "." vhdl-mode-syntax-table)
1667 (modify-syntax-entry ?\* "." vhdl-mode-syntax-table)
1668 (modify-syntax-entry ?\+ "." vhdl-mode-syntax-table)
1669 (modify-syntax-entry ?\. "." vhdl-mode-syntax-table)
1670 (modify-syntax-entry ?\/ "." vhdl-mode-syntax-table)
1671 (modify-syntax-entry ?\: "." vhdl-mode-syntax-table)
1672 (modify-syntax-entry ?\; "." vhdl-mode-syntax-table)
1673 (modify-syntax-entry ?\< "." vhdl-mode-syntax-table)
1674 (modify-syntax-entry ?\= "." vhdl-mode-syntax-table)
1675 (modify-syntax-entry ?\> "." vhdl-mode-syntax-table)
1676 (modify-syntax-entry ?\\ "." vhdl-mode-syntax-table)
1677 (modify-syntax-entry ?\| "." vhdl-mode-syntax-table)
1678 ;; define string
1679 (modify-syntax-entry ?\" "\"" vhdl-mode-syntax-table)
1680 ;; define underscore
1681 (when vhdl-underscore-is-part-of-word
1682 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table))
1683 ;; a single hyphen is punctuation, but a double hyphen starts a comment
1684 (modify-syntax-entry ?\- ". 12" vhdl-mode-syntax-table)
1685 ;; and \n and \^M end a comment
1686 (modify-syntax-entry ?\n ">" vhdl-mode-syntax-table)
1687 (modify-syntax-entry ?\^M ">" vhdl-mode-syntax-table)
1688 ;; define parentheses to match
1689 (modify-syntax-entry ?\( "()" vhdl-mode-syntax-table)
1690 (modify-syntax-entry ?\) ")(" vhdl-mode-syntax-table)
1691 (modify-syntax-entry ?\[ "(]" vhdl-mode-syntax-table)
1692 (modify-syntax-entry ?\] ")[" vhdl-mode-syntax-table)
1693 (modify-syntax-entry ?\{ "(}" vhdl-mode-syntax-table)
1694 (modify-syntax-entry ?\} "){" vhdl-mode-syntax-table))
1695
1696;; initialize syntax table for VHDL Mode
1697(vhdl-mode-syntax-table-init)
1698
1699(defmacro vhdl-ext-syntax-table (&rest body)
1700 "Execute BODY with syntax table that includes `_' in word class."
d4a5b644
GM
1701 `(let (result)
1702 (modify-syntax-entry ?_ "w" vhdl-mode-syntax-table)
1703 (setq result (progn ,@body))
1704 (when (not vhdl-underscore-is-part-of-word)
1705 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table))
1706 result))
d2ddb974
KH
1707
1708(defvar vhdl-syntactic-context nil
1709 "Buffer local variable containing syntactic analysis list.")
1710(make-variable-buffer-local 'vhdl-syntactic-context)
1711
5eabfe72 1712;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
1713;; Abbrev hook bindings
1714
1715(defvar vhdl-mode-abbrev-table nil
5eabfe72
KH
1716 "Abbrev table to use in `vhdl-mode' buffers.")
1717
1718(defun vhdl-mode-abbrev-table-init ()
1719 "Initialize `vhdl-mode-abbrev-table'."
1720 (when vhdl-mode-abbrev-table (clear-abbrev-table vhdl-mode-abbrev-table))
1721 (define-abbrev-table 'vhdl-mode-abbrev-table
1722 (append
1723 (when (memq 'vhdl vhdl-electric-keywords)
1724 ;; VHDL'93 keywords
1725 '(
610e1e80
PJ
1726 ("--" "" vhdl-template-display-comment-hook 0 t)
1727 ("abs" "" vhdl-template-default-hook 0 t)
1728 ("access" "" vhdl-template-default-hook 0 t)
1729 ("after" "" vhdl-template-default-hook 0 t)
1730 ("alias" "" vhdl-template-alias-hook 0 t)
1731 ("all" "" vhdl-template-default-hook 0 t)
1732 ("and" "" vhdl-template-default-hook 0 t)
1733 ("arch" "" vhdl-template-architecture-hook 0 t)
1734 ("architecture" "" vhdl-template-architecture-hook 0 t)
1735 ("array" "" vhdl-template-default-hook 0 t)
1736 ("assert" "" vhdl-template-assert-hook 0 t)
1737 ("attr" "" vhdl-template-attribute-hook 0 t)
1738 ("attribute" "" vhdl-template-attribute-hook 0 t)
1739 ("begin" "" vhdl-template-default-indent-hook 0 t)
1740 ("block" "" vhdl-template-block-hook 0 t)
1741 ("body" "" vhdl-template-default-hook 0 t)
1742 ("buffer" "" vhdl-template-default-hook 0 t)
1743 ("bus" "" vhdl-template-default-hook 0 t)
1744 ("case" "" vhdl-template-case-hook 0 t)
1745 ("comp" "" vhdl-template-component-hook 0 t)
1746 ("component" "" vhdl-template-component-hook 0 t)
1747 ("cond" "" vhdl-template-conditional-signal-asst-hook 0 t)
1748 ("conditional" "" vhdl-template-conditional-signal-asst-hook 0 t)
1749 ("conf" "" vhdl-template-configuration-hook 0 t)
1750 ("configuration" "" vhdl-template-configuration-hook 0 t)
1751 ("cons" "" vhdl-template-constant-hook 0 t)
1752 ("constant" "" vhdl-template-constant-hook 0 t)
1753 ("disconnect" "" vhdl-template-disconnect-hook 0 t)
1754 ("downto" "" vhdl-template-default-hook 0 t)
1755 ("else" "" vhdl-template-else-hook 0 t)
1756 ("elseif" "" vhdl-template-elsif-hook 0 t)
1757 ("elsif" "" vhdl-template-elsif-hook 0 t)
1758 ("end" "" vhdl-template-default-indent-hook 0 t)
1759 ("entity" "" vhdl-template-entity-hook 0 t)
1760 ("exit" "" vhdl-template-exit-hook 0 t)
1761 ("file" "" vhdl-template-file-hook 0 t)
1762 ("for" "" vhdl-template-for-hook 0 t)
1763 ("func" "" vhdl-template-function-hook 0 t)
1764 ("function" "" vhdl-template-function-hook 0 t)
1765 ("generic" "" vhdl-template-generic-hook 0 t)
1766 ("group" "" vhdl-template-group-hook 0 t)
1767 ("guarded" "" vhdl-template-default-hook 0 t)
1768 ("if" "" vhdl-template-if-hook 0 t)
1769 ("impure" "" vhdl-template-default-hook 0 t)
1770 ("in" "" vhdl-template-default-hook 0 t)
1771 ("inertial" "" vhdl-template-default-hook 0 t)
1772 ("inout" "" vhdl-template-default-hook 0 t)
1773 ("inst" "" vhdl-template-instance-hook 0 t)
1774 ("instance" "" vhdl-template-instance-hook 0 t)
1775 ("is" "" vhdl-template-default-hook 0 t)
1776 ("label" "" vhdl-template-default-hook 0 t)
1777 ("library" "" vhdl-template-library-hook 0 t)
1778 ("linkage" "" vhdl-template-default-hook 0 t)
1779 ("literal" "" vhdl-template-default-hook 0 t)
1780 ("loop" "" vhdl-template-bare-loop-hook 0 t)
1781 ("map" "" vhdl-template-map-hook 0 t)
1782 ("mod" "" vhdl-template-default-hook 0 t)
1783 ("nand" "" vhdl-template-default-hook 0 t)
1784 ("new" "" vhdl-template-default-hook 0 t)
1785 ("next" "" vhdl-template-next-hook 0 t)
1786 ("nor" "" vhdl-template-default-hook 0 t)
1787 ("not" "" vhdl-template-default-hook 0 t)
1788 ("null" "" vhdl-template-default-hook 0 t)
1789 ("of" "" vhdl-template-default-hook 0 t)
1790 ("on" "" vhdl-template-default-hook 0 t)
1791 ("open" "" vhdl-template-default-hook 0 t)
1792 ("or" "" vhdl-template-default-hook 0 t)
1793 ("others" "" vhdl-template-default-hook 0 t)
1794 ("out" "" vhdl-template-default-hook 0 t)
1795 ("pack" "" vhdl-template-package-hook 0 t)
1796 ("package" "" vhdl-template-package-hook 0 t)
1797 ("port" "" vhdl-template-port-hook 0 t)
1798 ("postponed" "" vhdl-template-default-hook 0 t)
1799 ("procedure" "" vhdl-template-procedure-hook 0 t)
1800 ("process" "" vhdl-template-process-hook 0 t)
1801 ("pure" "" vhdl-template-default-hook 0 t)
1802 ("range" "" vhdl-template-default-hook 0 t)
1803 ("record" "" vhdl-template-default-hook 0 t)
1804 ("register" "" vhdl-template-default-hook 0 t)
1805 ("reject" "" vhdl-template-default-hook 0 t)
1806 ("rem" "" vhdl-template-default-hook 0 t)
1807 ("report" "" vhdl-template-report-hook 0 t)
1808 ("return" "" vhdl-template-return-hook 0 t)
1809 ("rol" "" vhdl-template-default-hook 0 t)
1810 ("ror" "" vhdl-template-default-hook 0 t)
1811 ("select" "" vhdl-template-selected-signal-asst-hook 0 t)
1812 ("severity" "" vhdl-template-default-hook 0 t)
1813 ("shared" "" vhdl-template-default-hook 0 t)
1814 ("sig" "" vhdl-template-signal-hook 0 t)
1815 ("signal" "" vhdl-template-signal-hook 0 t)
1816 ("sla" "" vhdl-template-default-hook 0 t)
1817 ("sll" "" vhdl-template-default-hook 0 t)
1818 ("sra" "" vhdl-template-default-hook 0 t)
1819 ("srl" "" vhdl-template-default-hook 0 t)
1820 ("subtype" "" vhdl-template-subtype-hook 0 t)
1821 ("then" "" vhdl-template-default-hook 0 t)
1822 ("to" "" vhdl-template-default-hook 0 t)
1823 ("transport" "" vhdl-template-default-hook 0 t)
1824 ("type" "" vhdl-template-type-hook 0 t)
1825 ("unaffected" "" vhdl-template-default-hook 0 t)
1826 ("units" "" vhdl-template-default-hook 0 t)
1827 ("until" "" vhdl-template-default-hook 0 t)
1828 ("use" "" vhdl-template-use-hook 0 t)
1829 ("var" "" vhdl-template-variable-hook 0 t)
1830 ("variable" "" vhdl-template-variable-hook 0 t)
1831 ("wait" "" vhdl-template-wait-hook 0 t)
1832 ("when" "" vhdl-template-when-hook 0 t)
1833 ("while" "" vhdl-template-while-loop-hook 0 t)
1834 ("with" "" vhdl-template-with-hook 0 t)
1835 ("xnor" "" vhdl-template-default-hook 0 t)
1836 ("xor" "" vhdl-template-default-hook 0 t)
5eabfe72
KH
1837 ))
1838 ;; VHDL-AMS keywords
1839 (when (and (memq 'vhdl vhdl-electric-keywords) (vhdl-standard-p 'ams))
1840 '(
610e1e80
PJ
1841 ("across" "" vhdl-template-default-hook 0 t)
1842 ("break" "" vhdl-template-break-hook 0 t)
1843 ("limit" "" vhdl-template-limit-hook 0 t)
1844 ("nature" "" vhdl-template-nature-hook 0 t)
1845 ("noise" "" vhdl-template-default-hook 0 t)
1846 ("procedural" "" vhdl-template-procedural-hook 0 t)
1847 ("quantity" "" vhdl-template-quantity-hook 0 t)
1848 ("reference" "" vhdl-template-default-hook 0 t)
1849 ("spectrum" "" vhdl-template-default-hook 0 t)
1850 ("subnature" "" vhdl-template-subnature-hook 0 t)
1851 ("terminal" "" vhdl-template-terminal-hook 0 t)
1852 ("through" "" vhdl-template-default-hook 0 t)
1853 ("tolerance" "" vhdl-template-default-hook 0 t)
5eabfe72
KH
1854 ))
1855 ;; user model keywords
1856 (when (memq 'user vhdl-electric-keywords)
1857 (let ((alist vhdl-model-alist)
1858 abbrev-list keyword)
1859 (while alist
1860 (setq keyword (nth 3 (car alist)))
1861 (unless (equal keyword "")
1862 (setq abbrev-list
1863 (cons (list keyword ""
1864 (vhdl-function-name
1865 "vhdl-model" (nth 0 (car alist)) "hook") 0)
1866 abbrev-list)))
1867 (setq alist (cdr alist)))
1868 abbrev-list)))))
1869
1870;; initialize abbrev table for VHDL Mode
1871(vhdl-mode-abbrev-table-init)
1872
1873;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1874;; Template completion lists
1875
1876(defvar vhdl-template-construct-alist nil
1877 "List of built-in construct templates.")
1878
1879(defun vhdl-template-construct-alist-init ()
1880 "Initialize `vhdl-template-construct-alist'."
1881 (setq
1882 vhdl-template-construct-alist
1883 (append
1884 '(
1885 ("alias declaration" vhdl-template-alias)
1886 ("architecture body" vhdl-template-architecture)
1887 ("assertion" vhdl-template-assert)
1888 ("attribute declaration" vhdl-template-attribute-decl)
1889 ("attribute specification" vhdl-template-attribute-spec)
1890 ("block configuration" vhdl-template-block-configuration)
1891 ("block statement" vhdl-template-block)
1892 ("case statement" vhdl-template-case-is)
1893 ("component configuration" vhdl-template-component-conf)
1894 ("component declaration" vhdl-template-component-decl)
1895 ("component instantiation statement" vhdl-template-component-inst)
1896 ("conditional signal assignment" vhdl-template-conditional-signal-asst)
1897 ("configuration declaration" vhdl-template-configuration-decl)
1898 ("configuration specification" vhdl-template-configuration-spec)
1899 ("constant declaration" vhdl-template-constant)
1900 ("disconnection specification" vhdl-template-disconnect)
1901 ("entity declaration" vhdl-template-entity)
1902 ("exit statement" vhdl-template-exit)
1903 ("file declaration" vhdl-template-file)
1904 ("generate statement" vhdl-template-generate)
1905 ("generic clause" vhdl-template-generic)
1906 ("group declaration" vhdl-template-group-decl)
1907 ("group template declaration" vhdl-template-group-template)
1908 ("if statement" vhdl-template-if-then)
1909 ("library clause" vhdl-template-library)
1910 ("loop statement" vhdl-template-loop)
1911 ("next statement" vhdl-template-next)
1912 ("package declaration" vhdl-template-package-decl)
1913 ("package body" vhdl-template-package-body)
1914 ("port clause" vhdl-template-port)
1915 ("process statement" vhdl-template-process)
1916 ("report statement" vhdl-template-report)
1917 ("return statement" vhdl-template-return)
1918 ("selected signal assignment" vhdl-template-selected-signal-asst)
1919 ("signal declaration" vhdl-template-signal)
1920 ("subprogram declaration" vhdl-template-subprogram-decl)
1921 ("subprogram body" vhdl-template-subprogram-body)
1922 ("subtype declaration" vhdl-template-subtype)
1923 ("type declaration" vhdl-template-type)
1924 ("use clause" vhdl-template-use)
1925 ("variable declaration" vhdl-template-variable)
1926 ("wait statement" vhdl-template-wait)
1927 )
1928 (when (vhdl-standard-p 'ams)
1929 '(
1930 ("break statement" vhdl-template-break)
1931 ("nature declaration" vhdl-template-nature)
1932 ("quantity declaration" vhdl-template-quantity)
1933 ("simultaneous case statement" vhdl-template-case-use)
1934 ("simultaneous if statement" vhdl-template-if-use)
1935 ("simultaneous procedural statement" vhdl-template-procedural)
1936 ("step limit specification" vhdl-template-limit)
1937 ("subnature declaration" vhdl-template-subnature)
1938 ("terminal declaration" vhdl-template-terminal)
1939 )))))
d2ddb974 1940
5eabfe72
KH
1941;; initialize for VHDL Mode
1942(vhdl-template-construct-alist-init)
1943
1944(defvar vhdl-template-package-alist nil
1945 "List of built-in package templates.")
1946
1947(defun vhdl-template-package-alist-init ()
1948 "Initialize `vhdl-template-package-alist'."
1949 (setq
1950 vhdl-template-package-alist
1951 (append
1952 '(
1953 ("numeric_bit" vhdl-template-package-numeric-bit)
1954 ("numeric_std" vhdl-template-package-numeric-std)
1955 ("std_logic_1164" vhdl-template-package-std-logic-1164)
1956 ("std_logic_arith" vhdl-template-package-std-logic-arith)
1957 ("std_logic_misc" vhdl-template-package-std-logic-misc)
1958 ("std_logic_signed" vhdl-template-package-std-logic-signed)
1959 ("std_logic_textio" vhdl-template-package-std-logic-textio)
1960 ("std_logic_unsigned" vhdl-template-package-std-logic-unsigned)
1961 ("textio" vhdl-template-package-textio)
1962 )
1963 (when (vhdl-standard-p 'math)
1964 '(
1965 ("math_complex" vhdl-template-package-math-complex)
1966 ("math_real" vhdl-template-package-math-real)
1967 )))))
d2ddb974 1968
5eabfe72
KH
1969;; initialize for VHDL Mode
1970(vhdl-template-package-alist-init)
d2ddb974 1971
5eabfe72
KH
1972(defvar vhdl-template-directive-alist
1973 (append
1974 '(
1975 ("translate_on" vhdl-template-directive-translate-on)
1976 ("translate_off" vhdl-template-directive-translate-off)
1977 ("synthesis_on" vhdl-template-directive-synthesis-on)
1978 ("synthesis_off" vhdl-template-directive-synthesis-off)
1979 ))
1980 "List of built-in directive templates.")
d2ddb974 1981
5eabfe72
KH
1982
1983;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1984;;; Menues
1985;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1986
1987;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
1988;; VHDL menu (using `easy-menu.el')
1989
5eabfe72
KH
1990(defun vhdl-customize ()
1991 "Call the customize function with `vhdl' as argument."
1992 (interactive)
1993 (customize-browse 'vhdl))
1994
1995(defun vhdl-create-customize-menu ()
1996 "Create a full customization menu for VHDL, insert it into the menu."
1997 (interactive)
1998 (if (fboundp 'customize-menu-create)
1999 (easy-menu-change
2000 '("VHDL") "Customize"
2001 `(["Browse VHDL Group..." vhdl-customize t]
2002 ,(customize-menu-create 'vhdl)
2003 "--"
2004 ["Activate New Customizations" vhdl-activate-customizations t]))
2005 (error "Cannot expand menu (outdated version of cus-edit.el)")))
2006
2007(defun vhdl-create-mode-menu ()
2008 "Create VHDL Mode menu."
2009 (list
2010 "VHDL"
2011 '("Mode"
d2ddb974 2012 ["Electric" vhdl-electric-mode :style toggle :selected vhdl-electric-mode]
5eabfe72 2013 ["Stutter" vhdl-stutter-mode :style toggle :selected vhdl-stutter-mode]
d2ddb974 2014 )
5eabfe72
KH
2015 "--"
2016 (append
2017 '("Project"
2018 ["None" (vhdl-project-switch "")
2019 :style radio :selected (equal vhdl-project "")]
2020 "--"
2021 )
2022 ;; add menu entries for defined projects
2023 (let ((project-alist vhdl-project-alist) menu-alist name)
2024 (while project-alist
2025 (setq name (car (car project-alist)))
2026 (setq menu-alist (cons (vector name (list 'vhdl-project-switch name)
2027 :style 'radio :selected
2028 (list 'equal 'vhdl-project name))
2029 menu-alist))
2030 (setq project-alist (cdr project-alist)))
2031 (setq menu-alist (cons '["Add Project..."
2032 (customize-variable 'vhdl-project-alist) t]
2033 (cons "--" menu-alist)))
2034 (nreverse menu-alist)))
2035 "--"
2036 (list
2037 "Compile"
2038 ["Compile Buffer" vhdl-compile t]
2039 ["Stop Compilation" kill-compilation t]
2040 "--"
2041 ["Make" vhdl-make t]
2042 ["Generate Makefile" vhdl-generate-makefile t]
d2ddb974 2043 "--"
5eabfe72
KH
2044 ["Next Error" next-error t]
2045 ["Previous Error" previous-error t]
2046 ["First Error" first-error t]
2047 "--"
2048 (append
2049 '("Compiler")
2050 ;; add menu entries for defined compilers
2051 (let ((comp-alist vhdl-compiler-alist) menu-alist name)
2052 (while comp-alist
2053 (setq name (car (car comp-alist)))
2054 (setq menu-alist (cons (vector name (list 'setq 'vhdl-compiler name)
2055 :style 'radio :selected
2056 (list 'equal 'vhdl-compiler name))
2057 menu-alist))
2058 (setq comp-alist (cdr comp-alist)))
2059 (setq menu-alist (cons '["Add Compiler..."
2060 (customize-variable 'vhdl-compiler-alist) t]
2061 (cons "--" menu-alist)))
2062 (nreverse menu-alist))))
2063 "--"
2064 (append
2065 '("Template"
2066 ("VHDL Construct 1"
2067 ["Alias" vhdl-template-alias t]
2068 ["Architecture" vhdl-template-architecture t]
2069 ["Assert" vhdl-template-assert t]
2070 ["Attribute (Decl)" vhdl-template-attribute-decl t]
2071 ["Attribute (Spec)" vhdl-template-attribute-spec t]
2072 ["Block" vhdl-template-block t]
2073 ["Case" vhdl-template-case-is t]
2074 ["Component (Decl)" vhdl-template-component-decl t]
2075 ["(Component) Instance" vhdl-template-component-inst t]
2076 ["Conditional (Signal Asst)" vhdl-template-conditional-signal-asst t]
2077 ["Configuration (Block)"vhdl-template-block-configuration t]
2078 ["Configuration (Comp)" vhdl-template-component-conf t]
2079 ["Configuration (Decl)" vhdl-template-configuration-decl t]
2080 ["Configuration (Spec)" vhdl-template-configuration-spec t]
2081 ["Constant" vhdl-template-constant t]
2082 ["Disconnect" vhdl-template-disconnect t]
2083 ["Else" vhdl-template-else t]
2084 ["Elsif" vhdl-template-elsif t]
2085 ["Entity" vhdl-template-entity t]
2086 ["Exit" vhdl-template-exit t]
2087 ["File" vhdl-template-file t]
2088 ["For (Generate)" vhdl-template-for-generate t]
2089 ["For (Loop)" vhdl-template-for-loop t]
2090 ["Function (Body)" vhdl-template-function-body t]
2091 ["Function (Decl)" vhdl-template-function-decl t]
2092 ["Generic" vhdl-template-generic t]
2093 ["Group (Decl)" vhdl-template-group-decl t]
2094 ["Group (Template)" vhdl-template-group-template t]
2095 )
2096 ("VHDL Construct 2"
2097 ["If (Generate)" vhdl-template-if-generate t]
2098 ["If (Then)" vhdl-template-if-then t]
2099 ["Library" vhdl-template-library t]
2100 ["Loop" vhdl-template-bare-loop t]
2101 ["Map" vhdl-template-map t]
2102 ["Next" vhdl-template-next t]
2103 ["(Others)" vhdl-template-others t]
2104 ["Package (Decl)" vhdl-template-package-decl t]
2105 ["Package (Body)" vhdl-template-package-body t]
2106 ["Port" vhdl-template-port t]
2107 ["Procedure (Body)" vhdl-template-procedure-body t]
2108 ["Procedure (Decl)" vhdl-template-procedure-decl t]
2109 ["Process (Comb)" vhdl-template-process-comb t]
2110 ["Process (Seq)" vhdl-template-process-seq t]
2111 ["Report" vhdl-template-report t]
2112 ["Return" vhdl-template-return t]
2113 ["Select" vhdl-template-selected-signal-asst t]
2114 ["Signal" vhdl-template-signal t]
2115 ["Subtype" vhdl-template-subtype t]
2116 ["Type" vhdl-template-type t]
2117 ["Use" vhdl-template-use t]
2118 ["Variable" vhdl-template-variable t]
2119 ["Wait" vhdl-template-wait t]
2120 ["(Clocked Wait)" vhdl-template-clocked-wait t]
2121 ["When" vhdl-template-when t]
2122 ["While (Loop)" vhdl-template-while-loop t]
2123 ["With" vhdl-template-with t]
2124 ))
2125 (when (vhdl-standard-p 'ams)
2126 '(("VHDL-AMS Construct"
2127 ["Break" vhdl-template-break t]
2128 ["Case (Use)" vhdl-template-case-use t]
2129 ["If (Use)" vhdl-template-if-use t]
2130 ["Limit" vhdl-template-limit t]
2131 ["Nature" vhdl-template-nature t]
2132 ["Procedural" vhdl-template-procedural t]
2133 ["Quantity (Free)" vhdl-template-quantity-free t]
2134 ["Quantity (Branch)" vhdl-template-quantity-branch t]
2135 ["Quantity (Source)" vhdl-template-quantity-source t]
2136 ["Subnature" vhdl-template-subnature t]
2137 ["Terminal" vhdl-template-terminal t]
2138 )))
2139 '(["Insert Construct" vhdl-template-insert-construct
2140 :keys "C-c C-i C-c"]
2141 "--")
2142 (list
2143 (append
2144 '("Package")
2145 (when (vhdl-standard-p 'math)
2146 '(
2147 ["math_complex" vhdl-template-package-math-complex t]
2148 ["math_real" vhdl-template-package-math-real t]
2149 ))
2150 '(
2151 ["numeric_bit" vhdl-template-package-numeric-bit t]
2152 ["numeric_std" vhdl-template-package-numeric-std t]
2153 ["std_logic_1164" vhdl-template-package-std-logic-1164 t]
2154 ["textio" vhdl-template-package-textio t]
2155 "--"
2156 ["std_logic_arith" vhdl-template-package-std-logic-arith t]
2157 ["std_logic_signed" vhdl-template-package-std-logic-signed t]
2158 ["std_logic_unsigned" vhdl-template-package-std-logic-unsigned t]
2159 ["std_logic_misc" vhdl-template-package-std-logic-misc t]
2160 ["std_logic_textio" vhdl-template-package-std-logic-textio t]
2161 "--"
2162 ["Insert Package" vhdl-template-insert-package
2163 :keys "C-c C-i C-p"]
2164 )))
2165 '(("Directive"
2166 ["translate_on" vhdl-template-directive-translate-on t]
2167 ["translate_off" vhdl-template-directive-translate-off t]
2168 ["synthesis_on" vhdl-template-directive-synthesis-on t]
2169 ["synthesis_off" vhdl-template-directive-synthesis-off t]
2170 "--"
2171 ["Insert Directive" vhdl-template-insert-directive
2172 :keys "C-c C-i C-d"]
2173 )
2174 "--"
2175 ["Insert Header" vhdl-template-header :keys "C-c C-t C-h"]
2176 ["Insert Footer" vhdl-template-footer t]
2177 ["Insert Date" vhdl-template-insert-date t]
2178 ["Modify Date" vhdl-template-modify :keys "C-c C-t C-m"]
2179 "--"
2180 ["Query Next Prompt" vhdl-template-search-prompt t]
2181 ))
2182 (append
2183 '("Model")
2184 ;; add menu entries for defined models
2185 (let ((model-alist vhdl-model-alist) menu-alist model)
2186 (while model-alist
2187 (setq model (car model-alist))
2188 (setq menu-alist
2189 (cons (vector
2190 (nth 0 model)
2191 (vhdl-function-name "vhdl-model" (nth 0 model))
2192 :keys (concat "C-c C-m " (key-description (nth 2 model))))
2193 menu-alist))
2194 (setq model-alist (cdr model-alist)))
2195 (setq menu-alist
2196 (append
2197 (nreverse menu-alist)
2198 '("--"
2199 ["Insert Model" vhdl-model-insert :keys "C-c C-i C-m"]
2200 ["Add Model..." (customize-variable 'vhdl-model-alist) t])))
2201 menu-alist))
2202 '("Port"
2203 ["Copy" vhdl-port-copy t]
d2ddb974 2204 "--"
5eabfe72
KH
2205 ["Paste As Entity" vhdl-port-paste-entity vhdl-port-list]
2206 ["Paste As Component" vhdl-port-paste-component vhdl-port-list]
2207 ["Paste As Instance" vhdl-port-paste-instance
2208 :keys "C-c C-p C-i" :active vhdl-port-list]
2209 ["Paste As Signals" vhdl-port-paste-signals vhdl-port-list]
2210 ["Paste As Constants" vhdl-port-paste-constants vhdl-port-list]
2211 ["Paste As Generic Map" vhdl-port-paste-generic-map vhdl-port-list]
2212 ["Paste As Test Bench" vhdl-port-paste-testbench vhdl-port-list]
d2ddb974 2213 "--"
5eabfe72 2214 ["Flatten" vhdl-port-flatten vhdl-port-list]
d2ddb974 2215 )
5eabfe72
KH
2216 "--"
2217 '("Comment"
2218 ["(Un)Comment Out Region" vhdl-comment-uncomment-region (mark)]
2219 "--"
2220 ["Insert Inline Comment" vhdl-comment-append-inline t]
2221 ["Insert Horizontal Line" vhdl-comment-display-line t]
2222 ["Insert Display Comment" vhdl-comment-display t]
2223 "--"
2224 ["Fill Comment" fill-paragraph t]
2225 ["Fill Comment Region" fill-region (mark)]
2226 ["Kill Comment Region" vhdl-comment-kill-region (mark)]
2227 ["Kill Inline Comment Region" vhdl-comment-kill-inline-region (mark)]
2228 )
2229 '("Line"
2230 ["Kill" vhdl-line-kill t]
2231 ["Copy" vhdl-line-copy t]
2232 ["Yank" vhdl-line-yank t]
2233 ["Expand" vhdl-line-expand t]
2234 "--"
2235 ["Transpose Next" vhdl-line-transpose-next t]
2236 ["Transpose Prev" vhdl-line-transpose-previous t]
2237 ["Open" vhdl-line-open t]
2238 ["Join" delete-indentation t]
2239 "--"
2240 ["Goto" goto-line t]
2241 ["(Un)Comment Out" vhdl-comment-uncomment-line t]
d2ddb974 2242 )
5eabfe72
KH
2243 '("Move"
2244 ["Forward Statement" vhdl-end-of-statement t]
2245 ["Backward Statement" vhdl-beginning-of-statement t]
2246 ["Forward Expression" vhdl-forward-sexp t]
2247 ["Backward Expression" vhdl-backward-sexp t]
2248 ["Forward Function" vhdl-end-of-defun t]
2249 ["Backward Function" vhdl-beginning-of-defun t]
2250 ["Mark Function" vhdl-mark-defun t]
d2ddb974 2251 )
5eabfe72
KH
2252 "--"
2253 '("Indent"
2254 ["Line" vhdl-indent-line t]
2255 ["Region" vhdl-indent-region (mark)]
2256 ["Buffer" vhdl-indent-buffer t]
d2ddb974 2257 )
5eabfe72
KH
2258 '("Align"
2259 ["Group" vhdl-align-group t]
2260 ["Region" vhdl-align-noindent-region (mark)]
2261 ["Buffer" vhdl-align-noindent-buffer t]
2262 "--"
2263 ["Inline Comment Group" vhdl-align-inline-comment-group t]
2264 ["Inline Comment Region" vhdl-align-inline-comment-region (mark)]
2265 ["Inline Comment Buffer" vhdl-align-inline-comment-buffer t]
2266 "--"
2267 ["Fixup Whitespace Region" vhdl-fixup-whitespace-region (mark)]
2268 ["Fixup Whitespace Buffer" vhdl-fixup-whitespace-buffer t]
d2ddb974 2269 )
5eabfe72
KH
2270 '("Fix Case"
2271 ["Region" vhdl-fix-case-region (mark)]
2272 ["Buffer" vhdl-fix-case-buffer t]
d2ddb974 2273 )
5eabfe72
KH
2274 '("Beautify"
2275 ["Beautify Region" vhdl-beautify-region (mark)]
2276 ["Beautify Buffer" vhdl-beautify-buffer t]
d2ddb974 2277 )
5eabfe72
KH
2278 "--"
2279 ["Fontify Buffer" vhdl-fontify-buffer t]
2280 ["Syntactic Info" vhdl-show-syntactic-information t]
2281 "--"
2282 '("Documentation"
2283 ["VHDL Mode" vhdl-doc-mode :keys "C-c C-h"]
2284 ["Reserved Words" (vhdl-doc-variable 'vhdl-doc-keywords) t]
2285 ["Coding Style" (vhdl-doc-variable 'vhdl-doc-coding-style) t]
d2ddb974 2286 )
5eabfe72
KH
2287 ["Version" vhdl-version t]
2288 ["Bug Report..." vhdl-submit-bug-report t]
2289 "--"
2290 '("Speedbar"
2291 ["Open/Close" vhdl-speedbar t]
d2ddb974 2292 "--"
5eabfe72
KH
2293 ["Show Hierarchy" vhdl-speedbar-toggle-hierarchy
2294 :style toggle
2295 :selected
2296 (and (boundp 'speedbar-initial-expansion-list-name)
2297 (equal speedbar-initial-expansion-list-name "vhdl hierarchy"))
2298 :active (and (boundp 'speedbar-frame) speedbar-frame)]
2299 )
2300 "--"
2301 '("Customize"
2302 ["Browse VHDL Group..." vhdl-customize t]
2303 ["Build Customize Menu" vhdl-create-customize-menu
2304 (fboundp 'customize-menu-create)]
d2ddb974 2305 "--"
5eabfe72
KH
2306 ["Activate New Customizations" vhdl-activate-customizations t])
2307 ))
2308
2309(defvar vhdl-mode-menu-list (vhdl-create-mode-menu)
2310 "VHDL Mode menu.")
2311
2312(defun vhdl-update-mode-menu ()
2313 "Update VHDL mode menu."
2314 (interactive)
2315 (easy-menu-remove vhdl-mode-menu-list) ; for XEmacs
2316 (setq vhdl-mode-menu-list (vhdl-create-mode-menu))
2317 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2318 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2319 "Menu keymap for VHDL Mode." vhdl-mode-menu-list))
d2ddb974
KH
2320
2321(require 'easymenu)
2322
5eabfe72
KH
2323;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2324;; Index menu (using `imenu.el'), also used for speedbar (using `speedbar.el')
d2ddb974
KH
2325
2326(defvar vhdl-imenu-generic-expression
2327 '(
5eabfe72
KH
2328 ("Subprogram"
2329 "^\\s-*\\(\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\s-+\\(\"?\\(\\w\\|\\s_\\)+\"?\\)"
2330 4)
2331 ("Instance"
2332 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\s-*:\\(\\s-\\|\n\\)*\\(\\w\\|\\s_\\)+\\)\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>"
2333 1)
2334 ("Component"
2335 "^\\s-*\\(component\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
d2ddb974 2336 2)
5eabfe72
KH
2337 ("Procedural"
2338 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(procedural\\)"
2339 1)
2340 ("Process"
2341 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\(postponed\\s-+\\|\\)process\\)"
2342 1)
2343 ("Block"
2344 "^\\s-*\\(\\(\\w\\|\\s_\\)+\\)\\s-*:\\(\\s-\\|\n\\)*\\(block\\)"
2345 1)
2346 ("Package"
2347 "^\\s-*\\(package\\( body\\|\\)\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
2348 3)
d2ddb974
KH
2349 ("Configuration"
2350 "^\\s-*\\(configuration\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
2351 2)
5eabfe72
KH
2352 ("Architecture"
2353 "^\\s-*\\(architecture\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\s-+of\\s-+\\(\\w\\|\\s_\\)+\\)"
d2ddb974 2354 2)
5eabfe72
KH
2355 ("Entity"
2356 "^\\s-*\\(entity\\)\\s-+\\(\\(\\w\\|\\s_\\)+\\)"
d2ddb974 2357 2)
d2ddb974
KH
2358 )
2359 "Imenu generic expression for VHDL Mode. See `imenu-generic-expression'.")
2360
5eabfe72
KH
2361(defun vhdl-index-menu-init ()
2362 "Initialize index menu."
2363 (set (make-local-variable 'imenu-case-fold-search) t)
2364 (set (make-local-variable 'imenu-generic-expression)
2365 vhdl-imenu-generic-expression)
2366 (when (and vhdl-index-menu (not (string-match "XEmacs" emacs-version)))
2367 (if (or (not (boundp 'font-lock-maximum-size))
2368 (> font-lock-maximum-size (buffer-size)))
2369 (imenu-add-to-menubar "Index")
2370 (message "Scanning buffer for index...buffer too big"))))
d2ddb974
KH
2371
2372;; ############################################################################
2373;; Source file menu (using `easy-menu.el')
2374
5eabfe72
KH
2375(defvar vhdl-sources-menu nil)
2376
2377(defun vhdl-directory-files (directory &optional full match)
2378 "Call `directory-files' if DIRECTORY exists, otherwise generate error
2379message."
2380 (if (file-directory-p directory)
2381 (directory-files directory full match)
2382 (message "No such directory: \"%s\"" directory)
2383 nil))
2384
2385(defun vhdl-get-source-files (&optional full directory)
2386 "Get list of VHDL source files in DIRECTORY or current directory."
2387 (let ((mode-alist auto-mode-alist)
2388 filename-regexp)
2389 ;; create regular expressions for matching file names
2390 (setq filename-regexp ".*\\(")
2391 (while mode-alist
2392 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
2393 (setq filename-regexp
2394 (concat filename-regexp (car (car mode-alist)) "\\|")))
2395 (setq mode-alist (cdr mode-alist)))
2396 (setq filename-regexp
2397 (concat (substring filename-regexp 0
2398 (string-match "\\\\|$" filename-regexp)) "\\)"))
2399 ;; find files
2400 (nreverse (vhdl-directory-files
2401 (or directory default-directory) full filename-regexp))))
d2ddb974
KH
2402
2403(defun vhdl-add-source-files-menu ()
5eabfe72
KH
2404 "Scan directory for all VHDL source files and generate menu.
2405The directory of the current source file is scanned."
d2ddb974
KH
2406 (interactive)
2407 (message "Scanning directory for source files ...")
5eabfe72
KH
2408 (let ((newmap (current-local-map))
2409 (mode-alist auto-mode-alist)
2410 (file-list (vhdl-get-source-files))
2411 menu-list found)
2412 ;; Create list for menu
2413 (setq found nil)
2414 (while file-list
2415 (setq found t)
2416 (setq menu-list (cons (vector (car file-list)
2417 (list 'find-file (car file-list)) t)
2418 menu-list))
2419 (setq file-list (cdr file-list)))
2420 (setq menu-list (vhdl-menu-split menu-list 25))
2421 (when found (setq menu-list (cons "--" menu-list)))
2422 (setq menu-list (cons ["*Rescan*" vhdl-add-source-files-menu t] menu-list))
2423 (setq menu-list (cons "Sources" menu-list))
d2ddb974 2424 ;; Create menu
5eabfe72
KH
2425 (easy-menu-add menu-list)
2426 (easy-menu-define vhdl-sources-menu newmap
2427 "VHDL source files menu" menu-list))
d2ddb974
KH
2428 (message ""))
2429
2430(defun vhdl-menu-split (list n)
5eabfe72 2431 "Split menu LIST into several submenues, if number of elements > N."
d2ddb974
KH
2432 (if (> (length list) n)
2433 (let ((remain list)
2434 (result '())
2435 (sublist '())
2436 (menuno 1)
2437 (i 0))
2438 (while remain
2439 (setq sublist (cons (car remain) sublist))
2440 (setq remain (cdr remain))
2441 (setq i (+ i 1))
2442 (if (= i n)
2443 (progn
2444 (setq result (cons (cons (format "Sources %s" menuno)
2445 (nreverse sublist)) result))
2446 (setq i 0)
2447 (setq menuno (+ menuno 1))
2448 (setq sublist '()))))
2449 (and sublist
2450 (setq result (cons (cons (format "Sources %s" menuno)
2451 (nreverse sublist)) result)))
2452 (nreverse result))
2453 list))
2454
2455
5eabfe72
KH
2456;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2457;;; VHDL Mode definition
2458;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2459;; performs all buffer local initializations
2460
1c36bac6 2461;;;###autoload
d2ddb974
KH
2462(defun vhdl-mode ()
2463 "Major mode for editing VHDL code.
2464
2465Usage:
2466------
2467
5eabfe72
KH
2468- TEMPLATE INSERTION (electrification): After typing a VHDL keyword and
2469 entering `\\[vhdl-electric-space]', you are prompted for arguments while a template is generated
2470 for that VHDL construct. Typing `\\[vhdl-electric-return]' or `\\[keyboard-quit]' at the first (mandatory)
2471 prompt aborts the current template generation. Optional arguments are
2472 indicated by square brackets and removed if the queried string is left empty.
2473 Prompts for mandatory arguments remain in the code if the queried string is
2474 left empty. They can be queried again by `\\[vhdl-template-search-prompt]'.
2475 Typing `\\[just-one-space]' after a keyword inserts a space without calling the template
2476 generator. Automatic template generation (i.e. electrification) can be
2477 disabled (enabled) by typing `\\[vhdl-electric-mode]' or by setting custom variable
2478 `vhdl-electric-mode' (see CUSTOMIZATION).
2479 Enabled electrification is indicated by `/e' in the modeline.
2480 Template generators can be invoked from the VHDL menu, by key bindings, by
2481 typing `C-c C-i C-c' and choosing a construct, or by typing the keyword (i.e.
2482 first word of menu entry not in parenthesis) and `\\[vhdl-electric-space]'.
2483 The following abbreviations can also be used:
2484 arch, attr, cond, conf, comp, cons, func, inst, pack, sig, var.
2485 Template styles can be customized in customization group `vhdl-electric'
2486 \(see CUSTOMIZATION).
2487
2488- HEADER INSERTION: A file header can be inserted by `\\[vhdl-template-header]'. A
2489 file footer (template at the end of the file) can be inserted by
2490 `\\[vhdl-template-footer]'. See customization group `vhdl-header'.
2491
2492- STUTTERING: Double striking of some keys inserts cumbersome VHDL syntax
2493 elements. Stuttering can be disabled (enabled) by typing `\\[vhdl-stutter-mode]' or by
2494 variable `vhdl-stutter-mode'. Enabled stuttering is indicated by `/s' in
2495 the modeline. The stuttering keys and their effects are:
2496 ;; --> \" : \" [ --> ( -- --> comment
2497 ;;; --> \" := \" [[ --> [ --CR --> comment-out code
2498 .. --> \" => \" ] --> ) --- --> horizontal line
2499 ,, --> \" <= \" ]] --> ] ---- --> display comment
2500 == --> \" == \" '' --> \\\"
2501
2502- WORD COMPLETION: Typing `\\[vhdl-electric-tab]' after a (not completed) word looks for a VHDL
2503 keyword or a word in the buffer that starts alike, inserts it and adjusts
2504 case. Re-typing `\\[vhdl-electric-tab]' toggles through alternative word completions.
2505 This also works in the minibuffer (i.e. in template generator prompts).
2506 Typing `\\[vhdl-electric-tab]' after `(' looks for and inserts complete parenthesized
2507 expressions (e.g. for array index ranges). All keywords as well as standard
2508 types and subprograms of VHDL have predefined abbreviations (e.g. type \"std\"
2509 and `\\[vhdl-electric-tab]' will toggle through all standard types beginning with \"std\").
2510
2511 Typing `\\[vhdl-electric-tab]' after a non-word character indents the line if at the beginning
2512 of a line (i.e. no preceding non-blank characters),and inserts a tabulator
2513 stop otherwise. `\\[tab-to-tab-stop]' always inserts a tabulator stop.
2514
2515- COMMENTS:
d2ddb974
KH
2516 `--' puts a single comment.
2517 `---' draws a horizontal line for separating code segments.
2518 `----' inserts a display comment, i.e. two horizontal lines with a
2519 comment in between.
5eabfe72 2520 `--CR' comments out code on that line. Re-hitting CR comments out
d2ddb974 2521 following lines.
5eabfe72
KH
2522 `\\[vhdl-comment-uncomment-region]' comments out a region if not commented out,
2523 uncomments a region if already commented out.
d2ddb974
KH
2524
2525 You are prompted for comments after object definitions (i.e. signals,
2526 variables, constants, ports) and after subprogram and process specifications
5eabfe72
KH
2527 if variable `vhdl-prompt-for-comments' is non-nil. Comments are
2528 automatically inserted as additional labels (e.g. after begin statements) and
2529 as help comments if `vhdl-self-insert-comments' is non-nil.
d2ddb974 2530 Inline comments (i.e. comments after a piece of code on the same line) are
5eabfe72
KH
2531 indented at least to `vhdl-inline-comment-column'. Comments go at maximum to
2532 `vhdl-end-comment-column'. `\\[vhdl-electric-return]' after a space in a comment will open a
2533 new comment line. Typing beyond `vhdl-end-comment-column' in a comment
2534 automatically opens a new comment line. `\\[fill-paragraph]' re-fills
2535 multi-line comments.
d2ddb974 2536
5eabfe72 2537- INDENTATION: `\\[vhdl-electric-tab]' indents a line if at the beginning of the line.
d2ddb974 2538 The amount of indentation is specified by variable `vhdl-basic-offset'.
5eabfe72
KH
2539 `\\[vhdl-indent-line]' always indents the current line (is bound to `TAB' if variable
2540 `vhdl-intelligent-tab' is nil). Indentation can be done for an entire region
2541 \(`\\[vhdl-indent-region]') or buffer (menu). Argument and port lists are indented normally
2542 \(nil) or relative to the opening parenthesis (non-nil) according to variable
2543 `vhdl-argument-list-indent'. If variable `vhdl-indent-tabs-mode' is nil,
2544 spaces are used instead of tabs. `\\[tabify]' and `\\[untabify]' allow
2545 to convert spaces to tabs and vice versa.
2546
2547- ALIGNMENT: The alignment functions align operators, keywords, and inline
2548 comment to beautify argument lists, port maps, etc. `\\[vhdl-align-group]' aligns a group
2549 of consecutive lines separated by blank lines. `\\[vhdl-align-noindent-region]' aligns an
2550 entire region. If variable `vhdl-align-groups' is non-nil, groups of code
2551 lines separated by empty lines are aligned individually. `\\[vhdl-align-inline-comment-group]' aligns
2552 inline comments for a group of lines, and `\\[vhdl-align-inline-comment-region]' for a region.
2553 Some templates are automatically aligned after generation if custom variable
2554 `vhdl-auto-align' is non-nil.
2555 `\\[vhdl-fixup-whitespace-region]' fixes up whitespace in a region. That is, operator symbols
2556 are surrounded by one space, and multiple spaces are eliminated.
2557
2558- PORT TRANSLATION: Generic and port clauses from entity or component
2559 declarations can be copied (`\\[vhdl-port-copy]') and pasted as entity and
2560 component declarations, as component instantiations and corresponding
2561 internal constants and signals, as a generic map with constants as actual
2562 parameters, and as a test bench (menu).
2563 A clause with several generic/port names on the same line can be flattened
2564 (`\\[vhdl-port-flatten]') so that only one name per line exists. Names for actual
2565 ports, instances, test benches, and design-under-test instances can be
2566 derived from existing names according to variables `vhdl-...-name'.
2567 Variables `vhdl-testbench-...' allow the insertion of additional templates
2568 into a test bench. New files are created for the test bench entity and
2569 architecture according to variable `vhdl-testbench-create-files'.
2570 See customization group `vhdl-port'.
2571
2572- TEST BENCH GENERATION: See PORT TRANSLATION.
2573
2574- KEY BINDINGS: Key bindings (`C-c ...') exist for most commands (see in
2575 menu).
2576
2577- VHDL MENU: All commands can be invoked from the VHDL menu.
2578
2579- FILE BROWSER: The speedbar allows browsing of directories and file contents.
2580 It can be accessed from the VHDL menu and is automatically opened if
2581 variable `vhdl-speedbar' is non-nil.
2582 In speedbar, open files and directories with `mouse-2' on the name and
2583 browse/rescan their contents with `mouse-2'/`S-mouse-2' on the `+'.
2584
2585- DESIGN HIERARCHY BROWSER: The speedbar can also be used for browsing the
2586 hierarchy of design units contained in the source files of the current
2587 directory or in the source files/directories specified for a project (see
2588 variable `vhdl-project-alist').
2589 The speedbar can be switched between file and hierarchy browsing mode in the
2590 VHDL menu or by typing `f' and `h' in speedbar.
2591 In speedbar, open design units with `mouse-2' on the name and browse their
2592 hierarchy with `mouse-2' on the `+'. The hierarchy can be rescanned and
2593 ports directly be copied from entities by using the speedbar menu.
2594
2595- PROJECTS: Projects can be defined in variable `vhdl-project-alist' and a
2596 current project be selected using variable `vhdl-project' (permanently) or
2597 from the menu (temporarily). For each project, a title string (for the file
2598 headers) and source files/directories (for the hierarchy browser) can be
2599 specified.
2600
2601- SPECIAL MENUES: As an alternative to the speedbar, an index menu can
2602 be added (set variable `vhdl-index-menu' to non-nil) or made accessible
2603 as a mouse menu (e.g. add \"(global-set-key '[S-down-mouse-3] 'imenu)\" to
2604 your start-up file) for browsing the file contents. Also, a source file menu
2605 can be added (set variable `vhdl-source-file-menu' to non-nil) for browsing
2606 the current directory for VHDL source files.
2607
2608- SOURCE FILE COMPILATION: The syntax of the current buffer can be analyzed
2609 by calling a VHDL compiler (menu, `\\[vhdl-compile]'). The compiler to be used is
2610 specified by variable `vhdl-compiler'. The available compilers are listed
2611 in variable `vhdl-compiler-alist' including all required compilation command,
2612 destination directory, and error message syntax information. New compilers
2613 can be added. Additional compile command options can be set in variable
2614 `vhdl-compiler-options'.
2615 An entire hierarchy of source files can be compiled by the `make' command
2616 \(menu, `\\[vhdl-make]'). This only works if an appropriate Makefile exists.
2617 The make command itself as well as a command to generate a Makefile can also
2618 be specified in variable `vhdl-compiler-alist'.
2619
2620- VHDL STANDARDS: The VHDL standards to be used are specified in variable
2621 `vhdl-standard'. Available standards are: VHDL'87/'93, VHDL-AMS,
2622 Math Packages.
2623
2624- KEYWORD CASE: Lower and upper case for keywords and standardized types,
2625 attributes, and enumeration values is supported. If the variable
2626 `vhdl-upper-case-keywords' is set to non-nil, keywords can be typed in lower
2627 case and are converted into upper case automatically (not for types,
2628 attributes, and enumeration values). The case of keywords, types,
2629 attributes,and enumeration values can be fixed for an entire region (menu)
d2ddb974
KH
2630 or buffer (`\\[vhdl-fix-case-buffer]') according to the variables
2631 `vhdl-upper-case-{keywords,types,attributes,enum-values}'.
2632
5eabfe72
KH
2633- HIGHLIGHTING (fontification): Keywords and standardized types, attributes,
2634 enumeration values, and function names (controlled by variable
d2ddb974 2635 `vhdl-highlight-keywords'), as well as comments, strings, and template
5eabfe72
KH
2636 prompts are highlighted using different colors. Unit, subprogram, signal,
2637 variable, constant, parameter and generic/port names in declarations as well
2638 as labels are highlighted if variable `vhdl-highlight-names' is non-nil.
2639
2640 Additional reserved words or words with a forbidden syntax (e.g. words that
2641 should be avoided) can be specified in variable `vhdl-forbidden-words' or
2642 `vhdl-forbidden-syntax' and be highlighted in a warning color (variable
2643 `vhdl-highlight-forbidden-words'). Verilog keywords are highlighted as
2644 forbidden words if variable `vhdl-highlight-verilog-keywords' is non-nil.
2645
2646 Words with special syntax can be highlighted by specifying their syntax and
2647 color in variable `vhdl-special-syntax-alist' and by setting variable
2648 `vhdl-highlight-special-words' to non-nil. This allows to establish some
2649 naming conventions (e.g. to distinguish different kinds of signals or other
2650 objects by using name suffices) and to support them visually.
2651
2652 Variable `vhdl-highlight-case-sensitive' can be set to non-nil in order to
2653 support case-sensitive highlighting. However, keywords are then only
2654 highlighted if written in lower case.
2655
2656 Code between \"translate_off\" and \"translate_on\" pragmas is highlighted
2657 using a different background color if variable `vhdl-highlight-translate-off'
2658 is non-nil.
2659
2660 All colors can be customized by command `\\[customize-face]'.
2661 For highlighting of matching parenthesis, see customization group
2662 `paren-showing' (`\\[customize-group]').
2663
2664- USER MODELS: VHDL models (templates) can be specified by the user and made
2665 accessible in the menu, through key bindings (`C-c C-m ...'), or by keyword
2666 electrification. See custom variable `vhdl-model-alist'.
2667
2668- HIDE/SHOW: The code of entire VHDL design units can be hidden using the
2669 `Hide/Show' menu or by pressing `S-mouse-2' within the code (variable
2670 `vhdl-hideshow-menu').
2671
2672- PRINTING: Postscript printing with different faces (an optimized set of
2673 faces is used if `vhdl-print-customize-faces' is non-nil) or colors
2674 \(if `ps-print-color-p' is non-nil) is possible using the standard Emacs
2675 postscript printing commands. Variable `vhdl-print-two-column' defines
2676 appropriate default settings for nice landscape two-column printing. The
2677 paper format can be set by variable `ps-paper-type'. Do not forget to
2678 switch `ps-print-color-p' to nil for printing on black-and-white printers.
2679
2680- CUSTOMIZATION: All variables can easily be customized using the `Customize'
2681 menu entry or `\\[customize-option]' (`\\[customize-group]' for groups).
2682 Some customizations only take effect after some action (read the NOTE in
2683 the variable documentation). Customization can also be done globally (i.e.
2684 site-wide, read the INSTALL file).
2685
2686- FILE EXTENSIONS: As default, files with extensions \".vhd\" and \".vhdl\" are
2687 automatically recognized as VHDL source files. To add an extension \".xxx\",
2688 add the following line to your Emacs start-up file (`.emacs'):
2689 \(setq auto-mode-alist (cons '(\"\\\\.xxx\\\\'\" . vhdl-mode) auto-mode-alist))
2690
2691- HINTS:
2692 - Type `\\[keyboard-quit] \\[keyboard-quit]' to interrupt long operations or if Emacs hangs.
d2ddb974
KH
2693
2694
2695Maintenance:
2696------------
2697
2698To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
2699Add a description of the problem and include a reproducible test case.
2700
2701Questions and enhancement requests can be sent to <vhdl-mode@geocities.com>.
2702
2703The `vhdl-mode-announce' mailing list informs about new VHDL Mode releases.
2704The `vhdl-mode-victims' mailing list informs about new VHDL Mode beta releases.
5eabfe72 2705You are kindly invited to participate in beta testing. Subscribe to above
d2ddb974
KH
2706mailing lists by sending an email to <vhdl-mode@geocities.com>.
2707
5eabfe72
KH
2708VHDL Mode is officially distributed on the Emacs VHDL Mode Home Page
2709<http://www.geocities.com/SiliconValley/Peaks/8287>, where the latest
2710version and release notes can be found.
d2ddb974
KH
2711
2712
2713Bugs and Limitations:
2714---------------------
2715
d2ddb974 2716- Re-indenting large regions or expressions can be slow.
5eabfe72 2717- Indentation bug in simultaneous if- and case-statements (VHDL-AMS).
d2ddb974 2718- Hideshow does not work under XEmacs.
5eabfe72
KH
2719- Index menu and file tagging in speedbar do not work under XEmacs.
2720- Parsing compilation error messages for Ikos and Viewlogic VHDL compilers
d2ddb974
KH
2721 does not work under XEmacs.
2722
2723
5eabfe72
KH
2724 The VHDL Mode Maintainers
2725 Reto Zimmermann and Rod Whitby
2726
d2ddb974
KH
2727Key bindings:
2728-------------
2729
2730\\{vhdl-mode-map}"
2731 (interactive)
2732 (kill-all-local-variables)
d2ddb974
KH
2733 (setq major-mode 'vhdl-mode)
2734 (setq mode-name "VHDL")
5eabfe72
KH
2735
2736 ;; set maps and tables
d2ddb974 2737 (use-local-map vhdl-mode-map)
5eabfe72
KH
2738 (set-syntax-table vhdl-mode-syntax-table)
2739 (setq local-abbrev-table vhdl-mode-abbrev-table)
2740
d2ddb974 2741 ;; set local variable values
5eabfe72
KH
2742 (set (make-local-variable 'paragraph-start)
2743 "\\s-*\\(--+\\s-*$\\|[^ -]\\|$\\)")
d2ddb974
KH
2744 (set (make-local-variable 'paragraph-separate) paragraph-start)
2745 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
2746 (set (make-local-variable 'require-final-newline) t)
2747 (set (make-local-variable 'parse-sexp-ignore-comments) t)
2748 (set (make-local-variable 'indent-line-function) 'vhdl-indent-line)
2749 (set (make-local-variable 'comment-start) "--")
2750 (set (make-local-variable 'comment-end) "")
5eabfe72 2751 (set (make-local-variable 'comment-column) vhdl-inline-comment-column)
d2ddb974
KH
2752 (set (make-local-variable 'end-comment-column) vhdl-end-comment-column)
2753 (set (make-local-variable 'comment-start-skip) "--+\\s-*")
5eabfe72 2754 (set (make-local-variable 'comment-multi-line) nil)
d2ddb974 2755 (set (make-local-variable 'indent-tabs-mode) vhdl-indent-tabs-mode)
5eabfe72
KH
2756 (set (make-local-variable 'hippie-expand-only-buffers) '(vhdl-mode))
2757 (set (make-local-variable 'hippie-expand-verbose) nil)
d2ddb974
KH
2758
2759 ;; setup the comment indent variable in a Emacs version portable way
2760 ;; ignore any byte compiler warnings you might get here
5eabfe72
KH
2761 (when (boundp 'comment-indent-function)
2762 (make-local-variable 'comment-indent-function)
2763 (setq comment-indent-function 'vhdl-comment-indent))
d2ddb974
KH
2764
2765 ;; initialize font locking
2766 (require 'font-lock)
5eabfe72
KH
2767 (set (make-local-variable 'font-lock-defaults)
2768 (list
2769 'vhdl-font-lock-keywords nil
2770 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
2771 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
2772 (set (make-local-variable 'font-lock-support-mode) 'lazy-lock-mode)
2773 (set (make-local-variable 'lazy-lock-defer-contextually) nil)
2774 (set (make-local-variable 'lazy-lock-defer-on-the-fly) t)
2775; (set (make-local-variable 'lazy-lock-defer-time) 0.1)
2776 (set (make-local-variable 'lazy-lock-defer-on-scrolling) t)
d2ddb974
KH
2777 (turn-on-font-lock)
2778
2779 ;; variables for source file compilation
5eabfe72
KH
2780 (require 'compile)
2781 (set (make-local-variable 'compilation-error-regexp-alist) nil)
2782 (set (make-local-variable 'compilation-file-regexp-alist) nil)
2783
2784 ;; add index menu
2785 (vhdl-index-menu-init)
2786 ;; add source file menu
d2ddb974 2787 (if vhdl-source-file-menu (vhdl-add-source-files-menu))
5eabfe72
KH
2788 ;; add VHDL menu
2789 (easy-menu-add vhdl-mode-menu-list) ; for XEmacs
2790 (easy-menu-define vhdl-mode-menu vhdl-mode-map
2791 "Menu keymap for VHDL Mode." vhdl-mode-menu-list)
2792 ;; initialize hideshow and add menu
2793 (make-local-variable 'hs-minor-mode-hook)
2794 (vhdl-hideshow-init)
d2ddb974
KH
2795 (run-hooks 'menu-bar-update-hook)
2796
5eabfe72
KH
2797 ;; add speedbar
2798 (when (fboundp 'speedbar)
2799 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
2800 (progn
2801 (when (and vhdl-speedbar (not (and (boundp 'speedbar-frame)
2802 (frame-live-p speedbar-frame))))
2803 (speedbar-frame-mode 1)
2804 (select-frame speedbar-attached-frame)))
2805 (error (vhdl-add-warning "Before using Speedbar, install included `speedbar.el' patch"))))
2806
2807 ;; miscellaneous
2808 (vhdl-ps-print-init)
2809 (vhdl-modify-date-init)
2810 (vhdl-mode-line-update)
2811 (message "VHDL Mode %s. Type C-c C-h for documentation."
2812 vhdl-version)
2813 (vhdl-print-warnings)
2814
2815 ;; run hooks
2816 (run-hooks 'vhdl-mode-hook))
2817
2818(defun vhdl-activate-customizations ()
2819 "Activate all customizations on local variables."
2820 (interactive)
2821 (vhdl-mode-map-init)
2822 (use-local-map vhdl-mode-map)
2823 (set-syntax-table vhdl-mode-syntax-table)
2824 (setq comment-column vhdl-inline-comment-column)
2825 (setq end-comment-column vhdl-end-comment-column)
2826 (vhdl-modify-date-init)
2827 (vhdl-update-mode-menu)
2828 (vhdl-hideshow-init)
2829 (run-hooks 'menu-bar-update-hook)
2830 (vhdl-mode-line-update))
2831
2832(defun vhdl-modify-date-init ()
2833 "Add/remove hook for modifying date when buffer is saved."
2834 (if vhdl-modify-date-on-saving
2835 (add-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)
2836 (remove-hook 'local-write-file-hooks 'vhdl-template-modify-noerror)))
2837
2838
2839;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2840;;; Documentation
2841;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2842
2843(defvar vhdl-doc-keywords nil
2844 "Reserved words in VHDL:
2845
2846VHDL'93 (IEEE Std 1076-1993):
2847 `vhdl-93-keywords' : keywords
2848 `vhdl-93-types' : standardized types
2849 `vhdl-93-attributes' : standardized attributes
2850 `vhdl-93-enum-values' : standardized enumeration values
2851 `vhdl-93-functions' : standardized functions
2852 `vhdl-93-packages' : standardized packages and libraries
2853
2854VHDL-AMS (IEEE Std 1076.1):
2855 `vhdl-ams-keywords' : keywords
2856 `vhdl-ams-types' : standardized types
2857 `vhdl-ams-attributes' : standardized attributes
2858 `vhdl-ams-enum-values' : standardized enumeration values
2859 `vhdl-ams-functions' : standardized functions
2860
2861Math Packages (IEEE Std 1076.2):
2862 `vhdl-math-types' : standardized types
2863 `vhdl-math-constants' : standardized constants
2864 `vhdl-math-functions' : standardized functions
2865 `vhdl-math-packages' : standardized packages
2866
2867Forbidden words:
2868 `vhdl-verilog-keywords' : Verilog reserved words
2869
2870NOTE: click `mouse-2' on variable names above (not in XEmacs).")
2871
2872(defvar vhdl-doc-coding-style nil
2873 "For VHDL coding style and naming convention guidelines, see the following
2874references:
2875
2876\[1] Ben Cohen.
2877 \"VHDL Coding Styles and Methodologies\".
2878 Kluwer Academic Publishers, 1999.
2879 http://members.aol.com/vhdlcohen/vhdl/
2880
2881\[2] Michael Keating and Pierre Bricaud.
2882 \"Reuse Methodology Manual\".
2883 Kluwer Academic Publishers, 1998.
2884 http://www.synopsys.com/products/reuse/rmm.html
2885
2886\[3] European Space Agency.
2887 \"VHDL Modelling Guidelines\".
2888 ftp://ftp.estec.esa.nl/pub/vhdl/doc/ModelGuide.{pdf,ps}
2889
2890Use variables `vhdl-highlight-special-words' and `vhdl-special-syntax-alist'
2891to visually support naming conventions.")
2892
2893(defun vhdl-doc-variable (variable)
2894 "Display VARIABLE's documentation in *Help* buffer."
2895 (interactive)
2896 (with-output-to-temp-buffer "*Help*"
2897 (princ (documentation-property variable 'variable-documentation))
2898 (unless (string-match "XEmacs" emacs-version)
2899 (help-setup-xref (list #'vhdl-doc-variable variable) (interactive-p)))
2900 (save-excursion
2901 (set-buffer standard-output)
2902 (help-mode))
2903 (print-help-return-message)))
d2ddb974 2904
5eabfe72
KH
2905(defun vhdl-doc-mode ()
2906 "Display VHDL mode documentation in *Help* buffer."
2907 (interactive)
2908 (with-output-to-temp-buffer "*Help*"
2909 (princ mode-name)
2910 (princ " mode:\n")
2911 (princ (documentation 'vhdl-mode))
2912 (unless (string-match "XEmacs" emacs-version)
2913 (help-setup-xref (list #'vhdl-doc-mode) (interactive-p)))
2914 (save-excursion
2915 (set-buffer standard-output)
2916 (help-mode))
2917 (print-help-return-message)))
d2ddb974 2918
d2ddb974 2919
5eabfe72
KH
2920;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2921;;; Keywords and standardized words
2922;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 2923
5eabfe72
KH
2924(defconst vhdl-93-keywords
2925 '(
2926 "abs" "access" "after" "alias" "all" "and" "architecture" "array"
2927 "assert" "attribute"
2928 "begin" "block" "body" "buffer" "bus"
2929 "case" "component" "configuration" "constant"
2930 "disconnect" "downto"
2931 "else" "elsif" "end" "entity" "exit"
2932 "file" "for" "function"
2933 "generate" "generic" "group" "guarded"
2934 "if" "impure" "in" "inertial" "inout" "is"
2935 "label" "library" "linkage" "literal" "loop"
2936 "map" "mod"
2937 "nand" "new" "next" "nor" "not" "null"
2938 "of" "on" "open" "or" "others" "out"
2939 "package" "port" "postponed" "procedure" "process" "pure"
2940 "range" "record" "register" "reject" "rem" "report" "return"
2941 "rol" "ror"
2942 "select" "severity" "shared" "signal" "sla" "sll" "sra" "srl" "subtype"
2943 "then" "to" "transport" "type"
2944 "unaffected" "units" "until" "use"
2945 "variable"
2946 "wait" "when" "while" "with"
2947 "xnor" "xor"
2948 )
2949 "List of VHDL'93 keywords.")
d2ddb974 2950
5eabfe72
KH
2951(defconst vhdl-ams-keywords
2952 '(
2953 "across" "break" "limit" "nature" "noise" "procedural" "quantity"
2954 "reference" "spectrum" "subnature" "terminal" "through"
2955 "tolerance"
2956 )
2957 "List of VHDL-AMS keywords.")
d2ddb974 2958
5eabfe72
KH
2959(defconst vhdl-verilog-keywords
2960 '(
2961 "`define" "`else" "`endif" "`ifdef" "`include" "`timescale" "`undef"
2962 "always" "and" "assign" "begin" "buf" "bufif0" "bufif1"
2963 "case" "casex" "casez" "cmos" "deassign" "default" "defparam" "disable"
2964 "edge" "else" "end" "endattribute" "endcase" "endfunction" "endmodule"
2965 "endprimitive" "endspecify" "endtable" "endtask" "event"
2966 "for" "force" "forever" "fork" "function"
2967 "highz0" "highz1" "if" "initial" "inout" "input" "integer" "join" "large"
2968 "macromodule" "makefile" "medium" "module"
2969 "nand" "negedge" "nmos" "nor" "not" "notif0" "notif1" "or" "output"
2970 "parameter" "pmos" "posedge" "primitive" "pull0" "pull1" "pulldown"
2971 "pullup"
2972 "rcmos" "real" "realtime" "reg" "release" "repeat" "rnmos" "rpmos" "rtran"
2973 "rtranif0" "rtranif1"
2974 "scalared" "signed" "small" "specify" "specparam" "strength" "strong0"
2975 "strong1" "supply" "supply0" "supply1"
2976 "table" "task" "time" "tran" "tranif0" "tranif1" "tri" "tri0" "tri1"
2977 "triand" "trior" "trireg"
2978 "vectored" "wait" "wand" "weak0" "weak1" "while" "wire" "wor" "xnor" "xor"
2979 )
2980 "List of Verilog keywords as candidate for additional reserved words.")
d2ddb974 2981
5eabfe72
KH
2982(defconst vhdl-93-types
2983 '(
2984 "boolean" "bit" "bit_vector" "character" "severity_level" "integer"
2985 "real" "time" "natural" "positive" "string" "line" "text" "side"
2986 "unsigned" "signed" "delay_length" "file_open_kind" "file_open_status"
2987 "std_logic" "std_logic_vector"
2988 "std_ulogic" "std_ulogic_vector"
2989 )
2990 "List of VHDL'93 standardized types.")
d2ddb974 2991
5eabfe72
KH
2992(defconst vhdl-ams-types
2993 '(
2994 "domain_type" "real_vector"
2995 )
2996 "List of VHDL-AMS standardized types.")
d2ddb974 2997
5eabfe72
KH
2998(defconst vhdl-math-types
2999 '(
3000 "complex" "complex_polar"
3001 )
3002 "List of Math Packages standardized types.")
d2ddb974 3003
5eabfe72
KH
3004(defconst vhdl-93-attributes
3005 '(
3006 "base" "left" "right" "high" "low" "pos" "val" "succ"
3007 "pred" "leftof" "rightof" "range" "reverse_range"
3008 "length" "delayed" "stable" "quiet" "transaction"
3009 "event" "active" "last_event" "last_active" "last_value"
3010 "driving" "driving_value" "ascending" "value" "image"
3011 "simple_name" "instance_name" "path_name"
3012 "foreign"
3013 )
3014 "List of VHDL'93 standardized attributes.")
d2ddb974 3015
5eabfe72
KH
3016(defconst vhdl-ams-attributes
3017 '(
3018 "across" "through"
3019 "reference" "contribution" "tolerance"
3020 "dot" "integ" "delayed" "above" "zoh" "ltf" "ztf"
3021 "ramp" "slew"
3022 )
3023 "List of VHDL-AMS standardized attributes.")
d2ddb974 3024
5eabfe72
KH
3025(defconst vhdl-93-enum-values
3026 '(
3027 "true" "false"
3028 "note" "warning" "error" "failure"
3029 "read_mode" "write_mode" "append_mode"
3030 "open_ok" "status_error" "name_error" "mode_error"
3031 "fs" "ps" "ns" "us" "ms" "sec" "min" "hr"
3032 "right" "left"
3033 )
3034 "List of VHDL'93 standardized enumeration values.")
d2ddb974 3035
5eabfe72
KH
3036(defconst vhdl-ams-enum-values
3037 '(
3038 "quiescent_domain" "time_domain" "frequency_domain"
3039 )
3040 "List of VHDL-AMS standardized enumeration values.")
3041
3042(defconst vhdl-math-constants
3043 '(
3044 "math_e" "math_1_over_e"
3045 "math_pi" "math_two_pi" "math_1_over_pi"
3046 "math_half_pi" "math_q_pi" "math_3_half_pi"
3047 "math_log_of_2" "math_log_of_10" "math_log2_of_e" "math_log10_of_e"
3048 "math_sqrt2" "math_sqrt1_2" "math_sqrt_pi"
3049 "math_deg_to_rad" "math_rad_to_deg"
3050 "cbase_1" "cbase_j" "czero"
3051 )
3052 "List of Math Packages standardized constants.")
3053
3054(defconst vhdl-93-functions
3055 '(
3056 "now" "resolved" "rising_edge" "falling_edge"
3057 "read" "readline" "write" "writeline" "endfile"
3058 "resize" "is_X" "std_match"
3059 "shift_left" "shift_right" "rotate_left" "rotate_right"
3060 "to_unsigned" "to_signed" "to_integer"
3061 "to_stdLogicVector" "to_stdULogic" "to_stdULogicVector"
3062 "to_bit" "to_bitVector" "to_X01" "to_X01Z" "to_UX01" "to_01"
3063 "conv_unsigned" "conv_signed" "conv_integer" "conv_std_logic_vector"
3064 "shl" "shr" "ext" "sxt"
3065 )
3066 "List of VHDL'93 standardized functions.")
3067
3068(defconst vhdl-ams-functions
3069 '(
3070 "frequency"
3071 )
3072 "List of VHDL-AMS standardized functions.")
3073
3074(defconst vhdl-math-functions
3075 '(
3076 "sign" "ceil" "floor" "round" "trunc" "fmax" "fmin" "uniform"
3077 "sqrt" "cbrt" "exp" "log"
3078 "sin" "cos" "tan" "arcsin" "arccos" "arctan"
3079 "sinh" "cosh" "tanh" "arcsinh" "arccosh" "arctanh"
3080 "cmplx" "complex_to_polar" "polar_to_complex" "arg" "conj"
3081 )
3082 "List of Math Packages standardized functions.")
3083
3084(defconst vhdl-93-packages
3085 '(
3086 "std_logic_1164" "numeric_std" "numeric_bit"
3087 "standard" "textio"
3088 "std_logic_arith" "std_logic_signed" "std_logic_unsigned"
3089 "std_logic_misc" "std_logic_textio"
3090 "ieee" "std" "work"
3091 )
3092 "List of VHDL'93 standardized packages and libraries.")
3093
3094(defconst vhdl-math-packages
3095 '(
3096 "math_real" "math_complex"
3097 )
3098 "List of Math Packages standardized packages and libraries.")
3099
3100(defvar vhdl-keywords nil
3101 "List of VHDL keywords.")
3102
3103(defvar vhdl-types nil
3104 "List of VHDL standardized types.")
3105
3106(defvar vhdl-attributes nil
3107 "List of VHDL standardized attributes.")
3108
3109(defvar vhdl-enum-values nil
3110 "List of VHDL standardized enumeration values.")
3111
3112(defvar vhdl-constants nil
3113 "List of VHDL standardized constants.")
3114
3115(defvar vhdl-functions nil
3116 "List of VHDL standardized functions.")
3117
3118(defvar vhdl-packages nil
3119 "List of VHDL standardized packages and libraries.")
3120
3121(defvar vhdl-reserved-words nil
3122 "List of additional reserved words.")
3123
3124(defvar vhdl-keywords-regexp nil
3125 "Regexp for VHDL keywords.")
3126
3127(defvar vhdl-types-regexp nil
3128 "Regexp for VHDL standardized types.")
3129
3130(defvar vhdl-attributes-regexp nil
3131 "Regexp for VHDL standardized attributes.")
3132
3133(defvar vhdl-enum-values-regexp nil
3134 "Regexp for VHDL standardized enumeration values.")
3135
3136(defvar vhdl-functions-regexp nil
3137 "Regexp for VHDL standardized functions.")
3138
3139(defvar vhdl-packages-regexp nil
3140 "Regexp for VHDL standardized packages and libraries.")
3141
3142(defvar vhdl-reserved-words-regexp nil
3143 "Regexp for additional reserved words.")
3144
3145(defun vhdl-words-init ()
3146 "Initialize reserved words."
3147 (setq vhdl-keywords
3148 (append vhdl-93-keywords
3149 (when (vhdl-standard-p 'ams) vhdl-ams-keywords)))
3150 (setq vhdl-types
3151 (append vhdl-93-types
3152 (when (vhdl-standard-p 'ams) vhdl-ams-types)
3153 (when (vhdl-standard-p 'math) vhdl-math-types)))
3154 (setq vhdl-attributes
3155 (append vhdl-93-attributes
3156 (when (vhdl-standard-p 'ams) vhdl-ams-attributes)))
3157 (setq vhdl-enum-values
3158 (append vhdl-93-enum-values
3159 (when (vhdl-standard-p 'ams) vhdl-ams-enum-values)))
3160 (setq vhdl-constants
3161 (append (when (vhdl-standard-p 'math) vhdl-math-constants)))
3162 (setq vhdl-functions
3163 (append vhdl-93-functions
3164 (when (vhdl-standard-p 'ams) vhdl-ams-functions)
3165 (when (vhdl-standard-p 'math) vhdl-math-functions)))
3166 (setq vhdl-packages
3167 (append vhdl-93-packages
3168 (when (vhdl-standard-p 'math) vhdl-math-packages)))
3169 (setq vhdl-reserved-words
3170 (append (when vhdl-highlight-forbidden-words vhdl-forbidden-words)
3171 (when vhdl-highlight-verilog-keywords vhdl-verilog-keywords)
3172 '("")))
3173 (setq vhdl-keywords-regexp
3174 (concat "\\<\\(" (regexp-opt vhdl-keywords) "\\)\\>"))
3175 (setq vhdl-types-regexp
3176 (concat "\\<\\(" (regexp-opt vhdl-types) "\\)\\>"))
3177 (setq vhdl-attributes-regexp
3178 (concat "\\<\\(" (regexp-opt vhdl-attributes) "\\)\\>"))
3179 (setq vhdl-enum-values-regexp
3180 (concat "\\<\\(" (regexp-opt vhdl-enum-values) "\\)\\>"))
3181 (setq vhdl-functions-regexp
3182 (concat "\\<\\(" (regexp-opt vhdl-functions) "\\)\\>"))
3183 (setq vhdl-packages-regexp
3184 (concat "\\<\\(" (regexp-opt vhdl-packages) "\\)\\>"))
3185 (setq vhdl-reserved-words-regexp
3186 (concat "\\<\\("
3187 (unless (equal vhdl-forbidden-syntax "")
3188 (concat vhdl-forbidden-syntax "\\|"))
3189 (regexp-opt vhdl-reserved-words)
3190 "\\)\\>"))
3191 (vhdl-abbrev-list-init))
3192
3193;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3194;; Words to expand
3195
3196(defvar vhdl-abbrev-list nil
3197 "Predefined abbreviations for VHDL.")
3198
3199(defun vhdl-abbrev-list-init ()
3200 (setq vhdl-abbrev-list
3201 (append
3202 (list vhdl-upper-case-keywords) vhdl-keywords
3203 (list vhdl-upper-case-types) vhdl-types
3204 (list vhdl-upper-case-attributes) vhdl-attributes
3205 (list vhdl-upper-case-enum-values) vhdl-enum-values
3206 (list vhdl-upper-case-constants) vhdl-constants
3207 (list nil) vhdl-functions
3208 (list nil) vhdl-packages)))
3209
3210;; initialize reserved words for VHDL Mode
3211(vhdl-words-init)
3212
3213
3214;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3215;;; Syntax analysis and indentation
3216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3217
3218;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
3219;; Syntax analysis
3220
3221;; constant regular expressions for looking at various constructs
3222
3223(defconst vhdl-symbol-key "\\(\\w\\|\\s_\\)+"
3224 "Regexp describing a VHDL symbol.
3225We cannot use just `word' syntax class since `_' cannot be in word
3226class. Putting underscore in word class breaks forward word movement
3227behavior that users are familiar with.")
3228
3229(defconst vhdl-case-header-key "case[( \t\n][^;=>]+[) \t\n]is"
3230 "Regexp describing a case statement header key.")
3231
3232(defconst vhdl-label-key
3233 (concat "\\(" vhdl-symbol-key "\\s-*:\\)[^=]")
3234 "Regexp describing a VHDL label.")
3235
3236;; Macro definitions:
3237
3238(defmacro vhdl-point (position)
5eabfe72
KH
3239 "Return the value of point at certain commonly referenced POSITIONs.
3240POSITION can be one of the following symbols:
3241
3242bol -- beginning of line
3243eol -- end of line
3244bod -- beginning of defun
3245boi -- back to indentation
3246eoi -- last whitespace on line
3247ionl -- indentation of next line
3248iopl -- indentation of previous line
3249bonl -- beginning of next line
3250bopl -- beginning of previous line
3251
3252This function does not modify point or mark."
d2ddb974
KH
3253 (or (and (eq 'quote (car-safe position))
3254 (null (cdr (cdr position))))
5eabfe72 3255 (error "Bad buffer position requested: %s" position))
d2ddb974 3256 (setq position (nth 1 position))
d4a5b644
GM
3257 `(let ((here (point)))
3258 ,@(cond
3259 ((eq position 'bol) '((beginning-of-line)))
3260 ((eq position 'eol) '((end-of-line)))
3261 ((eq position 'bod) '((save-match-data
3262 (vhdl-beginning-of-defun))))
3263 ((eq position 'boi) '((back-to-indentation)))
3264 ((eq position 'eoi) '((end-of-line)(skip-chars-backward " \t")))
3265 ((eq position 'bonl) '((forward-line 1)))
3266 ((eq position 'bopl) '((forward-line -1)))
3267 ((eq position 'iopl)
3268 '((forward-line -1)
3269 (back-to-indentation)))
3270 ((eq position 'ionl)
3271 '((forward-line 1)
3272 (back-to-indentation)))
3273 (t (error "Unknown buffer position requested: %s" position))
3274 )
3275 (prog1
3276 (point)
3277 (goto-char here))
3278 ;; workaround for an Emacs18 bug -- blech! Well, at least it
3279 ;; doesn't hurt for v19
3280 ,@nil
3281 ))
d2ddb974
KH
3282
3283(defmacro vhdl-safe (&rest body)
5eabfe72 3284 "Safely execute BODY, return nil if an error occurred."
d4a5b644
GM
3285 `(condition-case nil
3286 (progn ,@body)
3287 (error nil)))
d2ddb974
KH
3288
3289(defmacro vhdl-add-syntax (symbol &optional relpos)
5eabfe72
KH
3290 "A simple macro to append the syntax in SYMBOL to the syntax list.
3291Try to increase performance by using this macro."
d4a5b644
GM
3292 `(setq vhdl-syntactic-context
3293 (cons (cons ,symbol ,relpos) vhdl-syntactic-context)))
d2ddb974
KH
3294
3295(defmacro vhdl-has-syntax (symbol)
5eabfe72
KH
3296 "A simple macro to return check the syntax list.
3297Try to increase performance by using this macro."
d4a5b644 3298 `(assoc ,symbol vhdl-syntactic-context))
d2ddb974
KH
3299
3300;; Syntactic element offset manipulation:
3301
3302(defun vhdl-read-offset (langelem)
5eabfe72
KH
3303 "Read new offset value for LANGELEM from minibuffer.
3304Return a legal value only."
d2ddb974
KH
3305 (let ((oldoff (format "%s" (cdr-safe (assq langelem vhdl-offsets-alist))))
3306 (errmsg "Offset must be int, func, var, or one of +, -, ++, --: ")
3307 (prompt "Offset: ")
3308 offset input interned)
3309 (while (not offset)
3310 (setq input (read-string prompt oldoff)
3311 offset (cond ((string-equal "+" input) '+)
3312 ((string-equal "-" input) '-)
3313 ((string-equal "++" input) '++)
3314 ((string-equal "--" input) '--)
3315 ((string-match "^-?[0-9]+$" input)
3316 (string-to-int input))
3317 ((fboundp (setq interned (intern input)))
3318 interned)
3319 ((boundp interned) interned)
3320 ;; error, but don't signal one, keep trying
3321 ;; to read an input value
3322 (t (ding)
3323 (setq prompt errmsg)
3324 nil))))
3325 offset))
3326
3327(defun vhdl-set-offset (symbol offset &optional add-p)
3328 "Change the value of a syntactic element symbol in `vhdl-offsets-alist'.
3329SYMBOL is the syntactic element symbol to change and OFFSET is the new
3330offset for that syntactic element. Optional ADD says to add SYMBOL to
3331`vhdl-offsets-alist' if it doesn't already appear there."
3332 (interactive
3333 (let* ((langelem
3334 (intern (completing-read
3335 (concat "Syntactic symbol to change"
3336 (if current-prefix-arg " or add" "")
3337 ": ")
3338 (mapcar
3339 (function
3340 (lambda (langelem)
3341 (cons (format "%s" (car langelem)) nil)))
3342 vhdl-offsets-alist)
3343 nil (not current-prefix-arg)
3344 ;; initial contents tries to be the last element
3345 ;; on the syntactic analysis list for the current
3346 ;; line
3347 (let* ((syntax (vhdl-get-syntactic-context))
3348 (len (length syntax))
3349 (ic (format "%s" (car (nth (1- len) syntax)))))
5eabfe72 3350 ic)
d2ddb974
KH
3351 )))
3352 (offset (vhdl-read-offset langelem)))
3353 (list langelem offset current-prefix-arg)))
3354 ;; sanity check offset
3355 (or (eq offset '+)
3356 (eq offset '-)
3357 (eq offset '++)
3358 (eq offset '--)
3359 (integerp offset)
3360 (fboundp offset)
3361 (boundp offset)
3362 (error "Offset must be int, func, var, or one of +, -, ++, --: %s"
3363 offset))
3364 (let ((entry (assq symbol vhdl-offsets-alist)))
3365 (if entry
3366 (setcdr entry offset)
3367 (if add-p
5eabfe72
KH
3368 (setq vhdl-offsets-alist
3369 (cons (cons symbol offset) vhdl-offsets-alist))
3370 (error "%s is not a valid syntactic symbol" symbol))))
d2ddb974
KH
3371 (vhdl-keep-region-active))
3372
3373(defun vhdl-set-style (style &optional local)
5eabfe72 3374 "Set `vhdl-mode' variables to use one of several different indentation styles.
d2ddb974
KH
3375STYLE is a string representing the desired style and optional LOCAL is
3376a flag which, if non-nil, means to make the style variables being
3377changed buffer local, instead of the default, which is to set the
3378global variables. Interactively, the flag comes from the prefix
3379argument. The styles are chosen from the `vhdl-style-alist' variable."
3380 (interactive (list (completing-read "Use which VHDL indentation style? "
5eabfe72 3381 vhdl-style-alist nil t)
d2ddb974
KH
3382 current-prefix-arg))
3383 (let ((vars (cdr (assoc style vhdl-style-alist))))
3384 (or vars
3385 (error "Invalid VHDL indentation style `%s'" style))
3386 ;; set all the variables
3387 (mapcar
3388 (function
3389 (lambda (varentry)
3390 (let ((var (car varentry))
3391 (val (cdr varentry)))
3392 (and local
3393 (make-local-variable var))
3394 ;; special case for vhdl-offsets-alist
3395 (if (not (eq var 'vhdl-offsets-alist))
3396 (set var val)
3397 ;; reset vhdl-offsets-alist to the default value first
3398 (setq vhdl-offsets-alist (copy-alist vhdl-offsets-alist-default))
3399 ;; now set the langelems that are different
3400 (mapcar
3401 (function
3402 (lambda (langentry)
3403 (let ((langelem (car langentry))
3404 (offset (cdr langentry)))
3405 (vhdl-set-offset langelem offset)
3406 )))
3407 val))
3408 )))
3409 vars))
3410 (vhdl-keep-region-active))
3411
3412(defun vhdl-get-offset (langelem)
5eabfe72
KH
3413 "Get offset from LANGELEM which is a cons cell of the form:
3414\(SYMBOL . RELPOS). The symbol is matched against
3415vhdl-offsets-alist and the offset found there is either returned,
3416or added to the indentation at RELPOS. If RELPOS is nil, then
3417the offset is simply returned."
d2ddb974
KH
3418 (let* ((symbol (car langelem))
3419 (relpos (cdr langelem))
3420 (match (assq symbol vhdl-offsets-alist))
3421 (offset (cdr-safe match)))
3422 ;; offset can be a number, a function, a variable, or one of the
3423 ;; symbols + or -
3424 (cond
3425 ((not match)
3426 (if vhdl-strict-syntax-p
5eabfe72 3427 (error "Don't know how to indent a %s" symbol)
d2ddb974
KH
3428 (setq offset 0
3429 relpos 0)))
3430 ((eq offset '+) (setq offset vhdl-basic-offset))
3431 ((eq offset '-) (setq offset (- vhdl-basic-offset)))
3432 ((eq offset '++) (setq offset (* 2 vhdl-basic-offset)))
3433 ((eq offset '--) (setq offset (* 2 (- vhdl-basic-offset))))
3434 ((and (not (numberp offset))
3435 (fboundp offset))
3436 (setq offset (funcall offset langelem)))
3437 ((not (numberp offset))
3438 (setq offset (eval offset)))
3439 )
3440 (+ (if (and relpos
3441 (< relpos (vhdl-point 'bol)))
3442 (save-excursion
3443 (goto-char relpos)
3444 (current-column))
3445 0)
3446 offset)))
3447
3448;; Syntactic support functions:
3449
3450;; Returns `comment' if in a comment, `string' if in a string literal,
3451;; or nil if not in a literal at all. Optional LIM is used as the
3452;; backward limit of the search. If omitted, or nil, (point-min) is
3453;; used.
3454
3455(defun vhdl-in-literal (&optional lim)
5eabfe72 3456 "Determine if point is in a VHDL literal."
d2ddb974 3457 (save-excursion
5eabfe72 3458 (let ((state (parse-partial-sexp (vhdl-point 'bol) (point))))
d2ddb974
KH
3459 (cond
3460 ((nth 3 state) 'string)
3461 ((nth 4 state) 'comment)
5eabfe72 3462 (t nil)))))
d2ddb974
KH
3463
3464;; This is the best we can do in Win-Emacs.
3465(defun vhdl-win-il (&optional lim)
5eabfe72 3466 "Determine if point is in a VHDL literal."
d2ddb974
KH
3467 (save-excursion
3468 (let* ((here (point))
3469 (state nil)
3470 (match nil)
3471 (lim (or lim (vhdl-point 'bod))))
3472 (goto-char lim )
3473 (while (< (point) here)
3474 (setq match
3475 (and (re-search-forward "--\\|[\"']"
3476 here 'move)
3477 (buffer-substring (match-beginning 0) (match-end 0))))
3478 (setq state
3479 (cond
3480 ;; no match
3481 ((null match) nil)
3482 ;; looking at the opening of a VHDL style comment
3483 ((string= "--" match)
3484 (if (<= here (progn (end-of-line) (point))) 'comment))
3485 ;; looking at the opening of a double quote string
3486 ((string= "\"" match)
3487 (if (not (save-restriction
3488 ;; this seems to be necessary since the
3489 ;; re-search-forward will not work without it
3490 (narrow-to-region (point) here)
3491 (re-search-forward
3492 ;; this regexp matches a double quote
3493 ;; which is preceded by an even number
3494 ;; of backslashes, including zero
3495 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)*\"" here 'move)))
3496 'string))
3497 ;; looking at the opening of a single quote string
3498 ((string= "'" match)
3499 (if (not (save-restriction
3500 ;; see comments from above
3501 (narrow-to-region (point) here)
3502 (re-search-forward
3503 ;; this matches a single quote which is
3504 ;; preceded by zero or two backslashes.
3505 "\\([^\\]\\|^\\)\\(\\\\\\\\\\)?'"
3506 here 'move)))
3507 'string))
3508 (t nil)))
3509 ) ; end-while
3510 state)))
3511
5eabfe72 3512(and (string-match "Win-Emacs" emacs-version)
d2ddb974
KH
3513 (fset 'vhdl-in-literal 'vhdl-win-il))
3514
3515;; Skipping of "syntactic whitespace". Syntactic whitespace is
3516;; defined as lexical whitespace or comments. Search no farther back
3517;; or forward than optional LIM. If LIM is omitted, (point-min) is
3518;; used for backward skipping, (point-max) is used for forward
3519;; skipping.
3520
3521(defun vhdl-forward-syntactic-ws (&optional lim)
5eabfe72 3522 "Forward skip of syntactic whitespace."
d2ddb974
KH
3523 (save-restriction
3524 (let* ((lim (or lim (point-max)))
3525 (here lim)
3526 (hugenum (point-max)))
3527 (narrow-to-region lim (point))
3528 (while (/= here (point))
3529 (setq here (point))
3530 (forward-comment hugenum))
3531 )))
3532
3533;; This is the best we can do in Win-Emacs.
3534(defun vhdl-win-fsws (&optional lim)
5eabfe72 3535 "Forward skip syntactic whitespace for Win-Emacs."
d2ddb974
KH
3536 (let ((lim (or lim (point-max)))
3537 stop)
3538 (while (not stop)
3539 (skip-chars-forward " \t\n\r\f" lim)
3540 (cond
3541 ;; vhdl comment
3542 ((looking-at "--") (end-of-line))
3543 ;; none of the above
3544 (t (setq stop t))
3545 ))))
3546
5eabfe72 3547(and (string-match "Win-Emacs" emacs-version)
d2ddb974
KH
3548 (fset 'vhdl-forward-syntactic-ws 'vhdl-win-fsws))
3549
3550(defun vhdl-backward-syntactic-ws (&optional lim)
5eabfe72 3551 "Backward skip over syntactic whitespace."
d2ddb974
KH
3552 (save-restriction
3553 (let* ((lim (or lim (point-min)))
3554 (here lim)
3555 (hugenum (- (point-max))))
3556 (if (< lim (point))
3557 (progn
3558 (narrow-to-region lim (point))
3559 (while (/= here (point))
3560 (setq here (point))
3561 (forward-comment hugenum)
3562 )))
3563 )))
3564
3565;; This is the best we can do in Win-Emacs.
3566(defun vhdl-win-bsws (&optional lim)
5eabfe72 3567 "Backward skip syntactic whitespace for Win-Emacs."
d2ddb974
KH
3568 (let ((lim (or lim (vhdl-point 'bod)))
3569 stop)
3570 (while (not stop)
3571 (skip-chars-backward " \t\n\r\f" lim)
3572 (cond
3573 ;; vhdl comment
3574 ((eq (vhdl-in-literal lim) 'comment)
3575 (skip-chars-backward "^-" lim)
3576 (skip-chars-backward "-" lim)
3577 (while (not (or (and (= (following-char) ?-)
3578 (= (char-after (1+ (point))) ?-))
3579 (<= (point) lim)))
3580 (skip-chars-backward "^-" lim)
3581 (skip-chars-backward "-" lim)))
3582 ;; none of the above
3583 (t (setq stop t))
3584 ))))
3585
5eabfe72 3586(and (string-match "Win-Emacs" emacs-version)
d2ddb974
KH
3587 (fset 'vhdl-backward-syntactic-ws 'vhdl-win-bsws))
3588
3589;; Functions to help finding the correct indentation column:
3590
3591(defun vhdl-first-word (point)
3592 "If the keyword at POINT is at boi, then return (current-column) at
3593that point, else nil."
3594 (save-excursion
3595 (and (goto-char point)
3596 (eq (point) (vhdl-point 'boi))
3597 (current-column))))
3598
3599(defun vhdl-last-word (point)
3600 "If the keyword at POINT is at eoi, then return (current-column) at
3601that point, else nil."
3602 (save-excursion
3603 (and (goto-char point)
3604 (save-excursion (or (eq (progn (forward-sexp) (point))
3605 (vhdl-point 'eoi))
3606 (looking-at "\\s-*\\(--\\)?")))
3607 (current-column))))
3608
3609;; Core syntactic evaluation functions:
3610
3611(defconst vhdl-libunit-re
3612 "\\b\\(architecture\\|configuration\\|entity\\|package\\)\\b[^_]")
3613
3614(defun vhdl-libunit-p ()
3615 (and
3616 (save-excursion
3617 (forward-sexp)
3618 (skip-chars-forward " \t\n")
3619 (not (looking-at "is\\b[^_]")))
3620 (save-excursion
3621 (backward-sexp)
3622 (and (not (looking-at "use\\b[^_]"))
3623 (progn
3624 (forward-sexp)
3625 (vhdl-forward-syntactic-ws)
3626 (/= (following-char) ?:))))
3627 ))
3628
3629(defconst vhdl-defun-re
5eabfe72 3630 "\\b\\(architecture\\|block\\|configuration\\|entity\\|package\\|process\\|procedural\\|procedure\\|function\\)\\b[^_]")
d2ddb974
KH
3631
3632(defun vhdl-defun-p ()
3633 (save-excursion
5eabfe72
KH
3634 (if (looking-at "block\\|process\\|procedural")
3635 ;; "block", "process", "procedural":
d2ddb974
KH
3636 (save-excursion
3637 (backward-sexp)
3638 (not (looking-at "end\\s-+\\w")))
3639 ;; "architecture", "configuration", "entity",
3640 ;; "package", "procedure", "function":
3641 t)))
3642
3643(defun vhdl-corresponding-defun ()
3644 "If the word at the current position corresponds to a \"defun\"
3645keyword, then return a string that can be used to find the
3646corresponding \"begin\" keyword, else return nil."
3647 (save-excursion
3648 (and (looking-at vhdl-defun-re)
3649 (vhdl-defun-p)
5eabfe72
KH
3650 (if (looking-at "block\\|process\\|procedural")
3651 ;; "block", "process". "procedural:
d2ddb974
KH
3652 (buffer-substring (match-beginning 0) (match-end 0))
3653 ;; "architecture", "configuration", "entity", "package",
3654 ;; "procedure", "function":
3655 "is"))))
3656
3657(defconst vhdl-begin-fwd-re
5eabfe72 3658 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b\\([^_]\\|\\'\\)"
d2ddb974
KH
3659 "A regular expression for searching forward that matches all known
3660\"begin\" keywords.")
3661
3662(defconst vhdl-begin-bwd-re
5eabfe72 3663 "\\b\\(is\\|begin\\|block\\|component\\|generate\\|then\\|else\\|loop\\|process\\|procedural\\|units\\|record\\|for\\)\\b[^_]"
d2ddb974
KH
3664 "A regular expression for searching backward that matches all known
3665\"begin\" keywords.")
3666
3667(defun vhdl-begin-p (&optional lim)
3668 "Return t if we are looking at a real \"begin\" keyword.
3669Assumes that the caller will make sure that we are looking at
3670vhdl-begin-fwd-re, and are not inside a literal, and that we are not in
3671the middle of an identifier that just happens to contain a \"begin\"
3672keyword."
3673 (cond
3674 ;; "[architecture|case|configuration|entity|package|
3675 ;; procedure|function] ... is":
3676 ((and (looking-at "i")
3677 (save-excursion
3678 ;; Skip backward over first sexp (needed to skip over a
3679 ;; procedure interface list, and is harmless in other
3680 ;; situations). Note that we need "return" in the
3681 ;; following search list so that we don't run into
3682 ;; semicolons in the function interface list.
3683 (backward-sexp)
3684 (let (foundp)
3685 (while (and (not foundp)
3686 (re-search-backward
5eabfe72 3687 ";\\|\\b\\(architecture\\|case\\|configuration\\|entity\\|package\\|procedure\\|return\\|is\\|begin\\|process\\|procedural\\|block\\)\\b[^_]"
d2ddb974
KH
3688 lim 'move))
3689 (if (or (= (preceding-char) ?_)
3690 (vhdl-in-literal lim))
3691 (backward-char)
3692 (setq foundp t))))
3693 (and (/= (following-char) ?\;)
5eabfe72 3694 (not (looking-at "is\\|begin\\|process\\|procedural\\|block")))))
d2ddb974
KH
3695 t)
3696 ;; "begin", "then":
3697 ((looking-at "be\\|t")
3698 t)
3699 ;; "else":
3700 ((and (looking-at "e")
3701 ;; make sure that the "else" isn't inside a
3702 ;; conditional signal assignment.
3703 (save-excursion
3704 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3705 (or (eq (following-char) ?\;)
3706 (eq (point) lim))))
3707 t)
5eabfe72 3708 ;; "block", "generate", "loop", "process", "procedural",
d2ddb974
KH
3709 ;; "units", "record":
3710 ((and (looking-at "bl\\|[glpur]")
3711 (save-excursion
3712 (backward-sexp)
3713 (not (looking-at "end\\s-+\\w"))))
3714 t)
3715 ;; "component":
3716 ((and (looking-at "c")
3717 (save-excursion
3718 (backward-sexp)
3719 (not (looking-at "end\\s-+\\w")))
3720 ;; look out for the dreaded entity class in an attribute
3721 (save-excursion
3722 (vhdl-backward-syntactic-ws lim)
3723 (/= (preceding-char) ?:)))
3724 t)
3725 ;; "for" (inside configuration declaration):
3726 ((and (looking-at "f")
3727 (save-excursion
3728 (backward-sexp)
3729 (not (looking-at "end\\s-+\\w")))
3730 (vhdl-has-syntax 'configuration))
3731 t)
3732 ))
3733
3734(defun vhdl-corresponding-mid (&optional lim)
3735 (cond
5eabfe72 3736 ((looking-at "is\\|block\\|generate\\|process\\|procedural")
d2ddb974
KH
3737 "begin")
3738 ((looking-at "then")
3739 "<else>")
3740 (t
3741 "end")))
3742
3743(defun vhdl-corresponding-end (&optional lim)
3744 "If the word at the current position corresponds to a \"begin\"
3745keyword, then return a vector containing enough information to find
3746the corresponding \"end\" keyword, else return nil. The keyword to
3747search forward for is aref 0. The column in which the keyword must
3748appear is aref 1 or nil if any column is suitable.
3749Assumes that the caller will make sure that we are not in the middle
3750of an identifier that just happens to contain a \"begin\" keyword."
3751 (save-excursion
3752 (and (looking-at vhdl-begin-fwd-re)
3753 (/= (preceding-char) ?_)
3754 (not (vhdl-in-literal lim))
3755 (vhdl-begin-p lim)
3756 (cond
3757 ;; "is", "generate", "loop":
3758 ((looking-at "[igl]")
3759 (vector "end"
3760 (and (vhdl-last-word (point))
3761 (or (vhdl-first-word (point))
3762 (save-excursion
3763 (vhdl-beginning-of-statement-1 lim)
3764 (vhdl-backward-skip-label lim)
3765 (vhdl-first-word (point)))))))
3766 ;; "begin", "else", "for":
3767 ((looking-at "be\\|[ef]")
3768 (vector "end"
3769 (and (vhdl-last-word (point))
3770 (or (vhdl-first-word (point))
3771 (save-excursion
3772 (vhdl-beginning-of-statement-1 lim)
3773 (vhdl-backward-skip-label lim)
3774 (vhdl-first-word (point)))))))
3775 ;; "component", "units", "record":
3776 ((looking-at "[cur]")
3777 ;; The first end found will close the block
3778 (vector "end" nil))
5eabfe72 3779 ;; "block", "process", "procedural":
d2ddb974
KH
3780 ((looking-at "bl\\|p")
3781 (vector "end"
3782 (or (vhdl-first-word (point))
3783 (save-excursion
3784 (vhdl-beginning-of-statement-1 lim)
3785 (vhdl-backward-skip-label lim)
3786 (vhdl-first-word (point))))))
3787 ;; "then":
3788 ((looking-at "t")
3789 (vector "elsif\\|else\\|end\\s-+if"
3790 (and (vhdl-last-word (point))
3791 (or (vhdl-first-word (point))
3792 (save-excursion
3793 (vhdl-beginning-of-statement-1 lim)
3794 (vhdl-backward-skip-label lim)
3795 (vhdl-first-word (point)))))))
3796 ))))
3797
3798(defconst vhdl-end-fwd-re "\\b\\(end\\|else\\|elsif\\)\\b\\([^_]\\|\\'\\)")
3799
3800(defconst vhdl-end-bwd-re "\\b\\(end\\|else\\|elsif\\)\\b[^_]")
3801
3802(defun vhdl-end-p (&optional lim)
3803 "Return t if we are looking at a real \"end\" keyword.
3804Assumes that the caller will make sure that we are looking at
3805vhdl-end-fwd-re, and are not inside a literal, and that we are not in
3806the middle of an identifier that just happens to contain an \"end\"
3807keyword."
3808 (or (not (looking-at "else"))
3809 ;; make sure that the "else" isn't inside a conditional signal
3810 ;; assignment.
3811 (save-excursion
3812 (re-search-backward ";\\|\\bwhen\\b[^_]" lim 'move)
3813 (or (eq (following-char) ?\;)
3814 (eq (point) lim)))))
3815
3816(defun vhdl-corresponding-begin (&optional lim)
3817 "If the word at the current position corresponds to an \"end\"
3818keyword, then return a vector containing enough information to find
3819the corresponding \"begin\" keyword, else return nil. The keyword to
9b61eea1 3820search backward for is aref 0. The column in which the keyword must
d2ddb974
KH
3821appear is aref 1 or nil if any column is suitable. The supplementary
3822keyword to search forward for is aref 2 or nil if this is not
3823required. If aref 3 is t, then the \"begin\" keyword may be found in
3824the middle of a statement.
3825Assumes that the caller will make sure that we are not in the middle
3826of an identifier that just happens to contain an \"end\" keyword."
3827 (save-excursion
3828 (let (pos)
3829 (if (and (looking-at vhdl-end-fwd-re)
3830 (not (vhdl-in-literal lim))
3831 (vhdl-end-p lim))
3832 (if (looking-at "el")
3833 ;; "else", "elsif":
3834 (vector "if\\|elsif" (vhdl-first-word (point)) "then" nil)
3835 ;; "end ...":
3836 (setq pos (point))
3837 (forward-sexp)
3838 (skip-chars-forward " \t\n")
3839 (cond
3840 ;; "end if":
3841 ((looking-at "if\\b[^_]")
3842 (vector "else\\|elsif\\|if"
3843 (vhdl-first-word pos)
3844 "else\\|then" nil))
3845 ;; "end component":
3846 ((looking-at "component\\b[^_]")
3847 (vector (buffer-substring (match-beginning 1)
3848 (match-end 1))
3849 (vhdl-first-word pos)
3850 nil nil))
3851 ;; "end units", "end record":
3852 ((looking-at "\\(units\\|record\\)\\b[^_]")
3853 (vector (buffer-substring (match-beginning 1)
3854 (match-end 1))
3855 (vhdl-first-word pos)
3856 nil t))
5eabfe72
KH
3857 ;; "end block", "end process", "end procedural":
3858 ((looking-at "\\(block\\|process\\|procedural\\)\\b[^_]")
d2ddb974
KH
3859 (vector "begin" (vhdl-first-word pos) nil nil))
3860 ;; "end case":
3861 ((looking-at "case\\b[^_]")
3862 (vector "case" (vhdl-first-word pos) "is" nil))
3863 ;; "end generate":
3864 ((looking-at "generate\\b[^_]")
3865 (vector "generate\\|for\\|if"
3866 (vhdl-first-word pos)
3867 "generate" nil))
3868 ;; "end loop":
3869 ((looking-at "loop\\b[^_]")
3870 (vector "loop\\|while\\|for"
3871 (vhdl-first-word pos)
3872 "loop" nil))
3873 ;; "end for" (inside configuration declaration):
3874 ((looking-at "for\\b[^_]")
3875 (vector "for" (vhdl-first-word pos) nil nil))
3876 ;; "end [id]":
3877 (t
3878 (vector "begin\\|architecture\\|configuration\\|entity\\|package\\|procedure\\|function"
3879 (vhdl-first-word pos)
3880 ;; return an alist of (statement . keyword) mappings
3881 '(
3882 ;; "begin ... end [id]":
3883 ("begin" . nil)
3884 ;; "architecture ... is ... begin ... end [id]":
3885 ("architecture" . "is")
3886 ;; "configuration ... is ... end [id]":
3887 ("configuration" . "is")
3888 ;; "entity ... is ... end [id]":
3889 ("entity" . "is")
3890 ;; "package ... is ... end [id]":
3891 ("package" . "is")
3892 ;; "procedure ... is ... begin ... end [id]":
3893 ("procedure" . "is")
3894 ;; "function ... is ... begin ... end [id]":
3895 ("function" . "is")
3896 )
3897 nil))
3898 ))) ; "end ..."
3899 )))
3900
3901(defconst vhdl-leader-re
5eabfe72 3902 "\\b\\(block\\|component\\|process\\|procedural\\|for\\)\\b[^_]")
d2ddb974
KH
3903
3904(defun vhdl-end-of-leader ()
3905 (save-excursion
5eabfe72 3906 (cond ((looking-at "block\\|process\\|procedural")
d2ddb974
KH
3907 (if (save-excursion
3908 (forward-sexp)
3909 (skip-chars-forward " \t\n")
3910 (= (following-char) ?\())
3911 (forward-sexp 2)
3912 (forward-sexp))
3913 (point))
3914 ((looking-at "component")
3915 (forward-sexp 2)
3916 (point))
3917 ((looking-at "for")
3918 (forward-sexp 2)
3919 (skip-chars-forward " \t\n")
3920 (while (looking-at "[,:(]")
3921 (forward-sexp)
3922 (skip-chars-forward " \t\n"))
3923 (point))
3924 (t nil)
3925 )))
3926
3927(defconst vhdl-trailer-re
3928 "\\b\\(is\\|then\\|generate\\|loop\\)\\b[^_]")
3929
3930(defconst vhdl-statement-fwd-re
3931 "\\b\\(if\\|for\\|while\\)\\b\\([^_]\\|\\'\\)"
3932 "A regular expression for searching forward that matches all known
3933\"statement\" keywords.")
3934
3935(defconst vhdl-statement-bwd-re
3936 "\\b\\(if\\|for\\|while\\)\\b[^_]"
3937 "A regular expression for searching backward that matches all known
3938\"statement\" keywords.")
3939
3940(defun vhdl-statement-p (&optional lim)
3941 "Return t if we are looking at a real \"statement\" keyword.
3942Assumes that the caller will make sure that we are looking at
5eabfe72
KH
3943vhdl-statement-fwd-re, and are not inside a literal, and that we are not
3944in the middle of an identifier that just happens to contain a
3945\"statement\" keyword."
d2ddb974
KH
3946 (cond
3947 ;; "for" ... "generate":
3948 ((and (looking-at "f")
3949 ;; Make sure it's the start of a parameter specification.
3950 (save-excursion
3951 (forward-sexp 2)
3952 (skip-chars-forward " \t\n")
3953 (looking-at "in\\b[^_]"))
3954 ;; Make sure it's not an "end for".
3955 (save-excursion
3956 (backward-sexp)
3957 (not (looking-at "end\\s-+\\w"))))
3958 t)
3959 ;; "if" ... "then", "if" ... "generate", "if" ... "loop":
3960 ((and (looking-at "i")
3961 ;; Make sure it's not an "end if".
3962 (save-excursion
3963 (backward-sexp)
3964 (not (looking-at "end\\s-+\\w"))))
3965 t)
3966 ;; "while" ... "loop":
3967 ((looking-at "w")
3968 t)
3969 ))
3970
3971(defconst vhdl-case-alternative-re "when[( \t\n][^;=>]+=>"
3972 "Regexp describing a case statement alternative key.")
3973
3974(defun vhdl-case-alternative-p (&optional lim)
3975 "Return t if we are looking at a real case alternative.
3976Assumes that the caller will make sure that we are looking at
3977vhdl-case-alternative-re, and are not inside a literal, and that
3978we are not in the middle of an identifier that just happens to
3979contain a \"when\" keyword."
3980 (save-excursion
3981 (let (foundp)
3982 (while (and (not foundp)
3983 (re-search-backward ";\\|<=" lim 'move))
3984 (if (or (= (preceding-char) ?_)
3985 (vhdl-in-literal lim))
3986 (backward-char)
3987 (setq foundp t)))
3988 (or (eq (following-char) ?\;)
3989 (eq (point) lim)))
3990 ))
3991
3992;; Core syntactic movement functions:
3993
3994(defconst vhdl-b-t-b-re
3995 (concat vhdl-begin-bwd-re "\\|" vhdl-end-bwd-re))
3996
3997(defun vhdl-backward-to-block (&optional lim)
3998 "Move backward to the previous \"begin\" or \"end\" keyword."
3999 (let (foundp)
4000 (while (and (not foundp)
4001 (re-search-backward vhdl-b-t-b-re lim 'move))
4002 (if (or (= (preceding-char) ?_)
4003 (vhdl-in-literal lim))
4004 (backward-char)
4005 (cond
4006 ;; "begin" keyword:
4007 ((and (looking-at vhdl-begin-fwd-re)
4008 (/= (preceding-char) ?_)
4009 (vhdl-begin-p lim))
4010 (setq foundp 'begin))
4011 ;; "end" keyword:
4012 ((and (looking-at vhdl-end-fwd-re)
4013 (/= (preceding-char) ?_)
4014 (vhdl-end-p lim))
4015 (setq foundp 'end))
4016 ))
4017 )
4018 foundp
4019 ))
4020
4021(defun vhdl-forward-sexp (&optional count lim)
4022 "Move forward across one balanced expression (sexp).
4023With COUNT, do it that many times."
4024 (interactive "p")
4025 (let ((count (or count 1))
4026 (case-fold-search t)
4027 end-vec target)
4028 (save-excursion
4029 (while (> count 0)
4030 ;; skip whitespace
4031 (skip-chars-forward " \t\n")
4032 ;; Check for an unbalanced "end" keyword
4033 (if (and (looking-at vhdl-end-fwd-re)
4034 (/= (preceding-char) ?_)
4035 (not (vhdl-in-literal lim))
4036 (vhdl-end-p lim)
4037 (not (looking-at "else")))
4038 (error
4039 "Containing expression ends prematurely in vhdl-forward-sexp"))
4040 ;; If the current keyword is a "begin" keyword, then find the
4041 ;; corresponding "end" keyword.
4042 (if (setq end-vec (vhdl-corresponding-end lim))
4043 (let (
4044 ;; end-re is the statement keyword to search for
4045 (end-re
4046 (concat "\\b\\(" (aref end-vec 0) "\\)\\b\\([^_]\\|\\'\\)"))
4047 ;; column is either the statement keyword target column
4048 ;; or nil
4049 (column (aref end-vec 1))
4050 (eol (vhdl-point 'eol))
4051 foundp literal placeholder)
4052 ;; Look for the statement keyword.
4053 (while (and (not foundp)
4054 (re-search-forward end-re nil t)
4055 (setq placeholder (match-end 1))
4056 (goto-char (match-beginning 0)))
4057 ;; If we are in a literal, or not in the right target
4058 ;; column and not on the same line as the begin, then
4059 ;; try again.
4060 (if (or (and column
4061 (/= (current-indentation) column)
4062 (> (point) eol))
4063 (= (preceding-char) ?_)
4064 (setq literal (vhdl-in-literal lim)))
4065 (if (eq literal 'comment)
4066 (end-of-line)
4067 (forward-char))
4068 ;; An "else" keyword corresponds to both the opening brace
4069 ;; of the following sexp and the closing brace of the
4070 ;; previous sexp.
4071 (if (not (looking-at "else"))
4072 (goto-char placeholder))
4073 (setq foundp t))
4074 )
4075 (if (not foundp)
4076 (error "Unbalanced keywords in vhdl-forward-sexp"))
4077 )
4078 ;; If the current keyword is not a "begin" keyword, then just
4079 ;; perform the normal forward-sexp.
4080 (forward-sexp)
4081 )
4082 (setq count (1- count))
4083 )
4084 (setq target (point)))
4085 (goto-char target)
4086 nil))
4087
4088(defun vhdl-backward-sexp (&optional count lim)
4089 "Move backward across one balanced expression (sexp).
4090With COUNT, do it that many times. LIM bounds any required backward
4091searches."
4092 (interactive "p")
4093 (let ((count (or count 1))
4094 (case-fold-search t)
4095 begin-vec target)
4096 (save-excursion
4097 (while (> count 0)
4098 ;; Perform the normal backward-sexp, unless we are looking at
4099 ;; "else" - an "else" keyword corresponds to both the opening brace
4100 ;; of the following sexp and the closing brace of the previous sexp.
4101 (if (and (looking-at "else\\b\\([^_]\\|\\'\\)")
4102 (/= (preceding-char) ?_)
4103 (not (vhdl-in-literal lim)))
4104 nil
4105 (backward-sexp)
4106 (if (and (looking-at vhdl-begin-fwd-re)
4107 (/= (preceding-char) ?_)
4108 (not (vhdl-in-literal lim))
4109 (vhdl-begin-p lim))
4110 (error "Containing expression ends prematurely in vhdl-backward-sexp")))
4111 ;; If the current keyword is an "end" keyword, then find the
4112 ;; corresponding "begin" keyword.
4113 (if (and (setq begin-vec (vhdl-corresponding-begin lim))
4114 (/= (preceding-char) ?_))
4115 (let (
4116 ;; begin-re is the statement keyword to search for
4117 (begin-re
4118 (concat "\\b\\(" (aref begin-vec 0) "\\)\\b[^_]"))
4119 ;; column is either the statement keyword target column
4120 ;; or nil
4121 (column (aref begin-vec 1))
4122 ;; internal-p controls where the statement keyword can
4123 ;; be found.
4124 (internal-p (aref begin-vec 3))
4125 (last-backward (point)) last-forward
4126 foundp literal keyword)
4127 ;; Look for the statement keyword.
4128 (while (and (not foundp)
4129 (re-search-backward begin-re lim t)
4130 (setq keyword
4131 (buffer-substring (match-beginning 1)
4132 (match-end 1))))
4133 ;; If we are in a literal or in the wrong column,
4134 ;; then try again.
4135 (if (or (and column
4136 (and (/= (current-indentation) column)
4137 ;; possibly accept current-column as
4138 ;; well as current-indentation.
4139 (or (not internal-p)
4140 (/= (current-column) column))))
4141 (= (preceding-char) ?_)
4142 (vhdl-in-literal lim))
4143 (backward-char)
4144 ;; If there is a supplementary keyword, then
4145 ;; search forward for it.
4146 (if (and (setq begin-re (aref begin-vec 2))
4147 (or (not (listp begin-re))
4148 ;; If begin-re is an alist, then find the
4149 ;; element corresponding to the actual
4150 ;; keyword that we found.
4151 (progn
4152 (setq begin-re
4153 (assoc keyword begin-re))
4154 (and begin-re
4155 (setq begin-re (cdr begin-re))))))
4156 (and
4157 (setq begin-re
4158 (concat "\\b\\(" begin-re "\\)\\b[^_]"))
4159 (save-excursion
4160 (setq last-forward (point))
4161 ;; Look for the supplementary keyword
4162 ;; (bounded by the backward search start
4163 ;; point).
4164 (while (and (not foundp)
4165 (re-search-forward begin-re
4166 last-backward t)
4167 (goto-char (match-beginning 1)))
4168 ;; If we are in a literal, then try again.
4169 (if (or (= (preceding-char) ?_)
4170 (setq literal
4171 (vhdl-in-literal last-forward)))
4172 (if (eq literal 'comment)
4173 (goto-char
4174 (min (vhdl-point 'eol) last-backward))
4175 (forward-char))
4176 ;; We have found the supplementary keyword.
4177 ;; Save the position of the keyword in foundp.
4178 (setq foundp (point)))
4179 )
4180 foundp)
4181 ;; If the supplementary keyword was found, then
4182 ;; move point to the supplementary keyword.
4183 (goto-char foundp))
4184 ;; If there was no supplementary keyword, then
4185 ;; point is already at the statement keyword.
4186 (setq foundp t)))
4187 ) ; end of the search for the statement keyword
4188 (if (not foundp)
4189 (error "Unbalanced keywords in vhdl-backward-sexp"))
4190 ))
4191 (setq count (1- count))
4192 )
4193 (setq target (point)))
4194 (goto-char target)
4195 nil))
4196
4197(defun vhdl-backward-up-list (&optional count limit)
4198 "Move backward out of one level of blocks.
4199With argument, do this that many times."
4200 (interactive "p")
4201 (let ((count (or count 1))
4202 target)
4203 (save-excursion
4204 (while (> count 0)
4205 (if (looking-at vhdl-defun-re)
4206 (error "Unbalanced blocks"))
4207 (vhdl-backward-to-block limit)
4208 (setq count (1- count)))
4209 (setq target (point)))
4210 (goto-char target)))
4211
4212(defun vhdl-end-of-defun (&optional count)
4213 "Move forward to the end of a VHDL defun."
4214 (interactive)
4215 (let ((case-fold-search t))
4216 (vhdl-beginning-of-defun)
5eabfe72 4217 (if (not (looking-at "block\\|process\\|procedural"))
d2ddb974
KH
4218 (re-search-forward "\\bis\\b"))
4219 (vhdl-forward-sexp)))
4220
4221(defun vhdl-mark-defun ()
4222 "Put mark at end of this \"defun\", point at beginning."
4223 (interactive)
4224 (let ((case-fold-search t))
4225 (push-mark)
4226 (vhdl-beginning-of-defun)
4227 (push-mark)
5eabfe72 4228 (if (not (looking-at "block\\|process\\|procedural"))
d2ddb974
KH
4229 (re-search-forward "\\bis\\b"))
4230 (vhdl-forward-sexp)
4231 (exchange-point-and-mark)))
4232
4233(defun vhdl-beginning-of-libunit ()
4234 "Move backward to the beginning of a VHDL library unit.
4235Returns the location of the corresponding begin keyword, unless search
5eabfe72
KH
4236stops due to beginning or end of buffer.
4237Note that if point is between the \"libunit\" keyword and the
4238corresponding \"begin\" keyword, then that libunit will not be
4239recognised, and the search will continue backwards. If point is
4240at the \"begin\" keyword, then the defun will be recognised. The
4241returned point is at the first character of the \"libunit\" keyword."
d2ddb974
KH
4242 (let ((last-forward (point))
4243 (last-backward
4244 ;; Just in case we are actually sitting on the "begin"
4245 ;; keyword, allow for the keyword and an extra character,
4246 ;; as this will be used when looking forward for the
4247 ;; "begin" keyword.
4248 (save-excursion (forward-word 1) (1+ (point))))
4249 foundp literal placeholder)
4250 ;; Find the "libunit" keyword.
4251 (while (and (not foundp)
4252 (re-search-backward vhdl-libunit-re nil 'move))
4253 ;; If we are in a literal, or not at a real libunit, then try again.
4254 (if (or (= (preceding-char) ?_)
4255 (vhdl-in-literal (point-min))
4256 (not (vhdl-libunit-p)))
4257 (backward-char)
4258 ;; Find the corresponding "begin" keyword.
4259 (setq last-forward (point))
4260 (while (and (not foundp)
4261 (re-search-forward "\\bis\\b[^_]" last-backward t)
4262 (setq placeholder (match-beginning 0)))
4263 (if (or (= (preceding-char) ?_)
4264 (setq literal (vhdl-in-literal last-forward)))
4265 ;; It wasn't a real keyword, so keep searching.
4266 (if (eq literal 'comment)
4267 (goto-char
4268 (min (vhdl-point 'eol) last-backward))
4269 (forward-char))
4270 ;; We have found the begin keyword, loop will exit.
4271 (setq foundp placeholder)))
4272 ;; Go back to the libunit keyword
4273 (goto-char last-forward)))
4274 foundp))
4275
4276(defun vhdl-beginning-of-defun (&optional count)
4277 "Move backward to the beginning of a VHDL defun.
4278With argument, do it that many times.
4279Returns the location of the corresponding begin keyword, unless search
4280stops due to beginning or end of buffer."
4281 ;; Note that if point is between the "defun" keyword and the
4282 ;; corresponding "begin" keyword, then that defun will not be
4283 ;; recognised, and the search will continue backwards. If point is
4284 ;; at the "begin" keyword, then the defun will be recognised. The
4285 ;; returned point is at the first character of the "defun" keyword.
4286 (interactive "p")
4287 (let ((count (or count 1))
4288 (case-fold-search t)
4289 (last-forward (point))
4290 foundp)
4291 (while (> count 0)
4292 (setq foundp nil)
4293 (goto-char last-forward)
4294 (let ((last-backward
4295 ;; Just in case we are actually sitting on the "begin"
4296 ;; keyword, allow for the keyword and an extra character,
4297 ;; as this will be used when looking forward for the
4298 ;; "begin" keyword.
4299 (save-excursion (forward-word 1) (1+ (point))))
4300 begin-string literal)
4301 (while (and (not foundp)
4302 (re-search-backward vhdl-defun-re nil 'move))
4303 ;; If we are in a literal, then try again.
4304 (if (or (= (preceding-char) ?_)
4305 (vhdl-in-literal (point-min)))
4306 (backward-char)
4307 (if (setq begin-string (vhdl-corresponding-defun))
4308 ;; This is a real defun keyword.
4309 ;; Find the corresponding "begin" keyword.
4310 ;; Look for the begin keyword.
4311 (progn
4312 ;; Save the search start point.
4313 (setq last-forward (point))
4314 (while (and (not foundp)
4315 (search-forward begin-string last-backward t))
4316 (if (or (= (preceding-char) ?_)
4317 (save-match-data
4318 (setq literal (vhdl-in-literal last-forward))))
4319 ;; It wasn't a real keyword, so keep searching.
4320 (if (eq literal 'comment)
4321 (goto-char
4322 (min (vhdl-point 'eol) last-backward))
4323 (forward-char))
4324 ;; We have found the begin keyword, loop will exit.
4325 (setq foundp (match-beginning 0)))
4326 )
4327 ;; Go back to the defun keyword
4328 (goto-char last-forward)) ; end search for begin keyword
4329 ))
4330 ) ; end of the search for the defun keyword
4331 )
4332 (setq count (1- count))
4333 )
4334 (vhdl-keep-region-active)
4335 foundp))
4336
4337(defun vhdl-beginning-of-statement (&optional count lim)
4338 "Go to the beginning of the innermost VHDL statement.
4339With prefix arg, go back N - 1 statements. If already at the
4340beginning of a statement then go to the beginning of the preceding
4341one. If within a string or comment, or next to a comment (only
4342whitespace between), move by sentences instead of statements.
4343
4344When called from a program, this function takes 2 optional args: the
4345prefix arg, and a buffer position limit which is the farthest back to
4346search."
4347 (interactive "p")
4348 (let ((count (or count 1))
4349 (case-fold-search t)
4350 (lim (or lim (point-min)))
4351 (here (point))
4352 state)
4353 (save-excursion
4354 (goto-char lim)
4355 (setq state (parse-partial-sexp (point) here nil nil)))
4356 (if (and (interactive-p)
4357 (or (nth 3 state)
4358 (nth 4 state)
4359 (looking-at (concat "[ \t]*" comment-start-skip))))
4360 (forward-sentence (- count))
4361 (while (> count 0)
4362 (vhdl-beginning-of-statement-1 lim)
4363 (setq count (1- count))))
4364 ;; its possible we've been left up-buf of lim
4365 (goto-char (max (point) lim))
4366 )
4367 (vhdl-keep-region-active))
4368
4369(defconst vhdl-e-o-s-re
4370 (concat ";\\|" vhdl-begin-fwd-re "\\|" vhdl-statement-fwd-re))
4371
4372(defun vhdl-end-of-statement ()
4373 "Very simple implementation."
4374 (interactive)
4375 (re-search-forward vhdl-e-o-s-re))
4376
4377(defconst vhdl-b-o-s-re
4378 (concat ";\\|\(\\|\)\\|\\bwhen\\b[^_]\\|"
4379 vhdl-begin-bwd-re "\\|" vhdl-statement-bwd-re))
4380
4381(defun vhdl-beginning-of-statement-1 (&optional lim)
5eabfe72
KH
4382 "Move to the start of the current statement, or the previous
4383statement if already at the beginning of one."
d2ddb974
KH
4384 (let ((lim (or lim (point-min)))
4385 (here (point))
4386 (pos (point))
4387 donep)
4388 ;; go backwards one balanced expression, but be careful of
4389 ;; unbalanced paren being reached
4390 (if (not (vhdl-safe (progn (backward-sexp) t)))
4391 (progn
4392 (backward-up-list 1)
4393 (forward-char)
4394 (vhdl-forward-syntactic-ws here)
4395 (setq donep t)))
4396 (while (and (not donep)
4397 (not (bobp))
4398 ;; look backwards for a statement boundary
4399 (re-search-backward vhdl-b-o-s-re lim 'move))
4400 (if (or (= (preceding-char) ?_)
4401 (vhdl-in-literal lim))
4402 (backward-char)
4403 (cond
4404 ;; If we are looking at an open paren, then stop after it
4405 ((eq (following-char) ?\()
4406 (forward-char)
4407 (vhdl-forward-syntactic-ws here)
4408 (setq donep t))
4409 ;; If we are looking at a close paren, then skip it
4410 ((eq (following-char) ?\))
4411 (forward-char)
4412 (setq pos (point))
4413 (backward-sexp)
4414 (if (< (point) lim)
4415 (progn (goto-char pos)
4416 (vhdl-forward-syntactic-ws here)
4417 (setq donep t))))
4418 ;; If we are looking at a semicolon, then stop
4419 ((eq (following-char) ?\;)
4420 (progn
4421 (forward-char)
4422 (vhdl-forward-syntactic-ws here)
4423 (setq donep t)))
4424 ;; If we are looking at a "begin", then stop
4425 ((and (looking-at vhdl-begin-fwd-re)
4426 (/= (preceding-char) ?_)
4427 (vhdl-begin-p nil))
4428 ;; If it's a leader "begin", then find the
4429 ;; right place
4430 (if (looking-at vhdl-leader-re)
4431 (save-excursion
4432 ;; set a default stop point at the begin
4433 (setq pos (point))
4434 ;; is the start point inside the leader area ?
4435 (goto-char (vhdl-end-of-leader))
4436 (vhdl-forward-syntactic-ws here)
4437 (if (< (point) here)
4438 ;; start point was not inside leader area
4439 ;; set stop point at word after leader
4440 (setq pos (point))))
4441 (forward-word 1)
4442 (vhdl-forward-syntactic-ws here)
4443 (setq pos (point)))
4444 (goto-char pos)
4445 (setq donep t))
4446 ;; If we are looking at a "statement", then stop
4447 ((and (looking-at vhdl-statement-fwd-re)
4448 (/= (preceding-char) ?_)
4449 (vhdl-statement-p nil))
4450 (setq donep t))
4451 ;; If we are looking at a case alternative key, then stop
5eabfe72
KH
4452 ((and (looking-at vhdl-case-alternative-re)
4453 (vhdl-case-alternative-p lim))
d2ddb974
KH
4454 (save-excursion
4455 ;; set a default stop point at the when
4456 (setq pos (point))
4457 ;; is the start point inside the case alternative key ?
4458 (looking-at vhdl-case-alternative-re)
4459 (goto-char (match-end 0))
4460 (vhdl-forward-syntactic-ws here)
4461 (if (< (point) here)
4462 ;; start point was not inside the case alternative key
4463 ;; set stop point at word after case alternative keyleader
4464 (setq pos (point))))
4465 (goto-char pos)
4466 (setq donep t))
4467 ;; Bogus find, continue
4468 (t
4469 (backward-char)))))
4470 ))
4471
4472;; Defuns for calculating the current syntactic state:
4473
4474(defun vhdl-get-library-unit (bod placeholder)
5eabfe72
KH
4475 "If there is an enclosing library unit at bod, with it's \"begin\"
4476keyword at placeholder, then return the library unit type."
d2ddb974
KH
4477 (let ((here (vhdl-point 'bol)))
4478 (if (save-excursion
4479 (goto-char placeholder)
4480 (vhdl-safe (vhdl-forward-sexp 1 bod))
4481 (<= here (point)))
4482 (save-excursion
4483 (goto-char bod)
4484 (cond
4485 ((looking-at "e") 'entity)
4486 ((looking-at "a") 'architecture)
4487 ((looking-at "c") 'configuration)
4488 ((looking-at "p")
4489 (save-excursion
4490 (goto-char bod)
4491 (forward-sexp)
4492 (vhdl-forward-syntactic-ws here)
4493 (if (looking-at "body\\b[^_]")
4494 'package-body 'package))))))
4495 ))
4496
4497(defun vhdl-get-block-state (&optional lim)
5eabfe72
KH
4498 "Finds and records all the closest opens.
4499lim is the furthest back we need to search (it should be the
4500previous libunit keyword)."
d2ddb974
KH
4501 (let ((here (point))
4502 (lim (or lim (point-min)))
4503 keyword sexp-start sexp-mid sexp-end
4504 preceding-sexp containing-sexp
4505 containing-begin containing-mid containing-paren)
4506 (save-excursion
4507 ;; Find the containing-paren, and use that as the limit
4508 (if (setq containing-paren
4509 (save-restriction
4510 (narrow-to-region lim (point))
4511 (vhdl-safe (scan-lists (point) -1 1))))
4512 (setq lim containing-paren))
4513 ;; Look backwards for "begin" and "end" keywords.
4514 (while (and (> (point) lim)
4515 (not containing-sexp))
4516 (setq keyword (vhdl-backward-to-block lim))
4517 (cond
4518 ((eq keyword 'begin)
4519 ;; Found a "begin" keyword
4520 (setq sexp-start (point))
4521 (setq sexp-mid (vhdl-corresponding-mid lim))
4522 (setq sexp-end (vhdl-safe
4523 (save-excursion
4524 (vhdl-forward-sexp 1 lim) (point))))
4525 (if (and sexp-end (<= sexp-end here))
4526 ;; we want to record this sexp, but we only want to
4527 ;; record the last-most of any of them before here
4528 (or preceding-sexp
4529 (setq preceding-sexp sexp-start))
4530 ;; we're contained in this sexp so put sexp-start on
4531 ;; front of list
4532 (setq containing-sexp sexp-start)
4533 (setq containing-mid sexp-mid)
4534 (setq containing-begin t)))
4535 ((eq keyword 'end)
4536 ;; Found an "end" keyword
4537 (forward-sexp)
4538 (setq sexp-end (point))
4539 (setq sexp-mid nil)
4540 (setq sexp-start
4541 (or (vhdl-safe (vhdl-backward-sexp 1 lim) (point))
4542 (progn (backward-sexp) (point))))
4543 ;; we want to record this sexp, but we only want to
4544 ;; record the last-most of any of them before here
4545 (or preceding-sexp
4546 (setq preceding-sexp sexp-start)))
4547 )))
4548 ;; Check if the containing-paren should be the containing-sexp
4549 (if (and containing-paren
4550 (or (null containing-sexp)
4551 (< containing-sexp containing-paren)))
4552 (setq containing-sexp containing-paren
4553 preceding-sexp nil
4554 containing-begin nil
4555 containing-mid nil))
4556 (vector containing-sexp preceding-sexp containing-begin containing-mid)
4557 ))
4558
4559
4560(defconst vhdl-s-c-a-re
4561 (concat vhdl-case-alternative-re "\\|" vhdl-case-header-key))
4562
4563(defun vhdl-skip-case-alternative (&optional lim)
5eabfe72
KH
4564 "Skip forward over case/when bodies, with optional maximal
4565limit. If no next case alternative is found, nil is returned and point
4566is not moved."
d2ddb974
KH
4567 (let ((lim (or lim (point-max)))
4568 (here (point))
4569 donep foundp)
4570 (while (and (< (point) lim)
4571 (not donep))
4572 (if (and (re-search-forward vhdl-s-c-a-re lim 'move)
4573 (save-match-data
4574 (not (vhdl-in-literal)))
4575 (/= (match-beginning 0) here))
4576 (progn
4577 (goto-char (match-beginning 0))
4578 (cond
4579 ((and (looking-at "case")
4580 (re-search-forward "\\bis[^_]" lim t))
4581 (backward-sexp)
4582 (vhdl-forward-sexp))
4583 (t
4584 (setq donep t
4585 foundp t))))))
4586 (if (not foundp)
4587 (goto-char here))
4588 foundp))
4589
4590(defun vhdl-backward-skip-label (&optional lim)
5eabfe72
KH
4591 "Skip backward over a label, with optional maximal
4592limit. If label is not found, nil is returned and point
4593is not moved."
d2ddb974
KH
4594 (let ((lim (or lim (point-min)))
4595 placeholder)
4596 (if (save-excursion
4597 (vhdl-backward-syntactic-ws lim)
4598 (and (eq (preceding-char) ?:)
4599 (progn
4600 (backward-sexp)
4601 (setq placeholder (point))
4602 (looking-at vhdl-label-key))))
4603 (goto-char placeholder))
4604 ))
4605
4606(defun vhdl-forward-skip-label (&optional lim)
5eabfe72
KH
4607 "Skip forward over a label, with optional maximal
4608limit. If label is not found, nil is returned and point
4609is not moved."
d2ddb974
KH
4610 (let ((lim (or lim (point-max))))
4611 (if (looking-at vhdl-label-key)
4612 (progn
4613 (goto-char (match-end 0))
4614 (vhdl-forward-syntactic-ws lim)))
4615 ))
4616
4617(defun vhdl-get-syntactic-context ()
5eabfe72 4618 "Guess the syntactic description of the current line of VHDL code."
d2ddb974
KH
4619 (save-excursion
4620 (save-restriction
4621 (beginning-of-line)
4622 (let* ((indent-point (point))
4623 (case-fold-search t)
4624 vec literal containing-sexp preceding-sexp
4625 containing-begin containing-mid containing-leader
4626 char-before-ip char-after-ip begin-after-ip end-after-ip
4627 placeholder lim library-unit
4628 )
4629
4630 ;; Reset the syntactic context
4631 (setq vhdl-syntactic-context nil)
4632
4633 (save-excursion
4634 ;; Move to the start of the previous library unit, and
4635 ;; record the position of the "begin" keyword.
4636 (setq placeholder (vhdl-beginning-of-libunit))
4637 ;; The position of the "libunit" keyword gives us a gross
4638 ;; limit point.
4639 (setq lim (point))
4640 )
4641
4642 ;; If there is a previous library unit, and we are enclosed by
4643 ;; it, then set the syntax accordingly.
4644 (and placeholder
4645 (setq library-unit (vhdl-get-library-unit lim placeholder))
4646 (vhdl-add-syntax library-unit lim))
4647
4648 ;; Find the surrounding state.
4649 (if (setq vec (vhdl-get-block-state lim))
4650 (progn
4651 (setq containing-sexp (aref vec 0))
4652 (setq preceding-sexp (aref vec 1))
4653 (setq containing-begin (aref vec 2))
4654 (setq containing-mid (aref vec 3))
4655 ))
4656
4657 ;; set the limit on the farthest back we need to search
4658 (setq lim (if containing-sexp
4659 (save-excursion
4660 (goto-char containing-sexp)
4661 ;; set containing-leader if required
4662 (if (looking-at vhdl-leader-re)
4663 (setq containing-leader (vhdl-end-of-leader)))
4664 (vhdl-point 'bol))
4665 (point-min)))
4666
4667 ;; cache char before and after indent point, and move point to
4668 ;; the most likely position to perform the majority of tests
4669 (goto-char indent-point)
4670 (skip-chars-forward " \t")
4671 (setq literal (vhdl-in-literal lim))
4672 (setq char-after-ip (following-char))
4673 (setq begin-after-ip (and
4674 (not literal)
4675 (looking-at vhdl-begin-fwd-re)
4676 (vhdl-begin-p)))
4677 (setq end-after-ip (and
4678 (not literal)
4679 (looking-at vhdl-end-fwd-re)
4680 (vhdl-end-p)))
4681 (vhdl-backward-syntactic-ws lim)
4682 (setq char-before-ip (preceding-char))
4683 (goto-char indent-point)
4684 (skip-chars-forward " \t")
4685
4686 ;; now figure out syntactic qualities of the current line
4687 (cond
4688 ;; CASE 1: in a string or comment.
4689 ((memq literal '(string comment))
4690 (vhdl-add-syntax literal (vhdl-point 'bopl)))
4691 ;; CASE 2: Line is at top level.
4692 ((null containing-sexp)
4693 ;; Find the point to which indentation will be relative
4694 (save-excursion
4695 (if (null preceding-sexp)
4696 ;; CASE 2X.1
4697 ;; no preceding-sexp -> use the preceding statement
4698 (vhdl-beginning-of-statement-1 lim)
4699 ;; CASE 2X.2
4700 ;; if there is a preceding-sexp then indent relative to it
4701 (goto-char preceding-sexp)
4702 ;; if not at boi, then the block-opening keyword is
4703 ;; probably following a label, so we need a different
4704 ;; relpos
4705 (if (/= (point) (vhdl-point 'boi))
4706 ;; CASE 2X.3
4707 (vhdl-beginning-of-statement-1 lim)))
4708 ;; v-b-o-s could have left us at point-min
4709 (and (bobp)
4710 ;; CASE 2X.4
4711 (vhdl-forward-syntactic-ws indent-point))
4712 (setq placeholder (point)))
4713 (cond
4714 ;; CASE 2A : we are looking at a block-open
4715 (begin-after-ip
4716 (vhdl-add-syntax 'block-open placeholder))
4717 ;; CASE 2B: we are looking at a block-close
4718 (end-after-ip
4719 (vhdl-add-syntax 'block-close placeholder))
4720 ;; CASE 2C: we are looking at a top-level statement
4721 ((progn
4722 (vhdl-backward-syntactic-ws lim)
4723 (or (bobp)
4724 (= (preceding-char) ?\;)))
4725 (vhdl-add-syntax 'statement placeholder))
4726 ;; CASE 2D: we are looking at a top-level statement-cont
4727 (t
4728 (vhdl-beginning-of-statement-1 lim)
4729 ;; v-b-o-s could have left us at point-min
4730 (and (bobp)
4731 ;; CASE 2D.1
4732 (vhdl-forward-syntactic-ws indent-point))
4733 (vhdl-add-syntax 'statement-cont (point)))
4734 )) ; end CASE 2
4735 ;; CASE 3: line is inside parentheses. Most likely we are
4736 ;; either in a subprogram argument (interface) list, or a
4737 ;; continued expression containing parentheses.
4738 ((null containing-begin)
4739 (vhdl-backward-syntactic-ws containing-sexp)
4740 (cond
4741 ;; CASE 3A: we are looking at the arglist closing paren
4742 ((eq char-after-ip ?\))
4743 (goto-char containing-sexp)
4744 (vhdl-add-syntax 'arglist-close (vhdl-point 'boi)))
4745 ;; CASE 3B: we are looking at the first argument in an empty
4746 ;; argument list.
4747 ((eq char-before-ip ?\()
4748 (goto-char containing-sexp)
4749 (vhdl-add-syntax 'arglist-intro (vhdl-point 'boi)))
4750 ;; CASE 3C: we are looking at an arglist continuation line,
4751 ;; but the preceding argument is on the same line as the
4752 ;; opening paren. This case includes multi-line
4753 ;; expression paren groupings.
4754 ((and (save-excursion
4755 (goto-char (1+ containing-sexp))
4756 (skip-chars-forward " \t")
4757 (not (eolp))
4758 (not (looking-at "--")))
4759 (save-excursion
4760 (vhdl-beginning-of-statement-1 containing-sexp)
4761 (skip-chars-backward " \t(")
4762 (<= (point) containing-sexp)))
4763 (goto-char containing-sexp)
4764 (vhdl-add-syntax 'arglist-cont-nonempty (vhdl-point 'boi)))
4765 ;; CASE 3D: we are looking at just a normal arglist
4766 ;; continuation line
4767 (t (vhdl-beginning-of-statement-1 containing-sexp)
4768 (vhdl-forward-syntactic-ws indent-point)
4769 (vhdl-add-syntax 'arglist-cont (vhdl-point 'boi)))
4770 ))
4771 ;; CASE 4: A block mid open
4772 ((and begin-after-ip
4773 (looking-at containing-mid))
4774 (goto-char containing-sexp)
4775 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4776 (if (looking-at vhdl-trailer-re)
4777 ;; CASE 4.1
4778 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4779 (vhdl-backward-skip-label (vhdl-point 'boi))
4780 (vhdl-add-syntax 'block-open (point)))
4781 ;; CASE 5: block close brace
4782 (end-after-ip
4783 (goto-char containing-sexp)
4784 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4785 (if (looking-at vhdl-trailer-re)
4786 ;; CASE 5.1
4787 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4788 (vhdl-backward-skip-label (vhdl-point 'boi))
4789 (vhdl-add-syntax 'block-close (point)))
4790 ;; CASE 6: A continued statement
4791 ((and (/= char-before-ip ?\;)
4792 ;; check it's not a trailer begin keyword, or a begin
4793 ;; keyword immediately following a label.
4794 (not (and begin-after-ip
4795 (or (looking-at vhdl-trailer-re)
4796 (save-excursion
4797 (vhdl-backward-skip-label containing-sexp)))))
4798 ;; check it's not a statement keyword
4799 (not (and (looking-at vhdl-statement-fwd-re)
4800 (vhdl-statement-p)))
4801 ;; see if the b-o-s is before the indent point
4802 (> indent-point
4803 (save-excursion
4804 (vhdl-beginning-of-statement-1 containing-sexp)
4805 ;; If we ended up after a leader, then this will
4806 ;; move us forward to the start of the first
4807 ;; statement. Note that a containing sexp here is
4808 ;; always a keyword, not a paren, so this will
4809 ;; have no effect if we hit the containing-sexp.
4810 (vhdl-forward-syntactic-ws indent-point)
4811 (setq placeholder (point))))
4812 ;; check it's not a block-intro
4813 (/= placeholder containing-sexp)
4814 ;; check it's not a case block-intro
4815 (save-excursion
4816 (goto-char placeholder)
4817 (or (not (looking-at vhdl-case-alternative-re))
4818 (> (match-end 0) indent-point))))
4819 ;; Make placeholder skip a label, but only if it puts us
4820 ;; before the indent point at the start of a line.
4821 (let ((new placeholder))
4822 (if (and (> indent-point
4823 (save-excursion
4824 (goto-char placeholder)
4825 (vhdl-forward-skip-label indent-point)
4826 (setq new (point))))
4827 (save-excursion
4828 (goto-char new)
4829 (eq new (progn (back-to-indentation) (point)))))
4830 (setq placeholder new)))
4831 (vhdl-add-syntax 'statement-cont placeholder)
4832 (if begin-after-ip
4833 (vhdl-add-syntax 'block-open)))
4834 ;; Statement. But what kind?
4835 ;; CASE 7: A case alternative key
4836 ((and (looking-at vhdl-case-alternative-re)
4837 (vhdl-case-alternative-p containing-sexp))
4838 ;; for a case alternative key, we set relpos to the first
4839 ;; non-whitespace char on the line containing the "case"
4840 ;; keyword.
4841 (goto-char containing-sexp)
4842 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4843 (if (looking-at vhdl-trailer-re)
4844 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4845 (vhdl-add-syntax 'case-alternative (vhdl-point 'boi)))
4846 ;; CASE 8: statement catchall
4847 (t
4848 ;; we know its a statement, but we need to find out if it is
4849 ;; the first statement in a block
4850 (if containing-leader
4851 (goto-char containing-leader)
4852 (goto-char containing-sexp)
4853 ;; Note that a containing sexp here is always a keyword,
4854 ;; not a paren, so skip over the keyword.
4855 (forward-sexp))
4856 ;; move to the start of the first statement
4857 (vhdl-forward-syntactic-ws indent-point)
4858 (setq placeholder (point))
4859 ;; we want to ignore case alternatives keys when skipping forward
4860 (let (incase-p)
4861 (while (looking-at vhdl-case-alternative-re)
4862 (setq incase-p (point))
4863 ;; we also want to skip over the body of the
4864 ;; case/when statement if that doesn't put us at
4865 ;; after the indent-point
4866 (while (vhdl-skip-case-alternative indent-point))
4867 ;; set up the match end
4868 (looking-at vhdl-case-alternative-re)
4869 (goto-char (match-end 0))
4870 ;; move to the start of the first case alternative statement
4871 (vhdl-forward-syntactic-ws indent-point)
4872 (setq placeholder (point)))
4873 (cond
4874 ;; CASE 8A: we saw a case/when statement so we must be
4875 ;; in a switch statement. find out if we are at the
4876 ;; statement just after a case alternative key
4877 ((and incase-p
4878 (= (point) indent-point))
4879 ;; relpos is the "when" keyword
4880 (vhdl-add-syntax 'statement-case-intro incase-p))
4881 ;; CASE 8B: any old statement
4882 ((< (point) indent-point)
4883 ;; relpos is the first statement of the block
4884 (vhdl-add-syntax 'statement placeholder)
4885 (if begin-after-ip
4886 (vhdl-add-syntax 'block-open)))
4887 ;; CASE 8C: first statement in a block
4888 (t
4889 (goto-char containing-sexp)
4890 ;; If the \"begin\" keyword is a trailer, then find v-b-o-s
4891 (if (looking-at vhdl-trailer-re)
4892 (progn (forward-sexp) (vhdl-beginning-of-statement-1 nil)))
4893 (vhdl-backward-skip-label (vhdl-point 'boi))
4894 (vhdl-add-syntax 'statement-block-intro (point))
4895 (if begin-after-ip
4896 (vhdl-add-syntax 'block-open)))
4897 )))
4898 )
4899
4900 ;; now we need to look at any modifiers
4901 (goto-char indent-point)
4902 (skip-chars-forward " \t")
4903 (if (looking-at "--")
4904 (vhdl-add-syntax 'comment))
4905 ;; return the syntax
4906 vhdl-syntactic-context))))
4907
4908;; Standard indentation line-ups:
4909
4910(defun vhdl-lineup-arglist (langelem)
5eabfe72
KH
4911 "Lineup the current arglist line with the arglist appearing just
4912after the containing paren which starts the arglist."
d2ddb974
KH
4913 (save-excursion
4914 (let* ((containing-sexp
4915 (save-excursion
4916 ;; arglist-cont-nonempty gives relpos ==
4917 ;; to boi of containing-sexp paren. This
4918 ;; is good when offset is +, but bad
4919 ;; when it is vhdl-lineup-arglist, so we
4920 ;; have to special case a kludge here.
4921 (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty))
4922 (progn
4923 (beginning-of-line)
4924 (backward-up-list 1)
4925 (skip-chars-forward " \t" (vhdl-point 'eol)))
4926 (goto-char (cdr langelem)))
4927 (point)))
4928 (cs-curcol (save-excursion
4929 (goto-char (cdr langelem))
4930 (current-column))))
4931 (if (save-excursion
4932 (beginning-of-line)
4933 (looking-at "[ \t]*)"))
4934 (progn (goto-char (match-end 0))
4935 (backward-sexp)
4936 (forward-char)
4937 (vhdl-forward-syntactic-ws)
4938 (- (current-column) cs-curcol))
4939 (goto-char containing-sexp)
4940 (or (eolp)
4941 (let ((eol (vhdl-point 'eol))
4942 (here (progn
4943 (forward-char)
4944 (skip-chars-forward " \t")
4945 (point))))
4946 (vhdl-forward-syntactic-ws)
4947 (if (< (point) eol)
4948 (goto-char here))))
4949 (- (current-column) cs-curcol)
4950 ))))
4951
4952(defun vhdl-lineup-arglist-intro (langelem)
5eabfe72 4953 "Lineup an arglist-intro line to just after the open paren."
d2ddb974
KH
4954 (save-excursion
4955 (let ((cs-curcol (save-excursion
4956 (goto-char (cdr langelem))
4957 (current-column)))
4958 (ce-curcol (save-excursion
4959 (beginning-of-line)
4960 (backward-up-list 1)
4961 (skip-chars-forward " \t" (vhdl-point 'eol))
4962 (current-column))))
4963 (- ce-curcol cs-curcol -1))))
4964
4965(defun vhdl-lineup-comment (langelem)
5eabfe72
KH
4966 "Support old behavior for comment indentation. We look at
4967vhdl-comment-only-line-offset to decide how to indent comment
4968only-lines."
d2ddb974
KH
4969 (save-excursion
4970 (back-to-indentation)
4971 ;; at or to the right of comment-column
4972 (if (>= (current-column) comment-column)
4973 (vhdl-comment-indent)
4974 ;; otherwise, indent as specified by vhdl-comment-only-line-offset
4975 (if (not (bolp))
4976 (or (car-safe vhdl-comment-only-line-offset)
4977 vhdl-comment-only-line-offset)
4978 (or (cdr-safe vhdl-comment-only-line-offset)
4979 (car-safe vhdl-comment-only-line-offset)
5eabfe72 4980 -1000 ;jam it against the left side
d2ddb974
KH
4981 )))))
4982
4983(defun vhdl-lineup-statement-cont (langelem)
5eabfe72 4984 "Line up statement-cont after the assignment operator."
d2ddb974
KH
4985 (save-excursion
4986 (let* ((relpos (cdr langelem))
4987 (assignp (save-excursion
4988 (goto-char (vhdl-point 'boi))
4989 (and (re-search-forward "\\(<\\|:\\)="
4990 (vhdl-point 'eol) t)
4991 (- (point) (vhdl-point 'boi)))))
4992 (curcol (progn
4993 (goto-char relpos)
4994 (current-column)))
4995 foundp)
4996 (while (and (not foundp)
4997 (< (point) (vhdl-point 'eol)))
4998 (re-search-forward "\\(<\\|:\\)=\\|(" (vhdl-point 'eol) 'move)
4999 (if (vhdl-in-literal (cdr langelem))
5000 (forward-char)
5001 (if (= (preceding-char) ?\()
5002 ;; skip over any parenthesized expressions
5003 (goto-char (min (vhdl-point 'eol)
5004 (scan-lists (point) 1 1)))
5005 ;; found an assignment operator (not at eol)
5006 (setq foundp (not (looking-at "\\s-*$"))))))
5007 (if (not foundp)
5008 ;; there's no assignment operator on the line
5009 vhdl-basic-offset
5010 ;; calculate indentation column after assign and ws, unless
5011 ;; our line contains an assignment operator
5012 (if (not assignp)
5013 (progn
5014 (forward-char)
5015 (skip-chars-forward " \t")
5016 (setq assignp 0)))
5017 (- (current-column) assignp curcol))
5018 )))
5019
5eabfe72 5020;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
5021;; Indentation commands
5022
5eabfe72
KH
5023(defsubst vhdl-in-comment-p ()
5024 "Check if point is to right of beginning comment delimiter."
5025 (let ((position (point)))
5026 (save-excursion ; finds an unquoted comment
5027 (beginning-of-line)
5028 (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*--" position t))))
5029
5030(defsubst vhdl-in-string-p ()
5031 "Check if point is in a string."
5032 (let ((position (point)))
5033 (save-excursion ; preceeded by odd number of string delimiters?
5034 (beginning-of-line)
5035 (eq position (re-search-forward "^\\([^\"]*\"[^\"]*\"\\)*[^\"]*\"[^\"]*"
5036 position t)))))
5037
5038(defsubst vhdl-in-comment-or-string-p ()
5039 "Check if point is in a comment or a string."
5040 (and (vhdl-in-comment-p)
5041 (vhdl-in-string-p)))
5042
5043(defun vhdl-electric-tab (&optional prefix-arg)
5044 "If preceeding character is part of a word or a paren then hippie-expand,
d2ddb974
KH
5045else if right of non whitespace on line then tab-to-tab-stop,
5046else if last command was a tab or return then dedent one step,
5047else indent `correctly'."
5048 (interactive "*P")
5eabfe72
KH
5049 (vhdl-ext-syntax-table
5050 (cond ((= (char-syntax (preceding-char)) ?w)
5051 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5052 (case-replace nil))
5053 (vhdl-expand-abbrev prefix-arg)))
5054 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
5055 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
5056 (case-replace nil))
5057 (vhdl-expand-paren prefix-arg)))
5058 ((> (current-column) (current-indentation))
5059 (tab-to-tab-stop))
5060 ((and (or (eq last-command 'vhdl-electric-tab)
5061 (eq last-command 'vhdl-electric-return))
5062 (/= 0 (current-indentation)))
5063 (backward-delete-char-untabify vhdl-basic-offset nil))
5064 (t (vhdl-indent-line)))
5065 (setq this-command 'vhdl-electric-tab)))
5066
5067(defun vhdl-electric-return ()
d2ddb974
KH
5068 "newline-and-indent or indent-new-comment-line if in comment and preceding
5069character is a space."
5070 (interactive)
5071 (if (and (= (preceding-char) ? ) (vhdl-in-comment-p))
5072 (indent-new-comment-line)
5eabfe72
KH
5073 (newline-and-indent)))
5074
5075(defvar vhdl-progress-info nil
5076 "Array variable for progress information: 0 begin, 1 end, 2 time.")
d2ddb974
KH
5077
5078(defun vhdl-indent-line ()
5eabfe72 5079 "Indent the current line as VHDL code. Returns the amount of
d2ddb974
KH
5080indentation change."
5081 (interactive)
5082 (let* ((syntax (vhdl-get-syntactic-context))
5083 (pos (- (point-max) (point)))
5eabfe72
KH
5084 ;; special case: comments at or right of comment-column
5085 (indent (if (and (eq (car (car syntax)) 'comment)
5086 (>= (vhdl-get-offset (car syntax)) comment-column))
5087 (vhdl-get-offset (car syntax))
5088 (apply '+ (mapcar 'vhdl-get-offset syntax))))
5089; (indent (apply '+ (mapcar 'vhdl-get-offset syntax)))
5090 (shift-amt (- indent (current-indentation))))
d2ddb974
KH
5091 (and vhdl-echo-syntactic-information-p
5092 (message "syntax: %s, indent= %d" syntax indent))
5eabfe72 5093 (unless (zerop shift-amt)
d2ddb974
KH
5094 (delete-region (vhdl-point 'bol) (vhdl-point 'boi))
5095 (beginning-of-line)
5096 (indent-to indent))
5097 (if (< (point) (vhdl-point 'boi))
5098 (back-to-indentation)
5099 ;; If initial point was within line's indentation, position after
5100 ;; the indentation. Else stay at same point in text.
5eabfe72
KH
5101 (when (> (- (point-max) pos) (point))
5102 (goto-char (- (point-max) pos))))
d2ddb974 5103 (run-hooks 'vhdl-special-indent-hook)
5eabfe72
KH
5104 ;; update progress status
5105 (when vhdl-progress-info
5106 (aset vhdl-progress-info 1 (+ (aref vhdl-progress-info 1)
5107 (if (> -500 shift-amt) 0 shift-amt)))
5108 (when (< vhdl-progress-interval
5109 (- (nth 1 (current-time)) (aref vhdl-progress-info 2)))
5110 (message "Indenting... (%2d%s)"
5111 (/ (* 100 (- (point) (aref vhdl-progress-info 0)))
5112 (- (aref vhdl-progress-info 1)
5113 (aref vhdl-progress-info 0))) "%")
5114 (aset vhdl-progress-info 2 (nth 1 (current-time)))))
d2ddb974
KH
5115 shift-amt))
5116
5117(defun vhdl-indent-buffer ()
5eabfe72
KH
5118 "Indent whole buffer as VHDL code.
5119Calls `indent-region' for whole buffer and adds progress reporting."
d2ddb974 5120 (interactive)
5eabfe72
KH
5121 (when vhdl-progress-interval
5122 (setq vhdl-progress-info (vector (point-min) (point-max) 0)))
d2ddb974 5123 (indent-region (point-min) (point-max) nil)
5eabfe72
KH
5124 (when vhdl-progress-interval (message "Indenting...done"))
5125 (setq vhdl-progress-info nil))
5126
5127(defun vhdl-indent-region (start end column)
5128 "Indent region as VHDL code.
5129Adds progress reporting to `indent-region'."
5130 (interactive "r\nP")
5131 (when vhdl-progress-interval (setq vhdl-progress-info (vector start end 0)))
5132 (indent-region start end column)
5133 (when vhdl-progress-interval (message "Indenting...done"))
5134 (setq vhdl-progress-info nil))
d2ddb974
KH
5135
5136(defun vhdl-indent-sexp (&optional endpos)
5137 "Indent each line of the list starting just after point.
5138If optional arg ENDPOS is given, indent each line, stopping when
5139ENDPOS is encountered."
5140 (interactive)
5141 (save-excursion
5142 (let ((beg (point))
5eabfe72 5143 (end (progn (vhdl-forward-sexp nil endpos) (point))))
d2ddb974
KH
5144 (indent-region beg end nil))))
5145
5eabfe72 5146;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
5147;; Miscellaneous commands
5148
5149(defun vhdl-show-syntactic-information ()
5150 "Show syntactic information for current line."
5151 (interactive)
5152 (message "syntactic analysis: %s" (vhdl-get-syntactic-context))
5153 (vhdl-keep-region-active))
5154
5155;; Verification and regression functions:
5156
5157(defun vhdl-regress-line (&optional arg)
5158 "Check syntactic information for current line."
5159 (interactive "P")
5160 (let ((expected (save-excursion
5161 (end-of-line)
5eabfe72
KH
5162 (when (search-backward " -- ((" (vhdl-point 'bol) t)
5163 (forward-char 4)
5164 (read (current-buffer)))))
d2ddb974
KH
5165 (actual (vhdl-get-syntactic-context))
5166 (expurgated))
5167 ;; remove the library unit symbols
5168 (mapcar
5169 (function
5170 (lambda (elt)
5171 (if (memq (car elt) '(entity configuration package
5172 package-body architecture))
5173 nil
5174 (setq expurgated (append expurgated (list elt))))))
5175 actual)
5176 (if (and (not arg) expected (listp expected))
5177 (if (not (equal expected expurgated))
5178 (error "Should be: %s, is: %s" expected expurgated))
5179 (save-excursion
5180 (beginning-of-line)
5eabfe72
KH
5181 (when (not (looking-at "^\\s-*\\(--.*\\)?$"))
5182 (end-of-line)
5183 (if (search-backward " -- ((" (vhdl-point 'bol) t)
5184 (kill-line))
5185 (insert " -- ")
5186 (insert (format "%s" expurgated))))))
d2ddb974
KH
5187 (vhdl-keep-region-active))
5188
5189
5eabfe72
KH
5190;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5191;;; Alignment, whitespace fixup, beautifying
5192;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
5193
5194(defvar vhdl-align-alist
5195 '(
5196 ;; after some keywords
5eabfe72
KH
5197 (vhdl-mode "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)[ \t]"
5198 "\\<\\(constant\\|quantity\\|signal\\|terminal\\|variable\\)\\([ \t]+\\)" 2)
d2ddb974 5199 ;; before ':'
5eabfe72 5200 (vhdl-mode ":[^=]" "\\([ \t]*\\):[^=]")
d2ddb974 5201 ;; after direction specifications
5eabfe72
KH
5202 (vhdl-mode ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\>"
5203 ":[ \t]*\\(in\\|out\\|inout\\|buffer\\|\\)\\([ \t]+\\)" 2)
5204 ;; before "==", ":=", "=>", and "<="
5205 (vhdl-mode "==" "\\([ \t]*\\)==" 1)
5206 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since ":= ... =>" can occur
5207 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "<= ... =>" can occur
5208 (vhdl-mode "=>" "\\([ \t]*\\)=>" 1)
5209 (vhdl-mode ":=" "\\([ \t]*\\):=" 1) ; since "=> ... :=" can occur
5210 (vhdl-mode "<=" "\\([ \t]*\\)<=" 1) ; since "=> ... <=" can occur
d2ddb974
KH
5211 ;; before some keywords
5212 (vhdl-mode "[ \t]after\\>" "[^ \t]\\([ \t]+\\)after\\>" 1)
d2ddb974
KH
5213 (vhdl-mode "[ \t]when\\>" "[^ \t]\\([ \t]+\\)when\\>" 1)
5214 (vhdl-mode "[ \t]else\\>" "[^ \t]\\([ \t]+\\)else\\>" 1)
d2ddb974 5215 )
5eabfe72 5216 "The format of this alist is (MODES [or MODE] REGEXP ALIGN-PATTERN SUBEXP).
d2ddb974
KH
5217It is searched in order. If REGEXP is found anywhere in the first
5218line of a region to be aligned, ALIGN-PATTERN will be used for that
5219region. ALIGN-PATTERN must include the whitespace to be expanded or
5eabfe72
KH
5220contracted. It may also provide regexps for the text surrounding the
5221whitespace. SUBEXP specifies which sub-expression of
d2ddb974
KH
5222ALIGN-PATTERN matches the white space to be expanded/contracted.")
5223
5224(defvar vhdl-align-try-all-clauses t
5225 "If REGEXP is not found on the first line of the region that clause
5eabfe72 5226is ignored. If this variable is non-nil, then the clause is tried anyway.")
d2ddb974 5227
5eabfe72 5228(defun vhdl-align-region (begin end &optional spacing alignment-list indent)
d2ddb974 5229 "Attempt to align a range of lines based on the content of the
5eabfe72
KH
5230lines. The definition of `alignment-list' determines the matching
5231order and the manner in which the lines are aligned. If ALIGNMENT-LIST
5232is not specified `vhdl-align-alist' is used. If INDENT is non-nil,
d2ddb974
KH
5233indentation is done before aligning."
5234 (interactive "r\np")
5eabfe72
KH
5235 (setq alignment-list (or alignment-list vhdl-align-alist))
5236 (setq spacing (or spacing 1))
d2ddb974
KH
5237 (save-excursion
5238 (let (bol indent)
5239 (goto-char end)
5240 (setq end (point-marker))
5241 (goto-char begin)
5eabfe72
KH
5242 (setq bol (setq begin (progn (beginning-of-line) (point))))
5243 ; (untabify bol end)
5244 (when indent
5245 (indent-region bol end nil))))
5246 (let ((case-fold-search t)
5247 (copy (copy-alist alignment-list)))
5248 (vhdl-ext-syntax-table
5249 (while copy
5250 (save-excursion
5251 (goto-char begin)
5252 (let (element
5253 (eol (save-excursion (progn (end-of-line) (point)))))
5254 (setq element (nth 0 copy))
5255 (when (and (or (and (listp (car element))
5256 (memq major-mode (car element)))
5257 (eq major-mode (car element)))
5258 (or vhdl-align-try-all-clauses
5259 (re-search-forward (car (cdr element)) eol t)))
5260 (vhdl-align-region-1 begin end (car (cdr (cdr element)))
5261 (car (cdr (cdr (cdr element)))) spacing))
5262 (setq copy (cdr copy))))))))
5263
5264(defun vhdl-align-region-1 (begin end match &optional substr spacing)
d2ddb974
KH
5265 "Align a range of lines from BEGIN to END. The regular expression
5266MATCH must match exactly one fields: the whitespace to be
5267contracted/expanded. The alignment column will equal the
5268rightmost column of the widest whitespace block. SPACING is
5269the amount of extra spaces to add to the calculated maximum required.
5270SPACING defaults to 1 so that at least one space is inserted after
5271the token in MATCH."
5eabfe72
KH
5272 (setq spacing (or spacing 1))
5273 (setq substr (or substr 1))
d2ddb974
KH
5274 (save-excursion
5275 (let (distance (max 0) (lines 0) bol eol width)
5276 ;; Determine the greatest whitespace distance to the alignment
5277 ;; character
5278 (goto-char begin)
5279 (setq eol (progn (end-of-line) (point))
5eabfe72 5280 bol (setq begin (progn (beginning-of-line) (point))))
d2ddb974 5281 (while (< bol end)
5eabfe72
KH
5282 (save-excursion
5283 (when (and (re-search-forward match eol t)
5284 (not (vhdl-in-comment-p)))
5285 (setq distance (- (match-beginning substr) bol))
5286 (when (> distance max)
5287 (setq max distance))))
5288 (forward-line)
5289 (setq bol (point)
5290 eol (save-excursion (end-of-line) (point)))
5291 (setq lines (1+ lines)))
d2ddb974
KH
5292 ;; Now insert enough maxs to push each assignment operator to
5293 ;; the same column. We need to use 'lines' as a counter, since
5294 ;; the location of the mark may change
5295 (goto-char (setq bol begin))
5eabfe72 5296 (setq eol (save-excursion (end-of-line) (point)))
d2ddb974 5297 (while (> lines 0)
5eabfe72
KH
5298 (when (and (re-search-forward match eol t)
5299 (not (vhdl-in-comment-p)))
5300 (setq width (- (match-end substr) (match-beginning substr)))
5301 (setq distance (- (match-beginning substr) bol))
5302 (goto-char (match-beginning substr))
5303 (delete-char width)
5304 (insert-char ? (+ (- max distance) spacing)))
5305 (beginning-of-line)
5306 (forward-line)
5307 (setq bol (point)
5308 eol (save-excursion (end-of-line) (point)))
5309 (setq lines (1- lines))))))
5310
5311(defun vhdl-align-inline-comment-region-1 (beg end &optional spacing)
5312 "Align inline comments in region."
5313 (save-excursion
5314 (let ((high-start 0)
5315 (high-length 0)
5316 (case-fold-search t))
5317 (vhdl-ext-syntax-table
5318 (goto-char beg)
5319 ;; search for longest code line and longest inline comment
5320 (while (< (point) end)
5321 (cond
5322 ((and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5323 (looking-at "^\\(.*[^ \t\n-]+\\)\\s-*\\(--\\s-*.*\\)$"))
5324 (setq high-start
5325 (max high-start (- (match-end 1) (match-beginning 1))))
5326 (setq high-length
5327 (max high-length (- (match-end 2) (match-beginning 2)))))
5328 ((and (looking-at "^\\(\\s-*\\))\\(--\\s-*.*\\)$")
5329 (>= (- (match-end 1) (match-beginning 1)) comment-column))
5330 (setq high-length
5331 (max high-length (- (match-end 2) (match-beginning 2))))))
5332 (beginning-of-line 2))
5333 (goto-char beg)
5334 (setq spacing (or spacing 2))
5335 (setq high-start (+ high-start spacing))
5336 ;; align as nice as possible
5337 (while (< (point) end)
5338 (when (and (not (looking-at "^\\s-*\\(begin\\|end\\)\\>"))
5339 (or (looking-at "^.*[^ \t\n-]+\\(\\s-*\\)--")
5340 (and (looking-at "^\\(\\s-*\\)--")
5341 (>= (- (match-end 1) (match-beginning 1))
5342 comment-column))))
5343 (goto-char (match-end 1))
5344 (delete-region (match-beginning 1) (match-end 1))
5345 (insert-char ? spacing)
5346 (cond ((<= high-start comment-column)
5347 (indent-to comment-column))
5348 ((<= (+ high-start high-length) end-comment-column)
5349 (indent-to high-start))
5350 (t (indent-to comment-column))))
5351 (beginning-of-line 2))))))
5352
5353(defun vhdl-align-noindent-region (beg end &optional spacing no-message)
5354 "Align region without indentation."
d2ddb974 5355 (interactive "r\nP")
5eabfe72
KH
5356 (save-excursion
5357 (let (pos)
5358 (goto-char beg)
5359 (beginning-of-line)
5360 (setq beg (point))
5361 (goto-char end)
5362 (setq end (point-marker))
5363 (untabify beg end)
5364 (unless no-message (message "Aligning..."))
5365 (vhdl-fixup-whitespace-region beg end t)
5366 (goto-char beg)
5367 (if (not vhdl-align-groups)
5368 ;; align entire region
5369 (progn (vhdl-align-region beg end spacing)
5370 (vhdl-align-inline-comment-region-1 beg end))
5371 ;; align groups
5372 (while (and (< beg end)
5373 (re-search-forward "^\\s-*$" end t))
5374 (setq pos (point-marker))
5375 (vhdl-align-region beg pos spacing)
5376 (vhdl-align-inline-comment-region-1 beg pos)
5377 (setq beg (1+ pos))
5378 (goto-char beg))
5379 ;; align last group
5380 (when (< beg end)
5381 (vhdl-align-region beg end spacing)
5382 (vhdl-align-inline-comment-region-1 beg end)))))
5383 (unless no-message (message "Aligning...done")))
5384
5385(defun vhdl-align-group (&optional spacing)
5386 "Align group of lines between empty lines."
5387 (interactive)
5388 (save-excursion
5389 (let ((start (point))
5390 beg end)
5391 (setq end (if (re-search-forward "^\\s-*$" nil t)
5392 (point-marker) (point-max)))
5393 (goto-char start)
5394 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5395 (untabify beg end)
5396 (message "Aligning...")
5397 (vhdl-fixup-whitespace-region beg end t)
5398 (vhdl-align-region beg end spacing)
5399 (vhdl-align-inline-comment-region-1 beg end)
5400 (message "Aligning...done"))))
5401
5402(defun vhdl-align-noindent-buffer ()
5403 "Align buffer without indentation."
5404 (interactive)
5405 (vhdl-align-noindent-region (point-min) (point-max)))
d2ddb974 5406
5eabfe72
KH
5407(defun vhdl-align-inline-comment-region (beg end &optional spacing no-message)
5408 "Align inline comments within a region. Groups of code lines separated by
5409empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
d2ddb974 5410 (interactive "r\nP")
5eabfe72
KH
5411 (save-excursion
5412 (let (pos)
5413 (goto-char beg)
5414 (beginning-of-line)
5415 (setq beg (point))
5416 (goto-char end)
5417 (setq end (point-marker))
5418 (untabify beg end)
5419 (unless no-message (message "Aligning inline comments..."))
5420 (goto-char beg)
5421 (if (not vhdl-align-groups)
5422 ;; align entire region
5423 (vhdl-align-inline-comment-region-1 beg end spacing)
5424 ;; align groups
5425 (while (and (< beg end) (re-search-forward "^\\s-*$" end t))
5426 (setq pos (point-marker))
5427 (vhdl-align-inline-comment-region-1 beg pos spacing)
5428 (setq beg (1+ pos))
5429 (goto-char beg))
5430 ;; align last group
5431 (when (< beg end)
5432 (vhdl-align-inline-comment-region-1 beg end spacing))))
5433 (unless no-message (message "Aligning inline comments...done"))))
5434
5435(defun vhdl-align-inline-comment-group (&optional spacing)
5436 "Align inline comments within a group of lines between empty lines."
5437 (interactive)
5438 (save-excursion
5439 (let ((start (point))
5440 beg end)
5441 (setq end (if (re-search-forward "^\\s-*$" nil t)
5442 (point-marker) (point-max)))
5443 (goto-char start)
5444 (setq beg (if (re-search-backward "^\\s-*$" nil t) (point) (point-min)))
5445 (untabify beg end)
5446 (message "Aligning inline comments...")
5447 (vhdl-align-inline-comment-region-1 beg end)
5448 (message "Aligning inline comments...done"))))
5449
5450(defun vhdl-align-inline-comment-buffer ()
5451 "Align inline comments within buffer. Groups of code lines separated by
5452empty lines are aligned individually, if `vhdl-align-groups' is non-nil."
5453 (interactive)
5454 (vhdl-align-inline-comment-region (point-min) (point-max)))
5455
5456(defun vhdl-fixup-whitespace-region (beg end &optional no-message)
5457 "Fixup whitespace in region. Surround operator symbols by one space,
5458eliminate multiple spaces (except at beginning of line), eliminate spaces at
5459end of line, do nothing in comments."
5460 (interactive "r")
5461 (unless no-message (message "Fixing up whitespace..."))
5462 (save-excursion
5463 (goto-char end)
5464 (setq end (point-marker))
5465 ;; surround operator symbols by one space
5466 (goto-char beg)
5467 (while (re-search-forward "\\([^/:<>=]\\|^\\)\\(--\\|:\\|=\\|<\\|>\\|:=\\|<=\\|>=\\|=>\\)\\([^=>]\\|$\\)"
5468 end t)
5469 (if (equal "--" (match-string 2))
5470 (re-search-forward ".*\n" end t)
5471 (replace-match "\\1 \\2 \\3")))
5472 ;; have no space before and one space after `,' and ';'
5473 (goto-char beg)
5474 (while (re-search-forward "\\(--\\|\\s-*\\([,;]\\)\\)" end t)
5475 (if (equal "--" (match-string 1))
5476 (re-search-forward ".*\n" end t)
5477 (replace-match "\\2 " nil nil nil 1)))
5478 ;; eliminate multiple spaces and spaces at end of line
5479 (goto-char beg)
5480 (while (or (and (looking-at "--.*\n") (re-search-forward "--.*\n" end t))
5481 (and (looking-at "\\s-+$") (re-search-forward "\\s-+$" end t)
5482 (progn (replace-match "" nil nil) t))
5483 (and (looking-at "\\s-+;") (re-search-forward "\\s-+;" end t)
5484 (progn (replace-match ";" nil nil) t))
5485 (and (looking-at "^\\s-+") (re-search-forward "^\\s-+" end t))
5486 (and (looking-at "\\s-+--") (re-search-forward "\\s-+" end t)
5487 (progn (replace-match " " nil nil) t ))
5488 (and (looking-at "\\s-+") (re-search-forward "\\s-+" end t)
5489 (progn (replace-match " " nil nil) t ))
5490 (re-search-forward "\\S-+" end t))))
5491 (unless no-message (message "Fixing up whitespace...done")))
5492
5493(defun vhdl-fixup-whitespace-buffer ()
5494 "Fixup whitespace in buffer. Surround operator symbols by one space,
5495eliminate multiple spaces (except at beginning of line), eliminate spaces at
5496end of line, do nothing in comments."
5497 (interactive)
5498 (vhdl-fixup-whitespace-region (point-min) (point-max)))
5499
5500(defun vhdl-beautify-region (beg end)
5501 "Beautify region by applying indentation, whitespace fixup, alignment, and
5502case fixing to a resion. Calls functions `vhdl-indent-buffer',
5503`vhdl-align-noindent-buffer' (variable `vhdl-align-groups' set to non-nil), and
5504`vhdl-fix-case-buffer'."
5505 (interactive "r")
5506 (vhdl-indent-region beg end nil)
5507 (let ((vhdl-align-groups t))
5508 (vhdl-align-noindent-region beg end))
5509 (vhdl-fix-case-region beg end))
5510
5511(defun vhdl-beautify-buffer ()
5512 "Beautify buffer by applying indentation, whitespace fixup, alignment, and
5513case fixing to entire buffer. Calls `vhdl-beautify-region' for the entire
5514buffer."
5515 (interactive)
5516 (vhdl-beautify-region (point-min) (point-max)))
d2ddb974
KH
5517
5518
5eabfe72
KH
5519;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5520;;; Electrification
5521;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 5522
5eabfe72
KH
5523(defconst vhdl-template-prompt-syntax "[^ =<>][^<>@.\n]*[^ =<>]"
5524 "Syntax of prompt inserted by template generators.")
5525
5526(defvar vhdl-template-invoked-by-hook nil
5527 "Indicates whether a template has been invoked by a hook or by key or menu.
5528Used for undoing after template abortion.")
5529
5530;; correct different behavior of function `unread-command-events' in XEmacs
5531(defalias 'vhdl-character-to-event
5532 (if (string-match "XEmacs" emacs-version) 'character-to-event 'identity))
5533
5534;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5535;; Enabling/disabling
5536
5537(defun vhdl-mode-line-update ()
5538 "Update the modeline string for VHDL major mode."
5539 (setq mode-name (concat "VHDL"
5540 (and (or vhdl-electric-mode vhdl-stutter-mode) "/")
5541 (and vhdl-electric-mode "e")
5542 (and vhdl-stutter-mode "s")))
5543 (force-mode-line-update))
5544
5545(defun vhdl-electric-mode (arg)
5546 "Toggle VHDL electric mode.
5547Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5548 (interactive "P")
5549 (setq vhdl-electric-mode
5550 (cond ((or (not arg) (zerop arg)) (not vhdl-electric-mode))
5551 ((> arg 0) t) (t nil)))
5552 (vhdl-mode-line-update))
5553
5554(defun vhdl-stutter-mode (arg)
5555 "Toggle VHDL stuttering mode.
5556Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
5557 (interactive "P")
5558 (setq vhdl-stutter-mode
5559 (cond ((or (not arg) (zerop arg)) (not vhdl-stutter-mode))
5560 ((> arg 0) t) (t nil)))
5561 (vhdl-mode-line-update))
5562
5563;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5564;; Stuttering
d2ddb974 5565
5eabfe72
KH
5566(defun vhdl-electric-dash (count)
5567 "-- starts a comment, --- draws a horizontal line,
5568---- starts a display comment"
d2ddb974
KH
5569 (interactive "p")
5570 (if vhdl-stutter-mode
5eabfe72
KH
5571 (cond
5572 ((and abbrev-start-location (= abbrev-start-location (point)))
5573 (setq abbrev-start-location nil)
5574 (goto-char last-abbrev-location)
5575 (beginning-of-line nil)
5576 (vhdl-comment-display))
5577 ((/= (preceding-char) ?-) ; standard dash (minus)
d2ddb974 5578 (self-insert-command count))
5eabfe72
KH
5579 (t (self-insert-command count)
5580 (message "Enter '-' for horiz. line, 'CR' for commenting-out code, else enter comment")
5581 (let ((next-input (read-char)))
5582 (if (= next-input ?-) ; triple dash
5583 (progn
5584 (vhdl-comment-display-line)
5585 (message
5586 "Enter '-' for display comment, else continue coding")
5587 (let ((next-input (read-char)))
5588 (if (= next-input ?-) ; four dashes
5589 (vhdl-comment-display t)
5590 (setq unread-command-events ; pushback the char
5591 (list (vhdl-character-to-event next-input))))))
5592 (setq unread-command-events ; pushback the char
5593 (list (vhdl-character-to-event next-input)))
5594 (vhdl-comment-insert)))))
5595 (self-insert-command count)))
5596
5597(defun vhdl-electric-open-bracket (count) "'[' --> '(', '([' --> '['"
d2ddb974
KH
5598 (interactive "p")
5599 (if (and vhdl-stutter-mode (= count 1))
5eabfe72
KH
5600 (if (= (preceding-char) ?\()
5601 (progn (delete-char -1) (insert-char ?\[ 1))
5602 (insert-char ?\( 1))
5603 (self-insert-command count)))
d2ddb974 5604
5eabfe72 5605(defun vhdl-electric-close-bracket (count) "']' --> ')', ')]' --> ']'"
d2ddb974
KH
5606 (interactive "p")
5607 (if (and vhdl-stutter-mode (= count 1))
5608 (progn
5eabfe72
KH
5609 (if (= (preceding-char) ?\))
5610 (progn (delete-char -1) (insert-char ?\] 1))
5611 (insert-char ?\) 1))
5612 (blink-matching-open))
5613 (self-insert-command count)))
d2ddb974 5614
5eabfe72 5615(defun vhdl-electric-quote (count) "'' --> \""
d2ddb974
KH
5616 (interactive "p")
5617 (if (and vhdl-stutter-mode (= count 1))
5eabfe72
KH
5618 (if (= (preceding-char) last-input-char)
5619 (progn (delete-backward-char 1) (insert-char ?\" 1))
5620 (insert-char ?\' 1))
5621 (self-insert-command count)))
d2ddb974 5622
5eabfe72 5623(defun vhdl-electric-semicolon (count) "';;' --> ' : ', ': ;' --> ' := '"
d2ddb974
KH
5624 (interactive "p")
5625 (if (and vhdl-stutter-mode (= count 1))
5eabfe72
KH
5626 (cond ((= (preceding-char) last-input-char)
5627 (progn (delete-char -1)
5628 (when (not (eq (preceding-char) ? )) (insert " "))
5629 (insert ": ")
5630 (setq this-command 'vhdl-electric-colon)))
5631 ((and
5632 (eq last-command 'vhdl-electric-colon) (= (preceding-char) ? ))
5633 (progn (delete-char -1) (insert "= ")))
5634 (t (insert-char ?\; 1)))
5635 (self-insert-command count)))
5636
5637(defun vhdl-electric-comma (count) "',,' --> ' <= '"
d2ddb974
KH
5638 (interactive "p")
5639 (if (and vhdl-stutter-mode (= count 1))
5640 (cond ((= (preceding-char) last-input-char)
5641 (progn (delete-char -1)
5eabfe72 5642 (when (not (eq (preceding-char) ? )) (insert " "))
d2ddb974 5643 (insert "<= ")))
5eabfe72
KH
5644 (t (insert-char ?\, 1)))
5645 (self-insert-command count)))
d2ddb974 5646
5eabfe72 5647(defun vhdl-electric-period (count) "'..' --> ' => '"
d2ddb974
KH
5648 (interactive "p")
5649 (if (and vhdl-stutter-mode (= count 1))
5650 (cond ((= (preceding-char) last-input-char)
5651 (progn (delete-char -1)
5eabfe72 5652 (when (not (eq (preceding-char) ? )) (insert " "))
d2ddb974 5653 (insert "=> ")))
5eabfe72
KH
5654 (t (insert-char ?\. 1)))
5655 (self-insert-command count)))
d2ddb974 5656
5eabfe72 5657(defun vhdl-electric-equal (count) "'==' --> ' == '"
d2ddb974 5658 (interactive "p")
5eabfe72
KH
5659 (if (and vhdl-stutter-mode (= count 1))
5660 (cond ((= (preceding-char) last-input-char)
5661 (progn (delete-char -1)
5662 (when (not (eq (preceding-char) ? )) (insert " "))
5663 (insert "== ")))
5664 (t (insert-char ?\= 1)))
5665 (self-insert-command count)))
d2ddb974 5666
5eabfe72 5667;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
5668;; VHDL templates
5669
5eabfe72
KH
5670(defun vhdl-template-paired-parens ()
5671 "Insert a pair of round parentheses, placing point between them."
d2ddb974 5672 (interactive)
5eabfe72
KH
5673 (insert "()")
5674 (backward-char))
d2ddb974 5675
5eabfe72
KH
5676(defun vhdl-template-alias ()
5677 "Insert alias declaration."
d2ddb974 5678 (interactive)
5eabfe72
KH
5679 (let ((start (point)))
5680 (vhdl-insert-keyword "ALIAS ")
5681 (when (vhdl-template-field "name" nil t start (point))
5682 (insert " : ")
5683 (unless (vhdl-template-field
5684 (concat "[type" (and (vhdl-standard-p 'ams) " or nature") "]")
5685 nil t)
5686 (backward-delete-char 3))
5687 (vhdl-insert-keyword " IS ")
5688 (vhdl-template-field "name" ";")
5689 (vhdl-comment-insert-inline))))
5690
5691(defun vhdl-template-architecture ()
5692 "Insert architecture."
5693 (interactive)
5694 (let ((margin (current-indentation))
5695 (start (point))
5696 arch-name entity-exists string
d2ddb974
KH
5697 (case-fold-search t))
5698 (vhdl-insert-keyword "ARCHITECTURE ")
5eabfe72
KH
5699 (when (setq arch-name
5700 (vhdl-template-field "name" nil t start (point)))
d2ddb974 5701 (vhdl-insert-keyword " OF ")
5eabfe72
KH
5702 (save-excursion
5703 (vhdl-ext-syntax-table
5704 (setq entity-exists (re-search-backward
5705 "\\<entity \\(\\w+\\) is\\>" nil t))
5706 (setq string (match-string 1))))
d2ddb974 5707 (if (and entity-exists (not (equal string "")))
5eabfe72
KH
5708 (insert string)
5709 (vhdl-template-field "entity name"))
d2ddb974 5710 (vhdl-insert-keyword " IS")
5eabfe72
KH
5711 (vhdl-template-begin-end
5712 (unless (vhdl-standard-p '87) "ARCHITECTURE") arch-name margin
5713 (memq vhdl-insert-empty-lines '(unit all))))))
d2ddb974 5714
5eabfe72 5715(defun vhdl-template-array (kind &optional secondary)
d2ddb974
KH
5716 "Insert array type definition."
5717 (interactive)
5eabfe72
KH
5718 (let ((start (point)))
5719 (vhdl-insert-keyword "ARRAY (")
5720 (when (or (vhdl-template-field "range" nil (not secondary) start (point))
5721 secondary)
5722 (vhdl-insert-keyword ") OF ")
5723 (vhdl-template-field (if (eq kind 'type) "type" "nature"))
5724 (vhdl-insert-keyword ";"))))
5725
5726(defun vhdl-template-assert ()
5727 "Insert an assertion statement."
5728 (interactive)
5729 (let ((start (point)))
5730 (vhdl-insert-keyword "ASSERT ")
5731 (when vhdl-conditions-in-parenthesis (insert "("))
5732 (when (vhdl-template-field "condition (negated)" nil t start (point))
5733 (when vhdl-conditions-in-parenthesis (insert ")"))
5734 (setq start (point))
5735 (vhdl-insert-keyword " REPORT ")
5736 (unless (vhdl-template-field "string expression" nil nil nil nil t)
5737 (delete-region start (point)))
5738 (setq start (point))
5739 (vhdl-insert-keyword " SEVERITY ")
5740 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
5741 (delete-region start (point)))
5742 (insert ";"))))
5743
5744(defun vhdl-template-attribute ()
5745 "Insert an attribute declaration or specification."
5746 (interactive)
5747 (if (eq (vhdl-decision-query
5748 "attribute" "(d)eclaration or (s)pecification?" t) ?s)
5749 (vhdl-template-attribute-spec)
5750 (vhdl-template-attribute-decl)))
d2ddb974 5751
5eabfe72
KH
5752(defun vhdl-template-attribute-decl ()
5753 "Insert an attribute declaration."
d2ddb974 5754 (interactive)
5eabfe72
KH
5755 (let ((start (point)))
5756 (vhdl-insert-keyword "ATTRIBUTE ")
5757 (when (vhdl-template-field "name" " : " t start (point))
5758 (vhdl-template-field "type" ";")
5759 (vhdl-comment-insert-inline))))
5760
5761(defun vhdl-template-attribute-spec ()
5762 "Insert an attribute specification."
5763 (interactive)
5764 (let ((start (point)))
5765 (vhdl-insert-keyword "ATTRIBUTE ")
5766 (when (vhdl-template-field "name" nil t start (point))
5767 (vhdl-insert-keyword " OF ")
5768 (vhdl-template-field "entity names | OTHERS | ALL" " : ")
5769 (vhdl-template-field "entity class")
5770 (vhdl-insert-keyword " IS ")
5771 (vhdl-template-field "expression" ";"))))
d2ddb974 5772
5eabfe72
KH
5773(defun vhdl-template-block ()
5774 "Insert a block."
d2ddb974 5775 (interactive)
5eabfe72
KH
5776 (let ((margin (current-indentation))
5777 (start (point))
5778 label)
5779 (vhdl-insert-keyword ": BLOCK ")
5780 (goto-char start)
5781 (when (setq label (vhdl-template-field "label" nil t start (+ (point) 8)))
5782 (forward-word 1)
5783 (forward-char 1)
d2ddb974 5784 (insert "(")
5eabfe72
KH
5785 (if (vhdl-template-field "[guard expression]" nil t)
5786 (insert ")")
5787 (delete-char -2))
5788 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
5789 (vhdl-template-begin-end "BLOCK" label margin)
5790 (vhdl-comment-block))))
d2ddb974 5791
5eabfe72 5792(defun vhdl-template-block-configuration ()
d2ddb974
KH
5793 "Insert a block configuration statement."
5794 (interactive)
5eabfe72
KH
5795 (let ((margin (current-indentation))
5796 (start (point)))
d2ddb974 5797 (vhdl-insert-keyword "FOR ")
5eabfe72 5798 (when (vhdl-template-field "block name" nil t start (point))
d2ddb974
KH
5799 (vhdl-insert-keyword "\n\n")
5800 (indent-to margin)
5801 (vhdl-insert-keyword "END FOR;")
5802 (end-of-line 0)
5eabfe72 5803 (indent-to (+ margin vhdl-basic-offset)))))
d2ddb974 5804
5eabfe72
KH
5805(defun vhdl-template-break ()
5806 "Insert a break statement."
d2ddb974 5807 (interactive)
5eabfe72
KH
5808 (let (position)
5809 (vhdl-insert-keyword "BREAK")
5810 (setq position (point))
5811 (insert " ")
5812 (while (or
5813 (progn (vhdl-insert-keyword "FOR ")
5814 (if (vhdl-template-field "[quantity name]" " USE " t)
5815 (progn (vhdl-template-field "quantity name" " => ") t)
5816 (kill-word -1) nil))
5817 (vhdl-template-field "[quantity name]" " => " t))
5818 (vhdl-template-field "expression")
5819 (setq position (point))
5820 (insert ", "))
5821 (delete-region position (point))
5822 (unless (vhdl-sequential-statement-p)
5823 (vhdl-insert-keyword " ON ")
5824 (if (vhdl-template-field "[sensitivity list]" nil t)
5825 (setq position (point))
5826 (delete-region position (point))))
5827 (vhdl-insert-keyword " WHEN ")
5828 (when vhdl-conditions-in-parenthesis (insert "("))
5829 (if (vhdl-template-field "[condition]" nil t)
5830 (when vhdl-conditions-in-parenthesis (insert ")"))
5831 (delete-region position (point)))
5832 (insert ";")))
5833
5834(defun vhdl-template-case (&optional kind)
5835 "Insert a case statement."
5836 (interactive)
5837 (let ((margin (current-indentation))
5838 (start (point))
5839 label)
5840 (unless kind (setq kind (if (vhdl-sequential-statement-p) 'is 'use)))
5841 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
5842 (vhdl-insert-keyword "CASE ")
5843 (vhdl-insert-keyword ": CASE ")
5844 (goto-char start)
5845 (setq label (vhdl-template-field "[label]" nil t))
5846 (unless label (delete-char 2))
5847 (forward-word 1)
5848 (forward-char 1))
5849 (when (vhdl-template-field "expression" nil t start (point))
5850 (vhdl-insert-keyword (concat " " (if (eq kind 'is) "IS" "USE") "\n\n"))
d2ddb974 5851 (indent-to margin)
5eabfe72
KH
5852 (vhdl-insert-keyword "END CASE")
5853 (when label (insert " " label))
5854 (insert ";")
d2ddb974
KH
5855 (forward-line -1)
5856 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
5857 (vhdl-insert-keyword "WHEN ")
5858 (let ((position (point)))
5859 (insert " => ;\n")
5860 (indent-to (+ margin vhdl-basic-offset))
5861 (vhdl-insert-keyword "WHEN OTHERS => null;")
5862 (goto-char position)))))
d2ddb974 5863
5eabfe72
KH
5864(defun vhdl-template-case-is ()
5865 "Insert a sequential case statement."
d2ddb974 5866 (interactive)
5eabfe72
KH
5867 (vhdl-template-case 'is))
5868
5869(defun vhdl-template-case-use ()
5870 "Insert a simultaneous case statement."
5871 (interactive)
5872 (vhdl-template-case 'use))
5873
5874(defun vhdl-template-component ()
5875 "Insert a component declaration."
5876 (interactive)
5877 (vhdl-template-component-decl))
5878
5879(defun vhdl-template-component-conf ()
5880 "Insert a component configuration (uses `vhdl-template-configuration-spec'
5881since these are almost equivalent)."
5882 (interactive)
5883 (let ((margin (current-indentation))
5884 (result (vhdl-template-configuration-spec t)))
5885 (when result
5886 (insert "\n")
5887 (indent-to margin)
5888 (vhdl-insert-keyword "END FOR;")
5889 (when (eq result 'no-use)
5890 (end-of-line -0)))))
5891
5892(defun vhdl-template-component-decl ()
5893 "Insert a component declaration."
5894 (interactive)
5895 (let ((margin (current-indentation))
5896 (start (point))
5897 name end-column)
d2ddb974 5898 (vhdl-insert-keyword "COMPONENT ")
5eabfe72 5899 (when (setq name (vhdl-template-field "name" nil t start (point)))
d2ddb974
KH
5900 (insert "\n\n")
5901 (indent-to margin)
5eabfe72
KH
5902 (vhdl-insert-keyword "END COMPONENT")
5903 (unless (vhdl-standard-p '87) (insert " " name))
5904 (insert ";")
5905 (setq end-column (current-column))
d2ddb974
KH
5906 (end-of-line -0)
5907 (indent-to (+ margin vhdl-basic-offset))
5eabfe72 5908 (vhdl-template-generic-list t t)
d2ddb974
KH
5909 (insert "\n")
5910 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
5911 (vhdl-template-port-list t)
5912 (beginning-of-line 2)
5913 (forward-char end-column))))
d2ddb974 5914
5eabfe72
KH
5915(defun vhdl-template-component-inst ()
5916 "Insert a component instantiation statement."
d2ddb974 5917 (interactive)
5eabfe72
KH
5918 (let ((margin (current-indentation))
5919 (start (point))
5920 unit position)
5921 (when (vhdl-template-field "instance label" nil t start (point))
5922 (insert ": ")
5923 (if (vhdl-standard-p '87)
5924 (vhdl-template-field "component name")
5925 ;; direct instantiation
5926 (setq unit (vhdl-template-field
5927 "[COMPONENT | ENTITY | CONFIGURATION]" " " t))
5928 (setq unit (upcase (or unit "")))
5929 (cond ((equal unit "ENTITY")
5930 (vhdl-template-field "library name" "." nil nil nil nil "work")
5931 (vhdl-template-field "entity name" "(")
5932 (if (vhdl-template-field "[architecture name]" nil t)
5933 (insert ")")
5934 (delete-char -1)))
5935 ((equal unit "CONFIGURATION")
5936 (vhdl-template-field "library name" "." nil nil nil nil "work")
5937 (vhdl-template-field "configuration name"))
5938 (t (vhdl-template-field "component name"))))
5939 (insert "\n")
d2ddb974 5940 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
5941 (setq position (point))
5942 (vhdl-insert-keyword "GENERIC ")
5943 (when (vhdl-template-map position t t)
5944 (insert "\n")
5945 (indent-to (+ margin vhdl-basic-offset)))
5946 (setq position (point))
5947 (vhdl-insert-keyword "PORT ")
5948 (unless (vhdl-template-map position t t)
5949 (kill-line -0)
5950 (delete-char -1))
5951 (insert ";"))))
d2ddb974 5952
5eabfe72
KH
5953(defun vhdl-template-conditional-signal-asst ()
5954 "Insert a conditional signal assignment."
d2ddb974 5955 (interactive)
5eabfe72 5956 (when (vhdl-template-field "target signal")
d2ddb974 5957 (insert " <= ")
5eabfe72
KH
5958; (if (not (equal (vhdl-template-field "[GUARDED] [TRANSPORT]") ""))
5959; (insert " "))
d2ddb974 5960 (let ((margin (current-column))
5eabfe72
KH
5961 (start (point))
5962 position)
5963 (vhdl-template-field "waveform")
5964 (setq position (point))
d2ddb974 5965 (vhdl-insert-keyword " WHEN ")
5eabfe72
KH
5966 (when vhdl-conditions-in-parenthesis (insert "("))
5967 (while (and (vhdl-template-field "[condition]" nil t)
5968 (progn
5969 (when vhdl-conditions-in-parenthesis (insert ")"))
5970 (setq position (point))
5971 (vhdl-insert-keyword " ELSE")
5972 (insert "\n")
5973 (indent-to margin)
5974 (vhdl-template-field "[waveform]" nil t)))
5975 (setq position (point))
d2ddb974 5976 (vhdl-insert-keyword " WHEN ")
5eabfe72
KH
5977 (when vhdl-conditions-in-parenthesis (insert "(")))
5978 (delete-region position (point))
d2ddb974 5979 (insert ";")
5eabfe72 5980 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
d2ddb974 5981
5eabfe72
KH
5982(defun vhdl-template-configuration ()
5983 "Insert a configuration specification if within an architecture,
d2ddb974
KH
5984a block or component configuration if within a configuration declaration,
5985a configuration declaration if not within a design unit."
5986 (interactive)
5eabfe72
KH
5987 (let ((case-fold-search t))
5988 (vhdl-ext-syntax-table
5989 (cond
5990 ((and (save-excursion ; architecture body
5991 (re-search-backward "^\\(architecture\\|end\\)\\>" nil t))
5992 (equal "ARCHITECTURE" (upcase (match-string 1))))
5993 (vhdl-template-configuration-spec))
5994 ((and (save-excursion ; configuration declaration
5995 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
5996 (equal "CONFIGURATION" (upcase (match-string 1))))
5997 (if (eq (vhdl-decision-query
5998 "configuration" "(b)lock or (c)omponent configuration?" t) ?c)
5999 (vhdl-template-component-conf)
6000 (vhdl-template-block-configuration)))
6001 (t (vhdl-template-configuration-decl)))))) ; otherwise
6002
6003(defun vhdl-template-configuration-spec (&optional optional-use)
6004 "Insert a configuration specification."
d2ddb974 6005 (interactive)
5eabfe72
KH
6006 (let ((margin (current-indentation))
6007 (start (point))
6008 aspect position)
d2ddb974 6009 (vhdl-insert-keyword "FOR ")
5eabfe72
KH
6010 (when (vhdl-template-field "component names | OTHERS | ALL" " : "
6011 t start (point))
6012 (vhdl-template-field "component type" "\n")
d2ddb974 6013 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
6014 (setq start (point))
6015 (vhdl-insert-keyword "USE ")
6016 (if (and optional-use
6017 (not (setq aspect (vhdl-template-field
6018 "[ENTITY | CONFIGURATION | OPEN]" " " t))))
6019 (progn (delete-region start (point)) 'no-use)
6020 (unless optional-use
6021 (setq aspect (vhdl-template-field
6022 "ENTITY | CONFIGURATION | OPEN" " ")))
6023 (setq aspect (upcase (or aspect "")))
6024 (cond ((equal aspect "ENTITY")
6025 (vhdl-template-field "library name" "." nil nil nil nil "work")
6026 (vhdl-template-field "entity name" "(")
6027 (if (vhdl-template-field "[architecture name]" nil t)
6028 (insert ")")
d2ddb974 6029 (delete-char -1))
5eabfe72
KH
6030 (insert "\n")
6031 (indent-to (+ margin (* 2 vhdl-basic-offset)))
6032 (setq position (point))
6033 (vhdl-insert-keyword "GENERIC ")
6034 (when (vhdl-template-map position t t)
6035 (insert "\n")
6036 (indent-to (+ margin (* 2 vhdl-basic-offset))))
6037 (setq position (point))
6038 (vhdl-insert-keyword "PORT ")
6039 (unless (vhdl-template-map position t t)
6040 (kill-line -0)
6041 (delete-char -1))
6042 (insert ";")
6043 t)
6044 ((equal aspect "CONFIGURATION")
6045 (vhdl-template-field "library name" "." nil nil nil nil "work")
6046 (vhdl-template-field "configuration name" ";"))
6047 (t (backward-delete-char 1) (insert ";") t))))))
6048
d2ddb974 6049
5eabfe72
KH
6050(defun vhdl-template-configuration-decl ()
6051 "Insert a configuration declaration."
d2ddb974 6052 (interactive)
5eabfe72
KH
6053 (let ((margin (current-indentation))
6054 (start (point))
6055 (case-fold-search t)
6056 entity-exists string name position)
d2ddb974 6057 (vhdl-insert-keyword "CONFIGURATION ")
5eabfe72 6058 (when (setq name (vhdl-template-field "name" nil t start (point)))
d2ddb974 6059 (vhdl-insert-keyword " OF ")
5eabfe72
KH
6060 (save-excursion
6061 (vhdl-ext-syntax-table
6062 (setq entity-exists (re-search-backward
6063 "\\<entity \\(\\w*\\) is\\>" nil t))
6064 (setq string (match-string 1))))
d2ddb974 6065 (if (and entity-exists (not (equal string "")))
5eabfe72
KH
6066 (insert string)
6067 (vhdl-template-field "entity name"))
6068 (vhdl-insert-keyword " IS\n")
6069 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6070 (indent-to (+ margin vhdl-basic-offset))
6071 (setq position (point))
6072 (insert "\n")
6073 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
d2ddb974
KH
6074 (indent-to margin)
6075 (vhdl-insert-keyword "END ")
5eabfe72
KH
6076 (unless (vhdl-standard-p '87)
6077 (vhdl-insert-keyword "CONFIGURATION "))
d2ddb974 6078 (insert name ";")
5eabfe72 6079 (goto-char position))))
d2ddb974 6080
5eabfe72
KH
6081(defun vhdl-template-constant ()
6082 "Insert a constant declaration."
6083 (interactive)
6084 (let ((start (point))
6085 (in-arglist (vhdl-in-argument-list-p)))
6086 (vhdl-insert-keyword "CONSTANT ")
6087 (when (vhdl-template-field "name" nil t start (point))
d2ddb974 6088 (insert " : ")
5eabfe72
KH
6089 (when in-arglist (vhdl-insert-keyword "IN "))
6090 (vhdl-template-field "type")
d2ddb974 6091 (if in-arglist
5eabfe72
KH
6092 (progn (insert ";")
6093 (vhdl-comment-insert-inline))
d2ddb974
KH
6094 (let ((position (point)))
6095 (insert " := ")
5eabfe72
KH
6096 (unless (vhdl-template-field "[initialization]" nil t)
6097 (delete-region position (point)))
6098 (insert ";")
6099 (vhdl-comment-insert-inline))))))
d2ddb974 6100
5eabfe72 6101(defun vhdl-template-default ()
d2ddb974
KH
6102 "Insert nothing."
6103 (interactive)
6104 (insert " ")
6105 (unexpand-abbrev)
6106 (backward-word 1)
6107 (vhdl-case-word 1)
5eabfe72 6108 (forward-char 1))
d2ddb974 6109
5eabfe72 6110(defun vhdl-template-default-indent ()
d2ddb974
KH
6111 "Insert nothing and indent."
6112 (interactive)
6113 (insert " ")
6114 (unexpand-abbrev)
6115 (backward-word 1)
6116 (vhdl-case-word 1)
6117 (forward-char 1)
5eabfe72 6118 (vhdl-indent-line))
d2ddb974 6119
5eabfe72 6120(defun vhdl-template-disconnect ()
d2ddb974
KH
6121 "Insert a disconnect statement."
6122 (interactive)
5eabfe72
KH
6123 (let ((start (point)))
6124 (vhdl-insert-keyword "DISCONNECT ")
6125 (when (vhdl-template-field "signal names | OTHERS | ALL"
6126 " : " t start (point))
6127 (vhdl-template-field "type")
6128 (vhdl-insert-keyword " AFTER ")
6129 (vhdl-template-field "time expression" ";"))))
6130
6131(defun vhdl-template-else ()
d2ddb974
KH
6132 "Insert an else statement."
6133 (interactive)
5eabfe72
KH
6134 (let ((case-fold-search t)
6135 margin)
6136 (vhdl-ext-syntax-table
6137 (vhdl-insert-keyword "ELSE")
6138 (if (save-excursion
6139 (re-search-backward "\\(\\<when\\>\\|;\\)" nil t)
6140 (equal "WHEN" (upcase (match-string 1))))
6141 (insert " ")
6142 (vhdl-indent-line)
6143 (setq margin (current-indentation))
6144 (insert "\n")
6145 (indent-to (+ margin vhdl-basic-offset))))))
6146
6147(defun vhdl-template-elsif ()
d2ddb974
KH
6148 "Insert an elsif statement."
6149 (interactive)
5eabfe72
KH
6150 (let ((start (point))
6151 margin)
d2ddb974 6152 (vhdl-insert-keyword "ELSIF ")
5eabfe72
KH
6153 (when vhdl-conditions-in-parenthesis (insert "("))
6154 (when (vhdl-template-field "condition" nil t start (point))
6155 (when vhdl-conditions-in-parenthesis (insert ")"))
d2ddb974
KH
6156 (vhdl-indent-line)
6157 (setq margin (current-indentation))
5eabfe72
KH
6158 (vhdl-insert-keyword
6159 (concat " " (if (vhdl-sequential-statement-p) "THEN" "USE") "\n"))
6160 (indent-to (+ margin vhdl-basic-offset)))))
d2ddb974 6161
5eabfe72
KH
6162(defun vhdl-template-entity ()
6163 "Insert an entity."
d2ddb974 6164 (interactive)
5eabfe72
KH
6165 (let ((margin (current-indentation))
6166 (start (point))
6167 name end-column)
d2ddb974 6168 (vhdl-insert-keyword "ENTITY ")
5eabfe72 6169 (when (setq name (vhdl-template-field "name" nil t start (point)))
d2ddb974
KH
6170 (vhdl-insert-keyword " IS\n\n")
6171 (indent-to margin)
6172 (vhdl-insert-keyword "END ")
5eabfe72
KH
6173 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
6174 (insert name ";")
6175 (setq end-column (current-column))
d2ddb974
KH
6176 (end-of-line -0)
6177 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
6178 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6179 (indent-to (+ margin vhdl-basic-offset))
6180 (when (vhdl-template-generic-list t)
6181 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6182 (insert "\n")
6183 (indent-to (+ margin vhdl-basic-offset))
6184 (when (vhdl-template-port-list t)
6185 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n")))
6186 (beginning-of-line 2)
6187 (forward-char end-column))))
d2ddb974 6188
5eabfe72 6189(defun vhdl-template-exit ()
d2ddb974
KH
6190 "Insert an exit statement."
6191 (interactive)
5eabfe72
KH
6192 (let ((start (point)))
6193 (vhdl-insert-keyword "EXIT ")
6194 (unless (vhdl-template-field "[loop label]" nil t)
d2ddb974 6195 (delete-char -1))
5eabfe72
KH
6196 (let ((position (point)))
6197 (vhdl-insert-keyword " WHEN ")
6198 (when vhdl-conditions-in-parenthesis (insert "("))
6199 (if (vhdl-template-field "[condition]" nil t)
6200 (when vhdl-conditions-in-parenthesis (insert ")"))
6201 (delete-region position (point))))
6202 (insert ";")))
6203
6204(defun vhdl-template-file ()
6205 "Insert a file declaration."
6206 (interactive)
6207 (let ((start (point)))
6208 (vhdl-insert-keyword "FILE ")
6209 (when (vhdl-template-field "name" nil t start (point))
6210 (insert " : ")
6211 (vhdl-template-field "type")
6212 (unless (vhdl-standard-p '87)
6213 (vhdl-insert-keyword " OPEN ")
6214 (unless (vhdl-template-field "[READ_MODE | WRITE_MODE | APPEND_MODE]"
6215 nil t)
6216 (backward-delete-char 6)))
6217 (vhdl-insert-keyword " IS ")
6218 (when (vhdl-standard-p '87)
6219 (vhdl-template-field "[IN | OUT]" " " t))
6220 (vhdl-template-field "filename-string" nil nil nil nil t)
6221 (insert ";")
6222 (vhdl-comment-insert-inline))))
d2ddb974 6223
5eabfe72
KH
6224(defun vhdl-template-for ()
6225 "Insert a block or component configuration if within a configuration
6226declaration, a configuration specification if within an architecture
6227declarative part (and not within a subprogram), and a for-loop otherwise."
6228 (interactive)
6229 (let ((case-fold-search t))
6230 (vhdl-ext-syntax-table
6231 (cond
6232 ((and (save-excursion ; configuration declaration
6233 (re-search-backward "^\\(configuration\\|end\\)\\>" nil t))
6234 (equal "CONFIGURATION" (upcase (match-string 1))))
6235 (if (eq (vhdl-decision-query
6236 "for" "(b)lock or (c)omponent configuration?" t) ?c)
6237 (vhdl-template-component-conf)
6238 (vhdl-template-block-configuration)))
6239 ((and (save-excursion
6240 (re-search-backward ; architecture declarative part
6241 "^\\(architecture\\|entity\\|begin\\|end\\)\\>" nil t))
6242 (equal "ARCHITECTURE" (upcase (match-string 1)))
6243 (not (and (save-excursion ; not subprogram
6244 (re-search-backward
6245 "^\\s-*\\(architecture\\|begin\\|end\\)\\>" nil t))
6246 (equal "BEGIN" (upcase (match-string 1)))
6247 (save-excursion
6248 (re-search-backward
6249 "^\\s-*\\(function\\|procedure\\)\\>" nil t)))))
6250 (vhdl-template-configuration-spec))
6251 ((vhdl-sequential-statement-p) ; sequential statement
6252 (vhdl-template-for-loop))
6253 (t (vhdl-template-for-generate)))))) ; concurrent statement
6254
6255(defun vhdl-template-for-generate ()
6256 "Insert a for-generate."
d2ddb974 6257 (interactive)
5eabfe72
KH
6258 (let ((margin (current-indentation))
6259 (start (point))
6260 label string position)
6261 (vhdl-insert-keyword ": FOR ")
6262 (setq position (point-marker))
6263 (goto-char start)
6264 (when (setq label (vhdl-template-field "label" nil t start position))
6265 (goto-char position)
6266 (vhdl-template-field "loop variable")
6267 (vhdl-insert-keyword " IN ")
6268 (vhdl-template-field "range")
6269 (vhdl-template-generate-body margin label))))
d2ddb974 6270
5eabfe72
KH
6271(defun vhdl-template-for-loop ()
6272 "Insert a for loop."
d2ddb974 6273 (interactive)
5eabfe72
KH
6274 (let ((margin (current-indentation))
6275 (start (point))
6276 label index)
6277 (if (not (eq vhdl-optional-labels 'all))
6278 (vhdl-insert-keyword "FOR ")
6279 (vhdl-insert-keyword ": FOR ")
6280 (goto-char start)
6281 (setq label (vhdl-template-field "[label]" nil t))
6282 (unless label (delete-char 2))
6283 (forward-word 1)
6284 (forward-char 1))
6285 (when (setq index (vhdl-template-field "loop variable"
6286 nil t start (point)))
d2ddb974 6287 (vhdl-insert-keyword " IN ")
5eabfe72 6288 (vhdl-template-field "range")
d2ddb974
KH
6289 (vhdl-insert-keyword " LOOP\n\n")
6290 (indent-to margin)
6291 (vhdl-insert-keyword "END LOOP")
5eabfe72
KH
6292 (if label
6293 (insert " " label ";")
d2ddb974 6294 (insert ";")
5eabfe72 6295 (when vhdl-self-insert-comments (insert " -- " index)))
d2ddb974 6296 (forward-line -1)
5eabfe72 6297 (indent-to (+ margin vhdl-basic-offset)))))
d2ddb974 6298
5eabfe72
KH
6299(defun vhdl-template-footer ()
6300 "Insert a VHDL file footer."
d2ddb974 6301 (interactive)
5eabfe72
KH
6302 (unless (equal vhdl-file-footer "")
6303 (save-excursion
6304 (goto-char (point-max))
6305 (insert "\n")
6306 (vhdl-insert-string-or-file vhdl-file-footer))))
d2ddb974 6307
5eabfe72
KH
6308(defun vhdl-template-function (&optional kind)
6309 "Insert a function declaration or body."
d2ddb974 6310 (interactive)
5eabfe72
KH
6311 (let ((margin (current-indentation))
6312 (start (point))
6313 name)
6314 (vhdl-insert-keyword "FUNCTION ")
6315 (when (setq name (vhdl-template-field "name" nil t start (point)))
6316 (vhdl-template-argument-list t)
6317 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
d2ddb974 6318 (end-of-line)
5eabfe72 6319 (insert "\n")
d2ddb974 6320 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
6321 (vhdl-insert-keyword "RETURN ")
6322 (vhdl-template-field "type")
6323 (if (if kind (eq kind 'body)
6324 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6325 (progn (vhdl-insert-keyword " IS")
6326 (vhdl-template-begin-end
6327 (unless (vhdl-standard-p '87) "FUNCTION") name margin)
6328 (vhdl-comment-block))
6329 (insert ";")))))
6330
6331(defun vhdl-template-function-decl ()
6332 "Insert a function declaration."
6333 (interactive)
6334 (vhdl-template-function 'decl))
d2ddb974 6335
5eabfe72
KH
6336(defun vhdl-template-function-body ()
6337 "Insert a function declaration."
d2ddb974 6338 (interactive)
5eabfe72
KH
6339 (vhdl-template-function 'body))
6340
6341(defun vhdl-template-generate ()
6342 "Insert a generation scheme."
6343 (interactive)
6344 (if (eq (vhdl-decision-query nil "(f)or or (i)f?" t) ?i)
6345 (vhdl-template-if-generate)
6346 (vhdl-template-for-generate)))
d2ddb974 6347
5eabfe72
KH
6348(defun vhdl-template-generic ()
6349 "Insert generic declaration, or generic map in instantiation statements."
6350 (interactive)
6351 (let ((start (point))
6352 (case-fold-search t))
6353 (vhdl-ext-syntax-table
6354 (cond
6355 ((and (save-excursion ; entity declaration
6356 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6357 (equal "ENTITY" (upcase (match-string 1))))
6358 (vhdl-template-generic-list nil))
6359 ((or (save-excursion
6360 (or (beginning-of-line)
6361 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6362 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6363 (vhdl-insert-keyword "GENERIC ")
6364 (vhdl-template-map start))
6365 (t (vhdl-template-generic-list nil t))))))
6366
6367(defun vhdl-template-group ()
6368 "Insert group or group template declaration."
6369 (interactive)
6370 (let ((start (point)))
6371 (if (eq (vhdl-decision-query
6372 "group" "(d)eclaration or (t)emplate declaration?" t) ?t)
6373 (vhdl-template-group-template)
6374 (vhdl-template-group-decl))))
6375
6376(defun vhdl-template-group-decl ()
6377 "Insert group declaration."
6378 (interactive)
6379 (let ((start (point)))
6380 (vhdl-insert-keyword "GROUP ")
6381 (when (vhdl-template-field "name" " : " t start (point))
6382 (vhdl-template-field "template name" " (")
6383 (vhdl-template-field "constituent list" ");")
6384 (vhdl-comment-insert-inline))))
6385
6386(defun vhdl-template-group-template ()
6387 "Insert group template declaration."
6388 (interactive)
6389 (let ((start (point)))
6390 (vhdl-insert-keyword "GROUP ")
6391 (when (vhdl-template-field "template name" nil t start (point))
6392 (vhdl-insert-keyword " IS (")
6393 (vhdl-template-field "entity class list" ");")
6394 (vhdl-comment-insert-inline))))
6395
6396(defun vhdl-template-header ()
d2ddb974
KH
6397 "Insert a VHDL file header."
6398 (interactive)
5eabfe72
KH
6399 (unless (equal vhdl-file-header "")
6400 (let ((case-fold-search t)
6401 (project-name (or (nth 0 (aget vhdl-project-alist vhdl-project)) ""))
6402 (project-desc (or (nth 2 (aget vhdl-project-alist vhdl-project)) ""))
6403 eot)
6404 (vhdl-ext-syntax-table
6405 (save-excursion
6406 (save-restriction
6407 (widen)
6408 (goto-char (point-min))
6409 (vhdl-insert-string-or-file vhdl-file-header)
6410 (setq eot (point))
6411 (narrow-to-region (point-min) eot)
6412 (goto-char (point-min))
6413 (while (search-forward "<projectdesc>" nil t)
6414 (replace-match project-desc t t))
6415 (goto-char (point-min))
6416 (while (search-forward "<filename>" nil t)
6417 (replace-match (buffer-name) t t))
6418 (goto-char (point-min))
6419 (while (search-forward "<author>" nil t)
6420 (replace-match "" t t)
6421 (insert (user-full-name))
6422 (when user-mail-address (insert " <" user-mail-address ">")))
6423 (goto-char (point-min))
6424 (while (search-forward "<login>" nil t)
6425 (replace-match (user-login-name) t t))
6426 (goto-char (point-min))
6427 (while (search-forward "<project>" nil t)
6428 (replace-match project-name t t))
6429 (goto-char (point-min))
6430 (while (search-forward "<company>" nil t)
6431 (replace-match vhdl-company-name t t))
6432 (goto-char (point-min))
6433 (while (search-forward "<platform>" nil t)
6434 (replace-match vhdl-platform-spec t t))
6435 (goto-char (point-min))
6436 ;; Replace <RCS> with $, so that RCS for the source is
6437 ;; not over-enthusiastic with replacements
6438 (while (search-forward "<RCS>" nil t)
6439 (replace-match "$" nil t))
6440 (goto-char (point-min))
6441 (while (search-forward "<date>" nil t)
6442 (replace-match "" t t)
6443 (vhdl-template-insert-date))
6444 (goto-char (point-min))
6445 (let (string)
6446 (while
6447 (re-search-forward "<\\(\\(\\w\\|\\s_\\)*\\) string>" nil t)
6448 (setq string (read-string (concat (match-string 1) ": ")))
6449 (replace-match string t t)))))
6450 (goto-char (point-min))
6451 (when (search-forward "<cursor>" nil t)
6452 (replace-match "" t t))
6453 (when (or (not project-name) (equal project-name ""))
6454 (message "You can specify a project title in custom variable `vhdl-project-alist'"))
6455 (when (or (not project-desc) (equal project-desc ""))
6456 (message "You can specify a project description in custom variable `vhdl-project-alist'"))
6457 (when (equal vhdl-company-name "")
6458 (message "You can specify a company name in custom variable `vhdl-company-name'"))
6459 (when (equal vhdl-platform-spec "")
6460 (message "You can specify a platform in custom variable `vhdl-platform-spec'"))))))
6461
6462(defun vhdl-template-if ()
6463 "Insert a sequential if statement or an if-generate statement."
6464 (interactive)
6465 (if (vhdl-sequential-statement-p)
6466 (vhdl-template-if-then)
6467 (if (and (vhdl-standard-p 'ams)
6468 (eq (vhdl-decision-query "if" "(g)enerate or (u)se?" t) ?u))
6469 (vhdl-template-if-use)
6470 (vhdl-template-if-generate))))
6471
6472(defun vhdl-template-if-generate ()
6473 "Insert an if-generate."
6474 (interactive)
6475 (let ((margin (current-indentation))
6476 (start (point))
6477 label string position)
6478 (vhdl-insert-keyword ": IF ")
6479 (setq position (point-marker))
6480 (goto-char start)
6481 (when (setq label (vhdl-template-field "label" nil t start position))
6482 (goto-char position)
6483 (when vhdl-conditions-in-parenthesis (insert "("))
6484 (vhdl-template-field "condition")
6485 (when vhdl-conditions-in-parenthesis (insert ")"))
6486 (vhdl-template-generate-body margin label))))
d2ddb974 6487
5eabfe72
KH
6488(defun vhdl-template-if-then-use (kind)
6489 "Insert a sequential if statement."
6490 (interactive)
6491 (let ((margin (current-indentation))
6492 (start (point))
6493 label)
6494 (if (or (not (eq vhdl-optional-labels 'all)) (vhdl-standard-p '87))
6495 (vhdl-insert-keyword "IF ")
6496 (vhdl-insert-keyword ": IF ")
6497 (goto-char start)
6498 (setq label (vhdl-template-field "[label]" nil t))
6499 (unless label (delete-char 2))
6500 (forward-word 1)
6501 (forward-char 1))
6502 (when vhdl-conditions-in-parenthesis (insert "("))
6503 (when (vhdl-template-field "condition" nil t start (point))
6504 (when vhdl-conditions-in-parenthesis (insert ")"))
6505 (vhdl-insert-keyword
6506 (concat " " (if (eq kind 'then) "THEN" "USE") "\n\n"))
d2ddb974 6507 (indent-to margin)
5eabfe72
KH
6508 (vhdl-insert-keyword "END IF")
6509 (when label (insert " " label))
6510 (insert ";")
d2ddb974 6511 (forward-line -1)
5eabfe72
KH
6512 (indent-to (+ margin vhdl-basic-offset)))))
6513
6514(defun vhdl-template-if-then ()
6515 "Insert a sequential if statement."
6516 (interactive)
6517 (vhdl-template-if-then-use 'then))
6518
6519(defun vhdl-template-if-use ()
6520 "Insert a simultaneous if statement."
6521 (interactive)
6522 (vhdl-template-if-then-use 'use))
6523
6524(defun vhdl-template-instance ()
6525 "Insert a component instantiation statement."
6526 (interactive)
6527 (vhdl-template-component-inst))
d2ddb974 6528
5eabfe72 6529(defun vhdl-template-library ()
d2ddb974
KH
6530 "Insert a library specification."
6531 (interactive)
5eabfe72
KH
6532 (let ((margin (current-indentation))
6533 (start (point))
6534 name end-pos)
d2ddb974 6535 (vhdl-insert-keyword "LIBRARY ")
5eabfe72
KH
6536 (when (setq name (vhdl-template-field "names" nil t start (point)))
6537 (insert ";")
6538 (unless (string-match "," name)
6539 (setq end-pos (point))
6540 (insert "\n")
6541 (indent-to margin)
6542 (vhdl-insert-keyword "USE ")
6543 (insert name)
6544 (vhdl-insert-keyword "..ALL;")
6545 (backward-char 5)
6546 (if (vhdl-template-field "package name")
6547 (forward-char 5)
6548 (delete-region end-pos (+ (point) 5)))))))
6549
6550(defun vhdl-template-limit ()
6551 "Insert a limit."
d2ddb974 6552 (interactive)
5eabfe72
KH
6553 (let ((start (point)))
6554 (vhdl-insert-keyword "LIMIT ")
6555 (when (vhdl-template-field "quantity names | OTHERS | ALL" " : "
6556 t start (point))
6557 (vhdl-template-field "type")
6558 (vhdl-insert-keyword " WITH ")
6559 (vhdl-template-field "real expression" ";"))))
6560
6561(defun vhdl-template-loop ()
6562 "Insert a loop."
6563 (interactive)
6564 (let ((char (vhdl-decision-query nil "(w)hile, (f)or, or (b)are?" t)))
6565 (cond ((eq char ?w)
6566 (vhdl-template-while-loop))
6567 ((eq char ?f)
6568 (vhdl-template-for-loop))
6569 (t (vhdl-template-bare-loop)))))
6570
6571(defun vhdl-template-bare-loop ()
6572 "Insert a loop."
6573 (interactive)
6574 (let ((margin (current-indentation))
6575 (start (point))
6576 label)
6577 (if (not (eq vhdl-optional-labels 'all))
6578 (vhdl-insert-keyword "LOOP ")
6579 (vhdl-insert-keyword ": LOOP ")
6580 (goto-char start)
6581 (setq label (vhdl-template-field "[label]" nil t))
6582 (unless label (delete-char 2))
6583 (forward-word 1)
6584 (delete-char 1))
d2ddb974
KH
6585 (insert "\n\n")
6586 (indent-to margin)
6587 (vhdl-insert-keyword "END LOOP")
5eabfe72 6588 (insert (if label (concat " " label ";") ";"))
d2ddb974 6589 (forward-line -1)
5eabfe72 6590 (indent-to (+ margin vhdl-basic-offset))))
d2ddb974 6591
5eabfe72
KH
6592(defun vhdl-template-map (&optional start optional secondary)
6593 "Insert a map specification with association list."
d2ddb974 6594 (interactive)
5eabfe72
KH
6595 (let ((start (or start (point)))
6596 margin end-pos)
6597 (vhdl-insert-keyword "MAP (")
6598 (if (not vhdl-association-list-with-formals)
6599 (if (vhdl-template-field
6600 (concat (and optional "[") "association list" (and optional "]"))
6601 ")" (or (not secondary) optional)
6602 (and (not secondary) start) (point))
6603 t
6604 (if (and optional secondary) (delete-region start (point)))
6605 nil)
6606 (if vhdl-argument-list-indent
6607 (setq margin (current-column))
6608 (setq margin (+ (current-indentation) vhdl-basic-offset))
6609 (insert "\n")
6610 (indent-to margin))
6611 (if (vhdl-template-field
6612 (concat (and optional "[") "formal" (and optional "]"))
6613 " => " (or (not secondary) optional)
6614 (and (not secondary) start) (point))
6615 (progn
6616 (vhdl-template-field "actual" ",")
6617 (setq end-pos (point))
6618 (insert "\n")
6619 (indent-to margin)
6620 (while (vhdl-template-field "[formal]" " => " t)
6621 (vhdl-template-field "actual" ",")
6622 (setq end-pos (point))
6623 (insert "\n")
6624 (indent-to margin))
6625 (delete-region end-pos (point))
6626 (backward-delete-char 1)
6627 (insert ")")
6628 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6629 t)
6630 (when (and optional secondary) (delete-region start (point)))
6631 nil))))
d2ddb974 6632
5eabfe72 6633(defun vhdl-template-modify (&optional noerror)
d2ddb974
KH
6634 "Actualize modification date."
6635 (interactive)
5eabfe72
KH
6636 (let ((case-fold-search t))
6637 (vhdl-ext-syntax-table
6638 (save-excursion
6639 (goto-char (point-min))
6640 (if (re-search-forward vhdl-modify-date-prefix-string nil t)
6641 (progn (kill-line)
6642 (vhdl-template-insert-date))
6643 (unless noerror
6644 (error (concat "Modification date prefix string \""
6645 vhdl-modify-date-prefix-string "\" not found"))))))))
6646
6647(defun vhdl-template-modify-noerror ()
6648 "Call `vhdl-template-modify' with NOERROR non-nil."
6649 (vhdl-template-modify t))
6650
6651(defun vhdl-template-nature ()
6652 "Insert a nature declaration."
6653 (interactive)
6654 (let ((start (point))
6655 name mid-pos end-pos)
6656 (vhdl-insert-keyword "NATURE ")
6657 (when (setq name (vhdl-template-field "name" nil t start (point)))
6658 (vhdl-insert-keyword " IS ")
6659 (let ((definition
6660 (upcase
6661 (or (vhdl-template-field
6662 "across type | ARRAY | RECORD")
6663 ""))))
6664 (cond ((equal definition "")
6665 (insert ";"))
6666 ((equal definition "ARRAY")
6667 (kill-word -1)
6668 (vhdl-template-array 'nature t))
6669 ((equal definition "RECORD")
6670 (setq mid-pos (point-marker))
6671 (kill-word -1)
6672 (vhdl-template-record 'nature name t))
6673 (t
6674 (vhdl-insert-keyword " ACROSS ")
6675 (vhdl-template-field "through type")
6676 (vhdl-insert-keyword " THROUGH ")
6677 (vhdl-template-field "reference name")
6678 (vhdl-insert-keyword " REFERENCE;")))
6679 (when mid-pos
6680 (setq end-pos (point-marker))
6681 (goto-char mid-pos)
6682 (end-of-line))
6683 (vhdl-comment-insert-inline)
6684 (when end-pos (goto-char end-pos))))))
6685
6686(defun vhdl-template-next ()
6687 "Insert a next statement."
d2ddb974
KH
6688 (interactive)
6689 (vhdl-insert-keyword "NEXT ")
5eabfe72
KH
6690 (unless (vhdl-template-field "[loop label]" nil t)
6691 (delete-char -1))
6692 (let ((position (point)))
d2ddb974 6693 (vhdl-insert-keyword " WHEN ")
5eabfe72
KH
6694 (when vhdl-conditions-in-parenthesis (insert "("))
6695 (if (vhdl-template-field "[condition]" nil t)
6696 (when vhdl-conditions-in-parenthesis (insert ")"))
6697 (delete-region position (point)))
6698 (insert ";")))
6699
6700(defun vhdl-template-others ()
6701 "Insert an others aggregate."
6702 (interactive)
6703 (vhdl-insert-keyword "(OTHERS => '')")
6704 (backward-char 2))
d2ddb974 6705
5eabfe72 6706(defun vhdl-template-package (&optional kind)
d2ddb974
KH
6707 "Insert a package specification or body."
6708 (interactive)
5eabfe72
KH
6709 (let ((margin (current-indentation))
6710 (start (point))
6711 name body position)
d2ddb974 6712 (vhdl-insert-keyword "PACKAGE ")
5eabfe72
KH
6713 (setq body (if kind (eq kind 'body)
6714 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b)))
6715 (when body (vhdl-insert-keyword "BODY "))
6716 (when (setq name (vhdl-template-field "name" nil t start (point)))
6717 (vhdl-insert-keyword " IS\n")
6718 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6719 (indent-to (+ margin vhdl-basic-offset))
6720 (setq position (point))
6721 (insert "\n")
6722 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
6723 (indent-to margin)
6724 (vhdl-insert-keyword "END ")
6725 (unless (vhdl-standard-p '87)
6726 (vhdl-insert-keyword (concat "PACKAGE " (and body "BODY "))))
6727 (insert (or name "") ";")
6728 (goto-char position))))
d2ddb974 6729
5eabfe72
KH
6730(defun vhdl-template-package-decl ()
6731 "Insert a package specification."
d2ddb974 6732 (interactive)
5eabfe72 6733 (vhdl-template-package 'decl))
d2ddb974 6734
5eabfe72
KH
6735(defun vhdl-template-package-body ()
6736 "Insert a package body."
d2ddb974 6737 (interactive)
5eabfe72 6738 (vhdl-template-package 'body))
d2ddb974 6739
5eabfe72
KH
6740(defun vhdl-template-port ()
6741 "Insert a port declaration, or port map in instantiation statements."
d2ddb974 6742 (interactive)
5eabfe72
KH
6743 (let ((start (point))
6744 (case-fold-search t))
6745 (vhdl-ext-syntax-table
6746 (cond
6747 ((and (save-excursion ; entity declaration
6748 (re-search-backward "^\\(entity\\|end\\)\\>" nil t))
6749 (equal "ENTITY" (upcase (match-string 1))))
6750 (vhdl-template-port-list nil))
6751 ((or (save-excursion
6752 (or (beginning-of-line)
6753 (looking-at "^\\s-*\\w+\\s-*:\\s-*\\w+")))
6754 (equal 'statement-cont (car (car (vhdl-get-syntactic-context)))))
6755 (vhdl-insert-keyword "PORT ")
6756 (vhdl-template-map start))
6757 (t (vhdl-template-port-list nil))))))
6758
6759(defun vhdl-template-procedural ()
6760 "Insert a procedural."
6761 (interactive)
6762 (let ((margin (current-indentation))
6763 (start (point))
6764 (case-fold-search t)
6765 label)
6766 (vhdl-insert-keyword "PROCEDURAL ")
6767 (when (memq vhdl-optional-labels '(process all))
6768 (goto-char start)
6769 (insert ": ")
6770 (goto-char start)
6771 (setq label (vhdl-template-field "[label]" nil t))
6772 (unless label (delete-char 2))
6773 (forward-word 1)
6774 (forward-char 1))
6775 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "IS"))
6776 (vhdl-template-begin-end "PROCEDURAL" label margin)
6777 (vhdl-comment-block)))
6778
6779(defun vhdl-template-procedure (&optional kind)
6780 "Insert a procedure declaration or body."
6781 (interactive)
6782 (let ((margin (current-indentation))
6783 (start (point))
6784 name)
6785 (vhdl-insert-keyword "PROCEDURE ")
6786 (when (setq name (vhdl-template-field "name" nil t start (point)))
6787 (vhdl-template-argument-list)
6788 (if (if kind (eq kind 'body)
6789 (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
6790 (progn (vhdl-insert-keyword " IS")
6791 (when vhdl-auto-align
6792 (vhdl-align-noindent-region start (point) 1))
6793 (end-of-line)
6794 (vhdl-template-begin-end
6795 (unless (vhdl-standard-p '87) "PROCEDURE")
6796 name margin)
6797 (vhdl-comment-block))
6798 (insert ";")
6799 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
6800 (end-of-line)))))
6801
6802(defun vhdl-template-procedure-decl ()
6803 "Insert a procedure declaration."
6804 (interactive)
6805 (vhdl-template-procedure 'decl))
d2ddb974 6806
5eabfe72
KH
6807(defun vhdl-template-procedure-body ()
6808 "Insert a procedure body."
6809 (interactive)
6810 (vhdl-template-procedure 'body))
6811
6812(defun vhdl-template-process (&optional kind)
6813 "Insert a process."
6814 (interactive)
6815 (let ((margin (current-indentation))
6816 (start (point))
6817 (case-fold-search t)
6818 label seq input-signals clock reset final-pos)
6819 (setq seq (if kind (eq kind 'seq)
6820 (eq (vhdl-decision-query
6821 "process" "(c)ombinational or (s)equential?" t) ?s)))
6822 (vhdl-insert-keyword "PROCESS ")
6823 (when (memq vhdl-optional-labels '(process all))
6824 (goto-char start)
6825 (insert ": ")
6826 (goto-char start)
6827 (setq label (vhdl-template-field "[label]" nil t))
6828 (unless label (delete-char 2))
6829 (forward-word 1)
6830 (forward-char 1))
6831 (insert "(")
6832 (if (not seq)
6833 (unless (setq input-signals
6834 (vhdl-template-field "[sensitivity list]" ")" t))
6835 (setq input-signals "")
6836 (delete-char -2))
6837 (setq clock (or (and (not (equal "" vhdl-clock-name))
6838 (progn (insert vhdl-clock-name) vhdl-clock-name))
6839 (vhdl-template-field "clock name") "<clock>"))
6840 (when (eq vhdl-reset-kind 'async)
6841 (insert ", ")
6842 (setq reset (or (and (not (equal "" vhdl-reset-name))
6843 (progn (insert vhdl-reset-name) vhdl-reset-name))
6844 (vhdl-template-field "reset name") "<reset>")))
6845 (insert ")"))
6846 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " IS"))
6847 (vhdl-template-begin-end "PROCESS" label margin)
6848 (when seq (setq reset (vhdl-template-seq-process clock reset)))
6849 (when vhdl-prompt-for-comments
6850 (setq final-pos (point-marker))
6851 (vhdl-ext-syntax-table
6852 (when (and (re-search-backward "\\<begin\\>" nil t)
6853 (re-search-backward "\\<process\\>" nil t))
6854 (end-of-line -0)
6855 (if (bobp)
6856 (progn (insert "\n") (forward-line -1))
6857 (insert "\n"))
6858 (indent-to margin)
6859 (insert "-- purpose: ")
6860 (if (not (vhdl-template-field "[description]" nil t))
6861 (vhdl-line-kill-entire)
6862 (insert "\n")
6863 (indent-to margin)
6864 (insert "-- type : ")
6865 (insert (if seq "sequential" "combinational") "\n")
6866 (indent-to margin)
6867 (insert "-- inputs : ")
6868 (if (not seq)
6869 (insert input-signals)
6870 (insert clock ", ")
6871 (when reset (insert reset ", "))
6872 (unless (vhdl-template-field "[signal names]" nil t)
6873 (delete-char -2)))
6874 (insert "\n")
6875 (indent-to margin)
6876 (insert "-- outputs: ")
6877 (vhdl-template-field "[signal names]" nil t))))
6878 (goto-char final-pos))))
6879
6880(defun vhdl-template-process-comb ()
6881 "Insert a combinational process."
6882 (interactive)
6883 (vhdl-template-process 'comb))
6884
6885(defun vhdl-template-process-seq ()
6886 "Insert a sequential process."
6887 (interactive)
6888 (vhdl-template-process 'seq))
6889
6890(defun vhdl-template-quantity ()
6891 "Insert a quantity declaration."
6892 (interactive)
6893 (if (vhdl-in-argument-list-p)
6894 (let ((start (point)))
6895 (vhdl-insert-keyword "QUANTITY ")
6896 (when (vhdl-template-field "names" nil t start (point))
6897 (insert " : ")
6898 (vhdl-template-field "[IN | OUT]" " " t)
6899 (vhdl-template-field "type")
6900 (insert ";")
6901 (vhdl-comment-insert-inline)))
6902 (let ((char (vhdl-decision-query
6903 "quantity" "(f)ree, (b)ranch, or (s)ource quantity?" t)))
6904 (cond ((eq char ?f) (vhdl-template-quantity-free))
6905 ((eq char ?b) (vhdl-template-quantity-branch))
6906 ((eq char ?s) (vhdl-template-quantity-source))
6907 (t (vhdl-template-undo (point) (point)))))))
6908
6909(defun vhdl-template-quantity-free ()
6910 "Insert a free quantity declaration."
6911 (interactive)
6912 (vhdl-insert-keyword "QUANTITY ")
6913 (vhdl-template-field "names")
6914 (insert " : ")
6915 (vhdl-template-field "type")
6916 (let ((position (point)))
6917 (insert " := ")
6918 (unless (vhdl-template-field "[initialization]" nil t)
6919 (delete-region position (point)))
6920 (insert ";")
6921 (vhdl-comment-insert-inline)))
6922
6923(defun vhdl-template-quantity-branch ()
6924 "Insert a branch quantity declaration."
6925 (interactive)
6926 (let (position)
6927 (vhdl-insert-keyword "QUANTITY ")
6928 (when (vhdl-template-field "[across names]" " " t)
6929 (vhdl-insert-keyword "ACROSS "))
6930 (when (vhdl-template-field "[through names]" " " t)
6931 (vhdl-insert-keyword "THROUGH "))
6932 (vhdl-template-field "plus terminal name")
6933 (setq position (point))
6934 (vhdl-insert-keyword " TO ")
6935 (unless (vhdl-template-field "[minus terminal name]" nil t)
6936 (delete-region position (point)))
6937 (insert ";")
6938 (vhdl-comment-insert-inline)))
6939
6940(defun vhdl-template-quantity-source ()
6941 "Insert a source quantity declaration."
6942 (interactive)
6943 (vhdl-insert-keyword "QUANTITY ")
6944 (vhdl-template-field "names")
6945 (insert " : ")
6946 (vhdl-template-field "type" " ")
6947 (if (eq (vhdl-decision-query nil "(s)pectrum or (n)oise?") ?n)
6948 (progn (vhdl-insert-keyword "NOISE ")
6949 (vhdl-template-field "power expression"))
6950 (vhdl-insert-keyword "SPECTRUM ")
6951 (vhdl-template-field "magnitude expression" ", ")
6952 (vhdl-template-field "phase expression"))
6953 (insert ";")
6954 (vhdl-comment-insert-inline))
6955
6956(defun vhdl-template-record (kind &optional name secondary)
d2ddb974
KH
6957 "Insert a record type declaration."
6958 (interactive)
6959 (let ((margin (current-column))
6960 (start (point))
6961 (first t))
6962 (vhdl-insert-keyword "RECORD\n")
6963 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
6964 (when (or (vhdl-template-field "element names"
6965 nil (not secondary) start (point))
6966 secondary)
6967 (while (or first (vhdl-template-field "[element names]" nil t))
6968 (insert " : ")
6969 (vhdl-template-field (if (eq kind 'type) "type" "nature") ";")
6970 (vhdl-comment-insert-inline)
6971 (insert "\n")
d2ddb974 6972 (indent-to (+ margin vhdl-basic-offset))
5eabfe72 6973 (setq first nil))
d2ddb974
KH
6974 (kill-line -0)
6975 (indent-to margin)
5eabfe72
KH
6976 (vhdl-insert-keyword "END RECORD")
6977 (unless (vhdl-standard-p '87) (and name (insert " " name)))
6978 (insert ";")
6979 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
d2ddb974 6980
5eabfe72
KH
6981(defun vhdl-template-report ()
6982 "Insert a report statement."
6983 (interactive)
6984 (let ((start (point)))
6985 (vhdl-insert-keyword "REPORT ")
6986 (if (equal "\"\"" (vhdl-template-field
6987 "string expression" nil t start (point) t))
6988 (backward-delete-char 2)
6989 (setq start (point))
6990 (vhdl-insert-keyword " SEVERITY ")
6991 (unless (vhdl-template-field "[NOTE | WARNING | ERROR | FAILURE]" nil t)
6992 (delete-region start (point)))
6993 (insert ";"))))
6994
6995(defun vhdl-template-return ()
d2ddb974
KH
6996 "Insert a return statement."
6997 (interactive)
6998 (vhdl-insert-keyword "RETURN ")
5eabfe72
KH
6999 (unless (vhdl-template-field "[expression]" nil t)
7000 (delete-char -1))
7001 (insert ";"))
d2ddb974 7002
5eabfe72 7003(defun vhdl-template-selected-signal-asst ()
d2ddb974
KH
7004 "Insert a selected signal assignment."
7005 (interactive)
5eabfe72
KH
7006 (let ((margin (current-indentation))
7007 (start (point))
7008 (choices t))
d2ddb974 7009 (let ((position (point)))
5eabfe72 7010 (vhdl-insert-keyword " SELECT ")
d2ddb974
KH
7011 (goto-char position))
7012 (vhdl-insert-keyword "WITH ")
5eabfe72
KH
7013 (when (vhdl-template-field "selector expression"
7014 nil t start (+ (point) 7))
7015 (forward-word 1)
7016 (delete-char 1)
d2ddb974
KH
7017 (insert "\n")
7018 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
7019 (vhdl-template-field "target signal" " <= ")
7020; (vhdl-template-field "[GUARDED] [TRANSPORT]")
d2ddb974
KH
7021 (insert "\n")
7022 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
7023 (vhdl-template-field "waveform")
7024 (vhdl-insert-keyword " WHEN ")
7025 (vhdl-template-field "choices" ",")
7026 (insert "\n")
7027 (indent-to (+ margin vhdl-basic-offset))
7028 (while (and choices (vhdl-template-field "[waveform]" nil t))
d2ddb974 7029 (vhdl-insert-keyword " WHEN ")
5eabfe72
KH
7030 (if (setq choices (vhdl-template-field "[choices]" "," t))
7031 (progn (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
7032 (vhdl-insert-keyword "OTHERS")))
7033 (when choices
d2ddb974
KH
7034 (fixup-whitespace)
7035 (delete-char -2))
7036 (insert ";")
5eabfe72 7037 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
d2ddb974 7038
5eabfe72 7039(defun vhdl-template-signal ()
d2ddb974
KH
7040 "Insert a signal declaration."
7041 (interactive)
5eabfe72
KH
7042 (let ((start (point))
7043 (in-arglist (vhdl-in-argument-list-p)))
7044 (vhdl-insert-keyword "SIGNAL ")
7045 (when (vhdl-template-field "names" nil t start (point))
d2ddb974 7046 (insert " : ")
5eabfe72
KH
7047 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7048 (vhdl-template-field "type")
d2ddb974 7049 (if in-arglist
5eabfe72
KH
7050 (progn (insert ";")
7051 (vhdl-comment-insert-inline))
d2ddb974
KH
7052 (let ((position (point)))
7053 (insert " := ")
5eabfe72
KH
7054 (unless (vhdl-template-field "[initialization]" nil t)
7055 (delete-region position (point)))
7056 (insert ";")
7057 (vhdl-comment-insert-inline))))))
7058
7059(defun vhdl-template-subnature ()
7060 "Insert a subnature declaration."
7061 (interactive)
7062 (let ((start (point))
7063 position)
7064 (vhdl-insert-keyword "SUBNATURE ")
7065 (when (vhdl-template-field "name" nil t start (point))
7066 (vhdl-insert-keyword " IS ")
7067 (vhdl-template-field "nature" " (")
7068 (if (vhdl-template-field "[index range]" nil t)
7069 (insert ")")
7070 (delete-char -2))
7071 (setq position (point))
7072 (vhdl-insert-keyword " TOLERANCE ")
7073 (if (equal "\"\"" (vhdl-template-field "[string expression]"
7074 nil t nil nil t))
7075 (delete-region position (point))
7076 (vhdl-insert-keyword " ACROSS ")
7077 (vhdl-template-field "string expression" nil nil nil nil t)
7078 (vhdl-insert-keyword " THROUGH"))
7079 (insert ";")
7080 (vhdl-comment-insert-inline))))
7081
7082(defun vhdl-template-subprogram-body ()
7083 "Insert a subprogram body."
7084 (interactive)
7085 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7086 (vhdl-template-function-body)
7087 (vhdl-template-procedure-body)))
d2ddb974 7088
5eabfe72
KH
7089(defun vhdl-template-subprogram-decl ()
7090 "Insert a subprogram declaration."
7091 (interactive)
7092 (if (eq (vhdl-decision-query nil "(p)rocedure or (f)unction?" t) ?f)
7093 (vhdl-template-function-decl)
7094 (vhdl-template-procedure-decl)))
7095
7096(defun vhdl-template-subtype ()
d2ddb974
KH
7097 "Insert a subtype declaration."
7098 (interactive)
5eabfe72
KH
7099 (let ((start (point)))
7100 (vhdl-insert-keyword "SUBTYPE ")
7101 (when (vhdl-template-field "name" nil t start (point))
7102 (vhdl-insert-keyword " IS ")
7103 (vhdl-template-field "type" " ")
7104 (unless
7105 (vhdl-template-field "[RANGE value range | ( index range )]" nil t)
d2ddb974 7106 (delete-char -1))
5eabfe72
KH
7107 (insert ";")
7108 (vhdl-comment-insert-inline))))
d2ddb974 7109
5eabfe72
KH
7110(defun vhdl-template-terminal ()
7111 "Insert a terminal declaration."
d2ddb974 7112 (interactive)
5eabfe72
KH
7113 (let ((start (point)))
7114 (vhdl-insert-keyword "TERMINAL ")
7115 (when (vhdl-template-field "names" nil t start (point))
7116 (insert " : ")
7117 (vhdl-template-field "nature")
7118 (insert ";")
7119 (vhdl-comment-insert-inline))))
d2ddb974 7120
5eabfe72
KH
7121(defun vhdl-template-type ()
7122 "Insert a type declaration."
7123 (interactive)
7124 (let ((start (point))
7125 name mid-pos end-pos)
7126 (vhdl-insert-keyword "TYPE ")
7127 (when (setq name (vhdl-template-field "name" nil t start (point)))
7128 (vhdl-insert-keyword " IS ")
7129 (let ((definition
7130 (upcase
7131 (or (vhdl-template-field
7132 "[scalar type | ARRAY | RECORD | ACCESS | FILE]" nil t)
7133 ""))))
7134 (cond ((equal definition "")
7135 (backward-delete-char 4)
7136 (insert ";"))
7137 ((equal definition "ARRAY")
7138 (kill-word -1)
7139 (vhdl-template-array 'type t))
7140 ((equal definition "RECORD")
7141 (setq mid-pos (point-marker))
7142 (kill-word -1)
7143 (vhdl-template-record 'type name t))
7144 ((equal definition "ACCESS")
7145 (insert " ")
7146 (vhdl-template-field "type" ";"))
7147 ((equal definition "FILE")
7148 (vhdl-insert-keyword " OF ")
7149 (vhdl-template-field "type" ";"))
7150 (t (insert ";")))
7151 (when mid-pos
7152 (setq end-pos (point-marker))
7153 (goto-char mid-pos)
7154 (end-of-line))
7155 (vhdl-comment-insert-inline)
7156 (when end-pos (goto-char end-pos))))))
7157
7158(defun vhdl-template-use ()
d2ddb974
KH
7159 "Insert a use clause."
7160 (interactive)
5eabfe72
KH
7161 (let ((start (point))
7162 (case-fold-search t))
7163 (vhdl-ext-syntax-table
7164 (vhdl-insert-keyword "USE ")
7165 (when (save-excursion (beginning-of-line) (looking-at "^\\s-*use\\>"))
7166 (vhdl-insert-keyword "..ALL;")
7167 (backward-char 6)
7168 (when (vhdl-template-field "library name" nil t start (+ (point) 6))
7169 (forward-char 1)
7170 (vhdl-template-field "package name")
7171 (forward-char 5))))))
7172
7173(defun vhdl-template-variable ()
d2ddb974
KH
7174 "Insert a variable declaration."
7175 (interactive)
5eabfe72
KH
7176 (let ((start (point))
7177 (case-fold-search t)
7178 (in-arglist (vhdl-in-argument-list-p)))
7179 (vhdl-ext-syntax-table
7180 (if (or (save-excursion
7181 (and (re-search-backward
7182 "\\<function\\|procedure\\|process\\|procedural\\|end\\>"
7183 nil t)
7184 (not (progn (backward-word 1) (looking-at "\\<end\\>")))))
7185 (save-excursion (backward-word 1) (looking-at "\\<shared\\>")))
7186 (vhdl-insert-keyword "VARIABLE ")
7187 (vhdl-insert-keyword "SHARED VARIABLE ")))
7188 (when (vhdl-template-field "names" nil t start (point))
d2ddb974 7189 (insert " : ")
5eabfe72
KH
7190 (when in-arglist (vhdl-template-field "[IN | OUT | INOUT]" " " t))
7191 (vhdl-template-field "type")
d2ddb974 7192 (if in-arglist
5eabfe72
KH
7193 (progn (insert ";")
7194 (vhdl-comment-insert-inline))
d2ddb974
KH
7195 (let ((position (point)))
7196 (insert " := ")
5eabfe72
KH
7197 (unless (vhdl-template-field "[initialization]" nil t)
7198 (delete-region position (point)))
7199 (insert ";")
7200 (vhdl-comment-insert-inline))))))
d2ddb974 7201
5eabfe72 7202(defun vhdl-template-wait ()
d2ddb974
KH
7203 "Insert a wait statement."
7204 (interactive)
7205 (vhdl-insert-keyword "WAIT ")
5eabfe72
KH
7206 (unless (vhdl-template-field
7207 "[ON sensitivity list] [UNTIL condition] [FOR time expression]"
7208 nil t)
7209 (delete-char -1))
7210 (insert ";"))
d2ddb974 7211
5eabfe72 7212(defun vhdl-template-when ()
d2ddb974
KH
7213 "Indent correctly if within a case statement."
7214 (interactive)
7215 (let ((position (point))
5eabfe72
KH
7216 (case-fold-search t)
7217 margin)
7218 (vhdl-ext-syntax-table
7219 (if (and (= (current-column) (current-indentation))
7220 (re-search-forward "\\<end\\>" nil t)
7221 (looking-at "\\s-*\\<case\\>"))
7222 (progn
7223 (setq margin (current-indentation))
7224 (goto-char position)
7225 (delete-horizontal-space)
7226 (indent-to (+ margin vhdl-basic-offset)))
7227 (goto-char position)))
7228 (vhdl-insert-keyword "WHEN ")))
7229
7230(defun vhdl-template-while-loop ()
7231 "Insert a while loop."
d2ddb974 7232 (interactive)
5eabfe72
KH
7233 (let* ((margin (current-indentation))
7234 (start (point))
7235 label)
7236 (if (not (eq vhdl-optional-labels 'all))
7237 (vhdl-insert-keyword "WHILE ")
7238 (vhdl-insert-keyword ": WHILE ")
7239 (goto-char start)
7240 (setq label (vhdl-template-field "[label]" nil t))
7241 (unless label (delete-char 2))
7242 (forward-word 1)
7243 (forward-char 1))
7244 (when vhdl-conditions-in-parenthesis (insert "("))
7245 (when (vhdl-template-field "condition" nil t start (point))
7246 (when vhdl-conditions-in-parenthesis (insert ")"))
d2ddb974
KH
7247 (vhdl-insert-keyword " LOOP\n\n")
7248 (indent-to margin)
7249 (vhdl-insert-keyword "END LOOP")
5eabfe72 7250 (insert (if label (concat " " label ";") ";"))
d2ddb974 7251 (forward-line -1)
5eabfe72 7252 (indent-to (+ margin vhdl-basic-offset)))))
d2ddb974 7253
5eabfe72 7254(defun vhdl-template-with ()
d2ddb974
KH
7255 "Insert a with statement (i.e. selected signal assignment)."
7256 (interactive)
5eabfe72
KH
7257 (let ((case-fold-search t))
7258 (vhdl-ext-syntax-table
7259 (if (save-excursion
7260 (re-search-backward "\\(\\<limit\\>\\|;\\)")
7261 (equal ";" (match-string 1)))
7262 (vhdl-template-selected-signal-asst)
7263 (vhdl-insert-keyword "WITH ")))))
7264
7265;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7266;; Special templates
7267
7268(defun vhdl-template-clocked-wait ()
7269 "Insert a wait statement for rising/falling clock edge."
7270 (interactive)
7271 (let ((start (point))
7272 clock)
7273 (vhdl-insert-keyword "WAIT UNTIL ")
7274 (when (setq clock
7275 (or (and (not (equal "" vhdl-clock-name))
7276 (progn (insert vhdl-clock-name) vhdl-clock-name))
7277 (vhdl-template-field "clock name" nil t start (point))))
7278 (insert "'event")
7279 (vhdl-insert-keyword " AND ")
7280 (insert clock)
7281 (insert
7282 " = " (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string) ";")
7283 (vhdl-comment-insert-inline
7284 (concat (if vhdl-clock-rising-edge "rising" "falling")
7285 " clock edge")))))
7286
7287(defun vhdl-template-seq-process (clock reset)
7288 "Insert a template for the body of a sequential process."
7289 (let ((margin (current-indentation))
7290 position)
d2ddb974 7291 (vhdl-insert-keyword "IF ")
5eabfe72
KH
7292 (when (eq vhdl-reset-kind 'async)
7293 (insert reset " = "
7294 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7295 (vhdl-insert-keyword " THEN")
7296 (vhdl-comment-insert-inline
7297 (concat "asynchronous reset (active "
7298 (if vhdl-reset-active-high "high" "low") ")"))
7299 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7300 (setq position (point))
7301 (insert "\n") (indent-to margin)
7302 (vhdl-insert-keyword "ELSIF "))
7303 (if (eq vhdl-clock-edge-condition 'function)
7304 (insert (if vhdl-clock-rising-edge "rising" "falling")
7305 "_edge(" clock ")")
7306 (insert clock "'event")
7307 (vhdl-insert-keyword " AND ")
7308 (insert clock " = "
7309 (if vhdl-clock-rising-edge vhdl-one-string vhdl-zero-string)))
7310 (vhdl-insert-keyword " THEN")
7311 (vhdl-comment-insert-inline
7312 (concat (if vhdl-clock-rising-edge "rising" "falling") " clock edge"))
7313 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7314 (when (eq vhdl-reset-kind 'sync)
7315 (vhdl-insert-keyword "IF ")
7316 (setq reset (or (and (not (equal "" vhdl-reset-name))
7317 (progn (insert vhdl-reset-name) vhdl-reset-name))
7318 (vhdl-template-field "reset name") "<reset>"))
7319 (insert " = "
7320 (if vhdl-reset-active-high vhdl-one-string vhdl-zero-string))
7321 (vhdl-insert-keyword " THEN")
7322 (vhdl-comment-insert-inline
7323 (concat "synchronous reset (active "
7324 (if vhdl-reset-active-high "high" "low") ")"))
7325 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7326 (setq position (point))
7327 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7328 (vhdl-insert-keyword "ELSE")
7329 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset)))
7330 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
7331 (vhdl-insert-keyword "END IF;"))
7332 (when (eq vhdl-reset-kind 'none)
7333 (setq position (point)))
7334 (insert "\n") (indent-to margin)
d2ddb974 7335 (vhdl-insert-keyword "END IF;")
5eabfe72
KH
7336 (goto-char position)
7337 reset))
d2ddb974 7338
5eabfe72
KH
7339(defun vhdl-template-standard-package (library package)
7340 "Insert specification of a standard package. Include a library
7341specification, if not already there."
7342 (let ((margin (current-indentation))
7343 (case-fold-search t))
7344 (save-excursion
7345 (vhdl-ext-syntax-table
7346 (and (not (bobp))
7347 (re-search-backward
7348 (concat "^\\s-*\\(library\\s-+\\(\\(\\w\\|\\s_\\)+,\\s-+\\)*"
7349 library "\\|end\\)\\>") nil t))))
7350 (unless (and (match-string 1) (string-match "library" (match-string 1)))
7351 (vhdl-insert-keyword "LIBRARY ")
7352 (insert library ";\n")
7353 (indent-to margin))
d2ddb974
KH
7354 (vhdl-insert-keyword "USE ")
7355 (insert library "." package)
5eabfe72 7356 (vhdl-insert-keyword ".ALL;")))
d2ddb974 7357
5eabfe72
KH
7358(defun vhdl-template-package-math-complex ()
7359 "Insert specification of `math_complex' package."
d2ddb974 7360 (interactive)
5eabfe72 7361 (vhdl-template-standard-package "ieee" "math_complex"))
d2ddb974 7362
5eabfe72
KH
7363(defun vhdl-template-package-math-real ()
7364 "Insert specification of `math_real' package."
d2ddb974 7365 (interactive)
5eabfe72 7366 (vhdl-template-standard-package "ieee" "math_real"))
d2ddb974 7367
5eabfe72
KH
7368(defun vhdl-template-package-numeric-bit ()
7369 "Insert specification of `numeric_bit' package."
d2ddb974 7370 (interactive)
5eabfe72 7371 (vhdl-template-standard-package "ieee" "numeric_bit"))
d2ddb974 7372
5eabfe72
KH
7373(defun vhdl-template-package-numeric-std ()
7374 "Insert specification of `numeric_std' package."
d2ddb974 7375 (interactive)
5eabfe72 7376 (vhdl-template-standard-package "ieee" "numeric_std"))
d2ddb974 7377
5eabfe72
KH
7378(defun vhdl-template-package-std-logic-1164 ()
7379 "Insert specification of `std_logic_1164' package."
7380 (interactive)
7381 (vhdl-template-standard-package "ieee" "std_logic_1164"))
d2ddb974 7382
5eabfe72
KH
7383(defun vhdl-template-package-std-logic-arith ()
7384 "Insert specification of `std_logic_arith' package."
7385 (interactive)
7386 (vhdl-template-standard-package "ieee" "std_logic_arith"))
7387
7388(defun vhdl-template-package-std-logic-misc ()
7389 "Insert specification of `std_logic_misc' package."
7390 (interactive)
7391 (vhdl-template-standard-package "ieee" "std_logic_misc"))
7392
7393(defun vhdl-template-package-std-logic-signed ()
7394 "Insert specification of `std_logic_signed' package."
7395 (interactive)
7396 (vhdl-template-standard-package "ieee" "std_logic_signed"))
d2ddb974 7397
5eabfe72
KH
7398(defun vhdl-template-package-std-logic-textio ()
7399 "Insert specification of `std_logic_textio' package."
7400 (interactive)
7401 (vhdl-template-standard-package "ieee" "std_logic_textio"))
7402
7403(defun vhdl-template-package-std-logic-unsigned ()
7404 "Insert specification of `std_logic_unsigned' package."
7405 (interactive)
7406 (vhdl-template-standard-package "ieee" "std_logic_unsigned"))
7407
7408(defun vhdl-template-package-textio ()
7409 "Insert specification of `textio' package."
7410 (interactive)
7411 (vhdl-template-standard-package "std" "textio"))
7412
7413(defun vhdl-template-directive (directive)
7414 "Insert directive."
7415 (unless (= (current-indentation) (current-column))
7416 (delete-horizontal-space)
7417 (insert " "))
7418 (insert "-- pragma " directive))
7419
7420(defun vhdl-template-directive-translate-on ()
7421 "Insert directive 'translate_on'."
7422 (interactive)
7423 (vhdl-template-directive "translate_on"))
7424
7425(defun vhdl-template-directive-translate-off ()
7426 "Insert directive 'translate_off'."
7427 (interactive)
7428 (vhdl-template-directive "translate_off"))
7429
7430(defun vhdl-template-directive-synthesis-on ()
7431 "Insert directive 'synthesis_on'."
7432 (interactive)
7433 (vhdl-template-directive "synthesis_on"))
7434
7435(defun vhdl-template-directive-synthesis-off ()
7436 "Insert directive 'synthesis_off'."
7437 (interactive)
7438 (vhdl-template-directive "synthesis_off"))
7439
7440;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7441;; Comment templates and functions
7442
7443(defun vhdl-comment-indent ()
7444 "Indent comments."
7445 (let* ((position (point))
7446 (col
7447 (progn
7448 (forward-line -1)
7449 (if (re-search-forward "--" position t)
7450 (- (current-column) 2) ; existing comment at bol stays there
7451 (goto-char position)
7452 (skip-chars-backward " \t")
7453 (max comment-column ; else indent to comment column
7454 (1+ (current-column))))))) ; except leave at least one space
7455 (goto-char position)
7456 col))
7457
7458(defun vhdl-comment-insert ()
d2ddb974 7459 "Start a comment at the end of the line.
5eabfe72
KH
7460If on line with code, indent at least `comment-column'.
7461If starting after end-comment-column, start a new line."
d2ddb974 7462 (interactive)
5eabfe72
KH
7463 (when (> (current-column) end-comment-column) (newline-and-indent))
7464 (if (or (looking-at "\\s-*$") ; end of line
d2ddb974
KH
7465 (and (not unread-command-events) ; called with key binding or menu
7466 (not (end-of-line))))
5eabfe72
KH
7467 (let (margin)
7468 (while (= (preceding-char) ?-) (delete-char -1))
d2ddb974 7469 (setq margin (current-column))
5eabfe72
KH
7470 (delete-horizontal-space)
7471 (if (bolp)
7472 (progn (indent-to margin) (insert "--"))
d2ddb974 7473 (insert " ")
5eabfe72
KH
7474 (indent-to comment-column)
7475 (insert "--"))
d2ddb974 7476 (if (not unread-command-events) (insert " ")))
5eabfe72 7477 ;; else code following current point implies commenting out code
d2ddb974
KH
7478 (let (next-input code)
7479 (while (= (preceding-char) ?-) (delete-char -2))
7480 (while (= (setq next-input (read-char)) 13) ; CR
5eabfe72 7481 (insert "--") ; or have a space after it?
d2ddb974
KH
7482 (forward-char -2)
7483 (forward-line 1)
7484 (message "Enter CR if commenting out a line of code.")
5eabfe72
KH
7485 (setq code t))
7486 (when (not code)
7487 (insert "--")) ; hardwire to 1 space or use vhdl-basic-offset?
d2ddb974 7488 (setq unread-command-events
5eabfe72 7489 (list (vhdl-character-to-event next-input)))))) ; pushback the char
d2ddb974 7490
5eabfe72 7491(defun vhdl-comment-display (&optional line-exists)
d2ddb974
KH
7492 "Add 2 comment lines at the current indent, making a display comment."
7493 (interactive)
5eabfe72
KH
7494 (let ((margin (current-indentation)))
7495 (when (not line-exists) (vhdl-comment-display-line))
7496 (insert "\n") (indent-to margin)
7497 (insert "\n") (indent-to margin)
7498 (vhdl-comment-display-line)
7499 (end-of-line -0)
7500 (insert "-- ")))
7501
7502(defun vhdl-comment-display-line ()
d2ddb974
KH
7503 "Displays one line of dashes."
7504 (interactive)
7505 (while (= (preceding-char) ?-) (delete-char -2))
7506 (let* ((col (current-column))
7507 (len (- end-comment-column col)))
5eabfe72 7508 (insert-char ?- len)))
d2ddb974 7509
5eabfe72
KH
7510(defun vhdl-comment-append-inline ()
7511 "Append empty inline comment to current line."
7512 (interactive)
7513 (end-of-line)
7514 (delete-horizontal-space)
7515 (insert " ")
7516 (indent-to comment-column)
7517 (insert "-- "))
7518
7519(defun vhdl-comment-insert-inline (&optional string always-insert)
7520 "Insert inline comment."
7521 (when (or (and string (or vhdl-self-insert-comments always-insert))
7522 (and (not string) vhdl-prompt-for-comments))
7523 (let ((position (point)))
7524 (insert " ")
7525 (indent-to comment-column)
7526 (insert "-- ")
7527 (if (or (and string (progn (insert string) t))
7528 (vhdl-template-field "[comment]" nil t))
7529 (when (> (current-column) end-comment-column)
7530 (setq position (point-marker))
7531 (re-search-backward "-- ")
7532 (insert "\n")
7533 (indent-to comment-column)
7534 (goto-char position))
7535 (delete-region position (point))))))
7536
7537(defun vhdl-comment-block ()
7538 "Insert comment for code block."
7539 (when vhdl-prompt-for-comments
7540 (let ((final-pos (point-marker))
7541 (case-fold-search t))
7542 (vhdl-ext-syntax-table
7543 (when (and (re-search-backward "^\\s-*begin\\>" nil t)
7544 (re-search-backward
7545 "\\<\\(architecture\\|block\\|function\\|procedure\\|process\\|procedural\\)\\>"
7546 nil t))
7547 (let (margin)
7548 (back-to-indentation)
7549 (setq margin (current-column))
7550 (end-of-line -0)
7551 (if (bobp)
7552 (progn (insert "\n") (forward-line -1))
7553 (insert "\n"))
7554 (indent-to margin)
7555 (insert "-- purpose: ")
7556 (unless (vhdl-template-field "[description]" nil t)
7557 (vhdl-line-kill-entire)))))
7558 (goto-char final-pos))))
d2ddb974
KH
7559
7560(defun vhdl-comment-uncomment-region (beg end &optional arg)
5eabfe72 7561 "Comment out region if not commented out, uncomment otherwise."
d2ddb974 7562 (interactive "r\nP")
5eabfe72
KH
7563 (save-excursion
7564 (goto-char (1- end))
7565 (end-of-line)
7566 (setq end (point-marker))
7567 (goto-char beg)
7568 (beginning-of-line)
7569 (setq beg (point))
7570 (if (looking-at comment-start)
e3c46ed6 7571 (comment-region beg end -2)
5eabfe72
KH
7572 (comment-region beg end))))
7573
7574(defun vhdl-comment-uncomment-line (&optional arg)
7575 "Comment out line if not commented out, uncomment otherwise."
d2ddb974 7576 (interactive "p")
5eabfe72
KH
7577 (save-excursion
7578 (beginning-of-line)
7579 (let ((position (point)))
7580 (forward-line (or arg 1))
7581 (vhdl-comment-uncomment-region position (point)))))
d2ddb974 7582
5eabfe72
KH
7583(defun vhdl-comment-kill-region (beg end)
7584 "Kill comments in region."
7585 (interactive "r")
7586 (save-excursion
7587 (goto-char end)
7588 (setq end (point-marker))
7589 (goto-char beg)
7590 (beginning-of-line)
7591 (while (< (point) end)
7592 (if (looking-at "^\\(\\s-*--.*\n\\)")
7593 (progn (delete-region (match-beginning 1) (match-end 1)))
7594 (beginning-of-line 2)))))
7595
7596(defun vhdl-comment-kill-inline-region (beg end)
7597 "Kill inline comments in region."
7598 (interactive "r")
7599 (save-excursion
7600 (goto-char end)
7601 (setq end (point-marker))
7602 (goto-char beg)
7603 (beginning-of-line)
7604 (while (< (point) end)
7605 (when (looking-at "^.*[^ \t\n-]+\\(\\s-*--.*\\)$")
7606 (delete-region (match-beginning 1) (match-end 1)))
7607 (beginning-of-line 2))))
7608
7609;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7610;; Subtemplates
7611
7612(defun vhdl-template-begin-end (construct name margin &optional empty-lines)
d2ddb974
KH
7613 "Insert a begin ... end pair with optional name after the end.
7614Point is left between them."
5eabfe72 7615 (let (position)
d2ddb974 7616 (insert "\n")
5eabfe72 7617 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
d2ddb974
KH
7618 (indent-to margin)
7619 (vhdl-insert-keyword "BEGIN")
5eabfe72
KH
7620 (when (and (or construct name) vhdl-self-insert-comments)
7621 (insert " --")
7622 (when construct (insert " ") (vhdl-insert-keyword construct))
7623 (when name (insert " " name)))
d2ddb974 7624 (insert "\n")
5eabfe72 7625 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
d2ddb974 7626 (indent-to (+ margin vhdl-basic-offset))
5eabfe72
KH
7627 (setq position (point))
7628 (insert "\n")
7629 (when (or empty-lines (eq vhdl-insert-empty-lines 'all)) (insert "\n"))
d2ddb974
KH
7630 (indent-to margin)
7631 (vhdl-insert-keyword "END")
5eabfe72
KH
7632 (when construct (insert " ") (vhdl-insert-keyword construct))
7633 (insert (if name (concat " " name) "") ";")
7634 (goto-char position)))
d2ddb974 7635
5eabfe72 7636(defun vhdl-template-argument-list (&optional is-function)
d2ddb974
KH
7637 "Read from user a procedure or function argument list."
7638 (insert " (")
d2ddb974 7639 (let ((margin (current-column))
5eabfe72
KH
7640 (start (point))
7641 (end-pos (point))
7642 not-empty interface semicolon-pos)
7643 (when (not vhdl-argument-list-indent)
7644 (setq margin (+ (current-indentation) vhdl-basic-offset))
7645 (insert "\n")
7646 (indent-to margin))
7647 (setq interface (vhdl-template-field
7648 (concat "[CONSTANT | SIGNAL"
7649 (unless is-function " | VARIABLE") "]") " " t))
7650 (while (vhdl-template-field "[names]" nil t)
7651 (setq not-empty t)
7652 (insert " : ")
7653 (when (not is-function)
7654 (if (and interface (equal (upcase interface) "CONSTANT"))
7655 (vhdl-insert-keyword "IN ")
7656 (vhdl-template-field "[IN | OUT | INOUT]" " " t)))
7657 (vhdl-template-field "type")
7658 (setq semicolon-pos (point))
7659 (insert ";")
7660 (vhdl-comment-insert-inline)
7661 (setq end-pos (point))
7662 (insert "\n")
7663 (indent-to margin)
7664 (setq interface (vhdl-template-field
7665 (concat "[CONSTANT | SIGNAL"
7666 (unless is-function " | VARIABLE") "]") " " t)))
7667 (delete-region end-pos (point))
7668 (when semicolon-pos (goto-char semicolon-pos))
7669 (if not-empty
7670 (progn (delete-char 1) (insert ")"))
7671 (backward-delete-char 2))))
7672
7673(defun vhdl-template-generic-list (optional &optional no-value)
d2ddb974 7674 "Read from user a generic spec argument list."
5eabfe72 7675 (let (margin
d2ddb974 7676 (start (point)))
5eabfe72
KH
7677 (vhdl-insert-keyword "GENERIC (")
7678 (setq margin (current-column))
7679 (when (not vhdl-argument-list-indent)
7680 (let ((position (point)))
7681 (back-to-indentation)
7682 (setq margin (+ (current-column) vhdl-basic-offset))
7683 (goto-char position)
7684 (insert "\n")
7685 (indent-to margin)))
7686 (let ((vhdl-generics (vhdl-template-field
7687 (concat (and optional "[") "name"
7688 (and no-value "s") (and optional "]"))
7689 nil optional)))
7690 (if (not vhdl-generics)
d2ddb974 7691 (if optional
5eabfe72
KH
7692 (progn (vhdl-line-kill-entire) (end-of-line -0)
7693 (when (not vhdl-argument-list-indent)
7694 (vhdl-line-kill-entire) (end-of-line -0)))
7695 (vhdl-template-undo start (point))
d2ddb974
KH
7696 nil )
7697 (insert " : ")
5eabfe72
KH
7698 (let (semicolon-pos end-pos)
7699 (while vhdl-generics
7700 (vhdl-template-field "type")
7701 (if no-value
7702 (progn (setq semicolon-pos (point))
7703 (insert ";"))
7704 (insert " := ")
7705 (unless (vhdl-template-field "[value]" nil t)
7706 (delete-char -4))
7707 (setq semicolon-pos (point))
7708 (insert ";"))
7709 (vhdl-comment-insert-inline)
7710 (setq end-pos (point))
7711 (insert "\n")
7712 (indent-to margin)
7713 (setq vhdl-generics (vhdl-template-field
7714 (concat "[name" (and no-value "s") "]")
7715 " : " t)))
7716 (delete-region end-pos (point))
7717 (goto-char semicolon-pos)
7718 (insert ")")
7719 (end-of-line)
7720 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))
7721 t)))))
7722
7723(defun vhdl-template-port-list (optional)
7724 "Read from user a port spec argument list."
7725 (let ((start (point))
7726 margin vhdl-ports object)
7727 (vhdl-insert-keyword "PORT (")
7728 (setq margin (current-column))
7729 (when (not vhdl-argument-list-indent)
7730 (let ((position (point)))
7731 (back-to-indentation)
7732 (setq margin (+ (current-column) vhdl-basic-offset))
7733 (goto-char position)
7734 (insert "\n")
7735 (indent-to margin)))
7736 (when (vhdl-standard-p 'ams)
7737 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7738 " " t)))
7739 (setq vhdl-ports (vhdl-template-field
7740 (concat (and optional "[") "names" (and optional "]"))
7741 nil optional))
7742 (if (not vhdl-ports)
7743 (if optional
7744 (progn (vhdl-line-kill-entire) (end-of-line -0)
7745 (when (not vhdl-argument-list-indent)
7746 (vhdl-line-kill-entire) (end-of-line -0)))
7747 (vhdl-template-undo start (point))
7748 nil)
7749 (insert " : ")
7750 (let (semicolon-pos end-pos)
7751 (while vhdl-ports
7752 (cond ((or (null object) (equal "SIGNAL" (upcase object)))
7753 (vhdl-template-field "IN | OUT | INOUT" " "))
7754 ((equal "QUANTITY" (upcase object))
7755 (vhdl-template-field "[IN | OUT]" " " t)))
7756 (vhdl-template-field
7757 (if (and object (equal "TERMINAL" (upcase object)))
7758 "nature" "type"))
7759 (setq semicolon-pos (point))
7760 (insert ";")
7761 (vhdl-comment-insert-inline)
7762 (setq end-pos (point))
7763 (insert "\n")
7764 (indent-to margin)
7765 (when (vhdl-standard-p 'ams)
7766 (setq object (vhdl-template-field "[SIGNAL | TERMINAL | QUANTITY]"
7767 " " t)))
7768 (setq vhdl-ports (vhdl-template-field "[names]" " : " t)))
7769 (delete-region end-pos (point))
7770 (goto-char semicolon-pos)
7771 (insert ")")
7772 (end-of-line)
7773 (when vhdl-auto-align (vhdl-align-noindent-region start end-pos 1))
7774 t))))
7775
7776(defun vhdl-template-generate-body (margin label)
7777 "Insert body for generate template."
7778 (vhdl-insert-keyword " GENERATE")
7779 (if (not (vhdl-standard-p '87))
7780 (vhdl-template-begin-end "GENERATE" label margin)
7781 (insert "\n\n")
7782 (indent-to margin)
7783 (vhdl-insert-keyword "END GENERATE ")
7784 (insert label ";")
7785 (end-of-line 0)
7786 (indent-to (+ margin vhdl-basic-offset))))
7787
7788(defun vhdl-template-insert-date ()
d2ddb974
KH
7789 "Insert date in appropriate format."
7790 (interactive)
5eabfe72
KH
7791 (insert
7792 (cond
7793 ;; 'american, 'european', 'scientific kept for backward compatibility
7794 ((eq vhdl-date-format 'american) (format-time-string "%m/%d/%Y" nil))
7795 ((eq vhdl-date-format 'european) (format-time-string "%d.%m.%Y" nil))
7796 ((eq vhdl-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
7797 (t (format-time-string vhdl-date-format nil)))))
7798
7799;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7800;; Help functions
7801
7802(defun vhdl-electric-space (count)
7803 "Expand abbreviations and self-insert space(s), do indent-new-comment-line
7804if in comment and past end-comment-column."
7805 (interactive "p")
7806 (cond ((vhdl-in-comment-p)
7807 (self-insert-command count)
7808 (cond ((>= (current-column) (+ 2 end-comment-column))
7809 (backward-word 1)
7810 (indent-new-comment-line)
7811 (forward-word 1)
7812 (forward-char 1))
7813 ((>= (current-column) end-comment-column)
7814 (indent-new-comment-line))
7815 (t nil)))
7816 ((or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
7817 (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z)))
7818 (vhdl-ext-syntax-table
7819 (let ((case-fold-search t))
7820 (expand-abbrev)))
7821 (self-insert-command count))
7822 (t (self-insert-command count))))
7823
7824(defun vhdl-template-field (prompt &optional follow-string optional
7825 begin end is-string default)
7826 "Prompt for string and insert it in buffer with optional FOLLOW-STRING.
7827If OPTIONAL is nil, the prompt is left if an empty string is inserted. If
7828an empty string is inserted, return nil and call `vhdl-template-undo' for
7829the region between BEGIN and END. IS-STRING indicates whether a string
7830with double-quotes is to be inserted. DEFAULT specifies a default string."
7831 (let ((position (point))
7832 string)
7833 (insert "<" prompt ">")
7834 (setq string
7835 (condition-case ()
7836 (read-from-minibuffer (concat prompt ": ")
7837 (or (and is-string '("\"\"" . 2)) default)
7838 vhdl-minibuffer-local-map)
7839 (quit (if (and optional begin end)
7840 (progn (beep) "")
7841 (keyboard-quit)))))
7842 (when (or (not (equal string "")) optional)
7843 (delete-region position (point)))
7844 (when (and (equal string "") optional begin end)
7845 (vhdl-template-undo begin end)
7846 (message "Template aborted"))
7847 (when (not (equal string ""))
7848 (insert string)
7849 (vhdl-fix-case-region-1 position (point) vhdl-upper-case-keywords
7850 vhdl-keywords-regexp))
7851 (when (or (not (equal string "")) (not optional))
7852 (insert (or follow-string "")))
7853 (if (equal string "") nil string)))
7854
7855(defun vhdl-decision-query (string prompt &optional optional)
7856 "Query a decision from the user."
7857 (let ((start (point)))
7858 (when string (vhdl-insert-keyword (concat string " ")))
7859 (message prompt)
7860 (let ((char (read-char)))
7861 (delete-region start (point))
7862 (if (and optional (eq char ?\r))
7863 (progn (insert " ")
7864 (unexpand-abbrev)
7865 (throw 'abort "Template aborted"))
7866 char))))
d2ddb974
KH
7867
7868(defun vhdl-insert-keyword (keyword)
5eabfe72
KH
7869 "Insert KEYWORD and adjust case."
7870 (insert (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword))))
d2ddb974
KH
7871
7872(defun vhdl-case-keyword (keyword)
5eabfe72
KH
7873 "Adjust case of KEYWORD."
7874 (if vhdl-upper-case-keywords (upcase keyword) (downcase keyword)))
d2ddb974
KH
7875
7876(defun vhdl-case-word (num)
5eabfe72
KH
7877 "Adjust case or following NUM words."
7878 (if vhdl-upper-case-keywords (upcase-word num) (downcase-word num)))
7879
7880(defun vhdl-minibuffer-tab (&optional prefix-arg)
7881 "If preceeding character is part of a word or a paren then hippie-expand,
7882else if right of non whitespace on line then tab-to-tab-stop,
7883else indent line in proper way for current major mode (used for word
7884completion in VHDL minibuffer)."
7885 (interactive "P")
7886 (cond ((= (char-syntax (preceding-char)) ?w)
7887 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7888 (case-replace nil))
7889 (vhdl-expand-abbrev prefix-arg)))
7890 ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
7891 (let ((case-fold-search (not vhdl-word-completion-case-sensitive))
7892 (case-replace nil))
7893 (vhdl-expand-paren prefix-arg)))
7894 ((> (current-column) (current-indentation))
7895 (tab-to-tab-stop))
7896 (t (if (eq indent-line-function 'indent-to-left-margin)
7897 (insert-tab prefix-arg)
7898 (if prefix-arg
7899 (funcall indent-line-function prefix-arg)
7900 (funcall indent-line-function))))))
7901
7902(defun vhdl-template-search-prompt ()
7903 "Search for left out template prompts and query again."
7904 (interactive)
7905 (let ((case-fold-search t))
7906 (vhdl-ext-syntax-table
7907 (when (or (re-search-forward
7908 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t)
7909 (re-search-backward
7910 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") nil t))
7911 (let ((string (match-string 1)))
7912 (replace-match "")
7913 (vhdl-template-field string))))))
7914
7915(defun vhdl-template-undo (begin end)
7916 "Undo aborted template by deleting region and unexpanding the keyword."
7917 (cond (vhdl-template-invoked-by-hook
7918 (goto-char end)
7919 (insert " ")
7920 (delete-region begin end)
7921 (unexpand-abbrev))
7922 (t (delete-region begin end))))
7923
7924(defun vhdl-insert-string-or-file (string)
7925 "Insert STRING or file contents if STRING is an existing file name."
7926 (unless (equal string "")
7927 (cond ((file-exists-p string)
7928 (forward-char (cadr (insert-file-contents string))))
7929 (t (insert string)))))
7930
7931(defun vhdl-sequential-statement-p ()
7932 "Check if point is within sequential statement part."
7933 (save-excursion
7934 (let ((case-fold-search t)
7935 (start (point)))
7936 (vhdl-ext-syntax-table
7937 (set-match-data nil)
7938 (while (and (re-search-backward "^\\s-*\\(begin\\|end\\(\\s-*\\(case\\|if\\|loop\\)\\)?\\)\\>"
7939 nil t)
7940 (match-string 2)))
7941 (and (match-data)
7942 (equal "BEGIN" (upcase (match-string 1)))
7943 (re-search-backward "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(\\w+\\s-+\\)?\\(function\\|procedure\\|process\\|procedural\\|end\\)\\>"
7944 nil t)
7945 (not (equal "END" (upcase (match-string 3)))))))))
7946
7947(defun vhdl-in-argument-list-p ()
7948 "Check if within an argument list."
7949 (save-excursion
7950 (let ((case-fold-search t))
7951 (vhdl-ext-syntax-table
7952 (or (string-match "arglist"
7953 (format "%s" (car (car (vhdl-get-syntactic-context)))))
7954 (progn (beginning-of-line)
7955 (looking-at "^\\s-*\\(generic\\|port\\|\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\)\\>\\s-*\\(\\w+\\s-*\\)?(")
7956 ))))))
7957
7958;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7959;; Abbrev hooks
7960
7961(defun vhdl-hooked-abbrev (func)
7962 "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
7963but not if inside a comment or quote)."
7964 (if (or (vhdl-in-comment-p)
7965 (vhdl-in-string-p)
7966 (save-excursion
7967 (forward-word -1)
7968 (and (looking-at "\\<end\\>") (not (looking-at "\\<end;")))))
7969 (progn
7970 (insert " ")
7971 (unexpand-abbrev)
7972 (delete-char -1))
7973 (if (not vhdl-electric-mode)
7974 (progn
7975 (insert " ")
7976 (unexpand-abbrev)
7977 (backward-word 1)
7978 (vhdl-case-word 1)
7979 (delete-char 1))
7980 (let ((invoke-char last-command-char)
7981 (abbrev-mode -1)
7982 (vhdl-template-invoked-by-hook t))
7983 (let ((caught (catch 'abort
7984 (funcall func))))
7985 (when (stringp caught) (message caught)))
7986 (when (= invoke-char ?-) (setq abbrev-start-location (point)))
7987 ;; delete CR which is still in event queue
7988 (if (string-match "XEmacs" emacs-version)
7989 (enqueue-eval-event 'delete-char -1)
7990 (setq unread-command-events ; push back a delete char
7991 (list (vhdl-character-to-event ?\177))))))))
7992
7993(defun vhdl-template-alias-hook ()
7994 (vhdl-hooked-abbrev 'vhdl-template-alias))
7995(defun vhdl-template-architecture-hook ()
7996 (vhdl-hooked-abbrev 'vhdl-template-architecture))
7997(defun vhdl-template-assert-hook ()
7998 (vhdl-hooked-abbrev 'vhdl-template-assert))
7999(defun vhdl-template-attribute-hook ()
8000 (vhdl-hooked-abbrev 'vhdl-template-attribute))
8001(defun vhdl-template-block-hook ()
8002 (vhdl-hooked-abbrev 'vhdl-template-block))
8003(defun vhdl-template-break-hook ()
8004 (vhdl-hooked-abbrev 'vhdl-template-break))
8005(defun vhdl-template-case-hook ()
8006 (vhdl-hooked-abbrev 'vhdl-template-case))
8007(defun vhdl-template-component-hook ()
8008 (vhdl-hooked-abbrev 'vhdl-template-component))
8009(defun vhdl-template-instance-hook ()
8010 (vhdl-hooked-abbrev 'vhdl-template-instance))
8011(defun vhdl-template-conditional-signal-asst-hook ()
8012 (vhdl-hooked-abbrev 'vhdl-template-conditional-signal-asst))
8013(defun vhdl-template-configuration-hook ()
8014 (vhdl-hooked-abbrev 'vhdl-template-configuration))
8015(defun vhdl-template-constant-hook ()
8016 (vhdl-hooked-abbrev 'vhdl-template-constant))
8017(defun vhdl-template-disconnect-hook ()
8018 (vhdl-hooked-abbrev 'vhdl-template-disconnect))
8019(defun vhdl-template-display-comment-hook ()
8020 (vhdl-hooked-abbrev 'vhdl-comment-display))
8021(defun vhdl-template-else-hook ()
8022 (vhdl-hooked-abbrev 'vhdl-template-else))
8023(defun vhdl-template-elsif-hook ()
8024 (vhdl-hooked-abbrev 'vhdl-template-elsif))
8025(defun vhdl-template-entity-hook ()
8026 (vhdl-hooked-abbrev 'vhdl-template-entity))
8027(defun vhdl-template-exit-hook ()
8028 (vhdl-hooked-abbrev 'vhdl-template-exit))
8029(defun vhdl-template-file-hook ()
8030 (vhdl-hooked-abbrev 'vhdl-template-file))
8031(defun vhdl-template-for-hook ()
8032 (vhdl-hooked-abbrev 'vhdl-template-for))
8033(defun vhdl-template-function-hook ()
8034 (vhdl-hooked-abbrev 'vhdl-template-function))
8035(defun vhdl-template-generic-hook ()
8036 (vhdl-hooked-abbrev 'vhdl-template-generic))
8037(defun vhdl-template-group-hook ()
8038 (vhdl-hooked-abbrev 'vhdl-template-group))
8039(defun vhdl-template-library-hook ()
8040 (vhdl-hooked-abbrev 'vhdl-template-library))
8041(defun vhdl-template-limit-hook ()
8042 (vhdl-hooked-abbrev 'vhdl-template-limit))
8043(defun vhdl-template-if-hook ()
8044 (vhdl-hooked-abbrev 'vhdl-template-if))
8045(defun vhdl-template-bare-loop-hook ()
8046 (vhdl-hooked-abbrev 'vhdl-template-bare-loop))
8047(defun vhdl-template-map-hook ()
8048 (vhdl-hooked-abbrev 'vhdl-template-map))
8049(defun vhdl-template-nature-hook ()
8050 (vhdl-hooked-abbrev 'vhdl-template-nature))
8051(defun vhdl-template-next-hook ()
8052 (vhdl-hooked-abbrev 'vhdl-template-next))
8053(defun vhdl-template-package-hook ()
8054 (vhdl-hooked-abbrev 'vhdl-template-package))
8055(defun vhdl-template-port-hook ()
8056 (vhdl-hooked-abbrev 'vhdl-template-port))
8057(defun vhdl-template-procedural-hook ()
8058 (vhdl-hooked-abbrev 'vhdl-template-procedural))
8059(defun vhdl-template-procedure-hook ()
8060 (vhdl-hooked-abbrev 'vhdl-template-procedure))
8061(defun vhdl-template-process-hook ()
8062 (vhdl-hooked-abbrev 'vhdl-template-process))
8063(defun vhdl-template-quantity-hook ()
8064 (vhdl-hooked-abbrev 'vhdl-template-quantity))
8065(defun vhdl-template-report-hook ()
8066 (vhdl-hooked-abbrev 'vhdl-template-report))
8067(defun vhdl-template-return-hook ()
8068 (vhdl-hooked-abbrev 'vhdl-template-return))
8069(defun vhdl-template-selected-signal-asst-hook ()
8070 (vhdl-hooked-abbrev 'vhdl-template-selected-signal-asst))
8071(defun vhdl-template-signal-hook ()
8072 (vhdl-hooked-abbrev 'vhdl-template-signal))
8073(defun vhdl-template-subnature-hook ()
8074 (vhdl-hooked-abbrev 'vhdl-template-subnature))
8075(defun vhdl-template-subtype-hook ()
8076 (vhdl-hooked-abbrev 'vhdl-template-subtype))
8077(defun vhdl-template-terminal-hook ()
8078 (vhdl-hooked-abbrev 'vhdl-template-terminal))
8079(defun vhdl-template-type-hook ()
8080 (vhdl-hooked-abbrev 'vhdl-template-type))
8081(defun vhdl-template-use-hook ()
8082 (vhdl-hooked-abbrev 'vhdl-template-use))
8083(defun vhdl-template-variable-hook ()
8084 (vhdl-hooked-abbrev 'vhdl-template-variable))
8085(defun vhdl-template-wait-hook ()
8086 (vhdl-hooked-abbrev 'vhdl-template-wait))
8087(defun vhdl-template-when-hook ()
8088 (vhdl-hooked-abbrev 'vhdl-template-when))
8089(defun vhdl-template-while-loop-hook ()
8090 (vhdl-hooked-abbrev 'vhdl-template-while-loop))
8091(defun vhdl-template-with-hook ()
8092 (vhdl-hooked-abbrev 'vhdl-template-with))
8093(defun vhdl-template-and-hook ()
8094 (vhdl-hooked-abbrev 'vhdl-template-and))
8095(defun vhdl-template-or-hook ()
8096 (vhdl-hooked-abbrev 'vhdl-template-or))
8097(defun vhdl-template-nand-hook ()
8098 (vhdl-hooked-abbrev 'vhdl-template-nand))
8099(defun vhdl-template-nor-hook ()
8100 (vhdl-hooked-abbrev 'vhdl-template-nor))
8101(defun vhdl-template-xor-hook ()
8102 (vhdl-hooked-abbrev 'vhdl-template-xor))
8103(defun vhdl-template-xnor-hook ()
8104 (vhdl-hooked-abbrev 'vhdl-template-xnor))
8105(defun vhdl-template-not-hook ()
8106 (vhdl-hooked-abbrev 'vhdl-template-not))
8107
8108(defun vhdl-template-default-hook ()
8109 (vhdl-hooked-abbrev 'vhdl-template-default))
8110(defun vhdl-template-default-indent-hook ()
8111 (vhdl-hooked-abbrev 'vhdl-template-default-indent))
8112
8113;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8114;; Template insertion from completion list
8115
8116(defun vhdl-template-insert-construct (name)
8117 "Insert the built-in construct template with NAME."
8118 (interactive
8119 (list (let ((completion-ignore-case t))
8120 (completing-read "Construct name: "
8121 vhdl-template-construct-alist nil t))))
8122 (vhdl-template-insert-fun
8123 (car (cdr (assoc name vhdl-template-construct-alist)))))
8124
8125(defun vhdl-template-insert-package (name)
8126 "Insert the built-in package template with NAME."
8127 (interactive
8128 (list (let ((completion-ignore-case t))
8129 (completing-read "Package name: "
8130 vhdl-template-package-alist nil t))))
8131 (vhdl-template-insert-fun
8132 (car (cdr (assoc name vhdl-template-package-alist)))))
8133
8134(defun vhdl-template-insert-directive (name)
8135 "Insert the built-in directive template with NAME."
8136 (interactive
8137 (list (let ((completion-ignore-case t))
8138 (completing-read "Directive name: "
8139 vhdl-template-directive-alist nil t))))
8140 (vhdl-template-insert-fun
8141 (car (cdr (assoc name vhdl-template-directive-alist)))))
8142
8143(defun vhdl-template-insert-fun (fun)
8144 "Call FUN to insert a built-in template."
8145 (let ((caught (catch 'abort (when fun (funcall fun)))))
8146 (when (stringp caught) (message caught))))
8147
8148
8149;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8150;;; Models
8151;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8152
8153(defun vhdl-model-insert (model-name)
8154 "Insert the user model with name MODEL-NAME."
8155 (interactive
8156 (let ((completion-ignore-case t))
8157 (list (completing-read "Model name: " vhdl-model-alist))))
8158 (vhdl-indent-line)
8159 (let ((start (point-marker))
8160 (margin (current-indentation))
8161 (case-fold-search t)
8162 model position prompt string end)
8163 (vhdl-ext-syntax-table
8164 (when (setq model (assoc model-name vhdl-model-alist))
8165 ;; insert model
8166 (beginning-of-line)
8167 (delete-horizontal-space)
8168 (goto-char start)
8169 (vhdl-insert-string-or-file (nth 1 model))
8170 (setq end (point-marker))
8171 ;; indent code
8172 (goto-char start)
8173 (beginning-of-line)
8174 (while (< (point) end)
8175 (unless (looking-at "^$")
8176 (insert-char ? margin))
8177 (beginning-of-line 2))
8178 (goto-char start)
8179 ;; insert clock
8180 (unless (equal "" vhdl-clock-name)
8181 (while (re-search-forward "<clock>" end t)
8182 (replace-match vhdl-clock-name)))
8183 (goto-char start)
8184 ;; insert reset
8185 (unless (equal "" vhdl-reset-name)
8186 (while (re-search-forward "<reset>" end t)
8187 (replace-match vhdl-reset-name)))
8188 (goto-char start)
8189 ;; query prompts
8190 (while (re-search-forward
8191 (concat "<\\(" vhdl-template-prompt-syntax "\\)>") end t)
8192 (unless (equal "cursor" (match-string 1))
8193 (setq position (match-beginning 1))
8194 (setq prompt (match-string 1))
8195 (replace-match "")
8196 (setq string (vhdl-template-field prompt nil t))
a5a08b1f 8197 ;; replace occurrences of same prompt
5eabfe72
KH
8198 (while (re-search-forward (concat "<\\(" prompt "\\)>") end t)
8199 (replace-match (or string "")))
8200 (goto-char position)))
8201 (goto-char start)
8202 ;; goto final position
8203 (if (re-search-forward "<cursor>" end t)
8204 (replace-match "")
8205 (goto-char end))))))
8206
8207(defun vhdl-model-defun ()
8208 "Define help and hook functions for user models."
8209 (let ((model-alist vhdl-model-alist)
8210 model-name model-keyword)
8211 (while model-alist
8212 ;; define functions for user models that can be invoked from menu and key
8213 ;; bindings and which themselves call `vhdl-model-insert' with the model
8214 ;; name as argument
8215 (setq model-name (nth 0 (car model-alist)))
d4a5b644
GM
8216 (eval `(defun ,(vhdl-function-name "vhdl-model" model-name) ()
8217 ,(concat "Insert model for \"" model-name "\".")
8218 (interactive)
8219 (vhdl-model-insert ,model-name)))
5eabfe72
KH
8220 ;; define hooks for user models that are invoked from keyword abbrevs
8221 (setq model-keyword (nth 3 (car model-alist)))
8222 (unless (equal model-keyword "")
d4a5b644
GM
8223 (eval `(defun
8224 ,(vhdl-function-name
8225 "vhdl-model" model-name "hook") ()
8226 (vhdl-hooked-abbrev
8227 ',(vhdl-function-name "vhdl-model" model-name)))))
5eabfe72
KH
8228 (setq model-alist (cdr model-alist)))))
8229
8230(vhdl-model-defun)
8231
8232
8233;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8234;;; Port translation
8235;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8236
8237(defvar vhdl-port-list nil
8238 "Variable to hold last PORT map parsed.")
8239;; structure: (parenthesised expression means list of such entries)
8240;; ((generic-names) generic-type generic-init generic-comment)
8241;; ((port-names) port-object port-direct port-type port-comment)
8242
8243(defun vhdl-parse-string (string &optional optional)
8244 "Check that the text following point matches the regexp in STRING.
8245END is the point beyond which matching/searching should not go."
8246 (if (looking-at string)
8247 (re-search-forward string nil t)
8248 (unless optional
8249 (throw 'parse (format "Syntax error near line %s" (vhdl-current-line))))
8250 nil))
8251
8252(defun vhdl-replace-string (regexp-cons string)
8253 "Replace STRING from car of REGEXP-CONS to cdr of REGEXP-CONS."
8254 (vhdl-ext-syntax-table
8255 (if (string-match (car regexp-cons) string)
8256 (replace-match (cdr regexp-cons) t nil string)
8257 string)))
8258
8259(defun vhdl-port-flatten ()
8260 "Flatten port list so that only one generic/port exists per line."
8261 (interactive)
8262 (if (not vhdl-port-list)
8263 (error "No port read")
8264 (message "Flattening port...")
8265 (let ((new-vhdl-port-list (list (car vhdl-port-list)))
8266 (old-vhdl-port-list (cdr vhdl-port-list))
8267 old-port-list new-port-list old-port new-port names)
8268 ;; traverse port list and flatten entries
8269 (while old-vhdl-port-list
8270 (setq old-port-list (car old-vhdl-port-list))
8271 (setq new-port-list nil)
8272 (while old-port-list
8273 (setq old-port (car old-port-list))
8274 (setq names (car old-port))
8275 (while names
8276 (setq new-port (cons (list (car names)) (cdr old-port)))
8277 (setq new-port-list (append new-port-list (list new-port)))
8278 (setq names (cdr names)))
8279 (setq old-port-list (cdr old-port-list)))
8280 (setq old-vhdl-port-list (cdr old-vhdl-port-list))
8281 (setq new-vhdl-port-list (append new-vhdl-port-list
8282 (list new-port-list))))
8283 (setq vhdl-port-list new-vhdl-port-list)
8284 (message "Flattening port...done"))))
8285
8286(defun vhdl-port-copy ()
8287 "Get generic and port information from an entity or component declaration."
8288 (interactive)
8289 (message "Reading port...")
8290 (save-excursion
8291 (let ((case-fold-search t)
8292 parse-error end-of-list
8293 name generics ports
8294 object names direct type init comment)
8295 (vhdl-ext-syntax-table
8296 (setq
8297 parse-error
8298 (catch 'parse
8299 ;; check if within entity or component declaration
8300 (when (or (not (re-search-backward
8301 "^\\s-*\\(component\\|entity\\|end\\)\\>" nil t))
8302 (equal "end" (match-string 1)))
8303 (throw 'parse "Not within entity or component declaration"))
8304 (forward-word 1)
8305 (vhdl-parse-string "\\s-*\\(\\w+\\)\\s-*\\(is\\)?\\s-*$")
8306 (setq name (match-string 1))
8307 (vhdl-forward-syntactic-ws)
8308 ;; parse generic clause
8309 (when (vhdl-parse-string "generic[ \t\n]*(" t)
8310 (vhdl-forward-syntactic-ws)
8311 (setq end-of-list (looking-at ")"))
8312 (while (not end-of-list)
8313 ;; parse names
8314 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8315 (setq names (list (match-string 1)))
8316 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8317 (setq names (append names (list (match-string 1)))))
8318 ;; parse type
8319 (vhdl-parse-string ":[ \t\n]*\\([^():;\n]+\\)")
8320 (setq type (match-string 1))
8321 (setq comment nil)
8322 (while (looking-at "(")
8323 (setq type
8324 (concat type
8325 (buffer-substring
8326 (point) (progn (forward-sexp) (point)))
8327 (and (vhdl-parse-string "\\([^():;\n]*\\)" t)
8328 (match-string 1)))))
8329 ;; special case: closing parenthesis is on separate line
8330 (when (and type (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type))
8331 (setq comment (substring type (match-beginning 2)))
8332 (setq type (substring type 0 (match-beginning 1))))
8333 ;; strip of trailing whitespace
8334 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8335 (setq type (substring type 0 (match-end 1)))
8336 ;; parse initialization expression
8337 (setq init nil)
8338 (when (vhdl-parse-string ":=[ \t\n]*" t)
8339 (vhdl-parse-string "\\([^();\n]*\\)")
8340 (setq init (match-string 1))
8341 (while (looking-at "(")
8342 (setq init
8343 (concat init
8344 (buffer-substring
8345 (point) (progn (forward-sexp) (point)))
8346 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8347 (match-string 1))))))
8348 ;; special case: closing parenthesis is on separate line
8349 (when (and init (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" init))
8350 (setq comment (substring init (match-beginning 2)))
8351 (setq init (substring init 0 (match-beginning 1)))
8352 (vhdl-forward-syntactic-ws))
8353 (skip-chars-forward " \t")
8354 ;; parse inline comment, special case: as above, no initial.
8355 (unless comment
8356 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8357 (match-string 1))))
8358 (vhdl-forward-syntactic-ws)
8359 (setq end-of-list (vhdl-parse-string ")" t))
d4a5b644 8360 (vhdl-parse-string ";\\s-*")
5eabfe72
KH
8361 ;; parse inline comment
8362 (unless comment
8363 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8364 (match-string 1))))
8365 (vhdl-forward-syntactic-ws)
8366 ;; save everything in list
8367 (setq generics (append generics
8368 (list (list names type init comment))))))
8369 ;; parse port clause
8370 (when (vhdl-parse-string "port[ \t\n]*(" t)
8371 (vhdl-forward-syntactic-ws)
8372 (setq end-of-list (looking-at ")"))
8373 (while (not end-of-list)
8374 ;; parse object
8375 (setq object
8376 (and (vhdl-parse-string
8377 "\\(signal\\|quantity\\|terminal\\)[ \t\n]*" t)
8378 (match-string 1)))
8379 ;; parse names
8380 (vhdl-parse-string "\\(\\w+\\)[ \t\n]*")
8381 (setq names (list (match-string 1)))
8382 (while (vhdl-parse-string ",[ \t\n]*\\(\\w+\\)[ \t\n]*" t)
8383 (setq names (append names (list (match-string 1)))))
8384 ;; parse direction
8385 (vhdl-parse-string ":[ \t\n]*")
8386 (setq direct
8387 (and (vhdl-parse-string "\\(IN\\|OUT\\|INOUT\\)[ \t\n]+" t)
8388 (match-string 1)))
8389 ;; parse type
8390 (vhdl-parse-string "\\([^();\n]+\\)")
8391 (setq type (match-string 1))
8392 (setq comment nil)
8393 (while (looking-at "(")
8394 (setq type (concat type
8395 (buffer-substring
8396 (point) (progn (forward-sexp) (point)))
8397 (and (vhdl-parse-string "\\([^();\n]*\\)" t)
8398 (match-string 1)))))
8399 ;; special case: closing parenthesis is on separate line
8400 (when (string-match "\\(\\s-*--\\s-*\\)\\(.*\\)" type)
8401 (setq comment (substring type (match-beginning 2)))
8402 (setq type (substring type 0 (match-beginning 1))))
8403 ;; strip of trailing whitespace
8404 (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
8405 (setq type (substring type 0 (match-end 1)))
8406 (vhdl-forward-syntactic-ws)
8407 (setq end-of-list (vhdl-parse-string ")" t))
d4a5b644 8408 (vhdl-parse-string ";\\s-*")
5eabfe72
KH
8409 ;; parse inline comment
8410 (unless comment
8411 (setq comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
8412 (match-string 1))))
8413 (vhdl-forward-syntactic-ws)
8414 ;; save everything in list
8415 (setq ports
8416 (append ports
8417 (list (list names object direct type comment))))))
8418 nil)))
8419 ;; finish parsing
8420 (if parse-error
8421 (error parse-error)
8422 (setq vhdl-port-list (list name generics ports))
8423 (message "Reading port...done")))))
8424
8425(defun vhdl-port-paste-generic (&optional no-init)
8426 "Paste a generic clause."
8427 (let ((margin (current-indentation))
8428 list-margin start names generic
8429 (generics-list (nth 1 vhdl-port-list)))
8430 ;; paste generic clause
8431 (when generics-list
8432 (setq start (point))
8433 (vhdl-insert-keyword "GENERIC (")
8434 (unless vhdl-argument-list-indent
8435 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8436 (setq list-margin (current-column))
8437 (while generics-list
8438 ;; paste names
8439 (setq generic (car generics-list))
8440 (setq names (nth 0 generic))
8441 (while names
8442 (insert (car names))
8443 (setq names (cdr names))
8444 (when names (insert ", ")))
8445 ;; paste type
8446 (insert " : " (nth 1 generic))
8447 ;; paste initialization
8448 (when (and (not no-init) (nth 2 generic))
8449 (insert " := " (nth 2 generic)))
8450 (unless (cdr generics-list) (insert ")"))
8451 (insert ";")
8452 ;; paste comment
8453 (when (and vhdl-include-port-comments (nth 3 generic))
8454 (vhdl-comment-insert-inline (nth 3 generic) t))
8455 (setq generics-list (cdr generics-list))
8456 (when generics-list (insert "\n") (indent-to list-margin)))
8457 ;; align generic clause
8458 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1 t)))))
8459
8460(defun vhdl-port-paste-port ()
8461 "Paste a port clause."
8462 (let ((margin (current-indentation))
8463 list-margin start names port
8464 (ports-list (nth 2 vhdl-port-list)))
8465 ;; paste port clause
8466 (when ports-list
8467 (setq start (point))
8468 (vhdl-insert-keyword "PORT (")
8469 (unless vhdl-argument-list-indent
8470 (insert "\n") (indent-to (+ margin vhdl-basic-offset)))
8471 (setq list-margin (current-column))
8472 (while ports-list
8473 (setq port (car ports-list))
8474 ;; paste object
8475 (when (nth 1 port) (insert (nth 1 port) " "))
8476 ;; paste names
8477 (setq names (nth 0 port))
8478 (while names
8479 (insert (car names))
8480 (setq names (cdr names))
8481 (when names (insert ", ")))
8482 ;; paste direction
8483 (insert " : ")
8484 (when (nth 2 port) (insert (nth 2 port) " "))
8485 ;; paste type
8486 (insert (nth 3 port))
8487 (unless (cdr ports-list) (insert ")"))
8488 (insert ";")
8489 ;; paste comment
8490 (when (and vhdl-include-port-comments (nth 4 port))
8491 (vhdl-comment-insert-inline (nth 4 port) t))
8492 (setq ports-list (cdr ports-list))
8493 (when ports-list (insert "\n") (indent-to list-margin)))
8494 ;; align port clause
8495 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1)))))
8496
8497(defun vhdl-port-paste-declaration (kind)
8498 "Paste as an entity or component declaration."
8499 (vhdl-indent-line)
8500 (let ((margin (current-indentation))
8501 (name (nth 0 vhdl-port-list)))
8502 (vhdl-insert-keyword (if (eq kind 'entity) "ENTITY " "COMPONENT "))
8503 (insert name)
8504 (if (eq kind 'entity) (vhdl-insert-keyword " IS"))
8505 ;; paste generic and port clause
8506 (when (nth 1 vhdl-port-list)
8507 (insert "\n")
8508 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8509 (insert "\n"))
8510 (indent-to (+ margin vhdl-basic-offset))
8511 (vhdl-port-paste-generic (eq kind 'component)))
8512 (when (nth 2 vhdl-port-list)
8513 (insert "\n")
8514 (when (and (memq vhdl-insert-empty-lines '(unit all))
8515 (eq kind 'entity))
8516 (insert "\n"))
8517 (indent-to (+ margin vhdl-basic-offset)))
8518 (vhdl-port-paste-port)
8519 (insert "\n")
8520 (when (and (memq vhdl-insert-empty-lines '(unit all)) (eq kind 'entity))
8521 (insert "\n"))
8522 (indent-to margin)
8523 (vhdl-insert-keyword "END")
8524 (if (eq kind 'entity)
8525 (progn
8526 (unless (vhdl-standard-p '87) (vhdl-insert-keyword " ENTITY"))
8527 (insert " " name))
8528 (vhdl-insert-keyword " COMPONENT")
8529 (unless (vhdl-standard-p '87) (insert " " name)))
8530 (insert ";")))
8531
8532(defun vhdl-port-paste-entity ()
8533 "Paste as an entity declaration."
8534 (interactive)
8535 (if (not vhdl-port-list)
8536 (error "No port read")
8537 (message "Pasting port as entity...")
8538 (vhdl-port-paste-declaration 'entity)
8539 (message "Pasting port as entity...done")))
8540
8541(defun vhdl-port-paste-component ()
8542 "Paste as a component declaration."
8543 (interactive)
8544 (if (not vhdl-port-list)
8545 (error "No port read")
8546 (message "Pasting port as component...")
8547 (vhdl-port-paste-declaration 'component)
8548 (message "Pasting port as component...done")))
8549
8550(defun vhdl-port-paste-generic-map (&optional secondary no-constants)
8551 "Paste as a generic map."
8552 (interactive)
8553 (unless secondary (vhdl-indent-line))
8554 (let ((margin (current-indentation))
8555 list-margin start generic
8556 (generics-list (nth 1 vhdl-port-list)))
8557 (when generics-list
8558 (setq start (point))
8559 (vhdl-insert-keyword "GENERIC MAP (")
8560 (if (not vhdl-association-list-with-formals)
8561 ;; paste list of actual generics
8562 (while generics-list
8563 (insert (or (nth 2 (car generics-list)) " "))
8564 (setq generics-list (cdr generics-list))
8565 (insert (if generics-list ", " ")")))
8566 (unless vhdl-argument-list-indent
d4a5b644 8567 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
5eabfe72
KH
8568 (setq list-margin (current-column))
8569 (while generics-list
8570 (setq generic (car generics-list))
8571 ;; paste formal and actual generic
8572 (insert (car (nth 0 generic)) " => "
8573 (if no-constants
8574 (car (nth 0 generic))
8575 (or (nth 2 generic) "")))
8576 (setq generics-list (cdr generics-list))
8577 (insert (if generics-list "," ")"))
8578 ;; paste comment
8579 (when (and vhdl-include-port-comments (nth 3 generic))
8580 (vhdl-comment-insert-inline (nth 3 generic) t))
8581 (when generics-list (insert "\n") (indent-to list-margin)))
8582 ;; align generic map
8583 (when vhdl-auto-align
8584 (vhdl-align-noindent-region start (point) 1 t))))))
8585
8586(defun vhdl-port-paste-port-map ()
8587 "Paste as a port map."
8588 (let ((margin (current-indentation))
8589 list-margin start port
8590 (ports-list (nth 2 vhdl-port-list)))
8591 (when ports-list
8592 (setq start (point))
8593 (vhdl-insert-keyword "PORT MAP (")
8594 (if (not vhdl-association-list-with-formals)
8595 ;; paste list of actual ports
8596 (while ports-list
8597 (insert (vhdl-replace-string vhdl-actual-port-name
8598 (car (nth 0 (car ports-list)))))
8599 (setq ports-list (cdr ports-list))
8600 (insert (if ports-list ", " ");")))
8601 (unless vhdl-argument-list-indent
d4a5b644 8602 (insert "\n") (indent-to (+ margin (* 2 vhdl-basic-offset))))
5eabfe72
KH
8603 (setq list-margin (current-column))
8604 (while ports-list
8605 (setq port (car ports-list))
8606 ;; paste formal and actual port
8607 (insert (car (nth 0 port)) " => ")
8608 (insert (vhdl-replace-string vhdl-actual-port-name
8609 (car (nth 0 port))))
8610 (setq ports-list (cdr ports-list))
8611 (insert (if ports-list "," ");"))
8612 ;; paste comment
8613 (when (or vhdl-include-direction-comments
8614 (and vhdl-include-port-comments (nth 4 port)))
8615 (vhdl-comment-insert-inline
8616 (concat
8617 (if vhdl-include-direction-comments
8618 (format "%-4s" (or (concat (nth 2 port) " ") "")) "")
8619 (if vhdl-include-port-comments (nth 4 port) "")) t))
8620 (when ports-list (insert "\n") (indent-to list-margin)))
8621 ;; align port clause
8622 (when vhdl-auto-align
8623 (vhdl-align-noindent-region start (point) 1))))))
8624
8625(defun vhdl-port-paste-instance (&optional name)
8626 "Paste as an instantiation."
8627 (interactive)
8628 (if (not vhdl-port-list)
8629 (error "No port read")
8630 (let ((orig-vhdl-port-list vhdl-port-list))
8631 ;; flatten local copy of port list (must be flat for port mapping)
8632 (vhdl-port-flatten)
8633 (vhdl-indent-line)
8634 (let ((margin (current-indentation))
8635 list-margin start generic port
8636 (generics-list (nth 1 vhdl-port-list))
8637 (ports-list (nth 2 vhdl-port-list)))
8638 ;; paste instantiation
8639 (if name
8640 (insert name ": ")
8641 (if (equal (cdr vhdl-instance-name) "")
8642 (vhdl-template-field "instance name" ": ")
8643 (insert (vhdl-replace-string vhdl-instance-name
8644 (nth 0 vhdl-port-list)) ": ")))
8645 (message "Pasting port as instantiation...")
8646 (if (vhdl-standard-p '87)
8647 (insert (nth 0 vhdl-port-list))
8648 (vhdl-insert-keyword "ENTITY ")
8649 (insert "work." (nth 0 vhdl-port-list)))
8650 (when (nth 1 vhdl-port-list)
8651 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8652 (vhdl-port-paste-generic-map t t))
8653 (when (nth 2 vhdl-port-list)
8654 (insert "\n") (indent-to (+ margin vhdl-basic-offset))
8655 (vhdl-port-paste-port-map))
8656 (message "Pasting port as instantiation...done"))
8657 (setq vhdl-port-list orig-vhdl-port-list))))
8658
8659(defun vhdl-port-paste-signals (&optional initialize)
8660 "Paste ports as internal signals."
8661 (interactive)
8662 (if (not vhdl-port-list)
8663 (error "No port read")
8664 (message "Pasting port as signals...")
8665 (vhdl-indent-line)
8666 (let ((margin (current-indentation))
8667 start port names
8668 (ports-list (nth 2 vhdl-port-list)))
8669 (when ports-list
8670 (setq start (point))
8671 (while ports-list
8672 (setq port (car ports-list))
8673 ;; paste object
8674 (if (nth 1 port)
8675 (insert (nth 1 port) " ")
8676 (vhdl-insert-keyword "SIGNAL "))
8677 ;; paste actual port signals
8678 (setq names (nth 0 port))
8679 (while names
8680 (insert (vhdl-replace-string vhdl-actual-port-name (car names)))
8681 (setq names (cdr names))
8682 (when names (insert ", ")))
8683 ;; paste type
8684 (insert " : " (nth 3 port))
8685 ;; paste initialization (inputs only)
8686 (when (and initialize (equal "in" (nth 2 port)))
8687 (insert
8688 " := "
8689 (if (string-match "(.+)" (nth 3 port)) "(others => '0')" "'0'")))
8690 (insert ";")
8691 ;; paste comment
8692 (when (and vhdl-include-port-comments (nth 4 port))
8693 (vhdl-comment-insert-inline (nth 4 port) t))
8694 (setq ports-list (cdr ports-list))
8695 (when ports-list (insert "\n") (indent-to margin)))
8696 ;; align signal list
8697 (when vhdl-auto-align (vhdl-align-noindent-region start (point) 1))))
8698 (message "Pasting port as signals...done")))
8699
8700(defun vhdl-port-paste-constants ()
8701 "Paste generics as constants."
8702 (interactive)
8703 (if (not vhdl-port-list)
8704 (error "No port read")
8705 (let ((orig-vhdl-port-list vhdl-port-list))
8706 (message "Pasting port as constants...")
8707 ;; flatten local copy of port list (must be flat for constant initial.)
8708 (vhdl-port-flatten)
8709 (vhdl-indent-line)
8710 (let ((margin (current-indentation))
8711 start generic name
8712 (generics-list (nth 1 vhdl-port-list)))
8713 (when generics-list
8714 (setq start (point))
8715 (while generics-list
8716 (setq generic (car generics-list))
8717 (vhdl-insert-keyword "CONSTANT ")
8718 ;; paste generic constants
8719 (setq name (nth 0 generic))
8720 (when name
8721 (insert (car name))
8722 ;; paste type
8723 (insert " : " (nth 1 generic))
8724 ;; paste initialization
8725 (when (nth 2 generic)
8726 (insert " := " (nth 2 generic)))
8727 (insert ";")
8728 ;; paste comment
8729 (when (and vhdl-include-port-comments (nth 3 generic))
8730 (vhdl-comment-insert-inline (nth 3 generic) t))
8731 (setq generics-list (cdr generics-list))
8732 (when generics-list (insert "\n") (indent-to margin))))
8733 ;; align signal list
8734 (when vhdl-auto-align
8735 (vhdl-align-noindent-region start (point) 1))))
8736 (message "Pasting port as constants...done")
8737 (setq vhdl-port-list orig-vhdl-port-list))))
8738
8739(defun vhdl-port-paste-testbench ()
8740 "Paste as a bare-bones test bench."
8741 (interactive)
8742 (if (not vhdl-port-list)
8743 (error "No port read")
8744 (message "Pasting port as test bench...")
8745 (let ((case-fold-search t)
8746 (ent-name (vhdl-replace-string vhdl-testbench-entity-name
8747 (nth 0 vhdl-port-list)))
8748 (source-buffer (current-buffer))
8749 arch-name ent-file-name arch-file-name no-entity position)
8750 ;; open entity file
8751 (when (not (eq vhdl-testbench-create-files 'none))
8752 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8753 (setq ent-file-name
8754 (concat ent-name
8755 (substring (buffer-file-name (current-buffer))
8756 (match-beginning 0))))
8757 (when (file-exists-p ent-file-name)
8758 (if (y-or-n-p
8759 (concat "File `" ent-file-name "' exists; overwrite? "))
8760 (progn (delete-file ent-file-name)
8761 (when (get-file-buffer ent-file-name)
8762 (set-buffer ent-file-name)
8763 (set-buffer-modified-p nil)
8764 (kill-buffer ent-file-name)))
8765 (if (eq vhdl-testbench-create-files 'separate)
8766 (setq no-entity t)
8767 (error "Pasting port as test bench...aborted"))))
8768 (unless no-entity
8769 (set-buffer source-buffer)
8770 (find-file ent-file-name)))
8771 (let ((margin 0))
8772 (unless (and (eq vhdl-testbench-create-files 'separate) no-entity)
8773 ;; paste entity header
8774 (unless (equal "" vhdl-testbench-entity-header)
8775 (vhdl-insert-string-or-file vhdl-testbench-entity-header))
8776 (vhdl-comment-display-line) (insert "\n\n") (indent-to margin)
8777 ;; paste std_logic_1164 package
8778 (vhdl-insert-keyword "LIBRARY ")
8779 (insert "ieee;\n") (indent-to margin)
8780 (vhdl-insert-keyword "USE ")
8781 (insert "ieee.std_logic_1164.")
8782 (vhdl-insert-keyword "ALL;")
8783 (insert "\n\n") (indent-to margin) (vhdl-comment-display-line)
8784 (insert "\n\n") (indent-to margin)
8785 ;; paste entity declaration
8786 (vhdl-insert-keyword "ENTITY ")
8787 (insert ent-name)
8788 (vhdl-insert-keyword " IS")
8789 (when (memq vhdl-insert-empty-lines '(unit all)) (insert "\n"))
8790 (insert "\n") (indent-to margin)
8791 (vhdl-insert-keyword "END ")
8792 (unless (vhdl-standard-p '87) (vhdl-insert-keyword "ENTITY "))
8793 (insert ent-name ";")
8794 (insert "\n\n") (indent-to margin)
8795 (vhdl-comment-display-line) (insert "\n"))
8796 ;; get architecture name
8797 (setq arch-name
8798 (if (equal (cdr vhdl-testbench-architecture-name) "")
8799 (read-from-minibuffer "architecture name: "
8800 nil vhdl-minibuffer-local-map)
8801 (vhdl-replace-string vhdl-testbench-architecture-name
8802 (nth 0 vhdl-port-list))))
8803 ;; open architecture file
8804 (when (eq vhdl-testbench-create-files 'separate)
8805 (save-buffer)
8806 (string-match "\\.[^.]*\\'" (buffer-file-name (current-buffer)))
8807 (setq arch-file-name
8808 (concat arch-name
8809 (substring (buffer-file-name (current-buffer))
8810 (match-beginning 0))))
8811 (when (file-exists-p arch-file-name)
8812 (if (y-or-n-p
8813 (concat "File `" ent-file-name "' exists; overwrite? "))
8814 (progn (delete-file arch-file-name)
8815 (when (get-file-buffer arch-file-name)
8816 (set-buffer (get-file-buffer arch-file-name))
8817 (set-buffer-modified-p nil)
8818 (kill-buffer arch-file-name)))
8819 (error "Pasting port as test bench...aborted")))
8820 (set-buffer source-buffer)
8821 (find-file arch-file-name)
8822 ;; paste architecture header
8823 (unless (equal "" vhdl-testbench-architecture-header)
8824 (vhdl-insert-string-or-file vhdl-testbench-architecture-header))
8825 (vhdl-comment-display-line)
8826 (insert "\n"))
8827 (insert "\n") (indent-to margin)
8828 ;; paste architecture body
8829 (vhdl-insert-keyword "ARCHITECTURE ")
8830 (insert arch-name)
8831 (vhdl-insert-keyword " OF ")
8832 (insert ent-name)
8833 (vhdl-insert-keyword " IS")
8834 (insert "\n\n") (indent-to margin)
8835 ;; paste component declaration
8836 (when (vhdl-standard-p '87)
8837 (vhdl-port-paste-component)
8838 (insert "\n\n") (indent-to margin))
8839 ;; paste constants
8840 (when (nth 1 vhdl-port-list)
8841 (vhdl-port-paste-constants)
8842 (insert "\n\n") (indent-to margin))
8843 ;; paste internal signals
8844 (vhdl-port-paste-signals vhdl-testbench-initialize-signals)
8845 ;; paste custom declarations
8846 (unless (equal "" vhdl-testbench-declarations)
8847 (insert "\n\n")
8848 (vhdl-insert-string-or-file vhdl-testbench-declarations)
8849 (delete-indentation))
8850 (setq position (point))
8851 (insert "\n\n") (indent-to margin)
8852 (vhdl-comment-display-line) (insert "\n")
8853 (goto-char position)
8854 (vhdl-template-begin-end
8855 (unless (vhdl-standard-p '87) "ARCHITECTURE")
8856 arch-name margin t)
8857 ;; paste instantiation
8858 (vhdl-port-paste-instance
8859 (vhdl-replace-string vhdl-testbench-dut-name
8860 (nth 0 vhdl-port-list)))
8861 (insert "\n")
8862 ;; paste custom statements
8863 (unless (equal "" vhdl-testbench-statements)
8864 (insert "\n")
8865 (vhdl-insert-string-or-file vhdl-testbench-statements))
8866 (insert "\n")
8867 (indent-to (+ margin vhdl-basic-offset))
8868 (when (not (eq vhdl-testbench-create-files 'none))
8869 (save-buffer))
8870 (message "Pasting port as test bench...done")))))
8871
8872
8873;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8874;;; Miscellaneous
8875;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8876
8877;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8878;; Hippie expand customization
8879
8880(defvar vhdl-expand-upper-case nil)
8881
8882(defun vhdl-try-expand-abbrev (old)
8883 "Try expanding abbreviations from `vhdl-abbrev-list'."
8884 (unless old
8885 (he-init-string (he-dabbrev-beg) (point))
8886 (setq he-expand-list
8887 (let ((abbrev-list vhdl-abbrev-list)
8888 (sel-abbrev-list '()))
8889 (while abbrev-list
8890 (when (or (not (stringp (car abbrev-list)))
8891 (string-match
8892 (concat "^" he-search-string) (car abbrev-list)))
8893 (setq sel-abbrev-list
8894 (cons (car abbrev-list) sel-abbrev-list)))
8895 (setq abbrev-list (cdr abbrev-list)))
8896 (nreverse sel-abbrev-list))))
8897 (while (and he-expand-list
8898 (or (not (stringp (car he-expand-list)))
8899 (he-string-member (car he-expand-list) he-tried-table t)))
8900; (equal (car he-expand-list) he-search-string)))
8901 (unless (stringp (car he-expand-list))
8902 (setq vhdl-expand-upper-case (car he-expand-list)))
8903 (setq he-expand-list (cdr he-expand-list)))
8904 (if (null he-expand-list)
8905 (progn (when old (he-reset-string))
8906 nil)
8907 (he-substitute-string
8908 (if vhdl-expand-upper-case
8909 (upcase (car he-expand-list))
8910 (car he-expand-list))
8911 t)
8912 (setq he-expand-list (cdr he-expand-list))
8913 t))
8914
8915(defun vhdl-he-list-beg ()
8916 "Also looks at the word before `(' in order to better match parenthesized
8917expressions (e.g. for index ranges of types and signals)."
8918 (save-excursion
8919 (condition-case ()
8920 (progn (backward-up-list 1)
8921 (skip-syntax-backward "w_")) ; crashes in `viper-mode'
8922 (error ()))
8923 (point)))
8924
8925;; override `he-list-beg' from `hippie-exp'
8926(unless (and (boundp 'viper-mode) viper-mode)
8927 (require 'hippie-exp)
8928 (defalias 'he-list-beg 'vhdl-he-list-beg))
8929
8930;; function for expanding abbrevs and dabbrevs
8931(fset 'vhdl-expand-abbrev (make-hippie-expand-function
8932 '(try-expand-dabbrev
8933 try-expand-dabbrev-all-buffers
8934 vhdl-try-expand-abbrev)))
8935
8936;; function for expanding parenthesis
8937(fset 'vhdl-expand-paren (make-hippie-expand-function
8938 '(try-expand-list
8939 try-expand-list-all-buffers)))
8940
8941;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8942;; Case fixing
d2ddb974
KH
8943
8944(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
8945 "Convert all words matching word-regexp in region to lower or upper case,
8946depending on parameter upper-case."
8947 (let ((case-fold-search t)
8948 (case-replace nil)
5eabfe72
KH
8949 (last-update 0))
8950 (vhdl-ext-syntax-table
8951 (save-excursion
8952 (goto-char end)
8953 (setq end (point-marker))
8954 (goto-char beg)
8955 (while (re-search-forward word-regexp end t)
8956 (or (vhdl-in-comment-p)
8957 (vhdl-in-string-p)
8958 (if upper-case
8959 (upcase-word -1)
8960 (downcase-word -1)))
8961 (when (and count vhdl-progress-interval
8962 (< vhdl-progress-interval
8963 (- (nth 1 (current-time)) last-update)))
8964 (message "Fixing case... (%2d%s)"
8965 (+ (* count 25) (/ (* 25 (- (point) beg)) (- end beg)))
8966 "%")
8967 (setq last-update (nth 1 (current-time)))))
8968 (goto-char end)))
8969 (and count vhdl-progress-interval (message "Fixing case...done"))))
d2ddb974
KH
8970
8971(defun vhdl-fix-case-region (beg end &optional arg)
8972 "Convert all VHDL words in region to lower or upper case, depending on
8973variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
8974 (interactive "r\nP")
8975 (vhdl-fix-case-region-1
5eabfe72 8976 beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
d2ddb974 8977 (vhdl-fix-case-region-1
5eabfe72 8978 beg end vhdl-upper-case-types vhdl-types-regexp 1)
d2ddb974 8979 (vhdl-fix-case-region-1
5eabfe72
KH
8980 beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
8981 (vhdl-fix-case-region-1
8982 beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3))
d2ddb974 8983
5eabfe72
KH
8984(defun vhdl-fix-case-buffer ()
8985 "Convert all VHDL words in buffer to lower or upper case, depending on
8986variables vhdl-upper-case-{keywords,types,attributes,enum-values}."
d2ddb974 8987 (interactive)
5eabfe72
KH
8988 (vhdl-fix-case-region (point-min) (point-max)))
8989
8990;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8991;; Line handling functions
d2ddb974
KH
8992
8993(defun vhdl-current-line ()
8994 "Return the line number of the line containing point."
8995 (save-restriction
8996 (widen)
8997 (save-excursion
8998 (beginning-of-line)
5eabfe72 8999 (1+ (count-lines 1 (point))))))
d2ddb974 9000
5eabfe72 9001(defun vhdl-line-kill-entire (&optional arg)
d2ddb974 9002 "Delete entire line."
5eabfe72
KH
9003 (interactive "p")
9004 (beginning-of-line)
9005 (kill-line (or arg 1)))
9006
9007(defun vhdl-line-kill (&optional arg)
9008 "Kill current line."
9009 (interactive "p")
9010 (vhdl-line-kill-entire arg))
9011
9012(defun vhdl-line-copy (&optional arg)
9013 "Copy current line."
9014 (interactive "p")
9015 (save-excursion
9016 (beginning-of-line)
9017 (let ((position (point)))
9018 (forward-line (or arg 1))
9019 (copy-region-as-kill position (point)))))
9020
9021(defun vhdl-line-yank ()
9022 "Yank entire line."
d2ddb974 9023 (interactive)
5eabfe72
KH
9024 (beginning-of-line)
9025 (yank))
d2ddb974 9026
5eabfe72
KH
9027(defun vhdl-line-expand (&optional prefix-arg)
9028 "Hippie-expand current line."
9029 (interactive "P")
9030 (let ((case-fold-search t) (case-replace nil)
9031 (hippie-expand-try-functions-list
9032 '(try-expand-line try-expand-line-all-buffers)))
9033 (hippie-expand prefix-arg)))
9034
9035(defun vhdl-line-transpose-next (&optional arg)
9036 "Interchange this line with next line."
9037 (interactive "p")
9038 (forward-line 1)
9039 (transpose-lines (or arg 1))
9040 (forward-line -1))
9041
9042(defun vhdl-line-transpose-previous (&optional arg)
9043 "Interchange this line with previous line."
9044 (interactive "p")
9045 (forward-line 1)
9046 (transpose-lines (- 0 (or arg 0)))
9047 (forward-line -1))
9048
9049(defun vhdl-line-open ()
d2ddb974
KH
9050 "Open a new line and indent."
9051 (interactive)
5eabfe72
KH
9052 (end-of-line -0)
9053 (newline-and-indent))
d2ddb974 9054
d2ddb974 9055
5eabfe72
KH
9056;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9057;;; Project
9058;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974 9059
5eabfe72
KH
9060(defun vhdl-project-switch (name)
9061 "Switch to project NAME."
9062 (setq vhdl-project name)
9063 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame))
9064 (speedbar-refresh)))
9065
9066
9067;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9068;;; Compilation
9069;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9070;; (using `compile.el')
d2ddb974 9071
5eabfe72
KH
9072(defun vhdl-compile-init ()
9073 "Initialize for compilation."
9074 (unless compilation-error-regexp-alist
9075 (setq compilation-error-regexp-alist
9076 (let ((commands-alist vhdl-compiler-alist)
9077 regexp-alist sublist)
9078 (while commands-alist
9079 (setq sublist (nth 5 (car commands-alist)))
9080 (unless (equal "" (car sublist))
9081 (setq regexp-alist
9082 (cons (list (nth 0 sublist)
9083 (if (= 0 (nth 1 sublist))
9084 (if (string-match
9085 "XEmacs" emacs-version) 9 nil)
9086 (nth 1 sublist))
9087 (nth 2 sublist))
9088 regexp-alist)))
9089 (setq commands-alist (cdr commands-alist)))
9090 regexp-alist)))
9091 (unless compilation-file-regexp-alist
9092 (setq compilation-file-regexp-alist
9093 (let ((commands-alist vhdl-compiler-alist)
9094 regexp-alist)
9095 (while commands-alist
9096 (unless (equal "" (car (nth 6 (car commands-alist))))
9097 (setq regexp-alist
9098 (append regexp-alist
9099 (list (nth 6 (car commands-alist))))))
9100 (setq commands-alist (cdr commands-alist)))
9101 regexp-alist))))
9102
9103(defun vhdl-compile ()
9104 "Compile current buffer using the VHDL compiler specified in
9105`vhdl-compiler'."
d2ddb974 9106 (interactive)
5eabfe72
KH
9107 (vhdl-compile-init)
9108 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9109 (command (nth 1 command-elem))
9110 (default-directory (expand-file-name (nth 4 command-elem))))
9111 (when command
9112 (compile (concat command " " vhdl-compiler-options
9113 (unless (string-equal vhdl-compiler-options "") " ")
9114 (buffer-file-name))))))
d2ddb974 9115
5eabfe72
KH
9116(defun vhdl-make ()
9117 "Call make command for compilation of all updated source files (requires
9118`Makefile')."
d2ddb974 9119 (interactive)
5eabfe72
KH
9120 (vhdl-compile-init)
9121 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9122 (command (nth 2 command-elem))
9123 (default-directory (expand-file-name (nth 4 command-elem))))
9124 (if (equal command "")
9125 (compile "make")
9126 (compile command))))
d2ddb974 9127
5eabfe72
KH
9128(defun vhdl-generate-makefile ()
9129 "Generate new `Makefile'."
9130 (interactive)
9131 (vhdl-compile-init)
9132 (let* ((command-elem (assoc vhdl-compiler vhdl-compiler-alist))
9133 (command (nth 3 command-elem))
9134 (default-directory (expand-file-name (nth 4 command-elem))))
9135 (if (not (equal command ""))
9136 (compile command)
9137 (error "No such command specified for `%s'" vhdl-compiler))))
9138
9139
9140;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9141;;; Hideshow
9142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9143;; (using `hideshow.el')
d2ddb974 9144
5eabfe72
KH
9145(defun vhdl-forward-unit (&optional count)
9146 "Find begin and end of VHDL design units (for hideshow)."
9147 (interactive "p")
9148 (let ((case-fold-search t))
9149 (if (< count 0)
9150 (re-search-backward
9151 "^\\(architecture\\|configuration\\|entity\\|package\\)\\>" nil t)
9152 (re-search-forward "^end\\>" nil t))))
d2ddb974 9153
5eabfe72
KH
9154(when (string-match "XEmacs" emacs-version)
9155 (require 'hideshow))
d2ddb974 9156
5eabfe72
KH
9157(unless (assq 'vhdl-mode hs-special-modes-alist)
9158 (setq hs-special-modes-alist
9159 (cons
9160 '(vhdl-mode
9161 "\\(^\\)\\(architecture\\|ARCHITECTURE\\|configuration\\|CONFIGURATION\\|entity\\|ENTITY\\|package\\|PACKAGE\\)\\>"
9162 "\\(^\\)\\(end\\|END\\)\\>"
9163 "--\\( \\|$\\)"
9164 vhdl-forward-unit)
9165 hs-special-modes-alist)))
9166
9167(defun vhdl-hideshow-init ()
9168 "Initialize `hideshow'."
9169 (if vhdl-hide-all-init
9170 (add-hook 'hs-minor-mode-hook 'hs-hide-all)
9171 (remove-hook 'hs-minor-mode-hook 'hs-hide-all))
9172 (if vhdl-hideshow-menu
9173 (hs-minor-mode 1)
9174 (when (boundp 'hs-minor-mode) (hs-minor-mode 0))))
9175
9176
9177;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9178;;; Font locking
9179;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
9180;; (using `font-lock.el')
9181
5eabfe72
KH
9182;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9183;; Help functions for translate-off region highlighting
9184
9185(defun vhdl-within-translate-off ()
9186 "Return point if within translate-off region, else nil."
9187 (and (save-excursion
9188 (re-search-backward
9189 "^\\s-*--\\s-*pragma\\s-*translate_\\(on\\|off\\)\\s-*\n" nil t))
9190 (equal "off" (match-string 1))
9191 (point)))
9192
9193(defun vhdl-start-translate-off (limit)
9194 "Return point before translate-off pragma if before LIMIT, else nil."
9195 (when (re-search-forward
9196 "^\\s-*--\\s-*pragma\\s-*translate_off\\s-*\n" limit t)
9197 (match-beginning 0)))
9198
9199(defun vhdl-end-translate-off (limit)
9200 "Return point after translate-on pragma if before LIMIT, else nil."
9201 (re-search-forward "^\\s-*--\\s-*pragma\\s-*translate_on\\s-*\n" limit t))
9202
9203(defun vhdl-match-translate-off (limit)
9204 "Match a translate-off block, setting match-data and returning t, else nil."
9205 (when (< (point) limit)
9206 (let ((start (or (vhdl-within-translate-off)
9207 (vhdl-start-translate-off limit)))
9208 (case-fold-search t))
9209 (when start
9210 (let ((end (or (vhdl-end-translate-off limit) limit)))
9211 (set-match-data (list start end))
9212 (goto-char end))))))
9213
9214(defun vhdl-font-lock-match-item (limit)
9215 "Match, and move over, any declaration item after point. Adapted from
9216`font-lock-match-c-style-declaration-item-and-skip-to-next'."
9217 (condition-case nil
9218 (save-restriction
9219 (narrow-to-region (point-min) limit)
9220 ;; match item
9221 (when (looking-at "\\s-*\\(\\w+\\)")
9222 (save-match-data
9223 (goto-char (match-end 1))
9224 ;; move to next item
9225 (if (looking-at "\\(\\s-*,\\)")
9226 (goto-char (match-end 1))
9227 (end-of-line) t))))
9228 (error t)))
9229
9230;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
9231;; Syntax definitions
9232
5eabfe72
KH
9233(defconst vhdl-font-lock-syntactic-keywords
9234 '(("\\(\'\\).\\(\'\\)" (1 (7 . ?\')) (2 (7 . ?\'))))
9235 "Mark single quotes as having string quote syntax in 'c' instances.")
9236
d2ddb974
KH
9237(defvar vhdl-font-lock-keywords nil
9238 "Regular expressions to highlight in VHDL Mode.")
9239
9240(defconst vhdl-font-lock-keywords-0
5eabfe72
KH
9241 (list
9242 ;; highlight template prompts
9243 (list (concat "\\(<" vhdl-template-prompt-syntax ">\\)")
9244 1 'vhdl-font-lock-prompt-face t)
d2ddb974 9245
5eabfe72
KH
9246 ;; highlight directives
9247 '("--\\s-*pragma\\s-+\\(.*\\)$" 1 vhdl-font-lock-directive-face t)
9248 )
d2ddb974 9249 "For consideration as a value of `vhdl-font-lock-keywords'.
5eabfe72 9250This does highlighting of template prompts and directives (pragmas).")
d2ddb974 9251
5eabfe72
KH
9252(defvar vhdl-font-lock-keywords-1 nil
9253 ;; set in `vhdl-font-lock-init' because dependent on custom variables
9254 "For consideration as a value of `vhdl-font-lock-keywords'.
9255This does highlighting of keywords and standard identifiers.")
9256
9257(defconst vhdl-font-lock-keywords-2
d2ddb974
KH
9258 (list
9259 ;; highlight names of units, subprograms, and components when declared
9260 (list
9261 (concat
9262 "^\\s-*\\("
9263 "architecture\\|configuration\\|entity\\|package\\(\\s-+body\\|\\)\\|"
5eabfe72 9264 "\\(\\(impure\\|pure\\)\\s-+\\|\\)function\\|procedure\\|component"
d2ddb974 9265 "\\)\\s-+\\(\\w+\\)")
5eabfe72
KH
9266 5 'font-lock-function-name-face)
9267
9268 ;; highlight entity names of architectures and configurations
9269 (list
9270 "^\\s-*\\(architecture\\|configuration\\)\\s-+\\w+\\s-+of\\s-+\\(\\w+\\)"
9271 2 'font-lock-function-name-face)
d2ddb974
KH
9272
9273 ;; highlight labels of common constructs
9274 (list
9275 (concat
5eabfe72
KH
9276 "^\\s-*\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(\\("
9277 "assert\\|block\\|case\\|component\\|configuration\\|entity\\|exit\\|"
9278 "for\\|if\\|loop\\|next\\|null\\|postponed\\|process\\|"
9279 (when (vhdl-standard-p 'ams) "procedural\\|")
9280 "with\\|while"
9281 "\\)\\>\\|[^\n]*<=\\)")
d2ddb974
KH
9282 1 'font-lock-function-name-face)
9283
5eabfe72 9284 ;; highlight label and component name of component instantiations
d2ddb974 9285 (list
5eabfe72
KH
9286 (concat
9287 "^\\s-*\\(\\w+\\)\\s-*:[ \t\n]*\\(component\\s-+\\|\\)\\(\\w+\\)"
9288 "\\(\\s-\\|\n\\)+\\(generic\\|port\\)\\s-+map\\>")
9289 '(1 font-lock-function-name-face) '(3 font-lock-function-name-face))
d2ddb974
KH
9290
9291 ;; highlight names and labels at end of constructs
9292 (list
9293 (concat
5eabfe72
KH
9294 "^\\s-*end\\s-+\\(\\("
9295 "architecture\\|block\\|case\\|component\\|configuration\\|entity\\|"
9296 "for\\|function\\|generate\\|if\\|loop\\|package\\(\\s-+body\\|\\)\\|"
9297 "procedure\\|\\(postponed\\s-+\\|\\)process\\|"
9298 (when (vhdl-standard-p 'ams) "procedural\\|")
9299 "units"
9300 "\\)\\>\\|\\)\\s-*\\(\\w*\\)")
9301 5 'font-lock-function-name-face)
9302
9303 ;; highlight labels in exit and next statements
9304 (list
9305 (concat
9306 "^\\s-*\\(\\w+\\s-*:\\s-*\\)?\\(exit\\|next\\)\\s-+\\(\\w*\\)")
9307 3 'font-lock-function-name-face)
9308
9309 ;; highlight entity name in attribute specifications
9310 (list
9311 (concat
9312 "^\\s-*attribute\\s-+\\w+\\s-+of\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:")
9313 1 'font-lock-function-name-face)
9314
9315 ;; highlight labels in component specifications
9316 (list
9317 (concat
9318 "^\\s-*for\\s-+\\(\\w+\\(,\\s-*\\w+\\)*\\)\\s-*:"
9319 "\\(\\s-\\|\n\\)*\\(\\w+\\)")
9320 '(1 font-lock-function-name-face) '(4 font-lock-function-name-face))
9321
9322 ;; highlight attribute name in attribute declarations/specifications
9323 (list
9324 (concat
9325 "^\\s-*attribute\\s-+\\(\\w+\\)")
9326 1 'vhdl-font-lock-attribute-face)
9327
9328 ;; highlight type/nature name in (sub)type/(sub)nature declarations
9329 (list
9330 (concat
9331 "^\\s-*\\(sub\\|\\)\\(nature\\|type\\)\\s-+\\(\\w+\\)")
9332 3 'font-lock-type-face)
9333
9334 ;; highlight signal/variable/constant declaration names
9335 (list "\\(:[^=]\\)"
9336 '(vhdl-font-lock-match-item
9337 (progn (goto-char (match-beginning 1))
9338 (skip-syntax-backward " ")
9339 (skip-syntax-backward "w_")
9340 (skip-syntax-backward " ")
9341 (while (= (preceding-char) ?,)
9342 (backward-char 1)
9343 (skip-syntax-backward " ")
9344 (skip-syntax-backward "w_")
9345 (skip-syntax-backward " ")))
9346; (skip-chars-backward "^-(\n\";")
9347 (goto-char (match-end 1)) (1 font-lock-variable-name-face)))
9348
9349 ;; highlight alias/group declaration names and for-loop/-generate variables
9350 (list "\\<\\(alias\\|for\\|group\\)\\s-+\\w+\\s-+\\(in\\|is\\)\\>"
9351 '(vhdl-font-lock-match-item
9352 (progn (goto-char (match-end 1)) (match-beginning 2))
9353 nil (1 font-lock-variable-name-face)))
d2ddb974 9354 )
5eabfe72
KH
9355 "For consideration as a value of `vhdl-font-lock-keywords'.
9356This does context sensitive highlighting of names and labels.")
d2ddb974 9357
5eabfe72
KH
9358(defvar vhdl-font-lock-keywords-3 nil
9359 ;; set in `vhdl-font-lock-init' because dependent on custom variables
d2ddb974 9360 "For consideration as a value of `vhdl-font-lock-keywords'.
5eabfe72
KH
9361This does highlighting of words with special syntax.")
9362
9363(defvar vhdl-font-lock-keywords-4 nil
9364 ;; set in `vhdl-font-lock-init' because dependent on custom variables
d2ddb974 9365 "For consideration as a value of `vhdl-font-lock-keywords'.
5eabfe72 9366This does highlighting of additional reserved words.")
d2ddb974 9367
5eabfe72
KH
9368(defconst vhdl-font-lock-keywords-5
9369 ;; background highlight translate-off regions
9370 '((vhdl-match-translate-off (0 vhdl-font-lock-translate-off-face append)))
9371 "For consideration as a value of `vhdl-font-lock-keywords'.
9372This does background highlighting of translate-off regions.")
9373
9374;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
9375;; Font and color definitions
9376
5eabfe72 9377(defvar vhdl-font-lock-prompt-face 'vhdl-font-lock-prompt-face
d2ddb974
KH
9378 "Face name to use for prompts.")
9379
5eabfe72
KH
9380(defvar vhdl-font-lock-attribute-face 'vhdl-font-lock-attribute-face
9381 "Face name to use for standardized attributes.")
9382
9383(defvar vhdl-font-lock-enumvalue-face 'vhdl-font-lock-enumvalue-face
9384 "Face name to use for standardized enumeration values.")
d2ddb974 9385
5eabfe72
KH
9386(defvar vhdl-font-lock-function-face 'vhdl-font-lock-function-face
9387 "Face name to use for standardized functions and packages.")
d2ddb974 9388
5eabfe72
KH
9389(defvar vhdl-font-lock-directive-face 'vhdl-font-lock-directive-face
9390 "Face name to use for directives.")
d2ddb974 9391
5eabfe72
KH
9392(defvar vhdl-font-lock-reserved-words-face 'vhdl-font-lock-reserved-words-face
9393 "Face name to use for additional reserved words.")
d2ddb974 9394
5eabfe72
KH
9395(defvar vhdl-font-lock-translate-off-face 'vhdl-font-lock-translate-off-face
9396 "Face name to use for translate-off regions.")
d2ddb974 9397
5eabfe72
KH
9398;; face names to use for words with special syntax.
9399(let ((syntax-alist vhdl-special-syntax-alist)
9400 name)
9401 (while syntax-alist
9402 (setq name (vhdl-function-name
9403 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
d4a5b644
GM
9404 (eval `(defvar ,name ',name
9405 ,(concat "Face name to use for "
9406 (nth 0 (car syntax-alist)) ".")))
5eabfe72
KH
9407 (setq syntax-alist (cdr syntax-alist))))
9408
a152344b
MR
9409;; add faces used from `font-lock'.
9410(defgroup vhdl-highlight-faces
9411 '((font-lock-comment-face custom-face)
9412 (font-lock-string-face custom-face)
9413 (font-lock-keyword-face custom-face)
9414 (font-lock-type-face custom-face)
9415 (font-lock-function-name-face custom-face)
9416 (font-lock-variable-name-face custom-face))
5eabfe72
KH
9417 "Faces for highlighting."
9418 :group 'vhdl-highlight)
d2ddb974 9419
d2ddb974 9420(defface vhdl-font-lock-prompt-face
58b64ac7
RS
9421 '((((class color) (background light)) (:foreground "Red" :weight bold))
9422 (((class color) (background dark)) (:foreground "Pink" :weight bold))
d2ddb974 9423 (t (:inverse-video t)))
5eabfe72
KH
9424 "Font lock mode face used to highlight prompts."
9425 :group 'vhdl-highlight-faces
d2ddb974
KH
9426 :group 'font-lock-highlighting-faces)
9427
9428(defface vhdl-font-lock-attribute-face
5eabfe72
KH
9429 '((((class color) (background light)) (:foreground "Orchid"))
9430 (((class color) (background dark)) (:foreground "LightSteelBlue"))
58b64ac7 9431 (t (:slant italic :weight bold)))
5eabfe72
KH
9432 "Font lock mode face used to highlight standardized attributes."
9433 :group 'vhdl-highlight-faces
d2ddb974
KH
9434 :group 'font-lock-highlighting-faces)
9435
5eabfe72
KH
9436(defface vhdl-font-lock-enumvalue-face
9437 '((((class color) (background light)) (:foreground "Gold4"))
9438 (((class color) (background dark)) (:foreground "BurlyWood"))
58b64ac7 9439 (t (:slant italic :weight bold)))
5eabfe72
KH
9440 "Font lock mode face used to highlight standardized enumeration values."
9441 :group 'vhdl-highlight-faces
d2ddb974
KH
9442 :group 'font-lock-highlighting-faces)
9443
5eabfe72
KH
9444(defface vhdl-font-lock-function-face
9445 '((((class color) (background light)) (:foreground "Orchid4"))
9446 (((class color) (background dark)) (:foreground "Orchid1"))
58b64ac7 9447 (t (:slant italic :weight bold)))
5eabfe72
KH
9448 "Font lock mode face used to highlight standardized functions and packages."
9449 :group 'vhdl-highlight-faces
d2ddb974
KH
9450 :group 'font-lock-highlighting-faces)
9451
5eabfe72
KH
9452(defface vhdl-font-lock-directive-face
9453 '((((class color) (background light)) (:foreground "CadetBlue"))
9454 (((class color) (background dark)) (:foreground "Aquamarine"))
58b64ac7 9455 (t (:slant italic :weight bold)))
5eabfe72
KH
9456 "Font lock mode face used to highlight directives."
9457 :group 'vhdl-highlight-faces
d2ddb974
KH
9458 :group 'font-lock-highlighting-faces)
9459
5eabfe72 9460(defface vhdl-font-lock-reserved-words-face
58b64ac7
RS
9461 '((((class color) (background light)) (:foreground "Orange" :weight bold))
9462 (((class color) (background dark)) (:foreground "Yellow" :weight bold))
d2ddb974 9463 (t ()))
5eabfe72
KH
9464 "Font lock mode face used to highlight additional reserved words."
9465 :group 'vhdl-highlight-faces
d2ddb974
KH
9466 :group 'font-lock-highlighting-faces)
9467
5eabfe72
KH
9468(defface vhdl-font-lock-translate-off-face
9469 '((((class color) (background light)) (:background "LightGray"))
9470 (((class color) (background dark)) (:background "DimGray"))
d2ddb974 9471 (t ()))
5eabfe72
KH
9472 "Font lock mode face used to background highlight translate-off regions."
9473 :group 'vhdl-highlight-faces
d2ddb974
KH
9474 :group 'font-lock-highlighting-faces)
9475
5eabfe72
KH
9476;; font lock mode faces used to highlight words with special syntax.
9477(let ((syntax-alist vhdl-special-syntax-alist))
9478 (while syntax-alist
d4a5b644
GM
9479 (eval `(defface ,(vhdl-function-name
9480 "vhdl-font-lock" (car (car syntax-alist)) "face")
9481 '((((class color) (background light))
9482 (:foreground ,(nth 2 (car syntax-alist))))
9483 (((class color) (background dark))
9484 (:foreground ,(nth 3 (car syntax-alist))))
9485 (t ()))
9486 ,(concat "Font lock mode face used to highlight "
9487 (nth 0 (car syntax-alist)) ".")
9488 :group 'vhdl-highlight-faces
9489 :group 'font-lock-highlighting-faces))
5eabfe72
KH
9490 (setq syntax-alist (cdr syntax-alist))))
9491
9492;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
9493;; Font lock initialization
9494
9495(defun vhdl-font-lock-init ()
5eabfe72
KH
9496 "Initialize fontification."
9497 ;; highlight keywords and standardized types, attributes, enumeration
9498 ;; values, and subprograms
9499 (setq vhdl-font-lock-keywords-1
9500 (list
9501 (list (concat "'" vhdl-attributes-regexp)
9502 1 'vhdl-font-lock-attribute-face)
9503 (list vhdl-types-regexp 1 'font-lock-type-face)
9504 (list vhdl-functions-regexp 1 'vhdl-font-lock-function-face)
9505 (list vhdl-packages-regexp 1 'vhdl-font-lock-function-face)
9506 (list vhdl-enum-values-regexp 1 'vhdl-font-lock-enumvalue-face)
9507 (list vhdl-keywords-regexp 1 'font-lock-keyword-face)))
9508 ;; highlight words with special syntax.
9509 (setq vhdl-font-lock-keywords-3
9510 (let ((syntax-alist vhdl-special-syntax-alist)
9511 keywords)
9512 (while syntax-alist
9513 (setq keywords
9514 (cons
9515 (cons (concat "\\<\\(" (nth 1 (car syntax-alist)) "\\)\\>")
9516 (vhdl-function-name
9517 "vhdl-font-lock" (nth 0 (car syntax-alist)) "face"))
9518 keywords))
9519 (setq syntax-alist (cdr syntax-alist)))
9520 keywords))
9521 ;; highlight additional reserved words
9522 (setq vhdl-font-lock-keywords-4
9523 (list (list vhdl-reserved-words-regexp 1
9524 'vhdl-font-lock-reserved-words-face)))
9525 ;; highlight everything together
d2ddb974 9526 (setq vhdl-font-lock-keywords
5eabfe72
KH
9527 (append
9528 vhdl-font-lock-keywords-0
9529 (when vhdl-highlight-keywords vhdl-font-lock-keywords-1)
9530 (when (or vhdl-highlight-forbidden-words
9531 vhdl-highlight-verilog-keywords) vhdl-font-lock-keywords-4)
9532 (when vhdl-highlight-special-words vhdl-font-lock-keywords-3)
9533 (when vhdl-highlight-names vhdl-font-lock-keywords-2)
9534 (when vhdl-highlight-translate-off vhdl-font-lock-keywords-5))))
9535
9536;; initialize fontification for VHDL Mode
9537(vhdl-font-lock-init)
9538
9539(defun vhdl-fontify-buffer ()
9540 "Re-initialize fontification and fontify buffer."
9541 (interactive)
9542 (setq font-lock-defaults
9543 (list
9544 'vhdl-font-lock-keywords nil
9545 (not vhdl-highlight-case-sensitive) '((?\_ . "w")) 'beginning-of-line
9546 '(font-lock-syntactic-keywords . vhdl-font-lock-syntactic-keywords)))
9547 (when (fboundp 'font-lock-unset-defaults)
9548 (font-lock-unset-defaults)) ; not implemented in XEmacs
9549 (font-lock-set-defaults)
9550 (font-lock-fontify-buffer))
9551
9552;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9553;; Initialization for postscript printing
9554
9555(defun vhdl-ps-print-settings ()
9556 "Initialize custom face and page settings for postscript printing."
9557 ;; define custom face settings
9558 (unless (or (not vhdl-print-customize-faces)
d2ddb974
KH
9559 ps-print-color-p)
9560 (set (make-local-variable 'ps-bold-faces)
9561 '(font-lock-keyword-face
9562 font-lock-type-face
9563 vhdl-font-lock-attribute-face
5eabfe72
KH
9564 vhdl-font-lock-enumvalue-face
9565 vhdl-font-lock-directive-face))
d2ddb974
KH
9566 (set (make-local-variable 'ps-italic-faces)
9567 '(font-lock-comment-face
9568 font-lock-function-name-face
9569 font-lock-type-face
d2ddb974 9570 vhdl-font-lock-attribute-face
5eabfe72
KH
9571 vhdl-font-lock-enumvalue-face
9572 vhdl-font-lock-directive-face))
d2ddb974
KH
9573 (set (make-local-variable 'ps-underlined-faces)
9574 '(font-lock-string-face))
5eabfe72 9575 (setq ps-always-build-face-reference t))
d2ddb974
KH
9576 ;; define page settings, so that a line containing 79 characters (default)
9577 ;; fits into one column
5eabfe72
KH
9578 (when vhdl-print-two-column
9579 (set (make-local-variable 'ps-landscape-mode) t)
9580 (set (make-local-variable 'ps-number-of-columns) 2)
9581 (set (make-local-variable 'ps-font-size) 7.0)
9582 (set (make-local-variable 'ps-header-title-font-size) 10.0)
9583 (set (make-local-variable 'ps-header-font-size) 9.0)
9584 (set (make-local-variable 'ps-header-offset) 12.0)
9585 (when (eq ps-paper-type 'letter)
9586 (set (make-local-variable 'ps-inter-column) 40.0)
9587 (set (make-local-variable 'ps-left-margin) 40.0)
9588 (set (make-local-variable 'ps-right-margin) 40.0))))
9589
9590(defun vhdl-ps-print-init ()
9591 "Initialize postscript printing."
9592 (if (string-match "XEmacs" emacs-version)
9593 (vhdl-ps-print-settings)
9594 (make-local-variable 'ps-print-hook)
9595 (add-hook 'ps-print-hook 'vhdl-ps-print-settings)))
9596
9597
9598;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9599;;; Hierarchy browser (using `speedbar.el')
9600;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9601;; Allows displaying the hierarchy of all VHDL design units contained in a
9602;; directory by using the speedbar.
9603
9604;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9605;; Variables
9606
9607(defvar vhdl-entity-alist nil
9608 "Cache with entities and corresponding architectures and configurations for
9609each visited directory.")
9610;; structure: (parenthesised expression means list of such entries)
9611;; (directory-name
9612;; (ent-name ent-file ent-line
9613;; (arch-name arch-file arch-line
9614;; (inst-name inst-file inst-line inst-ent-name inst-arch-name))
9615;; (conf-name conf-file conf-line))
9616
9617(defvar vhdl-package-alist nil
9618 "Cache with packages for each visited directory.")
9619;; structure: (parenthesised expression means list of such entries)
9620;; (directory-name
9621;; (pack-name pack-file pack-line pack-body-file pack-body-line))
9622
9623(defvar vhdl-ent-inst-alist nil
9624 "Cache with instantiated entities for each visited directory.")
9625;; structure: (parenthesised expression means list of such entries)
9626;; (directory-name (inst-ent-name))
9627
9628(defvar vhdl-project-entity-alist nil
9629 "Cache with entities and corresponding architectures and configurations for
9630each visited project.")
9631;; same structure as `vhdl-entity-alist'
9632
9633(defvar vhdl-project-package-alist nil
9634 "Cache with packages for each visited directory.")
9635;; same structure as `vhdl-package-alist'
9636
9637(defvar vhdl-project-ent-inst-list nil
9638 "Cache with instantiated entities for each visited directory.")
9639;; same structure as `vhdl-ent-inst-alist'
9640
9641(defvar vhdl-speedbar-shown-units-alist nil
9642 "Alist of design units simultaneously open in the current speedbar for each
9643directory and project.")
9644
9645(defvar vhdl-speedbar-last-file-name nil
9646 "Last file for which design units were highlighted.")
9647
9648(defvar vhdl-file-alist nil
9649 "Cache with design units in each file.")
9650;; structure (parenthesised expression means list of such entries)
9651;; (file-name (ent-list) (arch-list) (conf-list) (pack-list) (inst-list))
9652
9653;; help function
9654(defsubst vhdl-speedbar-project-p ()
9655 "Return non-nil if a project is displayed, i.e. directories or files are
9656specified."
9657 (nth 1 (aget vhdl-project-alist vhdl-project)))
9658
9659;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9660;; Scan functions
9661
9662(defun vhdl-scan-file-contents (name &optional num-string)
9663 "Scan contents of VHDL files in FILE-LIST."
9664 (string-match "\\(.*/\\)\\(.*\\)" name)
9665; (unless (file-directory-p (match-string 1 name))
9666; (message "No such directory: \"%s\"" (match-string 1 name)))
9667 (let* ((is-directory (= (match-beginning 2) (match-end 2)))
9668 (file-list
9669 (if is-directory
9670 (nreverse (vhdl-get-source-files t name))
9671 (vhdl-directory-files (match-string 1 name) t
9672 (wildcard-to-regexp (match-string 2 name)))))
9673 (case-fold-search t)
9674 (source-buffer (current-buffer))
9675 ent-alist pack-alist ent-inst-list no-files)
9676 (when (and (not is-directory) (null file-list))
9677 (message "No such file: \"%s\"" name))
9678 (save-excursion
9679 (when file-list
9680 (setq no-files (length file-list))
9681 ;; do for all files
9682 (while file-list
9683 (message "Scanning %s %s\"%s\"... (%2d%s)"
9684 (if is-directory "directory" "files")
9685 (or num-string "") name
9686 (/ (* 100 (- no-files (length file-list))) no-files) "%")
9687 (let ((file-name (abbreviate-file-name (car file-list)))
9688 opened arch-name ent-name
9689 ent-list arch-list conf-list pack-list inst-list)
9690 ;; open file
9691 (if (find-buffer-visiting file-name)
9692 (set-buffer (find-buffer-visiting file-name))
9693 (set-buffer (find-file-noselect file-name nil t))
9694 (setq opened t))
9695 (modify-syntax-entry ?_ "w" (syntax-table))
9696 ;; scan for entities
9697 (goto-char (point-min))
9698 (while (re-search-forward "^\\s-*entity\\s-+\\(\\w+\\)" nil t)
9699 (let* ((ent-entry (aget ent-alist (match-string 1)))
9700 (arch-alist (nth 2 ent-entry))
9701 (conf-alist (nth 3 ent-entry)))
9702 (setq ent-list (cons (match-string 1) ent-list))
9703 (aput 'ent-alist (match-string 1)
9704 (list file-name (vhdl-current-line)
9705 arch-alist conf-alist nil))))
9706 ;; scan for architectures and instantiations
9707 (goto-char (point-min))
9708 (while (re-search-forward
9709 (concat
9710 "^\\s-*\\(architecture\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)\\|"
9711 "\\(\\w+\\)\\s-*:\\(\\s-\\|\n\\)*\\(entity\\s-+\\w+\\.\\)?"
9712 "\\(\\w+\\)\\(\\s-*(\\(\\w+\\))\\)?\\(\\s-\\|\n\\|--.*\n\\)*"
9713 "\\(generic\\|port\\)\\s-+map\\>\\)")
9714 nil t)
9715 (if (match-string 2)
9716 ;; architecture found
9717 (let* ((ent-entry (aget ent-alist (match-string 3)))
9718 (arch-alist (nth 2 ent-entry))
9719 (conf-alist (nth 3 ent-entry)))
9720 (setq arch-name (match-string 2))
9721 (setq ent-name (match-string 3))
9722 (setq arch-list (cons arch-name arch-list))
9723 (vhdl-aappend 'arch-alist arch-name
9724 (list file-name (vhdl-current-line) nil))
9725 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9726 arch-alist conf-alist nil))
9727 (aput 'ent-alist ent-name ent-entry))
9728 ;; instantiation found
9729 (let* ((ent-entry (aget ent-alist ent-name))
9730 (arch-alist (nth 2 ent-entry))
9731 (arch-entry (aget arch-alist arch-name))
9732 (inst-alist (nth 2 arch-entry))
9733 (inst-name (match-string 4))
9734 (inst-ent-name (match-string 7))
9735 (inst-arch-name (match-string 9))
9736 (conf-alist (nth 3 ent-entry)))
9737 (re-search-backward ":" nil t)
9738 (setq inst-list (cons inst-name inst-list))
9739 (vhdl-aappend 'inst-alist inst-name
9740 (list file-name (vhdl-current-line)
9741 inst-ent-name inst-arch-name))
9742 (setq arch-entry
9743 (list (nth 0 arch-entry) (nth 1 arch-entry)
9744 inst-alist))
9745 (vhdl-aappend 'arch-alist arch-name arch-entry)
9746 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9747 arch-alist conf-alist nil))
9748 (aput 'ent-alist ent-name ent-entry)
9749 (unless (member inst-ent-name ent-inst-list)
9750 (setq ent-inst-list
9751 (cons inst-ent-name ent-inst-list))))))
9752 ;; scan for configurations
9753 (goto-char (point-min))
9754 (while (re-search-forward
9755 "^\\s-*configuration\\s-+\\(\\w+\\)\\s-+of\\s-+\\(\\w+\\)"
9756 nil t)
9757 (let* ((ent-entry (aget ent-alist (match-string 2)))
9758 (arch-alist (nth 2 ent-entry))
9759 (conf-alist (nth 3 ent-entry)))
9760 (setq conf-list (cons (match-string 1) conf-list))
9761 (vhdl-aappend 'conf-alist (match-string 1)
9762 (list file-name (vhdl-current-line)))
9763 (setq ent-entry (list (nth 0 ent-entry) (nth 1 ent-entry)
9764 arch-alist conf-alist nil))
9765 (aput 'ent-alist (match-string 2) ent-entry)))
9766 ;; scan for packages
9767 (goto-char (point-min))
9768 (while (re-search-forward
9769 "^\\s-*package\\s-+\\(body\\s-+\\)?\\(\\w+\\)" nil t)
9770 (let ((pack-entry (aget pack-alist (match-string 2))))
9771 (setq pack-list (cons (match-string 2) pack-list))
9772 (aput 'pack-alist (match-string 2)
9773 (if (not (match-string 1))
9774 (list file-name (vhdl-current-line)
9775 (nth 2 pack-entry) (nth 3 pack-entry))
9776 (list (nth 0 pack-entry) (nth 1 pack-entry)
9777 file-name (vhdl-current-line))))))
9778 (setq file-list (cdr file-list))
9779 ;; add design units to variable `vhdl-file-alist'
9780 (aput 'vhdl-file-alist file-name
d4a5b644 9781 (list ent-list arch-list conf-list pack-list inst-list))
5eabfe72
KH
9782 ;; close file
9783 (if opened
9784 (kill-buffer (current-buffer))
9785 (when (not vhdl-underscore-is-part-of-word)
9786 (modify-syntax-entry ?_ "_" vhdl-mode-syntax-table)))
9787 (set-buffer source-buffer)))
9788 ;; sort entities and packages
9789 (setq ent-alist
9790 (sort ent-alist
9791 (function (lambda (a b) (string-lessp (car a) (car b))))))
9792 (setq pack-alist
9793 (sort pack-alist
9794 (function (lambda (a b) (string-lessp (car a) (car b))))))
9795 ;; put directory contents into cache
9796 (when ent-alist
9797 (aput 'vhdl-entity-alist name ent-alist))
9798 (when pack-alist
9799 (aput 'vhdl-package-alist name pack-alist))
9800 (when ent-inst-list
9801 (aput 'vhdl-ent-inst-alist name (list ent-inst-list)))
9802 (message "Scanning %s %s\"%s\"...done"
9803 (if is-directory "directory" "files") (or num-string "") name)
9804 t))))
9805
9806(defun vhdl-scan-project-contents (project &optional rescan)
9807 "Scan the contents of all VHDL files found in the directories and files
9808of PROJECT."
9809 (let ((dir-list-tmp (nth 1 (aget vhdl-project-alist project)))
9810 dir-list pro-ent-alist pro-pack-alist pro-ent-inst-list
9811 dir name num-dir act-dir)
9812 ;; resolve environment variables and path wildcards
9813 (setq dir-list-tmp (vhdl-resolve-paths dir-list-tmp))
9814 ;; expand directories
9815 (while dir-list-tmp
9816 (setq dir (car dir-list-tmp))
9817 ;; get subdirectories
9818 (if (string-match "-r \\(.*/\\)" dir)
9819 (setq dir-list (append dir-list (vhdl-get-subdirs
9820 (match-string 1 dir))))
9821 (setq dir-list (append dir-list (list dir))))
9822 (setq dir-list-tmp (cdr dir-list-tmp)))
9823 ;; get entities and packages of each directory in DIR-LIST
9824 (setq num-dir (length dir-list)
9825 act-dir 1)
9826 (while dir-list
9827 (setq name (abbreviate-file-name (car dir-list)))
9828 (or (and (not rescan)
9829 (or (assoc name vhdl-entity-alist)
9830 (assoc name vhdl-package-alist)))
9831 (vhdl-scan-file-contents name (format "(%s/%s) " act-dir num-dir)))
9832 ;; merge entities and corresponding architectures and configurations
9833 (let ((ent-alist (aget vhdl-entity-alist name)))
9834 (while ent-alist
9835 (let* ((ent-name (car (car ent-alist)))
9836 (ent-entry (cdr (car ent-alist)))
9837 (pro-ent-entry (aget pro-ent-alist ent-name)))
9838 (aput 'pro-ent-alist ent-name
9839 (list (or (nth 0 pro-ent-entry) (nth 0 ent-entry))
9840 (or (nth 1 pro-ent-entry) (nth 1 ent-entry))
9841 (append (nth 2 pro-ent-entry) (nth 2 ent-entry))
9842 (append (nth 3 pro-ent-entry) (nth 3 ent-entry)))))
9843 (setq ent-alist (cdr ent-alist))))
9844 ;; merge packages and corresponding package bodies
9845 (let ((pack-alist (aget vhdl-package-alist name)))
9846 (while pack-alist
9847 (let* ((pack-name (car (car pack-alist)))
9848 (pack-entry (cdr (car pack-alist)))
9849 (pro-pack-entry (aget pro-pack-alist pack-name)))
9850 (aput 'pro-pack-alist pack-name
9851 (list (or (nth 0 pro-pack-entry) (nth 0 pack-entry))
9852 (or (nth 1 pro-pack-entry) (nth 1 pack-entry))
9853 (or (nth 2 pro-pack-entry) (nth 2 pack-entry))
9854 (or (nth 3 pro-pack-entry) (nth 3 pack-entry)))))
9855 (setq pack-alist (cdr pack-alist))))
9856 ;; merge list of instantiated entities
9857 (setq pro-ent-inst-list
9858 (append pro-ent-inst-list
9859 (copy-alist
9860 (car (aget vhdl-ent-inst-alist name)))))
9861 (setq dir-list (cdr dir-list)
9862 act-dir (1+ act-dir)))
9863 ;; sort lists and put them into the caches
9864 (when pro-ent-alist
9865 (aput 'vhdl-project-entity-alist project
9866 (sort pro-ent-alist
9867 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9868 (when pro-pack-alist
9869 (aput 'vhdl-project-package-alist project
9870 (sort pro-pack-alist
9871 (function (lambda (a b) (string-lessp (car a) (car b)))))))
9872 (when pro-ent-inst-list
9873 (aput 'vhdl-project-ent-inst-list project pro-ent-inst-list))))
9874
9875(defun vhdl-get-hierarchy (ent-name arch-name level indent &optional ent-hier)
9876 "Get instantiation hierarchy beginning in architecture ARCH-NAME of
9877entity ENT-NAME."
9878 (let* ((ent-alist (if (vhdl-speedbar-project-p)
9879 (aget vhdl-project-entity-alist vhdl-project)
9880 (aget vhdl-entity-alist
9881 (abbreviate-file-name
9882 (file-name-as-directory
9883 (speedbar-line-path (1- indent)))))))
9884 (ent-entry (aget ent-alist ent-name))
9885 (arch-entry (if arch-name (aget (nth 2 ent-entry) arch-name)
9886 (cdr (car (last (nth 2 ent-entry))))))
9887 (inst-list (nth 2 arch-entry))
9888 inst-entry inst-ent-entry inst-arch-entry hier-list)
9889 (when (= level 0) (message "Extract design hierarchy..."))
9890 (when (member ent-name ent-hier)
9891 (error (format "Instantiation loop detected; component \"%s\" instantiates itself"
9892 ent-name)))
9893 (while inst-list
9894 (setq inst-entry (car inst-list))
9895 (setq inst-ent-entry (aget ent-alist (nth 3 inst-entry)))
9896 (setq inst-arch-entry
9897 (if (nth 4 inst-entry)
9898 (cons (nth 4 inst-entry)
9899 (aget (nth 2 inst-ent-entry) (nth 4 inst-entry)))
9900 (car (last (nth 2 inst-ent-entry)))))
9901 (setq hier-list
9902 (append
9903 hier-list
9904 (cons (list (nth 0 inst-entry)
9905 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9906 (nth 3 inst-entry)
9907 (cons (nth 0 inst-ent-entry) (nth 1 inst-ent-entry))
9908 (nth 0 inst-arch-entry)
9909 (cons (nth 1 inst-arch-entry) (nth 2 inst-arch-entry))
9910 level)
9911 (vhdl-get-hierarchy (nth 3 inst-entry) (nth 4 inst-entry)
9912 (1+ level) indent
9913 (cons ent-name ent-hier)))))
9914 (setq inst-list (cdr inst-list)))
9915 (when (= level 0) (message "Extract design hierarchy...done"))
9916 hier-list))
9917
9918(defun vhdl-get-instantiations (ent-name indent)
9919 "Get all instantiations of entity ENT-NAME."
9920 (let ((ent-alist (if (vhdl-speedbar-project-p)
9921 (aget vhdl-project-entity-alist vhdl-project)
9922 (aget vhdl-entity-alist
9923 (abbreviate-file-name
9924 (file-name-as-directory
9925 (speedbar-line-path indent))))))
9926 arch-alist inst-alist ent-inst-list
9927 ent-entry arch-entry inst-entry)
9928 (while ent-alist
9929 (setq ent-entry (car ent-alist))
9930 (setq arch-alist (nth 3 ent-entry))
9931 (while arch-alist
9932 (setq arch-entry (car arch-alist))
9933 (setq inst-alist (nth 3 arch-entry))
9934 (while inst-alist
9935 (setq inst-entry (car inst-alist))
9936 (when (equal ent-name (nth 3 inst-entry))
9937 (setq ent-inst-list
9938 (cons (list (nth 0 inst-entry)
9939 (cons (nth 1 inst-entry) (nth 2 inst-entry))
9940 (nth 0 ent-entry)
9941 (cons (nth 1 ent-entry) (nth 2 ent-entry))
9942 (nth 0 arch-entry)
9943 (cons (nth 1 arch-entry) (nth 2 arch-entry)))
9944 ent-inst-list)))
9945 (setq inst-alist (cdr inst-alist)))
9946 (setq arch-alist (cdr arch-alist)))
9947 (setq ent-alist (cdr ent-alist)))
9948 (nreverse ent-inst-list)))
9949
9950;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9951;; Add hierarchy browser functionality to speedbar.
9952
9953(defvar vhdl-speedbar-key-map nil
9954 "Keymap used when in the VHDL hierarchy browser mode.")
9955
9956(defvar vhdl-speedbar-menu-items
9957 '(["Edit Design Unit" speedbar-edit-line t]
9958 ["Expand Hierarchy" speedbar-expand-line
9959 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.\\+. "))]
9960 ["Contract Hierarchy" speedbar-contract-line
9961 (save-excursion (beginning-of-line) (looking-at "[0-9]+: *.-. "))]
9962 ["Rescan Hierarchy" vhdl-speedbar-rescan-hierarchy t]
9963 "--"
9964 ["Copy Port" vhdl-speedbar-port-copy
9965 (save-excursion
9966 (beginning-of-line) (looking-at "[0-9]+: *\\[[-+?]\\] "))])
9967 "Additional menu-items to add to speedbar frame.")
9968
9969(defun vhdl-speedbar-initialize ()
9970 "Initialize speedbar."
9971 ;; general settings
9972; (set (make-local-variable 'speedbar-tag-hierarchy-method) nil)
9973 ;; VHDL file extensions (extracted from `auto-mode-alist')
9974 (let ((mode-alist auto-mode-alist))
9975 (while mode-alist
9976 (when (eq (cdr (car mode-alist)) 'vhdl-mode)
9977 (speedbar-add-supported-extension (car (car mode-alist))))
9978 (setq mode-alist (cdr mode-alist))))
9979 ;; hierarchy browser settings
9980 (when (boundp 'speedbar-mode-functions-list)
9981 (speedbar-add-mode-functions-list
9982 '("vhdl hierarchy"
9983 (speedbar-item-info . vhdl-speedbar-item-info)
9984 (speedbar-line-path . speedbar-files-line-path)))
9985 (unless vhdl-speedbar-key-map
9986 (setq vhdl-speedbar-key-map (speedbar-make-specialized-keymap))
9987 (define-key vhdl-speedbar-key-map "e" 'speedbar-edit-line)
9988 (define-key vhdl-speedbar-key-map "\C-m" 'speedbar-edit-line)
9989 (define-key vhdl-speedbar-key-map "+" 'speedbar-expand-line)
9990 (define-key vhdl-speedbar-key-map "-" 'speedbar-contract-line)
9991 (define-key vhdl-speedbar-key-map "s" 'vhdl-speedbar-rescan-hierarchy)
9992 (define-key vhdl-speedbar-key-map "c" 'vhdl-speedbar-port-copy))
9993 (define-key speedbar-key-map "h"
9994 (lambda () (interactive)
9995 (speedbar-change-initial-expansion-list "vhdl hierarchy")))
9996 (speedbar-add-expansion-list '("vhdl hierarchy" vhdl-speedbar-menu-items
9997 vhdl-speedbar-key-map
9998 vhdl-speedbar-display-hierarchy))
9999 (setq speedbar-stealthy-function-list
10000 (cons '("vhdl hierarchy" vhdl-speedbar-update-current-unit)
10001 speedbar-stealthy-function-list))
10002 (when vhdl-speedbar-show-hierarchy
10003 (setq speedbar-initial-expansion-list-name "vhdl hierarchy"))))
10004
10005(defun vhdl-speedbar (&optional arg)
10006 "Open/close speedbar."
d2ddb974 10007 (interactive)
5eabfe72
KH
10008 (if (not (fboundp 'speedbar))
10009 (error "WARNING: Speedbar is only available in newer Emacs versions")
10010 (condition-case () ; due to bug in `speedbar-el' v0.7.2a
10011 (speedbar-frame-mode arg)
10012 (error (error "WARNING: Install included `speedbar.el' patch first")))))
10013
10014;; initialize speedbar for VHDL Mode
10015(if (not (boundp 'speedbar-frame))
10016 (add-hook 'speedbar-load-hook 'vhdl-speedbar-initialize)
10017 (vhdl-speedbar-initialize)
5d31462e 10018 (when speedbar-frame (speedbar-refresh)))
5eabfe72
KH
10019
10020;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10021;; Display functions
10022
10023;; macros must be defined in the file they are used (copied from `speedbar.el')
10024(defmacro speedbar-with-writable (&rest forms)
10025 "Allow the buffer to be writable and evaluate FORMS."
10026 (list 'let '((inhibit-read-only t))
10027 (cons 'progn forms)))
10028(put 'speedbar-with-writable 'lisp-indent-function 0)
10029
10030(defun vhdl-speedbar-display-hierarchy (directory depth &optional rescan)
10031 "Display directory and hierarchy information in speedbar."
10032 (setq directory (abbreviate-file-name (file-name-as-directory directory)))
10033 (setq speedbar-last-selected-file nil)
10034 (speedbar-with-writable
10035 (save-excursion
10036 (if (vhdl-speedbar-project-p)
10037 (progn
10038 ;; insert project title
10039 (vhdl-speedbar-make-title-line "Project:" 0)
10040 (let ((start (point)))
10041 (insert "p:")
10042 (put-text-property start (point) 'invisible t)
10043 (setq start (point))
10044 (insert vhdl-project)
10045 (put-text-property start (point) 'face 'speedbar-directory-face))
10046 (insert-char ?\n 1)
10047 ;; scan and insert hierarchy of project
10048 (vhdl-speedbar-insert-project-hierarchy vhdl-project
10049 speedbar-power-click))
10050 ;; insert directory path
10051 (speedbar-directory-buttons directory depth)
10052 ;; insert subdirectories
10053 (vhdl-speedbar-insert-dirs (speedbar-file-lists directory) depth)
10054 ;; scan and insert hierarchy of current directory
10055 (vhdl-speedbar-insert-dir-hierarchy directory depth
10056 speedbar-power-click)
10057 ;; expand subdirectories
10058 (when (= depth 0) (vhdl-speedbar-expand-dirs directory))))))
10059
10060(defun vhdl-speedbar-insert-hierarchy (ent-alist pack-alist
10061 ent-inst-list depth)
10062 "Insert hierarchy of ENT-ALIST and PACK-ALIST."
10063 (if (not (or ent-alist pack-alist))
10064 (vhdl-speedbar-make-title-line "No design units!" depth)
10065 (let (ent-entry pack-entry)
10066 ;; insert entities
10067 (when ent-alist (vhdl-speedbar-make-title-line "Entities:" depth))
10068 (while ent-alist
10069 (setq ent-entry (car ent-alist))
10070 (speedbar-make-tag-line
10071 'bracket ?+ 'vhdl-speedbar-expand-entity (nth 0 ent-entry)
10072 (nth 0 ent-entry) 'vhdl-speedbar-find-file
10073 (cons (nth 1 ent-entry) (nth 2 ent-entry))
10074 'vhdl-speedbar-entity-face depth)
10075 (when (not (member (nth 0 ent-entry) ent-inst-list))
10076 (end-of-line 0) (insert " (top)") (forward-char 1))
10077 (setq ent-alist (cdr ent-alist)))
10078 ;; insert packages
10079 (when pack-alist (vhdl-speedbar-make-title-line "Packages:" depth))
10080 (while pack-alist
10081 (setq pack-entry (car pack-alist))
10082 (vhdl-speedbar-make-pack-line
10083 (nth 0 pack-entry)
10084 (cons (nth 1 pack-entry) (nth 2 pack-entry))
10085 (cons (nth 3 pack-entry) (nth 4 pack-entry))
10086 depth)
10087 (setq pack-alist (cdr pack-alist))))))
10088
10089(defun vhdl-speedbar-insert-project-hierarchy (project &optional rescan)
10090 "Insert hierarchy of project. Rescan directories if RESCAN is non-nil,
10091otherwise use cached data of directories."
10092 (when (or rescan (and (not (assoc project vhdl-project-entity-alist))
10093 (not (assoc project vhdl-project-package-alist))))
10094 (vhdl-scan-project-contents project rescan))
10095 ;; insert design hierarchy in speedbar
10096 (vhdl-speedbar-insert-hierarchy
10097 (aget vhdl-project-entity-alist project)
10098 (aget vhdl-project-package-alist project)
10099 (aget vhdl-project-ent-inst-list project) 0)
10100 ;; expand design units
10101 (vhdl-speedbar-expand-units project))
10102
10103(defun vhdl-speedbar-insert-dir-hierarchy (directory depth &optional rescan)
10104 "Insert hierarchy of DIRECTORY. Rescan directory if RESCAN is non-nil,
10105otherwise use cached data."
10106 (when (or rescan (and (not (assoc directory vhdl-entity-alist))
10107 (not (assoc directory vhdl-package-alist))))
10108 (vhdl-scan-file-contents directory))
10109 (vhdl-speedbar-insert-hierarchy
10110 (aget vhdl-entity-alist directory)
10111 (aget vhdl-package-alist directory)
10112 (car (aget vhdl-ent-inst-alist directory))
10113 depth)
10114 (vhdl-speedbar-expand-units directory))
10115
10116(defun vhdl-speedbar-rescan-hierarchy ()
10117 "Rescan hierarchy for the directory under the cursor or the current project."
d2ddb974 10118 (interactive)
5eabfe72
KH
10119 (cond
10120 ;; the current project
10121 ((vhdl-speedbar-project-p)
10122 (vhdl-scan-project-contents vhdl-project t)
10123 (speedbar-refresh))
10124 ;; the top-level directory
10125 ((save-excursion (beginning-of-line) (looking-at "[^0-9]"))
10126 (re-search-forward "[0-9]+:" nil t)
10127 (vhdl-scan-file-contents (abbreviate-file-name (speedbar-line-path)))
10128 (speedbar-refresh))
10129 ;; the current directory
10130 (t (let ((path (speedbar-line-path)))
10131 (string-match "^\\(.+/\\)" path)
10132 (vhdl-scan-file-contents (abbreviate-file-name (match-string 1 path)))
10133 (speedbar-refresh)))))
10134
10135(defun vhdl-speedbar-expand-dirs (directory)
10136 "Expand subdirectories in DIRECTORY according to
10137 `speedbar-shown-directories'."
10138 ;; (nicked from `speedbar-default-directory-list')
10139 (let ((sf (cdr (reverse speedbar-shown-directories))))
10140 (setq speedbar-shown-directories
10141 (list (expand-file-name default-directory)))
10142 (while sf
10143 (when (speedbar-goto-this-file (car sf))
10144 (beginning-of-line)
10145 (when (looking-at "[0-9]+:\\s-*<")
10146 (goto-char (match-end 0))
10147 (let* ((position (point))
10148 (directory (abbreviate-file-name
10149 (file-name-as-directory (speedbar-line-file)))))
10150 (speedbar-do-function-pointer))))
10151 (setq sf (cdr sf)))))
10152
10153(defun vhdl-speedbar-expand-units (directory)
10154 "Expand design units in DIRECTORY according to
10155`vhdl-speedbar-shown-units-alist'."
10156 (let ((ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10157 (adelete 'vhdl-speedbar-shown-units-alist directory)
10158 (while ent-alist ; expand entities
10159 (vhdl-speedbar-goto-this-unit directory (car (car ent-alist)))
10160 (beginning-of-line)
10161 (let ((arch-alist (nth 1 (car ent-alist)))
10162 position)
10163 (when (looking-at "[0-9]+:\\s-*\\[")
10164 (goto-char (match-end 0))
10165 (setq position (point))
10166 (speedbar-do-function-pointer)
10167 (while arch-alist ; expand architectures
10168 (goto-char position)
10169 (when (re-search-forward
10170 (concat "[0-9]+:\\s-*\\(\\[\\|{.}\\s-+"
10171 (car arch-alist) "\\>\\)") nil t)
10172 (beginning-of-line)
10173 (when (looking-at "[0-9]+:\\s-*{")
10174 (goto-char (match-end 0))
10175 (speedbar-do-function-pointer)))
10176 (setq arch-alist (cdr arch-alist))))
10177 (setq ent-alist (cdr ent-alist))))))
10178
10179(defun vhdl-speedbar-expand-entity (text token indent)
10180 "Expand/contract the entity under the cursor."
10181 (cond
10182 ((string-match "+" text) ; expand entity
10183 (let* ((ent-alist (if (vhdl-speedbar-project-p)
10184 (aget vhdl-project-entity-alist vhdl-project)
10185 (aget vhdl-entity-alist
10186 (abbreviate-file-name
10187 (file-name-as-directory
10188 (speedbar-line-path indent))))))
10189 (arch-alist (nth 2 (aget ent-alist token)))
10190 (conf-alist (nth 3 (aget ent-alist token)))
10191 (inst-alist (vhdl-get-instantiations token indent))
10192 arch-entry conf-entry inst-entry)
10193 (if (not (or arch-alist conf-alist inst-alist))
10194 (speedbar-change-expand-button-char ??)
10195 (speedbar-change-expand-button-char ?-)
10196 ;; add entity to `vhdl-speedbar-shown-units-alist'
10197 (let* ((directory (if (vhdl-speedbar-project-p)
10198 vhdl-project
10199 (abbreviate-file-name
10200 (file-name-as-directory (speedbar-line-path)))))
10201 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10202 (aput 'ent-alist (speedbar-line-text) nil)
10203 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10204 (speedbar-with-writable
10205 (save-excursion
10206 (end-of-line) (forward-char 1)
10207 ;; insert architectures
10208 (when arch-alist
10209 (vhdl-speedbar-make-title-line "Architectures:" (1+ indent)))
10210 (while arch-alist
10211 (setq arch-entry (car arch-alist))
10212 (speedbar-make-tag-line
10213 'curly ?+ 'vhdl-speedbar-expand-architecture
10214 (cons token (nth 0 arch-entry))
10215 (nth 0 arch-entry) 'vhdl-speedbar-find-file
10216 (cons (nth 1 arch-entry) (nth 2 arch-entry))
10217 'vhdl-speedbar-architecture-face (1+ indent))
10218 (setq arch-alist (cdr arch-alist)))
10219 ;; insert configurations
10220 (when conf-alist
10221 (vhdl-speedbar-make-title-line "Configurations:" (1+ indent)))
10222 (while conf-alist
10223 (setq conf-entry (car conf-alist))
10224 (speedbar-make-tag-line
10225 nil nil nil
10226 (cons token (nth 0 conf-entry))
10227 (nth 0 conf-entry) 'vhdl-speedbar-find-file
10228 (cons (nth 1 conf-entry) (nth 2 conf-entry))
10229 'vhdl-speedbar-configuration-face (1+ indent))
10230 (setq conf-alist (cdr conf-alist)))
10231 ;; insert instantiations
10232 (when inst-alist
10233 (vhdl-speedbar-make-title-line "Instantiations:" (1+ indent)))
10234 (while inst-alist
10235 (setq inst-entry (car inst-alist))
10236 (vhdl-speedbar-make-inst-line
10237 (nth 0 inst-entry) (nth 1 inst-entry)
10238 (nth 2 inst-entry) (nth 3 inst-entry)
10239 (nth 4 inst-entry) (nth 5 inst-entry) (1+ indent) 0)
10240 (setq inst-alist (cdr inst-alist)))))
10241 (setq speedbar-last-selected-file nil)
10242 (save-excursion (speedbar-stealthy-updates)))))
10243 ((string-match "-" text) ; contract entity
10244 (speedbar-change-expand-button-char ?+)
10245 ;; remove entity from `vhdl-speedbar-shown-units-alist'
10246 (let* ((directory (if (vhdl-speedbar-project-p)
10247 vhdl-project
10248 (abbreviate-file-name
10249 (file-name-as-directory (speedbar-line-path)))))
10250 (ent-alist (aget vhdl-speedbar-shown-units-alist directory)))
10251 (adelete 'ent-alist (speedbar-line-text))
10252 (if ent-alist
10253 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist)
10254 (adelete 'vhdl-speedbar-shown-units-alist directory)))
10255 (speedbar-delete-subblock indent))
10256 (t (error "No architectures, configurations, nor instantiations exist for this entity")))
10257 (speedbar-center-buffer-smartly))
10258
10259(defun vhdl-speedbar-expand-architecture (text token indent)
10260 "Expand/contract the architecture under the cursor."
10261 (cond
10262 ((string-match "+" text) ; expand architecture
10263 (let ((hier-alist (vhdl-get-hierarchy (car token) (cdr token) 0 indent)))
10264 (if (not hier-alist)
10265 (speedbar-change-expand-button-char ??)
10266 (speedbar-change-expand-button-char ?-)
10267 ;; add architecture to `vhdl-speedbar-shown-units-alist'
10268 (let* ((path (speedbar-line-path))
10269 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10270 (ent-name (match-string 2 path))
10271 (directory (if (vhdl-speedbar-project-p)
10272 vhdl-project
10273 (abbreviate-file-name (match-string 1 path))))
10274 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10275 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10276 (aput 'ent-alist ent-name
10277 (list (cons (speedbar-line-text) arch-alist)))
10278 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10279 (speedbar-with-writable
10280 (save-excursion
10281 (end-of-line) (forward-char 1)
10282 ;; insert instance hierarchy
10283 (when hier-alist
10284 (vhdl-speedbar-make-title-line "Subcomponents:" (1+ indent)))
10285 (while hier-alist
10286 (let ((entry (car hier-alist)))
10287 (vhdl-speedbar-make-inst-line
10288 (nth 0 entry) (nth 1 entry)
10289 (nth 2 entry) (nth 3 entry)
10290 (nth 4 entry) (nth 5 entry)
10291 (1+ indent) (nth 6 entry))
10292 (setq hier-alist (cdr hier-alist))))))
10293 (setq speedbar-last-selected-file nil)
10294 (save-excursion (speedbar-stealthy-updates)))))
10295 ((string-match "-" text) ; contract architecture
10296 (speedbar-change-expand-button-char ?+)
10297 ;; remove architecture from `vhdl-speedbar-shown-units-alist'
10298 (let* ((path (speedbar-line-path))
10299 (dummy (string-match "^\\(.+/\\)\\([^/ ]+\\)" path))
10300 (ent-name (match-string 2 path))
10301 (directory (if (vhdl-speedbar-project-p)
10302 vhdl-project
10303 (abbreviate-file-name (match-string 1 path))))
10304 (ent-alist (aget vhdl-speedbar-shown-units-alist directory))
10305 (arch-alist (nth 0 (aget ent-alist ent-name t))))
10306 (aput 'ent-alist ent-name
10307 (list (delete (speedbar-line-text) arch-alist)))
10308 (aput 'vhdl-speedbar-shown-units-alist directory ent-alist))
10309 (speedbar-delete-subblock indent))
10310 (t (error "No component instantiations contained in this architecture")))
10311 (speedbar-center-buffer-smartly))
10312
10313;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10314;; Display help functions
10315
10316(defun vhdl-speedbar-update-current-unit (&optional no-position)
10317 "Highlight all design units that are contained in the current file.
10318NO-POSITION non-nil means do not re-position cursor."
10319 (let ((last-frame (selected-frame))
10320 file-name position)
10321 ;; get current file name
10322 (select-frame speedbar-attached-frame)
10323 (setq file-name (abbreviate-file-name (or (buffer-file-name) "")))
10324 (unless (equal file-name speedbar-last-selected-file)
10325 (select-frame speedbar-frame)
10326 (set-buffer speedbar-buffer)
10327 (speedbar-with-writable
10328 (save-excursion
10329 ;; unhighlight last units
10330 (let* ((file-entry
10331 (aget vhdl-file-alist speedbar-last-selected-file)))
10332 (vhdl-speedbar-update-units
10333 "\\[.\\]" (nth 0 file-entry)
10334 speedbar-last-selected-file 'vhdl-speedbar-entity-face)
10335 (vhdl-speedbar-update-units
10336 "{.}" (nth 1 file-entry)
10337 speedbar-last-selected-file 'vhdl-speedbar-architecture-face)
10338 (vhdl-speedbar-update-units
10339 ">" (nth 2 file-entry)
10340 speedbar-last-selected-file 'vhdl-speedbar-configuration-face)
10341 (vhdl-speedbar-update-units
10342 ">" (nth 3 file-entry)
10343 speedbar-last-selected-file 'vhdl-speedbar-package-face)
10344 (vhdl-speedbar-update-units
10345 ">" (nth 4 file-entry)
10346 speedbar-last-selected-file 'vhdl-speedbar-instantiation-face))
10347 ;; highlight current units
10348 (let* ((file-entry (aget vhdl-file-alist file-name)))
10349 (vhdl-speedbar-update-units
10350 "\\[.\\]" (nth 0 file-entry)
10351 file-name 'vhdl-speedbar-entity-selected-face)
10352 (setq position (or position (point-marker)))
10353 (vhdl-speedbar-update-units
10354 "{.}" (nth 1 file-entry)
10355 file-name 'vhdl-speedbar-architecture-selected-face)
10356 (setq position (or position (point-marker)))
10357 (vhdl-speedbar-update-units
10358 ">" (nth 2 file-entry)
10359 file-name 'vhdl-speedbar-configuration-selected-face)
10360 (setq position (or position (point-marker)))
10361 (vhdl-speedbar-update-units
10362 ">" (nth 3 file-entry)
10363 file-name 'vhdl-speedbar-package-selected-face)
10364 (setq position (or position (point-marker)))
10365 (vhdl-speedbar-update-units
10366 ">" (nth 4 file-entry)
10367 file-name 'vhdl-speedbar-instantiation-selected-face))))
10368 (setq position (or position (point-marker)))
10369 ;; move speedbar so the first highlighted unit is visible
10370 (when (and position (not no-position))
10371 (goto-char position)
10372 (speedbar-center-buffer-smartly)
10373 (speedbar-position-cursor-on-line))
10374 (setq speedbar-last-selected-file file-name))
10375 (select-frame last-frame)
10376 t))
10377
10378(defun vhdl-speedbar-update-units (text unit-list file-name face)
10379 "Help function to highlight design units."
10380 (let (position)
10381 (while unit-list
10382 (goto-char (point-min))
10383 (while (re-search-forward
10384 (concat text " \\(" (car unit-list) "\\)\\>") nil t)
10385 (when (equal file-name (car (get-text-property
10386 (match-beginning 1) 'speedbar-token)))
10387 (setq position (or position (point-marker)))
10388 (put-text-property (match-beginning 1) (match-end 1) 'face face)))
10389 (setq unit-list (cdr unit-list)))
10390 (when position (goto-char position))))
10391
10392(defun vhdl-speedbar-make-inst-line (inst-name inst-file-marker
10393 ent-name ent-file-marker
10394 arch-name arch-file-marker
10395 depth offset)
10396 "Insert instantiation entry."
10397 (let ((start (point)))
10398 (insert (int-to-string depth) ":")
10399 (put-text-property start (point) 'invisible t)
10400 (setq start (point))
10401 (insert-char ? (+ depth (* offset vhdl-speedbar-hierarchy-indent)))
10402 (insert "> ")
10403 (put-text-property start (point) 'invisible nil)
10404 (setq start (point))
10405 (insert inst-name)
10406 (speedbar-make-button
10407 start (point) 'vhdl-speedbar-instantiation-face 'speedbar-highlight-face
10408 'vhdl-speedbar-find-file inst-file-marker)
10409 (setq start (point))
10410 (insert ": ")
10411 (put-text-property start (point) 'invisible nil)
10412 (setq start (point))
10413 (insert ent-name)
10414 (speedbar-make-button
10415 start (point) 'vhdl-speedbar-entity-face 'speedbar-highlight-face
10416 'vhdl-speedbar-find-file ent-file-marker)
10417 (setq start (point))
10418 (when arch-name
10419 (insert " (")
10420 (put-text-property start (point) 'invisible nil)
10421 (setq start (point))
10422 (insert arch-name)
10423 (speedbar-make-button
10424 start (point) 'vhdl-speedbar-architecture-face 'speedbar-highlight-face
10425 'vhdl-speedbar-find-file arch-file-marker)
10426 (setq start (point))
10427 (insert ")"))
10428 (put-text-property start (point) 'invisible nil)
10429 (insert-char ?\n 1)
10430 (put-text-property (1- (point)) (point) 'invisible nil)))
10431
10432(defun vhdl-speedbar-make-pack-line (pack-name pack-file-marker
10433 body-file-marker depth)
10434 "Insert package entry."
10435 (let ((start (point)))
10436 (insert (int-to-string depth) ":")
10437 (put-text-property start (point) 'invisible t)
10438 (setq start (point))
10439 (insert-char ? depth)
10440 (insert "> ")
10441 (put-text-property start (point) 'invisible nil)
10442 (setq start (point))
10443 (insert pack-name)
10444 (speedbar-make-button
10445 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10446 'vhdl-speedbar-find-file pack-file-marker)
10447 (when (car body-file-marker)
10448 (setq start (point))
10449 (insert " (")
10450 (put-text-property start (point) 'invisible nil)
10451 (setq start (point))
10452 (insert "body")
10453 (speedbar-make-button
10454 start (point) 'vhdl-speedbar-package-face 'speedbar-highlight-face
10455 'vhdl-speedbar-find-file body-file-marker)
10456 (setq start (point))
10457 (insert ")")
10458 (put-text-property start (point) 'invisible nil))
10459 (insert-char ?\n 1)
10460 (put-text-property (1- (point)) (point) 'invisible nil)))
10461
10462(defun vhdl-speedbar-make-title-line (text depth)
10463 "Insert design unit title entry."
10464 (let ((start (point)))
10465 (insert (int-to-string depth) ":")
10466 (put-text-property start (point) 'invisible t)
10467 (setq start (point))
10468 (insert-char ? depth)
10469 (put-text-property start (point) 'invisible nil)
10470 (setq start (point))
10471 (insert text)
10472 (speedbar-make-button start (point) nil nil nil nil)
10473 (insert-char ?\n 1)
10474 (put-text-property start (point) 'invisible nil)))
10475
10476(defun vhdl-speedbar-insert-dirs (files level)
10477 "Insert subdirectories."
10478 (let ((dirs (car files)))
10479 (while dirs
10480 (speedbar-make-tag-line 'angle ?+ 'vhdl-speedbar-dired (car dirs)
10481 (car dirs) 'speedbar-dir-follow nil
10482 'speedbar-directory-face level)
10483 (setq dirs (cdr dirs)))))
10484
10485(defun vhdl-speedbar-dired (text token indent)
10486 "Speedbar click handler for directory expand button in hierarchy mode."
10487 (cond ((string-match "+" text) ; we have to expand this dir
10488 (setq speedbar-shown-directories
10489 (cons (expand-file-name
10490 (concat (speedbar-line-path indent) token "/"))
10491 speedbar-shown-directories))
10492 (speedbar-change-expand-button-char ?-)
10493 (speedbar-reset-scanners)
10494 (speedbar-with-writable
10495 (save-excursion
10496 (end-of-line) (forward-char 1)
10497 (vhdl-speedbar-insert-dirs
10498 (speedbar-file-lists
10499 (concat (speedbar-line-path indent) token "/"))
10500 (1+ indent))
10501 (speedbar-reset-scanners)
10502 (vhdl-speedbar-insert-dir-hierarchy
10503 (abbreviate-file-name
10504 (concat (speedbar-line-path indent) token "/"))
10505 (1+ indent) speedbar-power-click)))
10506 (setq speedbar-last-selected-file nil)
10507 (save-excursion (speedbar-stealthy-updates)))
10508 ((string-match "-" text) ; we have to contract this node
10509 (speedbar-reset-scanners)
10510 (let ((oldl speedbar-shown-directories)
10511 (newl nil)
10512 (td (expand-file-name
10513 (concat (speedbar-line-path indent) token))))
10514 (while oldl
10515 (if (not (string-match (concat "^" (regexp-quote td)) (car oldl)))
10516 (setq newl (cons (car oldl) newl)))
10517 (setq oldl (cdr oldl)))
10518 (setq speedbar-shown-directories (nreverse newl)))
10519 (speedbar-change-expand-button-char ?+)
10520 (speedbar-delete-subblock indent))
10521 (t (error "Ooops... not sure what to do")))
10522 (speedbar-center-buffer-smartly))
10523
10524(defun vhdl-speedbar-item-info ()
10525 "Derive and display information about this line item."
10526 (save-excursion
10527 (beginning-of-line)
10528 ;; skip invisible number info
10529 (when (looking-at "[0-9]+:") (goto-char (match-end 0)))
10530 (when (looking-at "p:")
10531 (message "Project \"%s\""
10532 (nth 0 (aget vhdl-project-alist vhdl-project))))
10533 (cond
10534 ;; directory entry
10535 ((looking-at "\\s-*<[-+?]> ") (speedbar-files-item-info))
10536 ;; design unit entry
10537 ((looking-at "\\s-*\\([[{][-+?][]}]\\|>\\) ")
10538 (goto-char (match-end 0))
10539 (let ((face (get-text-property (point) 'face)))
10540 (message
10541 "%s \"%s\" in \"%s\""
10542 ;; design unit kind
10543 (cond ((or (eq face 'vhdl-speedbar-entity-face)
10544 (eq face 'vhdl-speedbar-entity-selected-face))
10545 "Entity")
10546 ((or (eq face 'vhdl-speedbar-architecture-face)
10547 (eq face 'vhdl-speedbar-architecture-selected-face))
10548 "Architecture")
10549 ((or (eq face 'vhdl-speedbar-configuration-face)
10550 (eq face 'vhdl-speedbar-configuration-selected-face))
10551 "Configuration")
10552 ((or (eq face 'vhdl-speedbar-package-face)
10553 (eq face 'vhdl-speedbar-package-selected-face))
10554 "Package")
10555 ((or (eq face 'vhdl-speedbar-instantiation-face)
10556 (eq face 'vhdl-speedbar-instantiation-selected-face))
10557 "Instantiation")
10558 (t ""))
10559 ;; design unit name
10560 (buffer-substring-no-properties
10561 (point) (progn (looking-at"\\(\\w\\|_\\)+") (match-end 0)))
10562 ;; file name
10563 (abbreviate-file-name
10564 (or (car (get-text-property (point) 'speedbar-token)) "?"))))))))
10565
10566;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10567;; Help functions
d2ddb974 10568
5eabfe72
KH
10569(defun vhdl-get-subdirs (directory)
10570 "Recursively get subdirectories of DIRECTORY."
10571 (let ((dir-list (list (file-name-as-directory directory)))
10572 subdir-list file-list)
10573 (setq file-list (vhdl-directory-files directory t "\\w.*"))
10574 (while file-list
10575 (when (file-directory-p (car file-list))
10576 (setq dir-list (append dir-list (vhdl-get-subdirs (car file-list)))))
10577 (setq file-list (cdr file-list)))
10578 dir-list))
10579
10580(defun vhdl-resolve-paths (path-list)
10581 "Resolve environment variables and path wildcards in PATH-LIST."
10582 (let (path-list-1 path-list-2 path-list-3 path-beg path-end dir)
10583 ;; resolve environment variables
10584 (while path-list
10585 (setq dir (car path-list))
10586 (while (string-match "\\(.*\\)${?\\(\\(\\w\\|_\\)+\\)}?\\(.*\\)" dir)
10587 (setq dir (concat (match-string 1 dir) (getenv (match-string 2 dir))
10588 (match-string 4 dir))))
10589 (setq path-list-1 (cons dir path-list-1))
10590 (setq path-list (cdr path-list)))
10591 ;; eliminate non-existent directories
10592 (while path-list-1
10593 (setq dir (car path-list-1))
10594 (string-match "\\(-r \\)?\\(\\([^?*]*/\\)*\\)" dir)
10595 (if (file-directory-p (match-string 2 dir))
10596 (setq path-list-2 (cons dir path-list-2))
10597 (message "No such directory: \"%s\"" (match-string 2 dir)))
10598 (setq path-list-1 (cdr path-list-1)))
10599 ;; resolve path wildcards
10600 (while path-list-2
10601 (setq dir (car path-list-2))
10602 (if (string-match
10603 "\\(-r \\)?\\(\\([^?*]*/\\)*\\)\\([^/]*[?*][^/]*\\)\\(/.*\\)" dir)
10604 (progn
10605 (setq path-beg (match-string 1 dir)
10606 path-end (match-string 5 dir))
10607 (setq path-list-2
10608 (append
10609 (mapcar
10610 (function
10611 (lambda (var) (concat path-beg var path-end)))
10612 (let ((all-list (vhdl-directory-files
10613 (match-string 2 dir) t
10614 (concat "\\<" (wildcard-to-regexp
10615 (match-string 4 dir)))))
10616 dir-list)
10617 (while all-list
10618 (when (file-directory-p (car all-list))
10619 (setq dir-list (cons (car all-list) dir-list)))
10620 (setq all-list (cdr all-list)))
10621 dir-list))
10622 (cdr path-list-2))))
10623 (string-match "\\(-r \\)?\\(.*\\)/.*" dir)
10624 (when (file-directory-p (match-string 2 dir))
10625 (setq path-list-3 (cons dir path-list-3)))
10626 (setq path-list-2 (cdr path-list-2))))
10627 path-list-3))
10628
10629(defun vhdl-aappend (alist-symbol key value)
10630 "Append a key-value pair to an alist.
10631Similar to `aput' but moves the key-value pair to the tail of the alist."
10632 (let ((elem (aelement key value))
10633 (alist (adelete alist-symbol key)))
10634 (set alist-symbol (append alist elem))))
10635
10636(defun vhdl-speedbar-goto-this-unit (directory unit)
10637 "If UNIT is displayed in DIRECTORY, goto this line and return t, else nil."
10638 (let ((dest (point)))
10639 (if (and (if (vhdl-speedbar-project-p)
10640 (progn (goto-char (point-min)) t)
10641 (speedbar-goto-this-file directory))
10642 (re-search-forward (concat "[]}] " unit "\\>") nil t))
10643 (progn (speedbar-position-cursor-on-line)
10644 t)
10645 (goto-char dest)
10646 nil)))
10647
10648(defun vhdl-speedbar-find-file (text token indent)
10649 "When user clicks on TEXT, load file with name and position in TOKEN."
10650 (if (not (car token))
10651 (error "Design unit does not exist")
10652 (speedbar-find-file-in-frame (car token))
10653 (goto-line (cdr token))
10654 (recenter)
10655 (vhdl-speedbar-update-current-unit t)
10656 (speedbar-set-timer speedbar-update-speed)
10657 (speedbar-maybee-jump-to-attached-frame)))
10658
10659(defun vhdl-speedbar-toggle-hierarchy ()
10660 "Toggle between hierarchy and file browsing mode."
d2ddb974 10661 (interactive)
5eabfe72
KH
10662 (if (not (boundp 'speedbar-mode-functions-list))
10663 (error "WARNING: Install included `speedbar.el' patch first")
10664 (if (equal speedbar-initial-expansion-list-name "vhdl hierarchy")
10665 (speedbar-change-initial-expansion-list "files")
10666 (speedbar-change-initial-expansion-list "vhdl hierarchy"))))
10667
10668(defun vhdl-speedbar-port-copy ()
10669 "Copy the port of the entity under the cursor."
10670 (interactive)
10671 (beginning-of-line)
10672 (if (re-search-forward "\\([0-9]\\)+:\\s-*\\[[-+?]\\] \\(\\(\\w\\|\\s_\\)+\\)"
10673 (save-excursion (end-of-line) (point)) t)
10674 (condition-case ()
10675 (let* ((indent (string-to-number (match-string 1)))
10676 (ent-name (match-string 2))
10677 (ent-alist (if (vhdl-speedbar-project-p)
10678 (aget vhdl-project-entity-alist vhdl-project)
10679 (aget vhdl-entity-alist
10680 (abbreviate-file-name
10681 (file-name-as-directory
10682 (speedbar-line-path indent))))))
10683 (ent-entry (aget ent-alist ent-name))
10684 (file-name (nth 0 ent-entry))
10685 opened)
10686 ;; open file
10687 (if (find-buffer-visiting file-name)
10688 (set-buffer (file-name-nondirectory file-name))
10689 (set-buffer (find-file-noselect file-name nil t))
10690 (modify-syntax-entry ?\- ". 12" (syntax-table))
10691 (modify-syntax-entry ?\n ">" (syntax-table))
10692 (modify-syntax-entry ?\^M ">" (syntax-table))
10693 (setq opened t))
10694 ;; scan port
10695 (goto-line (nth 1 ent-entry))
10696 (end-of-line)
10697 (vhdl-port-copy)
10698 ;; close file
10699 (when opened (kill-buffer (current-buffer))))
10700 (error (error "Port not scanned successfully")))
10701 (error "No entity on current line")))
10702
10703;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10704;; Fontification
10705
10706(defface vhdl-speedbar-entity-face
10707 '((((class color) (background light)) (:foreground "ForestGreen"))
10708 (((class color) (background dark)) (:foreground "PaleGreen")))
10709 "Face used for displaying entity names."
10710 :group 'speedbar-faces)
10711
10712(defface vhdl-speedbar-architecture-face
10713 '((((class color) (background light)) (:foreground "Blue"))
10714 (((class color) (background dark)) (:foreground "LightSkyBlue")))
10715 "Face used for displaying architecture names."
10716 :group 'speedbar-faces)
d2ddb974 10717
5eabfe72
KH
10718(defface vhdl-speedbar-configuration-face
10719 '((((class color) (background light)) (:foreground "DarkGoldenrod"))
10720 (((class color) (background dark)) (:foreground "Salmon")))
10721 "Face used for displaying configuration names."
10722 :group 'speedbar-faces)
10723
10724(defface vhdl-speedbar-package-face
10725 '((((class color) (background light)) (:foreground "Grey50"))
10726 (((class color) (background dark)) (:foreground "Grey80")))
10727 "Face used for displaying package names."
10728 :group 'speedbar-faces)
10729
10730(defface vhdl-speedbar-instantiation-face
10731 '((((class color) (background light)) (:foreground "Brown"))
10732 (((class color) (background dark)) (:foreground "Yellow")))
10733 "Face used for displaying instantiation names."
10734 :group 'speedbar-faces)
10735
10736(defface vhdl-speedbar-entity-selected-face
10737 '((((class color) (background light)) (:foreground "ForestGreen" :underline t))
10738 (((class color) (background dark)) (:foreground "PaleGreen" :underline t)))
10739 "Face used for displaying entity names."
10740 :group 'speedbar-faces)
10741
10742(defface vhdl-speedbar-architecture-selected-face
10743 '((((class color) (background light)) (:foreground "Blue" :underline t))
10744 (((class color) (background dark)) (:foreground "LightSkyBlue" :underline t)))
10745 "Face used for displaying architecture names."
10746 :group 'speedbar-faces)
10747
10748(defface vhdl-speedbar-configuration-selected-face
10749 '((((class color) (background light)) (:foreground "DarkGoldenrod" :underline t))
10750 (((class color) (background dark)) (:foreground "Salmon" :underline t)))
10751 "Face used for displaying configuration names."
10752 :group 'speedbar-faces)
10753
10754(defface vhdl-speedbar-package-selected-face
10755 '((((class color) (background light)) (:foreground "Grey50" :underline t))
10756 (((class color) (background dark)) (:foreground "Grey80" :underline t)))
10757 "Face used for displaying package names."
10758 :group 'speedbar-faces)
10759
10760(defface vhdl-speedbar-instantiation-selected-face
10761 '((((class color) (background light)) (:foreground "Brown" :underline t))
10762 (((class color) (background dark)) (:foreground "Yellow" :underline t)))
10763 "Face used for displaying instantiation names."
10764 :group 'speedbar-faces)
10765
10766
10767;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10768;;; Bug reports
10769;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
10770;; (using `reporter.el')
10771
d2ddb974
KH
10772(defconst vhdl-mode-help-address "vhdl-mode@geocities.com"
10773 "Address for VHDL Mode bug reports.")
10774
10775(defun vhdl-version ()
10776 "Echo the current version of VHDL Mode in the minibuffer."
10777 (interactive)
10778 (message "Using VHDL Mode version %s" vhdl-version)
10779 (vhdl-keep-region-active))
10780
10781;; get reporter-submit-bug-report when byte-compiling
5eabfe72
KH
10782(eval-when-compile
10783 (require 'reporter))
d2ddb974
KH
10784
10785(defun vhdl-submit-bug-report ()
10786 "Submit via mail a bug report on VHDL Mode."
10787 (interactive)
10788 ;; load in reporter
10789 (and
10790 (y-or-n-p "Do you want to submit a report on VHDL Mode? ")
10791 (require 'reporter)
10792 (reporter-submit-bug-report
10793 vhdl-mode-help-address
10794 (concat "VHDL Mode " vhdl-version)
10795 (list
10796 ;; report all important variables
d2ddb974
KH
10797 'vhdl-offsets-alist
10798 'vhdl-comment-only-line-offset
10799 'tab-width
10800 'vhdl-electric-mode
10801 'vhdl-stutter-mode
10802 'vhdl-indent-tabs-mode
5eabfe72
KH
10803 'vhdl-project-alist
10804 'vhdl-project
10805 'vhdl-compiler-alist
d2ddb974
KH
10806 'vhdl-compiler
10807 'vhdl-compiler-options
5eabfe72
KH
10808 'vhdl-standard
10809 'vhdl-basic-offset
d2ddb974
KH
10810 'vhdl-upper-case-keywords
10811 'vhdl-upper-case-types
10812 'vhdl-upper-case-attributes
10813 'vhdl-upper-case-enum-values
5eabfe72
KH
10814 'vhdl-upper-case-constants
10815 'vhdl-electric-keywords
10816 'vhdl-optional-labels
10817 'vhdl-insert-empty-lines
d2ddb974 10818 'vhdl-argument-list-indent
5eabfe72 10819 'vhdl-association-list-with-formals
d2ddb974 10820 'vhdl-conditions-in-parenthesis
d2ddb974
KH
10821 'vhdl-zero-string
10822 'vhdl-one-string
5eabfe72
KH
10823 'vhdl-file-header
10824 'vhdl-file-footer
10825 'vhdl-company-name
10826 'vhdl-platform-spec
10827 'vhdl-date-format
10828 'vhdl-modify-date-prefix-string
10829 'vhdl-modify-date-on-saving
10830 'vhdl-reset-kind
10831 'vhdl-reset-active-high
10832 'vhdl-clock-rising-edge
10833 'vhdl-clock-edge-condition
10834 'vhdl-clock-name
10835 'vhdl-reset-name
10836 'vhdl-model-alist
10837 'vhdl-include-port-comments
10838 'vhdl-include-direction-comments
10839 'vhdl-actual-port-name
10840 'vhdl-instance-name
10841 'vhdl-testbench-entity-name
10842 'vhdl-testbench-architecture-name
10843 'vhdl-testbench-dut-name
10844 'vhdl-testbench-entity-header
10845 'vhdl-testbench-architecture-header
10846 'vhdl-testbench-declarations
10847 'vhdl-testbench-statements
10848 'vhdl-testbench-initialize-signals
10849 'vhdl-testbench-create-files
d2ddb974
KH
10850 'vhdl-self-insert-comments
10851 'vhdl-prompt-for-comments
5eabfe72 10852 'vhdl-inline-comment-column
d2ddb974 10853 'vhdl-end-comment-column
5eabfe72
KH
10854 'vhdl-auto-align
10855 'vhdl-align-groups
d2ddb974 10856 'vhdl-highlight-keywords
5eabfe72
KH
10857 'vhdl-highlight-names
10858 'vhdl-highlight-special-words
10859 'vhdl-highlight-forbidden-words
10860 'vhdl-highlight-verilog-keywords
10861 'vhdl-highlight-translate-off
d2ddb974 10862 'vhdl-highlight-case-sensitive
5eabfe72
KH
10863 'vhdl-special-syntax-alist
10864 'vhdl-forbidden-words
10865 'vhdl-forbidden-syntax
10866 'vhdl-speedbar
10867 'vhdl-speedbar-show-hierarchy
10868 'vhdl-speedbar-hierarchy-indent
d2ddb974 10869 'vhdl-index-menu
5eabfe72 10870 'vhdl-source-file-menu
d2ddb974 10871 'vhdl-hideshow-menu
5eabfe72 10872 'vhdl-hide-all-init
d2ddb974 10873 'vhdl-print-two-column
5eabfe72 10874 'vhdl-print-customize-faces
d2ddb974 10875 'vhdl-intelligent-tab
5eabfe72 10876 'vhdl-word-completion-case-sensitive
d2ddb974
KH
10877 'vhdl-word-completion-in-minibuffer
10878 'vhdl-underscore-is-part-of-word
10879 'vhdl-mode-hook
5eabfe72 10880 'vhdl-startup-warnings)
d2ddb974
KH
10881 (function
10882 (lambda ()
10883 (insert
10884 (if vhdl-special-indent-hook
10885 (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
10886 "vhdl-special-indent-hook is set to '"
10887 (format "%s" vhdl-special-indent-hook)
10888 ".\nPerhaps this is your problem?\n"
10889 "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n")
5eabfe72 10890 "\n"))))
d2ddb974 10891 nil
5eabfe72 10892 "Dear VHDL Mode maintainers,")))
d2ddb974
KH
10893
10894
5eabfe72 10895;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d2ddb974
KH
10896
10897(provide 'vhdl-mode)
10898
10899;;; vhdl-mode.el ends here