Update for last 2 commits.
[geany-mirror.git] / tagmanager / verilog.c
blobc6ed0d752f5a974cb30cef07a0464d67ed4139d6
1 /*
2 * $Id$
4 * Copyright (c) 2003, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for generating tags for the Verilog HDL
10 * (Hardware Description Language).
12 * Language definition documents:
13 * http://www.eg.bucknell.edu/~cs320/verilog/verilog-manual.html
14 * http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
15 * http://www.verilog.com/VerilogBNF.html
16 * http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html
20 * INCLUDE FILES
22 #include "general.h" /* must always come first */
24 #include <string.h>
25 #include <setjmp.h>
27 #include "keyword.h"
28 #include "parse.h"
29 #include "read.h"
30 #include "vstring.h"
31 #include "get.h"
34 * DATA DECLARATIONS
36 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
38 typedef enum {
39 K_UNDEFINED = -1,
40 K_CONSTANT,
41 K_EVENT,
42 K_FUNCTION,
43 K_MODULE,
44 K_NET,
45 K_PORT,
46 K_REGISTER,
47 K_TASK
48 } verilogKind;
50 typedef struct {
51 const char *keyword;
52 verilogKind kind;
53 } keywordAssoc;
56 * DATA DEFINITIONS
58 static int Ungetc;
59 static int Lang_verilog;
60 static jmp_buf Exception;
62 static kindOption VerilogKinds [] = {
63 { TRUE, 'c', "variable", "constants (define, parameter, specparam)" },
64 { TRUE, 'e', "typedef", "events" },
65 { TRUE, 'f', "function", "functions" },
66 { TRUE, 'm', "class", "modules" },
67 { TRUE, 'n', "variable", "net data types" },
68 { TRUE, 'p', "variable", "ports" },
69 { TRUE, 'r', "variable", "register data types" },
70 { TRUE, 't', "function", "tasks" }
73 static keywordAssoc VerilogKeywordTable [] = {
74 { "`define", K_CONSTANT },
75 { "event", K_EVENT },
76 { "function", K_FUNCTION },
77 { "inout", K_PORT },
78 { "input", K_PORT },
79 { "integer", K_REGISTER },
80 { "module", K_MODULE },
81 { "output", K_PORT },
82 { "parameter", K_CONSTANT },
83 { "real", K_REGISTER },
84 { "realtime", K_REGISTER },
85 { "reg", K_REGISTER },
86 { "specparam", K_CONSTANT },
87 { "supply0", K_NET },
88 { "supply1", K_NET },
89 { "task", K_TASK },
90 { "time", K_REGISTER },
91 { "tri0", K_NET },
92 { "tri1", K_NET },
93 { "triand", K_NET },
94 { "tri", K_NET },
95 { "trior", K_NET },
96 { "trireg", K_NET },
97 { "wand", K_NET },
98 { "wire", K_NET },
99 { "wor", K_NET }
103 * FUNCTION DEFINITIONS
106 static void initialize (const langType language)
108 size_t i;
109 const size_t count =
110 sizeof (VerilogKeywordTable) / sizeof (VerilogKeywordTable [0]);
111 Lang_verilog = language;
112 for (i = 0 ; i < count ; ++i)
114 const keywordAssoc* const p = &VerilogKeywordTable [i];
115 addKeyword (p->keyword, language, (int) p->kind);
119 static void vUngetc (int c)
121 Assert (Ungetc == '\0');
122 Ungetc = c;
125 static int vGetc (void)
127 int c;
128 if (Ungetc == '\0')
129 c = fileGetc ();
130 else
132 c = Ungetc;
133 Ungetc = '\0';
135 if (c == '/')
137 int c2 = fileGetc ();
138 if (c2 == EOF)
139 longjmp (Exception, (int) ExceptionEOF);
140 else if (c2 == '/') /* strip comment until end-of-line */
143 c = fileGetc ();
144 while (c != '\n' && c != EOF);
146 else if (c2 == '*') /* strip block comment */
148 c = skipOverCComment();
150 else
152 fileUngetc (c2);
155 else if (c == '"') /* strip string contents */
157 int c2;
159 c2 = fileGetc ();
160 while (c2 != '"' && c2 != EOF);
161 c = '@';
163 if (c == EOF)
164 longjmp (Exception, (int) ExceptionEOF);
165 return c;
168 static boolean isIdentifierCharacter (const int c)
170 return (boolean)(isalnum (c) || c == '_' || c == '`');
173 static int skipWhite (int c)
175 while (isspace (c))
176 c = vGetc ();
177 return c;
180 static int skipPastMatch (const char *const pair)
182 const int begin = pair [0], end = pair [1];
183 int matchLevel = 1;
184 int c;
187 c = vGetc ();
188 if (c == begin)
189 ++matchLevel;
190 else if (c == end)
191 --matchLevel;
193 while (matchLevel > 0);
194 return vGetc ();
197 static boolean readIdentifier (vString *const name, int c)
199 vStringClear (name);
200 if (isIdentifierCharacter (c))
202 while (isIdentifierCharacter (c))
204 vStringPut (name, c);
205 c = vGetc ();
207 vUngetc (c);
208 vStringTerminate (name);
210 return (boolean)(name->length > 0);
213 static void tagNameList (const verilogKind kind, int c)
215 vString *name = vStringNew ();
216 boolean repeat;
217 Assert (isIdentifierCharacter (c));
220 repeat = FALSE;
221 if (isIdentifierCharacter (c))
223 readIdentifier (name, c);
224 makeSimpleTag (name, VerilogKinds, kind);
226 else
227 break;
228 c = skipWhite (vGetc ());
229 if (c == '[')
230 c = skipPastMatch ("[]");
231 c = skipWhite (c);
232 if (c == '=')
234 if (c == '{')
235 skipPastMatch ("{}");
236 else
239 c = vGetc ();
240 while (c != ',' && c != ';');
243 if (c == ',')
245 c = skipWhite (vGetc ());
246 repeat = TRUE;
248 else
249 repeat = FALSE;
250 } while (repeat);
251 vStringDelete (name);
252 vUngetc (c);
255 static void findTag (vString *const name)
257 const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
258 if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
260 /* Bug #961001: Verilog compiler directives are line-based. */
261 int c = skipWhite (vGetc ());
262 readIdentifier (name, c);
263 makeSimpleTag (name, VerilogKinds, kind);
264 /* Skip the rest of the line. */
265 do {
266 c = vGetc();
267 } while (c != '\n');
268 vUngetc (c);
270 else if (kind != K_UNDEFINED)
272 int c = skipWhite (vGetc ());
274 /* Many keywords can have bit width.
275 * reg [3:0] net_name;
276 * inout [(`DBUSWIDTH-1):0] databus;
278 if (c == '(')
279 c = skipPastMatch ("()");
280 c = skipWhite (c);
281 if (c == '[')
282 c = skipPastMatch ("[]");
283 c = skipWhite (c);
284 if (c == '#')
286 c = vGetc ();
287 if (c == '(')
288 c = skipPastMatch ("()");
290 c = skipWhite (c);
291 if (isIdentifierCharacter (c))
292 tagNameList (kind, c);
296 static void findVerilogTags (void)
298 vString *const name = vStringNew ();
299 volatile boolean newStatement = TRUE;
300 volatile int c = '\0';
301 exception_t exception = (exception_t) setjmp (Exception);
303 if (exception == ExceptionNone) while (c != EOF)
305 c = vGetc ();
306 switch (c)
308 case ';':
309 case '\n':
310 newStatement = TRUE;
311 break;
313 case ' ':
314 case '\t':
315 break;
317 default:
318 if (newStatement && readIdentifier (name, c))
319 findTag (name);
320 newStatement = FALSE;
321 break;
324 vStringDelete (name);
327 extern parserDefinition* VerilogParser (void)
329 static const char *const extensions [] = { "v", NULL };
330 parserDefinition* def = parserNew ("Verilog");
331 def->kinds = VerilogKinds;
332 def->kindCount = KIND_COUNT (VerilogKinds);
333 def->extensions = extensions;
334 def->parser = findVerilogTags;
335 def->initialize = initialize;
336 return def;
339 /* vi:set tabstop=4 shiftwidth=4: */