manual: added documentation about replacement of 'untitled.ext' with filename (#1804)
[geany-mirror.git] / ctags / parsers / verilog.c
blob9fd826dc04254b0805fde1c319c40eba61490c7e
1 /*
2 * Copyright (c) 2003, Darren Hiebert
3 *
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
6 *
7 * This module contains functions for generating tags for the Verilog HDL
8 * (Hardware Description Language).
9 *
10 * Language definition documents:
11 * http://www.eg.bucknell.edu/~cs320/verilog/verilog-manual.html
12 * http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
13 * http://www.verilog.com/VerilogBNF.html
14 * http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html
18 * INCLUDE FILES
20 #include "general.h" /* must always come first */
22 #include <string.h>
23 #include <setjmp.h>
25 #include "debug.h"
26 #include "keyword.h"
27 #include "parse.h"
28 #include "read.h"
29 #include "vstring.h"
30 #include "lcpp.h"
31 #include "routines.h"
32 #include "xtag.h"
35 * DATA DECLARATIONS
37 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
39 typedef enum {
40 K_UNDEFINED = -1,
41 K_CONSTANT,
42 K_EVENT,
43 K_FUNCTION,
44 K_MODULE,
45 K_NET,
46 K_PORT,
47 K_REGISTER,
48 K_TASK
49 } verilogKind;
52 * DATA DEFINITIONS
54 static int Ungetc;
55 static int Lang_verilog;
56 static jmp_buf Exception;
58 static kindOption VerilogKinds [] = {
59 { true, 'c', "constant", "constants (define, parameter, specparam)" },
60 { true, 'e', "event", "events" },
61 { true, 'f', "function", "functions" },
62 { true, 'm', "module", "modules" },
63 { true, 'n', "net", "net data types" },
64 { true, 'p', "port", "ports" },
65 { true, 'r', "register", "register data types" },
66 { true, 't', "task", "tasks" }
69 static keywordTable VerilogKeywordTable [] = {
70 { "`define", K_CONSTANT },
71 { "event", K_EVENT },
72 { "function", K_FUNCTION },
73 { "inout", K_PORT },
74 { "input", K_PORT },
75 { "integer", K_REGISTER },
76 { "module", K_MODULE },
77 { "output", K_PORT },
78 { "parameter", K_CONSTANT },
79 { "real", K_REGISTER },
80 { "realtime", K_REGISTER },
81 { "reg", K_REGISTER },
82 { "specparam", K_CONSTANT },
83 { "supply0", K_NET },
84 { "supply1", K_NET },
85 { "task", K_TASK },
86 { "time", K_REGISTER },
87 { "tri0", K_NET },
88 { "tri1", K_NET },
89 { "triand", K_NET },
90 { "tri", K_NET },
91 { "trior", K_NET },
92 { "trireg", K_NET },
93 { "wand", K_NET },
94 { "wire", K_NET },
95 { "wor", K_NET }
99 * FUNCTION DEFINITIONS
102 static void initialize (const langType language)
104 size_t i;
105 const size_t count = ARRAY_SIZE (VerilogKeywordTable);
106 Lang_verilog = language;
107 for (i = 0 ; i < count ; ++i)
109 const keywordTable* const p = &VerilogKeywordTable [i];
110 addKeyword (p->name, language, (int) p->id);
114 static void vUngetc (int c)
116 Assert (Ungetc == '\0');
117 Ungetc = c;
120 static int vGetc (void)
122 int c;
123 if (Ungetc == '\0')
124 c = getcFromInputFile ();
125 else
127 c = Ungetc;
128 Ungetc = '\0';
130 if (c == '/')
132 int c2 = getcFromInputFile ();
133 if (c2 == EOF)
134 longjmp (Exception, (int) ExceptionEOF);
135 else if (c2 == '/') /* strip comment until end-of-line */
138 c = getcFromInputFile ();
139 while (c != '\n' && c != EOF);
141 else if (c2 == '*') /* strip block comment */
143 c = cppSkipOverCComment();
145 else
147 ungetcToInputFile (c2);
150 else if (c == '"') /* strip string contents */
152 int c2;
154 c2 = getcFromInputFile ();
155 while (c2 != '"' && c2 != EOF);
156 c = '@';
158 if (c == EOF)
159 longjmp (Exception, (int) ExceptionEOF);
160 return c;
163 static bool isIdentifierCharacter (const int c)
165 return (bool)(isalnum (c) || c == '_' || c == '`');
168 static int skipWhite (int c)
170 while (isspace (c))
171 c = vGetc ();
172 return c;
175 static int skipPastMatch (const char *const pair)
177 const int begin = pair [0], end = pair [1];
178 int matchLevel = 1;
179 int c;
182 c = vGetc ();
183 if (c == begin)
184 ++matchLevel;
185 else if (c == end)
186 --matchLevel;
188 while (matchLevel > 0);
189 return vGetc ();
192 static bool readIdentifier (vString *const name, int c)
194 vStringClear (name);
195 if (isIdentifierCharacter (c))
197 while (isIdentifierCharacter (c))
199 vStringPut (name, c);
200 c = vGetc ();
202 vUngetc (c);
204 return (bool)(name->length > 0);
207 static void tagNameList (const verilogKind kind, int c)
209 vString *name = vStringNew ();
210 bool repeat;
211 Assert (isIdentifierCharacter (c));
214 repeat = false;
215 if (isIdentifierCharacter (c))
217 readIdentifier (name, c);
218 makeSimpleTag (name, VerilogKinds, kind);
220 else
221 break;
222 c = skipWhite (vGetc ());
223 if (c == '[')
224 c = skipPastMatch ("[]");
225 c = skipWhite (c);
226 if (c == '=')
228 c = skipWhite (vGetc ());
229 if (c == '{')
230 skipPastMatch ("{}");
231 else
234 c = vGetc ();
235 while (c != ',' && c != ';');
238 if (c == ',')
240 c = skipWhite (vGetc ());
241 repeat = true;
243 else
244 repeat = false;
245 } while (repeat);
246 vStringDelete (name);
247 vUngetc (c);
250 static void findTag (vString *const name)
252 const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
253 if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
255 /* Bug #961001: Verilog compiler directives are line-based. */
256 int c = skipWhite (vGetc ());
257 readIdentifier (name, c);
258 makeSimpleTag (name, VerilogKinds, kind);
259 /* Skip the rest of the line. */
260 do {
261 c = vGetc();
262 } while (c != '\n');
263 vUngetc (c);
265 else if (kind != K_UNDEFINED)
267 int c = skipWhite (vGetc ());
269 /* Many keywords can have bit width.
270 * reg [3:0] net_name;
271 * inout [(`DBUSWIDTH-1):0] databus;
273 if (c == '(')
274 c = skipPastMatch ("()");
275 c = skipWhite (c);
276 if (c == '[')
277 c = skipPastMatch ("[]");
278 c = skipWhite (c);
279 if (c == '#')
281 c = vGetc ();
282 if (c == '(')
283 c = skipPastMatch ("()");
285 c = skipWhite (c);
286 if (isIdentifierCharacter (c))
287 tagNameList (kind, c);
291 static void findVerilogTags (void)
293 vString *const name = vStringNew ();
294 volatile bool newStatement = true;
295 volatile int c = '\0';
296 exception_t exception = (exception_t) setjmp (Exception);
298 if (exception == ExceptionNone) while (c != EOF)
300 c = vGetc ();
301 switch (c)
303 case ';':
304 case '\n':
305 newStatement = true;
306 break;
308 case ' ':
309 case '\t':
310 break;
312 default:
313 if (newStatement && readIdentifier (name, c))
314 findTag (name);
315 newStatement = false;
316 break;
319 vStringDelete (name);
322 extern parserDefinition* VerilogParser (void)
324 static const char *const extensions [] = { "v", NULL };
325 parserDefinition* def = parserNew ("Verilog");
326 def->kinds = VerilogKinds;
327 def->kindCount = ARRAY_SIZE (VerilogKinds);
328 def->extensions = extensions;
329 def->parser = findVerilogTags;
330 def->initialize = initialize;
331 return def;