ctags.rb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. data/Gemfile +2 -0
  2. data/Rakefile +23 -0
  3. data/ctags.rb.gemspec +23 -0
  4. data/ext/.gitignore +3 -0
  5. data/ext/extconf.rb +15 -0
  6. data/ext/vendor/exuberant-ctags/.gitignore +6 -0
  7. data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
  8. data/ext/vendor/exuberant-ctags/COPYING +340 -0
  9. data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
  10. data/ext/vendor/exuberant-ctags/FAQ +371 -0
  11. data/ext/vendor/exuberant-ctags/INSTALL +215 -0
  12. data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
  13. data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
  14. data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
  15. data/ext/vendor/exuberant-ctags/NEWS +871 -0
  16. data/ext/vendor/exuberant-ctags/README +73 -0
  17. data/ext/vendor/exuberant-ctags/ant.c +42 -0
  18. data/ext/vendor/exuberant-ctags/argproc.c +505 -0
  19. data/ext/vendor/exuberant-ctags/args.c +274 -0
  20. data/ext/vendor/exuberant-ctags/args.h +63 -0
  21. data/ext/vendor/exuberant-ctags/asm.c +387 -0
  22. data/ext/vendor/exuberant-ctags/asp.c +328 -0
  23. data/ext/vendor/exuberant-ctags/awk.c +81 -0
  24. data/ext/vendor/exuberant-ctags/basic.c +203 -0
  25. data/ext/vendor/exuberant-ctags/beta.c +321 -0
  26. data/ext/vendor/exuberant-ctags/c.c +2932 -0
  27. data/ext/vendor/exuberant-ctags/cobol.c +50 -0
  28. data/ext/vendor/exuberant-ctags/config.h.in +277 -0
  29. data/ext/vendor/exuberant-ctags/configure +7704 -0
  30. data/ext/vendor/exuberant-ctags/configure.ac +532 -0
  31. data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
  32. data/ext/vendor/exuberant-ctags/ctags.h +28 -0
  33. data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
  34. data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
  35. data/ext/vendor/exuberant-ctags/debug.c +113 -0
  36. data/ext/vendor/exuberant-ctags/debug.h +70 -0
  37. data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
  38. data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
  39. data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
  40. data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
  41. data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
  42. data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
  43. data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
  44. data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
  45. data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
  46. data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
  47. data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
  48. data/ext/vendor/exuberant-ctags/entry.c +847 -0
  49. data/ext/vendor/exuberant-ctags/entry.h +103 -0
  50. data/ext/vendor/exuberant-ctags/erlang.c +189 -0
  51. data/ext/vendor/exuberant-ctags/flex.c +2243 -0
  52. data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
  53. data/ext/vendor/exuberant-ctags/general.h +127 -0
  54. data/ext/vendor/exuberant-ctags/get.c +669 -0
  55. data/ext/vendor/exuberant-ctags/get.h +50 -0
  56. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
  57. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
  58. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
  59. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
  60. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
  61. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
  62. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
  63. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
  64. data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
  65. data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
  66. data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
  67. data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
  68. data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
  69. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
  70. data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
  71. data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
  72. data/ext/vendor/exuberant-ctags/html.c +49 -0
  73. data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
  74. data/ext/vendor/exuberant-ctags/keyword.c +258 -0
  75. data/ext/vendor/exuberant-ctags/keyword.h +34 -0
  76. data/ext/vendor/exuberant-ctags/lisp.c +139 -0
  77. data/ext/vendor/exuberant-ctags/lregex.c +704 -0
  78. data/ext/vendor/exuberant-ctags/lua.c +133 -0
  79. data/ext/vendor/exuberant-ctags/mac.c +273 -0
  80. data/ext/vendor/exuberant-ctags/magic.diff +21 -0
  81. data/ext/vendor/exuberant-ctags/main.c +584 -0
  82. data/ext/vendor/exuberant-ctags/main.h +32 -0
  83. data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
  84. data/ext/vendor/exuberant-ctags/make.c +217 -0
  85. data/ext/vendor/exuberant-ctags/matlab.c +44 -0
  86. data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
  87. data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
  88. data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
  89. data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
  90. data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
  91. data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
  92. data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
  93. data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
  94. data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
  95. data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
  96. data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
  97. data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
  98. data/ext/vendor/exuberant-ctags/options.c +1842 -0
  99. data/ext/vendor/exuberant-ctags/options.h +155 -0
  100. data/ext/vendor/exuberant-ctags/parse.c +677 -0
  101. data/ext/vendor/exuberant-ctags/parse.h +129 -0
  102. data/ext/vendor/exuberant-ctags/parsers.h +63 -0
  103. data/ext/vendor/exuberant-ctags/pascal.c +267 -0
  104. data/ext/vendor/exuberant-ctags/perl.c +382 -0
  105. data/ext/vendor/exuberant-ctags/php.c +237 -0
  106. data/ext/vendor/exuberant-ctags/python.c +771 -0
  107. data/ext/vendor/exuberant-ctags/qdos.c +106 -0
  108. data/ext/vendor/exuberant-ctags/read.c +569 -0
  109. data/ext/vendor/exuberant-ctags/read.h +116 -0
  110. data/ext/vendor/exuberant-ctags/readtags.c +959 -0
  111. data/ext/vendor/exuberant-ctags/readtags.h +252 -0
  112. data/ext/vendor/exuberant-ctags/rexx.c +39 -0
  113. data/ext/vendor/exuberant-ctags/routines.c +891 -0
  114. data/ext/vendor/exuberant-ctags/routines.h +134 -0
  115. data/ext/vendor/exuberant-ctags/ruby.c +408 -0
  116. data/ext/vendor/exuberant-ctags/scheme.c +111 -0
  117. data/ext/vendor/exuberant-ctags/sh.c +115 -0
  118. data/ext/vendor/exuberant-ctags/slang.c +41 -0
  119. data/ext/vendor/exuberant-ctags/sml.c +212 -0
  120. data/ext/vendor/exuberant-ctags/sort.c +230 -0
  121. data/ext/vendor/exuberant-ctags/sort.h +32 -0
  122. data/ext/vendor/exuberant-ctags/source.mak +122 -0
  123. data/ext/vendor/exuberant-ctags/sql.c +2112 -0
  124. data/ext/vendor/exuberant-ctags/strlist.c +281 -0
  125. data/ext/vendor/exuberant-ctags/strlist.h +54 -0
  126. data/ext/vendor/exuberant-ctags/tcl.c +116 -0
  127. data/ext/vendor/exuberant-ctags/tex.c +524 -0
  128. data/ext/vendor/exuberant-ctags/verilog.c +340 -0
  129. data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
  130. data/ext/vendor/exuberant-ctags/vim.c +636 -0
  131. data/ext/vendor/exuberant-ctags/vstring.c +232 -0
  132. data/ext/vendor/exuberant-ctags/vstring.h +85 -0
  133. data/ext/vendor/exuberant-ctags/yacc.c +40 -0
  134. data/lib/ctags/exuberant.rb +45 -0
  135. data/lib/ctags/version.rb +3 -0
  136. data/lib/ctags.rb +6 -0
  137. data/test/test_ctags.rb +24 -0
  138. metadata +233 -0
@@ -0,0 +1,835 @@
1
+ /*
2
+ * $Id: vhdl.c 652 2008-04-18 03:51:47Z elliotth $
3
+ *
4
+ * Copyright (c) 2008, Nicolas Vincent
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 VHDL files.
10
+ */
11
+
12
+ /*
13
+ * INCLUDE FILES
14
+ */
15
+ #include "general.h" /* must always come first */
16
+
17
+ #include <ctype.h> /* to define isalpha () */
18
+ #include <string.h>
19
+ #include <setjmp.h>
20
+
21
+ #include "debug.h"
22
+ #include "entry.h"
23
+ #include "keyword.h"
24
+ #include "parse.h"
25
+ #include "read.h"
26
+ #include "routines.h"
27
+ #include "vstring.h"
28
+
29
+ /*
30
+ * MACROS
31
+ */
32
+ #define isType(token,t) (boolean) ((token)->type == (t))
33
+ #define isKeyword(token,k) (boolean) ((token)->keyword == (k))
34
+
35
+ /*
36
+ * DATA DECLARATIONS
37
+ */
38
+ typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
39
+
40
+ /*
41
+ * Used to specify type of keyword.
42
+ */
43
+ typedef enum eKeywordId {
44
+ KEYWORD_NONE = -1,
45
+ KEYWORD_ABS,
46
+ KEYWORD_ACCESS,
47
+ KEYWORD_AFTER,
48
+ KEYWORD_ALIAS,
49
+ KEYWORD_ALL,
50
+ KEYWORD_AND,
51
+ KEYWORD_ARCHITECTURE,
52
+ KEYWORD_ARRAY,
53
+ KEYWORD_ASSERT,
54
+ KEYWORD_ATTRIBUTE,
55
+ KEYWORD_BEGIN,
56
+ KEYWORD_BLOCK,
57
+ KEYWORD_BODY,
58
+ KEYWORD_BUFFER,
59
+ KEYWORD_BUS,
60
+ KEYWORD_CASE,
61
+ KEYWORD_COMPONENT,
62
+ KEYWORD_CONFIGURATION,
63
+ KEYWORD_CONSTANT,
64
+ KEYWORD_DISCONNECT,
65
+ KEYWORD_DOWNTO,
66
+ KEYWORD_ELSE,
67
+ KEYWORD_ELSIF,
68
+ KEYWORD_END,
69
+ KEYWORD_ENTITY,
70
+ KEYWORD_EXIT,
71
+ KEYWORD_FILE,
72
+ KEYWORD_FOR,
73
+ KEYWORD_FUNCTION,
74
+ KEYWORD_GENERATE,
75
+ KEYWORD_GENERIC,
76
+ KEYWORD_GROUP,
77
+ KEYWORD_GUARDED,
78
+ KEYWORD_IF,
79
+ KEYWORD_IMPURE,
80
+ KEYWORD_IN,
81
+ KEYWORD_INERTIAL,
82
+ KEYWORD_INOUT,
83
+ KEYWORD_IS,
84
+ KEYWORD_LABEL,
85
+ KEYWORD_LIBRARY,
86
+ KEYWORD_LINKAGE,
87
+ KEYWORD_LITERAL,
88
+ KEYWORD_LOOP,
89
+ KEYWORD_MAP,
90
+ KEYWORD_MOD,
91
+ KEYWORD_NAND,
92
+ KEYWORD_NEW,
93
+ KEYWORD_NEXT,
94
+ KEYWORD_NOR,
95
+ KEYWORD_NOT,
96
+ KEYWORD_NULL,
97
+ KEYWORD_OF,
98
+ KEYWORD_ON,
99
+ KEYWORD_OPEN,
100
+ KEYWORD_OR,
101
+ KEYWORD_OTHERS,
102
+ KEYWORD_OUT,
103
+ KEYWORD_PACKAGE,
104
+ KEYWORD_PORT,
105
+ KEYWORD_POSTPONED,
106
+ KEYWORD_PROCEDURE,
107
+ KEYWORD_PROCESS,
108
+ KEYWORD_PURE,
109
+ KEYWORD_RANGE,
110
+ KEYWORD_RECORD,
111
+ KEYWORD_REGISTER,
112
+ KEYWORD_REJECT,
113
+ KEYWORD_RETURN,
114
+ KEYWORD_ROL,
115
+ KEYWORD_ROR,
116
+ KEYWORD_SELECT,
117
+ KEYWORD_SEVERITY,
118
+ KEYWORD_SIGNAL,
119
+ KEYWORD_SHARED,
120
+ KEYWORD_SLA,
121
+ KEYWORD_SLI,
122
+ KEYWORD_SRA,
123
+ KEYWORD_SRL,
124
+ KEYWORD_SUBTYPE,
125
+ KEYWORD_THEN,
126
+ KEYWORD_TO,
127
+ KEYWORD_TRANSPORT,
128
+ KEYWORD_TYPE,
129
+ KEYWORD_UNAFFECTED,
130
+ KEYWORD_UNITS,
131
+ KEYWORD_UNTIL,
132
+ KEYWORD_USE,
133
+ KEYWORD_VARIABLE,
134
+ KEYWORD_WAIT,
135
+ KEYWORD_WHEN,
136
+ KEYWORD_WHILE,
137
+ KEYWORD_WITH,
138
+ KEYWORD_XNOR,
139
+ KEYWORD_XOR
140
+ } keywordId;
141
+
142
+ /* Used to determine whether keyword is valid for the current language and
143
+ * what its ID is.
144
+ */
145
+ typedef struct sKeywordDesc {
146
+ const char *name;
147
+ keywordId id;
148
+ } keywordDesc;
149
+
150
+ typedef enum eTokenType {
151
+ TOKEN_NONE, /* none */
152
+ TOKEN_OPEN_PAREN, /* ( */
153
+ TOKEN_CLOSE_PAREN, /* ) */
154
+ TOKEN_COMMA, /* the comma character */
155
+ TOKEN_IDENTIFIER,
156
+ TOKEN_KEYWORD,
157
+ TOKEN_PERIOD, /* . */
158
+ TOKEN_OPERATOR,
159
+ TOKEN_SEMICOLON, /* the semicolon character */
160
+ TOKEN_STRING
161
+ } tokenType;
162
+
163
+ typedef struct sTokenInfo {
164
+ tokenType type;
165
+ keywordId keyword;
166
+ vString *string; /* the name of the token */
167
+ vString *scope;
168
+ unsigned long lineNumber; /* line number of tag */
169
+ fpos_t filePosition; /* file position of line containing name */
170
+ } tokenInfo;
171
+
172
+ /*
173
+ * DATA DEFINITIONS
174
+ */
175
+ static int Lang_vhdl;
176
+ static jmp_buf Exception;
177
+
178
+ /* Used to index into the VhdlKinds table. */
179
+ typedef enum {
180
+ VHDLTAG_UNDEFINED = -1,
181
+ VHDLTAG_CONSTANT,
182
+ VHDLTAG_TYPE,
183
+ VHDLTAG_SUBTYPE,
184
+ VHDLTAG_RECORD,
185
+ VHDLTAG_ENTITY,
186
+ VHDLTAG_COMPONENT,
187
+ VHDLTAG_PROTOTYPE,
188
+ VHDLTAG_FUNCTION,
189
+ VHDLTAG_PROCEDURE,
190
+ VHDLTAG_PACKAGE,
191
+ VHDLTAG_LOCAL
192
+ } vhdlKind;
193
+
194
+ static kindOption VhdlKinds[] = {
195
+ {TRUE, 'c', "constant", "constant declarations"},
196
+ {TRUE, 't', "type", "type definitions"},
197
+ {TRUE, 'T', "subtype", "subtype definitions"},
198
+ {TRUE, 'r', "record", "record names"},
199
+ {TRUE, 'e', "entity", "entity declarations"},
200
+ {FALSE, 'C', "component", "component declarations"},
201
+ {FALSE, 'd', "prototype", "prototypes"},
202
+ {TRUE, 'f', "function", "function prototypes and declarations"},
203
+ {TRUE, 'p', "procedure", "procedure prototypes and declarations"},
204
+ {TRUE, 'P', "package", "package definitions"},
205
+ {FALSE, 'l', "local", "local definitions"}
206
+ };
207
+
208
+ static keywordDesc VhdlKeywordTable[] = {
209
+ {"abs", KEYWORD_ABS},
210
+ {"access", KEYWORD_ACCESS},
211
+ {"after", KEYWORD_AFTER},
212
+ {"alias", KEYWORD_ALIAS},
213
+ {"all", KEYWORD_ALL},
214
+ {"and", KEYWORD_AND},
215
+ {"architecture", KEYWORD_ARCHITECTURE},
216
+ {"array", KEYWORD_ARRAY},
217
+ {"assert", KEYWORD_ASSERT},
218
+ {"attribute", KEYWORD_ATTRIBUTE},
219
+ {"begin", KEYWORD_BEGIN},
220
+ {"block", KEYWORD_BLOCK},
221
+ {"body", KEYWORD_BODY},
222
+ {"buffer", KEYWORD_BUFFER},
223
+ {"bus", KEYWORD_BUS},
224
+ {"case", KEYWORD_CASE},
225
+ {"component", KEYWORD_COMPONENT},
226
+ {"configuration", KEYWORD_CONFIGURATION},
227
+ {"constant", KEYWORD_CONSTANT},
228
+ {"disconnect", KEYWORD_DISCONNECT},
229
+ {"downto", KEYWORD_DOWNTO},
230
+ {"else", KEYWORD_ELSE},
231
+ {"elsif", KEYWORD_ELSIF},
232
+ {"end", KEYWORD_END},
233
+ {"entity", KEYWORD_ENTITY},
234
+ {"exit", KEYWORD_EXIT},
235
+ {"file", KEYWORD_FILE},
236
+ {"for", KEYWORD_FOR},
237
+ {"function", KEYWORD_FUNCTION},
238
+ {"generate", KEYWORD_GENERATE},
239
+ {"generic", KEYWORD_GENERIC},
240
+ {"group", KEYWORD_GROUP},
241
+ {"guarded", KEYWORD_GUARDED},
242
+ {"if", KEYWORD_IF},
243
+ {"impure", KEYWORD_IMPURE},
244
+ {"in", KEYWORD_IN},
245
+ {"inertial", KEYWORD_INERTIAL},
246
+ {"inout", KEYWORD_INOUT},
247
+ {"is", KEYWORD_IS},
248
+ {"label", KEYWORD_LABEL},
249
+ {"library", KEYWORD_LIBRARY},
250
+ {"linkage", KEYWORD_LINKAGE},
251
+ {"literal", KEYWORD_LITERAL},
252
+ {"loop", KEYWORD_LOOP},
253
+ {"map", KEYWORD_MAP},
254
+ {"mod", KEYWORD_MOD},
255
+ {"nand", KEYWORD_NAND},
256
+ {"new", KEYWORD_NEW},
257
+ {"next", KEYWORD_NEXT},
258
+ {"nor", KEYWORD_NOR},
259
+ {"not", KEYWORD_NOT},
260
+ {"null", KEYWORD_NULL},
261
+ {"of", KEYWORD_OF},
262
+ {"on", KEYWORD_ON},
263
+ {"open", KEYWORD_OPEN},
264
+ {"or", KEYWORD_OR},
265
+ {"others", KEYWORD_OTHERS},
266
+ {"out", KEYWORD_OUT},
267
+ {"package", KEYWORD_PACKAGE},
268
+ {"port", KEYWORD_PORT},
269
+ {"postponed", KEYWORD_POSTPONED},
270
+ {"procedure", KEYWORD_PROCEDURE},
271
+ {"process", KEYWORD_PROCESS},
272
+ {"pure", KEYWORD_PURE},
273
+ {"range", KEYWORD_RANGE},
274
+ {"record", KEYWORD_RECORD},
275
+ {"register", KEYWORD_REGISTER},
276
+ {"reject", KEYWORD_REJECT},
277
+ {"return", KEYWORD_RETURN},
278
+ {"rol", KEYWORD_ROL},
279
+ {"ror", KEYWORD_ROR},
280
+ {"select", KEYWORD_SELECT},
281
+ {"severity", KEYWORD_SEVERITY},
282
+ {"signal", KEYWORD_SIGNAL},
283
+ {"shared", KEYWORD_SHARED},
284
+ {"sla", KEYWORD_SLA},
285
+ {"sli", KEYWORD_SLI},
286
+ {"sra", KEYWORD_SRA},
287
+ {"srl", KEYWORD_SRL},
288
+ {"subtype", KEYWORD_SUBTYPE},
289
+ {"then", KEYWORD_THEN},
290
+ {"to", KEYWORD_TO},
291
+ {"transport", KEYWORD_TRANSPORT},
292
+ {"type", KEYWORD_TYPE},
293
+ {"unaffected", KEYWORD_UNAFFECTED},
294
+ {"units", KEYWORD_UNITS},
295
+ {"until", KEYWORD_UNTIL},
296
+ {"use", KEYWORD_USE},
297
+ {"variable", KEYWORD_VARIABLE},
298
+ {"wait", KEYWORD_WAIT},
299
+ {"when", KEYWORD_WHEN},
300
+ {"while", KEYWORD_WHILE},
301
+ {"with", KEYWORD_WITH},
302
+ {"xnor", KEYWORD_XNOR},
303
+ {"xor", KEYWORD_XOR}
304
+ };
305
+
306
+ /*
307
+ * FUNCTION DECLARATIONS
308
+ */
309
+ static void parseKeywords (tokenInfo * const token, boolean local);
310
+
311
+ /*
312
+ * FUNCTION DEFINITIONS
313
+ */
314
+
315
+ static boolean isIdentChar1 (const int c)
316
+ {
317
+ return (boolean) (isalpha (c) || c == '_');
318
+ }
319
+
320
+ static boolean isIdentChar (const int c)
321
+ {
322
+ return (boolean) (isalpha (c) || isdigit (c) || c == '_');
323
+ }
324
+
325
+ static boolean isIdentifierMatch (const tokenInfo * const token,
326
+ const vString * const name)
327
+ {
328
+ return (boolean) (isType (token, TOKEN_IDENTIFIER) &&
329
+ strcasecmp (vStringValue (token->string), vStringValue (name)) == 0);
330
+ /* XXX this is copy/paste from eiffel.c and slightly modified */
331
+ /* shouldn't we use strNcasecmp ? */
332
+ }
333
+
334
+ static boolean isKeywordOrIdent (const tokenInfo * const token,
335
+ const keywordId keyword, const vString * const name)
336
+ {
337
+ return (boolean) (isKeyword (token, keyword) ||
338
+ isIdentifierMatch (token, name));
339
+ }
340
+
341
+ static tokenInfo *newToken (void)
342
+ {
343
+ tokenInfo *const token = xMalloc (1, tokenInfo);
344
+ token->type = TOKEN_NONE;
345
+ token->keyword = KEYWORD_NONE;
346
+ token->string = vStringNew ();
347
+ token->scope = vStringNew ();
348
+ token->lineNumber = getSourceLineNumber ();
349
+ token->filePosition = getInputFilePosition ();
350
+ return token;
351
+ }
352
+
353
+ static void deleteToken (tokenInfo * const token)
354
+ {
355
+ if (token != NULL)
356
+ {
357
+ vStringDelete (token->string);
358
+ vStringDelete (token->scope);
359
+ eFree (token);
360
+ }
361
+ }
362
+
363
+ /*
364
+ * Parsing functions
365
+ */
366
+
367
+ static void parseString (vString * const string, const int delimiter)
368
+ {
369
+ boolean end = FALSE;
370
+ while (!end)
371
+ {
372
+ int c = fileGetc ();
373
+ if (c == EOF)
374
+ end = TRUE;
375
+ else if (c == '\\')
376
+ {
377
+ c = fileGetc (); /* This maybe a ' or ". */
378
+ vStringPut (string, c);
379
+ }
380
+ else if (c == delimiter)
381
+ end = TRUE;
382
+ else
383
+ vStringPut (string, c);
384
+ }
385
+ vStringTerminate (string);
386
+ }
387
+
388
+ /* Read a VHDL identifier beginning with "firstChar" and place it into "name".
389
+ */
390
+ static void parseIdentifier (vString * const string, const int firstChar)
391
+ {
392
+ int c = firstChar;
393
+ Assert (isIdentChar1 (c));
394
+ do
395
+ {
396
+ vStringPut (string, c);
397
+ c = fileGetc ();
398
+ } while (isIdentChar (c));
399
+ vStringTerminate (string);
400
+ if (!isspace (c))
401
+ fileUngetc (c); /* unget non-identifier character */
402
+ }
403
+
404
+ static void readToken (tokenInfo * const token)
405
+ {
406
+ int c;
407
+
408
+ token->type = TOKEN_NONE;
409
+ token->keyword = KEYWORD_NONE;
410
+ vStringClear (token->string);
411
+
412
+ getNextChar:
413
+ do
414
+ {
415
+ c = fileGetc ();
416
+ token->lineNumber = getSourceLineNumber ();
417
+ token->filePosition = getInputFilePosition ();
418
+ }
419
+ while (c == '\t' || c == ' ' || c == '\n');
420
+
421
+ switch (c)
422
+ {
423
+ case EOF:
424
+ longjmp (Exception, (int) ExceptionEOF);
425
+ break;
426
+ case '(':
427
+ token->type = TOKEN_OPEN_PAREN;
428
+ break;
429
+ case ')':
430
+ token->type = TOKEN_CLOSE_PAREN;
431
+ break;
432
+ case ';':
433
+ token->type = TOKEN_SEMICOLON;
434
+ break;
435
+ case '.':
436
+ token->type = TOKEN_PERIOD;
437
+ break;
438
+ case ',':
439
+ token->type = TOKEN_COMMA;
440
+ break;
441
+ case '\'': /* only single char are inside simple quotes */
442
+ break; /* or it is for attributes so we don't care */
443
+ case '"':
444
+ token->type = TOKEN_STRING;
445
+ parseString (token->string, c);
446
+ token->lineNumber = getSourceLineNumber ();
447
+ token->filePosition = getInputFilePosition ();
448
+ break;
449
+ case '-':
450
+ c = fileGetc ();
451
+ if (c == '-') /* start of a comment */
452
+ {
453
+ fileSkipToCharacter ('\n');
454
+ goto getNextChar;
455
+ }
456
+ else
457
+ {
458
+ if (!isspace (c))
459
+ fileUngetc (c);
460
+ token->type = TOKEN_OPERATOR;
461
+ }
462
+ break;
463
+ default:
464
+ if (!isIdentChar1 (c))
465
+ token->type = TOKEN_NONE;
466
+ else
467
+ {
468
+ parseIdentifier (token->string, c);
469
+ token->lineNumber = getSourceLineNumber ();
470
+ token->filePosition = getInputFilePosition ();
471
+ token->keyword = analyzeToken (token->string, Lang_vhdl);
472
+ if (isKeyword (token, KEYWORD_NONE))
473
+ token->type = TOKEN_IDENTIFIER;
474
+ else
475
+ token->type = TOKEN_KEYWORD;
476
+ }
477
+ break;
478
+ }
479
+ }
480
+
481
+ static void skipToKeyword (const keywordId keyword)
482
+ {
483
+ tokenInfo *const token = newToken ();
484
+ do
485
+ {
486
+ readToken (token);
487
+ }
488
+ while (!isKeyword (token, keyword));
489
+ deleteToken (token);
490
+ }
491
+
492
+ static void skipToMatched (tokenInfo * const token)
493
+ {
494
+ int nest_level = 0;
495
+ tokenType open_token;
496
+ tokenType close_token;
497
+
498
+ switch (token->type)
499
+ {
500
+ case TOKEN_OPEN_PAREN:
501
+ open_token = TOKEN_OPEN_PAREN;
502
+ close_token = TOKEN_CLOSE_PAREN;
503
+ break;
504
+ default:
505
+ return;
506
+ }
507
+
508
+ /*
509
+ * This routine will skip to a matching closing token.
510
+ * It will also handle nested tokens like the (, ) below.
511
+ * ( name varchar(30), text binary(10) )
512
+ */
513
+ if (isType (token, open_token))
514
+ {
515
+ nest_level++;
516
+ while (!(isType (token, close_token) && (nest_level == 0)))
517
+ {
518
+ readToken (token);
519
+ if (isType (token, open_token))
520
+ {
521
+ nest_level++;
522
+ }
523
+ if (isType (token, close_token))
524
+ {
525
+ if (nest_level > 0)
526
+ {
527
+ nest_level--;
528
+ }
529
+ }
530
+ }
531
+ readToken (token);
532
+ }
533
+ }
534
+
535
+ static void makeConstTag (tokenInfo * const token, const vhdlKind kind)
536
+ {
537
+ if (VhdlKinds[kind].enabled)
538
+ {
539
+ const char *const name = vStringValue (token->string);
540
+ tagEntryInfo e;
541
+ initTagEntry (&e, name);
542
+ e.lineNumber = token->lineNumber;
543
+ e.filePosition = token->filePosition;
544
+ e.kindName = VhdlKinds[kind].name;
545
+ e.kind = VhdlKinds[kind].letter;
546
+ makeTagEntry (&e);
547
+ }
548
+ }
549
+
550
+ static void makeVhdlTag (tokenInfo * const token, const vhdlKind kind)
551
+ {
552
+ if (VhdlKinds[kind].enabled)
553
+ {
554
+ /*
555
+ * If a scope has been added to the token, change the token
556
+ * string to include the scope when making the tag.
557
+ */
558
+ if (vStringLength (token->scope) > 0)
559
+ {
560
+ vString *fulltag = vStringNew ();
561
+ vStringCopy (fulltag, token->scope);
562
+ vStringCatS (fulltag, ".");
563
+ vStringCatS (fulltag, vStringValue (token->string));
564
+ vStringTerminate (fulltag);
565
+ vStringCopy (token->string, fulltag);
566
+ vStringDelete (fulltag);
567
+ }
568
+ makeConstTag (token, kind);
569
+ }
570
+ }
571
+
572
+ static void initialize (const langType language)
573
+ {
574
+ size_t i;
575
+ const size_t count =
576
+ sizeof (VhdlKeywordTable) / sizeof (VhdlKeywordTable[0]);
577
+ Lang_vhdl = language;
578
+ for (i = 0; i < count; ++i)
579
+ {
580
+ const keywordDesc *const p = &VhdlKeywordTable[i];
581
+ addKeyword (p->name, language, (int) p->id);
582
+ }
583
+ }
584
+
585
+ static void parsePackage (tokenInfo * const token)
586
+ {
587
+ tokenInfo *const name = newToken ();
588
+ Assert (isKeyword (token, KEYWORD_PACKAGE));
589
+ readToken (token);
590
+ if (isKeyword (token, KEYWORD_BODY))
591
+ {
592
+ readToken (name);
593
+ makeVhdlTag (name, VHDLTAG_PACKAGE);
594
+ }
595
+ else if (isType (token, TOKEN_IDENTIFIER))
596
+ {
597
+ makeVhdlTag (token, VHDLTAG_PACKAGE);
598
+ }
599
+ deleteToken (name);
600
+ }
601
+
602
+ static void parseModule (tokenInfo * const token)
603
+ {
604
+ tokenInfo *const name = newToken ();
605
+ const vhdlKind kind = isKeyword (token, KEYWORD_ENTITY) ?
606
+ VHDLTAG_ENTITY : VHDLTAG_COMPONENT;
607
+ Assert (isKeyword (token, KEYWORD_ENTITY) ||
608
+ isKeyword (token, KEYWORD_COMPONENT));
609
+ readToken (name);
610
+ if (kind == VHDLTAG_COMPONENT)
611
+ {
612
+ makeVhdlTag (name, VHDLTAG_COMPONENT);
613
+ skipToKeyword (KEYWORD_END);
614
+ fileSkipToCharacter (';');
615
+ }
616
+ else
617
+ {
618
+ readToken (token);
619
+ if (isKeyword (token, KEYWORD_IS))
620
+ {
621
+ makeVhdlTag (name, VHDLTAG_ENTITY);
622
+ skipToKeyword (KEYWORD_END);
623
+ fileSkipToCharacter (';');
624
+ }
625
+ }
626
+ deleteToken (name);
627
+ }
628
+
629
+ static void parseRecord (tokenInfo * const token)
630
+ {
631
+ tokenInfo *const name = newToken ();
632
+ Assert (isKeyword (token, KEYWORD_RECORD));
633
+ readToken (name);
634
+ do
635
+ {
636
+ readToken (token); /* should be a colon */
637
+ fileSkipToCharacter (';');
638
+ makeVhdlTag (name, VHDLTAG_RECORD);
639
+ readToken (name);
640
+ }
641
+ while (!isKeyword (name, KEYWORD_END));
642
+ fileSkipToCharacter (';');
643
+ deleteToken (name);
644
+ }
645
+
646
+ static void parseTypes (tokenInfo * const token)
647
+ {
648
+ tokenInfo *const name = newToken ();
649
+ const vhdlKind kind = isKeyword (token, KEYWORD_TYPE) ?
650
+ VHDLTAG_TYPE : VHDLTAG_SUBTYPE;
651
+ Assert (isKeyword (token, KEYWORD_TYPE) ||
652
+ isKeyword (token, KEYWORD_SUBTYPE));
653
+ readToken (name);
654
+ readToken (token);
655
+ if (isKeyword (token, KEYWORD_IS))
656
+ {
657
+ readToken (token); /* type */
658
+ if (isKeyword (token, KEYWORD_RECORD))
659
+ {
660
+ makeVhdlTag (name, kind);
661
+ /*TODO: make tags of the record's names */
662
+ parseRecord (token);
663
+ }
664
+ else
665
+ {
666
+ makeVhdlTag (name, kind);
667
+ }
668
+ }
669
+ deleteToken (name);
670
+ }
671
+
672
+ static void parseConstant (boolean local)
673
+ {
674
+ tokenInfo *const name = newToken ();
675
+ readToken (name);
676
+ if (local)
677
+ {
678
+ makeVhdlTag (name, VHDLTAG_LOCAL);
679
+ }
680
+ else
681
+ {
682
+ makeVhdlTag (name, VHDLTAG_CONSTANT);
683
+ }
684
+ fileSkipToCharacter (';');
685
+ deleteToken (name);
686
+ }
687
+
688
+ static void parseSubProgram (tokenInfo * const token)
689
+ {
690
+ tokenInfo *const name = newToken ();
691
+ boolean endSubProgram = FALSE;
692
+ const vhdlKind kind = isKeyword (token, KEYWORD_FUNCTION) ?
693
+ VHDLTAG_FUNCTION : VHDLTAG_PROCEDURE;
694
+ Assert (isKeyword (token, KEYWORD_FUNCTION) ||
695
+ isKeyword (token, KEYWORD_PROCEDURE));
696
+ readToken (name); /* the name of the function or procedure */
697
+ readToken (token);
698
+ if (isType (token, TOKEN_OPEN_PAREN))
699
+ {
700
+ skipToMatched (token);
701
+ }
702
+
703
+ if (kind == VHDLTAG_FUNCTION)
704
+ {
705
+ if (isKeyword (token, KEYWORD_RETURN))
706
+ {
707
+ /* Read datatype */
708
+ readToken (token);
709
+ while (! isKeyword (token, KEYWORD_IS) &&
710
+ ! isType (token, TOKEN_SEMICOLON))
711
+ {
712
+ readToken (token);
713
+ }
714
+ }
715
+ }
716
+
717
+ if (isType (token, TOKEN_SEMICOLON))
718
+ {
719
+ makeVhdlTag (name, VHDLTAG_PROTOTYPE);
720
+ }
721
+ else if (isKeyword (token, KEYWORD_IS))
722
+ {
723
+ if (kind == VHDLTAG_FUNCTION)
724
+ {
725
+ makeVhdlTag (name, VHDLTAG_FUNCTION);
726
+ do
727
+ {
728
+ readToken (token);
729
+ if (isKeyword (token, KEYWORD_END))
730
+ {
731
+ readToken (token);
732
+ endSubProgram = isKeywordOrIdent (token,
733
+ KEYWORD_FUNCTION, name->string);
734
+ fileSkipToCharacter (';');
735
+ }
736
+ else
737
+ {
738
+ parseKeywords (token, TRUE);
739
+ }
740
+ } while (!endSubProgram);
741
+ }
742
+ else
743
+ {
744
+ makeVhdlTag (name, VHDLTAG_PROCEDURE);
745
+ do
746
+ {
747
+ readToken (token);
748
+ if (isKeyword (token, KEYWORD_END))
749
+ {
750
+ readToken (token);
751
+ endSubProgram = isKeywordOrIdent (token,
752
+ KEYWORD_PROCEDURE, name->string);
753
+ fileSkipToCharacter (';');
754
+ }
755
+ else
756
+ {
757
+ parseKeywords (token, TRUE);
758
+ }
759
+ } while (!endSubProgram);
760
+ }
761
+ }
762
+ deleteToken (name);
763
+ }
764
+
765
+ /* TODO */
766
+ /* records */
767
+ static void parseKeywords (tokenInfo * const token, boolean local)
768
+ {
769
+ switch (token->keyword)
770
+ {
771
+ case KEYWORD_END:
772
+ fileSkipToCharacter (';');
773
+ break;
774
+ case KEYWORD_CONSTANT:
775
+ parseConstant (local);
776
+ break;
777
+ case KEYWORD_TYPE:
778
+ parseTypes (token);
779
+ break;
780
+ case KEYWORD_SUBTYPE:
781
+ parseTypes (token);
782
+ break;
783
+ case KEYWORD_ENTITY:
784
+ parseModule (token);
785
+ break;
786
+ case KEYWORD_COMPONENT:
787
+ parseModule (token);
788
+ break;
789
+ case KEYWORD_FUNCTION:
790
+ parseSubProgram (token);
791
+ break;
792
+ case KEYWORD_PROCEDURE:
793
+ parseSubProgram (token);
794
+ break;
795
+ case KEYWORD_PACKAGE:
796
+ parsePackage (token);
797
+ break;
798
+ default:
799
+ break;
800
+ }
801
+ }
802
+
803
+ static void parseVhdlFile (tokenInfo * const token)
804
+ {
805
+ do
806
+ {
807
+ readToken (token);
808
+ parseKeywords (token, FALSE);
809
+ } while (!isKeyword (token, KEYWORD_END));
810
+ }
811
+
812
+ static void findVhdlTags (void)
813
+ {
814
+ tokenInfo *const token = newToken ();
815
+ exception_t exception = (exception_t) (setjmp (Exception));
816
+
817
+ while (exception == ExceptionNone)
818
+ parseVhdlFile (token);
819
+
820
+ deleteToken (token);
821
+ }
822
+
823
+ extern parserDefinition *VhdlParser (void)
824
+ {
825
+ static const char *const extensions[] = { "vhdl", "vhd", NULL };
826
+ parserDefinition *def = parserNew ("VHDL");
827
+ def->kinds = VhdlKinds;
828
+ def->kindCount = KIND_COUNT (VhdlKinds);
829
+ def->extensions = extensions;
830
+ def->parser = findVhdlTags;
831
+ def->initialize = initialize;
832
+ return def;
833
+ }
834
+
835
+ /* vi:set tabstop=4 shiftwidth=4 noet: */