1 /*
2 *   $Id: vhdl.c,v 1.0 2005/11/05
3 *
4 *   Copyright (c) 2005, Klaus Dannecker
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 Vhdl HDL
10 *   (Hardware Description Language).
11 *
12 */
13 
14 /*
15  *   INCLUDE FILES
16  */
17 #include "general.h"    /* must always come first */
18 
19 #include <string.h>
20 #include <setjmp.h>
21 
22 #include "debug.h"
23 #include "keyword.h"
24 #include "parse.h"
25 #include "read.h"
26 #include "routines.h"
27 #include "vstring.h"
28 
29 /*
30  *   DATA DECLARATIONS
31  */
32 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
33 
34 typedef enum {
35 	K_UNDEFINED = -1,
36 	K_CONSTANT,
37 	K_TYPE,
38 	K_VARIABLE,
39 	K_ATTRIBUTE,
40 	K_SIGNAL,
41 	K_FUNCTION,
42 	K_PROCEDURE,
43 	K_COMPONENT,
44 	K_PACKAGE,
45 	K_PROCESS,
46 	K_ENTITY,
47 	K_ARCHITECTURE,
48 	K_PORT,
49 	K_BLOCK,
50 	K_ALIAS
51 } vhdlKind;
52 
53 /*
54  *   DATA DEFINITIONS
55  */
56 static int Ungetc;
57 static int Lang_vhdl;
58 static jmp_buf Exception;
59 static vString* Name=NULL;
60 static vString* Lastname=NULL;
61 static vString* Keyword=NULL;
62 static vString* TagName=NULL;
63 
64 static kindDefinition VhdlKinds [] = {
65 	{ true, 'c', "variable",     "constants" },
66 	{ true, 't', "typedef",      "types" },
67 	{ true, 'v', "variable",     "variables" },
68 	{ true, 'a', "attribute",    "attributes" },
69 	{ true, 's', "variable",     "signals" },
70 	{ true, 'f', "function",     "functions" },
71 	{ true, 'p', "function",     "procedure" },
72 	{ true, 'k', "member",       "components" },
73 	{ true, 'l', "namespace",    "packages" },
74 	{ true, 'm', "member",       "process" },
75 	{ true, 'n', "class",        "entity" },
76 	{ true, 'o', "struct",       "architecture" },
77 	{ true, 'u', "port",         "ports" },
78 	{ true, 'b', "member",       "blocks" },
79 	{ true, 'A', "typedef",      "alias" }
80 };
81 
82 static keywordTable VhdlKeywordTable [] = {
83 	{ "constant",     K_CONSTANT },
84 	{ "variable",     K_VARIABLE },
85 	{ "type",         K_TYPE },
86 	{ "subtype",      K_TYPE },
87 	{ "signal",       K_SIGNAL },
88 	{ "function",     K_FUNCTION },
89 	{ "procedure",    K_PROCEDURE },
90 	{ "component",    K_COMPONENT },
91 	{ "package",      K_PACKAGE },
92 	{ "process",      K_PROCESS },
93 	{ "entity",       K_ENTITY },
94 	{ "architecture", K_ARCHITECTURE },
95 	{ "inout",        K_PORT },
96 	{ "in",           K_PORT },
97 	{ "out",          K_PORT },
98 	{ "block",        K_BLOCK },
99 	{ "alias",        K_ALIAS }
100 };
101 
102 
103 /*
104  *   FUNCTION DEFINITIONS
105  */
106 
initialize(const langType language)107 static void initialize (const langType language)
108 {
109 	Lang_vhdl = language;
110 }
111 
vUngetc(int c)112 static void vUngetc (int c)
113 {
114 	Assert (Ungetc == '\0');
115 	Ungetc = c;
116 }
117 
vGetc(void)118 static int vGetc (void)
119 {
120 	int c;
121 	if (Ungetc == '\0')
122 		c = getcFromInputFile ();
123 	else
124 	{
125 		c = Ungetc;
126 		Ungetc = '\0';
127 	}
128 	if (c == '-')
129 	{
130 		int c2 = getcFromInputFile ();
131 		if (c2 == EOF)
132 			longjmp (Exception, (int) ExceptionEOF);
133 		else if (c2 == '-')   /* strip comment until end-of-line */
134 		{
135 			do
136 				c = getcFromInputFile ();
137 			while (c != '\n'  &&  c != EOF);
138 		}
139 		else
140 			Ungetc = c2;
141 	}
142 	if (c == EOF)
143 		longjmp (Exception, (int) ExceptionEOF);
144 	return c;
145 }
146 
isIdentifierCharacter(const int c)147 static bool isIdentifierCharacter (const int c)
148 {
149 	return (bool)(isalnum (c)  ||  c == '_'  ||  c == '`');
150 }
151 
skipWhite(int c)152 static int skipWhite (int c)
153 {
154 	while (c==' ')
155 		c = vGetc ();
156 	return c;
157 }
158 
readIdentifier(vString * const name,int c)159 static bool readIdentifier (vString *const name, int c)
160 {
161 	vStringClear (name);
162 	if (isIdentifierCharacter (c))
163 	{
164 		while (isIdentifierCharacter (c))
165 		{
166 			vStringPut (name, c);
167 			c = vGetc ();
168 		}
169 		vUngetc (c);
170 	}
171 	return (bool)(name->length > 0);
172 }
173 
tagNameList(const vhdlKind kind,int c)174 static void tagNameList (const vhdlKind kind, int c)
175 {
176 	Assert (isIdentifierCharacter (c));
177 	if (isIdentifierCharacter (c))
178 	{
179 		readIdentifier (TagName, c);
180 		makeSimpleTag (TagName, kind);
181 	}
182 }
183 
findTag(vString * const name)184 static void findTag (vString *const name)
185 {
186 	int c = '\0';
187 	vhdlKind kind;
188 	vStringCopyToLower (Keyword, name);
189 	kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
190 	if (kind == K_UNDEFINED)
191 	{
192 		c = skipWhite (vGetc ());
193 		vStringCopyS(Lastname,vStringValue(name));
194 		if (c == ':')
195 		{
196 			c = skipWhite (vGetc ());
197 			if (isIdentifierCharacter (c))
198 			{
199 				readIdentifier (name, c);
200 				vStringCopyToLower (Keyword, name);
201 				lookupKeyword (vStringValue (Keyword), Lang_vhdl);
202 				kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
203 				if (kind == K_PROCESS || kind == K_BLOCK || kind == K_PORT)
204 				{
205 					makeSimpleTag (Lastname, kind);
206 				}
207 			}
208 		} else {
209 			vUngetc (c);
210 		}
211 	}
212 	else
213 	{
214 		if (kind == K_SIGNAL) {
215 			while (c!=':') {
216 				c = skipWhite (vGetc ());
217 				if (c==',')
218 					c = vGetc ();
219 				if (isIdentifierCharacter (c))
220 					tagNameList (kind, c);
221 				else
222 					break;
223 				c = vGetc ();
224 			}
225 		}
226 		else if (kind == K_PROCESS || kind == K_BLOCK) {
227 			vStringCopyS(TagName,"unnamed");
228 			makeSimpleTag (TagName, kind);
229 		} else {
230 			c = skipWhite (vGetc ());
231 			if (c=='\"')
232 				c = vGetc ();
233 			if (isIdentifierCharacter (c))
234 				tagNameList (kind, c);
235 		}
236 	}
237 }
238 
findVhdlTags(void)239 static void findVhdlTags (void)
240 {
241 	volatile bool newStatement = true;
242 	volatile int c = '\0';
243 	exception_t exception = (exception_t) setjmp (Exception);
244 	Name = vStringNew ();
245 	Lastname = vStringNew ();
246 	Keyword = vStringNew ();
247 	TagName = vStringNew ();
248 
249 	if (exception == ExceptionNone) while (c != EOF)
250 	{
251 		c = vGetc ();
252 		switch (c)
253 		{
254 			case ';':
255 			case '\n':
256 				newStatement = true;
257 				break;
258 
259 			case ' ':
260 			case '\t':
261 				break;
262 
263 			default:
264 				if (newStatement && readIdentifier (Name, c)) {
265 					findTag (Name);
266 				}
267 				newStatement = false;
268 				break;
269 		}
270 	}
271 	vStringDelete (Name);
272 	vStringDelete (Lastname);
273 	vStringDelete (Keyword);
274 	vStringDelete (TagName);
275 }
276 
VhdlParser(void)277 extern parserDefinition* VhdlParser (void)
278 {
279 	static const char *const extensions [] = { "vhdl", "vhd", NULL };
280 	parserDefinition* def = parserNew ("Vhdl");
281 	def->kindTable  = VhdlKinds;
282 	def->kindCount  = ARRAY_SIZE (VhdlKinds);
283 	def->extensions = extensions;
284 	def->parser     = findVhdlTags;
285 	def->initialize = initialize;
286 	def->keywordTable = VhdlKeywordTable;
287 	def->keywordCount = ARRAY_SIZE (VhdlKeywordTable);
288 	return def;
289 }
290