Merge branch 'master' of github.com:geany/geany
[geany-mirror.git] / tagmanager / verilog.c
blobe836852caca5c64e5c923875866b4900f886e96f
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 if (c == '{')
233 skipPastMatch ("{}");
234 else
237 c = vGetc ();
238 while (c != ',' && c != ';');
241 if (c == ',')
243 c = skipWhite (vGetc ());
244 repeat = TRUE;
246 else
247 repeat = FALSE;
248 } while (repeat);
249 vStringDelete (name);
250 vUngetc (c);
253 static void findTag (vString *const name)
255 const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
256 if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
258 /* Bug #961001: Verilog compiler directives are line-based. */
259 int c = skipWhite (vGetc ());
260 readIdentifier (name, c);
261 makeSimpleTag (name, VerilogKinds, kind);
262 /* Skip the rest of the line. */
263 do {
264 c = vGetc();
265 } while (c != '\n');
266 vUngetc (c);
268 else if (kind != K_UNDEFINED)
270 int c = skipWhite (vGetc ());
272 /* Many keywords can have bit width.
273 * reg [3:0] net_name;
274 * inout [(`DBUSWIDTH-1):0] databus;
276 if (c == '(')
277 c = skipPastMatch ("()");
278 c = skipWhite (c);
279 if (c == '[')
280 c = skipPastMatch ("[]");
281 c = skipWhite (c);
282 if (c == '#')
284 c = vGetc ();
285 if (c == '(')
286 c = skipPastMatch ("()");
288 c = skipWhite (c);
289 if (isIdentifierCharacter (c))
290 tagNameList (kind, c);
294 static void findVerilogTags (void)
296 vString *const name = vStringNew ();
297 volatile boolean newStatement = TRUE;
298 volatile int c = '\0';
299 exception_t exception = (exception_t) setjmp (Exception);
301 if (exception == ExceptionNone) while (c != EOF)
303 c = vGetc ();
304 switch (c)
306 case ';':
307 case '\n':
308 newStatement = TRUE;
309 break;
311 case ' ':
312 case '\t':
313 break;
315 default:
316 if (newStatement && readIdentifier (name, c))
317 findTag (name);
318 newStatement = FALSE;
319 break;
322 vStringDelete (name);
325 extern parserDefinition* VerilogParser (void)
327 static const char *const extensions [] = { "v", NULL };
328 parserDefinition* def = parserNew ("Verilog");
329 def->kinds = VerilogKinds;
330 def->kindCount = KIND_COUNT (VerilogKinds);
331 def->extensions = extensions;
332 def->parser = findVerilogTags;
333 def->initialize = initialize;
334 return def;
337 /* vi:set tabstop=4 shiftwidth=4: */