~ubuntu-branches/debian/sid/exuberant-ctags/sid

1 by Colin Watson
Import upstream version 5.5.4
1
/*
1.1.2 by Colin Watson
Import upstream version 5.7
2
*   $Id: verilog.c 573 2007-06-26 05:41:27Z elliotth $
1 by Colin Watson
Import upstream version 5.5.4
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).
11
* 
12
*   Language definition documents:
1.1.2 by Colin Watson
Import upstream version 5.7
13
*       http://www.eg.bucknell.edu/~cs320/verilog/verilog-manual.html
1.1.1 by Colin Watson
Import upstream version 5.6
14
*       http://www.sutherland-hdl.com/on-line_ref_guide/vlog_ref_top.html
1.1.2 by Colin Watson
Import upstream version 5.7
15
*       http://www.verilog.com/VerilogBNF.html
1.1.1 by Colin Watson
Import upstream version 5.6
16
*       http://eesun.free.fr/DOC/VERILOG/verilog_manual1.html
1 by Colin Watson
Import upstream version 5.5.4
17
*/
18
19
/*
20
 *   INCLUDE FILES
21
 */
1.1.1 by Colin Watson
Import upstream version 5.6
22
#include "general.h"  /* must always come first */
1 by Colin Watson
Import upstream version 5.5.4
23
24
#include <string.h>
25
#include <setjmp.h>
26
27
#include "debug.h"
1.1.2 by Colin Watson
Import upstream version 5.7
28
#include "get.h"
1 by Colin Watson
Import upstream version 5.5.4
29
#include "keyword.h"
30
#include "parse.h"
31
#include "read.h"
32
#include "vstring.h"
33
34
/*
35
 *   DATA DECLARATIONS
36
 */
37
typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
38
39
typedef enum {
1.1.1 by Colin Watson
Import upstream version 5.6
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
1 by Colin Watson
Import upstream version 5.5.4
49
} verilogKind;
50
51
typedef struct {
1.1.1 by Colin Watson
Import upstream version 5.6
52
	const char *keyword;
53
	verilogKind kind;
1 by Colin Watson
Import upstream version 5.5.4
54
} keywordAssoc;
55
56
/*
57
 *   DATA DEFINITIONS
58
 */
59
static int Ungetc;
60
static int Lang_verilog;
61
static jmp_buf Exception;
62
63
static kindOption VerilogKinds [] = {
64
 { TRUE, 'c', "constant",  "constants (define, parameter, specparam)" },
65
 { TRUE, 'e', "event",     "events" },
66
 { TRUE, 'f', "function",  "functions" },
67
 { TRUE, 'm', "module",    "modules" },
68
 { TRUE, 'n', "net",       "net data types" },
69
 { TRUE, 'p', "port",      "ports" },
70
 { TRUE, 'r', "register",  "register data types" },
71
 { TRUE, 't', "task",      "tasks" }
72
};
73
74
static keywordAssoc VerilogKeywordTable [] = {
1.1.1 by Colin Watson
Import upstream version 5.6
75
	{ "`define",   K_CONSTANT },
76
	{ "event",     K_EVENT },
77
	{ "function",  K_FUNCTION },
78
	{ "inout",     K_PORT },
79
	{ "input",     K_PORT },
80
	{ "integer",   K_REGISTER },
81
	{ "module",    K_MODULE },
82
	{ "output",    K_PORT },
83
	{ "parameter", K_CONSTANT },
84
	{ "real",      K_REGISTER },
85
	{ "realtime",  K_REGISTER },
86
	{ "reg",       K_REGISTER },
87
	{ "specparam", K_CONSTANT },
88
	{ "supply0",   K_NET },
89
	{ "supply1",   K_NET },
90
	{ "task",      K_TASK },
91
	{ "time",      K_REGISTER },
92
	{ "tri0",      K_NET },
93
	{ "tri1",      K_NET },
94
	{ "triand",    K_NET },
95
	{ "tri",       K_NET },
96
	{ "trior",     K_NET },
97
	{ "trireg",    K_NET },
98
	{ "wand",      K_NET },
99
	{ "wire",      K_NET },
100
	{ "wor",       K_NET }
1 by Colin Watson
Import upstream version 5.5.4
101
};
102
103
/*
104
 *   FUNCTION DEFINITIONS
105
 */
106
107
static void initialize (const langType language)
108
{
1.1.1 by Colin Watson
Import upstream version 5.6
109
	size_t i;
110
	const size_t count = 
111
			sizeof (VerilogKeywordTable) / sizeof (VerilogKeywordTable [0]);
112
	Lang_verilog = language;
113
	for (i = 0  ;  i < count  ;  ++i)
114
	{
115
		const keywordAssoc* const p = &VerilogKeywordTable [i];
116
		addKeyword (p->keyword, language, (int) p->kind);
117
	}
1 by Colin Watson
Import upstream version 5.5.4
118
}
119
120
static void vUngetc (int c)
121
{
1.1.1 by Colin Watson
Import upstream version 5.6
122
	Assert (Ungetc == '\0');
123
	Ungetc = c;
1 by Colin Watson
Import upstream version 5.5.4
124
}
125
126
static int vGetc (void)
127
{
1.1.1 by Colin Watson
Import upstream version 5.6
128
	int c;
129
	if (Ungetc == '\0')
1 by Colin Watson
Import upstream version 5.5.4
130
		c = fileGetc ();
1.1.1 by Colin Watson
Import upstream version 5.6
131
	else
132
	{
133
		c = Ungetc;
134
		Ungetc = '\0';
135
	}
136
	if (c == '/')
137
	{
138
		int c2 = fileGetc ();
139
		if (c2 == EOF)
140
			longjmp (Exception, (int) ExceptionEOF);
141
		else if (c2 == '/')  /* strip comment until end-of-line */
142
		{
143
			do
144
				c = fileGetc ();
145
			while (c != '\n'  &&  c != EOF);
146
		}
147
		else if (c2 == '*')  /* strip block comment */
148
		{
1.1.2 by Colin Watson
Import upstream version 5.7
149
			c = skipOverCComment();
1.1.1 by Colin Watson
Import upstream version 5.6
150
		}
151
		else
1.1.2 by Colin Watson
Import upstream version 5.7
152
		{
153
			fileUngetc (c2);
154
		}
1.1.1 by Colin Watson
Import upstream version 5.6
155
	}
156
	else if (c == '"')  /* strip string contents */
157
	{
158
		int c2;
1 by Colin Watson
Import upstream version 5.5.4
159
		do
1.1.1 by Colin Watson
Import upstream version 5.6
160
			c2 = fileGetc ();
161
		while (c2 != '"'  &&  c2 != EOF);
162
		c = '@';
1 by Colin Watson
Import upstream version 5.5.4
163
	}
1.1.1 by Colin Watson
Import upstream version 5.6
164
	if (c == EOF)
165
		longjmp (Exception, (int) ExceptionEOF);
166
	return c;
1 by Colin Watson
Import upstream version 5.5.4
167
}
168
169
static boolean isIdentifierCharacter (const int c)
170
{
1.1.1 by Colin Watson
Import upstream version 5.6
171
	return (boolean)(isalnum (c)  ||  c == '_'  ||  c == '`');
1 by Colin Watson
Import upstream version 5.5.4
172
}
173
174
static int skipWhite (int c)
175
{
1.1.1 by Colin Watson
Import upstream version 5.6
176
	while (isspace (c))
177
		c = vGetc ();
178
	return c;
1 by Colin Watson
Import upstream version 5.5.4
179
}
180
181
static int skipPastMatch (const char *const pair)
182
{
1.1.1 by Colin Watson
Import upstream version 5.6
183
	const int begin = pair [0], end = pair [1];
184
	int matchLevel = 1;
185
	int c;
186
	do
187
	{
188
		c = vGetc ();
189
		if (c == begin)
190
			++matchLevel;
191
		else if (c == end)
192
			--matchLevel;
193
	}
194
	while (matchLevel > 0);
195
	return vGetc ();
1 by Colin Watson
Import upstream version 5.5.4
196
}
197
198
static boolean readIdentifier (vString *const name, int c)
199
{
1.1.1 by Colin Watson
Import upstream version 5.6
200
	vStringClear (name);
201
	if (isIdentifierCharacter (c))
1 by Colin Watson
Import upstream version 5.5.4
202
	{
1.1.1 by Colin Watson
Import upstream version 5.6
203
		while (isIdentifierCharacter (c))
204
		{
205
			vStringPut (name, c);
206
			c = vGetc ();
207
		}
208
		vUngetc (c);
209
		vStringTerminate (name);
1 by Colin Watson
Import upstream version 5.5.4
210
	}
1.1.1 by Colin Watson
Import upstream version 5.6
211
	return (boolean)(name->length > 0);
212
}
213
214
static void tagNameList (const verilogKind kind, int c)
215
{
216
	vString *name = vStringNew ();
217
	boolean repeat;
218
	Assert (isIdentifierCharacter (c));
219
	do
220
	{ 
221
		repeat = FALSE;
222
		if (isIdentifierCharacter (c))
223
		{
224
			readIdentifier (name, c);
225
			makeSimpleTag (name, VerilogKinds, kind);
226
		}
227
		else
228
			break;
229
		c = skipWhite (vGetc ());
230
		if (c == '[')
231
			c = skipPastMatch ("[]");
232
		c = skipWhite (c);
233
		if (c == '=')
234
		{
235
			if (c == '{')
236
				skipPastMatch ("{}");
237
			else
238
			{
239
				do
240
					c = vGetc ();
241
				while (c != ','  &&  c != ';');
242
			}
243
		}
244
		if (c == ',')
245
		{
246
			c = skipWhite (vGetc ());
247
			repeat = TRUE;
248
		}
249
		else
250
			repeat = FALSE;
251
	} while (repeat);
252
	vStringDelete (name);
1 by Colin Watson
Import upstream version 5.5.4
253
	vUngetc (c);
254
}
255
256
static void findTag (vString *const name)
257
{
1.1.2 by Colin Watson
Import upstream version 5.7
258
	const verilogKind kind = (verilogKind) lookupKeyword (vStringValue (name), Lang_verilog);
259
	if (kind == K_CONSTANT && vStringItem (name, 0) == '`')
260
	{
261
		/* Bug #961001: Verilog compiler directives are line-based. */
262
		int c = skipWhite (vGetc ());
263
		readIdentifier (name, c);
264
		makeSimpleTag (name, VerilogKinds, kind);
265
		/* Skip the rest of the line. */
266
		do {
267
			c = vGetc();
268
		} while (c != '\n');
269
		vUngetc (c);
270
	}
271
	else if (kind != K_UNDEFINED)
1 by Colin Watson
Import upstream version 5.5.4
272
	{
1.1.1 by Colin Watson
Import upstream version 5.6
273
		int c = skipWhite (vGetc ());
274
275
		/* Many keywords can have bit width.
276
		*   reg [3:0] net_name;
277
		*   inout [(`DBUSWIDTH-1):0] databus;
278
		*/
279
		if (c == '(')
280
			c = skipPastMatch ("()");
281
		c = skipWhite (c);
282
		if (c == '[')
283
			c = skipPastMatch ("[]");
284
		c = skipWhite (c);
285
		if (c == '#')
286
		{
287
			c = vGetc ();
288
			if (c == '(')
289
				c = skipPastMatch ("()");
290
		}
291
		c = skipWhite (c);
292
		if (isIdentifierCharacter (c))
293
			tagNameList (kind, c);
1 by Colin Watson
Import upstream version 5.5.4
294
	}
295
}
296
297
static void findVerilogTags (void)
298
{
1.1.1 by Colin Watson
Import upstream version 5.6
299
	vString *const name = vStringNew ();
300
	volatile boolean newStatement = TRUE;
301
	volatile int c = '\0';
302
	exception_t exception = (exception_t) setjmp (Exception);
1 by Colin Watson
Import upstream version 5.5.4
303
1.1.1 by Colin Watson
Import upstream version 5.6
304
	if (exception == ExceptionNone) while (c != EOF)
1 by Colin Watson
Import upstream version 5.5.4
305
	{
1.1.1 by Colin Watson
Import upstream version 5.6
306
		c = vGetc ();
307
		switch (c)
308
		{
309
			case ';':
310
			case '\n':
311
				newStatement = TRUE;
312
				break;
313
314
			case ' ':
315
			case '\t':
316
				break;
317
318
			default:
319
				if (newStatement && readIdentifier (name, c))
320
					findTag (name);
321
				newStatement = FALSE;
322
				break;
323
		}
1 by Colin Watson
Import upstream version 5.5.4
324
	}
1.1.1 by Colin Watson
Import upstream version 5.6
325
	vStringDelete (name);
1 by Colin Watson
Import upstream version 5.5.4
326
}
327
328
extern parserDefinition* VerilogParser (void)
329
{
1.1.1 by Colin Watson
Import upstream version 5.6
330
	static const char *const extensions [] = { "v", NULL };
331
	parserDefinition* def = parserNew ("Verilog");
332
	def->kinds      = VerilogKinds;
333
	def->kindCount  = KIND_COUNT (VerilogKinds);
334
	def->extensions = extensions;
335
	def->parser     = findVerilogTags;
336
	def->initialize = initialize;
337
	return def;
1 by Colin Watson
Import upstream version 5.5.4
338
}
339
1.1.1 by Colin Watson
Import upstream version 5.6
340
/* vi:set tabstop=4 shiftwidth=4: */