ctags.rb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Rakefile +23 -0
- data/ctags.rb.gemspec +23 -0
- data/ext/.gitignore +3 -0
- data/ext/extconf.rb +15 -0
- data/ext/vendor/exuberant-ctags/.gitignore +6 -0
- data/ext/vendor/exuberant-ctags/.indent.pro +31 -0
- data/ext/vendor/exuberant-ctags/COPYING +340 -0
- data/ext/vendor/exuberant-ctags/EXTENDING.html +386 -0
- data/ext/vendor/exuberant-ctags/FAQ +371 -0
- data/ext/vendor/exuberant-ctags/INSTALL +215 -0
- data/ext/vendor/exuberant-ctags/INSTALL.oth +73 -0
- data/ext/vendor/exuberant-ctags/MAINTAINERS +88 -0
- data/ext/vendor/exuberant-ctags/Makefile.in +222 -0
- data/ext/vendor/exuberant-ctags/NEWS +871 -0
- data/ext/vendor/exuberant-ctags/README +73 -0
- data/ext/vendor/exuberant-ctags/ant.c +42 -0
- data/ext/vendor/exuberant-ctags/argproc.c +505 -0
- data/ext/vendor/exuberant-ctags/args.c +274 -0
- data/ext/vendor/exuberant-ctags/args.h +63 -0
- data/ext/vendor/exuberant-ctags/asm.c +387 -0
- data/ext/vendor/exuberant-ctags/asp.c +328 -0
- data/ext/vendor/exuberant-ctags/awk.c +81 -0
- data/ext/vendor/exuberant-ctags/basic.c +203 -0
- data/ext/vendor/exuberant-ctags/beta.c +321 -0
- data/ext/vendor/exuberant-ctags/c.c +2932 -0
- data/ext/vendor/exuberant-ctags/cobol.c +50 -0
- data/ext/vendor/exuberant-ctags/config.h.in +277 -0
- data/ext/vendor/exuberant-ctags/configure +7704 -0
- data/ext/vendor/exuberant-ctags/configure.ac +532 -0
- data/ext/vendor/exuberant-ctags/ctags.1 +1186 -0
- data/ext/vendor/exuberant-ctags/ctags.h +28 -0
- data/ext/vendor/exuberant-ctags/ctags.html +2087 -0
- data/ext/vendor/exuberant-ctags/ctags.spec +40 -0
- data/ext/vendor/exuberant-ctags/debug.c +113 -0
- data/ext/vendor/exuberant-ctags/debug.h +70 -0
- data/ext/vendor/exuberant-ctags/descrip.mms +68 -0
- data/ext/vendor/exuberant-ctags/dosbatch.c +42 -0
- data/ext/vendor/exuberant-ctags/e_amiga.h +24 -0
- data/ext/vendor/exuberant-ctags/e_djgpp.h +47 -0
- data/ext/vendor/exuberant-ctags/e_mac.h +143 -0
- data/ext/vendor/exuberant-ctags/e_msoft.h +76 -0
- data/ext/vendor/exuberant-ctags/e_os2.h +37 -0
- data/ext/vendor/exuberant-ctags/e_qdos.h +34 -0
- data/ext/vendor/exuberant-ctags/e_riscos.h +58 -0
- data/ext/vendor/exuberant-ctags/e_vms.h +31 -0
- data/ext/vendor/exuberant-ctags/eiffel.c +1352 -0
- data/ext/vendor/exuberant-ctags/entry.c +847 -0
- data/ext/vendor/exuberant-ctags/entry.h +103 -0
- data/ext/vendor/exuberant-ctags/erlang.c +189 -0
- data/ext/vendor/exuberant-ctags/flex.c +2243 -0
- data/ext/vendor/exuberant-ctags/fortran.c +2197 -0
- data/ext/vendor/exuberant-ctags/general.h +127 -0
- data/ext/vendor/exuberant-ctags/get.c +669 -0
- data/ext/vendor/exuberant-ctags/get.h +50 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/all-wcprops +47 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/entries +112 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/README.txt.svn-base +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regcomp.c.svn-base +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.c.svn-base +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex.h.svn-base +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.c.svn-base +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regex_internal.h.svn-base +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/.svn/text-base/regexec.c.svn-base +4338 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/README.txt +5 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regcomp.c +3818 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.c +74 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex.h +575 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.c +1713 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regex_internal.h +773 -0
- data/ext/vendor/exuberant-ctags/gnu_regex/regexec.c +4338 -0
- data/ext/vendor/exuberant-ctags/html.c +49 -0
- data/ext/vendor/exuberant-ctags/jscript.c +1572 -0
- data/ext/vendor/exuberant-ctags/keyword.c +258 -0
- data/ext/vendor/exuberant-ctags/keyword.h +34 -0
- data/ext/vendor/exuberant-ctags/lisp.c +139 -0
- data/ext/vendor/exuberant-ctags/lregex.c +704 -0
- data/ext/vendor/exuberant-ctags/lua.c +133 -0
- data/ext/vendor/exuberant-ctags/mac.c +273 -0
- data/ext/vendor/exuberant-ctags/magic.diff +21 -0
- data/ext/vendor/exuberant-ctags/main.c +584 -0
- data/ext/vendor/exuberant-ctags/main.h +32 -0
- data/ext/vendor/exuberant-ctags/maintainer.mak +476 -0
- data/ext/vendor/exuberant-ctags/make.c +217 -0
- data/ext/vendor/exuberant-ctags/matlab.c +44 -0
- data/ext/vendor/exuberant-ctags/mk_bc3.mak +46 -0
- data/ext/vendor/exuberant-ctags/mk_bc5.mak +49 -0
- data/ext/vendor/exuberant-ctags/mk_djg.mak +18 -0
- data/ext/vendor/exuberant-ctags/mk_manx.mak +65 -0
- data/ext/vendor/exuberant-ctags/mk_mingw.mak +31 -0
- data/ext/vendor/exuberant-ctags/mk_mpw.mak +130 -0
- data/ext/vendor/exuberant-ctags/mk_mvc.mak +40 -0
- data/ext/vendor/exuberant-ctags/mk_os2.mak +104 -0
- data/ext/vendor/exuberant-ctags/mk_qdos.mak +100 -0
- data/ext/vendor/exuberant-ctags/mk_sas.mak +63 -0
- data/ext/vendor/exuberant-ctags/mkinstalldirs +40 -0
- data/ext/vendor/exuberant-ctags/ocaml.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.c +1842 -0
- data/ext/vendor/exuberant-ctags/options.h +155 -0
- data/ext/vendor/exuberant-ctags/parse.c +677 -0
- data/ext/vendor/exuberant-ctags/parse.h +129 -0
- data/ext/vendor/exuberant-ctags/parsers.h +63 -0
- data/ext/vendor/exuberant-ctags/pascal.c +267 -0
- data/ext/vendor/exuberant-ctags/perl.c +382 -0
- data/ext/vendor/exuberant-ctags/php.c +237 -0
- data/ext/vendor/exuberant-ctags/python.c +771 -0
- data/ext/vendor/exuberant-ctags/qdos.c +106 -0
- data/ext/vendor/exuberant-ctags/read.c +569 -0
- data/ext/vendor/exuberant-ctags/read.h +116 -0
- data/ext/vendor/exuberant-ctags/readtags.c +959 -0
- data/ext/vendor/exuberant-ctags/readtags.h +252 -0
- data/ext/vendor/exuberant-ctags/rexx.c +39 -0
- data/ext/vendor/exuberant-ctags/routines.c +891 -0
- data/ext/vendor/exuberant-ctags/routines.h +134 -0
- data/ext/vendor/exuberant-ctags/ruby.c +408 -0
- data/ext/vendor/exuberant-ctags/scheme.c +111 -0
- data/ext/vendor/exuberant-ctags/sh.c +115 -0
- data/ext/vendor/exuberant-ctags/slang.c +41 -0
- data/ext/vendor/exuberant-ctags/sml.c +212 -0
- data/ext/vendor/exuberant-ctags/sort.c +230 -0
- data/ext/vendor/exuberant-ctags/sort.h +32 -0
- data/ext/vendor/exuberant-ctags/source.mak +122 -0
- data/ext/vendor/exuberant-ctags/sql.c +2112 -0
- data/ext/vendor/exuberant-ctags/strlist.c +281 -0
- data/ext/vendor/exuberant-ctags/strlist.h +54 -0
- data/ext/vendor/exuberant-ctags/tcl.c +116 -0
- data/ext/vendor/exuberant-ctags/tex.c +524 -0
- data/ext/vendor/exuberant-ctags/verilog.c +340 -0
- data/ext/vendor/exuberant-ctags/vhdl.c +835 -0
- data/ext/vendor/exuberant-ctags/vim.c +636 -0
- data/ext/vendor/exuberant-ctags/vstring.c +232 -0
- data/ext/vendor/exuberant-ctags/vstring.h +85 -0
- data/ext/vendor/exuberant-ctags/yacc.c +40 -0
- data/lib/ctags/exuberant.rb +45 -0
- data/lib/ctags/version.rb +3 -0
- data/lib/ctags.rb +6 -0
- data/test/test_ctags.rb +24 -0
- 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: */
|