1%  VHDL mode		-* SLang -*-
2%
3% This is a simple vhdl mode. First it implements a highlighting scheme.
4%
5% modified by Thei Wijnen 22-nov-2001: added: xor xnor with after alias select
6% modified by Thei Wijnen 21-mar-2002: added: generate transport rising_edge falling_edge
7% Modified by Thei Wijnen 10-Aug-2003: implemented indentation style and folding.
8% Modified by Thei Wijnen 06-Jun-2004: indent region, added more keywords.
9% Modified by Thei Wijnen 03-Mar-2005: allow mixed case, added more keywords.
10%
11% Loading this file, then executing 'vhdl_mode' will start
12% VHDL mode on the current buffer.
13
14custom_variable ("VHDL_Comment_String", "--");
15custom_variable ("VHDL_Indent_Amount", 2);
16
17%
18% VHDL indent routine
19
20define vhdl_indent ()
21{
22  variable goal = 1;	        % start in column 1.
23  variable cs = CASE_SEARCH;
24  variable ch;
25
26  push_spot ();
27  push_spot ();
28  CASE_SEARCH = 0;	        % VHDL is not case sensitive
29
30  while (up_1 ())
31  {
32    bol_skip_white();
33    if (eolp() ) continue;
34
35    goal = what_column ();
36    if (goal == 1) continue;
37
38    if (looking_at("do ")
39        or looking_at("elsif ") or looking_at("elsif(")
40        or looking_at("else") )
41    {
42      goal += VHDL_Indent_Amount;
43    }
44    else if (looking_at("if ") or looking_at("if("))
45    {
46      if (ffind("then")) { goal += VHDL_Indent_Amount; }
47    }
48    else if (looking_at("for") or looking_at("for("))
49    {
50      if (ffind("loop")) goal += VHDL_Indent_Amount;
51    }
52    else if (looking_at("when"))
53    {
54      if (ffind("=>")) goal += VHDL_Indent_Amount;
55    }
56    else if (looking_at("case"))
57    {
58      if (ffind("is")) goal += VHDL_Indent_Amount;
59    }
60    else if (looking_at("begin"))
61    {
62      goal += VHDL_Indent_Amount;
63    }
64
65%    else if (looking_at("begin"))
66%    {
67%      push_spot ();
68%      while (up_1 ())
69%      {
70%        bol_skip_white();
71%        if (eolp() ) continue;
72%        if (looking_at("variable ") or looking_at("process") )
73%        {
74%          goal -= VHDL_Indent_Amount;
75%        }
76%        break;
77%      }
78%      pop_spot ();
79%    }
80
81    break;
82  }
83  pop_spot ();
84
85  % now check current line
86
87  bol_skip_white();
88%  if (looking_at("begin"))
89%    goal += VHDL_Indent_Amount;
90
91  if (looking_at("elsif")
92    or looking_at("else")
93    or looking_at("end")
94    or looking_at("when")
95%    or looking_at("end if")
96%    or looking_at("end process")
97%    or looking_at("end loop")
98      )
99  {
100    goal -= VHDL_Indent_Amount;
101  }
102
103  CASE_SEARCH = cs;		% done getting indent
104
105  bol_skip_white ();
106
107  ch = char(what_char());
108  switch (ch)
109%*     {
110%*	isdigit (ch) :		% label
111%*
112%*	if (what_column () >= 6)
113%*	  {
114%*	     bol_trim ();
115%*	     insert_single_space ();
116%*	  }
117%*	X_USER_BLOCK1 ();
118%*     }
119  {
120    not (bolp()) or eolp ():	% general case
121    bol_trim ();
122    goal--;
123    insert_spaces (goal);
124  }
125  pop_spot ();
126  skip_white ();
127}
128
129
130define vhdl_newline ()
131{
132  variable p, cont;
133
134  if (bolp ())
135  {
136    newline ();
137    return;
138  }
139
140  vhdl_indent ();
141  push_spot ();
142  bskip_white (); trim ();
143  pop_spot ();
144
145  newline ();
146  insert_single_space ();
147  vhdl_indent ();
148}
149
150
151%
152% Look for beginning of current subroutine/function
153
154define vhdl_beg_of_subprogram ()
155{
156  variable cs = CASE_SEARCH;
157
158  CASE_SEARCH = 0;
159  do
160  {
161    bol_skip_white ();
162    if (_get_point ())
163    {
164      if (looking_at ("process")
165        or looking_at ("switch")) break;
166    }
167  }
168  while (up_1 ());
169  CASE_SEARCH = cs;
170}
171
172%
173% Look for end of current subroutine/function
174
175define vhdl_end_of_subprogram ()
176{
177  variable cs = CASE_SEARCH;
178  CASE_SEARCH = 0;
179
180  do
181  {
182    bol_skip_white ();
183    if (looking_at ("end;")
184      or looking_at ("end process")) break;
185%	  {
186%	     go_right (3);
187%	     skip_white ();
188%	     if (eolp ()) break;
189%	  }
190  }
191  while (down_1 ());
192  CASE_SEARCH = cs;
193}
194
195define vhdl_mark_subprogram ()
196{
197  vhdl_end_of_subprogram ();
198  go_down_1 ();
199  set_mark_cmd ();
200  vhdl_beg_of_subprogram ();
201  bol ();
202}
203
204
205% Indent the selected region (bound to \e^i)
206
207define vhdl_indent_region ()
208{
209  check_region(1);
210  pop_mark_1 ();
211  push_mark();
212  vhdl_indent();        % set initial line indentation before narrowing
213  pop_spot();
214
215  push_spot();
216  go_up_1 ();
217  narrow();
218  bob();
219
220  flush("Indenting region...");
221  while (down_1 ()) {   % indent line by line (ie slowly)
222    vhdl_indent();
223    % flush(Sprintf("Indenting line %d", what_line(), 1));
224  }
225  flush("Indenting region... Done.");
226
227  widen();
228  pop_spot();
229}
230
231%
232% main entry point into the VHDL mode
233%
234% Set up syntax table
235
236$1 = "VHDL";
237
238create_syntax_table ($1);
239define_syntax ("--","",'%', $1);                % comments
240define_syntax ("([{", ")]}", '(', $1);          % parentheses
241define_syntax ('"', '"', $1);                   % quoted strings
242%define_syntax ('\'', '\'', $1);                 % quoted characters (paired ')
243define_syntax ('\'', '\\', $1);                 % continuations
244define_syntax ("0-9a-zA-Z_", 'w', $1);          % words
245define_syntax ("-+0-9a-fA-F.xXL", '0', $1);     % numbers
246define_syntax (",;.?:=<>", ',', $1);            % delimiters
247define_syntax ('#', '#', $1);                   % preprocessor
248define_syntax ("%-+/&*<>|!~^", '+', $1);        % operators
249set_syntax_flags ($1, 8);                       %
250
251% Type 0 keywords
252
253() = define_keywords ($1, "ifinisofonorto", 2);
254() = define_keywords ($1, "absandendformapmaxminmodnornotoutremrunusexor", 3);
255() = define_keywords ($1, "casebodyelsefileloopnandnextopenportpurethentypewaitwhenwithxnor", 4);
256() = define_keywords ($1, "afteraliasbeginelsifgroupinoutlabeltraceuntilwhile", 5);
257() = define_keywords ($1, "accessassertassignbufferdowntoentityimpureothersrecordrejectreportreturnselectsharedsignal", 6);
258() = define_keywords ($1, "genericguardedlibraryliteralpackageprocesssubtype", 7);
259() = define_keywords ($1, "constantfunctiongenerateinertialregisterseverityvariable", 8);
260() = define_keywords ($1, "attributecomponentpostponedproceduretransport", 9);
261() = define_keywords ($1, "architecture", 12);
262() = define_keywords ($1, "configuration", 13);
263
264% Type 1 keywords - use for operator like keywords
265() = define_keywords_n ($1, "eqgegtleltne", 2, 1);
266() = define_keywords_n ($1, "lowposslasllsrasrlval", 3, 1);
267() = define_keywords_n ($1, "basehighleftnotepredsucctrue", 4, 1);
268() = define_keywords_n ($1, "erroreventfalseimagequietrangerightvalue", 5, 1);
269() = define_keywords_n ($1, "activeleftoflengthstable", 6, 1);
270() = define_keywords_n ($1, "delayeddrivingfailurerightofwarning", 7, 1);
271() = define_keywords_n ($1, "ascendingdecending", 9, 1);
272() = define_keywords_n ($1, "last_eventlast_value", 10, 1);
273() = define_keywords_n ($1, "last_activerising_edgetransaction", 11, 1);
274() = define_keywords_n ($1, "falling_edge", 12, 1);
275() = define_keywords_n ($1, "driving_valuereverse_range", 13, 1);
276
277% Type 2 keywords - use for type declarator keywords
278() = define_keywords_n ($1, "msnspsus", 2, 2);
279() = define_keywords_n ($1, "linetime", 4, 2);
280() = define_keywords_n ($1, "string", 6, 2);
281() = define_keywords_n ($1, "booleanintegernatural", 7, 2);
282() = define_keywords_n ($1, "unsigned", 8, 2);
283() = define_keywords_n ($1, "characterstd_logic", 9, 2);
284() = define_keywords_n ($1, "std_logic_vector", 16, 2);
285
286% Set up syntax table
287
288$1 = "VHDL";
289!if (keymap_p ($1)) make_keymap ($1);
290
291definekey ("vhdl_beg_of_subprogram",	"\e^A",	$1);
292definekey ("vhdl_end_of_subprogram",	"\e^E",	$1);
293definekey ("vhdl_mark_subprogram",	"\e^H", $1);
294definekey ("vhdl_indent_region",	"\e^I", $1);
295
296%!%+
297%\function{vhdl_mode}
298%\synopsis{vhdl_mode}
299%\description
300% Mode designed for the purpose of editing VHDL files.
301% After the mode is loaded, the hook 'vhdl_hook' is called.
302% Useful functions include
303%
304%  Function:                    Default Binding:
305%   vhdl_beg_of_subprogram         ESC ^A
306%        moves cursor to beginning of current function/process
307%   vhdl_end_of_subprogram         ESC ^E
308%        moves cursor to end of current function/process
309%   vhdl_mark_subprogram           ESC ^H
310%        mark the current function/process
311%
312% Variables include:
313%   VHDL_Comment_String : string used by 'vhdl_comment' to
314%                         comment out a line.  Default is "--".
315%   VHDL_Indent_Amount  : number of spaces to indent statements in
316%                         a block.  The default is 2.
317%!%-
318
319define vhdl_mode ()
320{
321  variable mode = "VHDL";
322  set_mode (mode, 0x4 | 0x10);
323  use_keymap (mode);
324  use_syntax_table (mode);
325  set_syntax_flags (mode, 0x01);
326  set_buffer_hook ("indent_hook", "vhdl_indent");
327  set_buffer_hook ("newline_indent_hook", "vhdl_newline");
328  mode_set_mode_info (mode, "fold_info", "--{{{\r--}}}\r\r");
329  run_mode_hooks ("vhdl_mode_hook");
330}
331
332