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,1352 @@
1
+ /*
2
+ * $Id: eiffel.c 706 2009-06-28 23:09:30Z dhiebert $
3
+ *
4
+ * Copyright (c) 1998-2002, 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 Eiffel language
10
+ * files.
11
+ */
12
+
13
+ /*
14
+ * INCLUDE FILES
15
+ */
16
+ #include "general.h" /* must always come first */
17
+
18
+ #ifdef TYPE_REFERENCE_TOOL
19
+ #include <stdio.h>
20
+ #endif
21
+ #include <string.h>
22
+ #include <limits.h>
23
+ #include <ctype.h> /* to define tolower () */
24
+ #include <setjmp.h>
25
+
26
+ #include "debug.h"
27
+ #include "keyword.h"
28
+ #include "routines.h"
29
+ #include "vstring.h"
30
+ #ifndef TYPE_REFERENCE_TOOL
31
+ #include "entry.h"
32
+ #include "options.h"
33
+ #include "parse.h"
34
+ #include "read.h"
35
+ #endif
36
+
37
+ /*
38
+ * MACROS
39
+ */
40
+ #define isident(c) (isalnum(c) || (c) == '_')
41
+ #define isFreeOperatorChar(c) ((c) == '@' || (c) == '#' || \
42
+ (c) == '|' || (c) == '&')
43
+ #define isType(token,t) (boolean) ((token)->type == (t))
44
+ #define isKeyword(token,k) (boolean) ((token)->keyword == (k))
45
+
46
+ /*
47
+ * DATA DECLARATIONS
48
+ */
49
+
50
+ typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
51
+
52
+ /* Used to specify type of keyword.
53
+ */
54
+ typedef enum eKeywordId {
55
+ KEYWORD_NONE = -1,
56
+ KEYWORD_alias, KEYWORD_all, KEYWORD_and, KEYWORD_as, KEYWORD_assign,
57
+ KEYWORD_check, KEYWORD_class, KEYWORD_convert, KEYWORD_create,
58
+ KEYWORD_creation, KEYWORD_Current,
59
+ KEYWORD_debug, KEYWORD_deferred, KEYWORD_do, KEYWORD_else,
60
+ KEYWORD_elseif, KEYWORD_end, KEYWORD_ensure, KEYWORD_expanded,
61
+ KEYWORD_export, KEYWORD_external, KEYWORD_false, KEYWORD_feature,
62
+ KEYWORD_from, KEYWORD_frozen, KEYWORD_if, KEYWORD_implies,
63
+ KEYWORD_indexing, KEYWORD_infix, KEYWORD_inherit, KEYWORD_inspect,
64
+ KEYWORD_invariant, KEYWORD_is, KEYWORD_like, KEYWORD_local,
65
+ KEYWORD_loop, KEYWORD_not, KEYWORD_obsolete, KEYWORD_old, KEYWORD_once,
66
+ KEYWORD_or, KEYWORD_prefix, KEYWORD_redefine, KEYWORD_rename,
67
+ KEYWORD_require, KEYWORD_rescue, KEYWORD_Result, KEYWORD_retry,
68
+ KEYWORD_select, KEYWORD_separate, KEYWORD_strip, KEYWORD_then,
69
+ KEYWORD_true, KEYWORD_undefine, KEYWORD_unique, KEYWORD_until,
70
+ KEYWORD_variant, KEYWORD_when, KEYWORD_xor
71
+ } keywordId;
72
+
73
+ /* Used to determine whether keyword is valid for the token language and
74
+ * what its ID is.
75
+ */
76
+ typedef struct sKeywordDesc {
77
+ const char *name;
78
+ keywordId id;
79
+ } keywordDesc;
80
+
81
+ typedef enum eTokenType {
82
+ TOKEN_UNDEFINED,
83
+ TOKEN_BANG,
84
+ TOKEN_CHARACTER,
85
+ TOKEN_CLOSE_BRACE,
86
+ TOKEN_CLOSE_BRACKET,
87
+ TOKEN_CLOSE_PAREN,
88
+ TOKEN_COLON,
89
+ TOKEN_COMMA,
90
+ TOKEN_CONSTRAINT,
91
+ TOKEN_DOT,
92
+ TOKEN_DOLLAR,
93
+ TOKEN_IDENTIFIER,
94
+ TOKEN_KEYWORD,
95
+ TOKEN_NUMERIC,
96
+ TOKEN_OPEN_BRACE,
97
+ TOKEN_OPEN_BRACKET,
98
+ TOKEN_OPEN_PAREN,
99
+ TOKEN_OPERATOR,
100
+ TOKEN_OTHER,
101
+ TOKEN_QUESTION,
102
+ TOKEN_SEMICOLON,
103
+ TOKEN_SEPARATOR,
104
+ TOKEN_STRING,
105
+ TOKEN_TILDE
106
+ } tokenType;
107
+
108
+ typedef struct sTokenInfo {
109
+ tokenType type;
110
+ keywordId keyword;
111
+ boolean isExported;
112
+ vString* string;
113
+ vString* className;
114
+ vString* featureName;
115
+ } tokenInfo;
116
+
117
+ /*
118
+ * DATA DEFINITIONS
119
+ */
120
+
121
+ static langType Lang_eiffel;
122
+
123
+ #ifdef TYPE_REFERENCE_TOOL
124
+
125
+ static const char *FileName;
126
+ static FILE *File;
127
+ static int PrintClass;
128
+ static int PrintReferences;
129
+ static int SelfReferences;
130
+ static int Debug;
131
+ static stringList *GenericNames;
132
+ static stringList *ReferencedTypes;
133
+
134
+ #else
135
+
136
+ typedef enum {
137
+ EKIND_CLASS, EKIND_FEATURE, EKIND_LOCAL, EKIND_QUALIFIED_TAGS
138
+ } eiffelKind;
139
+
140
+ static kindOption EiffelKinds [] = {
141
+ { TRUE, 'c', "class", "classes"},
142
+ { TRUE, 'f', "feature", "features"},
143
+ { FALSE, 'l', "local", "local entities"}
144
+ };
145
+
146
+ #endif
147
+
148
+ static jmp_buf Exception;
149
+
150
+ static const keywordDesc EiffelKeywordTable [] = {
151
+ /* keyword keyword ID */
152
+ { "alias", KEYWORD_alias },
153
+ { "all", KEYWORD_all },
154
+ { "and", KEYWORD_and },
155
+ { "as", KEYWORD_as },
156
+ { "assign", KEYWORD_assign },
157
+ { "check", KEYWORD_check },
158
+ { "class", KEYWORD_class },
159
+ { "convert", KEYWORD_convert },
160
+ { "create", KEYWORD_create },
161
+ { "creation", KEYWORD_creation },
162
+ { "current", KEYWORD_Current },
163
+ { "debug", KEYWORD_debug },
164
+ { "deferred", KEYWORD_deferred },
165
+ { "do", KEYWORD_do },
166
+ { "else", KEYWORD_else },
167
+ { "elseif", KEYWORD_elseif },
168
+ { "end", KEYWORD_end },
169
+ { "ensure", KEYWORD_ensure },
170
+ { "expanded", KEYWORD_expanded },
171
+ { "export", KEYWORD_export },
172
+ { "external", KEYWORD_external },
173
+ { "false", KEYWORD_false },
174
+ { "feature", KEYWORD_feature },
175
+ { "from", KEYWORD_from },
176
+ { "frozen", KEYWORD_frozen },
177
+ { "if", KEYWORD_if },
178
+ { "implies", KEYWORD_implies },
179
+ { "indexing", KEYWORD_indexing },
180
+ { "infix", KEYWORD_infix },
181
+ { "inherit", KEYWORD_inherit },
182
+ { "inspect", KEYWORD_inspect },
183
+ { "invariant", KEYWORD_invariant },
184
+ { "is", KEYWORD_is },
185
+ { "like", KEYWORD_like },
186
+ { "local", KEYWORD_local },
187
+ { "loop", KEYWORD_loop },
188
+ { "not", KEYWORD_not },
189
+ { "obsolete", KEYWORD_obsolete },
190
+ { "old", KEYWORD_old },
191
+ { "once", KEYWORD_once },
192
+ { "or", KEYWORD_or },
193
+ { "prefix", KEYWORD_prefix },
194
+ { "redefine", KEYWORD_redefine },
195
+ { "rename", KEYWORD_rename },
196
+ { "require", KEYWORD_require },
197
+ { "rescue", KEYWORD_rescue },
198
+ { "result", KEYWORD_Result },
199
+ { "retry", KEYWORD_retry },
200
+ { "select", KEYWORD_select },
201
+ { "separate", KEYWORD_separate },
202
+ { "strip", KEYWORD_strip },
203
+ { "then", KEYWORD_then },
204
+ { "true", KEYWORD_true },
205
+ { "undefine", KEYWORD_undefine },
206
+ { "unique", KEYWORD_unique },
207
+ { "until", KEYWORD_until },
208
+ { "variant", KEYWORD_variant },
209
+ { "when", KEYWORD_when },
210
+ { "xor", KEYWORD_xor }
211
+ };
212
+
213
+ /*
214
+ * FUNCTION DEFINITIONS
215
+ */
216
+
217
+ static void buildEiffelKeywordHash (void)
218
+ {
219
+ const size_t count = sizeof (EiffelKeywordTable) /
220
+ sizeof (EiffelKeywordTable [0]);
221
+ size_t i;
222
+ for (i = 0 ; i < count ; ++i)
223
+ {
224
+ const keywordDesc* const p = &EiffelKeywordTable [i];
225
+ addKeyword (p->name, Lang_eiffel, (int) p->id);
226
+ }
227
+ }
228
+
229
+ #ifdef TYPE_REFERENCE_TOOL
230
+
231
+ static void addGenericName (tokenInfo *const token)
232
+ {
233
+ vStringUpper (token->string);
234
+ if (vStringLength (token->string) > 0)
235
+ stringListAdd (GenericNames, vStringNewCopy (token->string));
236
+ }
237
+
238
+ static boolean isGeneric (tokenInfo *const token)
239
+ {
240
+ return (boolean) stringListHas (GenericNames, vStringValue (token->string));
241
+ }
242
+
243
+ static void reportType (tokenInfo *const token)
244
+ {
245
+ vStringUpper (token->string);
246
+ if (vStringLength (token->string) > 0 && ! isGeneric (token) &&
247
+ (SelfReferences || strcmp (vStringValue (
248
+ token->string), vStringValue (token->className)) != 0) &&
249
+ ! stringListHas (ReferencedTypes, vStringValue (token->string)))
250
+ {
251
+ printf ("%s\n", vStringValue (token->string));
252
+ stringListAdd (ReferencedTypes, vStringNewCopy (token->string));
253
+ }
254
+ }
255
+
256
+ static int fileGetc (void)
257
+ {
258
+ int c = getc (File);
259
+ if (c == '\r')
260
+ {
261
+ c = getc (File);
262
+ if (c != '\n')
263
+ {
264
+ ungetc (c, File);
265
+ c = '\n';
266
+ }
267
+ }
268
+ if (Debug > 0 && c != EOF)
269
+ putc (c, errout);
270
+ return c;
271
+ }
272
+
273
+ static int fileUngetc (c)
274
+ {
275
+ return ungetc (c, File);
276
+ }
277
+
278
+ extern char *readLine (vString *const vLine, FILE *const fp)
279
+ {
280
+ return NULL;
281
+ }
282
+
283
+ #else
284
+
285
+ /*
286
+ * Tag generation functions
287
+ */
288
+
289
+ static void makeEiffelClassTag (tokenInfo *const token)
290
+ {
291
+ if (EiffelKinds [EKIND_CLASS].enabled)
292
+ {
293
+ const char *const name = vStringValue (token->string);
294
+ tagEntryInfo e;
295
+
296
+ initTagEntry (&e, name);
297
+
298
+ e.kindName = EiffelKinds [EKIND_CLASS].name;
299
+ e.kind = EiffelKinds [EKIND_CLASS].letter;
300
+
301
+ makeTagEntry (&e);
302
+ }
303
+ vStringCopy (token->className, token->string);
304
+ }
305
+
306
+ static void makeEiffelFeatureTag (tokenInfo *const token)
307
+ {
308
+ if (EiffelKinds [EKIND_FEATURE].enabled &&
309
+ (token->isExported || Option.include.fileScope))
310
+ {
311
+ const char *const name = vStringValue (token->string);
312
+ tagEntryInfo e;
313
+
314
+ initTagEntry (&e, name);
315
+
316
+ e.isFileScope = (boolean) (! token->isExported);
317
+ e.kindName = EiffelKinds [EKIND_FEATURE].name;
318
+ e.kind = EiffelKinds [EKIND_FEATURE].letter;
319
+ e.extensionFields.scope [0] = EiffelKinds [EKIND_CLASS].name;
320
+ e.extensionFields.scope [1] = vStringValue (token->className);
321
+
322
+ makeTagEntry (&e);
323
+
324
+ if (Option.include.qualifiedTags)
325
+ {
326
+ vString* qualified = vStringNewInit (vStringValue (token->className));
327
+ vStringPut (qualified, '.');
328
+ vStringCat (qualified, token->string);
329
+ e.name = vStringValue (qualified);
330
+ makeTagEntry (&e);
331
+ vStringDelete (qualified);
332
+ }
333
+ }
334
+ vStringCopy (token->featureName, token->string);
335
+ }
336
+
337
+ static void makeEiffelLocalTag (tokenInfo *const token)
338
+ {
339
+ if (EiffelKinds [EKIND_LOCAL].enabled && Option.include.fileScope)
340
+ {
341
+ const char *const name = vStringValue (token->string);
342
+ vString* scope = vStringNew ();
343
+ tagEntryInfo e;
344
+
345
+ initTagEntry (&e, name);
346
+
347
+ e.isFileScope = TRUE;
348
+ e.kindName = EiffelKinds [EKIND_LOCAL].name;
349
+ e.kind = EiffelKinds [EKIND_LOCAL].letter;
350
+
351
+ vStringCopy (scope, token->className);
352
+ vStringPut (scope, '.');
353
+ vStringCat (scope, token->featureName);
354
+
355
+ e.extensionFields.scope [0] = EiffelKinds [EKIND_FEATURE].name;
356
+ e.extensionFields.scope [1] = vStringValue (scope);
357
+
358
+ makeTagEntry (&e);
359
+ vStringDelete (scope);
360
+ }
361
+ }
362
+
363
+ #endif
364
+
365
+ /*
366
+ * Parsing functions
367
+ */
368
+
369
+ static int skipToCharacter (const int c)
370
+ {
371
+ int d;
372
+
373
+ do
374
+ {
375
+ d = fileGetc ();
376
+ } while (d != EOF && d != c);
377
+
378
+ return d;
379
+ }
380
+
381
+ /* If a numeric is passed in 'c', this is used as the first digit of the
382
+ * numeric being parsed.
383
+ */
384
+ static vString *parseInteger (int c)
385
+ {
386
+ vString *string = vStringNew ();
387
+
388
+ if (c == '\0')
389
+ c = fileGetc ();
390
+ if (c == '-')
391
+ {
392
+ vStringPut (string, c);
393
+ c = fileGetc ();
394
+ }
395
+ else if (! isdigit (c))
396
+ c = fileGetc ();
397
+ while (c != EOF && (isdigit (c) || c == '_'))
398
+ {
399
+ vStringPut (string, c);
400
+ c = fileGetc ();
401
+ }
402
+ vStringTerminate (string);
403
+ fileUngetc (c);
404
+
405
+ return string;
406
+ }
407
+
408
+ static vString *parseNumeric (int c)
409
+ {
410
+ vString *string = vStringNew ();
411
+ vString *integer = parseInteger (c);
412
+ vStringCopy (string, integer);
413
+ vStringDelete (integer);
414
+
415
+ c = fileGetc ();
416
+ if (c == '.')
417
+ {
418
+ integer = parseInteger ('\0');
419
+ vStringPut (string, c);
420
+ vStringCat (string, integer);
421
+ vStringDelete (integer);
422
+ c = fileGetc ();
423
+ }
424
+ if (tolower (c) == 'e')
425
+ {
426
+ integer = parseInteger ('\0');
427
+ vStringPut (string, c);
428
+ vStringCat (string, integer);
429
+ vStringDelete (integer);
430
+ }
431
+ else if (!isspace (c))
432
+ fileUngetc (c);
433
+
434
+ vStringTerminate (string);
435
+
436
+ return string;
437
+ }
438
+
439
+ static int parseEscapedCharacter (void)
440
+ {
441
+ int d = '\0';
442
+ int c = fileGetc ();
443
+
444
+ switch (c)
445
+ {
446
+ case 'A': d = '@'; break;
447
+ case 'B': d = '\b'; break;
448
+ case 'C': d = '^'; break;
449
+ case 'D': d = '$'; break;
450
+ case 'F': d = '\f'; break;
451
+ case 'H': d = '\\'; break;
452
+ case 'L': d = '~'; break;
453
+ case 'N': d = '\n'; break;
454
+ #ifdef QDOS
455
+ case 'Q': d = 0x9F; break;
456
+ #else
457
+ case 'Q': d = '`'; break;
458
+ #endif
459
+ case 'R': d = '\r'; break;
460
+ case 'S': d = '#'; break;
461
+ case 'T': d = '\t'; break;
462
+ case 'U': d = '\0'; break;
463
+ case 'V': d = '|'; break;
464
+ case '%': d = '%'; break;
465
+ case '\'': d = '\''; break;
466
+ case '"': d = '"'; break;
467
+ case '(': d = '['; break;
468
+ case ')': d = ']'; break;
469
+ case '<': d = '{'; break;
470
+ case '>': d = '}'; break;
471
+
472
+ case '\n': skipToCharacter ('%'); break;
473
+
474
+ case '/':
475
+ {
476
+ vString *string = parseInteger ('\0');
477
+ const char *value = vStringValue (string);
478
+ const unsigned long ascii = atol (value);
479
+ vStringDelete (string);
480
+
481
+ c = fileGetc ();
482
+ if (c == '/' && ascii < 256)
483
+ d = ascii;
484
+ break;
485
+ }
486
+
487
+ default: break;
488
+ }
489
+ return d;
490
+ }
491
+
492
+ static int parseCharacter (void)
493
+ {
494
+ int c = fileGetc ();
495
+ int result = c;
496
+
497
+ if (c == '%')
498
+ result = parseEscapedCharacter ();
499
+
500
+ c = fileGetc ();
501
+ if (c != '\'')
502
+ skipToCharacter ('\n');
503
+
504
+ return result;
505
+ }
506
+
507
+ static void parseString (vString *const string)
508
+ {
509
+ boolean verbatim = FALSE;
510
+ boolean align = FALSE;
511
+ boolean end = FALSE;
512
+ vString *verbatimCloser = vStringNew ();
513
+ vString *lastLine = vStringNew ();
514
+ int prev = '\0';
515
+ int c;
516
+
517
+ while (! end)
518
+ {
519
+ c = fileGetc ();
520
+ if (c == EOF)
521
+ end = TRUE;
522
+ else if (c == '"')
523
+ {
524
+ if (! verbatim)
525
+ end = TRUE;
526
+ else
527
+ end = (boolean) (strcmp (vStringValue (lastLine),
528
+ vStringValue (verbatimCloser)) == 0);
529
+ }
530
+ else if (c == '\n')
531
+ {
532
+ if (verbatim)
533
+ vStringClear (lastLine);
534
+ if (prev == '[' /* || prev == '{' */)
535
+ {
536
+ verbatim = TRUE;
537
+ vStringClear (verbatimCloser);
538
+ vStringClear (lastLine);
539
+ if (prev == '{')
540
+ vStringPut (verbatimCloser, '}');
541
+ else
542
+ {
543
+ vStringPut (verbatimCloser, ']');
544
+ align = TRUE;
545
+ }
546
+ vStringNCat (verbatimCloser, string, vStringLength (string) - 1);
547
+ vStringClear (string);
548
+ }
549
+ if (verbatim && align)
550
+ {
551
+ do
552
+ c = fileGetc ();
553
+ while (isspace (c));
554
+ }
555
+ }
556
+ else if (c == '%')
557
+ c = parseEscapedCharacter ();
558
+ if (! end)
559
+ {
560
+ vStringPut (string, c);
561
+ if (verbatim)
562
+ {
563
+ vStringPut (lastLine, c);
564
+ vStringTerminate (lastLine);
565
+ }
566
+ prev = c;
567
+ }
568
+ }
569
+ vStringTerminate (string);
570
+ vStringDelete (lastLine);
571
+ vStringDelete (verbatimCloser);
572
+ }
573
+
574
+ /* Read a C identifier beginning with "firstChar" and places it into "name".
575
+ */
576
+ static void parseIdentifier (vString *const string, const int firstChar)
577
+ {
578
+ int c = firstChar;
579
+
580
+ do
581
+ {
582
+ vStringPut (string, c);
583
+ c = fileGetc ();
584
+ } while (isident (c));
585
+
586
+ vStringTerminate (string);
587
+ if (!isspace (c))
588
+ fileUngetc (c); /* unget non-identifier character */
589
+ }
590
+
591
+ static void parseFreeOperator (vString *const string, const int firstChar)
592
+ {
593
+ int c = firstChar;
594
+
595
+ do
596
+ {
597
+ vStringPut (string, c);
598
+ c = fileGetc ();
599
+ } while (c > ' ');
600
+
601
+ vStringTerminate (string);
602
+ if (!isspace (c))
603
+ fileUngetc (c); /* unget non-identifier character */
604
+ }
605
+
606
+ static void copyToken (tokenInfo* dst, const tokenInfo *src)
607
+ {
608
+ dst->type = src->type;
609
+ dst->keyword = src->keyword;
610
+ dst->isExported = src->isExported;
611
+
612
+ vStringCopy (dst->string, src->string);
613
+ vStringCopy (dst->className, src->className);
614
+ vStringCopy (dst->featureName, src->featureName);
615
+ }
616
+
617
+ static tokenInfo *newToken (void)
618
+ {
619
+ tokenInfo *const token = xMalloc (1, tokenInfo);
620
+
621
+ token->type = TOKEN_UNDEFINED;
622
+ token->keyword = KEYWORD_NONE;
623
+ token->isExported = TRUE;
624
+
625
+ token->string = vStringNew ();
626
+ token->className = vStringNew ();
627
+ token->featureName = vStringNew ();
628
+
629
+ return token;
630
+ }
631
+
632
+ static void deleteToken (tokenInfo *const token)
633
+ {
634
+ vStringDelete (token->string);
635
+ vStringDelete (token->className);
636
+ vStringDelete (token->featureName);
637
+
638
+ eFree (token);
639
+ }
640
+
641
+ static void readToken (tokenInfo *const token)
642
+ {
643
+ int c;
644
+
645
+ token->type = TOKEN_UNDEFINED;
646
+ token->keyword = KEYWORD_NONE;
647
+ vStringClear (token->string);
648
+
649
+ getNextChar:
650
+
651
+ do
652
+ c = fileGetc ();
653
+ while (c == '\t' || c == ' ' || c == '\n');
654
+
655
+ switch (c)
656
+ {
657
+ case EOF: longjmp (Exception, (int)ExceptionEOF); break;
658
+ case ';': token->type = TOKEN_SEMICOLON; break;
659
+ case '!': token->type = TOKEN_BANG; break;
660
+ case '}': token->type = TOKEN_CLOSE_BRACE; break;
661
+ case ']': token->type = TOKEN_CLOSE_BRACKET; break;
662
+ case ')': token->type = TOKEN_CLOSE_PAREN; break;
663
+ case ',': token->type = TOKEN_COMMA; break;
664
+ case '$': token->type = TOKEN_DOLLAR; break;
665
+ case '.': token->type = TOKEN_DOT; break;
666
+ case '{': token->type = TOKEN_OPEN_BRACE; break;
667
+ case '[': token->type = TOKEN_OPEN_BRACKET; break;
668
+ case '(': token->type = TOKEN_OPEN_PAREN; break;
669
+ case '~': token->type = TOKEN_TILDE; break;
670
+
671
+
672
+ case '+':
673
+ case '*':
674
+ case '^':
675
+ case '=': token->type = TOKEN_OPERATOR; break;
676
+
677
+ case '-':
678
+ c = fileGetc ();
679
+ if (c == '>')
680
+ token->type = TOKEN_CONSTRAINT;
681
+ else if (c == '-') /* is this the start of a comment? */
682
+ {
683
+ skipToCharacter ('\n');
684
+ goto getNextChar;
685
+ }
686
+ else
687
+ {
688
+ if (!isspace (c))
689
+ fileUngetc (c);
690
+ token->type = TOKEN_OPERATOR;
691
+ }
692
+ break;
693
+
694
+ case '?':
695
+ case ':':
696
+ {
697
+ int c2 = fileGetc ();
698
+ if (c2 == '=')
699
+ token->type = TOKEN_OPERATOR;
700
+ else
701
+ {
702
+ if (!isspace (c2))
703
+ fileUngetc (c2);
704
+ if (c == ':')
705
+ token->type = TOKEN_COLON;
706
+ else
707
+ token->type = TOKEN_QUESTION;
708
+ }
709
+ break;
710
+ }
711
+
712
+ case '<':
713
+ c = fileGetc ();
714
+ if (c != '=' && c != '>' && !isspace (c))
715
+ fileUngetc (c);
716
+ token->type = TOKEN_OPERATOR;
717
+ break;
718
+
719
+ case '>':
720
+ c = fileGetc ();
721
+ if (c != '=' && c != '>' && !isspace (c))
722
+ fileUngetc (c);
723
+ token->type = TOKEN_OPERATOR;
724
+ break;
725
+
726
+ case '/':
727
+ c = fileGetc ();
728
+ if (c != '/' && c != '=' && !isspace (c))
729
+ fileUngetc (c);
730
+ token->type = TOKEN_OPERATOR;
731
+ break;
732
+
733
+ case '\\':
734
+ c = fileGetc ();
735
+ if (c != '\\' && !isspace (c))
736
+ fileUngetc (c);
737
+ token->type = TOKEN_OPERATOR;
738
+ break;
739
+
740
+ case '"':
741
+ token->type = TOKEN_STRING;
742
+ parseString (token->string);
743
+ break;
744
+
745
+ case '\'':
746
+ token->type = TOKEN_CHARACTER;
747
+ parseCharacter ();
748
+ break;
749
+
750
+ default:
751
+ if (isalpha (c))
752
+ {
753
+ parseIdentifier (token->string, c);
754
+ token->keyword = analyzeToken (token->string, Lang_eiffel);
755
+ if (isKeyword (token, KEYWORD_NONE))
756
+ token->type = TOKEN_IDENTIFIER;
757
+ else
758
+ token->type = TOKEN_KEYWORD;
759
+ }
760
+ else if (isdigit (c))
761
+ {
762
+ vString* numeric = parseNumeric (c);
763
+ vStringCat (token->string, numeric);
764
+ vStringDelete (numeric);
765
+ token->type = TOKEN_NUMERIC;
766
+ }
767
+ else if (isFreeOperatorChar (c))
768
+ {
769
+ parseFreeOperator (token->string, c);
770
+ token->type = TOKEN_OPERATOR;
771
+ }
772
+ else
773
+ {
774
+ token->type = TOKEN_UNDEFINED;
775
+ Assert (! isType (token, TOKEN_UNDEFINED));
776
+ }
777
+ break;
778
+ }
779
+ }
780
+
781
+ /*
782
+ * Scanning functions
783
+ */
784
+
785
+ static boolean isIdentifierMatch (
786
+ const tokenInfo *const token, const char *const name)
787
+ {
788
+ return (boolean) (isType (token, TOKEN_IDENTIFIER) &&
789
+ strcasecmp (vStringValue (token->string), name) == 0);
790
+ }
791
+
792
+ static void findToken (tokenInfo *const token, const tokenType type)
793
+ {
794
+ while (! isType (token, type))
795
+ readToken (token);
796
+ }
797
+
798
+ static void findKeyword (tokenInfo *const token, const keywordId keyword)
799
+ {
800
+ while (! isKeyword (token, keyword))
801
+ readToken (token);
802
+ }
803
+
804
+ static boolean parseType (tokenInfo *const token);
805
+
806
+ static void parseGeneric (tokenInfo *const token, boolean declaration __unused__)
807
+ {
808
+ unsigned int depth = 0;
809
+ #ifdef TYPE_REFERENCE_TOOL
810
+ boolean constraint = FALSE;
811
+ #endif
812
+ Assert (isType (token, TOKEN_OPEN_BRACKET));
813
+ do
814
+ {
815
+ if (isType (token, TOKEN_OPEN_BRACKET))
816
+ {
817
+ ++depth;
818
+ readToken (token);
819
+ }
820
+ else if (isType (token, TOKEN_CLOSE_BRACKET))
821
+ {
822
+ --depth;
823
+ readToken (token);
824
+ }
825
+ #ifdef TYPE_REFERENCE_TOOL
826
+ else if (declaration)
827
+ {
828
+ boolean advanced = FALSE;
829
+ if (depth == 1)
830
+ {
831
+ if (isType (token, TOKEN_CONSTRAINT))
832
+ constraint = TRUE;
833
+ else if (isKeyword (token, KEYWORD_create))
834
+ findKeyword (token, KEYWORD_end);
835
+ else if (isType (token, TOKEN_IDENTIFIER))
836
+ {
837
+ if (constraint)
838
+ advanced = parseType (token);
839
+ else
840
+ addGenericName (token);
841
+ constraint = FALSE;
842
+ }
843
+ }
844
+ else if (isType (token, TOKEN_IDENTIFIER))
845
+ advanced = parseType (token);
846
+ if (! advanced)
847
+ readToken (token);
848
+ }
849
+ #endif
850
+ else
851
+ parseType (token);
852
+ } while (depth > 0);
853
+ }
854
+
855
+ static boolean parseType (tokenInfo *const token)
856
+ {
857
+ tokenInfo* const id = newToken ();
858
+ copyToken (id, token);
859
+ readToken (token);
860
+ if (isType (token, TOKEN_COLON)) /* check for "{entity: TYPE}" */
861
+ {
862
+ readToken (id);
863
+ readToken (token);
864
+ }
865
+ if (isKeyword (id, KEYWORD_like))
866
+ {
867
+ if (isType (token, TOKEN_IDENTIFIER) ||
868
+ isKeyword (token, KEYWORD_Current))
869
+ readToken (token);
870
+ }
871
+ else
872
+ {
873
+ if (isKeyword (id, KEYWORD_expanded))
874
+ {
875
+ copyToken (id, token);
876
+ readToken (token);
877
+ }
878
+ if (isType (id, TOKEN_IDENTIFIER))
879
+ {
880
+ #ifdef TYPE_REFERENCE_TOOL
881
+ reportType (id);
882
+ #endif
883
+ if (isType (token, TOKEN_OPEN_BRACKET))
884
+ parseGeneric (token, FALSE);
885
+ else if ((strcmp ("BIT", vStringValue (id->string)) == 0))
886
+ readToken (token); /* read token after number of bits */
887
+ }
888
+ }
889
+ deleteToken (id);
890
+ return TRUE;
891
+ }
892
+
893
+ static void parseEntityType (tokenInfo *const token)
894
+ {
895
+ Assert (isType (token, TOKEN_COLON));
896
+ readToken (token);
897
+
898
+ if (isType (token, TOKEN_BANG) || isType (token, TOKEN_QUESTION))
899
+ readToken (token); /* skip over '!' or '?' */
900
+ parseType (token);
901
+ }
902
+
903
+ static void parseLocal (tokenInfo *const token)
904
+ {
905
+ Assert (isKeyword (token, KEYWORD_local));
906
+ readToken (token);
907
+
908
+ /* Check keyword first in case local clause is empty
909
+ */
910
+ while (! isKeyword (token, KEYWORD_do) &&
911
+ ! isKeyword (token, KEYWORD_once))
912
+ {
913
+ #ifndef TYPE_REFERENCE_TOOL
914
+ if (isType (token, TOKEN_IDENTIFIER))
915
+ makeEiffelLocalTag (token);
916
+ #endif
917
+ readToken (token);
918
+ if (isType (token, TOKEN_COLON))
919
+ parseEntityType (token);
920
+ }
921
+ }
922
+
923
+ static void findFeatureEnd (tokenInfo *const token)
924
+ {
925
+ boolean isFound = isKeyword (token, KEYWORD_is);
926
+ if (isFound)
927
+ readToken (token);
928
+ switch (token->keyword)
929
+ {
930
+ case KEYWORD_deferred:
931
+ case KEYWORD_do:
932
+ case KEYWORD_external:
933
+ case KEYWORD_local:
934
+ case KEYWORD_obsolete:
935
+ case KEYWORD_once:
936
+ case KEYWORD_require:
937
+ {
938
+ int depth = 1;
939
+
940
+ while (depth > 0)
941
+ {
942
+ #ifdef TYPE_REFERENCE_TOOL
943
+ if (isType (token, TOKEN_OPEN_BRACE))
944
+ {
945
+ readToken (token);
946
+ if (isType (token, TOKEN_IDENTIFIER))
947
+ parseType (token);
948
+ }
949
+ else if (isType (token, TOKEN_BANG))
950
+ {
951
+ readToken (token);
952
+ if (isType (token, TOKEN_IDENTIFIER))
953
+ parseType (token);
954
+ if (isType (token, TOKEN_BANG))
955
+ readToken (token);
956
+ }
957
+ else
958
+ #endif
959
+ switch (token->keyword)
960
+ {
961
+ case KEYWORD_check:
962
+ case KEYWORD_debug:
963
+ case KEYWORD_from:
964
+ case KEYWORD_if:
965
+ case KEYWORD_inspect:
966
+ ++depth;
967
+ break;
968
+
969
+ case KEYWORD_local:
970
+ parseLocal (token);
971
+ break;
972
+
973
+ case KEYWORD_end:
974
+ --depth;
975
+ break;
976
+
977
+ default:
978
+ break;
979
+ }
980
+ readToken (token);
981
+ }
982
+ break;
983
+ }
984
+
985
+ default:
986
+ /* is this a manifest constant? */
987
+ if (isFound || isType (token, TOKEN_OPERATOR)) {
988
+ if (isType (token, TOKEN_OPERATOR))
989
+ readToken (token);
990
+ readToken (token);
991
+ }
992
+ break;
993
+ }
994
+ }
995
+
996
+ static boolean readFeatureName (tokenInfo *const token)
997
+ {
998
+ boolean isFeatureName = FALSE;
999
+
1000
+ if (isKeyword (token, KEYWORD_frozen))
1001
+ readToken (token);
1002
+ if (isType (token, TOKEN_IDENTIFIER))
1003
+ isFeatureName = TRUE;
1004
+ else if (isKeyword (token, KEYWORD_assign)) /* legacy code */
1005
+ isFeatureName = TRUE;
1006
+ else if (isKeyword (token, KEYWORD_infix) ||
1007
+ isKeyword (token, KEYWORD_prefix))
1008
+ {
1009
+ readToken (token);
1010
+ if (isType (token, TOKEN_STRING))
1011
+ isFeatureName = TRUE;
1012
+ }
1013
+ return isFeatureName;
1014
+ }
1015
+
1016
+ static void parseArguments (tokenInfo *const token)
1017
+ {
1018
+ #ifndef TYPE_REFERENCE_TOOL
1019
+ findToken (token, TOKEN_CLOSE_PAREN);
1020
+ readToken (token);
1021
+ #else
1022
+ Assert (isType (token, TOKEN_OPEN_PAREN));
1023
+ readToken (token);
1024
+ do
1025
+ {
1026
+ if (isType (token, TOKEN_COLON))
1027
+ parseEntityType (token);
1028
+ else
1029
+ readToken (token);
1030
+ } while (! isType (token, TOKEN_CLOSE_PAREN));
1031
+ readToken (token);
1032
+ #endif
1033
+ }
1034
+
1035
+ static boolean parseFeature (tokenInfo *const token)
1036
+ {
1037
+ boolean found = FALSE;
1038
+ while (readFeatureName (token))
1039
+ {
1040
+ found = TRUE;
1041
+ #ifndef TYPE_REFERENCE_TOOL
1042
+ makeEiffelFeatureTag (token);
1043
+ #endif
1044
+ readToken (token);
1045
+ if (isType (token, TOKEN_COMMA))
1046
+ readToken (token);
1047
+ }
1048
+ if (found)
1049
+ {
1050
+ if (isKeyword (token, KEYWORD_alias)) {
1051
+ readToken (token);
1052
+ #ifndef TYPE_REFERENCE_TOOL
1053
+ if (isType (token, TOKEN_STRING))
1054
+ makeEiffelFeatureTag (token);
1055
+ #endif
1056
+ readToken (token);
1057
+ }
1058
+ if (isType (token, TOKEN_OPEN_PAREN)) /* arguments? */
1059
+ parseArguments (token);
1060
+ if (isType (token, TOKEN_COLON)) /* a query? */
1061
+ parseEntityType (token);
1062
+ if (isKeyword (token, KEYWORD_assign))
1063
+ {
1064
+ readToken (token);
1065
+ readToken (token);
1066
+ }
1067
+ if (isKeyword (token, KEYWORD_obsolete))
1068
+ {
1069
+ readToken (token);
1070
+ if (isType (token, TOKEN_STRING))
1071
+ readToken (token);
1072
+ }
1073
+ findFeatureEnd (token);
1074
+ }
1075
+ return found;
1076
+ }
1077
+
1078
+ static void parseExport (tokenInfo *const token)
1079
+ {
1080
+ token->isExported = TRUE;
1081
+ readToken (token);
1082
+ if (isType (token, TOKEN_OPEN_BRACE))
1083
+ {
1084
+ token->isExported = FALSE;
1085
+ while (! isType (token, TOKEN_CLOSE_BRACE))
1086
+ {
1087
+ if (isType (token, TOKEN_IDENTIFIER))
1088
+ token->isExported |= !isIdentifierMatch (token, "NONE");
1089
+ readToken (token);
1090
+ }
1091
+ readToken (token);
1092
+ }
1093
+ }
1094
+
1095
+ static void parseFeatureClauses (tokenInfo *const token)
1096
+ {
1097
+ Assert (isKeyword (token, KEYWORD_feature));
1098
+ do
1099
+ {
1100
+ if (isKeyword (token, KEYWORD_feature))
1101
+ parseExport (token);
1102
+ if (! isKeyword (token, KEYWORD_feature) &&
1103
+ ! isKeyword (token, KEYWORD_invariant) &&
1104
+ ! isKeyword (token, KEYWORD_indexing))
1105
+ {
1106
+ if (! parseFeature (token))
1107
+ readToken (token);
1108
+ }
1109
+ } while (! isKeyword (token, KEYWORD_end) &&
1110
+ ! isKeyword (token, KEYWORD_invariant) &&
1111
+ ! isKeyword (token, KEYWORD_indexing));
1112
+ }
1113
+
1114
+ static void parseRename (tokenInfo *const token)
1115
+ {
1116
+ Assert (isKeyword (token, KEYWORD_rename));
1117
+ do {
1118
+ readToken (token);
1119
+ if (readFeatureName (token))
1120
+ {
1121
+ readToken (token);
1122
+ if (isKeyword (token, KEYWORD_as))
1123
+ {
1124
+ readToken (token);
1125
+ if (readFeatureName (token))
1126
+ {
1127
+ #ifndef TYPE_REFERENCE_TOOL
1128
+ makeEiffelFeatureTag (token); /* renamed feature */
1129
+ #endif
1130
+ readToken (token);
1131
+ }
1132
+ }
1133
+ }
1134
+ } while (isType (token, TOKEN_COMMA));
1135
+ }
1136
+
1137
+ static void parseInherit (tokenInfo *const token)
1138
+ {
1139
+ Assert (isKeyword (token, KEYWORD_inherit));
1140
+ readToken (token);
1141
+ while (isType (token, TOKEN_IDENTIFIER))
1142
+ {
1143
+ parseType (token);
1144
+ if (isType (token, TOKEN_KEYWORD))
1145
+ {
1146
+ switch (token->keyword) /* check for feature adaptation */
1147
+ {
1148
+ case KEYWORD_rename:
1149
+ parseRename (token);
1150
+ case KEYWORD_export:
1151
+ case KEYWORD_undefine:
1152
+ case KEYWORD_redefine:
1153
+ case KEYWORD_select:
1154
+ findKeyword (token, KEYWORD_end);
1155
+ readToken (token);
1156
+ break;
1157
+
1158
+ case KEYWORD_end:
1159
+ readToken (token);
1160
+ break;
1161
+
1162
+ default: break;
1163
+ }
1164
+ }
1165
+ if (isType (token, TOKEN_SEMICOLON))
1166
+ readToken (token);
1167
+ }
1168
+ }
1169
+
1170
+ static void parseConvert (tokenInfo *const token)
1171
+ {
1172
+ Assert (isKeyword (token, KEYWORD_convert));
1173
+ do
1174
+ {
1175
+ readToken (token);
1176
+ if (! isType (token, TOKEN_IDENTIFIER))
1177
+ break;
1178
+ else if (isType (token, TOKEN_OPEN_PAREN))
1179
+ {
1180
+ while (! isType (token, TOKEN_CLOSE_PAREN))
1181
+ readToken (token);
1182
+ }
1183
+ else if (isType (token, TOKEN_COLON))
1184
+ {
1185
+ readToken (token);
1186
+ if (! isType (token, TOKEN_OPEN_BRACE))
1187
+ break;
1188
+ else while (! isType (token, TOKEN_CLOSE_BRACE))
1189
+ readToken (token);
1190
+ }
1191
+ } while (isType (token, TOKEN_COMMA));
1192
+ }
1193
+
1194
+ static void parseClass (tokenInfo *const token)
1195
+ {
1196
+ Assert (isKeyword (token, KEYWORD_class));
1197
+ readToken (token);
1198
+ if (isType (token, TOKEN_IDENTIFIER))
1199
+ {
1200
+ #ifndef TYPE_REFERENCE_TOOL
1201
+ makeEiffelClassTag (token);
1202
+ readToken (token);
1203
+ #else
1204
+ vStringCopy (token->className, token->string);
1205
+ vStringUpper (token->className);
1206
+ if (PrintClass)
1207
+ puts (vStringValue (token->className));
1208
+ if (! PrintReferences)
1209
+ exit (0);
1210
+ readToken (token);
1211
+ #endif
1212
+ }
1213
+
1214
+ do
1215
+ {
1216
+ if (isType (token, TOKEN_OPEN_BRACKET))
1217
+ parseGeneric (token, TRUE);
1218
+ else if (! isType (token, TOKEN_KEYWORD))
1219
+ readToken (token);
1220
+ else switch (token->keyword)
1221
+ {
1222
+ case KEYWORD_inherit: parseInherit (token); break;
1223
+ case KEYWORD_feature: parseFeatureClauses (token); break;
1224
+ case KEYWORD_convert: parseConvert (token); break;
1225
+ default: readToken (token); break;
1226
+ }
1227
+ } while (! isKeyword (token, KEYWORD_end));
1228
+ }
1229
+
1230
+ static void initialize (const langType language)
1231
+ {
1232
+ Lang_eiffel = language;
1233
+ buildEiffelKeywordHash ();
1234
+ }
1235
+
1236
+ static void findEiffelTags (void)
1237
+ {
1238
+ tokenInfo *const token = newToken ();
1239
+ exception_t exception;
1240
+
1241
+ exception = (exception_t) (setjmp (Exception));
1242
+ while (exception == ExceptionNone)
1243
+ {
1244
+ findKeyword (token, KEYWORD_class);
1245
+ parseClass (token);
1246
+ }
1247
+ deleteToken (token);
1248
+ }
1249
+
1250
+ #ifndef TYPE_REFERENCE_TOOL
1251
+
1252
+ extern parserDefinition* EiffelParser (void)
1253
+ {
1254
+ static const char *const extensions [] = { "e", NULL };
1255
+ parserDefinition* def = parserNew ("Eiffel");
1256
+ def->kinds = EiffelKinds;
1257
+ def->kindCount = KIND_COUNT (EiffelKinds);
1258
+ def->extensions = extensions;
1259
+ def->parser = findEiffelTags;
1260
+ def->initialize = initialize;
1261
+ return def;
1262
+ }
1263
+
1264
+ #else
1265
+
1266
+ static void findReferences (void)
1267
+ {
1268
+ ReferencedTypes = stringListNew ();
1269
+ GenericNames = stringListNew ();
1270
+ initialize (0);
1271
+
1272
+ findEiffelTags ();
1273
+
1274
+ stringListDelete (GenericNames);
1275
+ GenericNames = NULL;
1276
+ stringListDelete (ReferencedTypes);
1277
+ ReferencedTypes = NULL;
1278
+ }
1279
+
1280
+ static const char *const Usage =
1281
+ "Prints names of types referenced by an Eiffel language file.\n"
1282
+ "\n"
1283
+ "Usage: %s [-cdrs] [file_name | -]\n"
1284
+ "\n"
1285
+ "Options:\n"
1286
+ " -c Print class name of current file (on first line of output).\n"
1287
+ " -d Enable debug output.\n"
1288
+ " -r Print types referenced by current file (default unless -c).\n"
1289
+ " -s Include self-references.\n"
1290
+ "\n";
1291
+
1292
+ extern int main (int argc, char** argv)
1293
+ {
1294
+ int i;
1295
+ for (i = 1 ; argv [i] != NULL ; ++i)
1296
+ {
1297
+ const char *const arg = argv [i];
1298
+ if (arg [0] == '-')
1299
+ {
1300
+ int j;
1301
+ if (arg [1] == '\0')
1302
+ {
1303
+ File = stdin;
1304
+ FileName = "stdin";
1305
+ }
1306
+ else for (j = 1 ; arg [j] != '\0' ; ++j) switch (arg [j])
1307
+ {
1308
+ case 'c': PrintClass = 1; break;
1309
+ case 'r': PrintReferences = 1; break;
1310
+ case 's': SelfReferences = 1; break;
1311
+ case 'd': Debug = 1; break;
1312
+ default:
1313
+ fprintf (errout, "%s: unknown option: %c\n", argv [0], arg [1]);
1314
+ fprintf (errout, Usage, argv [0]);
1315
+ exit (1);
1316
+ break;
1317
+ }
1318
+ }
1319
+ else if (File != NULL)
1320
+ {
1321
+ fprintf (errout, Usage, argv [0]);
1322
+ exit (1);
1323
+ }
1324
+ else
1325
+ {
1326
+ FileName = arg;
1327
+ File = fopen (FileName, "r");
1328
+ if (File == NULL)
1329
+ {
1330
+ perror (argv [0]);
1331
+ exit (1);
1332
+ }
1333
+ }
1334
+ }
1335
+ if (! PrintClass)
1336
+ PrintReferences = 1;
1337
+ if (File == NULL)
1338
+ {
1339
+ fprintf (errout, Usage, argv [0]);
1340
+ exit (1);
1341
+ }
1342
+ else
1343
+ {
1344
+ findReferences ();
1345
+ fclose (File);
1346
+ }
1347
+ return 0;
1348
+ }
1349
+
1350
+ #endif
1351
+
1352
+ /* vi:set tabstop=4 shiftwidth=4: */