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