2
* $Id: eiffel.c,v 1.18 2006/05/30 04:37:12 darren Exp $
4
* Copyright (c) 1998-2002, Darren Hiebert
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 Eiffel language
16
#include "general.h" /* must always come first */
18
#ifdef TYPE_REFERENCE_TOOL
23
#include <ctype.h> /* to define tolower () */
30
#ifndef TYPE_REFERENCE_TOOL
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))
50
typedef enum eException { ExceptionNone, ExceptionEOF } exception_t;
52
/* Used to specify type of keyword.
54
typedef enum eKeywordId {
56
KEYWORD_alias, KEYWORD_all, KEYWORD_and, KEYWORD_as, KEYWORD_check,
57
KEYWORD_class, KEYWORD_create, KEYWORD_creation, KEYWORD_Current,
58
KEYWORD_debug, KEYWORD_deferred, KEYWORD_do, KEYWORD_else,
59
KEYWORD_elseif, KEYWORD_end, KEYWORD_ensure, KEYWORD_expanded,
60
KEYWORD_export, KEYWORD_external, KEYWORD_false, KEYWORD_feature,
61
KEYWORD_from, KEYWORD_frozen, KEYWORD_if, KEYWORD_implies,
62
KEYWORD_indexing, KEYWORD_infix, KEYWORD_inherit, KEYWORD_inspect,
63
KEYWORD_invariant, KEYWORD_is, KEYWORD_like, KEYWORD_local,
64
KEYWORD_loop, KEYWORD_not, KEYWORD_obsolete, KEYWORD_old, KEYWORD_once,
65
KEYWORD_or, KEYWORD_prefix, KEYWORD_redefine, KEYWORD_rename,
66
KEYWORD_require, KEYWORD_rescue, KEYWORD_Result, KEYWORD_retry,
67
KEYWORD_select, KEYWORD_separate, KEYWORD_strip, KEYWORD_then,
68
KEYWORD_true, KEYWORD_undefine, KEYWORD_unique, KEYWORD_until,
69
KEYWORD_variant, KEYWORD_when, KEYWORD_xor
72
/* Used to determine whether keyword is valid for the token language and
75
typedef struct sKeywordDesc {
80
typedef enum eTokenType {
105
typedef struct sTokenInfo {
111
vString* featureName;
118
static langType Lang_eiffel;
120
#ifdef TYPE_REFERENCE_TOOL
122
static const char *FileName;
124
static int PrintClass;
125
static int PrintReferences;
126
static int SelfReferences;
128
static stringList *GenericNames;
129
static stringList *ReferencedTypes;
134
EKIND_CLASS, EKIND_FEATURE, EKIND_LOCAL, EKIND_QUALIFIED_TAGS
137
static kindOption EiffelKinds [] = {
138
{ TRUE, 'c', "class", "classes"},
139
{ TRUE, 'f', "feature", "features"},
140
{ FALSE, 'l', "local", "local entities"}
145
static langType Lang_eiffel;
147
static jmp_buf Exception;
149
static const keywordDesc EiffelKeywordTable [] = {
150
/* keyword keyword ID */
151
{ "alias", KEYWORD_alias },
152
{ "all", KEYWORD_all },
153
{ "and", KEYWORD_and },
154
{ "as", KEYWORD_as },
155
{ "check", KEYWORD_check },
156
{ "class", KEYWORD_class },
157
{ "create", KEYWORD_create },
158
{ "creation", KEYWORD_creation },
159
{ "current", KEYWORD_Current },
160
{ "debug", KEYWORD_debug },
161
{ "deferred", KEYWORD_deferred },
162
{ "do", KEYWORD_do },
163
{ "else", KEYWORD_else },
164
{ "elseif", KEYWORD_elseif },
165
{ "end", KEYWORD_end },
166
{ "ensure", KEYWORD_ensure },
167
{ "expanded", KEYWORD_expanded },
168
{ "export", KEYWORD_export },
169
{ "external", KEYWORD_external },
170
{ "false", KEYWORD_false },
171
{ "feature", KEYWORD_feature },
172
{ "from", KEYWORD_from },
173
{ "frozen", KEYWORD_frozen },
174
{ "if", KEYWORD_if },
175
{ "implies", KEYWORD_implies },
176
{ "indexing", KEYWORD_indexing },
177
{ "infix", KEYWORD_infix },
178
{ "inherit", KEYWORD_inherit },
179
{ "inspect", KEYWORD_inspect },
180
{ "invariant", KEYWORD_invariant },
181
{ "is", KEYWORD_is },
182
{ "like", KEYWORD_like },
183
{ "local", KEYWORD_local },
184
{ "loop", KEYWORD_loop },
185
{ "not", KEYWORD_not },
186
{ "obsolete", KEYWORD_obsolete },
187
{ "old", KEYWORD_old },
188
{ "once", KEYWORD_once },
189
{ "or", KEYWORD_or },
190
{ "prefix", KEYWORD_prefix },
191
{ "redefine", KEYWORD_redefine },
192
{ "rename", KEYWORD_rename },
193
{ "require", KEYWORD_require },
194
{ "rescue", KEYWORD_rescue },
195
{ "result", KEYWORD_Result },
196
{ "retry", KEYWORD_retry },
197
{ "select", KEYWORD_select },
198
{ "separate", KEYWORD_separate },
199
{ "strip", KEYWORD_strip },
200
{ "then", KEYWORD_then },
201
{ "true", KEYWORD_true },
202
{ "undefine", KEYWORD_undefine },
203
{ "unique", KEYWORD_unique },
204
{ "until", KEYWORD_until },
205
{ "variant", KEYWORD_variant },
206
{ "when", KEYWORD_when },
207
{ "xor", KEYWORD_xor }
211
* FUNCTION DEFINITIONS
214
static void buildEiffelKeywordHash (void)
216
const size_t count = sizeof (EiffelKeywordTable) /
217
sizeof (EiffelKeywordTable [0]);
219
for (i = 0 ; i < count ; ++i)
221
const keywordDesc* const p = &EiffelKeywordTable [i];
222
addKeyword (p->name, Lang_eiffel, (int) p->id);
226
#ifdef TYPE_REFERENCE_TOOL
228
static void addGenericName (tokenInfo *const token)
230
vStringUpper (token->string);
231
if (vStringLength (token->string) > 0)
232
stringListAdd (GenericNames, vStringNewCopy (token->string));
235
static boolean isGeneric (tokenInfo *const token)
237
return (boolean) stringListHas (GenericNames, vStringValue (token->string));
240
static void reportType (tokenInfo *const token)
242
vStringUpper (token->string);
243
if (vStringLength (token->string) > 0 && ! isGeneric (token) &&
244
(SelfReferences || strcmp (vStringValue (
245
token->string), vStringValue (token->className)) != 0) &&
246
! stringListHas (ReferencedTypes, vStringValue (token->string)))
248
printf ("%s\n", vStringValue (token->string));
249
stringListAdd (ReferencedTypes, vStringNewCopy (token->string));
253
static int fileGetc (void)
265
if (Debug > 0 && c != EOF)
270
static int fileUngetc (c)
272
return ungetc (c, File);
275
extern char *readLine (vString *const vLine, FILE *const fp)
283
* Tag generation functions
286
static void makeEiffelClassTag (tokenInfo *const token)
288
if (EiffelKinds [EKIND_CLASS].enabled)
290
const char *const name = vStringValue (token->string);
293
initTagEntry (&e, name);
295
e.kindName = EiffelKinds [EKIND_CLASS].name;
296
e.kind = EiffelKinds [EKIND_CLASS].letter;
300
vStringCopy (token->className, token->string);
303
static void makeEiffelFeatureTag (tokenInfo *const token)
305
if (EiffelKinds [EKIND_FEATURE].enabled &&
306
(token->isExported || Option.include.fileScope))
308
const char *const name = vStringValue (token->string);
311
initTagEntry (&e, name);
313
e.isFileScope = (boolean) (! token->isExported);
314
e.kindName = EiffelKinds [EKIND_FEATURE].name;
315
e.kind = EiffelKinds [EKIND_FEATURE].letter;
316
e.extensionFields.scope [0] = EiffelKinds [EKIND_CLASS].name;
317
e.extensionFields.scope [1] = vStringValue (token->className);
321
if (Option.include.qualifiedTags)
323
vString* qualified = vStringNewInit (vStringValue (token->className));
324
vStringPut (qualified, '.');
325
vStringCat (qualified, token->string);
326
e.name = vStringValue (qualified);
328
vStringDelete (qualified);
331
vStringCopy (token->featureName, token->string);
334
static void makeEiffelLocalTag (tokenInfo *const token)
336
if (EiffelKinds [EKIND_LOCAL].enabled && Option.include.fileScope)
338
const char *const name = vStringValue (token->string);
339
vString* scope = vStringNew ();
342
initTagEntry (&e, name);
344
e.isFileScope = TRUE;
345
e.kindName = EiffelKinds [EKIND_LOCAL].name;
346
e.kind = EiffelKinds [EKIND_LOCAL].letter;
348
vStringCopy (scope, token->className);
349
vStringPut (scope, '.');
350
vStringCat (scope, token->featureName);
352
e.extensionFields.scope [0] = EiffelKinds [EKIND_FEATURE].name;
353
e.extensionFields.scope [1] = vStringValue (scope);
356
vStringDelete (scope);
366
static int skipToCharacter (const int c)
373
} while (d != EOF && d != c);
378
/* If a numeric is passed in 'c', this is used as the first digit of the
379
* numeric being parsed.
381
static vString *parseInteger (int c)
383
static vString *string = NULL;
386
string = vStringNew ();
387
vStringClear (string);
393
vStringPut (string, c);
396
else if (! isdigit (c))
398
while (c != EOF && (isdigit (c) || c == '_'))
400
vStringPut (string, c);
403
vStringTerminate (string);
409
static vString *parseNumeric (int c)
411
static vString *string = NULL;
414
string = vStringNew ();
415
vStringCopy (string, parseInteger (c));
420
vStringPut (string, c);
421
vStringCat (string, parseInteger ('\0'));
424
if (tolower (c) == 'e')
426
vStringPut (string, c);
427
vStringCat (string, parseInteger ('\0'));
429
else if (!isspace (c))
432
vStringTerminate (string);
437
static int parseEscapedCharacter (void)
444
case 'A': d = '@'; break;
445
case 'B': d = '\b'; break;
446
case 'C': d = '^'; break;
447
case 'D': d = '$'; break;
448
case 'F': d = '\f'; break;
449
case 'H': d = '\\'; break;
450
case 'L': d = '~'; break;
451
case 'N': d = '\n'; break;
453
case 'Q': d = 0x9F; break;
455
case 'Q': d = '`'; break;
457
case 'R': d = '\r'; break;
458
case 'S': d = '#'; break;
459
case 'T': d = '\t'; break;
460
case 'U': d = '\0'; break;
461
case 'V': d = '|'; break;
462
case '%': d = '%'; break;
463
case '\'': d = '\''; break;
464
case '"': d = '"'; break;
465
case '(': d = '['; break;
466
case ')': d = ']'; break;
467
case '<': d = '{'; break;
468
case '>': d = '}'; break;
470
case '\n': skipToCharacter ('%'); break;
474
vString *string = parseInteger ('\0');
475
const char *value = vStringValue (string);
476
const unsigned long ascii = atol (value);
479
if (c == '/' && ascii < 256)
489
static int parseCharacter (void)
495
result = parseEscapedCharacter ();
499
skipToCharacter ('\n');
504
static void parseString (vString *const string)
506
boolean verbatim = FALSE;
507
boolean align = FALSE;
509
vString *verbatimCloser = NULL;
510
vString *lastLine = NULL;
524
end = (boolean) (strcmp (vStringValue (lastLine),
525
vStringValue (verbatimCloser)) == 0);
530
vStringClear (lastLine);
531
if (prev == '[' /* || prev == '{' */)
534
verbatimCloser = vStringNew ();
535
lastLine = vStringNew ();
537
vStringPut (verbatimCloser, '}');
540
vStringPut (verbatimCloser, ']');
543
vStringNCat (verbatimCloser, string, vStringLength (string) - 1);
544
vStringClear (string);
546
if (verbatim && align)
554
c = parseEscapedCharacter ();
557
vStringPut (string, c);
560
vStringPut (lastLine, c);
561
vStringTerminate (lastLine);
566
vStringTerminate (string);
569
/* Read a C identifier beginning with "firstChar" and places it into "name".
571
static void parseIdentifier (vString *const string, const int firstChar)
577
vStringPut (string, c);
579
} while (isident (c));
581
vStringTerminate (string);
583
fileUngetc (c); /* unget non-identifier character */
586
static void parseFreeOperator (vString *const string, const int firstChar)
592
vStringPut (string, c);
596
vStringTerminate (string);
598
fileUngetc (c); /* unget non-identifier character */
601
static keywordId analyzeToken (vString *const name)
603
static vString *keyword = NULL;
607
keyword = vStringNew ();
608
vStringCopyToLower (keyword, name);
609
id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_eiffel);
614
static void readToken (tokenInfo *const token)
618
token->type = TOKEN_UNDEFINED;
619
token->keyword = KEYWORD_NONE;
620
vStringClear (token->string);
626
while (c == '\t' || c == ' ' || c == '\n');
630
case EOF: longjmp (Exception, (int)ExceptionEOF); break;
631
case '!': token->type = TOKEN_BANG; break;
632
case '$': token->type = TOKEN_DOLLAR; break;
633
case '(': token->type = TOKEN_OPEN_PAREN; break;
634
case ')': token->type = TOKEN_CLOSE_PAREN; break;
635
case ',': token->type = TOKEN_COMMA; break;
636
case '.': token->type = TOKEN_DOT; break;
637
case ';': goto getNextChar;
638
case '[': token->type = TOKEN_OPEN_BRACKET; break;
639
case ']': token->type = TOKEN_CLOSE_BRACKET; break;
640
case '{': token->type = TOKEN_OPEN_BRACE; break;
641
case '}': token->type = TOKEN_CLOSE_BRACE; break;
642
case '~': token->type = TOKEN_TILDE; break;
648
case '=': token->type = TOKEN_OPERATOR; break;
653
token->type = TOKEN_CONSTRAINT;
654
else if (c == '-') /* is this the start of a comment? */
656
skipToCharacter ('\n');
663
token->type = TOKEN_OPERATOR;
671
token->type = TOKEN_OPERATOR;
674
token->type = TOKEN_COLON;
682
if (c != '=' && c != '>' && !isspace (c))
684
token->type = TOKEN_OPERATOR;
689
if (c != '=' && c != '>' && !isspace (c))
691
token->type = TOKEN_OPERATOR;
696
if (c != '/' && c != '=' && !isspace (c))
698
token->type = TOKEN_OPERATOR;
703
if (c != '\\' && !isspace (c))
705
token->type = TOKEN_OPERATOR;
709
token->type = TOKEN_STRING;
710
parseString (token->string);
714
token->type = TOKEN_CHARACTER;
721
parseIdentifier (token->string, c);
722
token->keyword = analyzeToken (token->string);
723
if (isKeyword (token, KEYWORD_NONE))
724
token->type = TOKEN_IDENTIFIER;
726
token->type = TOKEN_KEYWORD;
728
else if (isdigit (c))
730
vStringCat (token->string, parseNumeric (c));
731
token->type = TOKEN_NUMERIC;
733
else if (isFreeOperatorChar (c))
735
parseFreeOperator (token->string, c);
736
token->type = TOKEN_OPERATOR;
740
token->type = TOKEN_UNDEFINED;
741
Assert (! isType (token, TOKEN_UNDEFINED));
751
static boolean isIdentifierMatch (
752
const tokenInfo *const token, const char *const name)
754
return (boolean) (isType (token, TOKEN_IDENTIFIER) &&
755
strcasecmp (vStringValue (token->string), name) == 0);
758
static void findToken (tokenInfo *const token, const tokenType type)
760
while (! isType (token, type))
764
static void findKeyword (tokenInfo *const token, const keywordId keyword)
766
while (! isKeyword (token, keyword))
770
static void parseGeneric (tokenInfo *const token, boolean declaration __unused__)
772
unsigned int depth = 0;
773
#ifdef TYPE_REFERENCE_TOOL
774
boolean constraint = FALSE;
776
Assert (isType (token, TOKEN_OPEN_BRACKET));
779
if (isType (token, TOKEN_OPEN_BRACKET))
781
else if (isType (token, TOKEN_CLOSE_BRACKET))
783
#ifdef TYPE_REFERENCE_TOOL
784
else if (declaration)
788
if (isType (token, TOKEN_CONSTRAINT))
790
else if (isKeyword (token, KEYWORD_create))
791
findKeyword (token, KEYWORD_end);
792
else if (isType (token, TOKEN_IDENTIFIER))
797
addGenericName (token);
801
else if (isKeyword (token, KEYWORD_like))
803
else if (isType (token, TOKEN_IDENTIFIER))
808
if (isType (token, TOKEN_OPEN_BRACKET))
810
else if (isType (token, TOKEN_IDENTIFIER))
812
else if (isKeyword (token, KEYWORD_like))
820
static void parseType (tokenInfo *const token)
823
Assert (isType (token, TOKEN_IDENTIFIER));
824
#ifdef TYPE_REFERENCE_TOOL
827
bitType = (boolean)(strcmp ("BIT", vStringValue (token->string)) == 0);
829
if (bitType && isType (token, TOKEN_NUMERIC))
831
else if (isType (token, TOKEN_OPEN_BRACKET))
832
parseGeneric (token, FALSE);
835
static void parseEntityType (tokenInfo *const token)
837
Assert (isType (token, TOKEN_COLON));
840
if (isKeyword (token, KEYWORD_expanded))
843
/* Skip over the type name, with possible generic parameters.
845
if (isType (token, TOKEN_IDENTIFIER))
847
else if (isKeyword (token, KEYWORD_like))
850
if (isType (token, TOKEN_IDENTIFIER) ||
851
isKeyword (token, KEYWORD_Current))
857
static void parseLocal (tokenInfo *const token)
859
Assert (isKeyword (token, KEYWORD_local));
862
/* Check keyword first in case local clause is empty
864
while (! isKeyword (token, KEYWORD_do) &&
865
! isKeyword (token, KEYWORD_once))
867
#ifndef TYPE_REFERENCE_TOOL
868
if (isType (token, TOKEN_IDENTIFIER))
869
makeEiffelLocalTag (token);
872
if (isType (token, TOKEN_COLON))
875
if (isType (token, TOKEN_IDENTIFIER))
881
static void findFeatureEnd (tokenInfo *const token)
885
switch (token->keyword)
888
if (isType (token, TOKEN_OPERATOR)) /* sign of manifest constant */
890
readToken (token); /* skip to next token after constant */
893
case KEYWORD_deferred:
895
case KEYWORD_external:
897
case KEYWORD_obsolete:
899
case KEYWORD_require:
905
#ifdef TYPE_REFERENCE_TOOL
906
if (isType (token, TOKEN_OPEN_BRACE))
909
if (isType (token, TOKEN_IDENTIFIER))
912
else if (isType (token, TOKEN_BANG))
915
if (isType (token, TOKEN_IDENTIFIER))
917
if (isType (token, TOKEN_BANG))
922
switch (token->keyword)
928
case KEYWORD_inspect:
950
static boolean readFeatureName (tokenInfo *const token)
952
boolean isFeatureName = FALSE;
954
if (isKeyword (token, KEYWORD_frozen))
956
if (isType (token, TOKEN_IDENTIFIER))
957
isFeatureName = TRUE;
958
else if (isKeyword (token, KEYWORD_infix) ||
959
isKeyword (token, KEYWORD_prefix))
962
if (isType (token, TOKEN_STRING))
963
isFeatureName = TRUE;
965
return isFeatureName;
968
static void parseArguments (tokenInfo *const token)
970
#ifndef TYPE_REFERENCE_TOOL
971
findToken (token, TOKEN_CLOSE_PAREN);
974
Assert (isType (token, TOKEN_OPEN_PAREN));
978
if (! isType (token, TOKEN_COLON))
983
if (isType (token, TOKEN_IDENTIFIER))
986
} while (! isType (token, TOKEN_CLOSE_PAREN));
991
static boolean parseFeature (tokenInfo *const token)
993
boolean found = FALSE;
994
while (readFeatureName (token))
997
#ifndef TYPE_REFERENCE_TOOL
998
makeEiffelFeatureTag (token);
1001
if (isType (token, TOKEN_COMMA))
1006
if (isType (token, TOKEN_OPEN_PAREN)) /* arguments? */
1007
parseArguments (token);
1008
if (isType (token, TOKEN_COLON)) /* a query? */
1009
parseEntityType (token);
1010
if (isKeyword (token, KEYWORD_obsolete))
1013
if (isType (token, TOKEN_STRING))
1016
if (isKeyword (token, KEYWORD_is))
1017
findFeatureEnd (token);
1022
static void parseExport (tokenInfo *const token)
1024
token->isExported = TRUE;
1026
if (isType (token, TOKEN_OPEN_BRACE))
1028
token->isExported = FALSE;
1029
while (! isType (token, TOKEN_CLOSE_BRACE))
1031
if (isType (token, TOKEN_IDENTIFIER))
1032
token->isExported |= !isIdentifierMatch (token, "NONE");
1039
static void parseFeatureClauses (tokenInfo *const token)
1041
Assert (isKeyword (token, KEYWORD_feature));
1044
if (isKeyword (token, KEYWORD_feature))
1045
parseExport (token);
1046
if (! isKeyword (token, KEYWORD_feature) &&
1047
! isKeyword (token, KEYWORD_invariant) &&
1048
! isKeyword (token, KEYWORD_indexing))
1050
if (! parseFeature (token))
1053
} while (! isKeyword (token, KEYWORD_end) &&
1054
! isKeyword (token, KEYWORD_invariant) &&
1055
! isKeyword (token, KEYWORD_indexing));
1058
static void parseRename (tokenInfo *const token)
1062
if (readFeatureName (token))
1065
if (isKeyword (token, KEYWORD_as))
1068
if (readFeatureName (token))
1070
#ifndef TYPE_REFERENCE_TOOL
1071
makeEiffelFeatureTag (token); /* renamed feature */
1077
} while (isType (token, TOKEN_COMMA));
1079
findKeyword (token, KEYWORD_end);
1084
static void parseInherit (tokenInfo *const token)
1086
Assert (isKeyword (token, KEYWORD_inherit));
1087
#ifdef TYPE_REFERENCE_TOOL
1089
while (isType (token, TOKEN_IDENTIFIER))
1092
if (isType (token, TOKEN_KEYWORD))
1094
switch (token->keyword) /* check for feature adaptation */
1096
case KEYWORD_rename:
1097
case KEYWORD_export:
1098
case KEYWORD_undefine:
1099
case KEYWORD_redefine:
1100
case KEYWORD_select:
1101
findKeyword (token, KEYWORD_end);
1109
while (isType (token, TOKEN_IDENTIFIER))
1112
switch (token->keyword) /* check for feature adaptation */
1114
case KEYWORD_rename:
1115
parseRename (token);
1116
if (isKeyword (token, KEYWORD_end))
1120
case KEYWORD_export:
1121
case KEYWORD_undefine:
1122
case KEYWORD_redefine:
1123
case KEYWORD_select:
1124
findKeyword (token, KEYWORD_end);
1138
static void parseClass (tokenInfo *const token)
1140
Assert (isKeyword (token, KEYWORD_class));
1142
if (isType (token, TOKEN_IDENTIFIER))
1144
#ifndef TYPE_REFERENCE_TOOL
1145
makeEiffelClassTag (token);
1148
vStringCopy (token->className, token->string);
1149
vStringUpper (token->className);
1151
puts (vStringValue (token->className));
1152
if (! PrintReferences)
1160
if (isType (token, TOKEN_OPEN_BRACKET))
1161
parseGeneric (token, TRUE);
1162
else if (! isType (token, TOKEN_KEYWORD))
1164
else switch (token->keyword)
1166
case KEYWORD_inherit: parseInherit (token); break;
1167
case KEYWORD_feature: parseFeatureClauses (token); break;
1168
default: readToken (token); break;
1170
} while (! isKeyword (token, KEYWORD_end));
1173
static tokenInfo *newToken (void)
1175
tokenInfo *const token = xMalloc (1, tokenInfo);
1177
token->type = TOKEN_UNDEFINED;
1178
token->keyword = KEYWORD_NONE;
1179
token->isExported = TRUE;
1181
token->string = vStringNew ();
1182
token->className = vStringNew ();
1183
token->featureName = vStringNew ();
1188
static void deleteToken (tokenInfo *const token)
1190
vStringDelete (token->string);
1191
vStringDelete (token->className);
1192
vStringDelete (token->featureName);
1197
static void initialize (const langType language)
1199
Lang_eiffel = language;
1200
buildEiffelKeywordHash ();
1203
static void findEiffelTags (void)
1205
tokenInfo *const token = newToken ();
1206
exception_t exception;
1208
exception = (exception_t) (setjmp (Exception));
1209
while (exception == ExceptionNone)
1211
findKeyword (token, KEYWORD_class);
1214
deleteToken (token);
1217
#ifndef TYPE_REFERENCE_TOOL
1219
extern parserDefinition* EiffelParser (void)
1221
static const char *const extensions [] = { "e", NULL };
1222
parserDefinition* def = parserNew ("Eiffel");
1223
def->kinds = EiffelKinds;
1224
def->kindCount = KIND_COUNT (EiffelKinds);
1225
def->extensions = extensions;
1226
def->parser = findEiffelTags;
1227
def->initialize = initialize;
1233
static void findReferences (void)
1235
ReferencedTypes = stringListNew ();
1236
GenericNames = stringListNew ();
1241
stringListDelete (GenericNames);
1242
GenericNames = NULL;
1243
stringListDelete (ReferencedTypes);
1244
ReferencedTypes = NULL;
1247
static const char *const Usage =
1248
"Prints names of types referenced by an Eiffel language file.\n"
1250
"Usage: %s [-cdrs] [file_name | -]\n"
1253
" -c Print class name of current file (on first line of output).\n"
1254
" -d Enable debug output.\n"
1255
" -r Print types referenced by current file (default unless -c).\n"
1256
" -s Include self-references.\n"
1259
extern int main (int argc, char** argv)
1262
for (i = 1 ; argv [i] != NULL ; ++i)
1264
const char *const arg = argv [i];
1268
if (arg [1] == '\0')
1273
else for (j = 1 ; arg [j] != '\0' ; ++j) switch (arg [j])
1275
case 'c': PrintClass = 1; break;
1276
case 'r': PrintReferences = 1; break;
1277
case 's': SelfReferences = 1; break;
1278
case 'd': Debug = 1; break;
1280
fprintf (errout, "%s: unknown option: %c\n", argv [0], arg [1]);
1281
fprintf (errout, Usage, argv [0]);
1286
else if (File != NULL)
1288
fprintf (errout, Usage, argv [0]);
1294
File = fopen (FileName, "r");
1303
PrintReferences = 1;
1306
fprintf (errout, Usage, argv [0]);
1319
/* vi:set tabstop=4 shiftwidth=4: */