Make parser includes closer to uctags and sync parser license header
[geany-mirror.git] / ctags / parsers / vhdl.c
blob9ede406b506d06423e6e773c1d387ac30259bae6
1 /*
2 * $Id: vhdl.c,v 1.0 2005/11/05
4 * Copyright (c) 2005, Klaus Dannecker
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for generating tags for the Vhdl HDL
10 * (Hardware Description Language).
15 * INCLUDE FILES
17 #include "general.h" /* must always come first */
19 #include <string.h>
20 #include <setjmp.h>
22 #include "debug.h"
23 #include "keyword.h"
24 #include "parse.h"
25 #include "read.h"
26 #include "routines.h"
27 #include "vstring.h"
30 * DATA DECLARATIONS
32 typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
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;
53 typedef struct {
54 const char *keyword;
55 vhdlKind kind;
56 } keywordAssoc;
59 * DATA DEFINITIONS
61 static int Ungetc;
62 static int Lang_vhdl;
63 static jmp_buf Exception;
64 static vString* Name=NULL;
65 static vString* Lastname=NULL;
66 static vString* Keyword=NULL;
67 static vString* TagName=NULL;
69 static kindOption VhdlKinds [] = {
70 { TRUE, 'c', "variable", "constants" },
71 { TRUE, 't', "typedef", "types" },
72 { TRUE, 'v', "variable", "variables" },
73 { TRUE, 'a', "attribute", "attributes" },
74 { TRUE, 's', "variable", "signals" },
75 { TRUE, 'f', "function", "functions" },
76 { TRUE, 'p', "function", "procedure" },
77 { TRUE, 'k', "member", "components" },
78 { TRUE, 'l', "namespace", "packages" },
79 { TRUE, 'm', "member", "process" },
80 { TRUE, 'n', "class", "entity" },
81 { TRUE, 'o', "struct", "architecture" },
82 { TRUE, 'u', "port", "ports" },
83 { TRUE, 'b', "member", "blocks" },
84 { TRUE, 'A', "typedef", "alias" }
87 static keywordAssoc VhdlKeywordTable [] = {
88 { "constant", K_CONSTANT },
89 { "variable", K_VARIABLE },
90 { "type", K_TYPE },
91 { "subtype", K_TYPE },
92 { "signal", K_SIGNAL },
93 { "function", K_FUNCTION },
94 { "procedure", K_PROCEDURE },
95 { "component", K_COMPONENT },
96 { "package", K_PACKAGE },
97 { "process", K_PROCESS },
98 { "entity", K_ENTITY },
99 { "architecture", K_ARCHITECTURE },
100 { "inout", K_PORT },
101 { "in", K_PORT },
102 { "out", K_PORT },
103 { "block", K_BLOCK },
104 { "alias", K_ALIAS }
109 * FUNCTION DEFINITIONS
112 static void initialize (const langType language)
114 size_t i;
115 const size_t count = sizeof (VhdlKeywordTable) /
116 sizeof (VhdlKeywordTable [0]);
117 Lang_vhdl = language;
118 for (i = 0 ; i < count ; ++i)
120 const keywordAssoc* const p = &VhdlKeywordTable [i];
121 addKeyword (p->keyword, language, (int) p->kind);
125 static void vUngetc (int c)
127 Assert (Ungetc == '\0');
128 Ungetc = c;
131 static int vGetc (void)
133 int c;
134 if (Ungetc == '\0')
135 c = fileGetc ();
136 else
138 c = Ungetc;
139 Ungetc = '\0';
141 if (c == '-')
143 int c2 = fileGetc ();
144 if (c2 == EOF)
145 longjmp (Exception, (int) ExceptionEOF);
146 else if (c2 == '-') /* strip comment until end-of-line */
149 c = fileGetc ();
150 while (c != '\n' && c != EOF);
152 else
153 Ungetc = c2;
155 if (c == EOF)
156 longjmp (Exception, (int) ExceptionEOF);
157 return c;
160 static boolean isIdentifierCharacter (const int c)
162 return (boolean)(isalnum (c) || c == '_' || c == '`');
165 static int skipWhite (int c)
167 while (c==' ')
168 c = vGetc ();
169 return c;
172 static boolean readIdentifier (vString *const name, int c)
174 vStringClear (name);
175 if (isIdentifierCharacter (c))
177 while (isIdentifierCharacter (c))
179 vStringPut (name, c);
180 c = vGetc ();
182 vUngetc (c);
183 vStringTerminate (name);
185 return (boolean)(name->length > 0);
188 static void tagNameList (const vhdlKind kind, int c)
190 Assert (isIdentifierCharacter (c));
191 if (isIdentifierCharacter (c))
193 readIdentifier (TagName, c);
194 makeSimpleTag (TagName, VhdlKinds, kind);
198 static void findTag (vString *const name)
200 int c = '\0';
201 vhdlKind kind;
202 vStringCopyToLower (Keyword, name);
203 kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
204 if (kind == K_UNDEFINED)
206 c = skipWhite (vGetc ());
207 vStringCopyS(Lastname,vStringValue(name));
208 if (c == ':')
210 c = skipWhite (vGetc ());
211 if (isIdentifierCharacter (c))
213 readIdentifier (name, c);
214 vStringCopyToLower (Keyword, name);
215 lookupKeyword (vStringValue (Keyword), Lang_vhdl);
216 kind = (vhdlKind)lookupKeyword (vStringValue (Keyword), Lang_vhdl);
217 if (kind == K_PROCESS || kind == K_BLOCK || kind == K_PORT)
219 makeSimpleTag (Lastname, VhdlKinds, kind);
222 } else {
223 vUngetc (c);
226 else
228 if (kind == K_SIGNAL) {
229 while (c!=':') {
230 c = skipWhite (vGetc ());
231 if (c==',')
232 c = vGetc ();
233 if (isIdentifierCharacter (c))
234 tagNameList (kind, c);
235 else
236 break;
237 c = vGetc ();
240 else if (kind == K_PROCESS || kind == K_BLOCK) {
241 vStringCopyS(TagName,"unnamed");
242 makeSimpleTag (TagName, VhdlKinds, kind);
243 } else {
244 c = skipWhite (vGetc ());
245 if (c=='\"')
246 c = vGetc ();
247 if (isIdentifierCharacter (c))
248 tagNameList (kind, c);
253 static void findVhdlTags (void)
255 volatile boolean newStatement = TRUE;
256 volatile int c = '\0';
257 exception_t exception = (exception_t) setjmp (Exception);
258 Name = vStringNew ();
259 Lastname = vStringNew ();
260 Keyword = vStringNew ();
261 TagName = vStringNew ();
263 if (exception == ExceptionNone) while (c != EOF)
265 c = vGetc ();
266 switch (c)
268 case ';':
269 case '\n':
270 newStatement = TRUE;
271 break;
273 case ' ':
274 case '\t':
275 break;
277 default:
278 if (newStatement && readIdentifier (Name, c)) {
279 findTag (Name);
281 newStatement = FALSE;
282 break;
285 vStringDelete (Name);
286 vStringDelete (Lastname);
287 vStringDelete (Keyword);
288 vStringDelete (TagName);
291 extern parserDefinition* VhdlParser (void)
293 static const char *const extensions [] = { "vhdl", "vhd", NULL };
294 parserDefinition* def = parserNew ("Vhdl");
295 def->kinds = VhdlKinds;
296 def->kindCount = KIND_COUNT (VhdlKinds);
297 def->extensions = extensions;
298 def->parser = findVhdlTags;
299 def->initialize = initialize;
300 return def;
303 /* vi:set tabstop=8 shiftwidth=4: */