Integrate adding files with the file manager
[anjuta-git-plugin.git] / tagmanager / verilog.c
blob44fc2131ceb6af0af423eec7e0b337008ac9f6d4
1 /*
2 * $Id$
3 *
4 * Copyright (c) 2003, Darren Hiebert
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
8 *
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/1995-fall/verilog-manual.html
14 * http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
15 * http://home.europa.com/~celiac/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 "debug.h"
28 #include "keyword.h"
29 #include "parse.h"
30 #include "read.h"
31 #include "vstring.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', "constant", "constants (define, parameter, specparam)" },
64 { TRUE, 'e', "event", "events" },
65 { TRUE, 'f', "function", "functions" },
66 { TRUE, 'm', "module", "modules" },
67 { TRUE, 'n', "net", "net data types" },
68 { TRUE, 'p', "port", "ports" },
69 { TRUE, 'r', "register", "register data types" },
70 { TRUE, 't', "task", "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 */
151 c = fileGetc ();
152 while (c != '*' && c != EOF);
153 if (c != EOF)
154 c = fileGetc ();
155 } while (c != '/' && c != EOF);
156 if (c != EOF)
157 c = ' '; /* comment equivalent to white space */
159 else
160 Ungetc = c2;
162 else if (c == '"') /* strip string contents */
164 int c2;
166 c2 = fileGetc ();
167 while (c2 != '"' && c2 != EOF);
168 c = '@';
170 if (c == EOF)
171 longjmp (Exception, (int) ExceptionEOF);
172 return c;
175 static boolean isIdentifierCharacter (const int c)
177 return (boolean)(isalnum (c) || c == '_' || c == '`');
180 static int skipWhite (int c)
182 while (isspace (c))
183 c = vGetc ();
184 return c;
187 static int skipPastMatch (const char *const pair)
189 const int begin = pair [0], end = pair [1];
190 int matchLevel = 1;
191 int c;
194 c = vGetc ();
195 if (c == begin)
196 ++matchLevel;
197 else if (c == end)
198 --matchLevel;
200 while (matchLevel > 0);
201 return vGetc ();
204 static boolean readIdentifier (vString *const name, int c)
206 vStringClear (name);
207 if (isIdentifierCharacter (c))
209 while (isIdentifierCharacter (c))
211 vStringPut (name, c);
212 c = vGetc ();
214 vUngetc (c);
215 vStringTerminate (name);
217 return (boolean)(name->length > 0);
220 static void tagNameList (const verilogKind kind, int c)
222 vString *name = vStringNew ();
223 boolean repeat;
224 Assert (isIdentifierCharacter (c));
227 repeat = FALSE;
228 if (isIdentifierCharacter (c))
230 readIdentifier (name, c);
231 makeSimpleTag (name, VerilogKinds, kind);
233 else
234 break;
235 c = skipWhite (vGetc ());
236 if (c == '[')
237 c = skipPastMatch ("[]");
238 c = skipWhite (c);
239 if (c == '=')
241 if (c == '{')
242 skipPastMatch ("{}");
243 else
246 c = vGetc ();
247 while (c != ',' && c != ';');
250 if (c == ',')
252 c = skipWhite (vGetc ());
253 repeat = TRUE;
255 else
256 repeat = FALSE;
257 } while (repeat);
258 vStringDelete (name);
259 vUngetc (c);
262 static void findTag (vString *const name)
264 const verilogKind kind = (verilogKind)
265 lookupKeyword (vStringValue (name), Lang_verilog);
266 if (kind != K_UNDEFINED)
268 int c = skipWhite (vGetc ());
270 /* Many keywords can have bit width.
271 * reg [3:0] net_name;
272 * inout [(`DBUSWIDTH-1):0] databus;
274 if (c == '(')
275 c = skipPastMatch ("()");
276 c = skipWhite (c);
277 if (c == '[')
278 c = skipPastMatch ("[]");
279 c = skipWhite (c);
280 if (c == '#')
282 c = vGetc ();
283 if (c == '(')
284 c = skipPastMatch ("()");
286 c = skipWhite (c);
287 if (isIdentifierCharacter (c))
288 tagNameList (kind, c);
292 static void findVerilogTags (void)
294 vString *const name = vStringNew ();
295 volatile boolean newStatement = TRUE;
296 volatile int c = '\0';
297 exception_t exception = (exception_t) setjmp (Exception);
299 if (exception == ExceptionNone) while (c != EOF)
301 c = vGetc ();
302 switch (c)
304 case ';':
305 case '\n':
306 newStatement = TRUE;
307 break;
309 case ' ':
310 case '\t':
311 break;
313 default:
314 if (newStatement && readIdentifier (name, c))
315 findTag (name);
316 newStatement = FALSE;
317 break;
320 vStringDelete (name);
323 extern parserDefinition* VerilogParser (void)
325 static const char *const extensions [] = { "v", NULL };
326 parserDefinition* def = parserNew ("Verilog");
327 def->kinds = VerilogKinds;
328 def->kindCount = KIND_COUNT (VerilogKinds);
329 def->extensions = extensions;
330 def->parser = findVerilogTags;
331 def->initialize = initialize;
332 return def;
335 /* vi:set tabstop=4 shiftwidth=4: */