Merge pull request #482 from philippwiesemann/fix-typos-po-de
[geany-mirror.git] / tagmanager / ctags / verilog.c
blob498988905bf61201c90953cf26cd4ee338a22b73
1 /*
2 * Copyright (c) 2003, Darren Hiebert
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License.
7 * This module contains functions for generating tags for the Verilog HDL
8 * (Hardware Description Language).
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 "keyword.h"
26 #include "parse.h"
27 #include "read.h"
28 #include "vstring.h"
29 #include "get.h"
32 * DATA DECLARATIONS
34 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
36 typedef enum {
37 K_UNDEFINED = -1,
38 K_CONSTANT,
39 K_EVENT,
40 K_FUNCTION,
41 K_MODULE,
42 K_NET,
43 K_PORT,
44 K_REGISTER,
45 K_TASK
46 } verilogKind;
48 typedef struct {
49 const char *keyword;
50 verilogKind kind;
51 } keywordAssoc;
54 * DATA DEFINITIONS
56 static int Ungetc;
57 static int Lang_verilog;
58 static jmp_buf Exception;
60 static kindOption VerilogKinds [] = {
61 { TRUE, 'c', "variable", "constants (define, parameter, specparam)" },
62 { TRUE, 'e', "typedef", "events" },
63 { TRUE, 'f', "function", "functions" },
64 { TRUE, 'm', "class", "modules" },
65 { TRUE, 'n', "variable", "net data types" },
66 { TRUE, 'p', "variable", "ports" },
67 { TRUE, 'r', "variable", "register data types" },
68 { TRUE, 't', "function", "tasks" }
71 static keywordAssoc VerilogKeywordTable [] = {
72 { "`define", K_CONSTANT },
73 { "event", K_EVENT },
74 { "function", K_FUNCTION },
75 { "inout", K_PORT },
76 { "input", K_PORT },
77 { "integer", K_REGISTER },
78 { "module", K_MODULE },
79 { "output", K_PORT },
80 { "parameter", K_CONSTANT },
81 { "real", K_REGISTER },
82 { "realtime", K_REGISTER },
83 { "reg", K_REGISTER },
84 { "specparam", K_CONSTANT },
85 { "supply0", K_NET },
86 { "supply1", K_NET },
87 { "task", K_TASK },
88 { "time", K_REGISTER },
89 { "tri0", K_NET },
90 { "tri1", K_NET },
91 { "triand", K_NET },
92 { "tri", K_NET },
93 { "trior", K_NET },
94 { "trireg", K_NET },
95 { "wand", K_NET },
96 { "wire", K_NET },
97 { "wor", K_NET }
101 * FUNCTION DEFINITIONS
104 static void initialize (const langType language)
106 size_t i;
107 const size_t count =
108 sizeof (VerilogKeywordTable) / sizeof (VerilogKeywordTable [0]);
109 Lang_verilog = language;
110 for (i = 0 ; i < count ; ++i)
112 const keywordAssoc* const p = &VerilogKeywordTable [i];
113 addKeyword (p->keyword, language, (int) p->kind);
117 static void vUngetc (int c)
119 Assert (Ungetc == '\0');
120 Ungetc = c;
123 static int vGetc (void)
125 int c;
126 if (Ungetc == '\0')
127 c = fileGetc ();
128 else
130 c = Ungetc;
131 Ungetc = '\0';
133 if (c == '/')
135 int c2 = fileGetc ();
136 if (c2 == EOF)
137 longjmp (Exception, (int) ExceptionEOF);
138 else if (c2 == '/') /* strip comment until end-of-line */
141 c = fileGetc ();
142 while (c != '\n' && c != EOF);
144 else if (c2 == '*') /* strip block comment */
146 c = skipOverCComment();
148 else
150 fileUngetc (c2);
153 else if (c == '"') /* strip string contents */
155 int c2;
157 c2 = fileGetc ();
158 while (c2 != '"' && c2 != EOF);
159 c = '@';
161 if (c == EOF)
162 longjmp (Exception, (int) ExceptionEOF);
163 return c;
166 static boolean isIdentifierCharacter (const int c)
168 return (boolean)(isalnum (c) || c == '_' || c == '`');
171 static int skipWhite (int c)
173 while (isspace (c))
174 c = vGetc ();
175 return c;
178 static int skipPastMatch (const char *const pair)
180 const int begin = pair [0], end = pair [1];
181 int matchLevel = 1;
182 int c;
185 c = vGetc ();
186 if (c == begin)
187 ++matchLevel;
188 else if (c == end)
189 --matchLevel;
191 while (matchLevel > 0);
192 return vGetc ();
195 static boolean readIdentifier (vString *const name, int c)
197 vStringClear (name);
198 if (isIdentifierCharacter (c))
200 while (isIdentifierCharacter (c))
202 vStringPut (name, c);
203 c = vGetc ();
205 vUngetc (c);
206 vStringTerminate (name);
208 return (boolean)(name->length > 0);
211 static void tagNameList (const verilogKind kind, int c)
213 vString *name = vStringNew ();
214 boolean repeat;
215 Assert (isIdentifierCharacter (c));
218 repeat = FALSE;
219 if (isIdentifierCharacter (c))
221 readIdentifier (name, c);
222 makeSimpleTag (name, VerilogKinds, kind);
224 else
225 break;
226 c = skipWhite (vGetc ());
227 if (c == '[')
228 c = skipPastMatch ("[]");
229 c = skipWhite (c);
230 if (c == '=')
232 c = skipWhite (vGetc ());
233 if (c == '{')
234 skipPastMatch ("{}");
235 else
238 c = vGetc ();
239 while (c != ',' && c != ';');
242 if (c == ',')
244 c = skipWhite (vGetc ());
245 repeat = TRUE;
247 else
248 repeat = FALSE;
249 } while (repeat);
250 vStringDelete (name);
251 vUngetc (c);
254 static void findTag (vString *const name)
256 const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
257 if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
259 /* Bug #961001: Verilog compiler directives are line-based. */
260 int c = skipWhite (vGetc ());
261 readIdentifier (name, c);
262 makeSimpleTag (name, VerilogKinds, kind);
263 /* Skip the rest of the line. */
264 do {
265 c = vGetc();
266 } while (c != '\n');
267 vUngetc (c);
269 else if (kind != K_UNDEFINED)
271 int c = skipWhite (vGetc ());
273 /* Many keywords can have bit width.
274 * reg [3:0] net_name;
275 * inout [(`DBUSWIDTH-1):0] databus;
277 if (c == '(')
278 c = skipPastMatch ("()");
279 c = skipWhite (c);
280 if (c == '[')
281 c = skipPastMatch ("[]");
282 c = skipWhite (c);
283 if (c == '#')
285 c = vGetc ();
286 if (c == '(')
287 c = skipPastMatch ("()");
289 c = skipWhite (c);
290 if (isIdentifierCharacter (c))
291 tagNameList (kind, c);
295 static void findVerilogTags (void)
297 vString *const name = vStringNew ();
298 volatile boolean newStatement = TRUE;
299 volatile int c = '\0';
300 exception_t exception = (exception_t) setjmp (Exception);
302 if (exception == ExceptionNone) while (c != EOF)
304 c = vGetc ();
305 switch (c)
307 case ';':
308 case '\n':
309 newStatement = TRUE;
310 break;
312 case ' ':
313 case '\t':
314 break;
316 default:
317 if (newStatement && readIdentifier (name, c))
318 findTag (name);
319 newStatement = FALSE;
320 break;
323 vStringDelete (name);
326 extern parserDefinition* VerilogParser (void)
328 static const char *const extensions [] = { "v", NULL };
329 parserDefinition* def = parserNew ("Verilog");
330 def->kinds = VerilogKinds;
331 def->kindCount = KIND_COUNT (VerilogKinds);
332 def->extensions = extensions;
333 def->parser = findVerilogTags;
334 def->initialize = initialize;
335 return def;
338 /* vi:set tabstop=4 shiftwidth=4: */